美文网首页
开发播放器知识点滴

开发播放器知识点滴

作者: 音视频直播技术专家 | 来源:发表于2018-05-18 15:38 被阅读440次

    前言

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

    播放器播放字幕原理

    • 字幕分为外挂字幕,硬字幕和软字幕三种。外挂字幕是以第三方文件的方式提供。如.srt 、.ass类型的字幕。硬字幕是将字与视频溶合到一起。软字幕是与媒体格式有关的。它与音频,视频并列,可以作为一个单独的轨进行处理。

    • 播放器显示字幕的大体流程。先将文本通过 FreeType 转成 BitMap, 然后再通过时间戳将这些 BitMap与视频同步后一同渲染出来。(针对的是软字幕与外挂字幕,因为硬字幕是与视频溶和到一起的,所以不用单独处理)

    图像缩放

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

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

    • 创建上下文
    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 可以选用下面的参数:

    • 第二步缩放
    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.

    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分量每行宽度
    )
    

    例子:

    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.

    int SDL_LockTexture(SDL_Texture*    texture,
                        const SDL_Rect* rect,
                        void**          pixels,
                        int*            pitch)
    

    例子

    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格式。这就要用到音频的数据转换了。

    • 创建上下文
    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) ;
    
    

    例子

    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);
    
    
    • 初始化上下文
    int  swr_init (struct SwrContext *s)
    
    • 重采样
    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) ;
    

    例子

    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);
    

    小结

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

    相关文章

      网友评论

          本文标题:开发播放器知识点滴

          本文链接:https://www.haomeiwen.com/subject/apmgdftx.html