Merge commit '9dcf2397219ca796f0fafce2a703770d6fd09920'
authorMichael Niedermayer <michaelni@gmx.at>
Sun, 26 Oct 2014 01:06:40 +0000 (02:06 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Sun, 26 Oct 2014 01:06:40 +0000 (02:06 +0100)
* commit '9dcf2397219ca796f0fafce2a703770d6fd09920':
  lavf: Check the return value of strftime

Conflicts:
libavformat/wtvdec.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
libavformat/mov.c
libavformat/mxfdec.c
libavformat/wtvdec.c

diff --combined libavformat/mov.c
@@@ -6,20 -6,20 +6,20 @@@
   * first version by Francois Revol <revol@free.fr>
   * seek function by Gael Chardon <gael.dev@4now.net>
   *
 - * 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/attributes.h"
  #include "libavutil/channel_layout.h"
 +#include "libavutil/display.h"
  #include "libavutil/intreadwrite.h"
  #include "libavutil/intfloat.h"
  #include "libavutil/mathematics.h"
  #include "libavutil/avstring.h"
  #include "libavutil/dict.h"
 +#include "libavutil/opt.h"
 +#include "libavutil/timecode.h"
  #include "libavcodec/ac3tab.h"
  #include "avformat.h"
  #include "internal.h"
@@@ -68,7 -65,6 +68,7 @@@ typedef struct MOVParseTableEntry 
  } MOVParseTableEntry;
  
  static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom);
 +static int mov_read_mfra(MOVContext *c, AVIOContext *f);
  
  static int mov_metadata_track_or_disc_number(MOVContext *c, AVIOContext *pb,
                                               unsigned len, const char *key)
  static int mov_metadata_int8_bypass_padding(MOVContext *c, AVIOContext *pb,
                                              unsigned len, const char *key)
  {
 -    char buf[16];
 -
      /* bypass padding bytes */
      avio_r8(pb);
      avio_r8(pb);
      avio_r8(pb);
  
 -    snprintf(buf, sizeof(buf), "%d", avio_r8(pb));
      c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
 -    av_dict_set(&c->fc->metadata, key, buf, 0);
 +    av_dict_set_int(&c->fc->metadata, key, avio_r8(pb), 0);
  
      return 0;
  }
  static int mov_metadata_int8_no_padding(MOVContext *c, AVIOContext *pb,
                                          unsigned len, const char *key)
  {
 -    char buf[16];
 -
 -    snprintf(buf, sizeof(buf), "%d", avio_r8(pb));
      c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
 -    av_dict_set(&c->fc->metadata, key, buf, 0);
 +    av_dict_set_int(&c->fc->metadata, key, avio_r8(pb), 0);
  
      return 0;
  }
@@@ -117,14 -119,16 +117,14 @@@ static int mov_metadata_gnre(MOVContex
                               unsigned len, const char *key)
  {
      short genre;
 -    char buf[20];
  
      avio_r8(pb); // unknown
  
      genre = avio_r8(pb);
      if (genre < 1 || genre > ID3v1_GENRE_MAX)
          return 0;
 -    snprintf(buf, sizeof(buf), "%s", ff_id3v1_genre_str[genre-1]);
      c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
 -    av_dict_set(&c->fc->metadata, key, buf, 0);
 +    av_dict_set(&c->fc->metadata, key, ff_id3v1_genre_str[genre-1], 0);
  
      return 0;
  }
@@@ -159,7 -163,7 +159,7 @@@ static int mov_read_mac_string(MOVConte
          uint8_t t, c = avio_r8(pb);
          if (c < 0x80 && p < end)
              *p++ = c;
 -        else
 +        else if (p < end)
              PUT_UTF8(mac_to_unicode[c-0x80], t, if (p < end) *p++ = t;);
      }
      *p = 0;
@@@ -208,17 -212,6 +208,17 @@@ static int mov_read_covr(MOVContext *c
      return 0;
  }
  
 +static int mov_metadata_raw(MOVContext *c, AVIOContext *pb,
 +                            unsigned len, const char *key)
 +{
 +    char *value = av_malloc(len + 1);
 +    if (!value)
 +        return AVERROR(ENOMEM);
 +    avio_read(pb, value, len);
 +    value[len] = 0;
 +    return av_dict_set(&c->fc->metadata, key, value, AV_DICT_DONT_STRDUP_VAL);
 +}
 +
  static int mov_metadata_loci(MOVContext *c, AVIOContext *pb, unsigned len)
  {
      char language[4] = { 0 };
@@@ -262,11 -255,10 +262,11 @@@ static int mov_read_udta_string(MOVCont
  #ifdef MOV_EXPORT_ALL_METADATA
      char tmp_key[5];
  #endif
 -    char str[1024], key2[16], language[4] = {0};
 +    char key2[16], language[4] = {0};
 +    char *str = NULL;
      const char *key = NULL;
      uint16_t langcode = 0;
 -    uint32_t data_type = 0, str_size;
 +    uint32_t data_type = 0, str_size, str_size_alloc;
      int (*parse)(MOVContext*, AVIOContext*, unsigned, const char*) = NULL;
  
      switch (atom.type) {
      case MKTAG(0xa9,'A','R','T'): key = "artist";    break;
      case MKTAG( 'a','A','R','T'): key = "album_artist";    break;
      case MKTAG(0xa9,'w','r','t'): key = "composer";  break;
 +    case MKTAG( 'c','p','i','l'): key = "compilation";
 +        parse = mov_metadata_int8_no_padding; break;
      case MKTAG( 'c','p','r','t'):
      case MKTAG(0xa9,'c','p','y'): key = "copyright"; break;
 +    case MKTAG(0xa9,'g','r','p'): key = "grouping"; break;
 +    case MKTAG(0xa9,'l','y','r'): key = "lyrics"; break;
      case MKTAG(0xa9,'c','m','t'):
      case MKTAG(0xa9,'i','n','f'): key = "comment";   break;
      case MKTAG(0xa9,'a','l','b'): key = "album";     break;
      case MKTAG(0xa9,'t','o','o'):
      case MKTAG(0xa9,'s','w','r'): key = "encoder";   break;
      case MKTAG(0xa9,'e','n','c'): key = "encoder";   break;
 +    case MKTAG(0xa9,'m','a','k'): key = "make";      break;
 +    case MKTAG(0xa9,'m','o','d'): key = "model";     break;
      case MKTAG(0xa9,'x','y','z'): key = "location";  break;
      case MKTAG( 'd','e','s','c'): key = "description";break;
      case MKTAG( 'l','d','e','s'): key = "synopsis";  break;
          parse = mov_metadata_int8_no_padding; break;
      case MKTAG( 'p','g','a','p'): key = "gapless_playback";
          parse = mov_metadata_int8_no_padding; break;
 +    case MKTAG( '@','P','R','M'):
 +        return mov_metadata_raw(c, pb, atom.size, "premiere_version");
 +    case MKTAG( '@','P','R','Q'):
 +        return mov_metadata_raw(c, pb, atom.size, "quicktime_version");
      case MKTAG( 'l','o','c','i'):
          return mov_metadata_loci(c, pb, atom.size);
 +    case MKTAG( 'X','M','P','_'):
 +        return mov_metadata_raw(c, pb, atom.size, "xmp");
      }
  
      if (c->itunes_metadata && atom.size > 8) {
                  int ret = mov_read_covr(c, pb, data_type, str_size);
                  if (ret < 0) {
                      av_log(c->fc, AV_LOG_ERROR, "Error parsing cover art.\n");
 -                    return ret;
                  }
 +                return ret;
              }
          } else return 0;
      } else if (atom.size > 4 && key && !c->itunes_metadata) {
      if (atom.size < 0)
          return AVERROR_INVALIDDATA;
  
 -    str_size = FFMIN3(sizeof(str)-1, str_size, atom.size);
 +    str_size_alloc = str_size << 1; // worst-case requirement for output string in case of utf8 coded input
 +    str = av_malloc(str_size_alloc);
 +    if (!str)
 +        return AVERROR(ENOMEM);
  
      if (parse)
          parse(c, pb, str_size, key);
      else {
          if (data_type == 3 || (data_type == 0 && (langcode < 0x400 || langcode == 0x7fff))) { // MAC Encoded
 -            mov_read_mac_string(c, pb, str_size, str, sizeof(str));
 +            mov_read_mac_string(c, pb, str_size, str, str_size_alloc);
          } else {
 -            avio_read(pb, str, str_size);
 +            int ret = avio_read(pb, str, str_size);
 +            if (ret != str_size) {
 +                av_freep(&str);
 +                return ret < 0 ? ret : AVERROR_INVALIDDATA;
 +            }
              str[str_size] = 0;
          }
          c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
      }
      av_dlog(c->fc, "lang \"%3s\" ", language);
      av_dlog(c->fc, "tag \"%s\" value \"%s\" atom \"%.4s\" %d %"PRId64"\n",
 -            key, str, (char*)&atom.type, str_size, atom.size);
 +            key, str, (char*)&atom.type, str_size_alloc, atom.size);
 +
 +    av_freep(&str);
  
      return 0;
  }
@@@ -444,7 -415,6 +444,7 @@@ static int mov_read_dref(MOVContext *c
          entries >= UINT_MAX / sizeof(*sc->drefs))
          return AVERROR_INVALIDDATA;
      av_free(sc->drefs);
 +    sc->drefs_count = 0;
      sc->drefs = av_mallocz(entries * sizeof(*sc->drefs));
      if (!sc->drefs)
          return AVERROR(ENOMEM);
              avio_skip(pb, 16);
  
              for (type = 0; type != -1 && avio_tell(pb) < next; ) {
 -                if (pb->eof_reached)
 +                if(avio_feof(pb))
                      return AVERROR_EOF;
                  type = avio_rb16(pb);
                  len = avio_rb16(pb);
                      dref->dir = av_malloc(len+1);
                      if (!dref->dir)
                          return AVERROR(ENOMEM);
 -                    avio_read(pb, dref->dir, len);
 +                    if (avio_read(pb, dref->dir, len) != len)
 +                        return AVERROR_INVALIDDATA;
                      dref->dir[len] = 0;
                      for (j = 0; j < len; j++)
                          if (dref->dir[j] == ':')
@@@ -542,8 -511,6 +542,8 @@@ static int mov_read_hdlr(MOVContext *c
      AVStream *st;
      uint32_t type;
      uint32_t av_unused ctype;
 +    int title_size;
 +    char *title_str;
  
      if (c->fc->nb_streams < 1) // meta before first trak
          return 0;
      avio_rb32(pb); /* component flags */
      avio_rb32(pb); /* component flags mask */
  
 +    title_size = atom.size - 24;
 +    if (title_size > 0) {
 +        title_str = av_malloc(title_size + 1); /* Add null terminator */
 +        if (!title_str)
 +            return AVERROR(ENOMEM);
 +        avio_read(pb, title_str, title_size);
 +        title_str[title_size] = 0;
 +        if (title_str[0])
 +            av_dict_set(&st->metadata, "handler_name", title_str +
 +                        (!c->isom && title_str[0] == title_size - 1), 0);
 +        av_freep(&title_str);
 +    }
 +
      return 0;
  }
  
@@@ -679,9 -633,6 +679,9 @@@ static int mov_read_chan(MOVContext *c
      if (atom.size < 16)
          return 0;
  
 +    /* skip version and flags */
 +    avio_skip(pb, 4);
 +
      ff_mov_read_chan(c->fc, pb, st, atom.size - 4);
  
      return 0;
@@@ -695,9 -646,7 +695,9 @@@ static int mov_read_wfex(MOVContext *c
          return 0;
      st = c->fc->streams[c->fc->nb_streams-1];
  
 -    ff_get_wav_header(pb, st->codec, atom.size);
 +    if (ff_get_wav_header(pb, st->codec, atom.size) < 0) {
 +        av_log(c->fc, AV_LOG_WARNING, "get_wav_header failed\n");
 +    }
  
      return 0;
  }
@@@ -739,6 -688,7 +739,6 @@@ static int mov_read_ftyp(MOVContext *c
  {
      uint32_t minor_ver;
      int comp_brand_size;
 -    char minor_ver_str[11]; /* 32 bit integer -> 10 digits + null */
      char* comp_brands_str;
      uint8_t type[5] = {0};
  
      av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type);
      av_dict_set(&c->fc->metadata, "major_brand", type, 0);
      minor_ver = avio_rb32(pb); /* minor version */
 -    snprintf(minor_ver_str, sizeof(minor_ver_str), "%"PRIu32"", minor_ver);
 -    av_dict_set(&c->fc->metadata, "minor_version", minor_ver_str, 0);
 +    av_dict_set_int(&c->fc->metadata, "minor_version", minor_ver, 0);
  
      comp_brand_size = atom.size - 8;
      if (comp_brand_size < 0)
@@@ -769,12 -720,6 +769,12 @@@ static int mov_read_moov(MOVContext *c
  {
      int ret;
  
 +    if (c->found_moov) {
 +        av_log(c->fc, AV_LOG_WARNING, "Found duplicated MOOV Atom. Skipped it\n");
 +        avio_skip(pb, atom.size);
 +        return 0;
 +    }
 +
      if ((ret = mov_read_default(c, pb, atom)) < 0)
          return ret;
      /* we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat' */
  
  static int mov_read_moof(MOVContext *c, AVIOContext *pb, MOVAtom atom)
  {
 +    if (!c->has_looked_for_mfra && c->use_mfra_for > 0) {
 +        c->has_looked_for_mfra = 1;
 +        if (pb->seekable) {
 +            int ret;
 +            av_log(c->fc, AV_LOG_VERBOSE, "stream has moof boxes, will look "
 +                    "for a mfra\n");
 +            if ((ret = mov_read_mfra(c, pb)) < 0) {
 +                av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but failed to "
 +                        "read the mfra (may be a live ismv)\n");
 +            }
 +        } else {
 +            av_log(c->fc, AV_LOG_VERBOSE, "found a moof box but stream is not "
 +                    "seekable, can not look for mfra\n");
 +        }
 +    }
      c->fragment.moof_offset = c->fragment.implicit_offset = avio_tell(pb) - 8;
      av_dlog(c->fc, "moof offset %"PRIx64"\n", c->fragment.moof_offset);
      return mov_read_default(c, pb, atom);
  }
  
 -static void mov_metadata_creation_time(AVDictionary **metadata, time_t time)
 +static void mov_metadata_creation_time(AVDictionary **metadata, int64_t time)
  {
      char buffer[32];
      if (time) {
          struct tm *ptm;
 -        time -= 2082844800;  /* seconds between 1904-01-01 and Epoch */
 -        ptm = gmtime(&time);
 +        time_t timet;
 +        if(time >= 2082844800)
 +            time -= 2082844800;  /* seconds between 1904-01-01 and Epoch */
 +        timet = time;
 +        ptm = gmtime(&timet);
          if (!ptm) return;
-         strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", ptm);
-         av_dict_set(metadata, "creation_time", buffer, 0);
+         if (strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", ptm))
+             av_dict_set(metadata, "creation_time", buffer, 0);
      }
  }
  
@@@ -828,7 -755,7 +828,7 @@@ static int mov_read_mdhd(MOVContext *c
      int version;
      char language[4] = {0};
      unsigned lang;
 -    time_t creation_time;
 +    int64_t creation_time;
  
      if (c->fc->nb_streams < 1)
          return 0;
  
  static int mov_read_mvhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
  {
 -    time_t creation_time;
 +    int64_t creation_time;
      int version = avio_r8(pb); /* version */
      avio_rb24(pb); /* flags */
  
      av_dlog(c->fc, "time scale = %i\n", c->time_scale);
  
      c->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */
 +    // set the AVCodecContext duration because the duration of individual tracks
 +    // may be inaccurate
 +    if (c->time_scale > 0 && !c->trex_data)
 +        c->fc->duration = av_rescale(c->duration, AV_TIME_BASE, c->time_scale);
      avio_rb32(pb); /* preferred scale */
  
      avio_rb16(pb); /* preferred volume */
      avio_rb32(pb); /* selection duration */
      avio_rb32(pb); /* current time */
      avio_rb32(pb); /* next track ID */
 -
 -    return 0;
 -}
 -
 -static int mov_read_smi(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 -{
 -    AVStream *st;
 -
 -    if (c->fc->nb_streams < 1)
 -        return 0;
 -    st = c->fc->streams[c->fc->nb_streams-1];
 -
 -    if ((uint64_t)atom.size > (1<<30))
 -        return AVERROR_INVALIDDATA;
 -
 -    // currently SVQ3 decoder expect full STSD header - so let's fake it
 -    // this should be fixed and just SMI header should be passed
 -    av_free(st->codec->extradata);
 -    st->codec->extradata = av_mallocz(atom.size + 0x5a + FF_INPUT_BUFFER_PADDING_SIZE);
 -    if (!st->codec->extradata)
 -        return AVERROR(ENOMEM);
 -    st->codec->extradata_size = 0x5a + atom.size;
 -    memcpy(st->codec->extradata, "SVQ3", 4); // fake
 -    avio_read(pb, st->codec->extradata + 0x5a, atom.size);
 -    av_dlog(c->fc, "Reading SMI %"PRId64"  %s\n", atom.size, st->codec->extradata + 0x5a);
      return 0;
  }
  
@@@ -916,7 -864,7 +916,7 @@@ static int mov_read_enda(MOVContext *c
          return 0;
      st = c->fc->streams[c->fc->nb_streams-1];
  
 -    little_endian = avio_rb16(pb);
 +    little_endian = avio_rb16(pb) & 0xFF;
      av_dlog(c->fc, "enda %d\n", little_endian);
      if (little_endian == 1) {
          switch (st->codec->codec_id) {
@@@ -961,12 -909,12 +961,12 @@@ static int mov_read_colr(MOVContext *c
      color_trc = avio_rb16(pb);
      color_matrix = avio_rb16(pb);
  
 -    av_dlog(c->fc, "%s: pri %"PRIu16" trc %"PRIu16" matrix %"PRIu16"",
 +    av_dlog(c->fc, "%s: pri %d trc %d matrix %d",
              color_parameter_type, color_primaries, color_trc, color_matrix);
  
      if (c->isom) {
          uint8_t color_range = avio_r8(pb) >> 7;
 -        av_dlog(c->fc, " full %"PRIu8"", color_range)
 +        av_dlog(c->fc, " full %"PRIu8"", color_range);
          if (color_range)
              st->codec->color_range = AVCOL_RANGE_JPEG;
          else
          case 7: st->codec->colorspace = AVCOL_SPC_SMPTE240M; break;
          }
      }
 -    av_dlog(c->fc, "\n")
 +    av_dlog(c->fc, "\n");
  
      return 0;
  }
@@@ -1043,8 -991,7 +1043,8 @@@ static int mov_read_fiel(MOVContext *c
  }
  
  /* FIXME modify qdm2/svq3/h264 decoders to take full atom as extradata */
 -static int mov_read_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 +static int mov_read_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
 +                              enum AVCodecID codec_id)
  {
      AVStream *st;
      uint64_t size;
      if (c->fc->nb_streams < 1) // will happen with jp2 files
          return 0;
      st= c->fc->streams[c->fc->nb_streams-1];
 +
 +    if (st->codec->codec_id != codec_id)
 +        return 0; /* unexpected codec_id - don't mess with extradata */
 +
      size= (uint64_t)st->codec->extradata_size + atom.size + 8 + FF_INPUT_BUFFER_PADDING_SIZE;
      if (size > INT_MAX || (uint64_t)atom.size > INT_MAX)
          return AVERROR_INVALIDDATA;
      st->codec->extradata_size= size - FF_INPUT_BUFFER_PADDING_SIZE;
      AV_WB32(       buf    , atom.size + 8);
      AV_WL32(       buf + 4, atom.type);
 -    avio_read(pb, buf + 8, atom.size);
 +    err = avio_read(pb, buf + 8, atom.size);
 +    if (err < 0) {
 +        return err;
 +    } else if (err < atom.size) {
 +        av_log(c->fc, AV_LOG_WARNING, "truncated extradata\n");
 +        st->codec->extradata_size -= atom.size - err;
 +    }
 +    memset(buf + 8 + err, 0, FF_INPUT_BUFFER_PADDING_SIZE);
      return 0;
  }
  
 +/* wrapper functions for reading ALAC/AVS/MJPEG/MJPEG2000 extradata atoms only for those codecs */
 +static int mov_read_alac(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 +{
 +    return mov_read_extradata(c, pb, atom, AV_CODEC_ID_ALAC);
 +}
 +
 +static int mov_read_avss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 +{
 +    return mov_read_extradata(c, pb, atom, AV_CODEC_ID_AVS);
 +}
 +
 +static int mov_read_jp2h(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 +{
 +    return mov_read_extradata(c, pb, atom, AV_CODEC_ID_JPEG2000);
 +}
 +
 +static int mov_read_avid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 +{
 +    int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_AVUI);
 +    if(ret == 0)
 +        ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_DNXHD);
 +    return ret;
 +}
 +
 +static int mov_read_targa_y216(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 +{
 +    int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_TARGA_Y216);
 +
 +    if (!ret && c->fc->nb_streams >= 1) {
 +        AVCodecContext *avctx = c->fc->streams[c->fc->nb_streams-1]->codec;
 +        if (avctx->extradata_size >= 40) {
 +            avctx->height = AV_RB16(&avctx->extradata[36]);
 +            avctx->width  = AV_RB16(&avctx->extradata[38]);
 +        }
 +    }
 +    return ret;
 +}
 +
 +static int mov_read_ares(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 +{
 +    if (c->fc->nb_streams >= 1) {
 +        AVCodecContext *codec = c->fc->streams[c->fc->nb_streams-1]->codec;
 +        if (codec->codec_tag == MKTAG('A', 'V', 'i', 'n') &&
 +            codec->codec_id == AV_CODEC_ID_H264 &&
 +            atom.size > 11) {
 +            avio_skip(pb, 10);
 +            /* For AVID AVCI50, force width of 1440 to be able to select the correct SPS and PPS */
 +            if (avio_rb16(pb) == 0xd4d)
 +                codec->width = 1440;
 +            return 0;
 +        }
 +    }
 +
 +    return mov_read_avid(c, pb, atom);
 +}
 +
 +static int mov_read_svq3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 +{
 +    return mov_read_extradata(c, pb, atom, AV_CODEC_ID_SVQ3);
 +}
 +
  static int mov_read_wave(MOVContext *c, AVIOContext *pb, MOVAtom atom)
  {
      AVStream *st;
      if ((uint64_t)atom.size > (1<<30))
          return AVERROR_INVALIDDATA;
  
 -    if (st->codec->codec_id == AV_CODEC_ID_QDM2 || st->codec->codec_id == AV_CODEC_ID_QDMC) {
 +    if (st->codec->codec_id == AV_CODEC_ID_QDM2 ||
 +        st->codec->codec_id == AV_CODEC_ID_QDMC ||
 +        st->codec->codec_id == AV_CODEC_ID_SPEEX) {
          // pass all frma atom to codec, needed at least for QDMC and QDM2
          av_free(st->codec->extradata);
 -        st->codec->extradata = av_mallocz(atom.size + FF_INPUT_BUFFER_PADDING_SIZE);
 -        if (!st->codec->extradata)
 +        if (ff_get_extradata(st->codec, pb, atom.size) < 0)
              return AVERROR(ENOMEM);
 -        st->codec->extradata_size = atom.size;
 -        avio_read(pb, st->codec->extradata, atom.size);
      } else if (atom.size > 8) { /* to read frma, esds atoms */
          int ret;
          if ((ret = mov_read_default(c, pb, atom)) < 0)
@@@ -1192,14 -1068,12 +1192,14 @@@ static int mov_read_glbl(MOVContext *c
          if (type == MKTAG('f','i','e','l') && size == atom.size)
              return mov_read_default(c, pb, atom);
      }
 +    if (st->codec->extradata_size > 1 && st->codec->extradata) {
 +        av_log(c, AV_LOG_WARNING, "ignoring multiple glbl\n");
 +        return 0;
 +    }
      av_free(st->codec->extradata);
 -    st->codec->extradata = av_mallocz(atom.size + FF_INPUT_BUFFER_PADDING_SIZE);
 -    if (!st->codec->extradata)
 +    if (ff_get_extradata(st->codec, pb, atom.size) < 0)
          return AVERROR(ENOMEM);
 -    st->codec->extradata_size = atom.size;
 -    avio_read(pb, st->codec->extradata, atom.size);
 +
      return 0;
  }
  
@@@ -1207,7 -1081,6 +1207,7 @@@ static int mov_read_dvc1(MOVContext *c
  {
      AVStream *st;
      uint8_t profile_level;
 +    int ret;
  
      if (c->fc->nb_streams < 1)
          return 0;
      if ((profile_level & 0xf0) != 0xc0)
          return 0;
  
 -    av_free(st->codec->extradata);
 -    st->codec->extradata = av_mallocz(atom.size - 7 + FF_INPUT_BUFFER_PADDING_SIZE);
 -    if (!st->codec->extradata)
 -        return AVERROR(ENOMEM);
 -    st->codec->extradata_size = atom.size - 7;
      avio_seek(pb, 6, SEEK_CUR);
 -    avio_read(pb, st->codec->extradata, st->codec->extradata_size);
 +    av_free(st->codec->extradata);
 +    if ((ret = ff_get_extradata(st->codec, pb, atom.size - 7)) < 0)
 +        return ret;
 +
      return 0;
  }
  
@@@ -1246,10 -1121,13 +1246,10 @@@ static int mov_read_strf(MOVContext *c
      if ((uint64_t)atom.size > (1<<30))
          return AVERROR_INVALIDDATA;
  
 +    avio_skip(pb, 40);
      av_free(st->codec->extradata);
 -    st->codec->extradata = av_mallocz(atom.size - 40 + FF_INPUT_BUFFER_PADDING_SIZE);
 -    if (!st->codec->extradata)
 +    if (ff_get_extradata(st->codec, pb, atom.size - 40) < 0)
          return AVERROR(ENOMEM);
 -    st->codec->extradata_size = atom.size - 40;
 -    avio_skip(pb, 40);
 -    avio_read(pb, st->codec->extradata, atom.size - 40);
      return 0;
  }
  
@@@ -1329,9 -1207,7 +1329,9 @@@ static int mov_codec_id(AVStream *st, u
              id = ff_codec_get_id(ff_codec_bmp_tags, format);
          if (id > 0)
              st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
 -        else if (st->codec->codec_type == AVMEDIA_TYPE_DATA) {
 +        else if (st->codec->codec_type == AVMEDIA_TYPE_DATA ||
 +                    (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE &&
 +                    st->codec->codec_id == AV_CODEC_ID_NONE)) {
              id = ff_codec_get_id(ff_codec_movsubtitle_tags, format);
              if (id > 0)
                  st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
@@@ -1376,11 -1252,8 +1376,11 @@@ static void mov_parse_stsd_video(MOVCon
          av_dict_set(&st->metadata, "encoder", codec_name, 0);
  
      /* codec_tag YV12 triggers an UV swap in rawdec.c */
 -    if (!memcmp(codec_name, "Planar Y'CbCr 8-bit 4:2:0", 25))
 +    if (!memcmp(codec_name, "Planar Y'CbCr 8-bit 4:2:0", 25)) {
          st->codec->codec_tag = MKTAG('I', '4', '2', '0');
 +        st->codec->width &= ~1;
 +        st->codec->height &= ~1;
 +    }
      /* Flash Media Server uses tag H263 with Sorenson Spark */
      if (st->codec->codec_tag == MKTAG('H','2','6','3') &&
          !memcmp(codec_name, "Sorenson H263", 13))
      /* figure out the palette situation */
      color_depth     = st->codec->bits_per_coded_sample & 0x1F;
      color_greyscale = st->codec->bits_per_coded_sample & 0x20;
 +    /* Do not create a greyscale palette for cinepak */
 +    if (color_greyscale && st->codec->codec_id == AV_CODEC_ID_CINEPAK)
 +        return;
  
      /* if the depth is 2, 4, or 8 bpp, file is palettized */
      if ((color_depth == 2) || (color_depth == 4) || (color_depth == 8)) {
          /* for palette traversal */
          unsigned int color_start, color_count, color_end;
 -        unsigned char r, g, b;
 +        unsigned char a, r, g, b;
  
          if (color_greyscale) {
              int color_index, color_dec;
              color_dec   = 256 / (color_count - 1);
              for (j = 0; j < color_count; j++) {
                  r = g = b = color_index;
 -                sc->palette[j] = (r << 16) | (g << 8) | (b);
 +                sc->palette[j] = (0xFFU << 24) | (r << 16) | (g << 8) | (b);
                  color_index -= color_dec;
                  if (color_index < 0)
                      color_index = 0;
                  r = color_table[j * 3 + 0];
                  g = color_table[j * 3 + 1];
                  b = color_table[j * 3 + 2];
 -                sc->palette[j] = (r << 16) | (g << 8) | (b);
 +                sc->palette[j] = (0xFFU << 24) | (r << 16) | (g << 8) | (b);
              }
          } else {
              /* load the palette from the file */
              color_end   = avio_rb16(pb);
              if ((color_start <= 255) && (color_end <= 255)) {
                  for (j = color_start; j <= color_end; j++) {
 -                    /* each R, G, or B component is 16 bits;
 -                     * only use the top 8 bits; skip alpha bytes
 -                     * up front */
 -                    avio_r8(pb);
 +                    /* each A, R, G, or B component is 16 bits;
 +                        * only use the top 8 bits */
 +                    a = avio_r8(pb);
                      avio_r8(pb);
                      r = avio_r8(pb);
                      avio_r8(pb);
                      avio_r8(pb);
                      b = avio_r8(pb);
                      avio_r8(pb);
 -                    sc->palette[j] = (r << 16) | (g << 8) | (b);
 +                    sc->palette[j] = (a << 24 ) | (r << 16) | (g << 8) | (b);
                  }
              }
          }
@@@ -1464,7 -1335,6 +1464,7 @@@ static void mov_parse_stsd_audio(MOVCon
  {
      int bits_per_sample, flags;
      uint16_t version = avio_rb16(pb);
 +    AVDictionaryEntry *compatible_brands = av_dict_get(c->fc->metadata, "compatible_brands", NULL, AV_DICT_MATCH_CASE);
  
      avio_rb16(pb); /* revision level */
      avio_rb32(pb); /* vendor */
  
      // Read QT version 1 fields. In version 0 these do not exist.
      av_dlog(c->fc, "version =%d, isom =%d\n", version, c->isom);
 -    if (!c->isom) {
 +    if (!c->isom ||
 +        (compatible_brands && strstr(compatible_brands->value, "qt  "))) {
 +
          if (version == 1) {
              sc->samples_per_frame = avio_rb32(pb);
              avio_rb32(pb); /* bytes per packet */
              st->codec->codec_id =
                  st->codec->codec_id == AV_CODEC_ID_PCM_S16BE ?
                  AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE;
 +        else if (st->codec->bits_per_coded_sample == 32)
 +             st->codec->codec_id =
 +                st->codec->codec_id == AV_CODEC_ID_PCM_S16BE ?
 +                AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
          break;
      /* set values for old format before stsd version 1 appeared */
      case AV_CODEC_ID_MACE3:
@@@ -1622,38 -1486,11 +1622,38 @@@ static int mov_parse_stsd_data(MOVConte
                                  int size)
  {
      if (st->codec->codec_tag == MKTAG('t','m','c','d')) {
 -        st->codec->extradata_size = size;
 -        st->codec->extradata = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE);
 -        if (!st->codec->extradata)
 +        if (ff_get_extradata(st->codec, pb, size) < 0)
              return AVERROR(ENOMEM);
 -        avio_read(pb, st->codec->extradata, size);
 +        if (size > 16) {
 +            MOVStreamContext *tmcd_ctx = st->priv_data;
 +            int val;
 +            val = AV_RB32(st->codec->extradata + 4);
 +            tmcd_ctx->tmcd_flags = val;
 +            if (val & 1)
 +                st->codec->flags2 |= CODEC_FLAG2_DROP_FRAME_TIMECODE;
 +            st->codec->time_base.den = st->codec->extradata[16]; /* number of frame */
 +            st->codec->time_base.num = 1;
 +            if (size > 30) {
 +                uint32_t len = AV_RB32(st->codec->extradata + 18); /* name atom length */
 +                uint32_t format = AV_RB32(st->codec->extradata + 22);
 +                if (format == AV_RB32("name") && (int64_t)size >= (int64_t)len + 18) {
 +                    uint16_t str_size = AV_RB16(st->codec->extradata + 26); /* string length */
 +                    if (str_size > 0 && size >= (int)str_size + 26) {
 +                        char *reel_name = av_malloc(str_size + 1);
 +                        if (!reel_name)
 +                            return AVERROR(ENOMEM);
 +                        memcpy(reel_name, st->codec->extradata + 30, str_size);
 +                        reel_name[str_size] = 0; /* Add null terminator */
 +                        /* don't add reel_name if emtpy string */
 +                        if (*reel_name == 0) {
 +                            av_free(reel_name);
 +                        } else {
 +                            av_dict_set(&st->metadata, "reel_name", reel_name,  AV_DICT_DONT_STRDUP_VAL);
 +                        }
 +                    }
 +                }
 +            }
 +        }
      } else {
          /* other codec type, just skip (rtp, mp4s ...) */
          avio_skip(pb, size);
@@@ -1688,10 -1525,6 +1688,10 @@@ static int mov_finalize_stsd_codec(MOVC
          // force sample rate for qcelp when not stored in mov
          if (st->codec->codec_tag != MKTAG('Q','c','l','p'))
              st->codec->sample_rate = 8000;
 +        // FIXME: Why is the following needed for some files?
 +        sc->samples_per_frame = 160;
 +        if (!sc->bytes_per_frame)
 +            sc->bytes_per_frame = 35;
          break;
      case AV_CODEC_ID_AMR_NB:
          st->codec->channels    = 1;
      case AV_CODEC_ID_ADPCM_MS:
      case AV_CODEC_ID_ADPCM_IMA_WAV:
      case AV_CODEC_ID_ILBC:
 +    case AV_CODEC_ID_MACE3:
 +    case AV_CODEC_ID_MACE6:
 +    case AV_CODEC_ID_QDM2:
          st->codec->block_align = sc->bytes_per_frame;
          break;
      case AV_CODEC_ID_ALAC:
              st->codec->sample_rate = AV_RB32(st->codec->extradata + 32);
          }
          break;
 +    case AV_CODEC_ID_AC3:
 +    case AV_CODEC_ID_EAC3:
 +    case AV_CODEC_ID_MPEG1VIDEO:
      case AV_CODEC_ID_VC1:
          st->need_parsing = AVSTREAM_PARSE_FULL;
          break;
  
  static int mov_skip_multiple_stsd(MOVContext *c, AVIOContext *pb,
                                    int codec_tag, int format,
 -                                  int size)
 +                                  int64_t size)
  {
      int video_codec_id = ff_codec_get_id(ff_codec_movvideo_tags, format);
  
      if (codec_tag &&
 -        (codec_tag == AV_RL32("avc1") ||
 -         codec_tag == AV_RL32("hvc1") ||
 -         codec_tag == AV_RL32("hev1") ||
           (codec_tag != format &&
            (c->fc->video_codec_id ? video_codec_id != c->fc->video_codec_id
 -                                 : codec_tag != MKTAG('j','p','e','g'))))) {
 +                                 : codec_tag != MKTAG('j','p','e','g')))) {
          /* Multiple fourcc, we skip JPEG. This is not correct, we should
           * export it as a separate AVStream but this needs a few changes
           * in the MOV demuxer, patch welcome. */
          avio_skip(pb, size);
          return 1;
      }
 +    if ( codec_tag == AV_RL32("avc1") ||
 +         codec_tag == AV_RL32("hvc1") ||
 +         codec_tag == AV_RL32("hev1")
 +    )
 +        av_log(c->fc, AV_LOG_WARNING, "Concatenated H.264 or H.265 might not play correctly.\n");
  
      return 0;
  }
@@@ -1781,15 -1606,15 +1781,15 @@@ int ff_mov_read_stsd_entries(MOVContex
          int ret, dref_id = 1;
          MOVAtom a = { AV_RL32("stsd") };
          int64_t start_pos = avio_tell(pb);
 -        uint32_t size = avio_rb32(pb); /* size */
 +        int64_t size = avio_rb32(pb); /* size */
          uint32_t format = avio_rl32(pb); /* data format */
  
          if (size >= 16) {
              avio_rb32(pb); /* reserved */
              avio_rb16(pb); /* reserved */
              dref_id = avio_rb16(pb);
 -        } else {
 -            av_log(c->fc, AV_LOG_ERROR, "invalid size %"PRIu32" in stsd\n", size);
 +        }else if (size <= 7){
 +            av_log(c->fc, AV_LOG_ERROR, "invalid size %"PRId64" in stsd\n", size);
              return AVERROR_INVALIDDATA;
          }
  
  
          id = mov_codec_id(st, format);
  
 -        av_dlog(c->fc, "size=%"PRIu32" 4CC= %"PRIu8"%"PRIu8"%"PRIu8"%"PRIu8" codec_type=%d\n", size,
 +        av_dlog(c->fc, "size=%"PRId64" 4CC= %c%c%c%c codec_type=%d\n", size,
                  (format >> 0) & 0xff, (format >> 8) & 0xff, (format >> 16) & 0xff,
                  (format >> 24) & 0xff, st->codec->codec_type);
  
@@@ -1942,8 -1767,6 +1942,8 @@@ static int mov_read_stss(MOVContext *c
      if (!entries)
      {
          sc->keyframe_absent = 1;
 +        if (!st->need_parsing && st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
 +            st->need_parsing = AVSTREAM_PARSE_HEADERS;
          return 0;
      }
      if (entries >= UINT_MAX / sizeof(int))
@@@ -1985,7 -1808,6 +1985,7 @@@ static int mov_read_stsz(MOVContext *c
          sample_size = avio_rb32(pb);
          if (!sc->sample_size) /* do not overwrite value computed in stsd */
              sc->sample_size = sample_size;
 +        sc->stsz_sample_size = sample_size;
          field_size = 32;
      } else {
          sample_size = 0;
@@@ -2063,8 -1885,10 +2063,8 @@@ static int mov_read_stts(MOVContext *c
      av_dlog(c->fc, "track[%i].stts.entries = %i\n",
              c->fc->nb_streams-1, entries);
  
 -    if (!entries)
 -        return 0;
      if (entries >= UINT_MAX / sizeof(*sc->stts_data))
 -        return AVERROR(EINVAL);
 +        return -1;
  
      av_free(sc->stts_data);
      sc->stts_data = av_malloc(entries * sizeof(*sc->stts_data));
  
          sample_count=avio_rb32(pb);
          sample_duration = avio_rb32(pb);
 +
 +        /* sample_duration < 0 is invalid based on the spec */
 +        if (sample_duration < 0) {
 +            av_log(c->fc, AV_LOG_ERROR, "Invalid SampleDelta %d in STTS, at %d st:%d\n",
 +                   sample_duration, i, c->fc->nb_streams-1);
 +            sample_duration = 1;
 +        }
          if (sample_count < 0) {
              av_log(c->fc, AV_LOG_ERROR, "Invalid sample_count=%d\n", sample_count);
              return AVERROR_INVALIDDATA;
          av_dlog(c->fc, "sample_count=%d, sample_duration=%d\n",
                  sample_count, sample_duration);
  
 +        if (   i+1 == entries
 +            && i
 +            && sample_count == 1
 +            && total_sample_count > 100
 +            && sample_duration/10 > duration / total_sample_count)
 +            sample_duration = duration / total_sample_count;
          duration+=(int64_t)sample_duration*sample_count;
          total_sample_count+=sample_count;
      }
  
      sc->stts_count = i;
  
 +    sc->duration_for_fps  += duration;
 +    sc->nb_frames_for_fps += total_sample_count;
 +
      if (pb->eof_reached)
          return AVERROR_EOF;
  
      return 0;
  }
  
 +static void mov_update_dts_shift(MOVStreamContext *sc, int duration)
 +{
 +    if (duration < 0) {
 +        sc->dts_shift = FFMAX(sc->dts_shift, -duration);
 +    }
 +}
 +
  static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
  {
      AVStream *st;
  
          sc->ctts_data[i].count   = count;
          sc->ctts_data[i].duration= duration;
 -        if (duration < 0)
 -            sc->dts_shift = FFMAX(sc->dts_shift, -duration);
 +
 +        av_dlog(c->fc, "count=%d, duration=%d\n",
 +                count, duration);
 +
 +        if (FFABS(duration) > (1<<28) && i+2<entries) {
 +            av_log(c->fc, AV_LOG_WARNING, "CTTS invalid\n");
 +            av_freep(&sc->ctts_data);
 +            sc->ctts_count = 0;
 +            return 0;
 +        }
 +
 +        if (i+2<entries)
 +            mov_update_dts_shift(sc, duration);
      }
  
      sc->ctts_count = i;
@@@ -2235,13 -2025,12 +2235,13 @@@ static void mov_build_index(MOVContext 
      uint64_t stream_size = 0;
  
      /* adjust first dts according to edit list */
 -    if (sc->time_offset && mov->time_scale > 0) {
 -        if (sc->time_offset < 0)
 -            sc->time_offset = av_rescale(sc->time_offset, sc->time_scale, mov->time_scale);
 +    if ((sc->empty_duration || sc->start_time) && mov->time_scale > 0) {
 +        if (sc->empty_duration)
 +            sc->empty_duration = av_rescale(sc->empty_duration, sc->time_scale, mov->time_scale);
 +        sc->time_offset = sc->start_time - sc->empty_duration;
          current_dts = -sc->time_offset;
 -        if (sc->ctts_data && sc->stts_data && sc->stts_data[0].duration &&
 -            sc->ctts_data[0].duration / sc->stts_data[0].duration > 16) {
 +        if (sc->ctts_count>0 && sc->stts_count>0 &&
 +            sc->ctts_data[0].duration / FFMAX(sc->stts_data[0].duration, 1) > 16) {
              /* more than 16 frames delay, dts are likely wrong
                 this happens with files created by iMovie */
              sc->wrong_dts = 1;
          unsigned int rap_group_index = 0;
          unsigned int rap_group_sample = 0;
          int rap_group_present = sc->rap_group_count && sc->rap_group;
 -        int key_off = (sc->keyframes && sc->keyframes[0] > 0) || (sc->stps_data && sc->stps_data[0] > 0);
 +        int key_off = (sc->keyframe_count && sc->keyframes[0] > 0) || (sc->stps_count && sc->stps_data[0] > 0);
  
          current_dts -= sc->dts_shift;
  
 -        if (!sc->sample_count)
 +        if (!sc->sample_count || st->nb_index_entries)
              return;
          if (sc->sample_count >= UINT_MAX / sizeof(*st->index_entries) - st->nb_index_entries)
              return;
          st->index_entries_allocated_size = (st->nb_index_entries + sc->sample_count) * sizeof(*st->index_entries);
  
          for (i = 0; i < sc->chunk_count; i++) {
 +            int64_t next_offset = i+1 < sc->chunk_count ? sc->chunk_offsets[i+1] : INT64_MAX;
              current_offset = sc->chunk_offsets[i];
              while (stsc_index + 1 < sc->stsc_count &&
                  i + 1 == sc->stsc_data[stsc_index + 1].first)
                  stsc_index++;
 +
 +            if (next_offset > current_offset && sc->sample_size>0 && sc->sample_size < sc->stsz_sample_size &&
 +                sc->stsc_data[stsc_index].count * (int64_t)sc->stsz_sample_size > next_offset - current_offset) {
 +                av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too large), ignoring\n", sc->stsz_sample_size);
 +                sc->stsz_sample_size = sc->sample_size;
 +            }
 +            if (sc->stsz_sample_size>0 && sc->stsz_sample_size < sc->sample_size) {
 +                av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too small), ignoring\n", sc->stsz_sample_size);
 +                sc->stsz_sample_size = sc->sample_size;
 +            }
 +
              for (j = 0; j < sc->stsc_data[stsc_index].count; j++) {
                  int keyframe = 0;
                  if (current_sample >= sc->sample_count) {
                          rap_group_index++;
                      }
                  }
 +                if (sc->keyframe_absent
 +                    && !sc->stps_count
 +                    && !rap_group_present
 +                    && (st->codec->codec_type == AVMEDIA_TYPE_AUDIO || (i==0 && j==0)))
 +                     keyframe = 1;
                  if (keyframe)
                      distance = 0;
 -                sample_size = sc->sample_size > 0 ? sc->sample_size : sc->sample_sizes[current_sample];
 +                sample_size = sc->stsz_sample_size > 0 ? sc->stsz_sample_size : sc->sample_sizes[current_sample];
                  if (sc->pseudo_stream_id == -1 ||
                     sc->stsc_data[stsc_index].id - 1 == sc->pseudo_stream_id) {
                      AVIndexEntry *e = &st->index_entries[st->nb_index_entries++];
                      av_dlog(mov->fc, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", "
                              "size %d, distance %d, keyframe %d\n", st->index, current_sample,
                              current_offset, current_dts, sample_size, distance, keyframe);
 +                    if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && st->nb_index_entries < 100)
 +                        ff_rfps_add_frame(mov->fc, st, current_dts);
                  }
  
                  current_offset += sample_size;
      }
  }
  
 -static int mov_open_dref(AVIOContext **pb, char *src, MOVDref *ref,
 -                         AVIOInterruptCB *int_cb)
 +static int mov_open_dref(AVIOContext **pb, const char *src, MOVDref *ref,
 +                         AVIOInterruptCB *int_cb, int use_absolute_path, AVFormatContext *fc)
  {
      /* try relative path, we do not try the absolute because it can leak information about our
         system to an attacker */
      if (ref->nlvl_to > 0 && ref->nlvl_from > 0) {
          char filename[1024];
 -        char *src_path;
 +        const char *src_path;
          int i, l;
  
          /* find a source dir */
              if (!avio_open2(pb, filename, AVIO_FLAG_READ, int_cb, NULL))
                  return 0;
          }
 +    } else if (use_absolute_path) {
 +        av_log(fc, AV_LOG_WARNING, "Using absolute path on user request, "
 +               "this is a possible security issue\n");
 +        if (!avio_open2(pb, ref->path, AVIO_FLAG_READ, int_cb, NULL))
 +            return 0;
      }
  
      return AVERROR(ENOENT);
  }
  
 +static void fix_timescale(MOVContext *c, MOVStreamContext *sc)
 +{
 +    if (sc->time_scale <= 0) {
 +        av_log(c->fc, AV_LOG_WARNING, "stream %d, timescale not set\n", sc->ffindex);
 +        sc->time_scale = c->time_scale;
 +        if (sc->time_scale <= 0)
 +            sc->time_scale = 1;
 +    }
 +}
 +
  static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
  {
      AVStream *st;
          return 0;
      }
  
 -    if (sc->time_scale <= 0) {
 -        av_log(c->fc, AV_LOG_WARNING, "stream %d, timescale not set\n", st->index);
 -        sc->time_scale = c->time_scale;
 -        if (sc->time_scale <= 0)
 -            sc->time_scale = 1;
 -    }
 +    fix_timescale(c, sc);
  
      avpriv_set_pts_info(st, 64, 1, sc->time_scale);
  
  
      if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) {
          MOVDref *dref = &sc->drefs[sc->dref_id - 1];
 -        if (mov_open_dref(&sc->pb, c->fc->filename, dref, &c->fc->interrupt_callback) < 0)
 +        if (mov_open_dref(&sc->pb, c->fc->filename, dref, &c->fc->interrupt_callback,
 +            c->use_absolute_path, c->fc) < 0)
              av_log(c->fc, AV_LOG_ERROR,
                     "stream %d, error opening alias: path='%s', dir='%s', "
                     "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d\n",
                     st->index, dref->path, dref->dir, dref->filename,
                     dref->volume, dref->nlvl_from, dref->nlvl_to);
 -    } else
 +    } else {
          sc->pb = c->fc->pb;
 +        sc->pb_is_copied = 1;
 +    }
  
      if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
          if (!st->sample_aspect_ratio.num &&
              st->sample_aspect_ratio = av_d2q(((double)st->codec->height * sc->width) /
                                               ((double)st->codec->width * sc->height), INT_MAX);
          }
 +
 +#if FF_API_R_FRAME_RATE
 +        if (sc->stts_count == 1 || (sc->stts_count == 2 && sc->stts_data[1].count == 1))
 +            av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den,
 +                      sc->time_scale, sc->stts_data[0].duration, INT_MAX);
 +#endif
      }
  
      // done for ai5q, ai52, ai55, ai1q, ai12 and ai15.
@@@ -2606,18 -2357,11 +2606,18 @@@ static int mov_read_ilst(MOVContext *c
      return ret;
  }
  
 -static int mov_read_replaygain(MOVContext *c, AVIOContext *pb, int size)
 +static int mov_read_custom_2plus(MOVContext *c, AVIOContext *pb, int size)
  {
      int64_t end = avio_tell(pb) + size;
      uint8_t *key = NULL, *val = NULL;
      int i;
 +    AVStream *st;
 +    MOVStreamContext *sc;
 +
 +    if (c->fc->nb_streams < 1)
 +        return 0;
 +    st = c->fc->streams[c->fc->nb_streams-1];
 +    sc = st->priv_data;
  
      for (i = 0; i < 2; i++) {
          uint8_t **p;
      }
  
      if (key && val) {
 -        av_dict_set(&c->fc->metadata, key, val,
 -                    AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
 -        key = val = NULL;
 +        if (strcmp(key, "iTunSMPB") == 0) {
 +            int priming, remainder, samples;
 +            if(sscanf(val, "%*X %X %X %X", &priming, &remainder, &samples) == 3){
 +                if(priming>0 && priming<16384)
 +                    sc->start_pad = priming;
 +            }
 +        }
 +        if (strcmp(key, "cdec") != 0) {
 +            av_dict_set(&c->fc->metadata, key, val,
 +                        AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
 +            key = val = NULL;
 +        }
      }
  
      avio_seek(pb, end, SEEK_SET);
@@@ -2694,7 -2429,8 +2694,7 @@@ static int mov_read_custom(MOVContext *
  
          domain_len = avio_get_str(pb, len, domain, sizeof(domain));
          avio_skip(pb, len - domain_len);
 -        if (!strcmp(domain, "org.hydrogenaudio.replaygain"))
 -            return mov_read_replaygain(c, pb, end - avio_tell(pb));
 +        return mov_read_custom_2plus(c, pb, end - avio_tell(pb));
      }
  
  fail:
@@@ -2773,8 -2509,7 +2773,8 @@@ static int mov_read_tkhd(MOVContext *c
      sc->width = width >> 16;
      sc->height = height >> 16;
  
 -    // save the matrix when it is not the default identity
 +    // save the matrix and add rotate metadata when it is not the default
 +    // identity
      if (display_matrix[0][0] != (1 << 16) ||
          display_matrix[1][1] != (1 << 16) ||
          display_matrix[2][2] != (1 << 30) ||
          display_matrix[1][0] || display_matrix[1][2] ||
          display_matrix[2][0] || display_matrix[2][1]) {
          int i, j;
 +        double rotate;
  
          av_freep(&sc->display_matrix);
          sc->display_matrix = av_malloc(sizeof(int32_t) * 9);
          for (i = 0; i < 3; i++)
              for (j = 0; j < 3; j++)
                  sc->display_matrix[i * 3 + j] = display_matrix[j][i];
 +
 +        rotate = av_display_rotation_get(sc->display_matrix);
 +        if (!isnan(rotate)) {
 +            char rotate_buf[64];
 +            rotate = -rotate;
 +            if (rotate < 0) // for backward compatibility
 +                rotate += 360;
 +            snprintf(rotate_buf, sizeof(rotate_buf), "%g", rotate);
 +            av_dict_set(&st->metadata, "rotate", rotate_buf, 0);
 +        }
      }
  
      // transform the display width/height according to the matrix
@@@ -2832,7 -2556,6 +2832,7 @@@ static int mov_read_tfhd(MOVContext *c
  {
      MOVFragment *frag = &c->fragment;
      MOVTrackExt *trex = NULL;
 +    MOVFragmentIndex* index = NULL;
      int flags, track_id, i;
  
      avio_r8(pb); /* version */
          av_log(c->fc, AV_LOG_ERROR, "could not find corresponding trex\n");
          return AVERROR_INVALIDDATA;
      }
 +    for (i = 0; i < c->fragment_index_count; i++) {
 +        MOVFragmentIndex* candidate = c->fragment_index_data[i];
 +        if (candidate->track_id == frag->track_id) {
 +            av_log(c->fc, AV_LOG_DEBUG,
 +                   "found fragment index for track %u\n", frag->track_id);
 +            index = candidate;
 +            break;
 +        }
 +    }
  
      frag->base_data_offset = flags & MOV_TFHD_BASE_DATA_OFFSET ?
                               avio_rb64(pb) : flags & MOV_TFHD_DEFAULT_BASE_IS_MOOF ?
                       avio_rb32(pb) : trex->size;
      frag->flags    = flags & MOV_TFHD_DEFAULT_FLAGS ?
                       avio_rb32(pb) : trex->flags;
 +    frag->time     = AV_NOPTS_VALUE;
 +    if (index) {
 +        int i, found = 0;
 +        for (i = index->current_item; i < index->item_count; i++) {
 +            if (frag->implicit_offset == index->items[i].moof_offset) {
 +                av_log(c->fc, AV_LOG_DEBUG, "found fragment index entry "
 +                        "for track %u and moof_offset %"PRId64"\n",
 +                        frag->track_id, index->items[i].moof_offset);
 +                frag->time = index->items[i].time;
 +                index->current_item = i + 1;
 +                found = 1;
 +            }
 +        }
 +        if (!found) {
 +            av_log(c->fc, AV_LOG_WARNING, "track %u has a fragment index "
 +                   "but it doesn't have an (in-order) entry for moof_offset "
 +                   "%"PRId64"\n", frag->track_id, frag->implicit_offset);
 +        }
 +    }
      av_dlog(c->fc, "frag flags 0x%x\n", frag->flags);
      return 0;
  }
@@@ -2913,9 -2608,6 +2913,9 @@@ static int mov_read_trex(MOVContext *c
          c->trex_count = 0;
          return err;
      }
 +
 +    c->fc->duration = AV_NOPTS_VALUE; // the duration from mvhd is not representing the whole file when fragments are used.
 +
      trex = &c->trex_data[c->trex_count++];
      avio_r8(pb); /* version */
      avio_rb24(pb); /* flags */
@@@ -2980,7 -2672,7 +2980,7 @@@ static int mov_read_trun(MOVContext *c
          return AVERROR_INVALIDDATA;
      }
      sc = st->priv_data;
 -    if (sc->pseudo_stream_id+1 != frag->stsd_id)
 +    if (sc->pseudo_stream_id+1 != frag->stsd_id && sc->pseudo_stream_id != -1)
          return 0;
      avio_r8(pb); /* version */
      flags = avio_rb24(pb);
          sc->ctts_data[sc->ctts_count].count = 1;
          sc->ctts_data[sc->ctts_count].duration = (flags & MOV_TRUN_SAMPLE_CTS) ?
                                                    avio_rb32(pb) : 0;
 +        mov_update_dts_shift(sc, sc->ctts_data[sc->ctts_count].duration);
 +        if (frag->time != AV_NOPTS_VALUE) {
 +            if (c->use_mfra_for == FF_MOV_FLAG_MFRA_PTS) {
 +                int64_t pts = frag->time;
 +                av_log(c->fc, AV_LOG_DEBUG, "found frag time %"PRId64
 +                        " sc->dts_shift %d ctts.duration %d"
 +                        " sc->time_offset %"PRId64" flags & MOV_TRUN_SAMPLE_CTS %d\n", pts,
 +                        sc->dts_shift, sc->ctts_data[sc->ctts_count].duration,
 +                        sc->time_offset, flags & MOV_TRUN_SAMPLE_CTS);
 +                dts = pts - sc->dts_shift;
 +                if (flags & MOV_TRUN_SAMPLE_CTS) {
 +                    dts -= sc->ctts_data[sc->ctts_count].duration;
 +                } else {
 +                    dts -= sc->time_offset;
 +                }
 +                av_log(c->fc, AV_LOG_DEBUG, "calculated into dts %"PRId64"\n", dts);
 +            } else {
 +                dts = frag->time;
 +                av_log(c->fc, AV_LOG_DEBUG, "found frag time %"PRId64
 +                        ", using it for dts\n", dts);
 +            }
 +            frag->time = AV_NOPTS_VALUE;
 +        }
          sc->ctts_count++;
          if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
              keyframe = 1;
          dts += sample_duration;
          offset += sample_size;
          sc->data_size += sample_size;
 +        sc->duration_for_fps += sample_duration;
 +        sc->nb_frames_for_fps ++;
      }
  
      if (pb->eof_reached)
@@@ -3117,7 -2784,7 +3117,7 @@@ static int mov_read_cmov(MOVContext *c
      if (avio_rl32(pb) != MKTAG('d','c','o','m'))
          return AVERROR_INVALIDDATA;
      if (avio_rl32(pb) != MKTAG('z','l','i','b')) {
 -        av_log(c->fc, AV_LOG_ERROR, "unknown compression for cmov atom !");
 +        av_log(c->fc, AV_LOG_ERROR, "unknown compression for cmov atom !\n");
          return AVERROR_INVALIDDATA;
      }
      avio_rb32(pb); /* cmvd atom */
@@@ -3156,10 -2823,9 +3156,10 @@@ free_and_return
  static int mov_read_elst(MOVContext *c, AVIOContext *pb, MOVAtom atom)
  {
      MOVStreamContext *sc;
 -    int i, edit_count, version;
 +    int i, edit_count, version, edit_start_index = 0;
 +    int unsupported = 0;
  
 -    if (c->fc->nb_streams < 1)
 +    if (c->fc->nb_streams < 1 || c->ignore_editlist)
          return 0;
      sc = c->fc->streams[c->fc->nb_streams-1]->priv_data;
  
      if ((uint64_t)edit_count*12+8 > atom.size)
          return AVERROR_INVALIDDATA;
  
 +    av_dlog(c->fc, "track[%i].edit_count = %i\n", c->fc->nb_streams-1, edit_count);
      for (i=0; i<edit_count; i++){
          int64_t time;
          int64_t duration;
 +        int rate;
          if (version == 1) {
              duration = avio_rb64(pb);
              time     = avio_rb64(pb);
              duration = avio_rb32(pb); /* segment duration */
              time     = (int32_t)avio_rb32(pb); /* media time */
          }
 -        avio_rb32(pb); /* Media rate */
 -        if (i == 0 && time >= -1) {
 -            sc->time_offset = time != -1 ? time : -duration;
 -        }
 +        rate = avio_rb32(pb);
 +        if (i == 0 && time == -1) {
 +            sc->empty_duration = duration;
 +            edit_start_index = 1;
 +        } else if (i == edit_start_index && time >= 0)
 +            sc->start_time = time;
 +        else
 +            unsupported = 1;
 +
 +        av_dlog(c->fc, "duration=%"PRId64" time=%"PRId64" rate=%f\n",
 +                duration, time, rate / 65536.0);
      }
  
 -    if (edit_count > 1)
 +    if (unsupported)
          av_log(c->fc, AV_LOG_WARNING, "multiple edit list entries, "
                 "a/v desync might occur, patch welcome\n");
  
 -    av_dlog(c->fc, "track[%i].edit_count = %i\n", c->fc->nb_streams-1, edit_count);
 +    return 0;
 +}
 +
 +static int mov_read_tmcd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 +{
 +    MOVStreamContext *sc;
 +
 +    if (c->fc->nb_streams < 1)
 +        return AVERROR_INVALIDDATA;
 +    sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
 +    sc->timecode_track = avio_rb32(pb);
 +    return 0;
 +}
 +
 +static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 +{
 +    int ret;
 +    uint8_t uuid[16];
 +    static const uint8_t uuid_isml_manifest[] = {
 +        0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
 +        0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
 +    };
 +
 +    if (atom.size < sizeof(uuid) || atom.size == INT64_MAX)
 +        return AVERROR_INVALIDDATA;
 +
 +    ret = avio_read(pb, uuid, sizeof(uuid));
 +    if (ret < 0) {
 +        return ret;
 +    } else if (ret != sizeof(uuid)) {
 +        return AVERROR_INVALIDDATA;
 +    }
 +    if (!memcmp(uuid, uuid_isml_manifest, sizeof(uuid))) {
 +        uint8_t *buffer, *ptr;
 +        char *endptr;
 +        size_t len = atom.size - sizeof(uuid);
 +
 +        if (len < 4) {
 +            return AVERROR_INVALIDDATA;
 +        }
 +        ret = avio_skip(pb, 4); // zeroes
 +        len -= 4;
 +
 +        buffer = av_mallocz(len + 1);
 +        if (!buffer) {
 +            return AVERROR(ENOMEM);
 +        }
 +        ret = avio_read(pb, buffer, len);
 +        if (ret < 0) {
 +            av_free(buffer);
 +            return ret;
 +        } else if (ret != len) {
 +            av_free(buffer);
 +            return AVERROR_INVALIDDATA;
 +        }
 +
 +        ptr = buffer;
 +        while ((ptr = av_stristr(ptr, "systemBitrate=\""))) {
 +            ptr += sizeof("systemBitrate=\"") - 1;
 +            c->bitrates_count++;
 +            c->bitrates = av_realloc_f(c->bitrates, c->bitrates_count, sizeof(*c->bitrates));
 +            if (!c->bitrates) {
 +                c->bitrates_count = 0;
 +                av_free(buffer);
 +                return AVERROR(ENOMEM);
 +            }
 +            errno = 0;
 +            ret = strtol(ptr, &endptr, 10);
 +            if (ret < 0 || errno || *endptr != '"') {
 +                c->bitrates[c->bitrates_count - 1] = 0;
 +            } else {
 +                c->bitrates[c->bitrates_count - 1] = ret;
 +            }
 +        }
 +
 +        av_free(buffer);
 +    }
 +    return 0;
 +}
 +
 +static int mov_read_free(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 +{
 +    int ret;
 +    uint8_t content[16];
 +
 +    if (atom.size < 8)
 +        return 0;
 +
 +    ret = avio_read(pb, content, FFMIN(sizeof(content), atom.size));
 +    if (ret < 0)
 +        return ret;
 +
 +    if (   !c->found_moov
 +        && !c->found_mdat
 +        && !memcmp(content, "Anevia\x1A\x1A", 8)
 +        && c->use_mfra_for == FF_MOV_FLAG_MFRA_AUTO) {
 +        c->use_mfra_for = FF_MOV_FLAG_MFRA_PTS;
 +    }
 +
      return 0;
  }
  
  static const MOVParseTableEntry mov_default_parse_table[] = {
 -{ MKTAG('a','v','s','s'), mov_read_extradata },
 +{ MKTAG('A','C','L','R'), mov_read_avid },
 +{ MKTAG('A','P','R','G'), mov_read_avid },
 +{ MKTAG('A','A','L','P'), mov_read_avid },
 +{ MKTAG('A','R','E','S'), mov_read_ares },
 +{ MKTAG('a','v','s','s'), mov_read_avss },
  { MKTAG('c','h','p','l'), mov_read_chpl },
  { MKTAG('c','o','6','4'), mov_read_stco },
  { MKTAG('c','o','l','r'), mov_read_colr },
  { MKTAG('g','l','b','l'), mov_read_glbl },
  { MKTAG('h','d','l','r'), mov_read_hdlr },
  { MKTAG('i','l','s','t'), mov_read_ilst },
 -{ MKTAG('j','p','2','h'), mov_read_extradata },
 +{ MKTAG('j','p','2','h'), mov_read_jp2h },
  { MKTAG('m','d','a','t'), mov_read_mdat },
  { MKTAG('m','d','h','d'), mov_read_mdhd },
  { MKTAG('m','d','i','a'), mov_read_default },
  { MKTAG('m','o','o','v'), mov_read_moov },
  { MKTAG('m','v','e','x'), mov_read_default },
  { MKTAG('m','v','h','d'), mov_read_mvhd },
 -{ MKTAG('S','M','I',' '), mov_read_smi }, /* Sorenson extension ??? */
 -{ MKTAG('a','l','a','c'), mov_read_extradata }, /* alac specific atom */
 +{ MKTAG('S','M','I',' '), mov_read_svq3 },
 +{ MKTAG('a','l','a','c'), mov_read_alac }, /* alac specific atom */
  { MKTAG('a','v','c','C'), mov_read_glbl },
  { MKTAG('p','a','s','p'), mov_read_pasp },
  { MKTAG('s','t','b','l'), mov_read_default },
  { MKTAG('t','r','a','k'), mov_read_trak },
  { MKTAG('t','r','a','f'), mov_read_default },
  { MKTAG('t','r','e','f'), mov_read_default },
 +{ MKTAG('t','m','c','d'), mov_read_tmcd },
  { MKTAG('c','h','a','p'), mov_read_chap },
  { MKTAG('t','r','e','x'), mov_read_trex },
  { MKTAG('t','r','u','n'), mov_read_trun },
  { MKTAG('d','v','c','1'), mov_read_dvc1 },
  { MKTAG('s','b','g','p'), mov_read_sbgp },
  { MKTAG('h','v','c','C'), mov_read_glbl },
 +{ MKTAG('u','u','i','d'), mov_read_uuid },
 +{ MKTAG('C','i','n', 0x8e), mov_read_targa_y216 },
 +{ MKTAG('f','r','e','e'), mov_read_free },
  { MKTAG('-','-','-','-'), mov_read_custom },
  { 0, NULL }
  };
@@@ -3382,46 -2933,25 +3382,46 @@@ static int mov_read_default(MOVContext 
  
      if (atom.size < 0)
          atom.size = INT64_MAX;
 -    while (total_size + 8 < atom.size && !pb->eof_reached) {
 +    while (total_size + 8 <= atom.size && !avio_feof(pb)) {
          int (*parse)(MOVContext*, AVIOContext*, MOVAtom) = NULL;
          a.size = atom.size;
          a.type=0;
          if (atom.size >= 8) {
              a.size = avio_rb32(pb);
              a.type = avio_rl32(pb);
 +            if (a.type == MKTAG('f','r','e','e') &&
 +                a.size >= 8 &&
 +                c->moov_retry) {
 +                uint8_t buf[8];
 +                uint32_t *type = (uint32_t *)buf + 1;
 +                avio_read(pb, buf, 8);
 +                avio_seek(pb, -8, SEEK_CUR);
 +                if (*type == MKTAG('m','v','h','d') ||
 +                    *type == MKTAG('c','m','o','v')) {
 +                    av_log(c->fc, AV_LOG_ERROR, "Detected moov in a free atom.\n");
 +                    a.type = MKTAG('m','o','o','v');
 +                }
 +            }
 +            if (atom.type != MKTAG('r','o','o','t') &&
 +                atom.type != MKTAG('m','o','o','v'))
 +            {
 +                if (a.type == MKTAG('t','r','a','k') || a.type == MKTAG('m','d','a','t'))
 +                {
 +                    av_log(c->fc, AV_LOG_ERROR, "Broken file, trak/mdat not at top-level\n");
 +                    avio_skip(pb, -8);
 +                    return 0;
 +                }
 +            }
 +            total_size += 8;
 +            if (a.size == 1) { /* 64 bit extended size */
 +                a.size = avio_rb64(pb) - 8;
 +                total_size += 8;
 +            }
          }
          av_dlog(c->fc, "type: %08x '%.4s' parent:'%.4s' sz: %"PRId64" %"PRId64" %"PRId64"\n",
                  a.type, (char*)&a.type, (char*)&atom.type, a.size, total_size, atom.size);
 -        total_size += 8;
 -        if (a.size == 1) { /* 64 bit extended size */
 -            a.size = avio_rb64(pb) - 8;
 -            total_size += 8;
 -        }
          if (a.size == 0) {
 -            a.size = atom.size - total_size;
 -            if (a.size <= 8)
 -                break;
 +            a.size = atom.size - total_size + 8;
          }
          a.size -= 8;
          if (a.size < 0)
  
  static int mov_probe(AVProbeData *p)
  {
 -    unsigned int offset;
 +    int64_t offset;
      uint32_t tag;
      int score = 0;
 +    int moov_offset = -1;
  
      /* check file header */
      offset = 0;
      for (;;) {
          /* ignore invalid offset */
          if ((offset + 8) > (unsigned int)p->buf_size)
 -            return score;
 +            break;
          tag = AV_RL32(p->buf + offset + 4);
          switch(tag) {
          /* check for obvious tags */
 -        case MKTAG('j','P',' ',' '): /* jpeg 2000 signature */
          case MKTAG('m','o','o','v'):
 +            moov_offset = offset + 4;
          case MKTAG('m','d','a','t'):
          case MKTAG('p','n','o','t'): /* detect movs with preview pics like ew.mov and april.mov */
          case MKTAG('u','d','t','a'): /* Packet Video PVAuthor adds this and a lot of more junk */
          case MKTAG('f','t','y','p'):
 -            return AVPROBE_SCORE_MAX;
 +            if (AV_RB32(p->buf+offset) < 8 &&
 +                (AV_RB32(p->buf+offset) != 1 ||
 +                 offset + 12 > (unsigned int)p->buf_size ||
 +                 AV_RB64(p->buf+offset + 8) == 0)) {
 +                score = FFMAX(score, AVPROBE_SCORE_EXTENSION);
 +            } else if (tag == MKTAG('f','t','y','p') &&
 +                       AV_RL32(p->buf + offset + 8) == MKTAG('j','p','2',' ')) {
 +                score = FFMAX(score, 5);
 +            } else {
 +                score = AVPROBE_SCORE_MAX;
 +            }
 +            offset = FFMAX(4, AV_RB32(p->buf+offset)) + offset;
 +            break;
          /* those are more common words, so rate then a bit less */
          case MKTAG('e','d','i','w'): /* xdcam files have reverted first tags */
          case MKTAG('w','i','d','e'):
          case MKTAG('f','r','e','e'):
          case MKTAG('j','u','n','k'):
          case MKTAG('p','i','c','t'):
 -            return AVPROBE_SCORE_MAX - 5;
 +            score  = FFMAX(score, AVPROBE_SCORE_MAX - 5);
 +            offset = FFMAX(4, AV_RB32(p->buf+offset)) + offset;
 +            break;
          case MKTAG(0x82,0x82,0x7f,0x7d):
          case MKTAG('s','k','i','p'):
          case MKTAG('u','u','i','d'):
          case MKTAG('p','r','f','l'):
 -            offset = AV_RB32(p->buf+offset) + offset;
              /* if we only find those cause probedata is too small at least rate them */
 -            score = AVPROBE_SCORE_EXTENSION;
 +            score  = FFMAX(score, AVPROBE_SCORE_EXTENSION);
 +            offset = FFMAX(4, AV_RB32(p->buf+offset)) + offset;
              break;
          default:
 -            /* unrecognized tag */
 -            return score;
 +            offset = FFMAX(4, AV_RB32(p->buf+offset)) + offset;
 +        }
 +    }
 +    if(score > AVPROBE_SCORE_MAX - 50 && moov_offset != -1) {
 +        /* moov atom in the header - we should make sure that this is not a
 +         * MOV-packed MPEG-PS */
 +        offset = moov_offset;
 +
 +        while(offset < (p->buf_size - 16)){ /* Sufficient space */
 +               /* We found an actual hdlr atom */
 +            if(AV_RL32(p->buf + offset     ) == MKTAG('h','d','l','r') &&
 +               AV_RL32(p->buf + offset +  8) == MKTAG('m','h','l','r') &&
 +               AV_RL32(p->buf + offset + 12) == MKTAG('M','P','E','G')){
 +                av_log(NULL, AV_LOG_WARNING, "Found media data tag MPEG indicating this is a MOV-packed MPEG-PS.\n");
 +                /* We found a media handler reference atom describing an
 +                 * MPEG-PS-in-MOV, return a
 +                 * low score to force expanding the probe window until
 +                 * mpegps_probe finds what it needs */
 +                return 5;
 +            }else
 +                /* Keep looking */
 +                offset+=2;
          }
      }
 +
 +    return score;
  }
  
  // must be done after parsing all trak because there's no order requirement
@@@ -3585,11 -3078,6 +3585,11 @@@ static void mov_read_chapters(AVFormatC
          uint16_t ch;
          int len, title_len;
  
 +        if (end < sample->timestamp) {
 +            av_log(s, AV_LOG_WARNING, "ignoring stream duration which is shorter than chapters\n");
 +            end = AV_NOPTS_VALUE;
 +        }
 +
          if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
              av_log(s, AV_LOG_ERROR, "Chapter %d not found in file\n", i);
              goto finish;
                  if (len == 1 || len == 2)
                      title[len] = 0;
                  else
 -                    avio_get_str(sc->pb, len - 2, title + 2, title_len - 2);
 +                    avio_get_str(sc->pb, INT_MAX, title + 2, len - 1);
              }
          }
  
@@@ -3630,49 -3118,6 +3630,49 @@@ finish
      avio_seek(sc->pb, cur_pos, SEEK_SET);
  }
  
 +static int parse_timecode_in_framenum_format(AVFormatContext *s, AVStream *st,
 +                                             uint32_t value, int flags)
 +{
 +    AVTimecode tc;
 +    char buf[AV_TIMECODE_STR_SIZE];
 +    AVRational rate = {st->codec->time_base.den,
 +                       st->codec->time_base.num};
 +    int ret = av_timecode_init(&tc, rate, flags, 0, s);
 +    if (ret < 0)
 +        return ret;
 +    av_dict_set(&st->metadata, "timecode",
 +                av_timecode_make_string(&tc, buf, value), 0);
 +    return 0;
 +}
 +
 +static int mov_read_timecode_track(AVFormatContext *s, AVStream *st)
 +{
 +    MOVStreamContext *sc = st->priv_data;
 +    int flags = 0;
 +    int64_t cur_pos = avio_tell(sc->pb);
 +    uint32_t value;
 +
 +    if (!st->nb_index_entries)
 +        return -1;
 +
 +    avio_seek(sc->pb, st->index_entries->pos, SEEK_SET);
 +    value = avio_rb32(s->pb);
 +
 +    if (sc->tmcd_flags & 0x0001) flags |= AV_TIMECODE_FLAG_DROPFRAME;
 +    if (sc->tmcd_flags & 0x0002) flags |= AV_TIMECODE_FLAG_24HOURSMAX;
 +    if (sc->tmcd_flags & 0x0004) flags |= AV_TIMECODE_FLAG_ALLOWNEGATIVE;
 +
 +    /* Assume Counter flag is set to 1 in tmcd track (even though it is likely
 +     * not the case) and thus assume "frame number format" instead of QT one.
 +     * No sample with tmcd track can be found with a QT timecode at the moment,
 +     * despite what the tmcd track "suggests" (Counter flag set to 0 means QT
 +     * format). */
 +    parse_timecode_in_framenum_format(s, st, value, flags);
 +
 +    avio_seek(sc->pb, cur_pos, SEEK_SET);
 +    return 0;
 +}
 +
  static int mov_read_close(AVFormatContext *s)
  {
      MOVContext *mov = s->priv_data;
              av_freep(&sc->drefs[j].dir);
          }
          av_freep(&sc->drefs);
 -        if (sc->pb && sc->pb != s->pb)
 +
 +        sc->drefs_count = 0;
 +
 +        if (!sc->pb_is_copied)
              avio_close(sc->pb);
  
 +        sc->pb = NULL;
          av_freep(&sc->chunk_offsets);
          av_freep(&sc->stsc_data);
          av_freep(&sc->sample_sizes);
      }
  
      av_freep(&mov->trex_data);
 +    av_freep(&mov->bitrates);
 +
 +    for (i = 0; i < mov->fragment_index_count; i++) {
 +        MOVFragmentIndex* index = mov->fragment_index_data[i];
 +        av_freep(&index->items);
 +        av_freep(&mov->fragment_index_data[i]);
 +    }
 +    av_freep(&mov->fragment_index_data);
 +
 +    return 0;
 +}
 +
 +static int tmcd_is_referenced(AVFormatContext *s, int tmcd_id)
 +{
 +    int i;
 +
 +    for (i = 0; i < s->nb_streams; i++) {
 +        AVStream *st = s->streams[i];
 +        MOVStreamContext *sc = st->priv_data;
  
 +        if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
 +            sc->timecode_track == tmcd_id)
 +            return 1;
 +    }
      return 0;
  }
  
 +/* look for a tmcd track not referenced by any video track, and export it globally */
 +static void export_orphan_timecode(AVFormatContext *s)
 +{
 +    int i;
 +
 +    for (i = 0; i < s->nb_streams; i++) {
 +        AVStream *st = s->streams[i];
 +
 +        if (st->codec->codec_tag  == MKTAG('t','m','c','d') &&
 +            !tmcd_is_referenced(s, i + 1)) {
 +            AVDictionaryEntry *tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
 +            if (tcr) {
 +                av_dict_set(&s->metadata, "timecode", tcr->value, 0);
 +                break;
 +            }
 +        }
 +    }
 +}
 +
 +static int read_tfra(MOVContext *mov, AVIOContext *f)
 +{
 +    MOVFragmentIndex* index = NULL;
 +    int version, fieldlength, i, j, err;
 +    int64_t pos = avio_tell(f);
 +    uint32_t size = avio_rb32(f);
 +    if (avio_rb32(f) != MKBETAG('t', 'f', 'r', 'a')) {
 +        return -1;
 +    }
 +    av_log(mov->fc, AV_LOG_VERBOSE, "found tfra\n");
 +    index = av_mallocz(sizeof(MOVFragmentIndex));
 +    if (!index) {
 +        return AVERROR(ENOMEM);
 +    }
 +    mov->fragment_index_count++;
 +    if ((err = av_reallocp(&mov->fragment_index_data,
 +                           mov->fragment_index_count *
 +                           sizeof(MOVFragmentIndex*))) < 0) {
 +        av_freep(&index);
 +        return err;
 +    }
 +    mov->fragment_index_data[mov->fragment_index_count - 1] =
 +        index;
 +
 +    version = avio_r8(f);
 +    avio_rb24(f);
 +    index->track_id = avio_rb32(f);
 +    fieldlength = avio_rb32(f);
 +    index->item_count = avio_rb32(f);
 +    index->items = av_mallocz(
 +            index->item_count * sizeof(MOVFragmentIndexItem));
 +    if (!index->items) {
 +        return AVERROR(ENOMEM);
 +    }
 +    for (i = 0; i < index->item_count; i++) {
 +        int64_t time, offset;
 +        if (version == 1) {
 +            time   = avio_rb64(f);
 +            offset = avio_rb64(f);
 +        } else {
 +            time   = avio_rb32(f);
 +            offset = avio_rb32(f);
 +        }
 +        index->items[i].time = time;
 +        index->items[i].moof_offset = offset;
 +        for (j = 0; j < ((fieldlength >> 4) & 3) + 1; j++)
 +            avio_r8(f);
 +        for (j = 0; j < ((fieldlength >> 2) & 3) + 1; j++)
 +            avio_r8(f);
 +        for (j = 0; j < ((fieldlength >> 0) & 3) + 1; j++)
 +            avio_r8(f);
 +    }
 +
 +    avio_seek(f, pos + size, SEEK_SET);
 +    return 0;
 +}
 +
 +static int mov_read_mfra(MOVContext *c, AVIOContext *f)
 +{
 +    int64_t stream_size = avio_size(f);
 +    int64_t original_pos = avio_tell(f);
 +    int32_t mfra_size;
 +    int ret = -1;
 +    if ((ret = avio_seek(f, stream_size - 4, SEEK_SET)) < 0) goto fail;
 +    mfra_size = avio_rb32(f);
 +    if (mfra_size < 0 || mfra_size > stream_size) {
 +        av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (unreasonable size)\n");
 +        ret = -1;
 +        goto fail;
 +    }
 +    if ((ret = avio_seek(f, -mfra_size, SEEK_CUR)) < 0) goto fail;
 +    if (avio_rb32(f) != mfra_size) {
 +        av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (size mismatch)\n");
 +        ret = -1;
 +        goto fail;
 +    }
 +    if (avio_rb32(f) != MKBETAG('m', 'f', 'r', 'a')) {
 +        av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (tag mismatch)\n");
 +        goto fail;
 +    }
 +    av_log(c->fc, AV_LOG_VERBOSE, "stream has mfra\n");
 +    while (!read_tfra(c, f)) {
 +        /* Empty */
 +    }
 +fail:
 +    ret = avio_seek(f, original_pos, SEEK_SET);
 +    if (ret < 0)
 +        av_log(c->fc, AV_LOG_ERROR,
 +               "failed to seek back after looking for mfra\n");
 +    else
 +        ret = 0;
 +    return ret;
 +}
 +
  static int mov_read_header(AVFormatContext *s)
  {
      MOVContext *mov = s->priv_data;
      AVIOContext *pb = s->pb;
 -    int err;
 +    int j, err;
      MOVAtom atom = { AV_RL32("root") };
      int i;
  
          atom.size = INT64_MAX;
  
      /* check MOV header */
 +    do {
 +    if (mov->moov_retry)
 +        avio_seek(pb, 0, SEEK_SET);
      if ((err = mov_read_default(mov, pb, atom)) < 0) {
 -        av_log(s, AV_LOG_ERROR, "error reading header: %d\n", err);
 +        av_log(s, AV_LOG_ERROR, "error reading header\n");
          mov_read_close(s);
          return err;
      }
 +    } while (pb->seekable && !mov->found_moov && !mov->moov_retry++);
      if (!mov->found_moov) {
          av_log(s, AV_LOG_ERROR, "moov atom not found\n");
          mov_read_close(s);
      }
      av_dlog(mov->fc, "on_parse_exit_offset=%"PRId64"\n", avio_tell(pb));
  
 -    if (pb->seekable && mov->chapter_track > 0)
 -        mov_read_chapters(s);
 +    if (pb->seekable) {
 +        if (mov->chapter_track > 0)
 +            mov_read_chapters(s);
 +        for (i = 0; i < s->nb_streams; i++)
 +            if (s->streams[i]->codec->codec_tag == AV_RL32("tmcd"))
 +                mov_read_timecode_track(s, s->streams[i]);
 +    }
  
 +    /* copy timecode metadata from tmcd tracks to the related video streams */
      for (i = 0; i < s->nb_streams; i++) {
          AVStream *st = s->streams[i];
          MOVStreamContext *sc = st->priv_data;
 +        if (sc->timecode_track > 0) {
 +            AVDictionaryEntry *tcr;
 +            int tmcd_st_id = -1;
 +
 +            for (j = 0; j < s->nb_streams; j++)
 +                if (s->streams[j]->id == sc->timecode_track)
 +                    tmcd_st_id = j;
 +
 +            if (tmcd_st_id < 0 || tmcd_st_id == i)
 +                continue;
 +            tcr = av_dict_get(s->streams[tmcd_st_id]->metadata, "timecode", NULL, 0);
 +            if (tcr)
 +                av_dict_set(&st->metadata, "timecode", tcr->value, 0);
 +        }
 +    }
 +    export_orphan_timecode(s);
  
 +    for (i = 0; i < s->nb_streams; i++) {
 +        AVStream *st = s->streams[i];
 +        MOVStreamContext *sc = st->priv_data;
 +        fix_timescale(mov, sc);
 +        if(st->codec->codec_type == AVMEDIA_TYPE_AUDIO && st->codec->codec_id == AV_CODEC_ID_AAC) {
 +            st->skip_samples = sc->start_pad;
 +        }
 +        if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && sc->nb_frames_for_fps > 0 && sc->duration_for_fps > 0)
 +            av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
 +                      sc->time_scale*(int64_t)sc->nb_frames_for_fps, sc->duration_for_fps, INT_MAX);
          if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
              if (st->codec->width <= 0 || st->codec->height <= 0) {
                  st->codec->width  = sc->width;
          }
      }
  
 +    if (mov->use_mfra_for > 0) {
 +        for (i = 0; i < s->nb_streams; i++) {
 +            AVStream *st = s->streams[i];
 +            MOVStreamContext *sc = st->priv_data;
 +            if (sc->duration_for_fps > 0) {
 +                st->codec->bit_rate = sc->data_size * 8 * sc->time_scale /
 +                    sc->duration_for_fps;
 +            }
 +        }
 +    }
 +
 +    for (i = 0; i < mov->bitrates_count && i < s->nb_streams; i++) {
 +        if (mov->bitrates[i]) {
 +            s->streams[i]->codec->bit_rate = mov->bitrates[i];
 +        }
 +    }
 +
 +    ff_rfps_calculate(s);
 +
      for (i = 0; i < s->nb_streams; i++) {
          AVStream *st = s->streams[i];
          MOVStreamContext *sc = st->priv_data;
@@@ -4032,7 -3282,6 +4032,7 @@@ static int mov_read_packet(AVFormatCont
      AVIndexEntry *sample;
      AVStream *st = NULL;
      int ret;
 +    mov->fc = s;
   retry:
      sample = mov_find_next_sample(s, &st);
      if (!sample) {
          avio_seek(s->pb, mov->next_root_atom, SEEK_SET);
          mov->next_root_atom = 0;
          if (mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX }) < 0 ||
 -            s->pb->eof_reached)
 +            avio_feof(s->pb))
              return AVERROR_EOF;
          av_dlog(s, "read fragments, offset 0x%"PRIx64"\n", avio_tell(s->pb));
          goto retry;
      /* must be done just before reading, to avoid infinite loop on sample */
      sc->current_sample++;
  
 +    if (mov->next_root_atom) {
 +        sample->pos = FFMIN(sample->pos, mov->next_root_atom);
 +        sample->size = FFMIN(sample->size, (mov->next_root_atom - sample->pos));
 +    }
 +
      if (st->discard != AVDISCARD_ALL) {
          if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
              av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%"PRIx64": partial file\n",
          }
  #if CONFIG_DV_DEMUXER
          if (mov->dv_demux && sc->dv_audio_container) {
 -            avpriv_dv_produce_packet(mov->dv_demux, pkt, pkt->data, pkt->size);
 +            avpriv_dv_produce_packet(mov->dv_demux, pkt, pkt->data, pkt->size, pkt->pos);
              av_free(pkt->data);
              pkt->size = 0;
              ret = avpriv_dv_get_packet(mov->dv_demux, pkt);
@@@ -4155,6 -3399,8 +4155,6 @@@ static int mov_read_seek(AVFormatContex
  
      if (stream_index >= s->nb_streams)
          return AVERROR_INVALIDDATA;
 -    if (sample_time < 0)
 -        sample_time = 0;
  
      st = s->streams[stream_index];
      sample = mov_seek_stream(s, st, sample_time, flags);
      seek_timestamp = st->index_entries[sample].timestamp;
  
      for (i = 0; i < s->nb_streams; i++) {
 +        MOVStreamContext *sc = s->streams[i]->priv_data;
          st = s->streams[i];
 +        st->skip_samples = (sample_time <= 0) ? sc->start_pad : 0;
 +
          if (stream_index == i)
              continue;
  
      return 0;
  }
  
 +static const AVOption options[] = {
 +    {"use_absolute_path",
 +        "allow using absolute path when opening alias, this is a possible security issue",
 +        offsetof(MOVContext, use_absolute_path), FF_OPT_TYPE_INT, {.i64 = 0},
 +        0, 1, AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_DECODING_PARAM},
 +    {"ignore_editlist", "", offsetof(MOVContext, ignore_editlist), FF_OPT_TYPE_INT, {.i64 = 0},
 +        0, 1, AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_DECODING_PARAM},
 +    {"use_mfra_for",
 +        "use mfra for fragment timestamps",
 +        offsetof(MOVContext, use_mfra_for), FF_OPT_TYPE_INT, {.i64 = FF_MOV_FLAG_MFRA_AUTO},
 +        -1, FF_MOV_FLAG_MFRA_PTS, AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_DECODING_PARAM,
 +        "use_mfra_for"},
 +    {"auto", "auto", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_AUTO}, 0, 0,
 +        AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_DECODING_PARAM, "use_mfra_for" },
 +    {"dts", "dts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_DTS}, 0, 0,
 +        AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_DECODING_PARAM, "use_mfra_for" },
 +    {"pts", "pts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_PTS}, 0, 0,
 +        AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_DECODING_PARAM, "use_mfra_for" },
 +    {NULL}
 +};
 +
 +static const AVClass mov_class = {
 +    .class_name = "mov,mp4,m4a,3gp,3g2,mj2",
 +    .item_name  = av_default_item_name,
 +    .option     = options,
 +    .version    = LIBAVUTIL_VERSION_INT,
 +};
 +
  AVInputFormat ff_mov_demuxer = {
      .name           = "mov,mp4,m4a,3gp,3g2,mj2",
      .long_name      = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
      .read_packet    = mov_read_packet,
      .read_close     = mov_read_close,
      .read_seek      = mov_read_seek,
 +    .priv_class     = &mov_class,
 +    .flags          = AVFMT_NO_BYTE_SEEK,
  };
diff --combined libavformat/mxfdec.c
@@@ -2,20 -2,20 +2,20 @@@
   * MXF demuxer.
   * Copyright (c) 2006 SmartJog S.A., Baptiste Coudurier <baptiste dot coudurier at smartjog dot com>
   *
 - * 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 <inttypes.h>
  
  #include "libavutil/aes.h"
 +#include "libavutil/avassert.h"
  #include "libavutil/mathematics.h"
  #include "libavcodec/bytestream.h"
 +#include "libavutil/intreadwrite.h"
 +#include "libavutil/timecode.h"
  #include "avformat.h"
  #include "internal.h"
  #include "mxf.h"
@@@ -72,7 -69,7 +72,7 @@@ typedef enum 
      OP3b,
      OP3c,
      OPAtom,
 -    OPSonyOpt,  /* FATE sample, violates the spec in places */
 +    OPSONYOpt,  /* FATE sample, violates the spec in places */
  } MXFOP;
  
  typedef struct {
@@@ -120,21 -117,6 +120,21 @@@ typedef struct 
  typedef struct {
      UID uid;
      enum MXFMetadataSetType type;
 +    int drop_frame;
 +    int start_frame;
 +    struct AVRational rate;
 +    AVTimecode tc;
 +} MXFTimecodeComponent;
 +
 +typedef struct {
 +    UID uid;
 +    enum MXFMetadataSetType type;
 +    UID input_segment_ref;
 +} MXFPulldownComponent;
 +
 +typedef struct {
 +    UID uid;
 +    enum MXFMetadataSetType type;
      MXFSequence *sequence; /* mandatory, and only one */
      UID sequence_ref;
      int track_id;
@@@ -194,7 -176,6 +194,7 @@@ typedef struct 
      int tracks_count;
      MXFDescriptor *descriptor; /* only one */
      UID descriptor_ref;
 +    char *name;
  } MXFPackage;
  
  typedef struct {
@@@ -256,8 -237,6 +256,8 @@@ typedef struct 
      enum MXFMetadataSetType type;
  } MXFMetadataReadTableEntry;
  
 +static int mxf_read_close(AVFormatContext *s);
 +
  /* partial keys to match */
  static const uint8_t mxf_header_partition_pack_key[]       = { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02 };
  static const uint8_t mxf_essence_element_key[]             = { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01 };
@@@ -291,7 -270,7 +291,7 @@@ static int64_t klv_decode_ber_length(AV
  static int mxf_read_sync(AVIOContext *pb, const uint8_t *key, unsigned size)
  {
      int i, b;
 -    for (i = 0; i < size && !pb->eof_reached; i++) {
 +    for (i = 0; i < size && !avio_feof(pb); i++) {
          b = avio_r8(pb);
          if (b == key[0])
              i = 0;
@@@ -428,18 -407,12 +428,18 @@@ static int mxf_read_primer_pack(void *a
          avpriv_request_sample(pb, "Primer pack item length %d", item_len);
          return AVERROR_PATCHWELCOME;
      }
 -    if (item_num > UINT_MAX / item_len)
 +    if (item_num > 65536) {
 +        av_log(mxf->fc, AV_LOG_ERROR, "item_num %d is too large\n", item_num);
          return AVERROR_INVALIDDATA;
 -    mxf->local_tags_count = item_num;
 -    mxf->local_tags = av_malloc(item_num*item_len);
 +    }
 +    if (mxf->local_tags)
 +        av_log(mxf->fc, AV_LOG_VERBOSE, "Multiple primer packs\n");
 +    av_free(mxf->local_tags);
 +    mxf->local_tags_count = 0;
 +    mxf->local_tags = av_calloc(item_num, item_len);
      if (!mxf->local_tags)
          return AVERROR(ENOMEM);
 +    mxf->local_tags_count = item_num;
      avio_read(pb, mxf->local_tags, item_num*item_len);
      return 0;
  }
  static int mxf_read_partition_pack(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
  {
      MXFContext *mxf = arg;
 -    MXFPartition *partition;
 +    MXFPartition *partition, *tmp_part;
      UID op;
      uint64_t footer_partition;
      uint32_t nb_essence_containers;
 -    int err;
  
 -    if ((err = av_reallocp_array(&mxf->partitions, mxf->partitions_count + 1,
 -                                 sizeof(*mxf->partitions))) < 0) {
 -        mxf->partitions_count = 0;
 -        return err;
 -    }
 +    tmp_part = av_realloc_array(mxf->partitions, mxf->partitions_count + 1, sizeof(*mxf->partitions));
 +    if (!tmp_part)
 +        return AVERROR(ENOMEM);
 +    mxf->partitions = tmp_part;
  
      if (mxf->parsing_backward) {
          /* insert the new partition pack in the middle
      partition->index_sid = avio_rb32(pb);
      avio_skip(pb, 8);
      partition->body_sid = avio_rb32(pb);
 -    avio_read(pb, op, sizeof(UID));
 +    if (avio_read(pb, op, sizeof(UID)) != sizeof(UID)) {
 +        av_log(mxf->fc, AV_LOG_ERROR, "Failed reading UID\n");
 +        return AVERROR_INVALIDDATA;
 +    }
      nb_essence_containers = avio_rb32(pb);
  
      if (partition->this_partition &&
      else if (op[12] == 3 && op[13] == 1) mxf->op = OP3a;
      else if (op[12] == 3 && op[13] == 2) mxf->op = OP3b;
      else if (op[12] == 3 && op[13] == 3) mxf->op = OP3c;
 -    else if (op[12] == 64&& op[13] == 1) mxf->op = OPSonyOpt;
 +    else if (op[12] == 64&& op[13] == 1) mxf->op = OPSONYOpt;
      else if (op[12] == 0x10) {
          /* SMPTE 390m: "There shall be exactly one essence container"
           * The following block deals with files that violate this, namely:
          av_log(mxf->fc, AV_LOG_WARNING, "invalid KAGSize %"PRId32" - guessing ",
                 partition->kag_size);
  
 -        if (mxf->op == OPSonyOpt)
 +        if (mxf->op == OPSONYOpt)
              partition->kag_size = 512;
          else
              partition->kag_size = 1;
  
  static int mxf_add_metadata_set(MXFContext *mxf, void *metadata_set)
  {
 -    int err;
 +    MXFMetadataSet **tmp;
  
 -    if ((err = av_reallocp_array(&mxf->metadata_sets, mxf->metadata_sets_count + 1,
 -                                 sizeof(*mxf->metadata_sets))) < 0) {
 -        mxf->metadata_sets_count = 0;
 -        return err;
 -    }
 +    tmp = av_realloc_array(mxf->metadata_sets, mxf->metadata_sets_count + 1, sizeof(*mxf->metadata_sets));
 +    if (!tmp)
 +        return AVERROR(ENOMEM);
 +    mxf->metadata_sets = tmp;
      mxf->metadata_sets[mxf->metadata_sets_count] = metadata_set;
      mxf->metadata_sets_count++;
      return 0;
@@@ -630,11 -603,10 +630,11 @@@ static int mxf_read_content_storage(voi
      MXFContext *mxf = arg;
      switch (tag) {
      case 0x1901:
 +        if (mxf->packages_refs)
 +            av_log(mxf->fc, AV_LOG_VERBOSE, "Multiple packages_refs\n");
 +        av_free(mxf->packages_refs);
          mxf->packages_count = avio_rb32(pb);
 -        if (mxf->packages_count >= UINT_MAX / sizeof(UID))
 -            return AVERROR_INVALIDDATA;
 -        mxf->packages_refs = av_malloc(mxf->packages_count * sizeof(UID));
 +        mxf->packages_refs = av_calloc(mxf->packages_count, sizeof(UID));
          if (!mxf->packages_refs)
              return AVERROR(ENOMEM);
          avio_skip(pb, 4); /* useless size of objects, always 16 according to specs */
@@@ -672,7 -644,9 +672,7 @@@ static int mxf_read_material_package(vo
      switch(tag) {
      case 0x4403:
          package->tracks_count = avio_rb32(pb);
 -        if (package->tracks_count >= UINT_MAX / sizeof(UID))
 -            return AVERROR_INVALIDDATA;
 -        package->tracks_refs = av_malloc(package->tracks_count * sizeof(UID));
 +        package->tracks_refs = av_calloc(package->tracks_count, sizeof(UID));
          if (!package->tracks_refs)
              return AVERROR(ENOMEM);
          avio_skip(pb, 4); /* useless size of objects, always 16 according to specs */
      return 0;
  }
  
 +static int mxf_read_timecode_component(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
 +{
 +    MXFTimecodeComponent *mxf_timecode = arg;
 +    switch(tag) {
 +    case 0x1501:
 +        mxf_timecode->start_frame = avio_rb64(pb);
 +        break;
 +    case 0x1502:
 +        mxf_timecode->rate = (AVRational){avio_rb16(pb), 1};
 +        break;
 +    case 0x1503:
 +        mxf_timecode->drop_frame = avio_r8(pb);
 +        break;
 +    }
 +    return 0;
 +}
 +
 +static int mxf_read_pulldown_component(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
 +{
 +    MXFPulldownComponent *mxf_pulldown = arg;
 +    switch(tag) {
 +    case 0x0d01:
 +        avio_read(pb, mxf_pulldown->input_segment_ref, 16);
 +        break;
 +    }
 +    return 0;
 +}
 +
  static int mxf_read_track(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
  {
      MXFTrack *track = arg;
@@@ -746,7 -692,9 +746,7 @@@ static int mxf_read_sequence(void *arg
          break;
      case 0x1001:
          sequence->structural_components_count = avio_rb32(pb);
 -        if (sequence->structural_components_count >= UINT_MAX / sizeof(UID))
 -            return AVERROR_INVALIDDATA;
 -        sequence->structural_components_refs = av_malloc(sequence->structural_components_count * sizeof(UID));
 +        sequence->structural_components_refs = av_calloc(sequence->structural_components_count, sizeof(UID));
          if (!sequence->structural_components_refs)
              return AVERROR(ENOMEM);
          avio_skip(pb, 4); /* useless size of objects, always 16 according to specs */
      return 0;
  }
  
 +static int mxf_read_utf16_string(AVIOContext *pb, int size, char** str)
 +{
 +    int ret;
 +    size_t buf_size;
 +
 +    if (size < 0)
 +        return AVERROR(EINVAL);
 +
 +    buf_size = size + size / 2 + 1;
 +    *str = av_malloc(buf_size);
 +    if (!*str)
 +        return AVERROR(ENOMEM);
 +
 +    if ((ret = avio_get_str16be(pb, size, *str, buf_size)) < 0) {
 +        av_freep(str);
 +        return ret;
 +    }
 +
 +    return ret;
 +}
 +
  static int mxf_read_source_package(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
  {
      MXFPackage *package = arg;
      switch(tag) {
      case 0x4403:
          package->tracks_count = avio_rb32(pb);
 -        if (package->tracks_count >= UINT_MAX / sizeof(UID))
 -            return AVERROR_INVALIDDATA;
 -        package->tracks_refs = av_malloc(package->tracks_count * sizeof(UID));
 +        package->tracks_refs = av_calloc(package->tracks_count, sizeof(UID));
          if (!package->tracks_refs)
              return AVERROR(ENOMEM);
          avio_skip(pb, 4); /* useless size of objects, always 16 according to specs */
      case 0x4701:
          avio_read(pb, package->descriptor_ref, 16);
          break;
 +    case 0x4402:
 +        return mxf_read_utf16_string(pb, size, &package->name);
      }
      return 0;
  }
@@@ -808,13 -735,29 +808,13 @@@ static int mxf_read_index_entry_array(A
      int i, length;
  
      segment->nb_index_entries = avio_rb32(pb);
 -    if (!segment->nb_index_entries)
 -        return 0;
 -    else if (segment->nb_index_entries < 0 ||
 -             segment->nb_index_entries >
 -             (INT_MAX / sizeof(*segment->stream_offset_entries)))
 -        return AVERROR(ENOMEM);
  
      length = avio_rb32(pb);
  
 -    segment->temporal_offset_entries = av_mallocz(segment->nb_index_entries *
 -                                 sizeof(*segment->temporal_offset_entries));
 -    segment->flag_entries            = av_mallocz(segment->nb_index_entries *
 -                                 sizeof(*segment->flag_entries));
 -    segment->stream_offset_entries   = av_mallocz(segment->nb_index_entries *
 -                                 sizeof(*segment->stream_offset_entries));
 -
 -    if (!segment->flag_entries || !segment->stream_offset_entries ||
 -        !segment->temporal_offset_entries) {
 -        av_freep(&segment->flag_entries);
 -        av_freep(&segment->stream_offset_entries);
 -        av_freep(&segment->temporal_offset_entries);
 +    if (!(segment->temporal_offset_entries=av_calloc(segment->nb_index_entries, sizeof(*segment->temporal_offset_entries))) ||
 +        !(segment->flag_entries          = av_calloc(segment->nb_index_entries, sizeof(*segment->flag_entries))) ||
 +        !(segment->stream_offset_entries = av_calloc(segment->nb_index_entries, sizeof(*segment->stream_offset_entries))))
          return AVERROR(ENOMEM);
 -    }
  
      for (i = 0; i < segment->nb_index_entries; i++) {
          segment->temporal_offset_entries[i] = avio_r8(pb);
@@@ -866,18 -809,17 +866,18 @@@ static int mxf_read_index_table_segment
  static void mxf_read_pixel_layout(AVIOContext *pb, MXFDescriptor *descriptor)
  {
      int code, value, ofs = 0;
 -    char layout[16] = {0};
 +    char layout[16] = {0}; /* not for printing, may end up not terminated on purpose */
  
      do {
          code = avio_r8(pb);
          value = avio_r8(pb);
          av_dlog(NULL, "pixel layout: code %#x\n", code);
  
 -        if (ofs < 16) {
 +        if (ofs <= 14) {
              layout[ofs++] = code;
              layout[ofs++] = value;
 -        }
 +        } else
 +            break;  /* don't read byte by byte on sneaky files filled with lots of non-zeroes */
      } while (code != 0); /* SMPTE 377M E.2.46 */
  
      ff_mxf_decode_pixel_layout(layout, &descriptor->pix_fmt);
@@@ -890,7 -832,9 +890,7 @@@ static int mxf_read_generic_descriptor(
      switch(tag) {
      case 0x3F01:
          descriptor->sub_descriptors_count = avio_rb32(pb);
 -        if (descriptor->sub_descriptors_count >= UINT_MAX / sizeof(UID))
 -            return AVERROR_INVALIDDATA;
 -        descriptor->sub_descriptors_refs = av_malloc(descriptor->sub_descriptors_count * sizeof(UID));
 +        descriptor->sub_descriptors_refs = av_calloc(descriptor->sub_descriptors_count, sizeof(UID));
          if (!descriptor->sub_descriptors_refs)
              return AVERROR(ENOMEM);
          avio_skip(pb, 4); /* useless size of objects, always 16 according to specs */
      default:
          /* Private uid used by SONY C0023S01.mxf */
          if (IS_KLV_KEY(uid, mxf_sony_mpeg4_extradata)) {
 +            if (descriptor->extradata)
 +                av_log(NULL, AV_LOG_WARNING, "Duplicate sony_mpeg4_extradata\n");
              av_free(descriptor->extradata);
              descriptor->extradata_size = 0;
 -            descriptor->extradata = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE);
 +            descriptor->extradata = av_malloc(size);
              if (!descriptor->extradata)
                  return AVERROR(ENOMEM);
              descriptor->extradata_size = size;
@@@ -1036,10 -978,10 +1036,10 @@@ static const MXFCodecUL mxf_sound_essen
  
  static const MXFCodecUL mxf_data_essence_container_uls[] = {
      { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x09,0x0d,0x01,0x03,0x01,0x02,0x0e,0x00,0x00 }, 16, 0 },
 -    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x09,0x0d,0x01,0x03,0x01,0x02,0x0e,0x00,0x00 }, 16, AV_CODEC_ID_NONE },
 +    { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },  0, AV_CODEC_ID_NONE },
  };
  
 -static const char* mxf_data_essence_descriptor[] = {
 +static const char* const mxf_data_essence_descriptor[] = {
      "vbi_vanc_smpte_436M",
  };
  
@@@ -1057,8 -999,9 +1057,8 @@@ static int mxf_get_sorted_table_segment
      if (!nb_segments)
          return AVERROR_INVALIDDATA;
  
 -    *sorted_segments  = av_mallocz(nb_segments * sizeof(**sorted_segments));
 -    unsorted_segments = av_mallocz(nb_segments * sizeof(*unsorted_segments));
 -    if (!*sorted_segments || !unsorted_segments) {
 +    if (!(unsorted_segments = av_calloc(nb_segments, sizeof(*unsorted_segments))) ||
 +        !(*sorted_segments  = av_calloc(nb_segments, sizeof(**sorted_segments)))) {
          av_freep(sorted_segments);
          av_free(unsorted_segments);
          return AVERROR(ENOMEM);
@@@ -1230,8 -1173,14 +1230,8 @@@ static int mxf_compute_ptses_fake_index
      if (index_table->nb_ptses <= 0)
          return 0;
  
 -    if (index_table->nb_ptses > INT_MAX / sizeof(AVIndexEntry))
 -        return AVERROR(ENOMEM);
 -
 -    index_table->ptses      = av_mallocz(index_table->nb_ptses *
 -                                         sizeof(int64_t));
 -    index_table->fake_index = av_mallocz(index_table->nb_ptses *
 -                                         sizeof(AVIndexEntry));
 -    if (!index_table->ptses || !index_table->fake_index) {
 +    if (!(index_table->ptses      = av_calloc(index_table->nb_ptses, sizeof(int64_t))) ||
 +        !(index_table->fake_index = av_calloc(index_table->nb_ptses, sizeof(AVIndexEntry)))) {
          av_freep(&index_table->ptses);
          return AVERROR(ENOMEM);
      }
@@@ -1406,101 -1355,12 +1406,101 @@@ finish_decoding_index
      return ret;
  }
  
 -static int mxf_is_intra_only(MXFDescriptor *d)
 +static int mxf_is_intra_only(MXFDescriptor *descriptor)
  {
      return mxf_get_codec_ul(mxf_intra_only_essence_container_uls,
 -                            &d->essence_container_ul)->id != AV_CODEC_ID_NONE ||
 +                            &descriptor->essence_container_ul)->id != AV_CODEC_ID_NONE ||
             mxf_get_codec_ul(mxf_intra_only_picture_essence_coding_uls,
 -                            &d->essence_codec_ul)->id     != AV_CODEC_ID_NONE;
 +                            &descriptor->essence_codec_ul)->id     != AV_CODEC_ID_NONE;
 +}
 +
 +static int mxf_add_timecode_metadata(AVDictionary **pm, const char *key, AVTimecode *tc)
 +{
 +    char buf[AV_TIMECODE_STR_SIZE];
 +    av_dict_set(pm, key, av_timecode_make_string(tc, buf, 0), 0);
 +
 +    return 0;
 +}
 +
 +static int mxf_parse_physical_source_package(MXFContext *mxf, MXFTrack *source_track, AVStream *st)
 +{
 +    MXFPackage *temp_package = NULL;
 +    MXFPackage *physical_package = NULL;
 +    MXFTrack *physical_track = NULL;
 +    MXFStructuralComponent *component = NULL;
 +    MXFStructuralComponent *sourceclip = NULL;
 +    MXFTimecodeComponent *mxf_tc = NULL;
 +    MXFPulldownComponent *mxf_pulldown = NULL;
 +    int i, j, k;
 +    AVTimecode tc;
 +    int flags;
 +    int64_t start_position;
 +
 +    for (i = 0; i < source_track->sequence->structural_components_count; i++) {
 +        component = mxf_resolve_strong_ref(mxf, &source_track->sequence->structural_components_refs[i], SourceClip);
 +        if (!component)
 +            continue;
 +
 +        for (j = 0; j < mxf->packages_count; j++) {
 +            temp_package = mxf_resolve_strong_ref(mxf, &mxf->packages_refs[j], SourcePackage);
 +            if (!temp_package)
 +                continue;
 +            if (!memcmp(temp_package->package_uid, component->source_package_uid, 16)){
 +                physical_package = temp_package;
 +                sourceclip = component;
 +                break;
 +            }
 +        }
 +        if (!physical_package)
 +            break;
 +
 +        /* the name of physical source package is name of the reel or tape */
 +        if (physical_package->name[0])
 +            av_dict_set(&st->metadata, "reel_name", physical_package->name, 0);
 +
 +        /* the source timecode is calculated by adding the start_position of the sourceclip from the file source package track
 +         * to the start_frame of the timecode component located on one of the tracks of the physical source package.
 +         */
 +        for (j = 0; j < physical_package->tracks_count; j++) {
 +            if (!(physical_track = mxf_resolve_strong_ref(mxf, &physical_package->tracks_refs[j], Track))) {
 +                av_log(mxf->fc, AV_LOG_ERROR, "could not resolve source track strong ref\n");
 +                continue;
 +            }
 +
 +            if (!(physical_track->sequence = mxf_resolve_strong_ref(mxf, &physical_track->sequence_ref, Sequence))) {
 +                av_log(mxf->fc, AV_LOG_ERROR, "could not resolve source track sequence strong ref\n");
 +                continue;
 +            }
 +
 +            for (k = 0; k < physical_track->sequence->structural_components_count; k++) {
 +                component = mxf_resolve_strong_ref(mxf, &physical_track->sequence->structural_components_refs[k], TimecodeComponent);
 +                if (!component){
 +                    /* timcode component may be located on a pulldown component */
 +                    component = mxf_resolve_strong_ref(mxf, &physical_track->sequence->structural_components_refs[k], PulldownComponent);
 +                    if (!component)
 +                        continue;
 +                    mxf_pulldown = (MXFPulldownComponent*)component;
 +                    component = mxf_resolve_strong_ref(mxf, &mxf_pulldown->input_segment_ref, TimecodeComponent);
 +                    if (!component)
 +                        continue;
 +                }
 +
 +                mxf_tc = (MXFTimecodeComponent*)component;
 +                flags = mxf_tc->drop_frame == 1 ? AV_TIMECODE_FLAG_DROPFRAME : 0;
 +                /* scale sourceclip start_position to match physical track edit rate */
 +                start_position = av_rescale_q(sourceclip->start_position,
 +                                              physical_track->edit_rate,
 +                                              source_track->edit_rate);
 +
 +                if (av_timecode_init(&tc, mxf_tc->rate, flags, start_position + mxf_tc->start_frame, mxf->fc) == 0) {
 +                    mxf_add_timecode_metadata(&st->metadata, "timecode", &tc);
 +                    return 0;
 +                }
 +            }
 +        }
 +    }
 +
 +    return 0;
  }
  
  static int mxf_parse_structural_metadata(MXFContext *mxf)
          MXFTrack *temp_track = NULL;
          MXFDescriptor *descriptor = NULL;
          MXFStructuralComponent *component = NULL;
 +        MXFTimecodeComponent *mxf_tc = NULL;
          UID *essence_container_ul = NULL;
          const MXFCodecUL *codec_ul = NULL;
          const MXFCodecUL *container_ul = NULL;
          const MXFCodecUL *pix_fmt_ul = NULL;
          AVStream *st;
 +        AVTimecode tc;
 +        int flags;
  
          if (!(material_track = mxf_resolve_strong_ref(mxf, &material_package->tracks_refs[i], Track))) {
              av_log(mxf->fc, AV_LOG_ERROR, "could not resolve material track strong ref\n");
              continue;
          }
  
 +        if ((component = mxf_resolve_strong_ref(mxf, &material_track->sequence_ref, TimecodeComponent))) {
 +            mxf_tc = (MXFTimecodeComponent*)component;
 +            flags = mxf_tc->drop_frame == 1 ? AV_TIMECODE_FLAG_DROPFRAME : 0;
 +            if (av_timecode_init(&tc, mxf_tc->rate, flags, mxf_tc->start_frame, mxf->fc) == 0) {
 +                mxf_add_timecode_metadata(&mxf->fc->metadata, "timecode", &tc);
 +            }
 +        }
 +
          if (!(material_track->sequence = mxf_resolve_strong_ref(mxf, &material_track->sequence_ref, Sequence))) {
              av_log(mxf->fc, AV_LOG_ERROR, "could not resolve material track sequence strong ref\n");
              continue;
          }
  
 +        for (j = 0; j < material_track->sequence->structural_components_count; j++) {
 +            component = mxf_resolve_strong_ref(mxf, &material_track->sequence->structural_components_refs[j], TimecodeComponent);
 +            if (!component)
 +                continue;
 +
 +            mxf_tc = (MXFTimecodeComponent*)component;
 +            flags = mxf_tc->drop_frame == 1 ? AV_TIMECODE_FLAG_DROPFRAME : 0;
 +            if (av_timecode_init(&tc, mxf_tc->rate, flags, mxf_tc->start_frame, mxf->fc) == 0) {
 +                mxf_add_timecode_metadata(&mxf->fc->metadata, "timecode", &tc);
 +                break;
 +            }
 +        }
 +
          /* TODO: handle multiple source clips */
          for (j = 0; j < material_track->sequence->structural_components_count; j++) {
 -            /* TODO: handle timecode component */
              component = mxf_resolve_strong_ref(mxf, &material_track->sequence->structural_components_refs[j], SourceClip);
              if (!component)
                  continue;
  
          /* TODO: drop PictureEssenceCoding and SoundEssenceCompression, only check EssenceContainer */
          codec_ul = mxf_get_codec_ul(ff_mxf_codec_uls, &descriptor->essence_codec_ul);
 -        st->codec->codec_id = codec_ul->id;
 +        st->codec->codec_id = (enum AVCodecID)codec_ul->id;
 +        av_log(mxf->fc, AV_LOG_VERBOSE, "%s: Universal Label: ",
 +               avcodec_get_name(st->codec->codec_id));
 +        for (k = 0; k < 16; k++) {
 +            av_log(mxf->fc, AV_LOG_VERBOSE, "%.2x",
 +                   descriptor->essence_codec_ul[k]);
 +            if (!(k+1 & 19) || k == 5)
 +                av_log(mxf->fc, AV_LOG_VERBOSE, ".");
 +        }
 +        av_log(mxf->fc, AV_LOG_VERBOSE, "\n");
 +
 +        mxf_parse_physical_source_package(mxf, source_track, st);
  
          if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
              source_track->intra_only = mxf_is_intra_only(descriptor);
              if (st->codec->codec_id == AV_CODEC_ID_NONE)
                  st->codec->codec_id = container_ul->id;
              st->codec->width = descriptor->width;
 -            /* Field height, not frame height */
 -            st->codec->height = descriptor->height;
 +            st->codec->height = descriptor->height; /* Field height, not frame height */
              switch (descriptor->frame_layout) {
                  case SegmentedFrame:
                      /* This one is a weird layout I don't fully understand. */
 -                    av_log(mxf->fc, AV_LOG_INFO,
 -                           "SegmentedFrame layout isn't currently supported\n");
 +                    av_log(mxf->fc, AV_LOG_INFO, "SegmentedFrame layout isn't currently supported\n");
                      break;
                  case FullFrame:
                      st->codec->field_order = AV_FIELD_PROGRESSIVE;
                      break;
                  case OneField:
                      /* Every other line is stored and needs to be duplicated. */
 -                    av_log(mxf->fc, AV_LOG_INFO,
 -                           "OneField frame layout isn't currently supported\n");
 +                    av_log(mxf->fc, AV_LOG_INFO, "OneField frame layout isn't currently supported\n");
 +                    break; /* The correct thing to do here is fall through, but by breaking we might be
 +                              able to decode some streams at half the vertical resolution, rather than not al all.
 +                              It's also for compatibility with the old behavior. */
 +                case MixedFields:
                      break;
 -                    /* The correct thing to do here is fall through, but by
 -                     * breaking we might be able to decode some streams at half
 -                     * the vertical resolution, rather than not al all.
 -                     * It's also for compatibility with the old behavior. */
                  case SeparateFields:
 -                case MixedFields:
                      switch (descriptor->field_dominance) {
                      case MXF_TFF:
                          st->codec->field_order = AV_FIELD_TT;
                      st->codec->height *= 2;
                      break;
                  default:
 -                    av_log(mxf->fc, AV_LOG_INFO,
 -                           "Unknown frame layout type: %d\n",
 -                           descriptor->frame_layout);
 +                    av_log(mxf->fc, AV_LOG_INFO, "Unknown frame layout type: %d\n", descriptor->frame_layout);
              }
              if (st->codec->codec_id == AV_CODEC_ID_RAWVIDEO) {
                  st->codec->pix_fmt = descriptor->pix_fmt;
                  if (st->codec->pix_fmt == AV_PIX_FMT_NONE) {
                      pix_fmt_ul = mxf_get_codec_ul(ff_mxf_pixel_format_uls,
                                                    &descriptor->essence_codec_ul);
 -                    st->codec->pix_fmt = pix_fmt_ul->id;
 +                    st->codec->pix_fmt = (enum AVPixelFormat)pix_fmt_ul->id;
                      if (st->codec->pix_fmt == AV_PIX_FMT_NONE) {
                          /* support files created before RP224v10 by defaulting to UYVY422
                             if subsampling is 4:2:2 and component depth is 8-bit */
              }
              st->need_parsing = AVSTREAM_PARSE_HEADERS;
              if (material_track->sequence->origin) {
 -                char material_origin[3];
 -                snprintf(material_origin, sizeof(material_origin), "%d", material_track->sequence->origin);
 -                av_dict_set(&st->metadata, "material_track_origin", material_origin, 0);
 +                av_dict_set_int(&st->metadata, "material_track_origin", material_track->sequence->origin, 0);
              }
              if (source_track->sequence->origin) {
 -                char source_origin[3];
 -                snprintf(source_origin, sizeof(source_origin), "%d", source_track->sequence->origin);
 -                av_dict_set(&st->metadata, "source_track_origin", source_origin, 0);
 +                av_dict_set_int(&st->metadata, "source_track_origin", source_track->sequence->origin, 0);
              }
          } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
              container_ul = mxf_get_codec_ul(mxf_sound_essence_container_uls, essence_container_ul);
 -            if (st->codec->codec_id == AV_CODEC_ID_NONE)
 -                st->codec->codec_id = container_ul->id;
 +            /* Only overwrite existing codec ID if it is unset or A-law, which is the default according to SMPTE RP 224. */
 +            if (st->codec->codec_id == AV_CODEC_ID_NONE || (st->codec->codec_id == AV_CODEC_ID_PCM_ALAW && (enum AVCodecID)container_ul->id != AV_CODEC_ID_NONE))
 +                st->codec->codec_id = (enum AVCodecID)container_ul->id;
              st->codec->channels = descriptor->channels;
              st->codec->bits_per_coded_sample = descriptor->bits_per_sample;
  
              }
          }
          if (descriptor->extradata) {
 -            st->codec->extradata = av_mallocz(descriptor->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
 -            if (st->codec->extradata) {
 +            if (!ff_alloc_extradata(st->codec, descriptor->extradata_size)) {
                  memcpy(st->codec->extradata, descriptor->extradata, descriptor->extradata_size);
 -                st->codec->extradata_size = descriptor->extradata_size;
              }
          } else if (st->codec->codec_id == AV_CODEC_ID_H264) {
              ret = ff_generate_avci_extradata(st);
@@@ -1837,6 -1674,27 +1837,6 @@@ fail_and_free
      return ret;
  }
  
 -static int mxf_read_utf16_string(AVIOContext *pb, int size, char** str)
 -{
 -    int ret;
 -    size_t buf_size;
 -
 -    if (size < 0)
 -        return AVERROR(EINVAL);
 -
 -    buf_size = size + size / 2 + 1;
 -    *str = av_malloc(buf_size);
 -    if (!*str)
 -        return AVERROR(ENOMEM);
 -
 -    if ((ret = avio_get_str16be(pb, size, *str, buf_size)) < 0) {
 -        av_freep(str);
 -        return ret;
 -    }
 -
 -    return ret;
 -}
 -
  static int mxf_uid_to_str(UID uid, char **str)
  {
      int i;
@@@ -1877,7 -1735,8 +1877,8 @@@ static int mxf_timestamp_to_str(uint64_
      *str = av_mallocz(32);
      if (!*str)
          return AVERROR(ENOMEM);
-     strftime(*str, 32, "%Y-%m-%d %H:%M:%S", &time);
+     if (!strftime(*str, 32, "%Y-%m-%d %H:%M:%S", &time))
+         str[0] = '\0';
  
      return 0;
  }
@@@ -1941,6 -1800,7 +1942,6 @@@ static int mxf_read_identification_meta
  
  static const MXFMetadataReadTableEntry mxf_metadata_read_table[] = {
      { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x05,0x01,0x00 }, mxf_read_primer_pack },
 -//    { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x2f,0x00 }, mxf_read_preface_pack },
      { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02,0x01,0x00 }, mxf_read_partition_pack },
      { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02,0x02,0x00 }, mxf_read_partition_pack },
      { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02,0x03,0x00 }, mxf_read_partition_pack },
      { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x18,0x00 }, mxf_read_content_storage, 0, AnyType },
      { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x37,0x00 }, mxf_read_source_package, sizeof(MXFPackage), SourcePackage },
      { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x36,0x00 }, mxf_read_material_package, sizeof(MXFPackage), MaterialPackage },
 -    { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x0F,0x00 }, mxf_read_sequence, sizeof(MXFSequence), Sequence },
 +    { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x0f,0x00 }, mxf_read_sequence, sizeof(MXFSequence), Sequence },
      { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x11,0x00 }, mxf_read_source_clip, sizeof(MXFStructuralComponent), SourceClip },
      { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x44,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), MultipleDescriptor },
      { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x42,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* Generic Sound */
      { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x5e,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* MPEG2AudioDescriptor */
      { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x3A,0x00 }, mxf_read_track, sizeof(MXFTrack), Track }, /* Static Track */
      { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x3B,0x00 }, mxf_read_track, sizeof(MXFTrack), Track }, /* Generic Track */
 +    { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x14,0x00 }, mxf_read_timecode_component, sizeof(MXFTimecodeComponent), TimecodeComponent },
 +    { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x0c,0x00 }, mxf_read_pulldown_component, sizeof(MXFPulldownComponent), PulldownComponent },
      { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x04,0x01,0x02,0x02,0x00,0x00 }, mxf_read_cryptographic_context, sizeof(MXFCryptoContext), CryptoContext },
      { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x10,0x01,0x00 }, mxf_read_index_table_segment, sizeof(MXFIndexTableSegment), IndexTableSegment },
      { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, NULL, 0, AnyType },
@@@ -1984,7 -1842,7 +1985,7 @@@ static int mxf_read_local_tags(MXFConte
  
      if (!ctx)
          return AVERROR(ENOMEM);
 -    while (avio_tell(pb) + 4 < klv_end && !pb->eof_reached) {
 +    while (avio_tell(pb) + 4 < klv_end && !avio_feof(pb)) {
          int ret;
          int tag = avio_rb16(pb);
          int size = avio_rb16(pb); /* KLV specified by 0x53 */
@@@ -2106,7 -1964,8 +2107,7 @@@ static int mxf_parse_handle_partition_o
  }
  
  /**
 - * Figure out the proper offset and length of the essence container
 - * in each partition
 + * Figures out the proper offset and length of the essence container in each partition
   */
  static void mxf_compute_essence_containers(MXFContext *mxf)
  {
@@@ -2146,6 -2005,38 +2147,6 @@@ static int64_t round_to_kag(int64_t pos
      return ret == position ? ret : ret + kag_size;
  }
  
 -static inline void compute_partition_essence_offset(AVFormatContext *s,
 -                                                    MXFContext *mxf,
 -                                                    KLVPacket *klv)
 -{
 -    MXFPartition *cur_part = mxf->current_partition;
 -    /* for OP1a we compute essence_offset
 -     * for OPAtom we point essence_offset after the KL
 -     *     (usually op1a_essence_offset + 20 or 25)
 -     * TODO: for OP1a we could eliminate this entire if statement, always
 -     *       stopping parsing at op1a_essence_offset
 -     *       for OPAtom we still need the actual essence_offset though
 -     *       (the KL's length can vary)
 -     */
 -    int64_t op1a_essence_offset =
 -        round_to_kag(cur_part->this_partition + cur_part->pack_length,
 -                     cur_part->kag_size) +
 -        round_to_kag(cur_part->header_byte_count, cur_part->kag_size) +
 -        round_to_kag(cur_part->index_byte_count, cur_part->kag_size);
 -
 -    if (mxf->op == OPAtom) {
 -        /* point essence_offset to the actual data
 -         * OPAtom has all the essence in one big KLV
 -         */
 -        cur_part->essence_offset = avio_tell(s->pb);
 -        cur_part->essence_length = klv->length;
 -    } else {
 -        /* NOTE: op1a_essence_offset may be less than to klv.offset
 -         * (C0023S01.mxf)  */
 -        cur_part->essence_offset = op1a_essence_offset;
 -    }
 -}
 -
  static int is_pcm(enum AVCodecID codec_id)
  {
      /* we only care about "normal" PCM codecs until we get samples */
@@@ -2215,8 -2106,6 +2216,8 @@@ static int mxf_read_header(AVFormatCont
      MXFContext *mxf = s->priv_data;
      KLVPacket klv;
      int64_t essence_offset = 0;
 +    int64_t last_pos = -1;
 +    uint64_t last_pos_index = 1;
      int ret;
  
      mxf->last_forward_tell = INT64_MAX;
  
      mxf_read_random_index_pack(s);
  
 -    while (!s->pb->eof_reached) {
 -
 +    while (!avio_feof(s->pb)) {
          const MXFMetadataReadTableEntry *metadata;
 -
 +        if (avio_tell(s->pb) == last_pos) {
 +            av_log(mxf->fc, AV_LOG_ERROR, "MXF structure loop detected\n");
 +            return AVERROR_INVALIDDATA;
 +        }
 +        if ((1ULL<<61) % last_pos_index++ == 0)
 +            last_pos = avio_tell(s->pb);
          if (klv_read_packet(&klv, s->pb) < 0) {
              /* EOF - seek to previous partition or stop */
              if(mxf_parse_handle_partition_or_eof(mxf) <= 0)
              IS_KLV_KEY(klv.key, mxf_system_item_key)) {
  
              if (!mxf->current_partition) {
 -                av_log(mxf->fc, AV_LOG_ERROR,
 -                       "found essence prior to first PartitionPack\n");
 +                av_log(mxf->fc, AV_LOG_ERROR, "found essence prior to first PartitionPack\n");
                  return AVERROR_INVALIDDATA;
              }
  
              if (!mxf->current_partition->essence_offset) {
 -                compute_partition_essence_offset(s, mxf, &klv);
 +                /* for OP1a we compute essence_offset
 +                 * for OPAtom we point essence_offset after the KL (usually op1a_essence_offset + 20 or 25)
 +                 * TODO: for OP1a we could eliminate this entire if statement, always stopping parsing at op1a_essence_offset
 +                 *       for OPAtom we still need the actual essence_offset though (the KL's length can vary)
 +                 */
 +                int64_t op1a_essence_offset =
 +                    round_to_kag(mxf->current_partition->this_partition +
 +                                 mxf->current_partition->pack_length,       mxf->current_partition->kag_size) +
 +                    round_to_kag(mxf->current_partition->header_byte_count, mxf->current_partition->kag_size) +
 +                    round_to_kag(mxf->current_partition->index_byte_count,  mxf->current_partition->kag_size);
 +
 +                if (mxf->op == OPAtom) {
 +                    /* point essence_offset to the actual data
 +                    * OPAtom has all the essence in one big KLV
 +                    */
 +                    mxf->current_partition->essence_offset = avio_tell(s->pb);
 +                    mxf->current_partition->essence_length = klv.length;
 +                } else {
 +                    /* NOTE: op1a_essence_offset may be less than to klv.offset (C0023S01.mxf)  */
 +                    mxf->current_partition->essence_offset = op1a_essence_offset;
 +                }
              }
  
              if (!essence_offset)
                  }
                  if (res < 0) {
                      av_log(s, AV_LOG_ERROR, "error reading header metadata\n");
 -                    return res;
 +                    ret = res;
 +                    goto fail;
                  }
                  break;
              } else {
      /* we need to do this before computing the index tables
       * to be able to fill in zero IndexDurations with st->duration */
      if ((ret = mxf_parse_structural_metadata(mxf)) < 0)
 -        return ret;
 +        goto fail;
  
      if ((ret = mxf_compute_index_tables(mxf)) < 0)
 -        return ret;
 +        goto fail;
  
      if (mxf->nb_index_tables > 1) {
          /* TODO: look up which IndexSID to use via EssenceContainerData */
                 mxf->nb_index_tables, mxf->index_tables[0].index_sid);
      } else if (mxf->nb_index_tables == 0 && mxf->op == OPAtom) {
          av_log(mxf->fc, AV_LOG_ERROR, "cannot demux OPAtom without an index\n");
 -        return AVERROR_INVALIDDATA;
 +        ret = AVERROR_INVALIDDATA;
 +        goto fail;
      }
  
      mxf_handle_small_eubc(s);
  
      return 0;
 +fail:
 +    mxf_read_close(s);
 +
 +    return ret;
  }
  
  /**
@@@ -2383,9 -2243,11 +2384,9 @@@ static int64_t mxf_set_current_edit_uni
      if (mxf->nb_index_tables <= 0)
          return -1;
  
 -    /* find mxf->current_edit_unit so that the next edit unit starts ahead
 -     * of current_offset */
 +    /* find mxf->current_edit_unit so that the next edit unit starts ahead of current_offset */
      while (mxf->current_edit_unit >= 0) {
 -        if (mxf_edit_unit_absolute_offset(mxf, t, mxf->current_edit_unit + 1,
 -                                          NULL, &next_ofs, 0) < 0)
 +        if (mxf_edit_unit_absolute_offset(mxf, t, mxf->current_edit_unit + 1, NULL, &next_ofs, 0) < 0)
              return -1;
  
          if (next_ofs <= last_ofs) {
          mxf->current_edit_unit++;
      }
  
 -    /* not checking mxf->current_edit_unit >= t->nb_ptses here since CBR files
 -     * may lack IndexEntryArrays */
 +    /* not checking mxf->current_edit_unit >= t->nb_ptses here since CBR files may lack IndexEntryArrays */
      if (mxf->current_edit_unit < 0)
          return -1;
  
@@@ -2441,7 -2304,8 +2442,7 @@@ static int mxf_compute_sample_count(MXF
          size++;
      }
  
 -    if (!size)
 -        return 0;
 +    av_assert2(size);
  
      *sample_count = (mxf->current_edit_unit / size) * (uint64_t)total;
      for (i = 0; i < mxf->current_edit_unit % size; i++) {
@@@ -2462,11 -2326,10 +2463,11 @@@ static int mxf_set_audio_pts(MXFContex
  
      pkt->pts = track->sample_count;
  
 -    if (codec->channels <= 0 || codec->channels * bits_per_sample < 8)
 -        return AVERROR_INVALIDDATA;
 -
 -    track->sample_count += pkt->size / (codec->channels * bits_per_sample / 8);
 +    if (   codec->channels <= 0
 +        || bits_per_sample <= 0
 +        || codec->channels * (int64_t)bits_per_sample < 8)
 +        return AVERROR(EINVAL);
 +    track->sample_count += pkt->size / (codec->channels * (int64_t)bits_per_sample / 8);
      return 0;
  }
  
@@@ -2476,7 -2339,9 +2477,7 @@@ static int mxf_read_packet_old(AVFormat
      MXFContext *mxf = s->priv_data;
      int ret;
  
 -    while (!s->pb->eof_reached) {
 -        if ((ret = klv_read_packet(&klv, s->pb)) < 0)
 -            return ret;
 +    while ((ret = klv_read_packet(&klv, s->pb)) == 0) {
          PRINT_KEY(s, "read packet", klv.key);
          av_dlog(s, "size %"PRIu64" offset %#"PRIx64"\n", klv.length, klv.offset);
          if (IS_KLV_KEY(klv.key, mxf_encrypted_triplet_key)) {
              next_ofs = mxf_set_current_edit_unit(mxf, klv.offset);
  
              if (next_ofs >= 0 && next_klv > next_ofs) {
 -                /* if this check is hit then it's possible OPAtom was treated
 -                 * as OP1a truncate the packet since it's probably very large
 -                 * (>2 GiB is common) */
 +                /* if this check is hit then it's possible OPAtom was treated as OP1a
 +                 * truncate the packet since it's probably very large (>2 GiB is common) */
                  avpriv_request_sample(s,
                                        "OPAtom misinterpreted as OP1a?"
                                        "KLV for edit unit %i extending into "
                   * index table to derive timestamps from */
                  MXFIndexTable *t = &mxf->index_tables[0];
  
 -                if (mxf->nb_index_tables >= 1 &&
 -                    mxf->current_edit_unit < t->nb_ptses) {
 +                if (mxf->nb_index_tables >= 1 && mxf->current_edit_unit < t->nb_ptses) {
                      pkt->dts = mxf->current_edit_unit + t->first_dts;
                      pkt->pts = t->ptses[mxf->current_edit_unit];
                  } else if (track->intra_only) {
                      /* intra-only -> PTS = EditUnit.
 -                     * let utils.c figure out DTS since it can be
 -                     * < PTS if low_delay = 0 (Sony IMX30) */
 +                     * let utils.c figure out DTS since it can be < PTS if low_delay = 0 (Sony IMX30) */
                      pkt->pts = mxf->current_edit_unit;
                  }
              } else if (codec->codec_type == AVMEDIA_TYPE_AUDIO) {
          skip:
              avio_skip(s->pb, klv.length);
      }
 -    return AVERROR_EOF;
 +    return avio_feof(s->pb) ? AVERROR_EOF : ret;
  }
  
  static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt)
      if ((ret64 = avio_seek(s->pb, pos, SEEK_SET)) < 0)
          return ret64;
  
 -        if ((ret = av_get_packet(s->pb, pkt, size)) != size)
 -            return ret < 0 ? ret : AVERROR_EOF;
 +    if ((size = av_get_packet(s->pb, pkt, size)) < 0)
 +        return size;
  
      pkt->stream_index = 0;
  
      return 0;
  }
  
 -
  static int mxf_read_close(AVFormatContext *s)
  {
      MXFContext *mxf = s->priv_data;
          case SourcePackage:
          case MaterialPackage:
              av_freep(&((MXFPackage *)mxf->metadata_sets[i])->tracks_refs);
 +            av_freep(&((MXFPackage *)mxf->metadata_sets[i])->name);
              break;
          case IndexTableSegment:
              seg = (MXFIndexTableSegment *)mxf->metadata_sets[i];
      av_freep(&mxf->aesc);
      av_freep(&mxf->local_tags);
  
 -    for (i = 0; i < mxf->nb_index_tables; i++) {
 -        av_freep(&mxf->index_tables[i].segments);
 -        av_freep(&mxf->index_tables[i].ptses);
 -        av_freep(&mxf->index_tables[i].fake_index);
 +    if (mxf->index_tables) {
 +        for (i = 0; i < mxf->nb_index_tables; i++) {
 +            av_freep(&mxf->index_tables[i].segments);
 +            av_freep(&mxf->index_tables[i].ptses);
 +            av_freep(&mxf->index_tables[i].fake_index);
 +        }
      }
      av_freep(&mxf->index_tables);
  
  }
  
  static int mxf_probe(AVProbeData *p) {
 -    uint8_t *bufp = p->buf;
 -    uint8_t *end = p->buf + p->buf_size;
 +    const uint8_t *bufp = p->buf;
 +    const uint8_t *end = p->buf + p->buf_size;
  
      if (p->buf_size < sizeof(mxf_header_partition_pack_key))
          return 0;
  
      /* Must skip Run-In Sequence and search for MXF header partition pack key SMPTE 377M 5.5 */
      end -= sizeof(mxf_header_partition_pack_key);
 -    for (; bufp < end; bufp++) {
 -        if (IS_KLV_KEY(bufp, mxf_header_partition_pack_key))
 -            return AVPROBE_SCORE_MAX;
 +
 +    for (; bufp < end;) {
 +        if (!((bufp[13] - 1) & 0xF2)){
 +            if (AV_RN32(bufp   ) == AV_RN32(mxf_header_partition_pack_key   ) &&
 +                AV_RN32(bufp+ 4) == AV_RN32(mxf_header_partition_pack_key+ 4) &&
 +                AV_RN32(bufp+ 8) == AV_RN32(mxf_header_partition_pack_key+ 8) &&
 +                AV_RN16(bufp+12) == AV_RN16(mxf_header_partition_pack_key+12))
 +                return AVPROBE_SCORE_MAX;
 +            bufp ++;
 +        } else
 +            bufp += 10;
      }
 +
      return 0;
  }
  
@@@ -2758,7 -2615,7 +2759,7 @@@ static int mxf_read_seek(AVFormatContex
              sample_time = FFMIN(sample_time, source_track->original_duration - 1);
          }
  
 -        if ((ret = mxf_edit_unit_absolute_offset(mxf, t, sample_time, &sample_time, &seekpos, 1)) << 0)
 +        if ((ret = mxf_edit_unit_absolute_offset(mxf, t, sample_time, &sample_time, &seekpos, 1)) < 0)
              return ret;
  
          ff_update_cur_dts(s, st, sample_time);
diff --combined libavformat/wtvdec.c
@@@ -2,20 -2,20 +2,20 @@@
   * Windows Television (WTV) demuxer
   * Copyright (c) 2010-2011 Peter Ross <pross@xvid.org>
   *
 - * 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/channel_layout.h"
  #include "libavutil/intreadwrite.h"
  #include "libavutil/intfloat.h"
 -#include "libavutil/dict.h"
  #include "avformat.h"
  #include "internal.h"
 -#include "riff.h"
 -#include "asf.h"
 +#include "wtv.h"
  #include "mpegts.h"
  
  /* Macros for formating GUIDs */
   *
   */
  
 -#define WTV_SECTOR_BITS    12
 -#define WTV_SECTOR_SIZE    (1 << WTV_SECTOR_BITS)
 -#define WTV_BIGSECTOR_BITS 18
 -
 -#define SHIFT_SECTOR_BITS(a) ((int64_t)(a) << WTV_SECTOR_BITS)
 -
  typedef struct {
 -    AVIOContext *pb_filesystem;  /** file system (AVFormatContext->pb) */
 +    AVIOContext *pb_filesystem;  /**< file system (AVFormatContext->pb) */
  
 -    int sector_bits;     /** sector shift bits; used to convert sector number into pb_filesystem offset */
 -    uint32_t *sectors;   /** file allocation table */
 -    int nb_sectors;      /** number of sectors */
 +    int sector_bits;     /**< sector shift bits; used to convert sector number into pb_filesystem offset */
 +    uint32_t *sectors;   /**< file allocation table */
 +    int nb_sectors;      /**< number of sectors */
  
      int error;
      int64_t position;
@@@ -62,7 -70,7 +62,7 @@@
  
  static int64_t seek_by_sector(AVIOContext *pb, int64_t sector, int64_t offset)
  {
 -    return avio_seek(pb, SHIFT_SECTOR_BITS(sector) + offset, SEEK_SET);
 +    return avio_seek(pb, (sector << WTV_SECTOR_BITS) + offset, SEEK_SET);
  }
  
  /**
@@@ -76,7 -84,7 +76,7 @@@ static int wtvfile_read_packet(void *op
  
      if (wf->error || pb->error)
          return -1;
 -    if (wf->position >= wf->length || pb->eof_reached)
 +    if (wf->position >= wf->length || avio_feof(pb))
          return 0;
  
      buf_size = FFMIN(buf_size, wf->length - wf->position);
@@@ -155,7 -163,6 +155,7 @@@ static AVIOContext * wtvfile_open_secto
      AVIOContext *pb;
      WtvFile *wf;
      uint8_t *buffer;
 +    int64_t size;
  
      if (seek_by_sector(s->pb, first_sector, 0) < 0)
          return NULL;
          }
          wf->sectors[0]  = first_sector;
          wf->nb_sectors  = 1;
 -        wf->sector_bits = WTV_SECTOR_BITS;
      } else if (depth == 1) {
          wf->sectors = av_malloc(WTV_SECTOR_SIZE);
          if (!wf->sectors) {
              return NULL;
          }
          wf->nb_sectors  = read_ints(s->pb, wf->sectors, WTV_SECTOR_SIZE / 4);
 -        wf->sector_bits = length & (1ULL<<63) ? WTV_SECTOR_BITS : WTV_BIGSECTOR_BITS;
      } else if (depth == 2) {
          uint32_t sectors1[WTV_SECTOR_SIZE / 4];
          int nb_sectors1 = read_ints(s->pb, sectors1, WTV_SECTOR_SIZE / 4);
          int i;
  
 -        wf->sectors = av_malloc(SHIFT_SECTOR_BITS(nb_sectors1));
 +        wf->sectors = av_malloc_array(nb_sectors1, 1 << WTV_SECTOR_BITS);
          if (!wf->sectors) {
              av_free(wf);
              return NULL;
                  break;
              wf->nb_sectors += read_ints(s->pb, wf->sectors + i * WTV_SECTOR_SIZE / 4, WTV_SECTOR_SIZE / 4);
          }
 -        wf->sector_bits = length & (1ULL<<63) ? WTV_SECTOR_BITS : WTV_BIGSECTOR_BITS;
      } else {
          av_log(s, AV_LOG_ERROR, "unsupported file allocation table depth (0x%x)\n", depth);
          av_free(wf);
          return NULL;
      }
 +    wf->sector_bits = length & (1ULL<<63) ? WTV_SECTOR_BITS : WTV_BIGSECTOR_BITS;
  
      if (!wf->nb_sectors) {
          av_free(wf->sectors);
          return NULL;
      }
  
 +    size = avio_size(s->pb);
 +    if (size >= 0 && (int64_t)wf->sectors[wf->nb_sectors - 1] << WTV_SECTOR_BITS > size)
 +        av_log(s, AV_LOG_WARNING, "truncated file\n");
 +
      /* check length */
      length &= 0xFFFFFFFFFFFF;
      if (length > ((int64_t)wf->nb_sectors << wf->sector_bits)) {
      return pb;
  }
  
 -static const ff_asf_guid dir_entry_guid =
 -    {0x92,0xB7,0x74,0x91,0x59,0x70,0x70,0x44,0x88,0xDF,0x06,0x3B,0x82,0xCC,0x21,0x3D};
 -
  /**
   * Open file using filename
   * @param[in]  buf       directory buffer
@@@ -262,7 -270,7 +262,7 @@@ static AVIOContext * wtvfile_open2(AVFo
          int dir_length, name_size, first_sector, depth;
          uint64_t file_length;
          const uint8_t *name;
 -        if (ff_guidcmp(buf, dir_entry_guid)) {
 +        if (ff_guidcmp(buf, ff_dir_entry_guid)) {
              av_log(s, AV_LOG_ERROR, "unknown guid "FF_PRI_GUID", expected dir_entry_guid; "
                     "remaining directory entries ignored\n", FF_ARG_GUID(buf));
              break;
                     "bad filename length, remaining directory entries ignored\n");
              break;
          }
 -        if (48 + name_size > buf_end - buf) {
 +        if (48 + (int64_t)name_size > buf_end - buf) {
              av_log(s, AV_LOG_ERROR, "filename exceeds buffer size; remaining directory entries ignored\n");
              break;
          }
@@@ -304,8 -312,8 +304,8 @@@ static void wtvfile_close(AVIOContext *
  {
      WtvFile *wf = pb->opaque;
      av_free(wf->sectors);
 -    av_free(wf);
 -    av_free(pb->buffer);
 +    av_freep(&pb->opaque);
 +    av_freep(&pb->buffer);
      av_free(pb);
  }
  
@@@ -320,10 -328,10 +320,10 @@@ typedef struct 
  } WtvStream;
  
  typedef struct {
 -    AVIOContext *pb;       /** timeline file */
 +    AVIOContext *pb;       /**< timeline file */
      int64_t epoch;
 -    int64_t pts;             /** pts for next data chunk */
 -    int64_t last_valid_pts;  /** latest valid pts, used for interative seeking */
 +    int64_t pts;             /**< pts for next data chunk */
 +    int64_t last_valid_pts;  /**< latest valid pts, used for interative seeking */
  
      /* maintain private seek index, as the AVIndexEntry->pos is relative to the
         start of the 'timeline' file, not the file system (AVFormatContext->pb) */
  } WtvContext;
  
  /* WTV GUIDs */
 -static const ff_asf_guid wtv_guid =
 -    {0xB7,0xD8,0x00,0x20,0x37,0x49,0xDA,0x11,0xA6,0x4E,0x00,0x07,0xE9,0x5E,0xAD,0x8D};
 -static const ff_asf_guid metadata_guid =
 -    {0x5A,0xFE,0xD7,0x6D,0xC8,0x1D,0x8F,0x4A,0x99,0x22,0xFA,0xB1,0x1C,0x38,0x14,0x53};
 -static const ff_asf_guid timestamp_guid =
 -    {0x5B,0x05,0xE6,0x1B,0x97,0xA9,0x49,0x43,0x88,0x17,0x1A,0x65,0x5A,0x29,0x8A,0x97};
 -static const ff_asf_guid data_guid =
 -    {0x95,0xC3,0xD2,0xC2,0x7E,0x9A,0xDA,0x11,0x8B,0xF7,0x00,0x07,0xE9,0x5E,0xAD,0x8D};
 -static const ff_asf_guid stream_guid =
 -    {0xED,0xA4,0x13,0x23,0x2D,0xBF,0x4F,0x45,0xAD,0x8A,0xD9,0x5B,0xA7,0xF9,0x1F,0xEE};
 -static const ff_asf_guid stream2_guid =
 -    {0xA2,0xC3,0xD2,0xC2,0x7E,0x9A,0xDA,0x11,0x8B,0xF7,0x00,0x07,0xE9,0x5E,0xAD,0x8D};
  static const ff_asf_guid EVENTID_SubtitleSpanningEvent =
      {0x48,0xC0,0xCE,0x5D,0xB9,0xD0,0x63,0x41,0x87,0x2C,0x4F,0x32,0x22,0x3B,0xE8,0x8A};
  static const ff_asf_guid EVENTID_LanguageSpanningEvent =
@@@ -355,6 -375,10 +355,6 @@@ static const ff_asf_guid EVENTID_AudioT
  /* Windows media GUIDs */
  
  /* Media types */
 -static const ff_asf_guid mediatype_audio =
 -    {'a','u','d','s',FF_MEDIASUBTYPE_BASE_GUID};
 -static const ff_asf_guid mediatype_video =
 -    {'v','i','d','s',FF_MEDIASUBTYPE_BASE_GUID};
  static const ff_asf_guid mediasubtype_mpeg1payload =
      {0x81,0xEB,0x36,0xE4,0x4F,0x52,0xCE,0x11,0x9F,0x53,0x00,0x20,0xAF,0x0B,0xA7,0x70};
  static const ff_asf_guid mediatype_mpeg2_sections =
@@@ -365,6 -389,8 +365,6 @@@ static const ff_asf_guid mediatype_mstv
      {0x89,0x8A,0x8B,0xB8,0x49,0xB0,0x80,0x4C,0xAD,0xCF,0x58,0x98,0x98,0x5E,0x22,0xC1};
  
  /* Media subtypes */
 -static const ff_asf_guid mediasubtype_cpfilters_processed =
 -    {0x28,0xBD,0xAD,0x46,0xD0,0x6F,0x96,0x47,0x93,0xB2,0x15,0x5C,0x51,0xDC,0x04,0x8D};
  static const ff_asf_guid mediasubtype_dvb_subtitle =
      {0xC3,0xCB,0xFF,0x34,0xB3,0xD5,0x71,0x41,0x90,0x02,0xD4,0xC6,0x03,0x01,0x69,0x7F};
  static const ff_asf_guid mediasubtype_teletext =
@@@ -374,51 -400,68 +374,54 @@@ static const ff_asf_guid mediasubtype_d
  static const ff_asf_guid mediasubtype_mpeg2_sections =
      {0x79,0x85,0x9F,0x4A,0xF8,0x6B,0x92,0x43,0x8A,0x6D,0xD2,0xDD,0x09,0xFA,0x78,0x61};
  
 -/* Formats */
 -static const ff_asf_guid format_cpfilters_processed =
 -    {0x6F,0xB3,0x39,0x67,0x5F,0x1D,0xC2,0x4A,0x81,0x92,0x28,0xBB,0x0E,0x73,0xD1,0x6A};
 -static const ff_asf_guid format_waveformatex =
 -    {0x81,0x9F,0x58,0x05,0x56,0xC3,0xCE,0x11,0xBF,0x01,0x00,0xAA,0x00,0x55,0x59,0x5A};
 -static const ff_asf_guid format_videoinfo2 =
 -    {0xA0,0x76,0x2A,0xF7,0x0A,0xEB,0xD0,0x11,0xAC,0xE4,0x00,0x00,0xC0,0xCC,0x16,0xBA};
 -static const ff_asf_guid format_mpeg2_video =
 -    {0xE3,0x80,0x6D,0xE0,0x46,0xDB,0xCF,0x11,0xB4,0xD1,0x00,0x80,0x5F,0x6C,0xBB,0xEA};
 -static const ff_asf_guid format_none =
 -    {0xD6,0x17,0x64,0x0F,0x18,0xC3,0xD0,0x11,0xA4,0x3F,0x00,0xA0,0xC9,0x22,0x31,0x96};
 -
 -static const AVCodecGuid video_guids[] = {
 -    {AV_CODEC_ID_MPEG2VIDEO, {0x26,0x80,0x6D,0xE0,0x46,0xDB,0xCF,0x11,0xB4,0xD1,0x00,0x80,0x5F,0x6C,0xBB,0xEA}},
 -    {AV_CODEC_ID_NONE}
 -};
 -
  static int read_probe(AVProbeData *p)
  {
 -    return ff_guidcmp(p->buf, wtv_guid) ? 0 : AVPROBE_SCORE_MAX;
 +    return ff_guidcmp(p->buf, ff_wtv_guid) ? 0 : AVPROBE_SCORE_MAX;
  }
  
  /**
   * Convert win32 FILETIME to ISO-8601 string
 + * @return <0 on error
   */
 -static void filetime_to_iso8601(char *buf, int buf_size, int64_t value)
 +static int filetime_to_iso8601(char *buf, int buf_size, int64_t value)
  {
      time_t t = (value / 10000000LL) - 11644473600LL;
      struct tm *tm = gmtime(&t);
 -    if (tm) {
 -        if (!strftime(buf, buf_size, "%Y-%m-%d %H:%M:%S", tm))
 -            buf[0] = '\0';
 -    } else
 -        buf[0] = '\0';
 +    if (!tm)
 +        return -1;
-     strftime(buf, buf_size, "%Y-%m-%d %H:%M:%S", tm);
++    if (!strftime(buf, buf_size, "%Y-%m-%d %H:%M:%S", tm))
++        return -1;
 +    return 0;
  }
  
  /**
   * Convert crazy time (100ns since 1 Jan 0001) to ISO-8601 string
 + * @return <0 on error
   */
 -static void crazytime_to_iso8601(char *buf, int buf_size, int64_t value)
 +static int crazytime_to_iso8601(char *buf, int buf_size, int64_t value)
  {
      time_t t = (value / 10000000LL) - 719162LL*86400LL;
      struct tm *tm = gmtime(&t);
 -    if (tm) {
 -        if (!strftime(buf, buf_size, "%Y-%m-%d %H:%M:%S", tm))
 -            buf[0] = '\0';
 -    } else
 -        buf[0] = '\0';
 +    if (!tm)
 +        return -1;
-     strftime(buf, buf_size, "%Y-%m-%d %H:%M:%S", tm);
++    if (!strftime(buf, buf_size, "%Y-%m-%d %H:%M:%S", tm))
++        return -1;
 +    return 0;
  }
  
  /**
   * Convert OLE DATE to ISO-8601 string
 + * @return <0 on error
   */
 -static void oledate_to_iso8601(char *buf, int buf_size, int64_t value)
 +static int oledate_to_iso8601(char *buf, int buf_size, int64_t value)
  {
 -    time_t t = 631112400LL + 86400*av_int2double(value);
 -    struct tm *tm = gmtime(&t);
 -    if (tm) {
 -        if (!strftime(buf, buf_size, "%Y-%m-%d %H:%M:%S", tm))
 -            buf[0] = '\0';
 -    } else
 -        buf[0] = '\0';
 +    time_t t = (av_int2double(value) - 25569.0) * 86400;
 +    struct tm *tm= gmtime(&t);
 +    if (!tm)
 +        return -1;
-     strftime(buf, buf_size, "%Y-%m-%d %H:%M:%S", tm);
++    if (!strftime(buf, buf_size, "%Y-%m-%d %H:%M:%S", tm))
++        return -1;
 +    return 0;
  }
  
  static void get_attachment(AVFormatContext *s, AVIOContext *pb, int length)
      char description[1024];
      unsigned int filesize;
      AVStream *st;
 +    int ret;
      int64_t pos = avio_tell(pb);
  
      avio_get_str16le(pb, INT_MAX, mime, sizeof(mime));
      if (!st)
          goto done;
      av_dict_set(&st->metadata, "title", description, 0);
 +    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
      st->codec->codec_id   = AV_CODEC_ID_MJPEG;
 -    st->codec->codec_type = AVMEDIA_TYPE_ATTACHMENT;
 -    st->codec->extradata  = av_mallocz(filesize);
      st->id = -1;
 -    if (!st->codec->extradata)
 +    ret = av_get_packet(pb, &st->attached_pic, filesize);
 +    if (ret < 0)
          goto done;
 -    st->codec->extradata_size = filesize;
 -    avio_read(pb, st->codec->extradata, filesize);
 +    st->attached_pic.stream_index = st->index;
 +    st->attached_pic.flags       |= AV_PKT_FLAG_KEY;
 +    st->disposition              |= AV_DISPOSITION_ATTACHED_PIC;
  done:
      avio_seek(pb, pos + length, SEEK_SET);
  }
  
  static void get_tag(AVFormatContext *s, AVIOContext *pb, const char *key, int type, int length)
  {
 -    int buf_size = FFMAX(2*length, LEN_PRETTY_GUID) + 1;
 -    char *buf = av_malloc(buf_size);
 +    int buf_size;
 +    char *buf;
 +
 +    if (!strcmp(key, "WM/MediaThumbType")) {
 +        avio_skip(pb, length);
 +        return;
 +    }
 +
 +    buf_size = FFMAX(2*length, LEN_PRETTY_GUID) + 1;
 +    buf = av_malloc(buf_size);
      if (!buf)
          return;
  
      } else if (type == 4 && length == 8) {
          int64_t num = avio_rl64(pb);
          if (!strcmp(key, "WM/EncodingTime") ||
 -            !strcmp(key, "WM/MediaOriginalBroadcastDateTime"))
 -            filetime_to_iso8601(buf, buf_size, num);
 -        else if (!strcmp(key, "WM/WMRVEncodeTime") ||
 -                 !strcmp(key, "WM/WMRVEndTime"))
 -            crazytime_to_iso8601(buf, buf_size, num);
 -        else if (!strcmp(key, "WM/WMRVExpirationDate"))
 -            oledate_to_iso8601(buf, buf_size, num);
 -        else if (!strcmp(key, "WM/WMRVBitrate"))
 +            !strcmp(key, "WM/MediaOriginalBroadcastDateTime")) {
 +            if (filetime_to_iso8601(buf, buf_size, num) < 0) {
 +                av_free(buf);
 +                return;
 +            }
 +        } else if (!strcmp(key, "WM/WMRVEncodeTime") ||
 +                   !strcmp(key, "WM/WMRVEndTime")) {
 +            if (crazytime_to_iso8601(buf, buf_size, num) < 0) {
 +                av_free(buf);
 +                return;
 +            }
 +        } else if (!strcmp(key, "WM/WMRVExpirationDate")) {
 +            if (oledate_to_iso8601(buf, buf_size, num) < 0 ) {
 +                av_free(buf);
 +                return;
 +            }
 +        } else if (!strcmp(key, "WM/WMRVBitrate"))
              snprintf(buf, buf_size, "%f", av_int2double(num));
          else
              snprintf(buf, buf_size, "%"PRIi64, num);
@@@ -533,14 -557,14 +536,14 @@@ static void parse_legacy_attrib(AVForma
  {
      ff_asf_guid guid;
      int length, type;
 -    while(!pb->eof_reached) {
 +    while(!avio_feof(pb)) {
          char key[1024];
          ff_get_guid(pb, &guid);
          type   = avio_rl32(pb);
          length = avio_rl32(pb);
          if (!length)
              break;
 -        if (ff_guidcmp(&guid, metadata_guid)) {
 +        if (ff_guidcmp(&guid, ff_metadata_guid)) {
              av_log(s, AV_LOG_WARNING, "unknown guid "FF_PRI_GUID", expected metadata_guid; "
                     "remaining metadata entries ignored\n", FF_ARG_GUID(guid));
              break;
@@@ -562,7 -586,7 +565,7 @@@ static int parse_videoinfoheader2(AVFor
      AVIOContext *pb = wtv->pb;
  
      avio_skip(pb, 72);  // picture aspect ratio is unreliable
 -    ff_get_bmp_header(pb, st);
 +    st->codec->codec_tag = ff_get_bmp_header(pb, st, NULL);
  
      return 72 + 40;
  }
@@@ -635,12 -659,12 +638,12 @@@ static AVStream * new_stream(AVFormatCo
   */
  static AVStream * parse_media_type(AVFormatContext *s, AVStream *st, int sid,
                                     ff_asf_guid mediatype, ff_asf_guid subtype,
 -                                   ff_asf_guid formattype, int size)
 +                                   ff_asf_guid formattype, uint64_t size)
  {
      WtvContext *wtv = s->priv_data;
      AVIOContext *pb = wtv->pb;
 -    if (!ff_guidcmp(subtype, mediasubtype_cpfilters_processed) &&
 -        !ff_guidcmp(formattype, format_cpfilters_processed)) {
 +    if (!ff_guidcmp(subtype, ff_mediasubtype_cpfilters_processed) &&
 +        !ff_guidcmp(formattype, ff_format_cpfilters_processed)) {
          ff_asf_guid actual_subtype;
          ff_asf_guid actual_formattype;
  
          st = parse_media_type(s, st, sid, mediatype, actual_subtype, actual_formattype, size - 32);
          avio_skip(pb, 32);
          return st;
 -    } else if (!ff_guidcmp(mediatype, mediatype_audio)) {
 +    } else if (!ff_guidcmp(mediatype, ff_mediatype_audio)) {
          st = new_stream(s, st, sid, AVMEDIA_TYPE_AUDIO);
          if (!st)
              return NULL;
 -        if (!ff_guidcmp(formattype, format_waveformatex)) {
 +        if (!ff_guidcmp(formattype, ff_format_waveformatex)) {
              int ret = ff_get_wav_header(pb, st->codec, size);
              if (ret < 0)
                  return NULL;
          } else {
 -            if (ff_guidcmp(formattype, format_none))
 +            if (ff_guidcmp(formattype, ff_format_none))
                  av_log(s, AV_LOG_WARNING, "unknown formattype:"FF_PRI_GUID"\n", FF_ARG_GUID(formattype));
              avio_skip(pb, size);
          }
                  av_log(s, AV_LOG_WARNING, "unknown subtype:"FF_PRI_GUID"\n", FF_ARG_GUID(subtype));
          }
          return st;
 -    } else if (!ff_guidcmp(mediatype, mediatype_video)) {
 +    } else if (!ff_guidcmp(mediatype, ff_mediatype_video)) {
          st = new_stream(s, st, sid, AVMEDIA_TYPE_VIDEO);
          if (!st)
              return NULL;
 -        if (!ff_guidcmp(formattype, format_videoinfo2)) {
 +        if (!ff_guidcmp(formattype, ff_format_videoinfo2)) {
              int consumed = parse_videoinfoheader2(s, st);
              avio_skip(pb, FFMAX(size - consumed, 0));
 -        } else if (!ff_guidcmp(formattype, format_mpeg2_video)) {
 -            int consumed = parse_videoinfoheader2(s, st);
 +        } else if (!ff_guidcmp(formattype, ff_format_mpeg2_video)) {
 +            uint64_t consumed = parse_videoinfoheader2(s, st);
 +            /* ignore extradata; files produced by windows media center contain meaningless mpeg1 sequence header */
              avio_skip(pb, FFMAX(size - consumed, 0));
          } else {
 -            if (ff_guidcmp(formattype, format_none))
 +            if (ff_guidcmp(formattype, ff_format_none))
                  av_log(s, AV_LOG_WARNING, "unknown formattype:"FF_PRI_GUID"\n", FF_ARG_GUID(formattype));
              avio_skip(pb, size);
          }
          if (!memcmp(subtype + 4, (const uint8_t[]){FF_MEDIASUBTYPE_BASE_GUID}, 12)) {
              st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, AV_RL32(subtype));
          } else {
 -            st->codec->codec_id = ff_codec_guid_get_id(video_guids, subtype);
 +            st->codec->codec_id = ff_codec_guid_get_id(ff_video_guids, subtype);
          }
          if (st->codec->codec_id == AV_CODEC_ID_NONE)
              av_log(s, AV_LOG_WARNING, "unknown subtype:"FF_PRI_GUID"\n", FF_ARG_GUID(subtype));
          st = new_stream(s, st, sid, AVMEDIA_TYPE_SUBTITLE);
          if (!st)
              return NULL;
 -        if (ff_guidcmp(formattype, format_none))
 +        if (ff_guidcmp(formattype, ff_format_none))
              av_log(s, AV_LOG_WARNING, "unknown formattype:"FF_PRI_GUID"\n", FF_ARG_GUID(formattype));
          avio_skip(pb, size);
          st->codec->codec_id = AV_CODEC_ID_DVB_SUBTITLE;
          st = new_stream(s, st, sid, AVMEDIA_TYPE_SUBTITLE);
          if (!st)
              return NULL;
 -        if (ff_guidcmp(formattype, format_none))
 +        if (ff_guidcmp(formattype, ff_format_none))
              av_log(s, AV_LOG_WARNING, "unknown formattype:"FF_PRI_GUID"\n", FF_ARG_GUID(formattype));
          avio_skip(pb, size);
 -        st->codec->codec_id   = AV_CODEC_ID_DVB_TELETEXT;
 +        st->codec->codec_id = !ff_guidcmp(subtype, mediasubtype_teletext) ? AV_CODEC_ID_DVB_TELETEXT : AV_CODEC_ID_EIA_608;
          return st;
      } else if (!ff_guidcmp(mediatype, mediatype_mpeg2_sections) &&
                 !ff_guidcmp(subtype, mediasubtype_mpeg2_sections)) {
 -        if (ff_guidcmp(formattype, format_none))
 +        if (ff_guidcmp(formattype, ff_format_none))
              av_log(s, AV_LOG_WARNING, "unknown formattype:"FF_PRI_GUID"\n", FF_ARG_GUID(formattype));
          avio_skip(pb, size);
          return NULL;
@@@ -751,26 -774,6 +754,26 @@@ enum 
  };
  
  /**
 + * Try to seek over a broken chunk
 + * @return <0 on error
 + */
 +static int recover(WtvContext *wtv, uint64_t broken_pos)
 +{
 +    AVIOContext *pb = wtv->pb;
 +    int i;
 +    for (i = 0; i < wtv->nb_index_entries; i++) {
 +        if (wtv->index_entries[i].pos > broken_pos) {
 +            int ret = avio_seek(pb, wtv->index_entries[i].pos, SEEK_SET);
 +            if (ret < 0)
 +                return ret;
 +            wtv->pts = wtv->index_entries[i].timestamp;
 +            return 0;
 +         }
 +     }
 +     return AVERROR(EIO);
 +}
 +
 +/**
   * Parse WTV chunks
   * @param mode SEEK_TO_DATA or SEEK_TO_PTS
   * @param seekts timestamp
@@@ -781,26 -784,19 +784,26 @@@ static int parse_chunks(AVFormatContex
  {
      WtvContext *wtv = s->priv_data;
      AVIOContext *pb = wtv->pb;
 -    while (!pb->eof_reached) {
 +    while (!avio_feof(pb)) {
          ff_asf_guid g;
          int len, sid, consumed;
  
          ff_get_guid(pb, &g);
          len = avio_rl32(pb);
 -        if (len < 32)
 -            break;
 +        if (len < 32) {
 +            int ret;
 +            if (avio_feof(pb))
 +                return AVERROR_EOF;
 +            av_log(s, AV_LOG_WARNING, "encountered broken chunk\n");
 +            if ((ret = recover(wtv, avio_tell(pb) - 20)) < 0)
 +                return ret;
 +            continue;
 +        }
          sid = avio_rl32(pb) & 0x7FFF;
          avio_skip(pb, 8);
          consumed = 32;
  
 -        if (!ff_guidcmp(g, stream_guid)) {
 +        if (!ff_guidcmp(g, ff_SBE2_STREAM_DESC_EVENT)) {
              if (ff_find_stream_index(s, sid) < 0) {
                  ff_asf_guid mediatype, subtype, formattype;
                  int size;
                  parse_media_type(s, 0, sid, mediatype, subtype, formattype, size);
                  consumed += 92 + size;
              }
 -        } else if (!ff_guidcmp(g, stream2_guid)) {
 +        } else if (!ff_guidcmp(g, ff_stream2_guid)) {
              int stream_index = ff_find_stream_index(s, sid);
 -            if (stream_index >= 0 && !((WtvStream*)s->streams[stream_index]->priv_data)->seen_data) {
 +            if (stream_index >= 0 && s->streams[stream_index]->priv_data && !((WtvStream*)s->streams[stream_index]->priv_data)->seen_data) {
                  ff_asf_guid mediatype, subtype, formattype;
                  int size;
                  avio_skip(pb, 12);
                  }
                  consumed += 15;
              }
 -        } else if (!ff_guidcmp(g, timestamp_guid)) {
 +        } else if (!ff_guidcmp(g, ff_timestamp_guid)) {
              int stream_index = ff_find_stream_index(s, sid);
              if (stream_index >= 0) {
                  avio_skip(pb, 8);
                      if (wtv->epoch == AV_NOPTS_VALUE || wtv->pts < wtv->epoch)
                          wtv->epoch = wtv->pts;
                  if (mode == SEEK_TO_PTS && wtv->pts >= seekts) {
 -#define WTV_PAD8(x) (((x) + 7) & ~7)
                      avio_skip(pb, WTV_PAD8(len) - consumed);
                      return 0;
                  }
                  }
              }
 -        } else if (!ff_guidcmp(g, data_guid)) {
 +        } else if (!ff_guidcmp(g, ff_data_guid)) {
              int stream_index = ff_find_stream_index(s, sid);
 -            if (mode == SEEK_TO_DATA && stream_index >= 0 && len > 32) {
 +            if (mode == SEEK_TO_DATA && stream_index >= 0 && len > 32 && s->streams[stream_index]->priv_data) {
                  WtvStream *wst = s->streams[stream_index]->priv_data;
                  wst->seen_data = 1;
                  if (len_ptr) {
                  }
                  return stream_index;
              }
 +        } else if (!ff_guidcmp(g, /* DSATTRIB_WMDRMProtectionInfo */ (const ff_asf_guid){0x83,0x95,0x74,0x40,0x9D,0x6B,0xEC,0x4E,0xB4,0x3C,0x67,0xA1,0x80,0x1E,0x1A,0x9B})) {
 +            int stream_index = ff_find_stream_index(s, sid);
 +            if (stream_index >= 0)
 +                av_log(s, AV_LOG_WARNING, "encrypted stream detected (st:%d), decoding will likely fail\n", stream_index);
          } else if (
              !ff_guidcmp(g, /* DSATTRIB_CAPTURE_STREAMTIME */ (const ff_asf_guid){0x14,0x56,0x1A,0x0C,0xCD,0x30,0x40,0x4F,0xBC,0xBF,0xD0,0x3E,0x52,0x30,0x62,0x07}) ||
 +            !ff_guidcmp(g, /* DSATTRIB_PBDATAG_ATTRIBUTE */ (const ff_asf_guid){0x79,0x66,0xB5,0xE0,0xB9,0x12,0xCC,0x43,0xB7,0xDF,0x57,0x8C,0xAA,0x5A,0x7B,0x63}) ||
              !ff_guidcmp(g, /* DSATTRIB_PicSampleSeq */ (const ff_asf_guid){0x02,0xAE,0x5B,0x2F,0x8F,0x7B,0x60,0x4F,0x82,0xD6,0xE4,0xEA,0x2F,0x1F,0x4C,0x99}) ||
 -            !ff_guidcmp(g, /* DSATTRIB_TRANSPORT_PROPERTIES */ (const ff_asf_guid){0x12,0xF6,0x22,0xB6,0xAD,0x47,0x71,0x46,0xAD,0x6C,0x05,0xA9,0x8E,0x65,0xDE,0x3A}) ||
 +            !ff_guidcmp(g, /* DSATTRIB_TRANSPORT_PROPERTIES */ ff_DSATTRIB_TRANSPORT_PROPERTIES) ||
              !ff_guidcmp(g, /* dvr_ms_vid_frame_rep_data */ (const ff_asf_guid){0xCC,0x32,0x64,0xDD,0x29,0xE2,0xDB,0x40,0x80,0xF6,0xD2,0x63,0x28,0xD2,0x76,0x1F}) ||
              !ff_guidcmp(g, /* EVENTID_ChannelChangeSpanningEvent */ (const ff_asf_guid){0xE5,0xC5,0x67,0x90,0x5C,0x4C,0x05,0x42,0x86,0xC8,0x7A,0xFE,0x20,0xFE,0x1E,0xFA}) ||
              !ff_guidcmp(g, /* EVENTID_ChannelInfoSpanningEvent */ (const ff_asf_guid){0x80,0x6D,0xF3,0x41,0x32,0x41,0xC2,0x4C,0xB1,0x21,0x01,0xA4,0x32,0x19,0xD8,0x1B}) ||
              !ff_guidcmp(g, (const ff_asf_guid){0x4E,0x7F,0x4C,0x5B,0xC4,0xD0,0x38,0x4B,0xA8,0x3E,0x21,0x7F,0x7B,0xBF,0x52,0xE7}) ||
              !ff_guidcmp(g, (const ff_asf_guid){0x63,0x36,0xEB,0xFE,0xA1,0x7E,0xD9,0x11,0x83,0x08,0x00,0x07,0xE9,0x5E,0xAD,0x8D}) ||
              !ff_guidcmp(g, (const ff_asf_guid){0x70,0xE9,0xF1,0xF8,0x89,0xA4,0x4C,0x4D,0x83,0x73,0xB8,0x12,0xE0,0xD5,0xF8,0x1E}) ||
 -            !ff_guidcmp(g, (const ff_asf_guid){0x96,0xC3,0xD2,0xC2,0x7E,0x9A,0xDA,0x11,0x8B,0xF7,0x00,0x07,0xE9,0x5E,0xAD,0x8D}) ||
 -            !ff_guidcmp(g, (const ff_asf_guid){0x97,0xC3,0xD2,0xC2,0x7E,0x9A,0xDA,0x11,0x8B,0xF7,0x00,0x07,0xE9,0x5E,0xAD,0x8D}) ||
 -            !ff_guidcmp(g, (const ff_asf_guid){0xA1,0xC3,0xD2,0xC2,0x7E,0x9A,0xDA,0x11,0x8B,0xF7,0x00,0x07,0xE9,0x5E,0xAD,0x8D})) {
 +            !ff_guidcmp(g, ff_index_guid) ||
 +            !ff_guidcmp(g, ff_sync_guid) ||
 +            !ff_guidcmp(g, ff_stream1_guid) ||
 +            !ff_guidcmp(g, (const ff_asf_guid){0xF7,0x10,0x02,0xB9,0xEE,0x7C,0xED,0x4E,0xBD,0x7F,0x05,0x40,0x35,0x86,0x18,0xA1})) {
              //ignore known guids
          } else
              av_log(s, AV_LOG_WARNING, "unsupported chunk:"FF_PRI_GUID"\n", FF_ARG_GUID(g));
      return AVERROR_EOF;
  }
  
 -/* declare utf16le strings */
 -#define _ , 0,
 -static const uint8_t timeline_le16[] =
 -    {'t'_'i'_'m'_'e'_'l'_'i'_'n'_'e', 0};
 -static const uint8_t table_0_entries_legacy_attrib_le16[] =
 -    {'t'_'a'_'b'_'l'_'e'_'.'_'0'_'.'_'e'_'n'_'t'_'r'_'i'_'e'_'s'_'.'_'l'_'e'_'g'_'a'_'c'_'y'_'_'_'a'_'t'_'t'_'r'_'i'_'b', 0};
 -static const uint8_t table_0_entries_time_le16[] =
 -    {'t'_'a'_'b'_'l'_'e'_'.'_'0'_'.'_'e'_'n'_'t'_'r'_'i'_'e'_'s'_'.'_'t'_'i'_'m'_'e', 0};
 -static const uint8_t timeline_table_0_entries_Events_le16[] =
 -    {'t'_'i'_'m'_'e'_'l'_'i'_'n'_'e'_'.'_'t'_'a'_'b'_'l'_'e'_'.'_'0'_'.'_'e'_'n'_'t'_'r'_'i'_'e'_'s'_'.'_'E'_'v'_'e'_'n'_'t'_'s', 0};
 -#undef _
 -
  static int read_header(AVFormatContext *s)
  {
      WtvContext *wtv = s->priv_data;
          return AVERROR_INVALIDDATA;
  
      /* parse chunks up until first data chunk */
 -    wtv->pb = wtvfile_open(s, root, root_size, timeline_le16);
 +    wtv->pb = wtvfile_open(s, root, root_size, ff_timeline_le16);
      if (!wtv->pb) {
          av_log(s, AV_LOG_ERROR, "timeline data missing\n");
          return AVERROR_INVALIDDATA;
      timeline_pos = avio_tell(s->pb); // save before opening another file
  
      /* read metadata */
 -    pb = wtvfile_open(s, root, root_size, table_0_entries_legacy_attrib_le16);
 +    pb = wtvfile_open(s, root, root_size, ff_table_0_entries_legacy_attrib_le16);
      if (pb) {
          parse_legacy_attrib(s, pb);
          wtvfile_close(pb);
      /* read seek index */
      if (s->nb_streams) {
          AVStream *st = s->streams[0];
 -        pb = wtvfile_open(s, root, root_size, table_0_entries_time_le16);
 +        pb = wtvfile_open(s, root, root_size, ff_table_0_entries_time_le16);
          if (pb) {
              while(1) {
                  uint64_t timestamp = avio_rl64(pb);
                  uint64_t frame_nb  = avio_rl64(pb);
 -                if (pb->eof_reached)
 +                if (avio_feof(pb))
                      break;
                  ff_add_index_entry(&wtv->index_entries, &wtv->nb_index_entries, &wtv->index_entries_allocated_size,
                                     0, timestamp, frame_nb, 0, AVINDEX_KEYFRAME);
              wtvfile_close(pb);
  
              if (wtv->nb_index_entries) {
 -                pb = wtvfile_open(s, root, root_size, timeline_table_0_entries_Events_le16);
 +                pb = wtvfile_open(s, root, root_size, ff_timeline_table_0_entries_Events_le16);
                  if (pb) {
                      int i;
                      while (1) {
                          uint64_t frame_nb = avio_rl64(pb);
                          uint64_t position = avio_rl64(pb);
 -                        if (pb->eof_reached)
 +                        if (avio_feof(pb))
                              break;
                          for (i = wtv->nb_index_entries - 1; i >= 0; i--) {
                              AVIndexEntry *e = wtv->index_entries + i;
@@@ -1084,30 -1087,26 +1087,30 @@@ static int read_seek(AVFormatContext *s
  
      i = ff_index_search_timestamp(wtv->index_entries, wtv->nb_index_entries, ts_relative, flags);
      if (i < 0) {
 -        if (wtv->last_valid_pts == AV_NOPTS_VALUE || ts < wtv->last_valid_pts)
 -            avio_seek(pb, 0, SEEK_SET);
 -        else if (st->duration != AV_NOPTS_VALUE && ts_relative > st->duration && wtv->nb_index_entries)
 -            avio_seek(pb, wtv->index_entries[wtv->nb_index_entries - 1].pos, SEEK_SET);
 +        if (wtv->last_valid_pts == AV_NOPTS_VALUE || ts < wtv->last_valid_pts) {
 +            if (avio_seek(pb, 0, SEEK_SET) < 0)
 +                return -1;
 +        } else if (st->duration != AV_NOPTS_VALUE && ts_relative > st->duration && wtv->nb_index_entries) {
 +            if (avio_seek(pb, wtv->index_entries[wtv->nb_index_entries - 1].pos, SEEK_SET) < 0)
 +                return -1;
 +        }
          if (parse_chunks(s, SEEK_TO_PTS, ts, 0) < 0)
              return AVERROR(ERANGE);
          return 0;
      }
 +    if (avio_seek(pb, wtv->index_entries[i].pos, SEEK_SET) < 0)
 +        return -1;
      wtv->pts = wtv->index_entries[i].timestamp;
      if (wtv->epoch != AV_NOPTS_VALUE)
          wtv->pts += wtv->epoch;
      wtv->last_valid_pts = wtv->pts;
 -    avio_seek(pb, wtv->index_entries[i].pos, SEEK_SET);
      return 0;
  }
  
  static int read_close(AVFormatContext *s)
  {
      WtvContext *wtv = s->priv_data;
 -    av_free(wtv->index_entries);
 +    av_freep(&wtv->index_entries);
      wtvfile_close(wtv->pb);
      return 0;
  }