1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * RIFF muxing functions 3cabdff1aSopenharmony_ci * Copyright (c) 2000 Fabrice Bellard 4cabdff1aSopenharmony_ci * 5cabdff1aSopenharmony_ci * This file is part of FFmpeg. 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 11cabdff1aSopenharmony_ci * 12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15cabdff1aSopenharmony_ci * Lesser General Public License for more details. 16cabdff1aSopenharmony_ci * 17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20cabdff1aSopenharmony_ci */ 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_ci#include "libavutil/channel_layout.h" 23cabdff1aSopenharmony_ci#include "libavutil/dict.h" 24cabdff1aSopenharmony_ci#include "libavutil/log.h" 25cabdff1aSopenharmony_ci#include "libavutil/mathematics.h" 26cabdff1aSopenharmony_ci#include "libavcodec/avcodec.h" 27cabdff1aSopenharmony_ci#include "libavcodec/bytestream.h" 28cabdff1aSopenharmony_ci#include "avformat.h" 29cabdff1aSopenharmony_ci#include "avio_internal.h" 30cabdff1aSopenharmony_ci#include "riff.h" 31cabdff1aSopenharmony_ci 32cabdff1aSopenharmony_ciint64_t ff_start_tag(AVIOContext *pb, const char *tag) 33cabdff1aSopenharmony_ci{ 34cabdff1aSopenharmony_ci ffio_wfourcc(pb, tag); 35cabdff1aSopenharmony_ci avio_wl32(pb, -1); 36cabdff1aSopenharmony_ci return avio_tell(pb); 37cabdff1aSopenharmony_ci} 38cabdff1aSopenharmony_ci 39cabdff1aSopenharmony_civoid ff_end_tag(AVIOContext *pb, int64_t start) 40cabdff1aSopenharmony_ci{ 41cabdff1aSopenharmony_ci int64_t pos; 42cabdff1aSopenharmony_ci 43cabdff1aSopenharmony_ci av_assert0((start&1) == 0); 44cabdff1aSopenharmony_ci 45cabdff1aSopenharmony_ci pos = avio_tell(pb); 46cabdff1aSopenharmony_ci if (pos & 1) 47cabdff1aSopenharmony_ci avio_w8(pb, 0); 48cabdff1aSopenharmony_ci avio_seek(pb, start - 4, SEEK_SET); 49cabdff1aSopenharmony_ci avio_wl32(pb, (uint32_t)(pos - start)); 50cabdff1aSopenharmony_ci avio_seek(pb, FFALIGN(pos, 2), SEEK_SET); 51cabdff1aSopenharmony_ci} 52cabdff1aSopenharmony_ci 53cabdff1aSopenharmony_ci/* WAVEFORMATEX header */ 54cabdff1aSopenharmony_ci/* returns the size or -1 on error */ 55cabdff1aSopenharmony_ciint ff_put_wav_header(AVFormatContext *s, AVIOContext *pb, 56cabdff1aSopenharmony_ci AVCodecParameters *par, int flags) 57cabdff1aSopenharmony_ci{ 58cabdff1aSopenharmony_ci int bps, blkalign, bytespersec, frame_size; 59cabdff1aSopenharmony_ci int hdrsize; 60cabdff1aSopenharmony_ci int64_t hdrstart = avio_tell(pb); 61cabdff1aSopenharmony_ci int waveformatextensible; 62cabdff1aSopenharmony_ci uint8_t temp[256]; 63cabdff1aSopenharmony_ci uint8_t *riff_extradata = temp; 64cabdff1aSopenharmony_ci uint8_t *riff_extradata_start = temp; 65cabdff1aSopenharmony_ci 66cabdff1aSopenharmony_ci if (!par->codec_tag || par->codec_tag > 0xffff) 67cabdff1aSopenharmony_ci return -1; 68cabdff1aSopenharmony_ci 69cabdff1aSopenharmony_ci if (par->codec_id == AV_CODEC_ID_ADPCM_SWF && par->block_align == 0) { 70cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "%s can only be written to WAVE with a constant frame size\n", 71cabdff1aSopenharmony_ci avcodec_get_name(par->codec_id)); 72cabdff1aSopenharmony_ci return AVERROR(EINVAL); 73cabdff1aSopenharmony_ci } 74cabdff1aSopenharmony_ci 75cabdff1aSopenharmony_ci /* We use the known constant frame size for the codec if known, otherwise 76cabdff1aSopenharmony_ci * fall back on using AVCodecContext.frame_size, which is not as reliable 77cabdff1aSopenharmony_ci * for indicating packet duration. */ 78cabdff1aSopenharmony_ci frame_size = av_get_audio_frame_duration2(par, par->block_align); 79cabdff1aSopenharmony_ci 80cabdff1aSopenharmony_ci waveformatextensible = (par->ch_layout.order == AV_CHANNEL_ORDER_NATIVE && 81cabdff1aSopenharmony_ci av_channel_layout_compare(&par->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_MONO) && 82cabdff1aSopenharmony_ci av_channel_layout_compare(&par->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO)) || 83cabdff1aSopenharmony_ci par->sample_rate > 48000 || 84cabdff1aSopenharmony_ci par->codec_id == AV_CODEC_ID_EAC3 || par->codec_id == AV_CODEC_ID_DFPWM || 85cabdff1aSopenharmony_ci av_get_bits_per_sample(par->codec_id) > 16; 86cabdff1aSopenharmony_ci 87cabdff1aSopenharmony_ci if (waveformatextensible) 88cabdff1aSopenharmony_ci avio_wl16(pb, 0xfffe); 89cabdff1aSopenharmony_ci else 90cabdff1aSopenharmony_ci avio_wl16(pb, par->codec_tag); 91cabdff1aSopenharmony_ci 92cabdff1aSopenharmony_ci avio_wl16(pb, par->ch_layout.nb_channels); 93cabdff1aSopenharmony_ci avio_wl32(pb, par->sample_rate); 94cabdff1aSopenharmony_ci if (par->codec_id == AV_CODEC_ID_ATRAC3 || 95cabdff1aSopenharmony_ci par->codec_id == AV_CODEC_ID_G723_1 || 96cabdff1aSopenharmony_ci par->codec_id == AV_CODEC_ID_MP2 || 97cabdff1aSopenharmony_ci par->codec_id == AV_CODEC_ID_MP3 || 98cabdff1aSopenharmony_ci par->codec_id == AV_CODEC_ID_GSM_MS) { 99cabdff1aSopenharmony_ci bps = 0; 100cabdff1aSopenharmony_ci } else { 101cabdff1aSopenharmony_ci if (!(bps = av_get_bits_per_sample(par->codec_id))) { 102cabdff1aSopenharmony_ci if (par->bits_per_coded_sample) 103cabdff1aSopenharmony_ci bps = par->bits_per_coded_sample; 104cabdff1aSopenharmony_ci else 105cabdff1aSopenharmony_ci bps = 16; // default to 16 106cabdff1aSopenharmony_ci } 107cabdff1aSopenharmony_ci } 108cabdff1aSopenharmony_ci if (bps != par->bits_per_coded_sample && par->bits_per_coded_sample) { 109cabdff1aSopenharmony_ci av_log(s, AV_LOG_WARNING, 110cabdff1aSopenharmony_ci "requested bits_per_coded_sample (%d) " 111cabdff1aSopenharmony_ci "and actually stored (%d) differ\n", 112cabdff1aSopenharmony_ci par->bits_per_coded_sample, bps); 113cabdff1aSopenharmony_ci } 114cabdff1aSopenharmony_ci 115cabdff1aSopenharmony_ci if (par->codec_id == AV_CODEC_ID_MP2) { 116cabdff1aSopenharmony_ci blkalign = (144 * par->bit_rate - 1)/par->sample_rate + 1; 117cabdff1aSopenharmony_ci } else if (par->codec_id == AV_CODEC_ID_MP3) { 118cabdff1aSopenharmony_ci blkalign = 576 * (par->sample_rate <= (24000 + 32000)/2 ? 1 : 2); 119cabdff1aSopenharmony_ci } else if (par->codec_id == AV_CODEC_ID_AC3) { 120cabdff1aSopenharmony_ci blkalign = 3840; /* maximum bytes per frame */ 121cabdff1aSopenharmony_ci } else if (par->codec_id == AV_CODEC_ID_AAC) { 122cabdff1aSopenharmony_ci blkalign = 768 * par->ch_layout.nb_channels; /* maximum bytes per frame */ 123cabdff1aSopenharmony_ci } else if (par->codec_id == AV_CODEC_ID_G723_1) { 124cabdff1aSopenharmony_ci blkalign = 24; 125cabdff1aSopenharmony_ci } else if (par->block_align != 0) { /* specified by the codec */ 126cabdff1aSopenharmony_ci blkalign = par->block_align; 127cabdff1aSopenharmony_ci } else 128cabdff1aSopenharmony_ci blkalign = bps * par->ch_layout.nb_channels / av_gcd(8, bps); 129cabdff1aSopenharmony_ci if (par->codec_id == AV_CODEC_ID_PCM_U8 || 130cabdff1aSopenharmony_ci par->codec_id == AV_CODEC_ID_PCM_S24LE || 131cabdff1aSopenharmony_ci par->codec_id == AV_CODEC_ID_PCM_S32LE || 132cabdff1aSopenharmony_ci par->codec_id == AV_CODEC_ID_PCM_F32LE || 133cabdff1aSopenharmony_ci par->codec_id == AV_CODEC_ID_PCM_F64LE || 134cabdff1aSopenharmony_ci par->codec_id == AV_CODEC_ID_PCM_S16LE) { 135cabdff1aSopenharmony_ci bytespersec = par->sample_rate * blkalign; 136cabdff1aSopenharmony_ci } else if (par->codec_id == AV_CODEC_ID_G723_1) { 137cabdff1aSopenharmony_ci bytespersec = 800; 138cabdff1aSopenharmony_ci } else { 139cabdff1aSopenharmony_ci bytespersec = par->bit_rate / 8; 140cabdff1aSopenharmony_ci } 141cabdff1aSopenharmony_ci avio_wl32(pb, bytespersec); /* bytes per second */ 142cabdff1aSopenharmony_ci avio_wl16(pb, blkalign); /* block align */ 143cabdff1aSopenharmony_ci avio_wl16(pb, bps); /* bits per sample */ 144cabdff1aSopenharmony_ci if (par->codec_id == AV_CODEC_ID_MP3) { 145cabdff1aSopenharmony_ci bytestream_put_le16(&riff_extradata, 1); /* wID */ 146cabdff1aSopenharmony_ci bytestream_put_le32(&riff_extradata, 2); /* fdwFlags */ 147cabdff1aSopenharmony_ci bytestream_put_le16(&riff_extradata, 1152); /* nBlockSize */ 148cabdff1aSopenharmony_ci bytestream_put_le16(&riff_extradata, 1); /* nFramesPerBlock */ 149cabdff1aSopenharmony_ci bytestream_put_le16(&riff_extradata, 1393); /* nCodecDelay */ 150cabdff1aSopenharmony_ci } else if (par->codec_id == AV_CODEC_ID_MP2) { 151cabdff1aSopenharmony_ci /* fwHeadLayer */ 152cabdff1aSopenharmony_ci bytestream_put_le16(&riff_extradata, 2); 153cabdff1aSopenharmony_ci /* dwHeadBitrate */ 154cabdff1aSopenharmony_ci bytestream_put_le32(&riff_extradata, par->bit_rate); 155cabdff1aSopenharmony_ci /* fwHeadMode */ 156cabdff1aSopenharmony_ci bytestream_put_le16(&riff_extradata, par->ch_layout.nb_channels == 2 ? 1 : 8); 157cabdff1aSopenharmony_ci /* fwHeadModeExt */ 158cabdff1aSopenharmony_ci bytestream_put_le16(&riff_extradata, 0); 159cabdff1aSopenharmony_ci /* wHeadEmphasis */ 160cabdff1aSopenharmony_ci bytestream_put_le16(&riff_extradata, 1); 161cabdff1aSopenharmony_ci /* fwHeadFlags */ 162cabdff1aSopenharmony_ci bytestream_put_le16(&riff_extradata, 16); 163cabdff1aSopenharmony_ci /* dwPTSLow */ 164cabdff1aSopenharmony_ci bytestream_put_le32(&riff_extradata, 0); 165cabdff1aSopenharmony_ci /* dwPTSHigh */ 166cabdff1aSopenharmony_ci bytestream_put_le32(&riff_extradata, 0); 167cabdff1aSopenharmony_ci } else if (par->codec_id == AV_CODEC_ID_G723_1) { 168cabdff1aSopenharmony_ci bytestream_put_le32(&riff_extradata, 0x9ace0002); /* extradata needed for msacm g723.1 codec */ 169cabdff1aSopenharmony_ci bytestream_put_le32(&riff_extradata, 0xaea2f732); 170cabdff1aSopenharmony_ci bytestream_put_le16(&riff_extradata, 0xacde); 171cabdff1aSopenharmony_ci } else if (par->codec_id == AV_CODEC_ID_GSM_MS || 172cabdff1aSopenharmony_ci par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) { 173cabdff1aSopenharmony_ci /* wSamplesPerBlock */ 174cabdff1aSopenharmony_ci bytestream_put_le16(&riff_extradata, frame_size); 175cabdff1aSopenharmony_ci } else if (par->extradata_size) { 176cabdff1aSopenharmony_ci riff_extradata_start = par->extradata; 177cabdff1aSopenharmony_ci riff_extradata = par->extradata + par->extradata_size; 178cabdff1aSopenharmony_ci } 179cabdff1aSopenharmony_ci /* write WAVEFORMATEXTENSIBLE extensions */ 180cabdff1aSopenharmony_ci if (waveformatextensible) { 181cabdff1aSopenharmony_ci int write_channel_mask = !(flags & FF_PUT_WAV_HEADER_SKIP_CHANNELMASK) && 182cabdff1aSopenharmony_ci (s->strict_std_compliance < FF_COMPLIANCE_NORMAL || 183cabdff1aSopenharmony_ci par->ch_layout.u.mask < 0x40000); 184cabdff1aSopenharmony_ci /* 22 is WAVEFORMATEXTENSIBLE size */ 185cabdff1aSopenharmony_ci avio_wl16(pb, riff_extradata - riff_extradata_start + 22); 186cabdff1aSopenharmony_ci /* ValidBitsPerSample || SamplesPerBlock || Reserved */ 187cabdff1aSopenharmony_ci avio_wl16(pb, bps); 188cabdff1aSopenharmony_ci /* dwChannelMask */ 189cabdff1aSopenharmony_ci avio_wl32(pb, write_channel_mask ? par->ch_layout.u.mask : 0); 190cabdff1aSopenharmony_ci /* GUID + next 3 */ 191cabdff1aSopenharmony_ci if (par->codec_id == AV_CODEC_ID_EAC3 || par->codec_id == AV_CODEC_ID_DFPWM) { 192cabdff1aSopenharmony_ci ff_put_guid(pb, ff_get_codec_guid(par->codec_id, ff_codec_wav_guids)); 193cabdff1aSopenharmony_ci } else { 194cabdff1aSopenharmony_ci avio_wl32(pb, par->codec_tag); 195cabdff1aSopenharmony_ci avio_wl32(pb, 0x00100000); 196cabdff1aSopenharmony_ci avio_wl32(pb, 0xAA000080); 197cabdff1aSopenharmony_ci avio_wl32(pb, 0x719B3800); 198cabdff1aSopenharmony_ci } 199cabdff1aSopenharmony_ci } else if ((flags & FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX) || 200cabdff1aSopenharmony_ci par->codec_tag != 0x0001 /* PCM */ || 201cabdff1aSopenharmony_ci riff_extradata - riff_extradata_start) { 202cabdff1aSopenharmony_ci /* WAVEFORMATEX */ 203cabdff1aSopenharmony_ci avio_wl16(pb, riff_extradata - riff_extradata_start); /* cbSize */ 204cabdff1aSopenharmony_ci } /* else PCMWAVEFORMAT */ 205cabdff1aSopenharmony_ci avio_write(pb, riff_extradata_start, riff_extradata - riff_extradata_start); 206cabdff1aSopenharmony_ci hdrsize = avio_tell(pb) - hdrstart; 207cabdff1aSopenharmony_ci if (hdrsize & 1) { 208cabdff1aSopenharmony_ci hdrsize++; 209cabdff1aSopenharmony_ci avio_w8(pb, 0); 210cabdff1aSopenharmony_ci } 211cabdff1aSopenharmony_ci 212cabdff1aSopenharmony_ci return hdrsize; 213cabdff1aSopenharmony_ci} 214cabdff1aSopenharmony_ci 215cabdff1aSopenharmony_ci/* BITMAPINFOHEADER header */ 216cabdff1aSopenharmony_civoid ff_put_bmp_header(AVIOContext *pb, AVCodecParameters *par, 217cabdff1aSopenharmony_ci int for_asf, int ignore_extradata, int rgb_frame_is_flipped) 218cabdff1aSopenharmony_ci{ 219cabdff1aSopenharmony_ci int flipped_extradata = (par->extradata_size >= 9 && 220cabdff1aSopenharmony_ci !memcmp(par->extradata + par->extradata_size - 9, "BottomUp", 9)); 221cabdff1aSopenharmony_ci int keep_height = flipped_extradata || rgb_frame_is_flipped; 222cabdff1aSopenharmony_ci int extradata_size = par->extradata_size - 9*flipped_extradata; 223cabdff1aSopenharmony_ci enum AVPixelFormat pix_fmt = par->format; 224cabdff1aSopenharmony_ci int pal_avi; 225cabdff1aSopenharmony_ci 226cabdff1aSopenharmony_ci if (pix_fmt == AV_PIX_FMT_NONE && par->bits_per_coded_sample == 1) 227cabdff1aSopenharmony_ci pix_fmt = AV_PIX_FMT_MONOWHITE; 228cabdff1aSopenharmony_ci pal_avi = !for_asf && 229cabdff1aSopenharmony_ci (pix_fmt == AV_PIX_FMT_PAL8 || 230cabdff1aSopenharmony_ci pix_fmt == AV_PIX_FMT_MONOWHITE || 231cabdff1aSopenharmony_ci pix_fmt == AV_PIX_FMT_MONOBLACK); 232cabdff1aSopenharmony_ci 233cabdff1aSopenharmony_ci /* Size (not including the size of the color table or color masks) */ 234cabdff1aSopenharmony_ci avio_wl32(pb, 40 + (ignore_extradata || pal_avi ? 0 : extradata_size)); 235cabdff1aSopenharmony_ci avio_wl32(pb, par->width); 236cabdff1aSopenharmony_ci //We always store RGB TopDown 237cabdff1aSopenharmony_ci avio_wl32(pb, par->codec_tag || keep_height ? par->height : -par->height); 238cabdff1aSopenharmony_ci /* planes */ 239cabdff1aSopenharmony_ci avio_wl16(pb, 1); 240cabdff1aSopenharmony_ci /* depth */ 241cabdff1aSopenharmony_ci avio_wl16(pb, par->bits_per_coded_sample ? par->bits_per_coded_sample : 24); 242cabdff1aSopenharmony_ci /* compression type */ 243cabdff1aSopenharmony_ci avio_wl32(pb, par->codec_tag); 244cabdff1aSopenharmony_ci avio_wl32(pb, (par->width * par->height * (par->bits_per_coded_sample ? par->bits_per_coded_sample : 24)+7) / 8); 245cabdff1aSopenharmony_ci avio_wl32(pb, 0); 246cabdff1aSopenharmony_ci avio_wl32(pb, 0); 247cabdff1aSopenharmony_ci /* Number of color indices in the color table that are used. 248cabdff1aSopenharmony_ci * A value of 0 means 2^biBitCount indices, but this doesn't work 249cabdff1aSopenharmony_ci * with Windows Media Player and files containing xxpc chunks. */ 250cabdff1aSopenharmony_ci avio_wl32(pb, pal_avi ? 1 << par->bits_per_coded_sample : 0); 251cabdff1aSopenharmony_ci avio_wl32(pb, 0); 252cabdff1aSopenharmony_ci 253cabdff1aSopenharmony_ci if (!ignore_extradata) { 254cabdff1aSopenharmony_ci if (par->extradata_size) { 255cabdff1aSopenharmony_ci avio_write(pb, par->extradata, extradata_size); 256cabdff1aSopenharmony_ci if (!for_asf && extradata_size & 1) 257cabdff1aSopenharmony_ci avio_w8(pb, 0); 258cabdff1aSopenharmony_ci } else if (pal_avi) { 259cabdff1aSopenharmony_ci int i; 260cabdff1aSopenharmony_ci for (i = 0; i < 1 << par->bits_per_coded_sample; i++) { 261cabdff1aSopenharmony_ci /* Initialize 1 bpp palette to black & white */ 262cabdff1aSopenharmony_ci if (i == 0 && pix_fmt == AV_PIX_FMT_MONOWHITE) 263cabdff1aSopenharmony_ci avio_wl32(pb, 0xffffff); 264cabdff1aSopenharmony_ci else if (i == 1 && pix_fmt == AV_PIX_FMT_MONOBLACK) 265cabdff1aSopenharmony_ci avio_wl32(pb, 0xffffff); 266cabdff1aSopenharmony_ci else 267cabdff1aSopenharmony_ci avio_wl32(pb, 0); 268cabdff1aSopenharmony_ci } 269cabdff1aSopenharmony_ci } 270cabdff1aSopenharmony_ci } 271cabdff1aSopenharmony_ci} 272cabdff1aSopenharmony_ci 273cabdff1aSopenharmony_civoid ff_parse_specific_params(AVStream *st, int *au_rate, 274cabdff1aSopenharmony_ci int *au_ssize, int *au_scale) 275cabdff1aSopenharmony_ci{ 276cabdff1aSopenharmony_ci AVCodecParameters *par = st->codecpar; 277cabdff1aSopenharmony_ci int gcd; 278cabdff1aSopenharmony_ci int audio_frame_size; 279cabdff1aSopenharmony_ci 280cabdff1aSopenharmony_ci audio_frame_size = av_get_audio_frame_duration2(par, 0); 281cabdff1aSopenharmony_ci if (!audio_frame_size) 282cabdff1aSopenharmony_ci audio_frame_size = par->frame_size; 283cabdff1aSopenharmony_ci 284cabdff1aSopenharmony_ci *au_ssize = par->block_align; 285cabdff1aSopenharmony_ci if (audio_frame_size && par->sample_rate) { 286cabdff1aSopenharmony_ci *au_scale = audio_frame_size; 287cabdff1aSopenharmony_ci *au_rate = par->sample_rate; 288cabdff1aSopenharmony_ci } else if (par->codec_type == AVMEDIA_TYPE_VIDEO || 289cabdff1aSopenharmony_ci par->codec_type == AVMEDIA_TYPE_DATA || 290cabdff1aSopenharmony_ci par->codec_type == AVMEDIA_TYPE_SUBTITLE) { 291cabdff1aSopenharmony_ci *au_scale = st->time_base.num; 292cabdff1aSopenharmony_ci *au_rate = st->time_base.den; 293cabdff1aSopenharmony_ci } else { 294cabdff1aSopenharmony_ci *au_scale = par->block_align ? par->block_align * 8 : 8; 295cabdff1aSopenharmony_ci *au_rate = par->bit_rate ? par->bit_rate : 296cabdff1aSopenharmony_ci 8 * par->sample_rate; 297cabdff1aSopenharmony_ci } 298cabdff1aSopenharmony_ci gcd = av_gcd(*au_scale, *au_rate); 299cabdff1aSopenharmony_ci *au_scale /= gcd; 300cabdff1aSopenharmony_ci *au_rate /= gcd; 301cabdff1aSopenharmony_ci} 302cabdff1aSopenharmony_ci 303cabdff1aSopenharmony_civoid ff_riff_write_info_tag(AVIOContext *pb, const char *tag, const char *str) 304cabdff1aSopenharmony_ci{ 305cabdff1aSopenharmony_ci size_t len = strlen(str); 306cabdff1aSopenharmony_ci if (len > 0 && len < UINT32_MAX) { 307cabdff1aSopenharmony_ci len++; 308cabdff1aSopenharmony_ci ffio_wfourcc(pb, tag); 309cabdff1aSopenharmony_ci avio_wl32(pb, len); 310cabdff1aSopenharmony_ci avio_put_str(pb, str); 311cabdff1aSopenharmony_ci if (len & 1) 312cabdff1aSopenharmony_ci avio_w8(pb, 0); 313cabdff1aSopenharmony_ci } 314cabdff1aSopenharmony_ci} 315cabdff1aSopenharmony_ci 316cabdff1aSopenharmony_cistatic const char riff_tags[][5] = { 317cabdff1aSopenharmony_ci "IARL", "IART", "IAS1", "IAS2", "IAS3", "IAS4", "IAS5", "IAS6", "IAS7", 318cabdff1aSopenharmony_ci "IAS8", "IAS9", "ICMS", "ICMT", "ICOP", "ICRD", "ICRP", "IDIM", "IDPI", 319cabdff1aSopenharmony_ci "IENG", "IGNR", "IKEY", "ILGT", "ILNG", "IMED", "INAM", "IPLT", "IPRD", 320cabdff1aSopenharmony_ci "IPRT", "ITRK", "ISBJ", "ISFT", "ISHP", "ISMP", "ISRC", "ISRF", "ITCH", 321cabdff1aSopenharmony_ci { 0 } 322cabdff1aSopenharmony_ci}; 323cabdff1aSopenharmony_ci 324cabdff1aSopenharmony_cistatic int riff_has_valid_tags(AVFormatContext *s) 325cabdff1aSopenharmony_ci{ 326cabdff1aSopenharmony_ci int i; 327cabdff1aSopenharmony_ci 328cabdff1aSopenharmony_ci for (i = 0; *riff_tags[i]; i++) 329cabdff1aSopenharmony_ci if (av_dict_get(s->metadata, riff_tags[i], NULL, AV_DICT_MATCH_CASE)) 330cabdff1aSopenharmony_ci return 1; 331cabdff1aSopenharmony_ci 332cabdff1aSopenharmony_ci return 0; 333cabdff1aSopenharmony_ci} 334cabdff1aSopenharmony_ci 335cabdff1aSopenharmony_civoid ff_riff_write_info(AVFormatContext *s) 336cabdff1aSopenharmony_ci{ 337cabdff1aSopenharmony_ci AVIOContext *pb = s->pb; 338cabdff1aSopenharmony_ci int i; 339cabdff1aSopenharmony_ci int64_t list_pos; 340cabdff1aSopenharmony_ci AVDictionaryEntry *t = NULL; 341cabdff1aSopenharmony_ci 342cabdff1aSopenharmony_ci ff_metadata_conv(&s->metadata, ff_riff_info_conv, NULL); 343cabdff1aSopenharmony_ci 344cabdff1aSopenharmony_ci /* writing empty LIST is not nice and may cause problems */ 345cabdff1aSopenharmony_ci if (!riff_has_valid_tags(s)) 346cabdff1aSopenharmony_ci return; 347cabdff1aSopenharmony_ci 348cabdff1aSopenharmony_ci list_pos = ff_start_tag(pb, "LIST"); 349cabdff1aSopenharmony_ci ffio_wfourcc(pb, "INFO"); 350cabdff1aSopenharmony_ci for (i = 0; *riff_tags[i]; i++) 351cabdff1aSopenharmony_ci if ((t = av_dict_get(s->metadata, riff_tags[i], 352cabdff1aSopenharmony_ci NULL, AV_DICT_MATCH_CASE))) 353cabdff1aSopenharmony_ci ff_riff_write_info_tag(s->pb, t->key, t->value); 354cabdff1aSopenharmony_ci ff_end_tag(pb, list_pos); 355cabdff1aSopenharmony_ci} 356cabdff1aSopenharmony_ci 357cabdff1aSopenharmony_civoid ff_put_guid(AVIOContext *s, const ff_asf_guid *g) 358cabdff1aSopenharmony_ci{ 359cabdff1aSopenharmony_ci av_assert0(sizeof(*g) == 16); 360cabdff1aSopenharmony_ci avio_write(s, *g, sizeof(*g)); 361cabdff1aSopenharmony_ci} 362cabdff1aSopenharmony_ci 363cabdff1aSopenharmony_ciconst ff_asf_guid *ff_get_codec_guid(enum AVCodecID id, const AVCodecGuid *av_guid) 364cabdff1aSopenharmony_ci{ 365cabdff1aSopenharmony_ci int i; 366cabdff1aSopenharmony_ci for (i = 0; av_guid[i].id != AV_CODEC_ID_NONE; i++) { 367cabdff1aSopenharmony_ci if (id == av_guid[i].id) 368cabdff1aSopenharmony_ci return &(av_guid[i].guid); 369cabdff1aSopenharmony_ci } 370cabdff1aSopenharmony_ci return NULL; 371cabdff1aSopenharmony_ci} 372