我想将一些压缩视频包(h.264)打包到“.mp4”容器中。一个字,Muxing,不解码不编码。而且我不知道如何设置 pts、dts 和持续时间。
- 我得到带有“pcap”库的数据包。
- 我在压缩视频数据出现之前删除了标题。例如以太网、VLAN。
- 我收集数据直到一帧并对其进行解码以获取数据信息。例如宽度、高度。(我不确定是否有必要)
- 我初始化了输出上下文、流和编解码器上下文。
- 我再次开始接收带有“pcap”库的数据包。(现在用于混合)
- 我制作了一帧并将该数据放入 AVPacket 结构中。
- 我尝试设置 PTS、DTS 和持续时间。(我认为这是错误的部分,但不确定)
*7-1。在第一帧,我用数据包头结构节省了时间(毫秒)。
*7-2。每当我制作一帧时,我都会设置如下参数:PTS(当前时间 - 开始时间),DTS(相同的 PTS 值),持续时间(当前 PTS - 在 PTS 之前)
我认为它有一些错误,因为:
我不知道从pts到dts有多远合适。
至少,我认为持续时间是指从现在到下一帧显示这一帧的时间,所以它应该有值(下一个 PTS - 当前 PTS),但当时我不知道下一个 PTS 的值。
它只有 I 帧。
// make input context for decoding
AVFormatContext *&ic = gInputContext;
ic = avformat_alloc_context();
AVCodec *cd = avcodec_find_decoder(AV_CODEC_ID_H264);
AVStream *st = avformat_new_stream(ic, cd);
AVCodecContext *cc = st->codec;
avcodec_open2(cc, cd, NULL);
// make packet and decode it after collect packets is be one frame
gPacket.stream_index = 0;
gPacket.size = gPacketLength[0];
gPacket.data = gPacketData[0];
gPacket.pts = AV_NOPTS_VALUE;
gPacket.dts = AV_NOPTS_VALUE;
gPacket.flags = AV_PKT_FLAG_KEY;
avcodec_decode_video2(cc, gFrame, &got_picture, &gPacket);
// I checked automatically it initialized after "avcodec_decode_video2"
// put some info that I know that not initialized
cc->time_base.den = 90000;
cc->time_base.num = 1;
cc->bit_rate = 2500000;
cc->gop_size = 1;
// make output context with input context
AVFormatContext *&oc = gOutputContext;
avformat_alloc_output_context2(&oc, NULL, NULL, filename);
AVFormatContext *&ic = gInputContext;
AVStream *ist = ic->streams[0];
AVCodecContext *&icc = ist->codec;
AVStream *ost = avformat_new_stream(oc, icc->codec);
AVCodecContext *occ = ost->codec;
avcodec_copy_context(occ, icc);
occ->flags |= CODEC_FLAG_GLOBAL_HEADER;
avio_open(&(oc->pb), filename, AVIO_FLAG_WRITE);
// repeated part for muxing
AVRational Millisecond = { 1, 1000 };
gPacket.stream_index = 0;
gPacket.data = gPacketData[0];
gPacket.size = gPacketLength[0];
gPacket.pts = av_rescale_rnd(pkthdr->ts.tv_sec * 1000 /
+ pkthdr->ts.tv_usec / 1000 /
- gStartTime, Millisecond.den, ost->time_base.den, /
(AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
gPacket.dts = gPacket.pts;
gPacket.duration = gPacket.pts - gPrev;
gPacket.flags = AV_PKT_FLAG_KEY;
gPrev = gPacket.pts;
av_interleaved_write_frame(gOutputContext, &gPacket);
预期和实际结果是可以播放的 .mp4 视频文件。