我try 为FFmpeg制作一个比特流过滤器,它会删除正值的第n个关键帧,并允许前n个关键帧,并删除非正值的其余关键帧,称为"datamosh":

ffmpeg -i input.webm -bsf:v datamosh=target=20 -c copy output.webm

输出错误:

Option 'target' not found
[vost#0:0/copy @ 0x54edc40] Error parsing bitstream filter sequence 'datamosh=target=20': Option not found

以下是"datamosh"比特流过滤器的代码:

#include "bsf.h"
#include "bsf_internal.h"

#include "libavutil/opt.h"

typedef struct {
    const AVClass *class;

    int target, i;
} DatamoshContext;

static int datamosh_init(AVBSFContext *ctx)
{
    DatamoshContext *s = ctx->priv_data;

    s->i = 0;

    return 0;
}

static int datamosh(AVBSFContext *ctx, AVPacket *pkt)
{
    DatamoshContext *s = ctx->priv_data;
    int ret;

    ret = ff_bsf_get_packet_ref(ctx, pkt);
    if (ret < 0)
        return ret;

    if (s->target < 1) {
        if (s->i <= -s->target)
            return 0;
        else {
            av_packet_unref(pkt);
            return AVERROR(EAGAIN);
        }
    }

    if (pkt->flags & AV_PKT_FLAG_KEY)
        ++s->i;

    if (s->i == s->target) {
        av_packet_unref(pkt);
        return AVERROR(EAGAIN);
    }

    return 0;
}


#define OFFSET(x) offsetof(DatamoshContext, x)
#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_BSF_PARAM)

static const AVOption options[] = {
    { "target", NULL, OFFSET(target), AV_OPT_TYPE_INT, { .i64 = 0 }, -INT_MAX, INT_MAX, FLAGS },
    { NULL },
};

static const AVClass datamosh_class = {
    .class_name = "datamosh",
    .item_name = av_default_item_name,
    .option = options,
    .version = LIBAVUTIL_VERSION_INT,
};

const FFBitStreamFilter ff_datamosh_bsf = {
    .p.name = "datamosh",
    .p.priv_class = &datamosh_class,
    .priv_data_size = sizeof(DatamoshContext),
    .init = datamosh_init,
    .filter = datamosh,
};

n在代码中被称为"目标".

奇怪的是,ffmpeg -h bsf=datamosh张照片:

Bit stream filter datamosh
datamosh AVOptions:
  -target            <int>        ...VA...B.. (from -2.14748e+09 to INT_MAX) (default 0)

推荐答案

我已经修复了我的代码.正确丢弃数据包存在问题.修复方法如下:

#include <stdbool.h>

#include "bsf.h"
#include "bsf_internal.h"

#include "libavutil/opt.h"

typedef struct {
    const AVClass *class;

    int target, i;
} DatamoshContext;

static int datamosh_init(AVBSFContext *ctx)
{
    DatamoshContext *s = ctx->priv_data;

    s->i = 0;

    return 0;
}

static int datamosh(AVBSFContext *ctx, AVPacket *pkt)
{
    DatamoshContext *s = ctx->priv_data;
    bool key;
    int ret;

    ret = ff_bsf_get_packet_ref(ctx, pkt);
    if (ret < 0)
        return ret;

    key = pkt->flags & AV_PKT_FLAG_KEY;
    if (key)
        ++s->i;

    if (s->target < 1) {
        if (s->i <= -s->target)
            return 0;
        else if (key) {
            av_packet_unref(pkt);
            return AVERROR(EAGAIN);
        }
    }

    if (key && s->i == s->target) {
        av_packet_unref(pkt);
        return AVERROR(EAGAIN);
    }

    return 0;
}


#define OFFSET(x) offsetof(DatamoshContext, x)
#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_BSF_PARAM)

static const AVOption options[] = {
    { "target", NULL, OFFSET(target), AV_OPT_TYPE_INT, { .i64 = 0 }, -INT_MAX, INT_MAX, FLAGS },
    { NULL },
};

static const AVClass datamosh_class = {
    .class_name = "datamosh",
    .item_name = av_default_item_name,
    .option = options,
    .version = LIBAVUTIL_VERSION_INT,
};

const FFBitStreamFilter ff_datamosh_bsf = {
    .p.name = "datamosh",
    .p.priv_class = &datamosh_class,
    .priv_data_size = sizeof(DatamoshContext),
    .init = datamosh_init,
    .filter = datamosh,
};

C++相关问答推荐

ARM上的Modulo Sim Aarch 64(NEON)

为什么下面的C代码会进入无限循环?

C中出现分段错误后关闭文件

减法运算结果的平方的最快方法?

无效指针值在函数调用之间莫名其妙地改变

仅在给定的大小和对齐方式下正确创建全局

非常大的数组的大小

如何在c++中包装返回空*的函数

如何捕捉只有换行符或空格字符缓冲区的边缘大小写

如何在ASM中访问C struct 成员

S在本文中的价值观到底出了什么问题?

收到不兼容的指针类型警告,因为函数的返回不是空*,而是 struct 指针

生成一个半RNG,结果用C表示(无随机/随机)

程序如何解释变量中的值

为什么GCC 13没有显示正确的二进制表示法?

atoi函数最大长-长误差的再创造

struct 中的qsort,但排序后的 struct 很乱

C 错误:对 int 数组使用 typedef 时出现不兼容的指针类型问题

memcmp 是否保证按顺序比较字节?

全局变量 y0 与 mathlib 冲突,无法编译最小的 C 代码