使用FFmpeg C++ API编码MPEGTS和KLV数据流

3
我需要使用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格式的输出视频中正确添加数据流?
非常感谢!

你尝试过从git主分支获取最新的ffmpeg吗? - Cornstalks
不,我正在使用的版本是20150526。 - arms
尝试最新的代码。最近有关于在mpegts中编码KLV的工作。 - Cornstalks
非常感谢。我会尝试最新版本并更新此帖子。 - arms
这个问题有任何更新吗? - omerfirmak
显示剩余2条评论
1个回答

3

我使用FFmpeg源代码中的“muxing.c”示例作为起点,并进行以下修改,成功将KLV流添加到复合输出中。

首先,我创建了AVStream。这里的“oc”是AVFormatContext(复用器)变量:

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",AV_CODEC_ID_OPUS 的值应该导致 stream_type 6,对于异步 KLV(没有伴随的 PTS 或 DTS)。这对于我的应用程序实际上很重要,但我无法让它工作 -- 调用 avformat_write_header() 时会抛出除以零的错误。如果我解决了这个问题,我会在这里更新。


为了初始化KLV流,我将codec_id设置为“AV_CODEC_ID_SMPTE_KLV”,并将codec_tag设置为“1096174667”。这两个步骤使数据流对我来说可以被识别为KLV流。 - Nikkisixx2
这太棒了,我一直在尝试用Python实现,但一直没有成功,我认为这可以帮助我。这是项目链接 https://github.com/All4Gis/QGISFMV - Fran Raga

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接