用FFMPEG输出MPEGTS格式时,发现视频和PCR的PID总是一样。
查看源码如下:
/* <strong>update PCR pid by using the first video stream</strong> */
if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
service->pcr_pid == 0x1fff) {
service->pcr_pid = ts_st->pid;
pcr_st = st;
}
<strong>/* if no video stream, use the first stream as PCR */</strong>
if (service->pcr_pid == 0x1fff && s->nb_streams > 0) {
pcr_st = s->streams[0];
ts_st = pcr_st->priv_data;
service->pcr_pid = ts_st->pid;
} else
也就是说PCR PID总是会和VIDEO PID一样。
解决办法:修改源码,在现在源码写PCR的时候,替换成自己的PCR写入函数。
-------------------------------- 华丽的分割线 --------------------------------------
关于PCR插入间隔的计算:
由复用总码率,计算出PCR需要间隔多少包插入一次
#define <strong>PCR_RETRANS_TIME </strong>20
{ "pcr_period", "PCR retransmission time",
offsetof(MpegTSWrite, pcr_period), AV_OPT_TYPE_INT,
{ .i64 = PCR_RETRANS_TIME }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
if (ts->mux_rate > 1) {
service-><strong>pcr_packet_period</strong> = (ts->mux_rate * ts->pcr_period) /
(TS_PACKET_SIZE * 8 * 1000);
ts->sdt_packet_period = (ts->mux_rate * SDT_RETRANS_TIME) /
(TS_PACKET_SIZE * 8 * 1000);
ts->pat_packet_period = (ts->mux_rate * PAT_RETRANS_TIME) /
(TS_PACKET_SIZE * 8 * 1000);
// output a PCR as soon as possible
service-><strong>pcr_packet_count</strong> = service-><strong>pcr_packet_period;</strong>
在写PES时,根据这个值来写入PES:
<strong>write_pcr = 0;</strong>
if (ts_st->pid == ts_st->service->pcr_pid) {
if (ts->mux_rate > 1 || is_start) // VBR pcr period is based on frames
ts_st->service->pcr_packet_count++;
if (ts_st->service->pcr_packet_count >=
ts_st->service->pcr_packet_period) {
ts_st->service->pcr_packet_count = 0;
<strong> write_pcr = 1;</strong>
}
}
。。。 。。。
if (<strong>write_pcr</strong>) {
set_af_flag(buf, 0x10);
q = get_ts_payload_start(buf);
// add 11, pcr references the last byte of program clock reference base
if (ts->mux_rate > 1)
pcr = get_pcr(ts, s->pb);
else
pcr = (dts - delay) * 300;
if (dts != AV_NOPTS_VALUE && dts < pcr / 300)
av_log(s, AV_LOG_WARNING, "dts < pcr, TS is invalid\n");
extend_af(buf,<strong> write_pcr_bits(q, pcr)</strong>);
q = get_ts_payload_start(buf);
}