前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >开发播放器知识点滴

开发播放器知识点滴

作者头像
音视频_李超
发布2020-04-02 18:22:04
8590
发布2020-04-02 18:22:04
举报

前言

这几天重新看了一下播放器的源码,对里边的一些知识又有了一些重新的认识。由于都是一些琐碎的知识点,不好放在其它的文章里,所以只能写这样一篇文章将它们记录下来。

播放器播放字幕原理

  • 字幕分为外挂字幕,硬字幕和软字幕三种。外挂字幕是以第三方文件的方式提供。如.srt 、.ass类型的字幕。硬字幕是将字与视频溶合到一起。软字幕是与媒体格式有关的。它与音频,视频并列,可以作为一个单独的轨进行处理。
  • 播放器显示字幕的大体流程。先将文本通过 FreeType 转成 BitMap, 然后再通过时间戳将这些 BitMap与视频同步后一同渲染出来。(针对的是软字幕与外挂字幕,因为硬字幕是与视频溶和到一起的,所以不用单独处理)

图像缩放

平常的时候我们很少使用图像缩放。但对于播放器来说,在窗口指定的情况下,很可能与最终要显示的YUV的宽高不一致。为了达到更好的效果,一般都需要对视频进行缩放操作。下面就是使用 ffmpeg进行缩放的方法。

注:ffmpeg的 swscale 模块的效率不高,建议尽量使用libyuv进行图像的缩放。

  • 创建上下文
代码语言:javascript
复制
sws_getCachedContext(*img_convert_ctx,
                frame->width, frame->height, frame->format, frame->width, frame->height,
                AV_PIX_FMT_BGRA, sws_flags, NULL, NULL, NULL);
或
sws_getContext(*img_convert_ctx,
                frame->width, frame->height, frame->format, frame->width, frame->height,
                AV_PIX_FMT_BGRA, sws_flags, NULL, NULL, NULL);

sws_flags 可以选用下面的参数:

  • 第二步缩放
代码语言:javascript
复制
uint8_t *pixels[4];
int pitch[4];

sws_scale(*sws_convert_ctx, (const uint8_t * const *)frame->data,
                 frame->linesize, 0, frame->height, pixels, pitch);

  • sws_convert_ctx: sws上下文.
  • frame->data: 指向 YUV数据。(pointer to the picture/channel planes)
  • frame->linesize: 指明YUV数据每行的宽度。
  • pixels: 输入数据地址
  • pitch: 输入YUV/RGBA数据每行的宽度。

SDL 个别 API 讲解

下面几个 SDL 的API之前没有用过,但今天看代码时发现这几个API非常有用,所以在这里记录一下,以便后面使用时便于查阅。

SDL_UpdateYUVTexture

his function to update a rectangle within a planar YV12 or IYUV texture with new pixel data.

代码语言:javascript
复制
int SDL_UpdateYUVTexture(SDL_Texture*    texture,
                         const SDL_Rect* rect,
                         const Uint8*    Yplane, //Y分量
                         int             Ypitch, //Y分量每行宽度
                         const Uint8*    Uplane, //U分量
                         int             Upitch, //U分量每行宽度
                         const Uint8*    Vplane, //V分量
                         int             Vpitch  //V分量每行宽度
)

例子:

代码语言:javascript
复制
ret = SDL_UpdateYUVTexture(tex, NULL, 
                            frame->data[0], frame->linesize[0],
                            frame->data[1], frame->linesize[1],
                            frame->data[2], frame->linesize[2]);

SDL_LockTexture

this function to lock a portion of the texture for write-only pixel access.

代码语言:javascript
复制
int SDL_LockTexture(SDL_Texture*    texture,
                    const SDL_Rect* rect,
                    void**          pixels,
                    int*            pitch)

例子

代码语言:javascript
复制
uint8_t *pixels[4];
int pitch[4];

SDL_LockTexture(tex, NULL, (void **)pixels, pitch);

SDL_UnlockTexture

this function to unlock a texture, uploading the changes to video memory

音频重采样

在一些媒体文件中使用的音频数据格式是 FLTP格式,也就是 float格式。之前没有仔细研究过,以为都是用16位大小,这两天才搞明白原来是32位大小。

而使用SDL将音频在送往硬件设备时,一般都使用的是 16位大小的数据。这样数据不一致就导致音频在播放时出现了问题。所以最好的解决办法是将 FLTP 格式转换成 S16格式。这就要用到音频的数据转换了。

  • 创建上下文
代码语言:javascript
复制
struct SwrContext swr_alloc_set_opts(struct SwrContext *s, 
                                   int64_t out_ch_layout, 
                                   enum AVSampleFormat  out_sample_fmt, 
                                   int out_sample_rate, 
                                   int64_t in_ch_layout, 
                                   enum AVSampleFormat  in_sample_fmt, 
                                   int in_sample_rate, 
                                   int log_offset, 
                                   void *log_ctx) ;

例子

代码语言:javascript
复制
swr_alloc_set_opts(NULL,
               is->audio_tgt.channel_layout, 
               is->audio_tgt.fmt, is->audio_tgt.freq,
               dec_channel_layout,  
               af->frame->format, 
               af->frame->sample_rate,
               0, NULL);
  • 初始化上下文
代码语言:javascript
复制
int  swr_init (struct SwrContext *s)
  • 重采样
代码语言:javascript
复制
int  swr_convert (struct SwrContext *s, 
                  uint8_t  *out_arg[SWR_CH_MAX], 
                  int out_count, 
                  const uint8_t  *in_arg[SWR_CH_MAX], 
                  int in_count) ;

例子

代码语言:javascript
复制
int out_count = (int64_t)wanted_nb_samples * is->audio_tgt.freq / af->frame->sample_rate + 256;

swr_convert(is->swr_ctx, out, out_count, in, af->frame->nb_samples);

小结

知识是不断积累的。在工作和学习的过程中,不断的完善自己的识识图谱,并分享给大家既可以使自己记得更牢固,又可以与大家交流,想来也是一件很美的事儿。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 播放器播放字幕原理
  • 图像缩放
  • SDL 个别 API 讲解
    • SDL_UpdateYUVTexture
      • SDL_LockTexture
        • SDL_UnlockTexture
        • 音频重采样
        • 小结
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档