From 75bfe3281f23851efb6a1d5b54a8512d1835a4a1 Mon Sep 17 00:00:00 2001
From: Jindrich Makovicka <jindrich.makovicka@nangu.tv>
Date: Thu, 5 May 2011 15:23:36 +0200
Subject: [PATCH] set Random Access indicator on keyframe start packets

needed for some DVB recorders

Signed-off-by: Jindrich Makovicka <makovick@gmail.com>
---
 libavformat/mpegtsenc.c |   41 +++++++++++++++++++++++++++++++++--------
 1 files changed, 33 insertions(+), 8 deletions(-)

diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c
index bf66aa0..bc4bdd7 100644
--- a/libavformat/mpegtsenc.c
+++ b/libavformat/mpegtsenc.c
@@ -686,6 +686,26 @@ static void write_pts(uint8_t *q, int fourbits, int64_t pts)
     *q++ = val;
 }
 
+static void set_af_flag(uint8_t *q, int flag)
+{
+    if ((q[3] & 0x20) == 0) {
+        // no AF yet, set adaptation field flag
+        q[3] |= 0x20;
+        // 1 byte length, no flags
+        q[4] = 1;
+        q[5] = 0;
+    }
+    q[5] |= flag;
+}
+
+static uint8_t *get_ts_header_end(uint8_t *q)
+{
+    if (q[3] & 0x20)
+        return q + 5 + q[4];
+    else
+        return q + 4;
+}
+
 /* Add a pes header to the front of payload, and segment into an integer number of
  * ts packets. The final ts packet is padded using an over-sized adaptation header
  * to exactly fill the last ts packet.
@@ -693,7 +713,7 @@ static void write_pts(uint8_t *q, int fourbits, int64_t pts)
  */
 static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
                              const uint8_t *payload, int payload_size,
-                             int64_t pts, int64_t dts)
+                             int64_t pts, int64_t dts, int key)
 {
     MpegTSWriteStream *ts_st = st->priv_data;
     MpegTSWrite *ts = s->priv_data;
@@ -738,8 +758,12 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
         *q++ = val;
         *q++ = ts_st->pid;
         ts_st->cc = (ts_st->cc + 1) & 0xf;
-        *q++ = 0x10 | ts_st->cc | (write_pcr ? 0x20 : 0);
+        *q++ = 0x10 | ts_st->cc;
+        if (key && is_start) {
+            set_af_flag(buf, 0x40);
+        }
         if (write_pcr) {
+            set_af_flag(buf, 0x10);
             // add 11, pcr references the last byte of program clock reference base
             if (ts->mux_rate > 1)
                 pcr = get_pcr(ts, s->pb);
@@ -747,10 +771,10 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
                 pcr = (dts - delay)*300;
             if (dts != AV_NOPTS_VALUE && dts < pcr / 300)
                 av_log(s, AV_LOG_WARNING, "dts < pcr, TS is invalid\n");
-            *q++ = 7; /* AFC length */
-            *q++ = 0x10; /* flags: PCR present */
-            q = write_pcr_bits(q, pcr);
+            q = write_pcr_bits(get_ts_header_end(buf), pcr);
+            buf[4] += q - get_ts_header_end(buf);
         }
+        q = get_ts_header_end(buf);
         if (is_start) {
             int pes_extension = 0;
             /* write PES header */
@@ -947,14 +971,15 @@ static int mpegts_write_packet(AVFormatContext *s, AVPacket *pkt)
 
     if (st->codec->codec_type != AVMEDIA_TYPE_AUDIO) {
         // for video and subtitle, write a single pes packet
-        mpegts_write_pes(s, st, buf, size, pts, dts);
+        mpegts_write_pes(s, st, buf, size, pts, dts, pkt->flags & AV_PKT_FLAG_KEY);
         av_free(data);
         return 0;
     }
 
     if (ts_st->payload_index + size > DEFAULT_PES_PAYLOAD_SIZE) {
         mpegts_write_pes(s, st, ts_st->payload, ts_st->payload_index,
-                         ts_st->payload_pts, ts_st->payload_dts);
+                         ts_st->payload_pts, ts_st->payload_dts,
+                         pkt->flags & AV_PKT_FLAG_KEY);
         ts_st->payload_index = 0;
     }
 
@@ -985,7 +1010,7 @@ static int mpegts_write_end(AVFormatContext *s)
         ts_st = st->priv_data;
         if (ts_st->payload_index > 0) {
             mpegts_write_pes(s, st, ts_st->payload, ts_st->payload_index,
-                             ts_st->payload_pts, ts_st->payload_dts);
+                             ts_st->payload_pts, ts_st->payload_dts, 0);
         }
         av_freep(&ts_st->adts);
     }
-- 
1.7.4.4

