Merge commit '56dc46a1893251e74be1ad63e54fb38d754bb1fe'
authorMichael Niedermayer <michaelni@gmx.at>
Thu, 6 Nov 2014 12:18:42 +0000 (13:18 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Thu, 6 Nov 2014 12:19:26 +0000 (13:19 +0100)
* commit '56dc46a1893251e74be1ad63e54fb38d754bb1fe':
  riffenc: do not fall back on AVCodecContext.frame_size for MP3

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

diff --combined libavformat/riffenc.c
@@@ -2,20 -2,20 +2,20 @@@
   * RIFF muxing functions
   * Copyright (c) 2000 Fabrice Bellard
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -31,7 -31,7 +31,7 @@@
  int64_t ff_start_tag(AVIOContext *pb, const char *tag)
  {
      ffio_wfourcc(pb, tag);
 -    avio_wl32(pb, 0);
 +    avio_wl32(pb, -1);
      return avio_tell(pb);
  }
  
@@@ -39,23 -39,18 +39,23 @@@ void ff_end_tag(AVIOContext *pb, int64_
  {
      int64_t pos;
  
 +    av_assert0((start&1) == 0);
 +
      pos = avio_tell(pb);
 +    if (pos & 1)
 +        avio_w8(pb, 0);
      avio_seek(pb, start - 4, SEEK_SET);
      avio_wl32(pb, (uint32_t)(pos - start));
 -    avio_seek(pb, pos, SEEK_SET);
 +    avio_seek(pb, FFALIGN(pos, 2), SEEK_SET);
  }
  
  /* WAVEFORMATEX header */
  /* returns the size or -1 on error */
 -int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc)
 +int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc, int flags)
  {
      int bps, blkalign, bytespersec, frame_size;
 -    int hdrsize = 18;
 +    int hdrsize;
 +    int64_t hdrstart = avio_tell(pb);
      int waveformatextensible;
      uint8_t temp[256];
      uint8_t *riff_extradata       = temp;
       * fall back on using AVCodecContext.frame_size, which is not as reliable
       * for indicating packet duration. */
      frame_size = av_get_audio_frame_duration(enc, enc->block_align);
-     if (!frame_size)
-         frame_size = enc->frame_size;
  
      waveformatextensible = (enc->channels > 2 && enc->channel_layout) ||
                             enc->sample_rate > 48000 ||
 +                           enc->codec_id == AV_CODEC_ID_EAC3 ||
                             av_get_bits_per_sample(enc->codec_id) > 16;
  
      if (waveformatextensible)
  
      avio_wl16(pb, enc->channels);
      avio_wl32(pb, enc->sample_rate);
 -    if (enc->codec_id == AV_CODEC_ID_MP2 ||
 -        enc->codec_id == AV_CODEC_ID_MP3 ||
 +    if (enc->codec_id == AV_CODEC_ID_ATRAC3 ||
 +        enc->codec_id == AV_CODEC_ID_G723_1 ||
 +        enc->codec_id == AV_CODEC_ID_MP2    ||
 +        enc->codec_id == AV_CODEC_ID_MP3    ||
          enc->codec_id == AV_CODEC_ID_GSM_MS) {
          bps = 0;
      } else {
                 enc->bits_per_coded_sample, bps);
      }
  
-     if (enc->codec_id == AV_CODEC_ID_MP2 ||
-         enc->codec_id == AV_CODEC_ID_MP3) {
-         /* This is wrong, but it seems many demuxers do not work if this
-          * is set correctly. */
+     if (enc->codec_id == AV_CODEC_ID_MP2) {
          blkalign = frame_size;
-         // blkalign = 144 * enc->bit_rate/enc->sample_rate;
+     } else if (enc->codec_id == AV_CODEC_ID_MP3) {
+         blkalign = 576 * (enc->sample_rate <= 24000 ? 1 : 2);
      } else if (enc->codec_id == AV_CODEC_ID_AC3) {
          blkalign = 3840;                /* maximum bytes per frame */
 +    } else if (enc->codec_id == AV_CODEC_ID_AAC) {
 +        blkalign = 768 * enc->channels; /* maximum bytes per frame */
 +    } else if (enc->codec_id == AV_CODEC_ID_G723_1) {
 +        blkalign = 24;
      } else if (enc->block_align != 0) { /* specified by the codec */
          blkalign = enc->block_align;
      } else
          enc->codec_id == AV_CODEC_ID_PCM_F64LE ||
          enc->codec_id == AV_CODEC_ID_PCM_S16LE) {
          bytespersec = enc->sample_rate * blkalign;
 +    } else if (enc->codec_id == AV_CODEC_ID_G723_1) {
 +        bytespersec = 800;
      } else {
          bytespersec = enc->bit_rate / 8;
      }
      avio_wl16(pb, blkalign);    /* block align */
      avio_wl16(pb, bps);         /* bits per sample */
      if (enc->codec_id == AV_CODEC_ID_MP3) {
 -        hdrsize += 12;
          bytestream_put_le16(&riff_extradata, 1);    /* wID */
          bytestream_put_le32(&riff_extradata, 2);    /* fdwFlags */
          bytestream_put_le16(&riff_extradata, 1152); /* nBlockSize */
          bytestream_put_le16(&riff_extradata, 1);    /* nFramesPerBlock */
          bytestream_put_le16(&riff_extradata, 1393); /* nCodecDelay */
      } else if (enc->codec_id == AV_CODEC_ID_MP2) {
 -        hdrsize += 22;
          /* fwHeadLayer */
          bytestream_put_le16(&riff_extradata, 2);
          /* dwHeadBitrate */
          bytestream_put_le32(&riff_extradata, 0);
          /* dwPTSHigh */
          bytestream_put_le32(&riff_extradata, 0);
 +    } else if (enc->codec_id == AV_CODEC_ID_G723_1) {
 +        bytestream_put_le32(&riff_extradata, 0x9ace0002); /* extradata needed for msacm g723.1 codec */
 +        bytestream_put_le32(&riff_extradata, 0xaea2f732);
 +        bytestream_put_le16(&riff_extradata, 0xacde);
      } else if (enc->codec_id == AV_CODEC_ID_GSM_MS ||
                 enc->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) {
 -        hdrsize += 2;
          /* wSamplesPerBlock */
          bytestream_put_le16(&riff_extradata, frame_size);
      } else if (enc->extradata_size) {
          riff_extradata_start = enc->extradata;
          riff_extradata       = enc->extradata + enc->extradata_size;
 -        hdrsize             += enc->extradata_size;
      }
      /* write WAVEFORMATEXTENSIBLE extensions */
      if (waveformatextensible) {
 -        hdrsize += 22;
 +        int write_channel_mask = enc->strict_std_compliance < FF_COMPLIANCE_NORMAL ||
 +                                 enc->channel_layout < 0x40000;
          /* 22 is WAVEFORMATEXTENSIBLE size */
          avio_wl16(pb, riff_extradata - riff_extradata_start + 22);
          /* ValidBitsPerSample || SamplesPerBlock || Reserved */
          avio_wl16(pb, bps);
          /* dwChannelMask */
 -        avio_wl32(pb, enc->channel_layout);
 +        avio_wl32(pb, write_channel_mask ? enc->channel_layout : 0);
          /* GUID + next 3 */
 +        if (enc->codec_id == AV_CODEC_ID_EAC3) {
 +            ff_put_guid(pb, get_codec_guid(enc->codec_id, ff_codec_wav_guids));
 +        } else {
          avio_wl32(pb, enc->codec_tag);
          avio_wl32(pb, 0x00100000);
          avio_wl32(pb, 0xAA000080);
          avio_wl32(pb, 0x719B3800);
 -    } else {
 +        }
 +    } else if ((flags & FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX) ||
 +               enc->codec_tag != 0x0001 /* PCM */ ||
 +               riff_extradata - riff_extradata_start) {
 +        /* WAVEFORMATEX */
          avio_wl16(pb, riff_extradata - riff_extradata_start); /* cbSize */
 -    }
 +    } /* else PCMWAVEFORMAT */
      avio_write(pb, riff_extradata_start, riff_extradata - riff_extradata_start);
 +    hdrsize = avio_tell(pb) - hdrstart;
      if (hdrsize & 1) {
          hdrsize++;
          avio_w8(pb, 0);
  
  /* BITMAPINFOHEADER header */
  void ff_put_bmp_header(AVIOContext *pb, AVCodecContext *enc,
 -                       const AVCodecTag *tags, int for_asf)
 +                       const AVCodecTag *tags, int for_asf, int ignore_extradata)
  {
 +    int keep_height = enc->extradata_size >= 9 &&
 +                      !memcmp(enc->extradata + enc->extradata_size - 9, "BottomUp", 9);
 +    int extradata_size = enc->extradata_size - 9*keep_height;
 +
      /* size */
 -    avio_wl32(pb, 40 + enc->extradata_size);
 +    avio_wl32(pb, 40 + (ignore_extradata ? 0 :extradata_size));
      avio_wl32(pb, enc->width);
      //We always store RGB TopDown
 -    avio_wl32(pb, enc->codec_tag ? enc->height : -enc->height);
 +    avio_wl32(pb, enc->codec_tag || keep_height ? enc->height : -enc->height);
      /* planes */
      avio_wl16(pb, 1);
      /* depth */
      avio_wl16(pb, enc->bits_per_coded_sample ? enc->bits_per_coded_sample : 24);
      /* compression type */
      avio_wl32(pb, enc->codec_tag);
 -    avio_wl32(pb, enc->width * enc->height * 3);
 +    avio_wl32(pb, (enc->width * enc->height * (enc->bits_per_coded_sample ? enc->bits_per_coded_sample : 24)+7) / 8);
      avio_wl32(pb, 0);
      avio_wl32(pb, 0);
      avio_wl32(pb, 0);
      avio_wl32(pb, 0);
  
 -    avio_write(pb, enc->extradata, enc->extradata_size);
 +    if (!ignore_extradata) {
 +        avio_write(pb, enc->extradata, extradata_size);
  
 -    if (!for_asf && enc->extradata_size & 1)
 -        avio_w8(pb, 0);
 +        if (!for_asf && extradata_size & 1)
 +            avio_w8(pb, 0);
 +    }
  }
  
  void ff_parse_specific_params(AVStream *st, int *au_rate,
@@@ -323,19 -290,3 +319,19 @@@ void ff_riff_write_info(AVFormatContex
              ff_riff_write_info_tag(s->pb, t->key, t->value);
      ff_end_tag(pb, list_pos);
  }
 +
 +void ff_put_guid(AVIOContext *s, const ff_asf_guid *g)
 +{
 +    av_assert0(sizeof(*g) == 16);
 +    avio_write(s, *g, sizeof(*g));
 +}
 +
 +const ff_asf_guid *get_codec_guid(enum AVCodecID id, const AVCodecGuid *av_guid)
 +{
 +    int i;
 +    for (i = 0; av_guid[i].id != AV_CODEC_ID_NONE; i++) {
 +        if (id == av_guid[i].id)
 +            return &(av_guid[i].guid);
 +    }
 +    return NULL;
 +}