[FFmpeg-devel] mpegtsenc cbr mode pcr accuracy

Timo Teras timo.teras at iki.fi
Sat Nov 28 08:03:20 CET 2015


While the pcr is accuracte, I was measuring the cbr pcr frequence with
opencaster suite's tspcmeasure tool, and it says that the frequency is
not that accurate. With default options (just muxrate specified) the
pcr should appear every 20ms. But it appears every 19-22.5ms (also
there some appearances with 1-18ms but those are probably the extra pcr
announces for key frames).

While in practice this is not too bad for me, I wondered how it should
be generated instead.

Seems that the period is calculated in mpegts_write_header():
  pcr_packet_period = mux_rate * pcr_period / (TS_PACKET_SIZE * 8 * 1000)

Which is the packet period over the whole mpeg ts stream. But the count
is actually incremented like mpegts_write_pes():
    while (payload_size > 0) {
        retransmit_si_info(s, force_pat, dts);
        force_pat = 0;
        write_pcr = 0;
        if (ts_st->pid == ts_st->service->pcr_pid) {
            if (ts->mux_rate > 1 || is_start) // VBR pcr period is based on frames

The problem seems to be that only packets for pcr_pid are counted in
the pcr period. That's why the gap goes >20ms when there's other
streams muxed (usually audio) and depends on the other PES' bandwidth.
Same is true for sdt and pat - they drift very slightly, because they
don't count each other's packets.

I was wondering how to fix this. Would it be best to remove all
{sdt,pat,pcr}_packet_count variables, and replace it with single
packet_count counter that is incremented everytime a packet is sent
(in the four functions section_write_packet(),
mpegts_insert_null_packet(), mpegts_insert_pcr_only(),
mpegts_write_pes()) and then calculate just the next packet count when
to trigger resend. packet_count + {sdt,pat,pcr}_packet_period.

Another problem case is the inserting of null/pcr-only packets. If it's
a non-pcr stream PES packet triggering the stuffing, it should still
stuff pcr to the pcr_pid - not the pid of the stream triggering the
stuffing. Basically the strategy in cbr mode should be:
 1) Check / send SDT/PAT as currently
 2) Check if PCR needs to be sent
 3) If filler packets needed: a) send pcr on pcr_pid, OR b) send null
 4) If PCR send needed but ES PID != pcr pid: send PCR only on pcr_pid
 5) Proceed with sending ES on ES PID as regular

Does this reasoning / approach make sense?


More information about the ffmpeg-devel mailing list