历史说明 以往FFmpeg版本中保存视音频流信息参数是AVStream结构体中的AVCodecContext字段。当前FFmpeg版本是3.4,新的版本已经将AVStream结构体中的AVCodecContext字段定义为废弃属性。因此无法像以前旧的版本直接通过如下的代码获取到AVCodecContext结构体参数: AVCodecContext* pAVCodecContext = avcodec_alloc_context3(NULL); pAVCodecContext = pAVFormatContext->streams[videoStream]->codec; 当前版本保存视音频流信息的结构体AVCodecParameters,FFmpeg提供了函数avcodec_parameters_to_context将音频流信息拷贝到新的AVCodecContext结构体中 函数说明 将AVCodecParameters结构体中码流参数拷贝到AVCodecContext结构体中,并且重新拷贝一份extradata内容,涉及到的视频的关键参数有format, width, height, codec_type等,这些参数在优化avformat_find_stream_info函数的时候,手动指定该参数通过InitDecoder函数解码统一指定H264,分辨率是1920*1080 调用avformat_open_input打开网络流后,下一步调用av_find_stream_info从网络流中读取视音频流的信息,通过调试查看AVCodecParameters结构体的视频参数 int avcodec_parameters_to_context(AVCodecContext *codec, const AVCodecParameters *par) { codec->codec_type = par->codec_type;//AVMEDIA_TYPE_VIDEO codec->codec_id = par->codec_id;//AV_CODEC_ID_H264 codec->codec_tag = par->codec_tag;//0 codec->bit_rate = par->bit_rate;//0 codec->bits_per_coded_sample = par->bits_per_coded_sample;//0 codec->bits_per_raw_sample = par->bits_per_raw_sample;//8 codec->profile = par->profile;//66 codec->level = par->level;//42 switch (par->codec_type) { case AVMEDIA_TYPE_VIDEO: codec->pix_fmt = par->format;//12 codec->width = par->width;//1920 codec->height = par->height;//1080 codec->field_order = par->field_order;//AV_FIELD_PROGRESSIVE codec->color_range = par->color_range;//AVCOL_RANGE_JPEG codec->color_primaries = par->color_primaries;//AVCOL_PRI_BT709 codec->color_trc = par->color_trc;//AVCOL_TRC_BT709 codec->colorspace = par->color_space;//AVCOL_SPC_BT709 codec->chroma_sample_location = par->chroma_location;//AVCHROMA_LOC_LEFT codec->sample_aspect_ratio = par->sample_aspect_ratio;//num=0,den=1 codec->has_b_frames = par->video_delay;//0 break; case AVMEDIA_TYPE_AUDIO: codec->sample_fmt = par->format; codec->channel_layout = par->channel_layout; codec->channels = par->channels; codec->sample_rate = par->sample_rate; codec->block_align = par->block_align; codec->frame_size = par->frame_size; codec->delay = codec->initial_padding = par->initial_padding; codec->trailing_padding = par->trailing_padding; codec->seek_preroll = par->seek_preroll; break; case AVMEDIA_TYPE_SUBTITLE: codec->width = par->width; codec->height = par->height; break; } //extradata保存SPS/PPS信息,重新拷贝一份到AVCodecContext中,用于解码 if (par->extradata) { av_freep(&codec->extradata); codec->extradata = av_mallocz(par->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!codec->extradata) return AVERROR(ENOMEM); memcpy(codec->extradata, par->extradata, par->extradata_size); codec->extradata_size = par->extradata_size; } return 0; } 代码定义 typedef struct AVStream { #if FF_API_LAVF_AVCTX /** * @deprecated use the codecpar struct instead */ attribute_deprecated AVCodecContext *codec; #endif } 说明: 当手动指定编码格式的时候,说明探测码流格式的代码是可以省略的,例如 avformat_open_input avformat_find_stream_info 在其他章节中调用InitDecoder函数替换上面的函数 avformat_open_input缺省情况下,无法播放图像,这个目前还在研究当中
本文转自fengyuzaitu 51CTO博客,原文链接:http://blog.51cto.com/fengyuzaitu/2059121,如需转载请自行联系原作者