我想完成相同的任务:将RTSP H264编码的流转换为分段的MP4流。此代码正是完成此任务。
但是我根本不想将mp4写入磁盘,但是我需要在C中获得一个字节缓冲区或包含通常写入磁盘的内容的数组。
这是如何实现的?此示例使用vs_open_output定义输出格式,并且此函数需要输出URL。
如果我不想将内容输出到磁盘,该如何修改此代码?或者也可能有更好的选择,也欢迎这些选择。
按照szatmary的建议,我检查了他的示例链接。
但是,正如我在问题中所述,我需要将输出作为缓冲区而不是文件。该示例很好地演示了如何读取自定义源并将其提供给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;
}
然后,我需要将标头写入输出缓冲区,并且此处的预期行为是打印“读取的字节: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)。
我找到了另一个阅读示例:doc / examples / avio_reading.c。
提到过类似的写作示例(avio_writing.c),但是ffmpeg没有这个功能(至少在我的Google搜索中如此)。
这个任务真的很难解决吗?标准rtsp输入到自定义avio?
幸运的是ffmpeg.org已经关闭。大。
这是一个愚蠢的错误:
在初始化部分,我将此称为:
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现在不见了。