在ffmpeg中编写一个bitstream filter,针对h264和hevc码流数据进行处理,能够产生各种类型的“问题码流”,比如NAL header出错、AVC layer层数据出错、SEI SPS PPS 等数据出错
时间: 2023-06-25 10:07:54 浏览: 193
编写一个bitstream filter需要以下步骤:
1. 定义一个结构体,用于保存过滤器的上下文信息。这个结构体应该至少包含一个AVBitStreamFilterContext成员,用于保存FFmpeg提供的默认的比特流过滤器的上下文信息。
2. 实现av_bsf_alloc函数,用于分配一个过滤器的上下文信息,并初始化默认的比特流过滤器。
3. 实现av_bsf_init函数,用于初始化自定义的过滤器。在这个函数中,你可以检查输入的AVCodecParameters参数,检查是否支持指定的编解码器。你还需要创建一个AVPacket数据结构,用于保存过滤后的结果。
4. 实现av_bsf_filter函数,用于过滤输入的AVPacket数据。在这个函数中,你需要检查AVPacket数据的类型,根据不同的类型进行不同的处理。如果数据类型是NALU,你可以修改NALU头部数据,比如将NRI字段修改为无效值,或者将NALU类型修改为无效值。如果数据类型是SPS/PPS,你可以修改这些数据的一些字段,或者直接删除这些数据。如果数据类型是SEI,你可以直接删除这些数据。过滤后的数据保存在AVPacket中,并返回0表示成功。
5. 实现av_bsf_close函数,用于关闭过滤器。在这个函数中,你需要释放所有过滤器的上下文信息,以及AVPacket数据结构。
以下是一个简单的例子,演示如何修改NALU头部数据:
```
typedef struct {
AVBSFContext *ctx;
} MyBitstreamFilterContext;
static int my_filter(AVBSFContext *ctx, AVPacket *pkt)
{
uint8_t *data = pkt->data;
uint8_t nal_type = (data[4] & 0x1f);
if (nal_type == 1 || nal_type == 5) {
data[4] |= 0x80; // 设置NRI为无效值
data[4] &= 0xdf; // 设置NALU类型为无效值
}
return 0;
}
static int my_init(AVBSFContext *ctx)
{
MyBitstreamFilterContext *priv = ctx->priv_data;
priv->ctx = ctx;
return 0;
}
static void my_close(AVBSFContext *ctx)
{
MyBitstreamFilterContext *priv = ctx->priv_data;
av_bsf_free(&priv->ctx);
}
AVBitStreamFilter my_filter = {
.name = "my_filter",
.filter = my_filter,
.priv_data_size = sizeof(MyBitstreamFilterContext),
.init = my_init,
.close = my_close,
};
```
这个例子演示了如何修改NALU头部数据。在my_filter函数中,我们检查NALU类型,如果是1(P帧)或者5(I帧),就将NRI字段设置为无效值,将NALU类型设置为无效值。在my_init函数中,我们保存AVBSFContext上下文信息。在my_close函数中,我们释放AVBSFContext上下文信息。
阅读全文