音视频解码流程简介(使用 ffmpeg)

​第一步:注册组件
​​​av_register_all()
注册编码器、解码器等等…

​​第二步:打开封装格式->打开文件
打开.mp4、.mov、.wmv...格式文件
​​​avformat_open_input();
api解释(文档人肉翻译):

/**
 * Open an input stream and read the header. The codecs are not opened.
--->打开一个输入流并且读取它的头文件。注意:编解码器不会被打开。
 * The stream must be closed with avformat_close_input().
--->记住:一定要用 avformat_close_input() 关闭打开的流。
 * 
 * @param ps Pointer to user-supplied AVFormatContext (allocated by avformat_alloc_context).
 *           May be a pointer to NULL, in which case an AVFormatContext is allocated by this
 *           function and written into ps.
 *           Note that a user-supplied AVFormatContext will be freed on failure.
--->使用用户提供的 AVFormatContext(封装格式上下文,使用 avformat_alloc_context 分配空间)创建。这个 AVFormatContext 大概是一个指向 NULL 的指针,在这种情况下,AVFormatContext 被这个函数(avformat_alloc_context)创建后,会被当前的函数写入到 ps 这个参数中。(人话:先自己创建一个空的内存空间,再传入此函数中,此函数会将信息写入到这个内存空间内)
--->注意:如果此函数失败了,用户提供的 AVFormatContext 将会被释放。
 * 
 * @param url URL of the stream to open.
--->需要打开的流路径。
 * @param fmt If non-NULL, this parameter forces a specific input format.
--->该参数如果不为空,就必须传入一个明确的输入格式。
 *            Otherwise the format is autodetected.
--->否则如果为空,会自动检测格式。
 * @param options  A dictionary filled with AVFormatContext and demuxer-private options.
--->一个参数字典(由 AVFormatContext 和 demuxer-private 填充)
 *                 On return this parameter will be destroyed and replaced with a dict containing
 *                 options that were not found. May be NULL.
--->如果填写的操作选项没有找到,则这个参数变为 NULL
 *
 * @return 0 on success, a negative AVERROR on failure.
--->返回值 0 表示成功,负数表示失败
 *
 * @note If you want to use custom IO, preallocate the format context and set its pb field.
--->注意:如果你想使用自己 IO 读取,需要给封装格式上下文预分配空间,并且设置 AVFormatContext 的 pb 属性。
 */
int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options);

​​第三步:查找视频流
​​​如果是视频解码,那么查找视频流,如果是音频解码,那么就查找音频流
​​​avformat_find_stream_info();
api解释:

/**
 * Read packets of a media file to get stream information. This
 * is useful for file formats with no headers such as MPEG. This
 * function also computes the real framerate in case of MPEG-2 repeat
 * frame mode.
--->读取媒体文件的包来获取流信息,对于没有头部的文件(如:MPEG)来说是很有用的。该函数也会重新计算类似于 MPEG-2 帧模式的真实帧率。
 * The logical file position is not changed by this function;
--->这个函数不会改变逻辑文件的位置。
 * examined packets may be buffered for later processing.
--->被检查的数据包可以被缓冲以便以后的处理。
 *
 * @param ic media file handle
--->媒体文件句柄(封装格式上下文)
 * @param options  If non-NULL, an ic.nb_streams long array of pointers to
 *                 dictionaries, where i-th member contains options for
 *                 codec corresponding to i-th stream.
 *                 On return each dictionary will be filled with options that were not found.
--->options 如果不为空,将会有一个指向多个字典的数组(长度:封装格式上下文的 nb_streams),该数组的每一个元素(字典指针)包含的编解码 options 将会赋给每一流。
--->(人话:你如果传入了 options 配置,那么你查找到的所有流就会使用这些 option 配置)
 * @return >=0 if OK, AVERROR_xxx on error
--->返回值:>=0表示成功,其他表示错误。
 *
 * @note this function isn't guaranteed to open all the codecs, so
 *       options being non-empty at return is a perfectly normal behavior.
--->注意:这个函数不能保证能打开所有的编解码器,所以传一个指定的 options 配置是一个非常正常的。
--->(人话:这个参数你最好自己传进来)
 *
 * @todo Let the user decide somehow what information is needed so that
 *       we do not waste time getting stuff the user does not need.
--->还有:让使用者自己来决定他们需要什么信息,所以我们不会浪费时间去给使用者不想要的东西。
 */
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);

​​第四步:查找音频/视频解码器
​​​1、查找音频/视频流索引位置
​​​2、根据音频/视频流索引,获取解码器上下文
​​​3、根据解码器上下文,获得解码器ID,然后查找解码器

​​第五步:打开解码器
​​​avcodec_open2();

​​第六步:读取音频/视频压缩数据->循环读取
每读取一帧数据,立即解码一帧数据

​​第七步:音频/视频解码->得到音频采样数据/视频像素数据->播放音频/视频

​​第八步:关闭解码器->解码完成

你可能感兴趣的:(音视频解码流程简介(使用 ffmpeg))