Merge commit 'cc8db760616a7ec3bd39b22ca45888c01326db13'
authorHendrik Leppkes <h.leppkes@gmail.com>
Tue, 29 Sep 2015 11:45:23 +0000 (13:45 +0200)
committerHendrik Leppkes <h.leppkes@gmail.com>
Tue, 29 Sep 2015 11:45:23 +0000 (13:45 +0200)
* commit 'cc8db760616a7ec3bd39b22ca45888c01326db13':
  mpegts: use avcodec_get_type() to set codec_type

Merged-by: Hendrik Leppkes <h.leppkes@gmail.com>
1  2 
libavformat/mpegts.c

diff --combined libavformat/mpegts.c
@@@ -2,32 -2,30 +2,32 @@@
   * MPEG2 transport stream (aka DVB) demuxer
   * Copyright (c) 2002-2003 Fabrice Bellard
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
  #include "libavutil/buffer.h"
  #include "libavutil/crc.h"
 +#include "libavutil/internal.h"
  #include "libavutil/intreadwrite.h"
  #include "libavutil/log.h"
  #include "libavutil/dict.h"
  #include "libavutil/mathematics.h"
  #include "libavutil/opt.h"
 +#include "libavutil/avassert.h"
  #include "libavcodec/bytestream.h"
  #include "libavcodec/get_bits.h"
  #include "libavcodec/opus.h"
@@@ -56,7 -54,6 +56,7 @@@
  enum MpegTSFilterType {
      MPEGTS_PES,
      MPEGTS_SECTION,
 +    MPEGTS_PCR,
  };
  
  typedef struct MpegTSFilter MpegTSFilter;
@@@ -77,8 -74,6 +77,8 @@@ typedef struct MpegTSSectionFilter 
      int section_index;
      int section_h_size;
      int last_ver;
 +    unsigned crc;
 +    unsigned last_crc;
      uint8_t *section_buf;
      unsigned int check_crc : 1;
      unsigned int end_of_section_reached : 1;
@@@ -90,7 -85,6 +90,7 @@@ struct MpegTSFilter 
      int pid;
      int es_id;
      int last_cc; /* last cc code (-1 if first packet) */
 +    int64_t last_pcr;
      enum MpegTSFilterType type;
      union {
          MpegTSPESFilter pes_filter;
@@@ -103,9 -97,6 +103,9 @@@ struct Program 
      unsigned int id; // program id/service id
      unsigned int nb_pids;
      unsigned int pids[MAX_PIDS_PER_PROGRAM];
 +
 +    /** have we found pmt for this program */
 +    int pmt_found;
  };
  
  struct MpegTSContext {
      /** raw packet size, including FEC if present */
      int raw_packet_size;
  
 -    int pos47;
 -    /** position corresponding to pos47, or 0 if pos47 invalid */
 -    int64_t pos;
 +    int size_stat[3];
 +    int size_stat_count;
 +#define SIZE_STAT_THRESHOLD 10
 +
 +    int64_t pos47_full;
  
      /** if true, all pids are analyzed to find streams */
      int auto_guess;
      /** compute exact PCR for each transport stream packet */
      int mpeg2ts_compute_pcr;
  
 +    /** fix dvb teletext pts                                 */
 +    int fix_teletext_pts;
 +
      int64_t cur_pcr;    /**< used to estimate the exact PCR */
      int pcr_incr;       /**< used to estimate the exact PCR */
  
      /** to detect seek */
      int64_t last_pos;
  
 +    int skip_changes;
 +    int skip_clear;
 +
 +    int scan_all_pmts;
 +
      int resync_size;
  
      /******************************************/
      unsigned int nb_prg;
      struct Program *prg;
  
 +    int8_t crc_validity[NB_PID_MAX];
      /** filters for various streams specified by PMT + for the PAT and PMT */
      MpegTSFilter *pids[NB_PID_MAX];
 +    int current_pid;
  };
  
  #define MPEGTS_OPTIONS \
 -    { "resync_size",   "Size limit for looking up a new syncronization.", offsetof(MpegTSContext, resync_size), AV_OPT_TYPE_INT,  { .i64 =  MAX_RESYNC_SIZE}, 0, INT_MAX,  AV_OPT_FLAG_DECODING_PARAM }
 +    { "resync_size",   "set size limit for looking up a new synchronization", offsetof(MpegTSContext, resync_size), AV_OPT_TYPE_INT,  { .i64 =  MAX_RESYNC_SIZE}, 0, INT_MAX,  AV_OPT_FLAG_DECODING_PARAM }
  
  static const AVOption options[] = {
      MPEGTS_OPTIONS,
 +    {"fix_teletext_pts", "try to fix pts values of dvb teletext streams", offsetof(MpegTSContext, fix_teletext_pts), AV_OPT_TYPE_INT,
 +     {.i64 = 1}, 0, 1, AV_OPT_FLAG_DECODING_PARAM },
 +    {"ts_packetsize", "output option carrying the raw packet size", offsetof(MpegTSContext, raw_packet_size), AV_OPT_TYPE_INT,
 +     {.i64 = 0}, 0, 0, AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_EXPORT | AV_OPT_FLAG_READONLY },
 +    {"scan_all_pmts",   "scan and combine all PMTs", offsetof(MpegTSContext, scan_all_pmts), AV_OPT_TYPE_INT,
 +     { .i64 =  -1}, -1, 1,  AV_OPT_FLAG_DECODING_PARAM },
 +    {"skip_changes", "skip changing / adding streams / programs", offsetof(MpegTSContext, skip_changes), AV_OPT_TYPE_INT,
 +     {.i64 = 0}, 0, 1, 0 },
 +    {"skip_clear", "skip clearing programs", offsetof(MpegTSContext, skip_clear), AV_OPT_TYPE_INT,
 +     {.i64 = 0}, 0, 1, 0 },
      { NULL },
  };
  
@@@ -188,10 -157,10 +188,10 @@@ static const AVClass mpegts_class = 
  
  static const AVOption raw_options[] = {
      MPEGTS_OPTIONS,
 -    { "compute_pcr",   "Compute exact PCR for each transport stream packet.",
 +    { "compute_pcr",   "compute exact PCR for each transport stream packet",
            offsetof(MpegTSContext, mpeg2ts_compute_pcr), AV_OPT_TYPE_INT,
            { .i64 = 0 }, 0, 1,  AV_OPT_FLAG_DECODING_PARAM },
 -    { "ts_packetsize", "Output option carrying the raw packet size.",
 +    { "ts_packetsize", "output option carrying the raw packet size",
        offsetof(MpegTSContext, raw_packet_size), AV_OPT_TYPE_INT,
        { .i64 = 0 }, 0, 0,
        AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_EXPORT | AV_OPT_FLAG_READONLY },
@@@ -244,42 -213,13 +244,42 @@@ typedef struct PESContext 
  
  extern AVInputFormat ff_mpegts_demuxer;
  
 +static struct Program * get_program(MpegTSContext *ts, unsigned int programid)
 +{
 +    int i;
 +    for (i = 0; i < ts->nb_prg; i++) {
 +        if (ts->prg[i].id == programid) {
 +            return &ts->prg[i];
 +        }
 +    }
 +    return NULL;
 +}
 +
 +static void clear_avprogram(MpegTSContext *ts, unsigned int programid)
 +{
 +    AVProgram *prg = NULL;
 +    int i;
 +
 +    for (i = 0; i < ts->stream->nb_programs; i++)
 +        if (ts->stream->programs[i]->id == programid) {
 +            prg = ts->stream->programs[i];
 +            break;
 +        }
 +    if (!prg)
 +        return;
 +    prg->nb_stream_indexes = 0;
 +}
 +
  static void clear_program(MpegTSContext *ts, unsigned int programid)
  {
      int i;
  
 +    clear_avprogram(ts, programid);
      for (i = 0; i < ts->nb_prg; i++)
 -        if (ts->prg[i].id == programid)
 +        if (ts->prg[i].id == programid) {
              ts->prg[i].nb_pids = 0;
 +            ts->prg[i].pmt_found = 0;
 +        }
  }
  
  static void clear_programs(MpegTSContext *ts)
@@@ -298,48 -238,28 +298,48 @@@ static void add_pat_entry(MpegTSContex
      p = &ts->prg[ts->nb_prg];
      p->id = programid;
      p->nb_pids = 0;
 +    p->pmt_found = 0;
      ts->nb_prg++;
  }
  
  static void add_pid_to_pmt(MpegTSContext *ts, unsigned int programid,
                             unsigned int pid)
  {
 +    struct Program *p = get_program(ts, programid);
      int i;
 -    struct Program *p = NULL;
 -    for (i = 0; i < ts->nb_prg; i++) {
 -        if (ts->prg[i].id == programid) {
 -            p = &ts->prg[i];
 -            break;
 -        }
 -    }
      if (!p)
          return;
  
      if (p->nb_pids >= MAX_PIDS_PER_PROGRAM)
          return;
 +
 +    for (i = 0; i < p->nb_pids; i++)
 +        if (p->pids[i] == pid)
 +            return;
 +
      p->pids[p->nb_pids++] = pid;
  }
  
 +static void set_pmt_found(MpegTSContext *ts, unsigned int programid)
 +{
 +    struct Program *p = get_program(ts, programid);
 +    if (!p)
 +        return;
 +
 +    p->pmt_found = 1;
 +}
 +
 +static void set_pcr_pid(AVFormatContext *s, unsigned int programid, unsigned int pid)
 +{
 +    int i;
 +    for (i = 0; i < s->nb_programs; i++) {
 +        if (s->programs[i]->id == programid) {
 +            s->programs[i]->pcr_pid = pid;
 +            break;
 +        }
 +    }
 +}
 +
  /**
   * @brief discard_pid() decides if the pid is to be discarded according
   *                      to caller's programs selection
@@@ -417,33 -337,22 +417,33 @@@ static void write_section_data(MpegTSCo
  
      if (tss->section_h_size != -1 &&
          tss->section_index >= tss->section_h_size) {
 +        int crc_valid = 1;
          tss->end_of_section_reached = 1;
 -        if (!tss->check_crc ||
 -            av_crc(av_crc_get_table(AV_CRC_32_IEEE), -1,
 -                   tss->section_buf, tss->section_h_size) == 0)
 +
 +        if (tss->check_crc) {
 +            crc_valid = !av_crc(av_crc_get_table(AV_CRC_32_IEEE), -1, tss->section_buf, tss->section_h_size);
 +            if (tss->section_h_size >= 4)
 +                tss->crc = AV_RB32(tss->section_buf + tss->section_h_size - 4);
 +
 +            if (crc_valid) {
 +                ts->crc_validity[ tss1->pid ] = 100;
 +            }else if (ts->crc_validity[ tss1->pid ] > -10) {
 +                ts->crc_validity[ tss1->pid ]--;
 +            }else
 +                crc_valid = 2;
 +        }
 +        if (crc_valid) {
              tss->section_cb(tss1, tss->section_buf, tss->section_h_size);
 +            if (crc_valid != 1)
 +                tss->last_ver = -1;
 +        }
      }
  }
  
 -static MpegTSFilter *mpegts_open_section_filter(MpegTSContext *ts,
 -                                                unsigned int pid,
 -                                                SectionCallback *section_cb,
 -                                                void *opaque,
 -                                                int check_crc)
 +static MpegTSFilter *mpegts_open_filter(MpegTSContext *ts, unsigned int pid,
 +                                        enum MpegTSFilterType type)
  {
      MpegTSFilter *filter;
 -    MpegTSSectionFilter *sec;
  
      av_log(ts->stream, AV_LOG_TRACE, "Filter: pid=0x%x\n", pid);
  
          return NULL;
      ts->pids[pid] = filter;
  
 -    filter->type    = MPEGTS_SECTION;
 +    filter->type    = type;
      filter->pid     = pid;
      filter->es_id   = -1;
      filter->last_cc = -1;
 +    filter->last_pcr= -1;
  
 +    return filter;
 +}
 +
 +static MpegTSFilter *mpegts_open_section_filter(MpegTSContext *ts,
 +                                                unsigned int pid,
 +                                                SectionCallback *section_cb,
 +                                                void *opaque,
 +                                                int check_crc)
 +{
 +    MpegTSFilter *filter;
 +    MpegTSSectionFilter *sec;
 +
 +    if (!(filter = mpegts_open_filter(ts, pid, MPEGTS_SECTION)))
 +        return NULL;
      sec = &filter->u.section_filter;
      sec->section_cb  = section_cb;
      sec->opaque      = opaque;
@@@ -495,20 -389,24 +495,20 @@@ static MpegTSFilter *mpegts_open_pes_fi
      MpegTSFilter *filter;
      MpegTSPESFilter *pes;
  
 -    if (pid >= NB_PID_MAX || ts->pids[pid])
 -        return NULL;
 -    filter = av_mallocz(sizeof(MpegTSFilter));
 -    if (!filter)
 +    if (!(filter = mpegts_open_filter(ts, pid, MPEGTS_PES)))
          return NULL;
  
 -    ts->pids[pid] = filter;
 -    filter->type    = MPEGTS_PES;
 -    filter->pid     = pid;
 -    filter->es_id   = -1;
 -    filter->last_cc = -1;
 -
      pes = &filter->u.pes_filter;
      pes->pes_cb = pes_cb;
      pes->opaque = opaque;
      return filter;
  }
  
 +static MpegTSFilter *mpegts_open_pcr_filter(MpegTSContext *ts, unsigned int pid)
 +{
 +    return mpegts_open_filter(ts, pid, MPEGTS_PCR);
 +}
 +
  static void mpegts_close_filter(MpegTSContext *ts, MpegTSFilter *filter)
  {
      int pid;
@@@ -534,27 -432,29 +534,27 @@@ static int analyze(const uint8_t *buf, 
                     int probe)
  {
      int stat[TS_MAX_PACKET_SIZE];
 +    int stat_all = 0;
      int i;
 -    int x = 0;
      int best_score = 0;
  
 -    memset(stat, 0, packet_size * sizeof(int));
 +    memset(stat, 0, packet_size * sizeof(*stat));
  
 -    for (x = i = 0; i < size - 3; i++) {
 +    for (i = 0; i < size - 3; i++) {
          if (buf[i] == 0x47 &&
 -            (!probe || (!(buf[i + 1] & 0x80) && (buf[i + 3] & 0x30)))) {
 +            (!probe || (!(buf[i + 1] & 0x80) && buf[i + 3] != 0x47))) {
 +            int x = i % packet_size;
              stat[x]++;
 +            stat_all++;
              if (stat[x] > best_score) {
                  best_score = stat[x];
                  if (index)
                      *index = x;
              }
          }
 -
 -        x++;
 -        if (x == packet_size)
 -            x = 0;
      }
  
 -    return best_score;
 +    return best_score - FFMAX(stat_all - 10*best_score, 0)/10;
  }
  
  /* autodetect fec presence. Must have at least 1024 bytes  */
@@@ -589,17 -489,6 +589,17 @@@ typedef struct SectionHeader 
      uint8_t last_sec_num;
  } SectionHeader;
  
 +static int skip_identical(const SectionHeader *h, MpegTSSectionFilter *tssf)
 +{
 +    if (h->version == tssf->last_ver && tssf->last_crc == tssf->crc)
 +        return 1;
 +
 +    tssf->last_ver = h->version;
 +    tssf->last_crc = tssf->crc;
 +
 +    return 0;
 +}
 +
  static inline int get8(const uint8_t **pp, const uint8_t *p_end)
  {
      const uint8_t *p;
@@@ -619,7 -508,7 +619,7 @@@ static inline int get16(const uint8_t *
      int c;
  
      p = *pp;
 -    if ((p + 1) >= p_end)
 +    if (1 >= p_end - p)
          return AVERROR_INVALIDDATA;
      c   = AV_RB16(p);
      p  += 2;
@@@ -638,7 -527,7 +638,7 @@@ static char *getstr8(const uint8_t **pp
      len = get8(&p, p_end);
      if (len < 0)
          return NULL;
 -    if ((p + len) > p_end)
 +    if (len > p_end - p)
          return NULL;
      str = av_malloc(len + 1);
      if (!str)
@@@ -692,13 -581,8 +692,13 @@@ static const StreamType ISO_types[] = 
      { 0x04, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_MP3        },
      { 0x0f, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AAC        },
      { 0x10, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_MPEG4      },
 +    /* Makito encoder sets stream type 0x11 for AAC,
 +     * so auto-detect LOAS/LATM instead of hardcoding it. */
 +#if !CONFIG_LOAS_DEMUXER
      { 0x11, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AAC_LATM   }, /* LATM syntax */
 +#endif
      { 0x1b, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_H264       },
 +    { 0x20, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_H264       },
      { 0x21, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_JPEG2000   },
      { 0x24, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_HEVC       },
      { 0x42, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_CAVS       },
@@@ -715,10 -599,7 +715,10 @@@ static const StreamType HDMV_types[] = 
      { 0x84, AVMEDIA_TYPE_AUDIO,    AV_CODEC_ID_EAC3              },
      { 0x85, AVMEDIA_TYPE_AUDIO,    AV_CODEC_ID_DTS               }, /* DTS HD */
      { 0x86, AVMEDIA_TYPE_AUDIO,    AV_CODEC_ID_DTS               }, /* DTS HD MASTER*/
 +    { 0xa1, AVMEDIA_TYPE_AUDIO,    AV_CODEC_ID_EAC3              }, /* E-AC3 Secondary Audio */
 +    { 0xa2, AVMEDIA_TYPE_AUDIO,    AV_CODEC_ID_DTS               }, /* DTS Express Secondary Audio */
      { 0x90, AVMEDIA_TYPE_SUBTITLE, AV_CODEC_ID_HDMV_PGS_SUBTITLE },
 +    { 0x92, AVMEDIA_TYPE_SUBTITLE, AV_CODEC_ID_HDMV_TEXT_SUBTITLE },
      { 0 },
  };
  
@@@ -737,18 -618,11 +737,18 @@@ static const StreamType REGD_types[] = 
      { MKTAG('D', 'T', 'S', '2'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS   },
      { MKTAG('D', 'T', 'S', '3'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS   },
      { MKTAG('H', 'E', 'V', 'C'), AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_HEVC  },
 +    { MKTAG('K', 'L', 'V', 'A'), AVMEDIA_TYPE_DATA,  AV_CODEC_ID_SMPTE_KLV },
      { MKTAG('V', 'C', '-', '1'), AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_VC1   },
      { MKTAG('O', 'p', 'u', 's'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_OPUS  },
      { 0 },
  };
  
 +static const StreamType METADATA_types[] = {
 +    { MKTAG('K','L','V','A'), AVMEDIA_TYPE_DATA, AV_CODEC_ID_SMPTE_KLV },
 +    { MKTAG('I','D','3',' '), AVMEDIA_TYPE_DATA, AV_CODEC_ID_TIMED_ID3 },
 +    { 0 },
 +};
 +
  /* descriptor present */
  static const StreamType DESC_types[] = {
      { 0x6a, AVMEDIA_TYPE_AUDIO,    AV_CODEC_ID_AC3          }, /* AC-3 descriptor */
@@@ -763,16 -637,10 +763,16 @@@ static void mpegts_find_stream_type(AVS
                                      uint32_t stream_type,
                                      const StreamType *types)
  {
 +    if (avcodec_is_open(st->codec)) {
 +        av_log(NULL, AV_LOG_DEBUG, "cannot set stream info, codec is open\n");
 +        return;
 +    }
 +
      for (; types->stream_type; types++)
          if (stream_type == types->stream_type) {
              st->codec->codec_type = types->codec_type;
              st->codec->codec_id   = types->codec_id;
 +            st->request_probe     = 0;
              return;
          }
  }
  static int mpegts_set_stream_info(AVStream *st, PESContext *pes,
                                    uint32_t stream_type, uint32_t prog_reg_desc)
  {
 +    int old_codec_type = st->codec->codec_type;
 +    int old_codec_id  = st->codec->codec_id;
 +
 +    if (avcodec_is_open(st->codec)) {
 +        av_log(pes->stream, AV_LOG_DEBUG, "cannot set stream info, codec is open\n");
 +        return 0;
 +    }
 +
      avpriv_set_pts_info(st, 33, 1, 90000);
      st->priv_data         = pes;
      st->codec->codec_type = AVMEDIA_TYPE_DATA;
      st->codec->codec_tag = pes->stream_type;
  
      mpegts_find_stream_type(st, pes->stream_type, ISO_types);
 -    if (prog_reg_desc == AV_RL32("HDMV") &&
 +    if ((prog_reg_desc == AV_RL32("HDMV") ||
 +         prog_reg_desc == AV_RL32("HDPR")) &&
          st->codec->codec_id == AV_CODEC_ID_NONE) {
          mpegts_find_stream_type(st, pes->stream_type, HDMV_types);
          if (pes->stream_type == 0x83) {
      }
      if (st->codec->codec_id == AV_CODEC_ID_NONE)
          mpegts_find_stream_type(st, pes->stream_type, MISC_types);
 +    if (st->codec->codec_id == AV_CODEC_ID_NONE) {
 +        st->codec->codec_id  = old_codec_id;
 +        st->codec->codec_type = old_codec_type;
 +    }
 +    if ((st->codec->codec_id == AV_CODEC_ID_NONE ||
 +            (st->request_probe > 0 && st->request_probe < AVPROBE_SCORE_STREAM_RETRY / 5)) &&
 +        !avcodec_is_open(st->codec) &&
 +        stream_type == STREAM_TYPE_PRIVATE_DATA) {
 +        st->codec->codec_type = AVMEDIA_TYPE_DATA;
 +        st->codec->codec_id   = AV_CODEC_ID_BIN_DATA;
 +        st->request_probe = AVPROBE_SCORE_STREAM_RETRY / 5;
 +    }
  
      return 0;
  }
  
 +static void reset_pes_packet_state(PESContext *pes)
 +{
 +    pes->pts        = AV_NOPTS_VALUE;
 +    pes->dts        = AV_NOPTS_VALUE;
 +    pes->data_index = 0;
 +    pes->flags      = 0;
 +    av_buffer_unref(&pes->buffer);
 +}
 +
  static void new_pes_packet(PESContext *pes, AVPacket *pkt)
  {
      av_init_packet(pkt);
      pkt->pos   = pes->ts_packet_pos;
      pkt->flags = pes->flags;
  
 -    /* reset pts values */
 -    pes->pts        = AV_NOPTS_VALUE;
 -    pes->dts        = AV_NOPTS_VALUE;
 -    pes->buffer     = NULL;
 -    pes->data_index = 0;
 -    pes->flags      = 0;
 +    pes->buffer = NULL;
 +    reset_pes_packet_state(pes);
 +}
 +
 +static uint64_t get_ts64(GetBitContext *gb, int bits)
 +{
 +    if (get_bits_left(gb) < bits)
 +        return AV_NOPTS_VALUE;
 +    return get_bits64(gb, bits);
  }
  
  static int read_sl_header(PESContext *pes, SLConfigDescr *sl,
      int padding_flag = 0, padding_bits = 0, inst_bitrate_flag = 0;
      int dts_flag = -1, cts_flag = -1;
      int64_t dts = AV_NOPTS_VALUE, cts = AV_NOPTS_VALUE;
 -    init_get_bits(&gb, buf, buf_size * 8);
 +    uint8_t buf_padded[128 + AV_INPUT_BUFFER_PADDING_SIZE];
 +    int buf_padded_size = FFMIN(buf_size, sizeof(buf_padded) - AV_INPUT_BUFFER_PADDING_SIZE);
 +
 +    memcpy(buf_padded, buf, buf_padded_size);
 +
 +    init_get_bits(&gb, buf_padded, buf_padded_size * 8);
  
      if (sl->use_au_start)
          au_start_flag = get_bits1(&gb);
          if (sl->inst_bitrate_len)
              inst_bitrate_flag = get_bits1(&gb);
          if (dts_flag == 1)
 -            dts = get_bits64(&gb, sl->timestamp_len);
 +            dts = get_ts64(&gb, sl->timestamp_len);
          if (cts_flag == 1)
 -            cts = get_bits64(&gb, sl->timestamp_len);
 +            cts = get_ts64(&gb, sl->timestamp_len);
          if (sl->au_len > 0)
              skip_bits_long(&gb, sl->au_len);
          if (inst_bitrate_flag)
@@@ -985,10 -815,9 +985,10 @@@ static int mpegts_push_data(MpegTSFilte
          if (pes->state == MPEGTS_PAYLOAD && pes->data_index > 0) {
              new_pes_packet(pes, ts->pkt);
              ts->stop_parse = 1;
 +        } else {
 +            reset_pes_packet_state(pes);
          }
          pes->state         = MPEGTS_HEADER;
 -        pes->data_index    = 0;
          pes->ts_packet_pos = pos;
      }
      p = buf;
  
                      /* stream not present in PMT */
                      if (!pes->st) {
 +                        if (ts->skip_changes)
 +                            goto skip;
 +
                          pes->st = avformat_new_stream(ts->stream, NULL);
                          if (!pes->st)
                              return AVERROR(ENOMEM);
                          code != 0x1ff && code != 0x1f2 && /* program_stream_directory, DSMCC_stream */
                          code != 0x1f8) {                  /* ITU-T Rec. H.222.1 type E stream */
                          pes->state = MPEGTS_PESHEADER;
 -                        if (pes->st->codec->codec_id == AV_CODEC_ID_NONE) {
 +                        if (pes->st->codec->codec_id == AV_CODEC_ID_NONE && !pes->st->request_probe) {
                              av_log(pes->stream, AV_LOG_TRACE,
                                      "pid=%x stream_type=%x probing\n",
                                      pes->pid,
                                      pes->stream_type);
 -                            pes->st->codec->codec_id = AV_CODEC_ID_PROBE;
 +                            pes->st->request_probe = 1;
                          }
                      } else {
 +                        pes->pes_header_size = 6;
                          pes->state      = MPEGTS_PAYLOAD;
                          pes->data_index = 0;
                      }
@@@ -1137,61 -962,10 +1137,61 @@@ skip
                      p += sl_header_bytes;
                      buf_size -= sl_header_bytes;
                  }
 +                if (pes->stream_type == 0x15 && buf_size >= 5) {
 +                    /* skip metadata access unit header */
 +                    pes->pes_header_size += 5;
 +                    p += 5;
 +                    buf_size -= 5;
 +                }
 +                if (   pes->ts->fix_teletext_pts
 +                    && (   pes->st->codec->codec_id == AV_CODEC_ID_DVB_TELETEXT
 +                        || pes->st->codec->codec_id == AV_CODEC_ID_DVB_SUBTITLE)
 +                    ) {
 +                    AVProgram *p = NULL;
 +                    while ((p = av_find_program_from_stream(pes->stream, p, pes->st->index))) {
 +                        if (p->pcr_pid != -1 && p->discard != AVDISCARD_ALL) {
 +                            MpegTSFilter *f = pes->ts->pids[p->pcr_pid];
 +                            if (f) {
 +                                AVStream *st = NULL;
 +                                if (f->type == MPEGTS_PES) {
 +                                    PESContext *pcrpes = f->u.pes_filter.opaque;
 +                                    if (pcrpes)
 +                                        st = pcrpes->st;
 +                                } else if (f->type == MPEGTS_PCR) {
 +                                    int i;
 +                                    for (i = 0; i < p->nb_stream_indexes; i++) {
 +                                        AVStream *pst = pes->stream->streams[p->stream_index[i]];
 +                                        if (pst->codec->codec_type == AVMEDIA_TYPE_VIDEO)
 +                                            st = pst;
 +                                    }
 +                                }
 +                                if (f->last_pcr != -1 && st && st->discard != AVDISCARD_ALL) {
 +                                    // teletext packets do not always have correct timestamps,
 +                                    // the standard says they should be handled after 40.6 ms at most,
 +                                    // and the pcr error to this packet should be no more than 100 ms.
 +                                    // TODO: we should interpolate the PCR, not just use the last one
 +                                    int64_t pcr = f->last_pcr / 300;
 +                                    pes->st->pts_wrap_reference = st->pts_wrap_reference;
 +                                    pes->st->pts_wrap_behavior = st->pts_wrap_behavior;
 +                                    if (pes->dts == AV_NOPTS_VALUE || pes->dts < pcr) {
 +                                        pes->pts = pes->dts = pcr;
 +                                    } else if (pes->st->codec->codec_id == AV_CODEC_ID_DVB_TELETEXT &&
 +                                               pes->dts > pcr + 3654 + 9000) {
 +                                        pes->pts = pes->dts = pcr + 3654 + 9000;
 +                                    } else if (pes->st->codec->codec_id == AV_CODEC_ID_DVB_SUBTITLE &&
 +                                               pes->dts > pcr + 10*90000) { //10sec
 +                                        pes->pts = pes->dts = pcr + 3654 + 9000;
 +                                    }
 +                                    break;
 +                                }
 +                            }
 +                        }
 +                    }
 +                }
              }
              break;
          case MPEGTS_PAYLOAD:
 -            if (buf_size > 0 && pes->buffer) {
 +            if (pes->buffer) {
                  if (pes->data_index > 0 &&
                      pes->data_index + buf_size > pes->total_size) {
                      new_pes_packet(pes, ts->pkt);
                  }
                  memcpy(pes->buffer->data + pes->data_index, p, buf_size);
                  pes->data_index += buf_size;
 +                /* emit complete packets with known packet size
 +                 * decreases demuxer delay for infrequent packets like subtitles from
 +                 * a couple of seconds to milliseconds for properly muxed files.
 +                 * total_size is the number of bytes following pes_packet_length
 +                 * in the pes header, i.e. not counting the first PES_START_SIZE bytes */
 +                if (!ts->stop_parse && pes->total_size < MAX_PES_PAYLOAD &&
 +                    pes->pes_header_size + pes->data_index == pes->total_size + PES_START_SIZE) {
 +                    ts->stop_parse = 1;
 +                    new_pes_packet(pes, ts->pkt);
 +                }
              }
              buf_size = 0;
 -            /* emit complete packets with known packet size
 -             * decreases demuxer delay for infrequent packets like subtitles from
 -             * a couple of seconds to milliseconds for properly muxed files.
 -             * total_size is the number of bytes following pes_packet_length
 -             * in the pes header, i.e. not counting the first PES_START_SIZE bytes */
 -            if (!ts->stop_parse && pes->total_size < MAX_PES_PAYLOAD &&
 -                pes->pes_header_size + pes->data_index == pes->total_size + PES_START_SIZE) {
 -                ts->stop_parse = 1;
 -                new_pes_packet(pes, ts->pkt);
 -            }
              break;
          case MPEGTS_SKIP:
              buf_size = 0;
@@@ -1264,7 -1038,6 +1264,7 @@@ typedef struct MP4DescrParseContext 
      int descr_count;
      int max_descr_count;
      int level;
 +    int predefined_SLConfigDescriptor_seen;
  } MP4DescrParseContext;
  
  static int init_MP4DescrParseContext(MP4DescrParseContext *d, AVFormatContext *s,
@@@ -1388,11 -1161,6 +1388,11 @@@ static int parse_MP4SLDescrTag(MP4Descr
          descr->sl.timestamp_res   = avio_rb32(&d->pb);
          avio_rb32(&d->pb);
          descr->sl.timestamp_len      = avio_r8(&d->pb);
 +        if (descr->sl.timestamp_len > 64) {
 +            avpriv_request_sample(NULL, "timestamp_len > 64");
 +            descr->sl.timestamp_len = 64;
 +            return AVERROR_PATCHWELCOME;
 +        }
          descr->sl.ocr_len            = avio_r8(&d->pb);
          descr->sl.au_len             = avio_r8(&d->pb);
          descr->sl.inst_bitrate_len   = avio_r8(&d->pb);
          descr->sl.degr_prior_len     = lengths >> 12;
          descr->sl.au_seq_num_len     = (lengths >> 7) & 0x1f;
          descr->sl.packet_seq_num_len = (lengths >> 2) & 0x1f;
 -    } else {
 +    } else if (!d->predefined_SLConfigDescriptor_seen){
          avpriv_report_missing_feature(d->s, "Predefined SLConfigDescriptor");
 +        d->predefined_SLConfigDescriptor_seen = 1;
      }
      return 0;
  }
@@@ -1507,8 -1274,9 +1507,8 @@@ static void m4sl_cb(MpegTSFilter *filte
          return;
      if (h.tid != M4OD_TID)
          return;
 -    if (h.version == tssf->last_ver)
 +    if (skip_identical(&h, tssf))
          return;
 -    tssf->last_ver = h.version;
  
      mp4_read_od(s, p, (unsigned) (p_end - p), mp4_descr, &mp4_descr_count,
                  MAX_MP4_DESCR_COUNT);
              AVStream *st;
              if (ts->pids[pid]->es_id != mp4_descr[i].es_id)
                  continue;
 -            if (!(ts->pids[pid] && ts->pids[pid]->type == MPEGTS_PES)) {
 +            if (ts->pids[pid]->type != MPEGTS_PES) {
                  av_log(s, AV_LOG_ERROR, "pid %x is not PES\n", pid);
                  continue;
              }
                  st->codec->extradata_size > 0)
                  st->need_parsing = 0;
  
-             if (st->codec->codec_id <= AV_CODEC_ID_NONE) {
-                 // do nothing
-             } else if (st->codec->codec_id < AV_CODEC_ID_FIRST_AUDIO)
-                 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-             else if (st->codec->codec_id < AV_CODEC_ID_FIRST_SUBTITLE)
-                 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-             else if (st->codec->codec_id < AV_CODEC_ID_FIRST_UNKNOWN)
-                 st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
+             st->codec->codec_type = avcodec_get_type(st->codec->codec_id);
          }
      }
      for (i = 0; i < mp4_descr_count; i++)
@@@ -1598,7 -1359,7 +1591,7 @@@ int ff_parse_mpeg2_descriptor(AVFormatC
  
      av_log(fc, AV_LOG_TRACE, "tag: 0x%02x len=%d\n", desc_tag, desc_len);
  
 -    if (st->codec->codec_id == AV_CODEC_ID_NONE &&
 +    if ((st->codec->codec_id == AV_CODEC_ID_NONE || st->request_probe > 0) &&
          stream_type == STREAM_TYPE_PRIVATE_DATA)
          mpegts_find_stream_type(st, desc_tag, DESC_types);
  
          if (get16(pp, desc_end) < 0)
              break;
          if (mp4_descr_count > 0 &&
 -            st->codec->codec_id == AV_CODEC_ID_AAC_LATM &&
 +            (st->codec->codec_id == AV_CODEC_ID_AAC_LATM ||
 +             (st->request_probe == 0 && st->codec->codec_id == AV_CODEC_ID_NONE) ||
 +             st->request_probe > 0) &&
              mp4_descr->dec_config_descr_len && mp4_descr->es_id == pid) {
              AVIOContext pb;
              ffio_init_context(&pb, mp4_descr->dec_config_descr,
                                NULL, NULL, NULL, NULL);
              ff_mp4_read_dec_config_descr(fc, st, &pb);
              if (st->codec->codec_id == AV_CODEC_ID_AAC &&
 -                st->codec->extradata_size > 0)
 -                st->need_parsing = 0;
 +                st->codec->extradata_size > 0) {
 +                st->request_probe = st->need_parsing = 0;
 +                st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
 +            }
          }
          break;
      case 0x56: /* DVB teletext descriptor */
 -        language[0] = get8(pp, desc_end);
 -        language[1] = get8(pp, desc_end);
 -        language[2] = get8(pp, desc_end);
 -        language[3] = 0;
 -        av_dict_set(&st->metadata, "language", language, 0);
 +        {
 +            uint8_t *extradata = NULL;
 +            int language_count = desc_len / 5;
 +
 +            if (desc_len > 0 && desc_len % 5 != 0)
 +                return AVERROR_INVALIDDATA;
 +
 +            if (language_count > 0) {
 +                /* 4 bytes per language code (3 bytes) with comma or NUL byte should fit language buffer */
 +                av_assert0(language_count <= sizeof(language) / 4);
 +
 +                if (st->codec->extradata == NULL) {
 +                    if (ff_alloc_extradata(st->codec, language_count * 2)) {
 +                        return AVERROR(ENOMEM);
 +                    }
 +                }
 +
 +               if (st->codec->extradata_size < language_count * 2)
 +                   return AVERROR_INVALIDDATA;
 +
 +               extradata = st->codec->extradata;
 +
 +                for (i = 0; i < language_count; i++) {
 +                    language[i * 4 + 0] = get8(pp, desc_end);
 +                    language[i * 4 + 1] = get8(pp, desc_end);
 +                    language[i * 4 + 2] = get8(pp, desc_end);
 +                    language[i * 4 + 3] = ',';
 +
 +                    memcpy(extradata, *pp, 2);
 +                    extradata += 2;
 +
 +                    *pp += 2;
 +                }
 +
 +                language[i * 4 - 1] = 0;
 +                av_dict_set(&st->metadata, "language", language, 0);
 +            }
 +        }
          break;
      case 0x59: /* subtitling descriptor */
 -        language[0] = get8(pp, desc_end);
 -        language[1] = get8(pp, desc_end);
 -        language[2] = get8(pp, desc_end);
 -        language[3] = 0;
 -        /* hearing impaired subtitles detection */
 -        switch (get8(pp, desc_end)) {
 -        case 0x20: /* DVB subtitles (for the hard of hearing) with no monitor aspect ratio criticality */
 -        case 0x21: /* DVB subtitles (for the hard of hearing) for display on 4:3 aspect ratio monitor */
 -        case 0x22: /* DVB subtitles (for the hard of hearing) for display on 16:9 aspect ratio monitor */
 -        case 0x23: /* DVB subtitles (for the hard of hearing) for display on 2.21:1 aspect ratio monitor */
 -        case 0x24: /* DVB subtitles (for the hard of hearing) for display on a high definition monitor */
 -        case 0x25: /* DVB subtitles (for the hard of hearing) with plano-stereoscopic disparity for display on a high definition monitor */
 -            st->disposition |= AV_DISPOSITION_HEARING_IMPAIRED;
 -            break;
 -        }
 -        if (st->codec->extradata) {
 -            if (st->codec->extradata_size == 4 &&
 -                memcmp(st->codec->extradata, *pp, 4))
 -                avpriv_request_sample(fc, "DVB sub with multiple IDs");
 -        } else {
 -            st->codec->extradata = av_malloc(4 + AV_INPUT_BUFFER_PADDING_SIZE);
 -            if (st->codec->extradata) {
 -                st->codec->extradata_size = 4;
 -                memcpy(st->codec->extradata, *pp, 4);
 +        {
 +            /* 8 bytes per DVB subtitle substream data:
 +             * ISO_639_language_code (3 bytes),
 +             * subtitling_type (1 byte),
 +             * composition_page_id (2 bytes),
 +             * ancillary_page_id (2 bytes) */
 +            int language_count = desc_len / 8;
 +
 +            if (desc_len > 0 && desc_len % 8 != 0)
 +                return AVERROR_INVALIDDATA;
 +
 +            if (language_count > 1) {
 +                avpriv_request_sample(fc, "DVB subtitles with multiple languages");
 +            }
 +
 +            if (language_count > 0) {
 +                uint8_t *extradata;
 +
 +                /* 4 bytes per language code (3 bytes) with comma or NUL byte should fit language buffer */
 +                av_assert0(language_count <= sizeof(language) / 4);
 +
 +                if (st->codec->extradata == NULL) {
 +                    if (ff_alloc_extradata(st->codec, language_count * 5)) {
 +                        return AVERROR(ENOMEM);
 +                    }
 +                }
 +
 +                if (st->codec->extradata_size < language_count * 5)
 +                    return AVERROR_INVALIDDATA;
 +
 +                extradata = st->codec->extradata;
 +
 +                for (i = 0; i < language_count; i++) {
 +                    language[i * 4 + 0] = get8(pp, desc_end);
 +                    language[i * 4 + 1] = get8(pp, desc_end);
 +                    language[i * 4 + 2] = get8(pp, desc_end);
 +                    language[i * 4 + 3] = ',';
 +
 +                    /* hearing impaired subtitles detection using subtitling_type */
 +                    switch (*pp[0]) {
 +                    case 0x20: /* DVB subtitles (for the hard of hearing) with no monitor aspect ratio criticality */
 +                    case 0x21: /* DVB subtitles (for the hard of hearing) for display on 4:3 aspect ratio monitor */
 +                    case 0x22: /* DVB subtitles (for the hard of hearing) for display on 16:9 aspect ratio monitor */
 +                    case 0x23: /* DVB subtitles (for the hard of hearing) for display on 2.21:1 aspect ratio monitor */
 +                    case 0x24: /* DVB subtitles (for the hard of hearing) for display on a high definition monitor */
 +                    case 0x25: /* DVB subtitles (for the hard of hearing) with plano-stereoscopic disparity for display on a high definition monitor */
 +                        st->disposition |= AV_DISPOSITION_HEARING_IMPAIRED;
 +                        break;
 +                    }
 +
 +                    extradata[4] = get8(pp, desc_end); /* subtitling_type */
 +                    memcpy(extradata, *pp, 4); /* composition_page_id and ancillary_page_id */
 +                    extradata += 5;
 +
 +                    *pp += 4;
 +                }
 +
 +                language[i * 4 - 1] = 0;
 +                av_dict_set(&st->metadata, "language", language, 0);
              }
          }
 -        *pp += 4;
 -        av_dict_set(&st->metadata, "language", language, 0);
          break;
      case 0x0a: /* ISO 639 language descriptor */
          for (i = 0; i + 4 <= desc_len; i += 4) {
      case 0x05: /* registration descriptor */
          st->codec->codec_tag = bytestream_get_le32(pp);
          av_log(fc, AV_LOG_TRACE, "reg_desc=%.4s\n", (char *)&st->codec->codec_tag);
 -        if (st->codec->codec_id == AV_CODEC_ID_NONE)
 +        if (st->codec->codec_id == AV_CODEC_ID_NONE || st->request_probe > 0)
              mpegts_find_stream_type(st, st->codec->codec_tag, REGD_types);
          break;
 +    case 0x52: /* stream identifier descriptor */
 +        st->stream_identifier = 1 + get8(pp, desc_end);
 +        break;
 +    case 0x26: /* metadata descriptor */
 +        if (get16(pp, desc_end) == 0xFFFF)
 +            *pp += 4;
 +        if (get8(pp, desc_end) == 0xFF) {
 +            st->codec->codec_tag = bytestream_get_le32(pp);
 +            if (st->codec->codec_id == AV_CODEC_ID_NONE)
 +                mpegts_find_stream_type(st, st->codec->codec_tag, METADATA_types);
 +        }
 +        break;
      case 0x7f: /* DVB extension descriptor */
          ext_desc_tag = get8(pp, desc_end);
          if (ext_desc_tag < 0)
                      return AVERROR_INVALIDDATA;
                  if (channel_config_code <= 0x8) {
                      st->codec->extradata[9]  = channels = channel_config_code ? channel_config_code : 2;
 -                    st->codec->extradata[18] = channel_config_code ? (channels > 2) : 255;
 +                    st->codec->extradata[18] = channel_config_code ? (channels > 2) : /* Dual Mono */ 255;
                      st->codec->extradata[19] = opus_stream_cnt[channel_config_code];
                      st->codec->extradata[20] = opus_coupled_stream_cnt[channel_config_code];
                      memcpy(&st->codec->extradata[21], opus_channel_map[channels - 1], channels);
@@@ -1849,26 -1528,22 +1842,26 @@@ static void pmt_cb(MpegTSFilter *filter
      p = section;
      if (parse_section_header(h, &p, p_end) < 0)
          return;
 -    if (h->version == tssf->last_ver)
 +    if (skip_identical(h, tssf))
          return;
 -    tssf->last_ver = h->version;
  
 -    av_log(ts->stream, AV_LOG_TRACE, "sid=0x%x sec_num=%d/%d\n",
 -            h->id, h->sec_num, h->last_sec_num);
 +    av_log(ts->stream, AV_LOG_TRACE, "sid=0x%x sec_num=%d/%d version=%d\n",
 +            h->id, h->sec_num, h->last_sec_num, h->version);
  
      if (h->tid != PMT_TID)
          return;
 +    if (!ts->scan_all_pmts && ts->skip_changes)
 +        return;
 +
 +    if (!ts->skip_clear)
 +        clear_program(ts, h->id);
  
 -    clear_program(ts, h->id);
      pcr_pid = get16(&p, p_end);
      if (pcr_pid < 0)
          return;
      pcr_pid &= 0x1fff;
      add_pid_to_pmt(ts, h->id, pcr_pid);
 +    set_pcr_pid(ts->stream, h->id, pcr_pid);
  
      av_log(ts->stream, AV_LOG_TRACE, "pcr_pid=0x%x\n", pcr_pid);
  
  
      // stop parsing after pmt, we found header
      if (!ts->stream->nb_streams)
 -        ts->stop_parse = 1;
 +        ts->stop_parse = 2;
 +
 +    set_pmt_found(ts, h->id);
  
  
      for (;;) {
              break;
          pid = get16(&p, p_end);
          if (pid < 0)
 -            break;
 +            goto out;
          pid &= 0x1fff;
 +        if (pid == ts->current_pid)
 +            goto out;
  
          /* now create stream */
          if (ts->pids[pid] && ts->pids[pid]->type == MPEGTS_PES) {
              pes = ts->pids[pid]->u.pes_filter.opaque;
              if (!pes->st) {
                  pes->st     = avformat_new_stream(pes->stream, NULL);
 +                if (!pes->st)
 +                    goto out;
                  pes->st->id = pes->pid;
              }
              st = pes->st;
              pes = add_pes_stream(ts, pid, pcr_pid);
              if (pes) {
                  st = avformat_new_stream(pes->stream, NULL);
 +                if (!st)
 +                    goto out;
                  st->id = pes->pid;
              }
          } else {
                  st = ts->stream->streams[idx];
              } else {
                  st = avformat_new_stream(ts->stream, NULL);
 +                if (!st)
 +                    goto out;
                  st->id = pid;
                  st->codec->codec_type = AVMEDIA_TYPE_DATA;
              }
  
          desc_list_len = get16(&p, p_end);
          if (desc_list_len < 0)
 -            break;
 +            goto out;
          desc_list_len &= 0xfff;
          desc_list_end  = p + desc_list_len;
          if (desc_list_end > p_end)
 -            break;
 +            goto out;
          for (;;) {
              if (ff_parse_mpeg2_descriptor(ts->stream, st, stream_type, &p,
                                            desc_list_end, mp4_descr,
          p = desc_list_end;
      }
  
 +    if (!ts->pids[pcr_pid])
 +        mpegts_open_pcr_filter(ts, pcr_pid);
 +
  out:
      for (i = 0; i < mp4_descr_count; i++)
          av_free(mp4_descr[i].dec_config_descr);
@@@ -2004,7 -1666,6 +1997,7 @@@ static void pat_cb(MpegTSFilter *filter
      SectionHeader h1, *h = &h1;
      const uint8_t *p, *p_end;
      int sid, pmt_pid;
 +    AVProgram *program;
  
      av_log(ts->stream, AV_LOG_TRACE, "PAT:\n");
      hex_dump_debug(ts->stream, section, section_len);
          return;
      if (h->tid != PAT_TID)
          return;
 -    if (h->version == tssf->last_ver)
 +    if (ts->skip_changes)
          return;
 -    tssf->last_ver = h->version;
 +
 +    if (skip_identical(h, tssf))
 +        return;
 +    ts->stream->ts_id = h->id;
  
      clear_programs(ts);
      for (;;) {
              break;
          pmt_pid &= 0x1fff;
  
 +        if (pmt_pid == ts->current_pid)
 +            break;
 +
          av_log(ts->stream, AV_LOG_TRACE, "sid=0x%x pid=0x%x\n", sid, pmt_pid);
  
          if (sid == 0x0000) {
              /* NIT info */
          } else {
 -            av_new_program(ts->stream, sid);
 -            if (ts->pids[pmt_pid])
 -                mpegts_close_filter(ts, ts->pids[pmt_pid]);
 -            mpegts_open_section_filter(ts, pmt_pid, pmt_cb, ts, 1);
 +            MpegTSFilter *fil = ts->pids[pmt_pid];
 +            program = av_new_program(ts->stream, sid);
 +            if (program) {
 +                program->program_num = sid;
 +                program->pmt_pid = pmt_pid;
 +            }
 +            if (fil)
 +                if (   fil->type != MPEGTS_SECTION
 +                    || fil->pid != pmt_pid
 +                    || fil->u.section_filter.section_cb != pmt_cb)
 +                    mpegts_close_filter(ts, ts->pids[pmt_pid]);
 +
 +            if (!ts->pids[pmt_pid])
 +                mpegts_open_section_filter(ts, pmt_pid, pmt_cb, ts, 1);
              add_pat_entry(ts, sid);
              add_pid_to_pmt(ts, sid, 0); // add pat pid to program
              add_pid_to_pmt(ts, sid, pmt_pid);
          }
      }
 +
 +    if (sid < 0) {
 +        int i,j;
 +        for (j=0; j<ts->stream->nb_programs; j++) {
 +            for (i = 0; i < ts->nb_prg; i++)
 +                if (ts->prg[i].id == ts->stream->programs[j]->id)
 +                    break;
 +            if (i==ts->nb_prg && !ts->skip_clear)
 +                clear_avprogram(ts, ts->stream->programs[j]->id);
 +        }
 +    }
  }
  
  static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len)
          return;
      if (h->tid != SDT_TID)
          return;
 -    if (h->version == tssf->last_ver)
 +    if (ts->skip_changes)
 +        return;
 +    if (skip_identical(h, tssf))
          return;
 -    tssf->last_ver = h->version;
  
      onid = get16(&p, p_end);
      if (onid < 0)
                  break;
              desc_len = get8(&p, desc_list_end);
              desc_end = p + desc_len;
 -            if (desc_end > desc_list_end)
 +            if (desc_len < 0 || desc_end > desc_list_end)
                  break;
  
              av_log(ts->stream, AV_LOG_TRACE, "tag: 0x%02x len=%d\n",
      }
  }
  
 +static int parse_pcr(int64_t *ppcr_high, int *ppcr_low,
 +                     const uint8_t *packet);
 +
  /* handle one TS packet */
  static int handle_packet(MpegTSContext *ts, const uint8_t *packet)
  {
      }
      if (!tss)
          return 0;
 +    ts->current_pid = pid;
  
      afc = (packet[3] >> 4) & 3;
      if (afc == 0) /* reserved value */
  
      tss->last_cc = cc;
      if (!cc_ok) {
 -        av_log(ts->stream, AV_LOG_WARNING,
 +        av_log(ts->stream, AV_LOG_DEBUG,
                 "Continuity check failed for pid %d expected %d got %d\n",
                 pid, expected_cc, cc);
          if (tss->type == MPEGTS_PES) {
          }
      }
  
 -    if (!has_payload)
 -        return 0;
      p = packet + 4;
      if (has_adaptation) {
 +        int64_t pcr_h;
 +        int pcr_l;
 +        if (parse_pcr(&pcr_h, &pcr_l, packet) == 0)
 +            tss->last_pcr = pcr_h * 300 + pcr_l;
          /* skip adaptation field */
          p += p[0] + 1;
      }
      /* if past the end of packet, ignore */
      p_end = packet + TS_PACKET_SIZE;
 -    if (p >= p_end)
 +    if (p >= p_end || !has_payload)
          return 0;
  
      pos = avio_tell(ts->stream->pb);
 -    MOD_UNLIKELY(ts->pos47, pos, ts->raw_packet_size, ts->pos);
 +    if (pos >= 0) {
 +        av_assert0(pos >= TS_PACKET_SIZE);
 +        ts->pos47_full = pos - TS_PACKET_SIZE;
 +    }
  
      if (tss->type == MPEGTS_SECTION) {
          if (is_start) {
              /* pointer field present */
              len = *p++;
 -            if (p + len > p_end)
 +            if (len > p_end - p)
                  return 0;
              if (len && cc_ok) {
                  /* write remaining section bytes */
                                     p, p_end - p, 0);
              }
          }
 +
 +        // stop find_stream_info from waiting for more streams
 +        // when all programs have received a PMT
 +        if (ts->stream->ctx_flags & AVFMTCTX_NOHEADER && ts->scan_all_pmts <= 0) {
 +            int i;
 +            for (i = 0; i < ts->nb_prg; i++) {
 +                if (!ts->prg[i].pmt_found)
 +                    break;
 +            }
 +            if (i == ts->nb_prg && ts->nb_prg > 0) {
 +                int types = 0;
 +                for (i = 0; i < ts->stream->nb_streams; i++) {
 +                    AVStream *st = ts->stream->streams[i];
 +                    types |= 1<<st->codec->codec_type;
 +                }
 +                if ((types & (1<<AVMEDIA_TYPE_AUDIO) && types & (1<<AVMEDIA_TYPE_VIDEO)) || pos > 100000) {
 +                    av_log(ts->stream, AV_LOG_DEBUG, "All programs have pmt, headers found\n");
 +                    ts->stream->ctx_flags &= ~AVFMTCTX_NOHEADER;
 +                }
 +            }
 +        }
 +
      } else {
          int ret;
          // Note: The position here points actually behind the current packet.
 -        if ((ret = tss->u.pes_filter.pes_cb(tss, p, p_end - p, is_start,
 -                                            pos - ts->raw_packet_size)) < 0)
 -            return ret;
 +        if (tss->type == MPEGTS_PES) {
 +            if ((ret = tss->u.pes_filter.pes_cb(tss, p, p_end - p, is_start,
 +                                                pos - ts->raw_packet_size)) < 0)
 +                return ret;
 +        }
      }
  
      return 0;
  }
  
 +static void reanalyze(MpegTSContext *ts) {
 +    AVIOContext *pb = ts->stream->pb;
 +    int64_t pos = avio_tell(pb);
 +    if (pos < 0)
 +        return;
 +    pos -= ts->pos47_full;
 +    if (pos == TS_PACKET_SIZE) {
 +        ts->size_stat[0] ++;
 +    } else if (pos == TS_DVHS_PACKET_SIZE) {
 +        ts->size_stat[1] ++;
 +    } else if (pos == TS_FEC_PACKET_SIZE) {
 +        ts->size_stat[2] ++;
 +    }
 +
 +    ts->size_stat_count ++;
 +    if (ts->size_stat_count > SIZE_STAT_THRESHOLD) {
 +        int newsize = 0;
 +        if (ts->size_stat[0] > SIZE_STAT_THRESHOLD) {
 +            newsize = TS_PACKET_SIZE;
 +        } else if (ts->size_stat[1] > SIZE_STAT_THRESHOLD) {
 +            newsize = TS_DVHS_PACKET_SIZE;
 +        } else if (ts->size_stat[2] > SIZE_STAT_THRESHOLD) {
 +            newsize = TS_FEC_PACKET_SIZE;
 +        }
 +        if (newsize && newsize != ts->raw_packet_size) {
 +            av_log(ts->stream, AV_LOG_WARNING, "changing packet size to %d\n", newsize);
 +            ts->raw_packet_size = newsize;
 +        }
 +        ts->size_stat_count = 0;
 +        memset(ts->size_stat, 0, sizeof(ts->size_stat));
 +    }
 +}
 +
  /* XXX: try to find a better synchro over several packets (use
   * get_packet_size() ?) */
  static int mpegts_resync(AVFormatContext *s)
  
      for (i = 0; i < ts->resync_size; i++) {
          c = avio_r8(pb);
 -        if (pb->eof_reached)
 +        if (avio_feof(pb))
              return AVERROR_EOF;
          if (c == 0x47) {
              avio_seek(pb, -1, SEEK_CUR);
 +            reanalyze(s->priv_data);
              return 0;
          }
      }
@@@ -2360,9 -1926,7 +2353,9 @@@ static int read_packet(AVFormatContext 
          /* check packet sync byte */
          if ((*data)[0] != 0x47) {
              /* find a new packet start */
 -            avio_seek(pb, -TS_PACKET_SIZE, SEEK_CUR);
 +            uint64_t pos = avio_tell(pb);
 +            avio_seek(pb, -FFMIN(raw_packet_size, pos), SEEK_CUR);
 +
              if (mpegts_resync(s) < 0)
                  return AVERROR(EAGAIN);
              else
@@@ -2382,13 -1946,12 +2375,13 @@@ static void finished_reading_packet(AVF
          avio_skip(pb, skip);
  }
  
 -static int handle_packets(MpegTSContext *ts, int nb_packets)
 +static int handle_packets(MpegTSContext *ts, int64_t nb_packets)
  {
      AVFormatContext *s = ts->stream;
      uint8_t packet[TS_PACKET_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
      const uint8_t *data;
 -    int packet_num, ret = 0;
 +    int64_t packet_num;
 +    int ret = 0;
  
      if (avio_tell(s->pb) != ts->last_pos) {
          int i;
                      av_buffer_unref(&pes->buffer);
                      pes->data_index = 0;
                      pes->state = MPEGTS_SKIP; /* skip until pes header */
 +                } else if (ts->pids[i]->type == MPEGTS_SECTION) {
 +                    ts->pids[i]->u.section_filter.last_ver = -1;
                  }
                  ts->pids[i]->last_cc = -1;
 +                ts->pids[i]->last_pcr = -1;
              }
          }
      }
      packet_num = 0;
      memset(packet + TS_PACKET_SIZE, 0, AV_INPUT_BUFFER_PADDING_SIZE);
      for (;;) {
 -        if (ts->stop_parse > 0)
 -            break;
          packet_num++;
 -        if (nb_packets != 0 && packet_num >= nb_packets)
 +        if (nb_packets != 0 && packet_num >= nb_packets ||
 +            ts->stop_parse > 1) {
 +            ret = AVERROR(EAGAIN);
              break;
 +        }
 +        if (ts->stop_parse > 0)
 +            break;
 +
          ret = read_packet(s, packet, ts->raw_packet_size, &data);
          if (ret != 0)
              break;
  static int mpegts_probe(AVProbeData *p)
  {
      const int size = p->buf_size;
 -    int score, fec_score, dvhs_score;
 +    int maxscore = 0;
 +    int sumscore = 0;
 +    int i;
      int check_count = size / TS_FEC_PACKET_SIZE;
  #define CHECK_COUNT 10
 +#define CHECK_BLOCK 100
  
      if (check_count < CHECK_COUNT)
 -        return AVERROR_INVALIDDATA;
 +        return 0;
  
 -    score = analyze(p->buf, TS_PACKET_SIZE * check_count,
 -                    TS_PACKET_SIZE, NULL, 1) * CHECK_COUNT / check_count;
 -    dvhs_score = analyze(p->buf, TS_DVHS_PACKET_SIZE * check_count,
 -                         TS_DVHS_PACKET_SIZE, NULL, 1) * CHECK_COUNT / check_count;
 -    fec_score = analyze(p->buf, TS_FEC_PACKET_SIZE * check_count,
 -                        TS_FEC_PACKET_SIZE, NULL, 1) * CHECK_COUNT / check_count;
 -    av_log(NULL, AV_LOG_TRACE, "score: %d, dvhs_score: %d, fec_score: %d \n",
 -            score, dvhs_score, fec_score);
 +    for (i = 0; i<check_count; i+=CHECK_BLOCK) {
 +        int left = FFMIN(check_count - i, CHECK_BLOCK);
 +        int score      = analyze(p->buf + TS_PACKET_SIZE     *i, TS_PACKET_SIZE     *left, TS_PACKET_SIZE     , NULL, 1);
 +        int dvhs_score = analyze(p->buf + TS_DVHS_PACKET_SIZE*i, TS_DVHS_PACKET_SIZE*left, TS_DVHS_PACKET_SIZE, NULL, 1);
 +        int fec_score  = analyze(p->buf + TS_FEC_PACKET_SIZE *i, TS_FEC_PACKET_SIZE *left, TS_FEC_PACKET_SIZE , NULL, 1);
 +        score = FFMAX3(score, dvhs_score, fec_score);
 +        sumscore += score;
 +        maxscore = FFMAX(maxscore, score);
 +    }
 +
 +    sumscore = sumscore * CHECK_COUNT / check_count;
 +    maxscore = maxscore * CHECK_COUNT / CHECK_BLOCK;
  
 -    /* we need a clear definition for the returned score otherwise
 -     * things will become messy sooner or later */
 -    if (score > fec_score && score > dvhs_score && score > 6)
 -        return AVPROBE_SCORE_MAX + score - CHECK_COUNT;
 -    else if (dvhs_score > score && dvhs_score > fec_score && dvhs_score > 6)
 -        return AVPROBE_SCORE_MAX + dvhs_score - CHECK_COUNT;
 -    else if (fec_score > 6)
 -        return AVPROBE_SCORE_MAX + fec_score - CHECK_COUNT;
 +    ff_dlog(0, "TS score: %d %d\n", sumscore, maxscore);
 +
 +    if      (sumscore > 6) return AVPROBE_SCORE_MAX   + sumscore - CHECK_COUNT;
 +    else if (maxscore > 6) return AVPROBE_SCORE_MAX/2 + sumscore - CHECK_COUNT;
      else
 -        return AVERROR_INVALIDDATA;
 +        return 0;
  }
  
  /* return the 90kHz PCR and the extension for the 27MHz PCR. return
@@@ -2497,34 -2050,24 +2490,34 @@@ static int parse_pcr(int64_t *ppcr_high
      return 0;
  }
  
 +static void seek_back(AVFormatContext *s, AVIOContext *pb, int64_t pos) {
 +
 +    /* NOTE: We attempt to seek on non-seekable files as well, as the
 +     * probe buffer usually is big enough. Only warn if the seek failed
 +     * on files where the seek should work. */
 +    if (avio_seek(pb, pos, SEEK_SET) < 0)
 +        av_log(s, pb->seekable ? AV_LOG_ERROR : AV_LOG_INFO, "Unable to seek back to the start\n");
 +}
 +
  static int mpegts_read_header(AVFormatContext *s)
  {
      MpegTSContext *ts = s->priv_data;
      AVIOContext *pb   = s->pb;
 -    uint8_t buf[5 * 1024];
 +    uint8_t buf[8 * 1024] = {0};
      int len;
 -    int64_t pos;
 +    int64_t pos, probesize = s->probesize;
 +
 +    if (ffio_ensure_seekback(pb, probesize) < 0)
 +        av_log(s, AV_LOG_WARNING, "Failed to allocate buffers for seekback\n");
  
 -    /* read the first 1024 bytes to get packet size */
 +    /* read the first 8192 bytes to get packet size */
      pos = avio_tell(pb);
      len = avio_read(pb, buf, sizeof(buf));
 -    if (len < 0)
 -        return len;
 -    if (len != sizeof(buf))
 -        return AVERROR_BUG;
 -    ts->raw_packet_size = get_packet_size(buf, sizeof(buf));
 -    if (ts->raw_packet_size <= 0)
 -        return AVERROR_INVALIDDATA;
 +    ts->raw_packet_size = get_packet_size(buf, len);
 +    if (ts->raw_packet_size <= 0) {
 +        av_log(s, AV_LOG_WARNING, "Could not detect TS packet size, defaulting to non-FEC/DVHS\n");
 +        ts->raw_packet_size = TS_PACKET_SIZE;
 +    }
      ts->stream     = s;
      ts->auto_guess = 0;
  
          /* normal demux */
  
          /* first do a scan to get all the services */
 -        if (avio_seek(pb, pos, SEEK_SET) < 0 && pb->seekable)
 -            av_log(s, AV_LOG_ERROR, "Unable to seek back to the start\n");
 +        seek_back(s, pb, pos);
  
          mpegts_open_section_filter(ts, SDT_PID, sdt_cb, ts, 1);
  
          mpegts_open_section_filter(ts, PAT_PID, pat_cb, ts, 1);
  
 -        handle_packets(ts, s->probesize / ts->raw_packet_size);
 +        handle_packets(ts, probesize / ts->raw_packet_size);
          /* if could not find service, enable auto_guess */
  
          ts->auto_guess = 1;
          /* NOTE2: it is only the bitrate of the start of the stream */
          ts->pcr_incr = (pcrs[1] - pcrs[0]) / (packet_count[1] - packet_count[0]);
          ts->cur_pcr  = pcrs[0] - ts->pcr_incr * packet_count[0];
 -        s->bit_rate  = TS_PACKET_SIZE * 8 * 27e6 / ts->pcr_incr;
 +        s->bit_rate  = TS_PACKET_SIZE * 8 * 27000000LL / ts->pcr_incr;
          st->codec->bit_rate = s->bit_rate;
          st->start_time      = ts->cur_pcr;
          av_log(ts->stream, AV_LOG_TRACE, "start=%0.3f pcr=%0.3f incr=%d\n",
                  st->start_time / 1000000.0, pcrs[0] / 27e6, ts->pcr_incr);
      }
  
 -    avio_seek(pb, pos, SEEK_SET);
 +    seek_back(s, pb, pos);
      return 0;
  }
  
@@@ -2661,7 -2205,6 +2654,7 @@@ static int mpegts_read_packet(AVFormatC
      ts->pkt = pkt;
      ret = handle_packets(ts, 0);
      if (ret < 0) {
 +        av_free_packet(ts->pkt);
          /* flush pes data left */
          for (i = 0; i < NB_PID_MAX; i++)
              if (ts->pids[i] && ts->pids[i]->type == MPEGTS_PES) {
@@@ -2698,7 -2241,7 +2691,7 @@@ static int mpegts_read_close(AVFormatCo
      return 0;
  }
  
 -static int64_t mpegts_get_pcr(AVFormatContext *s, int stream_index,
 +static av_unused int64_t mpegts_get_pcr(AVFormatContext *s, int stream_index,
                                int64_t *ppos, int64_t pos_limit)
  {
      MpegTSContext *ts = s->priv_data;
      uint8_t buf[TS_PACKET_SIZE];
      int pcr_l, pcr_pid =
          ((PESContext *)s->streams[stream_index]->priv_data)->pcr_pid;
 -    const int find_next = 1;
 +    int pos47 = ts->pos47_full % ts->raw_packet_size;
      pos =
 -        ((*ppos + ts->raw_packet_size - 1 - ts->pos47) / ts->raw_packet_size) *
 -        ts->raw_packet_size + ts->pos47;
 -    if (find_next) {
 -        for (;;) {
 -            avio_seek(s->pb, pos, SEEK_SET);
 -            if (avio_read(s->pb, buf, TS_PACKET_SIZE) != TS_PACKET_SIZE)
 +        ((*ppos + ts->raw_packet_size - 1 - pos47) / ts->raw_packet_size) *
 +        ts->raw_packet_size + pos47;
 +    while(pos < pos_limit) {
 +        if (avio_seek(s->pb, pos, SEEK_SET) < 0)
 +            return AV_NOPTS_VALUE;
 +        if (avio_read(s->pb, buf, TS_PACKET_SIZE) != TS_PACKET_SIZE)
 +            return AV_NOPTS_VALUE;
 +        if (buf[0] != 0x47) {
 +            avio_seek(s->pb, -TS_PACKET_SIZE, SEEK_CUR);
 +            if (mpegts_resync(s) < 0)
                  return AV_NOPTS_VALUE;
 -            if ((pcr_pid < 0 || (AV_RB16(buf + 1) & 0x1fff) == pcr_pid) &&
 -                parse_pcr(&timestamp, &pcr_l, buf) == 0) {
 -                break;
 -            }
 -            pos += ts->raw_packet_size;
 +            pos = avio_tell(s->pb);
 +            continue;
          }
 -    } else {
 -        for (;;) {
 -            pos -= ts->raw_packet_size;
 -            if (pos < 0)
 -                return AV_NOPTS_VALUE;
 -            avio_seek(s->pb, pos, SEEK_SET);
 -            if (avio_read(s->pb, buf, TS_PACKET_SIZE) != TS_PACKET_SIZE)
 -                return AV_NOPTS_VALUE;
 -            if ((pcr_pid < 0 || (AV_RB16(buf + 1) & 0x1fff) == pcr_pid) &&
 -                parse_pcr(&timestamp, &pcr_l, buf) == 0) {
 -                break;
 -            }
 +        if ((pcr_pid < 0 || (AV_RB16(buf + 1) & 0x1fff) == pcr_pid) &&
 +            parse_pcr(&timestamp, &pcr_l, buf) == 0) {
 +            *ppos = pos;
 +            return timestamp;
          }
 +        pos += ts->raw_packet_size;
      }
 -    *ppos = pos;
  
 -    return timestamp;
 +    return AV_NOPTS_VALUE;
  }
  
 -static int read_seek(AVFormatContext *s, int stream_index, int64_t target_ts, int flags)
 +static int64_t mpegts_get_dts(AVFormatContext *s, int stream_index,
 +                              int64_t *ppos, int64_t pos_limit)
  {
      MpegTSContext *ts = s->priv_data;
 -    uint8_t buf[TS_PACKET_SIZE];
      int64_t pos;
 -    int ret;
 -
 -    ret = ff_seek_frame_binary(s, stream_index, target_ts, flags);
 -    if (ret < 0)
 -        return ret;
 -
 -    pos = avio_tell(s->pb);
 -
 -    for (;;) {
 -        avio_seek(s->pb, pos, SEEK_SET);
 -        ret = avio_read(s->pb, buf, TS_PACKET_SIZE);
 +    int pos47 = ts->pos47_full % ts->raw_packet_size;
 +    pos = ((*ppos  + ts->raw_packet_size - 1 - pos47) / ts->raw_packet_size) * ts->raw_packet_size + pos47;
 +    ff_read_frame_flush(s);
 +    if (avio_seek(s->pb, pos, SEEK_SET) < 0)
 +        return AV_NOPTS_VALUE;
 +    while(pos < pos_limit) {
 +        int ret;
 +        AVPacket pkt;
 +        av_init_packet(&pkt);
 +        ret = av_read_frame(s, &pkt);
          if (ret < 0)
 -            return ret;
 -        if (ret != TS_PACKET_SIZE)
 -            return AVERROR_EOF;
 -        // pid = AV_RB16(buf + 1) & 0x1fff;
 -        if (buf[1] & 0x40)
 -            break;
 -        pos += ts->raw_packet_size;
 +            return AV_NOPTS_VALUE;
 +        av_free_packet(&pkt);
 +        if (pkt.dts != AV_NOPTS_VALUE && pkt.pos >= 0) {
 +            ff_reduce_index(s, pkt.stream_index);
 +            av_add_index_entry(s->streams[pkt.stream_index], pkt.pos, pkt.dts, 0, 0, AVINDEX_KEYFRAME /* FIXME keyframe? */);
 +            if (pkt.stream_index == stream_index && pkt.pos >= *ppos) {
 +                *ppos = pkt.pos;
 +                return pkt.dts;
 +            }
 +        }
 +        pos = pkt.pos;
      }
 -    avio_seek(s->pb, pos, SEEK_SET);
  
 -    return 0;
 +    return AV_NOPTS_VALUE;
  }
  
  /**************************************************************/
  /* parsing functions - called from other demuxers such as RTP */
  
 -MpegTSContext *ff_mpegts_parse_open(AVFormatContext *s)
 +MpegTSContext *avpriv_mpegts_parse_open(AVFormatContext *s)
  {
      MpegTSContext *ts;
  
      ts->raw_packet_size = TS_PACKET_SIZE;
      ts->stream = s;
      ts->auto_guess = 1;
 +    mpegts_open_section_filter(ts, SDT_PID, sdt_cb, ts, 1);
 +    mpegts_open_section_filter(ts, PAT_PID, pat_cb, ts, 1);
 +
      return ts;
  }
  
  /* return the consumed length if a packet was output, or -1 if no
   * packet is output */
 -int ff_mpegts_parse_packet(MpegTSContext *ts, AVPacket *pkt,
 -                           const uint8_t *buf, int len)
 +int avpriv_mpegts_parse_packet(MpegTSContext *ts, AVPacket *pkt,
 +                               const uint8_t *buf, int len)
  {
      int len1;
  
      len1 = len;
      ts->pkt = pkt;
 -    ts->stop_parse = 0;
      for (;;) {
 -        if (ts->stop_parse > 0)
 -            break;
 +        ts->stop_parse = 0;
          if (len < TS_PACKET_SIZE)
              return AVERROR_INVALIDDATA;
          if (buf[0] != 0x47) {
              handle_packet(ts, buf);
              buf += TS_PACKET_SIZE;
              len -= TS_PACKET_SIZE;
 +            if (ts->stop_parse == 1)
 +                break;
          }
      }
      return len1 - len;
  }
  
 -void ff_mpegts_parse_close(MpegTSContext *ts)
 +void avpriv_mpegts_parse_close(MpegTSContext *ts)
  {
      mpegts_free(ts);
      av_free(ts);
@@@ -2826,7 -2371,8 +2819,7 @@@ AVInputFormat ff_mpegts_demuxer = 
      .read_header    = mpegts_read_header,
      .read_packet    = mpegts_read_packet,
      .read_close     = mpegts_read_close,
 -    .read_seek      = read_seek,
 -    .read_timestamp = mpegts_get_pcr,
 +    .read_timestamp = mpegts_get_dts,
      .flags          = AVFMT_SHOW_IDS | AVFMT_TS_DISCONT,
      .priv_class     = &mpegts_class,
  };
@@@ -2838,7 -2384,8 +2831,7 @@@ AVInputFormat ff_mpegtsraw_demuxer = 
      .read_header    = mpegts_read_header,
      .read_packet    = mpegts_raw_read_packet,
      .read_close     = mpegts_read_close,
 -    .read_seek      = read_seek,
 -    .read_timestamp = mpegts_get_pcr,
 +    .read_timestamp = mpegts_get_dts,
      .flags          = AVFMT_SHOW_IDS | AVFMT_TS_DISCONT,
      .priv_class     = &mpegtsraw_class,
  };