对于编解码 API 有不懂的地方,官方文档是最值得阅读的。
此文对 ffmpeg4.4 版本编解码 API 的官方说明进行了翻译,如下文:

avcodec_send_packet()/avcodec_receive_frame() 为解码 API,
avcodec_send_frame()/avcodec_receive_packet() 为编码 API,
他们对输入输出进行了解耦。

音频、视频的编解码 API 非常相似,他们的工作原理如下:

流程

  1. 像往常一样建立并打开 AVCodecContext;

  2. 发送有效的输入:

    • 对于解码,调用 avcodec_send_packet() 给解码器喂压缩数据:AVPacket
    • 对于编码,调用 avcodec_send_frame() 给编码器发送未压缩的音频或视频帧:AVFrame
      在这两种情况下,建议将 AVPackets 和 AVFrames 使用引用计数,不然 libavcodec 可能得拷贝输入数据(libavformat 总是返回引用计数的 AVPackets,而 av_frame_get_buffer 分配引用计数的 AVFrames)。
  3. 循环接收输出。定期调用对应的 avcodec_receive_*() 函数并处理他们的输出:

    • 对于解码,调用 avcodec_receive_frame() 。如果成功,会返回解压缩的视频或音频数据 AVFrame
    • 对于编码,调用 avcodec_receive_packet() 。如果成功,会返回压缩的数据包 AVPacket

    重复调用上述函数,直到它返回 AVERROR(EAGAIN) 或错误。AVERROR(EAGAIN) 返回值表示需要新的输入数据才能返回新的输出。在这种情况下,继续发送输入数据。对于每个输入 frame/packet,解码器通常会返回 1 个输出 frame/packet,但也可以是 0 或大于 1 个。

    在编码或解码开始时,编解码器可能会接收多个输入 frames/packets 而不返回一个 frame,直到其内部缓冲区被填满。 如果您按照上述步骤进行操作,这种情况已被良好处理。

    从理论上讲,发送输入可能会导致 EAGAIN – 只有在没有收到任何输出时才会发生这种情况。 您可以使用它来构建除上述建议之外的解码或编码的循环。 例如,可以试着在每次循环中发送新的输入,并在返回 EAGAIN 时接收输出。

流结束的情况

文件流结束后需要“刷新”(耗尽)编解码器,因为编解码器可能会在内部缓冲多个帧或数据包以提高性能,或出于必要的原因(考虑到 B 帧的情况)。
处理如下:

  1. 发送 “NULL” 数据包到 avcodec_send_packet()(解码)或 avcodec_send_frame()(编码)函数,而不是输入有效的数据。 这将进入 draining 模式。
  2. 循环调用 avcodec_receive_frame()(解码)或 avcodec_receive_packet()(编码)函数直到返回 AVERROR_EOF。函数将不会返回 AVERROR(EAGAIN),除非你忘记进入 draining 模式。
  3. 在解码重新恢复之前,必须使用 avcodec_flush_buffers() 重置编解码器。

其它

强烈建议使用上述 API。但是也可以脱离这个固定模式去调用函数。例如,您可以重复调用 avcodec_send_packet() 而无需调用 avcodec_receive_frame()。在这种情况下,avcodec_send_packet() 将成功,直到编解码器的内部缓冲区被填满(通常在初始化输入后,每个输出帧的大小为 1),然后返回 AVERROR(EAGAIN) 拒绝输入。一旦开始被拒绝输入,你别无选择,只能至少去读取一些输出。
并非所有编解码器都会遵循严格且可预测的数据流;唯一的保证是,一端的 send/receive 调用返回 AVERROR(EAGAIN) 意味着另一端的 receive/send 调用将成功,或者至少不会因 AVERROR(EAGAIN) 而失败。通常,没有编解码器会允许输入/输出的无限制缓冲。
至此。

原文如下:
 * @ingroup libavc* @defgroup lavc_encdec send/receive encoding and decoding API overview* @{** The avcodec_send_packet()/avcodec_receive_frame()/avcodec_send_frame()/* avcodec_receive_packet() functions provide an encode/decode API, which* decouples input and output.** The API is very similar for encoding/decoding and audio/video, and works as* follows:* - Set up and open the AVCodecContext as usual.* - Send valid input:*   - For decoding, call avcodec_send_packet() to give the decoder raw*     compressed data in an AVPacket.*   - For encoding, call avcodec_send_frame() to give the encoder an AVFrame*     containing uncompressed audio or video.**   In both cases, it is recommended that AVPackets and AVFrames are*   refcounted, or libavcodec might have to copy the input data. (libavformat*   always returns refcounted AVPackets, and av_frame_get_buffer() allocates*   refcounted AVFrames.)* - Receive output in a loop. Periodically call one of the avcodec_receive_*()*   functions and process their output:*   - For decoding, call avcodec_receive_frame(). On success, it will return*     an AVFrame containing uncompressed audio or video data.*   - For encoding, call avcodec_receive_packet(). On success, it will return*     an AVPacket with a compressed frame.**   Repeat this call until it returns AVERROR(EAGAIN) or an error. The*   AVERROR(EAGAIN) return value means that new input data is required to*   return new output. In this case, continue with sending input. For each*   input frame/packet, the codec will typically return 1 output frame/packet,*   but it can also be 0 or more than 1.** At the beginning of decoding or encoding, the codec might accept multiple* input frames/packets without returning a frame, until its internal buffers* are filled. This situation is handled transparently if you follow the steps* outlined above.** In theory, sending input can result in EAGAIN - this should happen only if* not all output was received. You can use this to structure alternative decode* or encode loops other than the one suggested above. For example, you could* try sending new input on each iteration, and try to receive output if that* returns EAGAIN.** End of stream situations. These require "flushing" (aka draining) the codec,* as the codec might buffer multiple frames or packets internally for* performance or out of necessity (consider B-frames).* This is handled as follows:* - Instead of valid input, send NULL to the avcodec_send_packet() (decoding)*   or avcodec_send_frame() (encoding) functions. This will enter draining*   mode.* - Call avcodec_receive_frame() (decoding) or avcodec_receive_packet()*   (encoding) in a loop until AVERROR_EOF is returned. The functions will*   not return AVERROR(EAGAIN), unless you forgot to enter draining mode.* - Before decoding can be resumed again, the codec has to be reset with*   avcodec_flush_buffers().** Using the API as outlined above is highly recommended. But it is also* possible to call functions outside of this rigid schema. For example, you can* call avcodec_send_packet() repeatedly without calling* avcodec_receive_frame(). In this case, avcodec_send_packet() will succeed* until the codec's internal buffer has been filled up (which is typically of* size 1 per output frame, after initial input), and then reject input with* AVERROR(EAGAIN). Once it starts rejecting input, you have no choice but to* read at least some output.** Not all codecs will follow a rigid and predictable dataflow; the only* guarantee is that an AVERROR(EAGAIN) return value on a send/receive call on* one end implies that a receive/send call on the other end will succeed, or* at least will not fail with AVERROR(EAGAIN). In general, no codec will* permit unlimited buffering of input or output.

ffmpeg新版本解码API overview相关推荐

  1. FFMPEG 硬件解码API介绍

    https://zhuanlan.zhihu.com/p/168240163 软解和硬解的区别: 一般来说我们把使用CPU通用计算单元(无论是Intel还是AMD)就是软解:用专用芯片模组(GPU.Q ...

  2. FFmpeg硬件解码API介绍

    FFMPEG原生支持哪些硬解码类型: 在AVHWDeviceType(libavutil/hwcontext.h)中列举出所有原生支持的硬解码类型: enum AVHWDeviceType {AV_H ...

  3. 视频和视频帧:FFMPEG 硬件解码API介绍

    https://zhuanlan.zhihu.com/p/168240163 https://zhuanlan.zhihu.com/p/64739970 https://zhuanlan.zhihu. ...

  4. FFmpeg音频解码流程详解及简单demo参考

    本文主要讲解FFmpeg的音频解码具体流程,API使用.最后再以一个非常简单的demo演示将一个mp3格式的音频文件解码为原始数据pcm文件. 本文主要基于FFmpeg音频解码新接口. 一.FFmpe ...

  5. [ffmpeg] 解码API

    版本迭代 ffmpeg解码API经过了好几个版本的迭代,上一个版本的API是 解码视频:avcodec_decode_video2 解码音频:avcodec_decode_audio4 我们现在能看到 ...

  6. 如何利用ffmpeg提供的API函数进行多媒体文件的解封装

    多媒体已经无处不在,程序员必须知道的一些多媒体封装知识 如何利用ffmpeg提供的API函数进行多媒体文件的解封装. 上一篇文章我们搭好了环境并编译出所需的ffmpeg库,本篇我们讨论如何利用ffmp ...

  7. ffmpeg 硬解码

    ffmpeg 硬件解码 由于现在h264,h265视频的增多,分辨率增大,甚至2k,4k监控视频的增多,需要利用硬件来实现高效解码和AI识别等的情况越来越多,日益重要,显卡GPU的算力强大,可以提供更 ...

  8. ffmpeg 音频解码一

    1. ffmpeg 视频解码一 2. ffmpeg 视频解码二 3. ffmpeg 音频解码一 4. ffmpeg 音频解码二 5. ffmpeg 音视频解码 6. ffmpeg 视频编码一 7. f ...

  9. ffmpeg 音频解码二

    1. ffmpeg 视频解码一 2. ffmpeg 视频解码二 3. ffmpeg 音频解码一 4. ffmpeg 音频解码二 5. ffmpeg 音视频解码 6. ffmpeg 视频编码一 7. f ...

最新文章

  1. c mysql转sqlite_SqliteToMysql
  2. Nginx-1.9.8推出的切片模块
  3. python反爬虫破解_python中绕过反爬虫的方法总结
  4. SOCKET入门最简单的程序啊
  5. 软件测试桌面检查,静态测试的主要方法 - 测试天下,梦寻人生 - 51Testing软件测试网 51Testing软件测试网-软件测试人的精神家园...
  6. LeakCanary上传 leak trace 到服务器
  7. Python界面程序实例:按钮漂移,用Python小套路来撩女神
  8. c++ thread(2.1)---join()
  9. python进程与线程_Python 进程和线程
  10. 图片存储解决方案--阿里云OSS
  11. ShipConstructor.2006v1.00.rar
  12. 中国移动中兴ZTE F623光猫设置自动拨号启用wifi功
  13. batchplot插件用法_Batchplot设置使用指南,实现批量打印CAD图纸
  14. win11拉伸屏幕_win11系统出现拉伸屏幕问题修复办法
  15. Basler相机开发流程
  16. 【课程设计】俄罗斯方块游戏,重温经典(源码 + 详解)
  17. 超详细!联想小新700黑苹果双系统完整教程(1)
  18. 台式机连接蓝牙音响没声音 以及 声音延迟 问题解决
  19. 基于xsh的vbs脚本的使用(条件判断和函数)
  20. YV12和I420的区别 yuv420和yuv420p的区别

热门文章

  1. 湖南中医药大学计算机学院,实力“C位”!湖南中医药大学学子斩获省大学生计算机竞赛一等奖...
  2. 王者荣耀服务器更新维护2020,王者荣耀苹果版更新后进不去怎么办 王者荣耀iOS版服务器维护是怎么回事...
  3. 安卓取消apple music订阅
  4. P1799 小水同学的巧克力(加强版)
  5. 《暗黑II毁灭之王》装备DIY 打造自己的神器
  6. 男孩变成男人的标志35岁前必须做好的十件事情 [转]
  7. JAVA 电子邮箱格式验证,使用正则表达式
  8. JavaScript ES6-11常用新语法
  9. linux当中怎么修改文件后缀------- mv命令
  10. 作为shopee新手卖家的你,如何快速出单?不得不看的shopee店铺装修技巧