• FFmpeg采坑记录——aformat过滤器输出的linesize大小和音频编码后stream_index


    1. 流程图
    代码流程如图,视频流不做解码,音频流解码为pcm(FLIP,44.1K,MONO),通过aresample和aformat Filter转换采样率和采样格式,Filter输出为pcm(S16,16K,MONO)。
    流程图

    音频解码后的frame数据格式如下图:
    frame
    2. 遇到的问题
    2.1 如下图,音频过滤器输出frameFilter的linesize大小不是真实数据长度。linesize[0]=832,而根据nb_sample计算的长度为nb_sample*sizeof(short)=355*2=710,应当使用后者。
    frameFilter
    2.2 编码器输出pktEncode的srream_index默认为0,如果是音频流,则需要手动改为1,再送mux,否则会报错[AVBSFContext @ 00918400] Failed to send packet to filter h264_mp4toannexb for stream 0
    pktEncode
    2.3 使用av_frame_get_buffer接口为AVFrame申请yuv420p格式内存,内存分布在frame.data[0]、frame.data[1]、frame.data[2],但只有frame.buf[0].data合法,都在这一块内存上。如下图。
    这个情况我在自己的台式机上遇见过,另一台虚拟机上buf[]和data[]是对应的,ffmpeg版本也是一样的,比较奇怪。所以,尽量还是用data[]字段,不要用buf[].data字段。
    av_frame_get_buffer

    3. channels和channel_layout字段说明
    channels:表示几个音频通道;
    channel_layout:表示通道格式类型。
    eg.frame->channels=2;frame->channel_layout=3,表示2个音频通道,为立体声;
    eg.
    frameFilter->channels=1;frameFilter->channel_layout=4,表示1个音频通道,为单声道。

    详见源码channel_layout.h头文件中:

    #define AV_CH_FRONT_LEFT             0x00000001
    #define AV_CH_FRONT_RIGHT            0x00000002
    #define AV_CH_FRONT_CENTER           0x00000004
    
    #define AV_CH_LAYOUT_MONO              (AV_CH_FRONT_CENTER)
    #define AV_CH_LAYOUT_STEREO            (AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    单声道mono为4,立体声stereo为3。

    更多的对应关系:

    channel_layout_map[]
    	{ "mono",        1,  AV_CH_LAYOUT_MONO },
    	{ "stereo",      2,  AV_CH_LAYOUT_STEREO },
    	{ "2.1",         3,  AV_CH_LAYOUT_2POINT1 },
    	{ "3.0",         3,  AV_CH_LAYOUT_SURROUND },
    	{ "3.0(back)",   3,  AV_CH_LAYOUT_2_1 },
    	{ "4.0",         4,  AV_CH_LAYOUT_4POINT0 },
    	{ "quad",        4,  AV_CH_LAYOUT_QUAD },
    	{ "quad(side)",  4,  AV_CH_LAYOUT_2_2 },
    	{ "3.1",         4,  AV_CH_LAYOUT_3POINT1 },
    	{ "5.0",         5,  AV_CH_LAYOUT_5POINT0_BACK },
    	{ "5.0(side)",   5,  AV_CH_LAYOUT_5POINT0 },
    	{ "4.1",         5,  AV_CH_LAYOUT_4POINT1 },
    	{ "5.1",         6,  AV_CH_LAYOUT_5POINT1_BACK },
    	{ "5.1(side)",   6,  AV_CH_LAYOUT_5POINT1 },
    	{ "6.0",         6,  AV_CH_LAYOUT_6POINT0 },
    	{ "6.0(front)",  6,  AV_CH_LAYOUT_6POINT0_FRONT },
    	{ "hexagonal",   6,  AV_CH_LAYOUT_HEXAGONAL },
    	{ "6.1",         7,  AV_CH_LAYOUT_6POINT1 },
    	{ "6.1",         7,  AV_CH_LAYOUT_6POINT1_BACK },
    	{ "6.1(front)",  7,  AV_CH_LAYOUT_6POINT1_FRONT },
    	{ "7.0",         7,  AV_CH_LAYOUT_7POINT0 },
    	{ "7.0(front)",  7,  AV_CH_LAYOUT_7POINT0_FRONT },
    	{ "7.1",         8,  AV_CH_LAYOUT_7POINT1 },
    	{ "7.1(wide)",   8,  AV_CH_LAYOUT_7POINT1_WIDE },
    	{ "octagonal",   8,  AV_CH_LAYOUT_OCTAGONAL },
    	{ "downmix",     2,  AV_CH_LAYOUT_STEREO_DOWNMIX, },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
  • 相关阅读:
    Docker
    Python读写文件操作
    数组是内存的实现及栈和队列的数据结构
    《信息技术时代》期刊简介及投稿要求
    Mysql 并发多版本控制MVCC
    UML测试题(用例图基础a)
    Spring AOP以及统一处理
    Ubuntu - 用户和权限
    【ASP.NET Core】MVC控制器的各种自定义:特性化的路由规则
    快速掌握JVM及垃圾回收器
  • 原文地址:https://blog.csdn.net/SanShuiGeGe/article/details/126430503