【问题标题】:FFMPEG remux sample without writing to fileFFMPEG remux 样本不写入文件
【发布时间】:2020-02-01 01:03:29
【问题描述】:

让我们考虑一下这个非常好用且易于使用的remux sample by horgh

我想完成相同的任务:将 RTSP H264 编码流转换为分段 MP4 流。 这段代码正是完成了这项任务。

但是我根本不想将 mp4 写入磁盘,但我需要在 C 中获取一个字节缓冲区或数组,其中包含通常写入磁盘的内容。

这是如何实现的? 此示例使用 vs_open_output 定义输出格式,此函数需要输出 url。

如果我不想将内容输出到磁盘,我应该如何修改这段代码? 或者可能还有更好的替代品,我们也欢迎。

更新:

按照 szatmary 的建议,我查看了他的 example link

但是,正如我在问题中所说,我需要将输出作为缓冲区而不是文件。 这个例子很好地演示了如何读取我的自定义源并将其提供给 ffmpeg。

我需要的是如何将输入作为标准打开(使用 avformat_open_input)然后对数据包进行自定义修改,然后写入文件,写入缓冲区。

我尝试了什么?

基于 szatmary 的示例,我创建了一些缓冲区和初始化:

uint8_t *buffer;
buffer = (uint8_t *)av_malloc(4096);

format_ctx = avformat_alloc_context();
format_ctx->pb = avio_alloc_context(
                buffer, 4096, // internal buffer and its size
                1,            // write flag (1=true, 0=false)
                opaque,  // user data, will be passed to our callback functions
                0,      // no read
                &IOWriteFunc,
                &IOSeekFunc
);
format_ctx->flags |= AVFMT_FLAG_CUSTOM_IO; 

AVOutputFormat * const output_format = av_guess_format("mp4", NULL, NULL);
format_ctx->oformat = output_format;

avformat_alloc_output_context2(&format_ctx, output_format,
            NULL, NULL)

那么我当然创建了 'IOWriteFunc' 和 'IOSeekFunc':

static int IOWriteFunc(void *opaque, uint8_t *buf, int buf_size) {
    printf("Bytes read: %d\n", buf_size);
    int len = buf_size;
    return (int)len;
}

static int64_t IOSeekFunc (void *opaque, int64_t offset, int whence) {
    switch(whence){
        case SEEK_SET:
            return 1;
            break;
        case SEEK_CUR:
            return 1;
            break;
        case SEEK_END:
            return 1;
            break;
        case AVSEEK_SIZE:
            return 4096;
            break;
        default:
           return -1;
    }
    return 1;
}

然后我需要将 header 写入输出缓冲区,这里的预期行为是打印 "Bytes read: x":

AVDictionary * opts = NULL;
av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov", 0);
av_dict_set_int(&opts, "flush_packets", 1, 0);

avformat_write_header(output->format_ctx, &opts)

在执行的最后一行,总是遇到segfault,这里是回溯:

#0  0x00007ffff7a6ee30 in  () at /usr/lib/x86_64-linux-gnu/libavformat.so.57
#1  0x00007ffff7a98189 in avformat_init_output () at /usr/lib/x86_64-linux-gnu/libavformat.so.57
#2  0x00007ffff7a98ca5 in avformat_write_header () at /usr/lib/x86_64-linux-gnu/libavformat.so.57
...

这个例子对我来说最难的是它使用了 avformat_open_input

但是输出没有这样的东西(没有avformat_open_ouput)。

更新2:

我找到了另一个阅读示例:doc/examples/avio_reading.c

提到了一个类似的写作示例(avio_writing.c),但 ffmpeg 没有这个可用(至少在我的谷歌搜索中)。

这个任务真的这么难解决吗?自定义 avio 的标准 rtsp 输入?

幸运的是 ffmpeg.org 已关闭。太好了。

【问题讨论】:

    标签: c ffmpeg


    【解决方案1】:

    这是一个愚蠢的错误:

    在初始化部分我称之为:

    avformat_alloc_output_context2(&format_ctx, output_format,
            NULL, NULL)
    

    不过在此之前我已经将 avio 缓冲区放入 format_ctx:

    format_ctx->pb = ...
    

    另外,这行是不必要的:

    format_ctx = avformat_alloc_context();
    

    正确顺序:

    AVOutputFormat * const output_format = av_guess_format("mp4", NULL, NULL);
    
    avformat_alloc_output_context2(&format_ctx, output_format,
                NULL, NULL)
    
    format_ctx->pb = avio_alloc_context(
                    buffer, 4096, // internal buffer and its size
                    1,            // write flag (1=true, 0=false)
                    opaque,  // user data, will be passed to our callback functions
                    0,      // no read
                    &IOWriteFunc,
                    &IOSeekFunc
    );
    format_ctx->flags |= AVFMT_FLAG_CUSTOM_IO; 
    format_ctx->oformat = output_format; //might be unncessary too
    

    Segfault 现在消失了。

    【讨论】:

    • 写标志是我错过的一件非常重要的事情,感谢您指出这一点!
    【解决方案2】:

    您需要编写一个 AVIOContext 实现。

    【讨论】:

    • 谢谢,您能提供一些链接或参考吗?试图找到,但有很多结果要搜索。谢谢!
    • 这是谷歌上的第三个赞。 mw.gl/posts/ffmpeg_custom_io
    • 谢谢。我查看了您的示例,但它与我实际需要的相反。我也尝试根据我的需要对其进行修改,但它总是出现段错误。问题已更新。如果我们能解决这个问题,我会接受您的回答作为解决方案,谢谢。
    猜你喜欢
    • 2017-11-01
    • 1970-01-01
    • 2015-06-23
    • 2021-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-01
    • 2013-05-18
    相关资源
    最近更新 更多