原文链接:

https://stackoverflow.com/questions/32028437/what-are-bitstream-filters-in-ffmpeg

Let me explain by example. FFmpeg video decoders typically work by converting one video frame per call to avcodec_decode_video2. So the input is expected to be "one image" worth of bitstream data. Let's consider this issue of going from a file (an array of bytes of disk) to images for a second.

For "raw" (annexb) H264 (.h264/.bin/.264 files), the individual nal unit data (sps/pps header bitstreams or cabac-encoded frame data) is concatenated in a sequence of nal units, with a start code (00 00 01 XX) in between, where XX is the nal unit type. (In order to prevent the nal data itself to have 00 00 01 data, it is RBSP escaped.) So a h264 frame parser can simply cut the file at start code markers. They search for successive packets that start with and including 00 00 01, until and excluding the next occurence of 00 00 01. Then they parse the nal unit type and slice header to find which frame each packet belongs to, and return a set of nal units making up one frame as input to the h264 decoder.

H264 data in .mp4 files is different, though. You can imagine that the 00 00 01 start code can be considered redundant if the muxing format already has length markers in it, as is the case for mp4. So, to save 3 bytes per frame, they remove the 00 00 01 prefix. They also put the PPS/SPS in the file header instead of prepending it before the first frame, and these also miss their 00 00 01 prefixes. So, if I were to input this into the h264 decoder, which expects the prefixes for all nal units, it wouldn't work. The h264_mp4toannexb bitstream filter fixes this, by identifying the pps/sps in the extracted parts of the file header (ffmpeg calls this "extradata"), prepending this and each nal from individual frame packets with the start code, and concatenating them back together before inputting them in the h264 decoder.

You might now feel that there's a very fine line distinction between a "parser" and a "bitstream filter". This is true. I think the official definition is that a parser takes a sequence of input data and splits it in frames without discarding any data or adding any data. The only thing a parser does is change packet boundaries. A bitstream filter, on the other hand, is allowed to actually modify the data. I'm not sure this definition is entirely true (see e.g. vp9 below), but it's the conceptual reason mp4toannexb is a BSF, not a parser (because it adds 00 00 01 prefixes).

Other cases where such "bitstream tweaks" help keep decoders simple and uniform, but allow us to support all files variants that happen to exist in the wild:

  • mpeg4 (divx) b frame unpacking (to get B-frames sequences like IBP, which are coded as IPB, in AVI and get timestamps correct, people came up with this concept of B-frame packing where I-B-P / I-P-B is packed in frames as I-(PB)-(), i.e. the third packet is empty and the second has two frames. This means the timestamp associated with the P and B frame at the decoding phase is correct. It also means you have two frames worth of input data for one packet, which violates ffmpeg's one-frame-in-one-frame-out concept, so we wrote a bsf to split the packet back in two - along with deleting the marker that says that the packet contains two frames, hence a BSF and not a parser - before inputting it into the decoder. In practice, this solves otherwise hard problems with frame multithreading. VP9 does the same thing (called superframes), but splits frames in the parser, so the parser/BSF split isn't always theoretically perfect; maybe VP9's should be called a BSF)
  • hevc mp4 to annexb conversion (same story as above, but for hevc)
  • aac adts to asc conversion (this is basically the same as h264/hevc annexb vs. mp4, but for aac audio)
分离某些封装格式(例如MP4/FLV/MKV等)中的H.264的时候,需要首先写入SPS和PPS,否则会导致分离出来的数据没有SPS、PPS而无法播放。H.264码流的SPS和PPS信息存储在AVCodecContext结构体的extradata中。
需要使用FFmpeg中名称为 “h264_mp4toannexb" 等的 Bitstream Filter 处理。
 
旧的API已经被弃用,如
AVBitStreamFilterContext *av_bitstream_filter_init(const char *name);
int av_bitstream_filter_filter(AVBitStreamFilterContext *bsfc,
AVCodecContext *avctx, const char *args,
uint8_t **poutbuf, int *poutbuf_size,
const uint8_t *buf, int buf_size, int keyframe);

新版需要使用如下API实现功能:

// Get filter
const AVBitStreamFilter *av_bsf_next(void **opaque);
const AVBitStreamFilter *av_bsf_get_by_name(const char *name); // Init filter
int av_bsf_alloc(const AVBitStreamFilter *filter, AVBSFContext **ctx);
int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src);
int av_bsf_init(AVBSFContext *ctx); // Use filter
int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt);
int av_bsf_receive_packet(AVBSFContext *ctx, AVPacket *pkt); // Free
void av_bsf_free(AVBSFContext **ctx);
 
 

FFmpeg—— Bitstream Filters 作用的更多相关文章

  1. iOS: FFMpeg编译和使用问题总结

    iOS: FFmpeg编译和使用问题总结 折磨了我近一周多时间的FFmpeg库编译问题终于解决了,必须得把这一段时间来遇到过的坑全写出来.如果急着解决问题,编译最新版本的FFmpeg库请直接看第二部分 ...

  2. FFmpeg解码H264及swscale缩放详解

    本文概要: 本文介绍著名开源音视频编解码库ffmpeg如何解码h264码流,比较详细阐述了其h264码流输入过程,解码原理,解码过程.同时,大部分应用环境下,以原始码流视频大小展示并不是最佳方式,因此 ...

  3. iOS: FFmpeg编译和使用 学习

    ffmpeg是一个多平台多媒体处理工具,处理视频和音频的功能非常强大.目前在网上搜到的iOS上使用FFMPEG的资料都比较陈旧,而FFMPEG更新迭代比较快: 且网上的讲解不够详细,对于初次接触FFM ...

  4. FFmpeg源代码简单分析:configure

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  5. Xcode编译ffmpeg(2)

    iOS: FFmpeg编译和使用问题总结 折磨了我近一周多时间的FFmpeg库编译问题终于解决了,必须得把这一段时间来遇到过的坑全写出来.如果急着解决问题,编译最新版本的FFmpeg库请直接看第二部分 ...

  6. 【图像处理】FFmpeg解码H264及swscale缩放详解

      http://blog.csdn.net/gubenpeiyuan/article/details/19548019 主题 FFmpeg 本文概要: 本文介绍著名开源音视频编解码库ffmpeg如何 ...

  7. ffmpeg编译参数详解

    Usage: configure [options]用 法:configure [选项]Options: [defaults in brackets after descriptions]选   项: ...

  8. FFMPEG ./configure 参数及意义

    FFMPEG版本:2.6.2,编译环境:ubuntu 14.4. 不同版本的FFMPEG参数可能不同,可在FFMPEG目录下使用以下命令查看 ./configure --help --help pri ...

  9. [原]如何用Android NDK编译FFmpeg

    我们知道在Ubuntu下直接编译FFmpeg是很简单的,主要是先执行./configure,接着执行make命令来编译,完了紧接着执行make install执行安装.那么如何使用Android的ND ...

随机推荐

  1. 牛客网 —— 爱奇艺2020校招C++方向笔试题 总结

    错了5,6个,主要集中在数据库和操作系统上.    C++还需要提高熟练度. 总结 第6题: 折半查找树:根据二分查找构造得到的树,它一定是一个二叉排序树,是一个特殊的二叉排序树.  (接近于平衡二叉 ...

  2. 1级搭建类112-Oracle 19c SI FS(CentOS 8)

    Oracle 19c 单实例文件系统在 CentOS 8 上的静默安装

  3. C# LINQ学习笔记四:LINQ to OBJECT之操作文件目录

    本笔记摘抄自:https://www.cnblogs.com/liqingwen/p/5816051.html,记录一下学习过程以备后续查用. 许多文件系统操作实质上是查询,因此非常适合使用LINQ方 ...

  4. ZedGraph怎样在双击图形后添加箭头标记

    场景 在ZedGraph的曲线图上,双击图时会在图形上生成箭头符号标记. 效果 注: 博客主页: https://blog.csdn.net/badao_liumang_qizhi 关注公众号 霸道的 ...

  5. 第一个,net core项目,一起入门 !!!

    最近项目上开始使用.net core,新的项目,熟悉的东西比较多,现在花点时间来梳理一下,重头开始搭建一个.net core项目.哈哈,这个相对老手来说,估计会觉得小儿科,没事,也就当一次分享总结罢了 ...

  6. Ubuntu 16 服务器配置PHP+MySQL+Apache环境

    一.获取软件包资源并进行资源更新 apt是Ubuntu上默认的软件包管理器,使用它可以很容易进行各种软件安装,而且会自动帮你安装可能需要的依赖关系. 另一个强大的软件管理工具是 dpkg,可以用于安装 ...

  7. LaTeX技巧008:如何给文字添加阴影效果?

    大家可以使用这个包:shadowtext宏包

  8. layedit不可编辑,按钮不能使用

    $("#LAY_layedit_1").contents().find("body[contenteditable]").prop("contente ...

  9. Tomcat启动命令行窗口中文乱码

    找到Tomcat安装目录conf/logging.properties文件 添加语句:java.util.logging.ConsoleHandler.encoding = GBK 重启Tomcat

  10. [Agc002E/At1999] Candy Piles - 博弈论

    有n堆石子,第i堆有ai个石子.有两种操作: 把石子最多的那一堆给丢掉 把每一堆全部丢掉一个 谁拿走最后石子谁输.判断胜负情况. 直觉转化为一个走棋盘问题 考虑如何计算左下角点的状态 找到原点最右上方 ...