我需要使用ffmpeg C++ API对mpegts视频进行编码。输出视频应具有两个流:第一个流的类型应为AVMEDIA_TYPE_VIDEO;第二个应为AVMEDIA_TYPE_DATA类型,并应包含一组KLV数据。
我已经编写了自己的KLV库来管理KLV格式。
但是,我无法通过结合两个流“从头开始”创建新视频。按照FFMPEG C api h.264 encoding / MPEG2 ts streaming problems中的实现,我可以使用单个视频流成功编码mpegts视频。
但是,我无法将新的AVMEDIA_TYPE_DATA流添加到输出视频,因为一旦我使用avformat_new_stream(...)之类的方法添加新的数据流,则输出视频为空:数据流和视频都没有产生并且输出文件为空。
谁能给我建议一个教程页面或一个示例,说明如何正确地以mpegts格式向我的输出视频添加数据流?
非常感谢!
最佳答案
通过从FFmpeg源附带的“muxing.c”示例开始,并进行如下修改,我能够将KLV流添加到复用输出中。
首先,我如下创建AVStream,其中“oc”是AVFormatContext(muxer)变量:
AVStream *klv_stream = klv_stream = avformat_new_stream(oc, NULL);
klv_stream->codec->codec_type = AVMEDIA_TYPE_DATA;
klv_stream->codec->codec_id = AV_CODEC_ID_TIMED_ID3;
klv_stream->time_base = AVRational{ 1, 30 };
klv_stream->id = oc->nb_streams - 1;
然后,在编码/混合循环中:
AVPacket pkt;
av_init_packet(&pkt);
pkt.data = (uint8_t*)GetKlv(pkt.size);
auto res = write_frame(oc, &video_st.st->time_base, klv_stream, &pkt);
free(pkt.data);
(GetKlv()函数返回一个malloc()的二进制数据数组,该数组将被您用来获取编码KLV的任何内容所替换。它将pkt.size设置为数据长度。)
通过此修改,并指定“.ts”目标文件,我得到了一个三流文件,在VLC中可以正常播放。 KLV流的stream_type为0x15,表示同步KLV。
请注意AV_CODEC_ID_TIMED_ID3的codec_id值。根据libavformat源文件“mpegtsenc.c”,对于异步KLV(无随附的PTS或DTS),AV_CODEC_ID_OPUS的值应导致stream_type 6。这实际上对我的应用程序很重要,但是我无法使其正常工作-调用avformat_write_header()会导致除以零错误。如果知道了,我将在此处添加更新。