原文链接:

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. ACM-ICPC 2018 焦作赛区网络预赛 Give Candies 题解

    ACM-ICPC 2018 焦作赛区网络预赛 Give Candies n个糖果分给n个小朋友 从1到n个小朋友依次给,每次随机给个数,至少一个,知道没有糖果为止. 问糖果的分布情况方案数. 输出方案 ...

  2. Hadoop学习之路(4)Intelij+Maven搭建Hadoop项目

    1创建工程 点击project--Maven--next 2通过maven导入项目依赖jar包 (1)设置maven自动导入依赖jar包 勾选 Import Maven projects automa ...

  3. Git操作时遇到的一些问题和相应的处理方式

    Q1:如何解决冲突/避免冲突 A1:执行git fetch之后,本地可能会存在冲突. 如果希望合并本地修改内容,需要执行git merge.不过当有修改内容未提交时,不能merge,要么把修改内容提交 ...

  4. hdu1005 矩阵快速幂

    #include<iostream> #include<cstdio> #include<cstring> #include<set> #include ...

  5. Java Day2(下)

    Java learning_Day2(下) 本人学习视频用的是马士兵的,也在这里献上 <链接:https://pan.baidu.com/s/1qKNGJNh0GgvlJnitTJGqgA> ...

  6. linux基础安全

    一.用户防护 Chage  -l  用户名   查看用户账号有效期信息 Chage  -E   时间   用户名   给用户设置过期时间 /etc/login.defs  文件保存许多默认设置 Pas ...

  7. linux 安装 Django

    安装django的命令 pip install Django ## 这样运行默认安装的是最新版 备注 根据测试在python3.4基础上安装Django 1.8.9正式版是没有问题的,所以要执行下面命 ...

  8. 占位 CP

    占位 CP include: CP403 CP404 CP405

  9. Java大全-吐血整理

    gqzdev

  10. springboot整合websocket实现客户端与服务端通信

    定义  WebSocket是通过单个TCP连接提供全双工(双向通信)通信信道的计算机通信协议.此WebSocket API可在用户的浏览器和服务器之间进行双向通信.用户可以向服务器发送消息并接收事件驱 ...