Merge remote-tracking branch 'qatar/master'
authorMichael Niedermayer <michaelni@gmx.at>
Thu, 20 Sep 2012 19:46:35 +0000 (21:46 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Thu, 20 Sep 2012 19:46:35 +0000 (21:46 +0200)
* qatar/master:
  mp3dec: read Xing frame TOC index
  mp3dec: use named constants for Xing header flags
  libx264: add support for nal-hrd, required for Blu-ray streams.
  mov: support random access point grouping
  matroskadec: properly support BlockDuration

Conflicts:
libavcodec/libx264.c
libavformat/isom.h
libavformat/matroskadec.c
libavformat/mov.c
libavformat/mp3dec.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
libavcodec/libx264.c
libavformat/isom.h
libavformat/matroskadec.c
libavformat/mov.c
libavformat/mp3dec.c

@@@ -457,38 -374,12 +458,42 @@@ static av_cold int X264_init(AVCodecCon
      if (x4->fastfirstpass)
          x264_param_apply_fastfirstpass(&x4->params);
  
 +    /* Allow specifying the x264 profile through AVCodecContext. */
 +    if (!x4->profile)
 +        switch (avctx->profile) {
 +        case FF_PROFILE_H264_BASELINE:
 +            x4->profile = av_strdup("baseline");
 +            break;
 +        case FF_PROFILE_H264_HIGH:
 +            x4->profile = av_strdup("high");
 +            break;
 +        case FF_PROFILE_H264_HIGH_10:
 +            x4->profile = av_strdup("high10");
 +            break;
 +        case FF_PROFILE_H264_HIGH_422:
 +            x4->profile = av_strdup("high422");
 +            break;
 +        case FF_PROFILE_H264_HIGH_444:
 +            x4->profile = av_strdup("high444");
 +            break;
 +        case FF_PROFILE_H264_MAIN:
 +            x4->profile = av_strdup("main");
 +            break;
 +        default:
 +            break;
 +        }
++
+     if (x4->nal_hrd >= 0)
+         x4->params.i_nal_hrd = x4->nal_hrd;
      if (x4->profile)
          if (x264_param_apply_profile(&x4->params, x4->profile) < 0) {
 +            int i;
              av_log(avctx, AV_LOG_ERROR, "Error setting profile %s.\n", x4->profile);
 +            av_log(avctx, AV_LOG_INFO, "Possible profiles:");
 +            for (i = 0; x264_profile_names[i]; i++)
 +                av_log(avctx, AV_LOG_INFO, " %s", x264_profile_names[i]);
 +            av_log(avctx, AV_LOG_INFO, "\n");
              return AVERROR(EINVAL);
          }
  
@@@ -133,9 -132,9 +138,11 @@@ typedef struct MOVStreamContext 
      uint32_t palette[256];
      int has_palette;
      int64_t data_size;
 +    uint32_t tmcd_flags;  ///< tmcd track flags
      int64_t track_end;    ///< used for dts generation in fragmented movie files
 +    int start_pad;        ///< amount of samples to skip due to enc-dec delay
+     unsigned int rap_group_count;
+     MOVSbgp *rap_group;
  } MOVStreamContext;
  
  typedef struct MOVContext {
@@@ -2175,7 -2021,6 +2175,7 @@@ static int matroska_parse_block(Matrosk
      st = track->stream;
      if (st->discard >= AVDISCARD_ALL)
          return res;
-     av_assert1(duration != AV_NOPTS_VALUE);
++    av_assert1(block_duration != AV_NOPTS_VALUE);
  
      block_time = AV_RB16(data);
      data += 2;
      if (res)
          goto end;
  
-     if (!duration)
-         duration = track->default_duration * laces / matroska->time_scale;
 -    if (block_duration != AV_NOPTS_VALUE) {
 -        duration = block_duration / laces;
 -        if (block_duration != duration * laces) {
 -            av_log(matroska->ctx, AV_LOG_WARNING,
 -                   "Incorrect block_duration, possibly corrupted container");
 -        }
 -    } else {
 -        duration = track->default_duration / matroska->time_scale;
 -        block_duration = duration * laces;
 -    }
++    if (!block_duration)
++        block_duration = track->default_duration * laces / matroska->time_scale;
  
 -    if (timecode != AV_NOPTS_VALUE)
 +    if (cluster_time != (uint64_t)-1 && (block_time >= 0 || cluster_time >= -block_time))
-         track->end_timecode = FFMAX(track->end_timecode, timecode+duration);
+         track->end_timecode =
+             FFMAX(track->end_timecode, timecode + block_duration);
  
      for (n = 0; n < laces; n++) {
-         int64_t lace_duration = duration*(n+1) / laces - duration*n / laces;
++        int64_t lace_duration = block_duration*(n+1) / laces - block_duration*n / laces;
 +
 +        if (lace_size[n] > size) {
 +            av_log(matroska->ctx, AV_LOG_ERROR, "Invalid packet size\n");
 +            break;
 +        }
 +
          if ((st->codec->codec_id == AV_CODEC_ID_RA_288 ||
               st->codec->codec_id == AV_CODEC_ID_COOK ||
               st->codec->codec_id == AV_CODEC_ID_SIPR ||
               st->codec->block_align && track->audio.sub_packet_size) {
  
              res = matroska_parse_rm_audio(matroska, track, st, data, size,
--                                          timecode, duration, pos);
++                                          timecode, lace_duration, pos);
              if (res)
                  goto end;
  
@@@ -1914,7 -1810,10 +1954,10 @@@ static void mov_build_index(MOVContext 
          unsigned int stts_sample = 0;
          unsigned int sample_size;
          unsigned int distance = 0;
 -        int key_off = (sc->keyframes && sc->keyframes[0] > 0) || (sc->stps_data && sc->stps_data[0] > 0);
+         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->keyframe_count && sc->keyframes[0] > 0) || (sc->stps_data && sc->stps_data[0] > 0);
  
          current_dts -= sc->dts_shift;
  
                      if (stps_index + 1 < sc->stps_count)
                          stps_index++;
                  }
+                 if (rap_group_present && rap_group_index < sc->rap_group_count) {
+                     if (sc->rap_group[rap_group_index].index > 0)
+                         keyframe = 1;
+                     if (++rap_group_sample == sc->rap_group[rap_group_index].count) {
+                         rap_group_sample = 0;
+                         rap_group_index++;
+                     }
+                 }
                  if (keyframe)
                      distance = 0;
 -                sample_size = sc->sample_size > 0 ? sc->sample_size : sc->sample_sizes[current_sample];
 +                sample_size = sc->alt_sample_size > 0 ? sc->alt_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++];
  #include "id3v1.h"
  #include "libavcodec/mpegaudiodecheader.h"
  
+ #define XING_FLAG_FRAMES 0x01
+ #define XING_FLAG_SIZE   0x02
+ #define XING_FLAG_TOC    0x04
+ #define XING_TOC_COUNT 100
 +typedef struct {
 +    int64_t filesize;
 +    int start_pad;
 +    int end_pad;
 +} MP3Context;
 +
  /* mp3 read */
  
  static int mp3_read_probe(AVProbeData *p)
@@@ -106,24 -145,13 +134,25 @@@ static int mp3_parse_vbr_tags(AVFormatC
      v = avio_rb32(s->pb);
      if(v == MKBETAG('X', 'i', 'n', 'g') || v == MKBETAG('I', 'n', 'f', 'o')) {
          v = avio_rb32(s->pb);
-         if(v & 0x1)
+         if(v & XING_FLAG_FRAMES)
              frames = avio_rb32(s->pb);
-         if(v & 0x2)
+         if(v & XING_FLAG_SIZE)
              size = avio_rb32(s->pb);
-         if(v & 4)
-             avio_skip(s->pb, 100);
+         if (v & XING_FLAG_TOC && frames)
+             read_xing_toc(s, size, av_rescale_q(frames, (AVRational){spf, c.sample_rate},
+                                     st->time_base));
 +        if(v & 8)
 +            avio_skip(s->pb, 4);
 +
 +        v = avio_rb32(s->pb);
 +        if(v == MKBETAG('L', 'A', 'M', 'E') || v == MKBETAG('L', 'a', 'v', 'f')) {
 +            avio_skip(s->pb, 21-4);
 +            v= avio_rb24(s->pb);
 +            mp3->start_pad = v>>12;
 +            mp3->  end_pad = v&4095;
 +            st->skip_samples = mp3->start_pad + 528 + 1;
 +            av_log(s, AV_LOG_DEBUG, "pad %d %d\n", mp3->start_pad, mp3->  end_pad);
 +        }
      }
  
      /* Check for VBRI tag (always 32 bytes after end of mpegaudio header) */
@@@ -222,14 -233,32 +250,36 @@@ static int mp3_read_packet(AVFormatCont
      return ret;
  }
  
- static int read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
+ static int mp3_seek(AVFormatContext *s, int stream_index, int64_t timestamp,
+                     int flags)
  {
-     AVStream *st = s->streams[stream_index];
 +    MP3Context *mp3 = s->priv_data;
+     AVIndexEntry *ie;
+     AVStream *st = s->streams[0];
+     int64_t ret  = av_index_search_timestamp(st, timestamp, flags);
+     uint32_t header = 0;
+     if (ret < 0)
+         return ret;
+     ie = &st->index_entries[ret];
+     ret = avio_seek(s->pb, ie->pos, SEEK_SET);
+     if (ret < 0)
+         return ret;
  
-     st->skip_samples = timestamp <= 0 ? mp3->start_pad + 528 + 1 : 0;
+     while (!s->pb->eof_reached) {
+         header = (header << 8) + avio_r8(s->pb);
+         if (ff_mpa_check_header(header) >= 0) {
+             ff_update_cur_dts(s, st, ie->timestamp);
+             ret = avio_seek(s->pb, -4, SEEK_CUR);
++
++            st->skip_samples = ie->timestamp <= 0 ? mp3->start_pad + 528 + 1 : 0;
++
+             return (ret >= 0) ? 0 : ret;
+         }
+     }
  
-     return -1;
+     return AVERROR_EOF;
  }
  
  AVInputFormat ff_mp3_demuxer = {