libavformat/riffenc.c
3dd5c95d
 /*
  * RIFF muxing functions
  * Copyright (c) 2000 Fabrice Bellard
  *
508a5349
  * This file is part of FFmpeg.
3dd5c95d
  *
508a5349
  * FFmpeg is free software; you can redistribute it and/or
3dd5c95d
  * 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.
  *
508a5349
  * FFmpeg is distributed in the hope that it will be useful,
3dd5c95d
  * 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
508a5349
  * License along with FFmpeg; if not, write to the Free Software
3dd5c95d
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
 #include "libavutil/dict.h"
 #include "libavutil/log.h"
 #include "libavutil/mathematics.h"
 #include "libavcodec/avcodec.h"
 #include "libavcodec/bytestream.h"
 #include "avformat.h"
 #include "avio_internal.h"
 #include "riff.h"
 
 int64_t ff_start_tag(AVIOContext *pb, const char *tag)
 {
     ffio_wfourcc(pb, tag);
c2b0ce70
     avio_wl32(pb, -1);
3dd5c95d
     return avio_tell(pb);
 }
 
 void ff_end_tag(AVIOContext *pb, int64_t start)
 {
     int64_t pos;
 
508a5349
     av_assert0((start&1) == 0);
 
3dd5c95d
     pos = avio_tell(pb);
508a5349
     if (pos & 1)
         avio_w8(pb, 0);
3dd5c95d
     avio_seek(pb, start - 4, SEEK_SET);
     avio_wl32(pb, (uint32_t)(pos - start));
508a5349
     avio_seek(pb, FFALIGN(pos, 2), SEEK_SET);
3dd5c95d
 }
 
 /* WAVEFORMATEX header */
 /* returns the size or -1 on error */
9200514a
 int ff_put_wav_header(AVFormatContext *s, AVIOContext *pb,
6f69f7a8
                       AVCodecParameters *par, int flags)
3dd5c95d
 {
     int bps, blkalign, bytespersec, frame_size;
cf3fccce
     int hdrsize;
     int64_t hdrstart = avio_tell(pb);
3dd5c95d
     int waveformatextensible;
     uint8_t temp[256];
     uint8_t *riff_extradata       = temp;
     uint8_t *riff_extradata_start = temp;
 
9200514a
     if (!par->codec_tag || par->codec_tag > 0xffff)
3dd5c95d
         return -1;
 
     /* We use the known constant frame size for the codec if known, otherwise
      * fall back on using AVCodecContext.frame_size, which is not as reliable
      * for indicating packet duration. */
9200514a
     frame_size = av_get_audio_frame_duration2(par, par->block_align);
3dd5c95d
 
9200514a
     waveformatextensible = (par->channels > 2 && par->channel_layout) ||
fe8959bb
                            par->channels == 1 && par->channel_layout && par->channel_layout != AV_CH_LAYOUT_MONO ||
                            par->channels == 2 && par->channel_layout && par->channel_layout != AV_CH_LAYOUT_STEREO ||
9200514a
                            par->sample_rate > 48000 ||
6f69f7a8
                            par->codec_id == AV_CODEC_ID_EAC3 ||
9200514a
                            av_get_bits_per_sample(par->codec_id) > 16;
3dd5c95d
 
     if (waveformatextensible)
         avio_wl16(pb, 0xfffe);
     else
9200514a
         avio_wl16(pb, par->codec_tag);
3dd5c95d
 
9200514a
     avio_wl16(pb, par->channels);
     avio_wl32(pb, par->sample_rate);
6f69f7a8
     if (par->codec_id == AV_CODEC_ID_ATRAC3 ||
         par->codec_id == AV_CODEC_ID_G723_1 ||
         par->codec_id == AV_CODEC_ID_MP2    ||
         par->codec_id == AV_CODEC_ID_MP3    ||
9200514a
         par->codec_id == AV_CODEC_ID_GSM_MS) {
3dd5c95d
         bps = 0;
     } else {
9200514a
         if (!(bps = av_get_bits_per_sample(par->codec_id))) {
             if (par->bits_per_coded_sample)
                 bps = par->bits_per_coded_sample;
3dd5c95d
             else
                 bps = 16;  // default to 16
         }
     }
9200514a
     if (bps != par->bits_per_coded_sample && par->bits_per_coded_sample) {
         av_log(s, AV_LOG_WARNING,
3dd5c95d
                "requested bits_per_coded_sample (%d) "
                "and actually stored (%d) differ\n",
9200514a
                par->bits_per_coded_sample, bps);
3dd5c95d
     }
 
9200514a
     if (par->codec_id == AV_CODEC_ID_MP2) {
6f69f7a8
         blkalign = (144 * par->bit_rate - 1)/par->sample_rate + 1;
9200514a
     } else if (par->codec_id == AV_CODEC_ID_MP3) {
6f69f7a8
         blkalign = 576 * (par->sample_rate <= (24000 + 32000)/2 ? 1 : 2);
9200514a
     } else if (par->codec_id == AV_CODEC_ID_AC3) {
3dd5c95d
         blkalign = 3840;                /* maximum bytes per frame */
6f69f7a8
     } else if (par->codec_id == AV_CODEC_ID_AAC) {
         blkalign = 768 * par->channels; /* maximum bytes per frame */
     } else if (par->codec_id == AV_CODEC_ID_G723_1) {
508a5349
         blkalign = 24;
9200514a
     } else if (par->block_align != 0) { /* specified by the codec */
         blkalign = par->block_align;
3dd5c95d
     } else
9200514a
         blkalign = bps * par->channels / av_gcd(8, bps);
     if (par->codec_id == AV_CODEC_ID_PCM_U8 ||
         par->codec_id == AV_CODEC_ID_PCM_S24LE ||
         par->codec_id == AV_CODEC_ID_PCM_S32LE ||
         par->codec_id == AV_CODEC_ID_PCM_F32LE ||
         par->codec_id == AV_CODEC_ID_PCM_F64LE ||
         par->codec_id == AV_CODEC_ID_PCM_S16LE) {
         bytespersec = par->sample_rate * blkalign;
6f69f7a8
     } else if (par->codec_id == AV_CODEC_ID_G723_1) {
508a5349
         bytespersec = 800;
3dd5c95d
     } else {
9200514a
         bytespersec = par->bit_rate / 8;
3dd5c95d
     }
     avio_wl32(pb, bytespersec); /* bytes per second */
     avio_wl16(pb, blkalign);    /* block align */
     avio_wl16(pb, bps);         /* bits per sample */
9200514a
     if (par->codec_id == AV_CODEC_ID_MP3) {
3dd5c95d
         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 */
9200514a
     } else if (par->codec_id == AV_CODEC_ID_MP2) {
3dd5c95d
         /* fwHeadLayer */
         bytestream_put_le16(&riff_extradata, 2);
         /* dwHeadBitrate */
9200514a
         bytestream_put_le32(&riff_extradata, par->bit_rate);
3dd5c95d
         /* fwHeadMode */
9200514a
         bytestream_put_le16(&riff_extradata, par->channels == 2 ? 1 : 8);
3dd5c95d
         /* fwHeadModeExt */
         bytestream_put_le16(&riff_extradata, 0);
         /* wHeadEmphasis */
         bytestream_put_le16(&riff_extradata, 1);
         /* fwHeadFlags */
         bytestream_put_le16(&riff_extradata, 16);
         /* dwPTSLow */
         bytestream_put_le32(&riff_extradata, 0);
         /* dwPTSHigh */
         bytestream_put_le32(&riff_extradata, 0);
6f69f7a8
     } else if (par->codec_id == AV_CODEC_ID_G723_1) {
508a5349
         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);
9200514a
     } else if (par->codec_id == AV_CODEC_ID_GSM_MS ||
                par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) {
3dd5c95d
         /* wSamplesPerBlock */
         bytestream_put_le16(&riff_extradata, frame_size);
9200514a
     } else if (par->extradata_size) {
         riff_extradata_start = par->extradata;
         riff_extradata       = par->extradata + par->extradata_size;
3dd5c95d
     }
     /* write WAVEFORMATEXTENSIBLE extensions */
     if (waveformatextensible) {
14163700
         int write_channel_mask = !(flags & FF_PUT_WAV_HEADER_SKIP_CHANNELMASK) &&
6f69f7a8
                                  (s->strict_std_compliance < FF_COMPLIANCE_NORMAL ||
                                   par->channel_layout < 0x40000);
3dd5c95d
         /* 22 is WAVEFORMATEXTENSIBLE size */
         avio_wl16(pb, riff_extradata - riff_extradata_start + 22);
         /* ValidBitsPerSample || SamplesPerBlock || Reserved */
         avio_wl16(pb, bps);
         /* dwChannelMask */
6f69f7a8
         avio_wl32(pb, write_channel_mask ? par->channel_layout : 0);
3dd5c95d
         /* GUID + next 3 */
6f69f7a8
         if (par->codec_id == AV_CODEC_ID_EAC3) {
             ff_put_guid(pb, ff_get_codec_guid(par->codec_id, ff_codec_wav_guids));
bf9a8d18
         } else {
9200514a
         avio_wl32(pb, par->codec_tag);
3dd5c95d
         avio_wl32(pb, 0x00100000);
         avio_wl32(pb, 0xAA000080);
         avio_wl32(pb, 0x719B3800);
bf9a8d18
         }
5e7d21c7
     } else if ((flags & FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX) ||
6f69f7a8
                par->codec_tag != 0x0001 /* PCM */ ||
5e7d21c7
                riff_extradata - riff_extradata_start) {
         /* WAVEFORMATEX */
3dd5c95d
         avio_wl16(pb, riff_extradata - riff_extradata_start); /* cbSize */
5e7d21c7
     } /* else PCMWAVEFORMAT */
3dd5c95d
     avio_write(pb, riff_extradata_start, riff_extradata - riff_extradata_start);
cf3fccce
     hdrsize = avio_tell(pb) - hdrstart;
3dd5c95d
     if (hdrsize & 1) {
         hdrsize++;
         avio_w8(pb, 0);
     }
 
     return hdrsize;
 }
 
 /* BITMAPINFOHEADER header */
9200514a
 void ff_put_bmp_header(AVIOContext *pb, AVCodecParameters *par,
0aa8fa96
                        int for_asf, int ignore_extradata)
3dd5c95d
 {
6f69f7a8
     int keep_height = par->extradata_size >= 9 &&
                       !memcmp(par->extradata + par->extradata_size - 9, "BottomUp", 9);
     int extradata_size = par->extradata_size - 9*keep_height;
     enum AVPixelFormat pix_fmt = par->format;
698fdc85
     int pal_avi;
a51d82b8
 
6f69f7a8
     if (pix_fmt == AV_PIX_FMT_NONE && par->bits_per_coded_sample == 1)
698fdc85
         pix_fmt = AV_PIX_FMT_MONOWHITE;
     pal_avi = !for_asf &&
               (pix_fmt == AV_PIX_FMT_PAL8 ||
                pix_fmt == AV_PIX_FMT_MONOWHITE ||
                pix_fmt == AV_PIX_FMT_MONOBLACK);
 
ed5d295a
     /* Size (not including the size of the color table or color masks) */
     avio_wl32(pb, 40 + (ignore_extradata || pal_avi ? 0 : extradata_size));
9200514a
     avio_wl32(pb, par->width);
3dd5c95d
     //We always store RGB TopDown
6f69f7a8
     avio_wl32(pb, par->codec_tag || keep_height ? par->height : -par->height);
3dd5c95d
     /* planes */
     avio_wl16(pb, 1);
     /* depth */
9200514a
     avio_wl16(pb, par->bits_per_coded_sample ? par->bits_per_coded_sample : 24);
3dd5c95d
     /* compression type */
9200514a
     avio_wl32(pb, par->codec_tag);
6f69f7a8
     avio_wl32(pb, (par->width * par->height * (par->bits_per_coded_sample ? par->bits_per_coded_sample : 24)+7) / 8);
3dd5c95d
     avio_wl32(pb, 0);
     avio_wl32(pb, 0);
ed5d295a
     /* Number of color indices in the color table that are used.
      * A value of 0 means 2^biBitCount indices, but this doesn't work
      * with Windows Media Player and files containing xxpc chunks. */
6f69f7a8
     avio_wl32(pb, pal_avi ? 1 << par->bits_per_coded_sample : 0);
3dd5c95d
     avio_wl32(pb, 0);
 
fcbb9471
     if (!ignore_extradata) {
6f69f7a8
         if (par->extradata_size) {
             avio_write(pb, par->extradata, extradata_size);
a51d82b8
             if (!for_asf && extradata_size & 1)
                 avio_w8(pb, 0);
698fdc85
         } else if (pal_avi) {
a51d82b8
             int i;
6f69f7a8
             for (i = 0; i < 1 << par->bits_per_coded_sample; i++) {
a51d82b8
                 /* Initialize 1 bpp palette to black & white */
3ba57bfe
                 if (i == 0 && pix_fmt == AV_PIX_FMT_MONOWHITE)
                     avio_wl32(pb, 0xffffff);
                 else if (i == 1 && pix_fmt == AV_PIX_FMT_MONOBLACK)
a51d82b8
                     avio_wl32(pb, 0xffffff);
                 else
                     avio_wl32(pb, 0);
             }
         }
fcbb9471
     }
3dd5c95d
 }
 
d754ed41
 void ff_parse_specific_params(AVStream *st, int *au_rate,
3dd5c95d
                               int *au_ssize, int *au_scale)
 {
9200514a
     AVCodecParameters *par = st->codecpar;
3dd5c95d
     int gcd;
     int audio_frame_size;
 
9200514a
     audio_frame_size = av_get_audio_frame_duration2(par, 0);
0b1e94c5
     if (!audio_frame_size)
6f69f7a8
         audio_frame_size = par->frame_size;
3dd5c95d
 
9200514a
     *au_ssize = par->block_align;
     if (audio_frame_size && par->sample_rate) {
3dd5c95d
         *au_scale = audio_frame_size;
9200514a
         *au_rate  = par->sample_rate;
     } else if (par->codec_type == AVMEDIA_TYPE_VIDEO ||
                par->codec_type == AVMEDIA_TYPE_DATA ||
                par->codec_type == AVMEDIA_TYPE_SUBTITLE) {
194be1f4
         *au_scale = st->time_base.num;
         *au_rate  = st->time_base.den;
3dd5c95d
     } else {
9200514a
         *au_scale = par->block_align ? par->block_align * 8 : 8;
         *au_rate  = par->bit_rate ? par->bit_rate :
                     8 * par->sample_rate;
3dd5c95d
     }
     gcd        = av_gcd(*au_scale, *au_rate);
     *au_scale /= gcd;
     *au_rate  /= gcd;
 }
 
 void ff_riff_write_info_tag(AVIOContext *pb, const char *tag, const char *str)
 {
c3671e1d
     size_t len = strlen(str);
     if (len > 0 && len < UINT32_MAX) {
3dd5c95d
         len++;
         ffio_wfourcc(pb, tag);
         avio_wl32(pb, len);
         avio_put_str(pb, str);
         if (len & 1)
             avio_w8(pb, 0);
     }
 }
 
 static const char riff_tags[][5] = {
db4c1bee
     "IARL", "IART", "IAS1", "IAS2", "IAS3", "IAS4", "IAS5", "IAS6", "IAS7",
     "IAS8", "IAS9", "ICMS", "ICMT", "ICOP", "ICRD", "ICRP", "IDIM", "IDPI",
3dd5c95d
     "IENG", "IGNR", "IKEY", "ILGT", "ILNG", "IMED", "INAM", "IPLT", "IPRD",
508a5349
     "IPRT", "ITRK", "ISBJ", "ISFT", "ISHP", "ISMP", "ISRC", "ISRF", "ITCH",
3dd5c95d
     { 0 }
 };
 
 static int riff_has_valid_tags(AVFormatContext *s)
 {
     int i;
 
     for (i = 0; *riff_tags[i]; i++)
         if (av_dict_get(s->metadata, riff_tags[i], NULL, AV_DICT_MATCH_CASE))
             return 1;
 
     return 0;
 }
 
 void ff_riff_write_info(AVFormatContext *s)
 {
     AVIOContext *pb = s->pb;
     int i;
     int64_t list_pos;
     AVDictionaryEntry *t = NULL;
 
     ff_metadata_conv(&s->metadata, ff_riff_info_conv, NULL);
 
     /* writing empty LIST is not nice and may cause problems */
     if (!riff_has_valid_tags(s))
         return;
 
     list_pos = ff_start_tag(pb, "LIST");
     ffio_wfourcc(pb, "INFO");
     for (i = 0; *riff_tags[i]; i++)
         if ((t = av_dict_get(s->metadata, riff_tags[i],
                              NULL, AV_DICT_MATCH_CASE)))
             ff_riff_write_info_tag(s->pb, t->key, t->value);
     ff_end_tag(pb, list_pos);
 }
862174ec
 
 void ff_put_guid(AVIOContext *s, const ff_asf_guid *g)
 {
     av_assert0(sizeof(*g) == 16);
     avio_write(s, *g, sizeof(*g));
 }
 
0a23129b
 const ff_asf_guid *ff_get_codec_guid(enum AVCodecID id, const AVCodecGuid *av_guid)
862174ec
 {
     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;
 }