*** code/ffmpeg/svn/dvbmuxer/mpegtsenc.c	2008-12-18 13:58:40.000000000 +0200
--- workspace/ffmpeg/libavformat/mpegtsenc.c	2008-12-23 12:23:28.000000000 +0200
***************
*** 25,30 ****
--- 25,42 ----
  #include "libavcodec/bytestream.h"
  #include "mpegpes.h"
  
+ #define MAX_PCR_VALUE (0x1FFFFFFFF*300+0x12C)
+ #define PCR_TIME_BASE 27000000LL
+ #define PCR_REPETITION_INTERVAL (PCR_TIME_BASE / 25)
+ #define BYTES_TIME(num_bytes, mux_rate) ((num_bytes)*8*PCR_TIME_BASE / (mux_rate))
+ #define SINGLE_PACKET_TIME(mux_rate) BYTES_TIME(TS_PACKET_SIZE, mux_rate)
+ #define MULTI_PACKETS_TIME(num_packets, mux_rate) ((num_packets)*SINGLE_PACKET_TIME(mux_rate))
+ 
+ typedef struct MpegPcr {
+     int64_t base;
+     int ext;
+ } MpegPcr;
+ 
  /* write DVB SI sections */
  
  /*********************************************/
***************
*** 38,50 ****
  } MpegTSSection;
  
  /* NOTE: 4 bytes must be left at the end for the crc32 */
! static void mpegts_write_section(MpegTSSection *s, uint8_t *buf, int len)
  {
      unsigned int crc;
      unsigned char packet[TS_PACKET_SIZE];
      const unsigned char *buf_ptr;
      unsigned char *q;
      int first, b, len1, left;
  
      crc = bswap_32(av_crc(av_crc_get_table(AV_CRC_32_IEEE), -1, buf, len - 4));
      buf[len - 4] = (crc >> 24) & 0xff;
--- 50,63 ----
  } MpegTSSection;
  
  /* NOTE: 4 bytes must be left at the end for the crc32 */
! static int mpegts_write_section(MpegTSSection *s, uint8_t *buf, int len)
  {
      unsigned int crc;
      unsigned char packet[TS_PACKET_SIZE];
      const unsigned char *buf_ptr;
      unsigned char *q;
      int first, b, len1, left;
+     int num_packets_written;
  
      crc = bswap_32(av_crc(av_crc_get_table(AV_CRC_32_IEEE), -1, buf, len - 4));
      buf[len - 4] = (crc >> 24) & 0xff;
***************
*** 52,57 ****
--- 65,72 ----
      buf[len - 2] = (crc >> 8) & 0xff;
      buf[len - 1] = (crc) & 0xff;
  
+     num_packets_written = 0;
+ 
      /* send each packet */
      buf_ptr = buf;
      while (len > 0) {
***************
*** 78,87 ****
--- 93,105 ----
              memset(q, 0xff, left);
  
          s->write_packet(s, packet);
+         ++num_packets_written;
  
          buf_ptr += len1;
          len -= len1;
      }
+ 
+     return num_packets_written;
  }
  
  static inline void put16(uint8_t **q_ptr, int val)
***************
*** 114,121 ****
      *q++ = last_sec_num;
      memcpy(q, buf, len);
  
!     mpegts_write_section(s, section, tot_len);
!     return 0;
  }
  
  /*********************************************/
--- 132,138 ----
      *q++ = last_sec_num;
      memcpy(q, buf, len);
  
!     return mpegts_write_section(s, section, tot_len);
  }
  
  /*********************************************/
***************
*** 175,181 ****
      int mux_rate;
  } MpegTSWrite;
  
! static void mpegts_write_pat(AVFormatContext *s)
  {
      MpegTSWrite *ts = s->priv_data;
      MpegTSService *service;
--- 192,198 ----
      int mux_rate;
  } MpegTSWrite;
  
! static int mpegts_write_pat(AVFormatContext *s)
  {
      MpegTSWrite *ts = s->priv_data;
      MpegTSService *service;
***************
*** 188,198 ****
          put16(&q, service->sid);
          put16(&q, 0xe000 | service->pmt.pid);
      }
!     mpegts_write_section1(&ts->pat, PAT_TID, ts->tsid, 0, 0, 0,
                            data, q - data);
  }
  
! static void mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
  {
      //    MpegTSWrite *ts = s->priv_data;
      uint8_t data[1012], *q, *desc_length_ptr, *program_info_length_ptr;
--- 205,215 ----
          put16(&q, service->sid);
          put16(&q, 0xe000 | service->pmt.pid);
      }
!     return mpegts_write_section1(&ts->pat, PAT_TID, ts->tsid, 0, 0, 0,
                            data, q - data);
  }
  
! static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
  {
      //    MpegTSWrite *ts = s->priv_data;
      uint8_t data[1012], *q, *desc_length_ptr, *program_info_length_ptr;
***************
*** 277,283 ****
          desc_length_ptr[0] = val >> 8;
          desc_length_ptr[1] = val;
      }
!     mpegts_write_section1(&service->pmt, PMT_TID, service->sid, 0, 0, 0,
                            data, q - data);
  }
  
--- 294,300 ----
          desc_length_ptr[0] = val >> 8;
          desc_length_ptr[1] = val;
      }
!     return mpegts_write_section1(&service->pmt, PMT_TID, service->sid, 0, 0, 0,
                            data, q - data);
  }
  
***************
*** 298,304 ****
      *q_ptr = q;
  }
  
! static void mpegts_write_sdt(AVFormatContext *s)
  {
      MpegTSWrite *ts = s->priv_data;
      MpegTSService *service;
--- 315,321 ----
      *q_ptr = q;
  }
  
! static int mpegts_write_sdt(AVFormatContext *s)
  {
      MpegTSWrite *ts = s->priv_data;
      MpegTSService *service;
***************
*** 332,338 ****
          desc_list_len_ptr[0] = val >> 8;
          desc_list_len_ptr[1] = val;
      }
!     mpegts_write_section1(&ts->sdt, SDT_TID, ts->tsid, 0, 0, 0,
                            data, q - data);
  }
  
--- 349,355 ----
          desc_list_len_ptr[0] = val >> 8;
          desc_list_len_ptr[1] = val;
      }
!     return mpegts_write_section1(&ts->sdt, SDT_TID, ts->tsid, 0, 0, 0,
                            data, q - data);
  }
  
***************
*** 481,503 ****
      return -1;
  }
  
! /* send SDT, PAT and PMT tables regulary */
! static void retransmit_si_info(AVFormatContext *s)
  {
      MpegTSWrite *ts = s->priv_data;
      int i;
  
      if (++ts->sdt_packet_count == ts->sdt_packet_freq) {
          ts->sdt_packet_count = 0;
!         mpegts_write_sdt(s);
      }
      if (++ts->pat_packet_count == ts->pat_packet_freq) {
          ts->pat_packet_count = 0;
!         mpegts_write_pat(s);
          for(i = 0; i < ts->nb_services; i++) {
!             mpegts_write_pmt(s, ts->services[i]);
          }
      }
  }
  
  /* NOTE: pes_data contains all the PES packet */
--- 498,541 ----
      return -1;
  }
  
! /* send SDT, PAT and PMT tables regulary if the time is right */
! static int maybe_retransmit_si_info(AVFormatContext *s)
  {
      MpegTSWrite *ts = s->priv_data;
      int i;
+     int num_packets_written, ret_num_packets_written;
+     ret_num_packets_written = num_packets_written = 0;
+ 
+ #define TRY_ACCUMULATE_PACKETS(err_table) \
+     do { \
+         if (-1 == ret_num_packets_written) \
+             av_log(NULL, AV_LOG_ERROR, "Error generating %s\n", err_table); \
+         else \
+             num_packets_written += ret_num_packets_written; \
+     } while (0);
  
      if (++ts->sdt_packet_count == ts->sdt_packet_freq) {
          ts->sdt_packet_count = 0;
!         ret_num_packets_written = mpegts_write_sdt(s);
!         TRY_ACCUMULATE_PACKETS("SDT");
      }
      if (++ts->pat_packet_count == ts->pat_packet_freq) {
          ts->pat_packet_count = 0;
!         ret_num_packets_written = mpegts_write_pat(s);
!         TRY_ACCUMULATE_PACKETS("PAT");
          for(i = 0; i < ts->nb_services; i++) {
!             ret_num_packets_written = mpegts_write_pmt(s, ts->services[i]);
!             TRY_ACCUMULATE_PACKETS("PMT");
          }
      }
+ #undef TRY_ACCUMULATE_PACKETS
+     return num_packets_written;
+ }
+ 
+ /* increment pcr, handle wrap */
+ static int64_t increment_pcr(int64_t cur_value, int64_t inc_value)
+ {
+     return (cur_value + inc_value) % (MAX_PCR_VALUE + 1);
  }
  
  /* NOTE: pes_data contains all the PES packet */
***************
*** 510,526 ****
      uint8_t *q;
      int val, is_start, len, header_len, write_pcr;
      int afc_len, stuffing_len;
  
      is_start = 1;
!     ts->cur_pcr = pcr;
      while (payload_size > 0) {
!         retransmit_si_info(s);
  
!         write_pcr = !ts->cur_pcr;
!         if (ts_st->pid == ts_st->service->pcr_pid) {
!             pcr = ts->cur_pcr + (TS_PACKET_SIZE+4+7)*8*90000LL / ts->mux_rate;
!             if (pcr - ts->last_pcr > MAX_DELTA_PCR)
!                 write_pcr = 1;
          }
  
          /* prepare packet header */
--- 548,583 ----
      uint8_t *q;
      int val, is_start, len, header_len, write_pcr;
      int afc_len, stuffing_len;
+     MpegPcr mpeg_pcr;
+     int num_si_packets_written;
  
      is_start = 1;
! 
      while (payload_size > 0) {
!         num_si_packets_written = maybe_retransmit_si_info(s);
  
!         if (0 == pcr) // first pcr value in stream
!         {
!             ts->last_pcr = 0;
!             ts->cur_pcr =
!                 // the time passed while SI tables written
!                 MULTI_PACKETS_TIME(num_si_packets_written, ts->mux_rate)
!                 // the time passed for packets up until the first pcr bit, as
!                 // required in the standard
!                 + BYTES_TIME(11, ts->mux_rate);
!             write_pcr = 1;
!             ++pcr; // done with first time pcr
!         }
!         else
!         {
!             ts->cur_pcr = increment_pcr(ts->cur_pcr,
!                     // the time passed from last packet
!                     SINGLE_PACKET_TIME(ts->mux_rate)
!                     // the time passed while SI tables written
!                     + MULTI_PACKETS_TIME(num_si_packets_written, ts->mux_rate));
!             // write pcr only if pcr pid and if repetition interval is right
!             write_pcr = (ts_st->pid == ts_st->service->pcr_pid) ?
!                     ((ts->cur_pcr - ts->last_pcr) > PCR_REPETITION_INTERVAL ? 1 : 0) : 0;
          }
  
          /* prepare packet header */
***************
*** 536,552 ****
          *q++ = 0x10 | ts_st->cc | (write_pcr ? 0x20 : 0);
          ts_st->cc = (ts_st->cc + 1) & 0xf;
          if (write_pcr) {
              /* add header and pcr bytes to pcr according to specs */
-             pcr = ts->cur_pcr + (4+7)*8*90000LL / ts->mux_rate;
              *q++ = 7; /* AFC length */
              *q++ = 0x10; /* flags: PCR present */
!             *q++ = pcr >> 25;
!             *q++ = pcr >> 17;
!             *q++ = pcr >> 9;
!             *q++ = pcr >> 1;
!             *q++ = (pcr & 1) << 7;
!             *q++ = 0;
!             ts->last_pcr = pcr;
          }
          /* header size */
          header_len = q - buf;
--- 593,611 ----
          *q++ = 0x10 | ts_st->cc | (write_pcr ? 0x20 : 0);
          ts_st->cc = (ts_st->cc + 1) & 0xf;
          if (write_pcr) {
+             mpeg_pcr.base = ts->cur_pcr / 300;
+             mpeg_pcr.ext  = ts->cur_pcr % 300;
              /* add header and pcr bytes to pcr according to specs */
              *q++ = 7; /* AFC length */
              *q++ = 0x10; /* flags: PCR present */
!             *q++ = mpeg_pcr.base >> 25;
!             *q++ = mpeg_pcr.base >> 17;
!             *q++ = mpeg_pcr.base >> 9;
!             *q++ = mpeg_pcr.base >> 1;
!             *q = (mpeg_pcr.base & 1) << 7;
!             *q++ = (*q | 0x3E) | (mpeg_pcr.ext >> 8);
!             *q++ = mpeg_pcr.ext;
!             ts->last_pcr = ts->cur_pcr;
          }
          /* header size */
          header_len = q - buf;
***************
*** 580,586 ****
          payload += len;
          payload_size -= len;
          put_buffer(s->pb, buf, TS_PACKET_SIZE);
-         ts->cur_pcr += (TS_PACKET_SIZE+write_pcr)*8*90000LL / ts->mux_rate;
      }
      put_flush_packet(s->pb);
  }
--- 639,644 ----
