+static void enable_pcr_generation_for_stream(AVFormatContext *s, AVStream *pcr_st)
+{
+ MpegTSWrite *ts = s->priv_data;
+ MpegTSWriteStream *ts_st = pcr_st->priv_data;
+
+ if (ts->mux_rate > 1) {
+ ts_st->pcr_packet_period = (int64_t)ts->mux_rate * ts->pcr_period /
+ (TS_PACKET_SIZE * 8 * 1000);
+ } else {
+ if (pcr_st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
+ int frame_size = av_get_audio_frame_duration2(pcr_st->codecpar, 0);
+ if (!frame_size) {
+ av_log(s, AV_LOG_WARNING, "frame size not set\n");
+ ts_st->pcr_packet_period =
+ pcr_st->codecpar->sample_rate / (10 * 512);
+ } else {
+ ts_st->pcr_packet_period =
+ pcr_st->codecpar->sample_rate / (10 * frame_size);
+ }
+ } else {
+ // max delta PCR 0.1s
+ // TODO: should be avg_frame_rate
+ ts_st->pcr_packet_period =
+ ts_st->user_tb.den / (10 * ts_st->user_tb.num);
+ }
+ if (!ts_st->pcr_packet_period)
+ ts_st->pcr_packet_period = 1;
+ }
+
+ // output a PCR as soon as possible
+ ts_st->pcr_packet_count = ts_st->pcr_packet_period;
+}
+
+static void select_pcr_streams(AVFormatContext *s)
+{
+ MpegTSWrite *ts = s->priv_data;
+
+ for (int i = 0; i < ts->nb_services; i++) {
+ MpegTSService *service = ts->services[i];
+ AVStream *pcr_st = NULL;
+ AVProgram *program = service->program;
+ int nb_streams = program ? program->nb_stream_indexes : s->nb_streams;
+
+ for (int j = 0; j < nb_streams; j++) {
+ AVStream *st = s->streams[program ? program->stream_index[j] : j];
+ if (!pcr_st ||
+ pcr_st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
+ {
+ pcr_st = st;
+ }
+ }
+
+ if (pcr_st) {
+ MpegTSWriteStream *ts_st = pcr_st->priv_data;
+ service->pcr_pid = ts_st->pid;
+ enable_pcr_generation_for_stream(s, pcr_st);
+ av_log(s, AV_LOG_VERBOSE, "service %i using PCR in pid=%i\n", service->sid, service->pcr_pid);
+ }
+ }
+}
+