基于字节对齐、宏块宽高等因素,导致一个宽 w 高 h 的视频其实际参与编码的某一帧的宽高并不一定等于 w 和 h,而是有一个 ffmpeg 称之为 coded_width 及 coded_height 的编码宽高。出于另一些原因,例如数据送出与读取、数据加载到纹理等需求,不仅需要知道 w h,还需要知道其 coded_width 及 coded_height(以下简称 cw ch),那么该如何尽可能早地获取到这两个值呢?
解码之前获取不到 cw ch
参考着 FFmpeg 源码中的示例编写的编解码库,使用 avformat_open_input(&format_context, filename, nullptr, nullptr)
打开文件,然后用 avformat_find_stream_info(format_context, nullptr)
查找文件的流信息,再用 int stream_id = av_find_best_stream(format_context, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, false)
获取到视频流的 id,由此即可获取到该文件的视频流信息,其大部分主要信息存储于 format_context->streams[stream_id]->codecpar
这个参数中。包括宽、高、颜色格式、比特率、编码格式、采样宽高比等;而另一些诸如时长、帧数、帧率、时间基等信息也存在于上一层的 format_context->streams[stream_id]
这个 AVStream
结构体变量中。
而以上这些信息里,并没有 coded_width 及 coded_height 这两个信息。通过查 FFmpeg 源码可知,这两个变量是存储于结构体 AVCodecContext
中的,早一些的版本里,AVStream
结构体貌似还有个 AVCodecContext
变量,但 5.0 之后的版本已经去除。那该怎么获取呢?
如上图所示该视频宽为 1080 但参与编码的宽为 1088,忽然想到,使用命令行 ffprobe -show_streams -show_format
查看文件信息的时候是有这个参数打印的,那么,看一下 ffprobe 的源码不就行了?
查源码
其实全局搜索 coded_width
的时候,出现在比较靠前的搜索结果,或者说第一个存在于 c 文件中的搜索结果就来自 ffprobe.c 这个文件,点过去看,对比其代码上下文及上图 ffprobe 的输出信息,看起来就是打印上图信息的代码位置。
而这个 dec_ctx
就是个 AVCodecContext *
,那它是怎么获取到的呢?找到上图这段代码的函数起始发现,dec_ctx
来自参数 InputStream *ist
static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_idx, InputStream *ist, int in_program)
{
AVStream *stream = ist->st;
AVCodecParameters *par;
AVCodecContext *dec_ctx;
char val_str[128];
const char *s;
AVRational sar, dar;
AVBPrint pbuf;