Merge commit 'cb7b1a2dfb547ab78342a7a9d5cd729d77d90421'
authorMichael Niedermayer <michaelni@gmx.at>
Fri, 22 Aug 2014 18:59:49 +0000 (20:59 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Fri, 22 Aug 2014 19:00:06 +0000 (21:00 +0200)
* commit 'cb7b1a2dfb547ab78342a7a9d5cd729d77d90421':
  electronicarts: set the framerate for TGQ/TQI

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

@@@ -2,20 -2,20 +2,20 @@@
   * Copyright (c) 2004  The ffmpeg Project
   * Copyright (c) 2006-2008 Peter Ross
   *
 - * 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
   */
  
@@@ -68,7 -68,6 +68,7 @@@ typedef struct EaDemuxContext 
      enum AVCodecID video_codec;
      AVRational time_base;
      int width, height;
 +    int nb_frames;
      int video_stream_index;
  
      enum AVCodecID audio_codec;
@@@ -109,7 -108,7 +109,7 @@@ static int process_audio_header_element
      ea->sample_rate  = -1;
      ea->num_channels = 1;
  
 -    while (!pb->eof_reached && in_header) {
 +    while (!avio_feof(pb) && in_header) {
          int in_subheader;
          uint8_t byte;
          byte = avio_r8(pb);
          case 0xFD:
              av_log(s, AV_LOG_DEBUG, "entered audio subheader\n");
              in_subheader = 1;
 -            while (!pb->eof_reached && in_subheader) {
 +            while (!avio_feof(pb) && in_subheader) {
                  uint8_t subbyte;
                  subbyte = avio_r8(pb);
  
          case -1:
              break;
          default:
 -            av_log(s, AV_LOG_ERROR,
 -                   "unsupported stream type; revision=%i\n", revision);
 +            avpriv_request_sample(s, "stream type; revision=%i", revision);
              return 0;
          }
          switch (revision2) {
              ea->audio_codec = AV_CODEC_ID_PCM_S16LE_PLANAR;
              break;
          case 10:
 -            ea->audio_codec = AV_CODEC_ID_ADPCM_EA_R2;
 +            switch (revision) {
 +            case -1:
 +            case  2: ea->audio_codec = AV_CODEC_ID_ADPCM_EA_R1; break;
 +            case  3: ea->audio_codec = AV_CODEC_ID_ADPCM_EA_R2; break;
 +            default:
 +                avpriv_request_sample(s, "stream type; revision=%i, revision2=%i", revision, revision2);
 +                return 0;
 +            }
              break;
          case 16:
              ea->audio_codec = AV_CODEC_ID_MP3;
              break;
          default:
              ea->audio_codec = AV_CODEC_ID_NONE;
 -            av_log(s, AV_LOG_ERROR,
 -                   "unsupported stream type; revision2=%i\n", revision2);
 +            avpriv_request_sample(s, "stream type; revision2=%i", revision2);
              return 0;
          }
          break;
      default:
 -        av_log(s, AV_LOG_ERROR,
 -               "unsupported stream type; compression_type=%i\n",
 -               compression_type);
 +        avpriv_request_sample(s,
 +                              "stream type; compression_type=%i",
 +                              compression_type);
          return 0;
      }
  
@@@ -284,9 -278,9 +284,9 @@@ static void process_audio_header_eacs(A
          ea->audio_codec = AV_CODEC_ID_ADPCM_IMA_EA_EACS;
          break;
      default:
 -        av_log(s, AV_LOG_ERROR,
 -               "unsupported stream type; audio compression_type=%i\n",
 -               compression_type);
 +        avpriv_request_sample(s,
 +                              "stream type; audio compression_type=%i",
 +                              compression_type);
      }
  }
  
@@@ -312,23 -306,15 +312,23 @@@ static void process_video_header_mdec(A
      ea->video_codec = AV_CODEC_ID_MDEC;
  }
  
 -static void process_video_header_vp6(AVFormatContext *s)
 +static int process_video_header_vp6(AVFormatContext *s)
  {
      EaDemuxContext *ea = s->priv_data;
      AVIOContext *pb    = s->pb;
  
 -    avio_skip(pb, 16);
 +    avio_skip(pb, 8);
 +    ea->nb_frames = avio_rl32(pb);
 +    avio_skip(pb, 4);
      ea->time_base.den = avio_rl32(pb);
      ea->time_base.num = avio_rl32(pb);
 +    if (ea->time_base.den <= 0 || ea->time_base.num <= 0) {
 +        av_log(s, AV_LOG_ERROR, "Timebase is invalid\n");
 +        return AVERROR_INVALIDDATA;
 +    }
      ea->video_codec   = AV_CODEC_ID_VP6;
 +
 +    return 1;
  }
  
  static void process_video_header_cmv(AVFormatContext *s)
@@@ -353,25 -339,20 +353,25 @@@ static int process_ea_header(AVFormatCo
      int i;
  
      for (i = 0; i < 5 && (!ea->audio_codec || !ea->video_codec); i++) {
 -        unsigned int startpos = avio_tell(pb);
 +        uint64_t startpos     = avio_tell(pb);
          int err               = 0;
  
          blockid = avio_rl32(pb);
          size    = avio_rl32(pb);
          if (i == 0)
 -            ea->big_endian = size > 0x000FFFFF;
 +            ea->big_endian = size > av_bswap32(size);
          if (ea->big_endian)
              size = av_bswap32(size);
  
 +        if (size < 8) {
 +            av_log(s, AV_LOG_ERROR, "chunk size too small\n");
 +            return AVERROR_INVALIDDATA;
 +        }
 +
          switch (blockid) {
          case ISNh_TAG:
              if (avio_rl32(pb) != EACS_TAG) {
 -                av_log(s, AV_LOG_ERROR, "unknown 1SNh headerid\n");
 +                avpriv_request_sample(s, "unknown 1SNh headerid");
                  return 0;
              }
              process_audio_header_eacs(s);
              if (blockid == GSTR_TAG) {
                  avio_skip(pb, 4);
              } else if ((blockid & 0xFFFF) != PT00_TAG) {
 -                av_log(s, AV_LOG_ERROR, "unknown SCHl headerid\n");
 +                avpriv_request_sample(s, "unknown SCHl headerid");
                  return 0;
              }
              err = process_audio_header_elements(s);
  
          case kVGT_TAG:
              ea->video_codec = AV_CODEC_ID_TGV;
 -            ea->time_base   = (AVRational) { 1, 15 };
              break;
  
          case mTCD_TAG:
          case pQGT_TAG:
          case TGQs_TAG:
              ea->video_codec = AV_CODEC_ID_TGQ;
+             ea->time_base   = (AVRational) { 1, 15 };
              break;
  
          case pIQT_TAG:
              ea->video_codec = AV_CODEC_ID_TQI;
+             ea->time_base   = (AVRational) { 1, 15 };
              break;
  
          case MADk_TAG:
              break;
  
          case MVhd_TAG:
 -            process_video_header_vp6(s);
 +            err = process_video_header_vp6(s);
              break;
          }
  
  
  static int ea_probe(AVProbeData *p)
  {
 +    unsigned big_endian, size;
 +
      switch (AV_RL32(&p->buf[0])) {
      case ISNh_TAG:
      case SCHl_TAG:
      default:
          return 0;
      }
 -    if (AV_RL32(&p->buf[4]) > 0xfffff && AV_RB32(&p->buf[4]) > 0xfffff)
 +    size = AV_RL32(&p->buf[4]);
 +    big_endian = size > 0x000FFFFF;
 +    if (big_endian)
 +        size = av_bswap32(size);
 +    if (size > 0xfffff || size < 8)
          return 0;
  
      return AVPROBE_SCORE_MAX;
@@@ -475,7 -453,7 +477,7 @@@ static int ea_read_header(AVFormatConte
      EaDemuxContext *ea = s->priv_data;
      AVStream *st;
  
 -    if (!process_ea_header(s))
 +    if (process_ea_header(s)<=0)
          return AVERROR(EIO);
  
      if (ea->video_codec) {
          ea->video_stream_index = st->index;
          st->codec->codec_type  = AVMEDIA_TYPE_VIDEO;
          st->codec->codec_id    = ea->video_codec;
 +        // parsing is necessary to make FFmpeg generate correct timestamps
 +        if (st->codec->codec_id == AV_CODEC_ID_MPEG2VIDEO)
 +            st->need_parsing = AVSTREAM_PARSE_HEADERS;
          st->codec->codec_tag   = 0; /* no fourcc */
          st->codec->width       = ea->width;
          st->codec->height      = ea->height;
 -        avpriv_set_pts_info(st, 33, ea->time_base.num, ea->time_base.den);
 -        st->avg_frame_rate     = (AVRational) { ea->time_base.den,
 -                                                ea->time_base.num };
 +        st->duration           = st->nb_frames = ea->nb_frames;
 +        if (ea->time_base.num)
 +            avpriv_set_pts_info(st, 64, ea->time_base.num, ea->time_base.den);
 +        st->r_frame_rate       =
 +        st->avg_frame_rate     = av_inv_q(ea->time_base);
      }
  
      if (ea->audio_codec) {
@@@ -546,12 -519,11 +548,12 @@@ static int ea_read_packet(AVFormatConte
  {
      EaDemuxContext *ea = s->priv_data;
      AVIOContext *pb    = s->pb;
 +    int partial_packet = 0;
      unsigned int chunk_type, chunk_size;
      int ret = 0, packet_read = 0, key = 0;
      int av_uninit(num_samples);
  
 -    while (!packet_read) {
 +    while (!packet_read || partial_packet) {
          chunk_type = avio_rl32(pb);
          chunk_size = ea->big_endian ? avio_rb32(pb) : avio_rl32(pb);
          if (chunk_size < 8)
                  avio_skip(pb, 8);
                  chunk_size -= 12;
              }
 +
 +            if (partial_packet) {
 +                avpriv_request_sample(s, "video header followed by audio packet");
 +                av_free_packet(pkt);
 +                partial_packet = 0;
 +            }
 +
              if (!chunk_size)
                  continue;
  
@@@ -665,15 -630,9 +667,15 @@@ get_video_packet
              if (!chunk_size)
                  continue;
  
 -            ret = av_get_packet(pb, pkt, chunk_size);
 -            if (ret < 0)
 -                return ret;
 +            if (partial_packet) {
 +                ret = av_append_packet(pb, pkt, chunk_size);
 +            } else
 +                ret = av_get_packet(pb, pkt, chunk_size);
 +            if (ret < 0) {
 +                packet_read = 1;
 +                break;
 +            }
 +            partial_packet = chunk_type == MVIh_TAG;
              pkt->stream_index = ea->video_stream_index;
              pkt->flags       |= key;
              packet_read       = 1;
          }
      }
  
 +    if (ret < 0 && partial_packet)
 +        av_free_packet(pkt);
      return ret;
  }