【发布时间】: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 已关闭。太好了。
【问题讨论】: