* commit '255d9c570e117f0fcb8e51fa2c5996f3c4b2052b': riff: Move demuxing code to a separate file. Conflicts: configure libavformat/riff.c Merged-by: Michael Niedermayer <michaelni@gmx.at>tags/n2.1
@@ -1574,6 +1574,7 @@ CONFIG_EXTRA=" | |||||
mpegvideoenc | mpegvideoenc | ||||
nettle | nettle | ||||
rangecoder | rangecoder | ||||
riffdec | |||||
riffenc | riffenc | ||||
rtpdec | rtpdec | ||||
rtpenc_chain | rtpenc_chain | ||||
@@ -2025,13 +2026,18 @@ libutvideo_encoder_deps="libutvideo" | |||||
# demuxers / muxers | # demuxers / muxers | ||||
ac3_demuxer_select="ac3_parser" | ac3_demuxer_select="ac3_parser" | ||||
asf_demuxer_select="riffdec" | |||||
asf_muxer_select="riffenc" | asf_muxer_select="riffenc" | ||||
asf_stream_muxer_select="asf_muxer" | asf_stream_muxer_select="asf_muxer" | ||||
avi_demuxer_select="riffdec" | |||||
avi_muxer_select="riffenc" | avi_muxer_select="riffenc" | ||||
avisynth_demuxer_deps="avisynth" | avisynth_demuxer_deps="avisynth" | ||||
avisynth_demuxer_select="riffdec" | |||||
caf_demuxer_select="riffdec" | |||||
dirac_demuxer_select="dirac_parser" | dirac_demuxer_select="dirac_parser" | ||||
dts_demuxer_select="dca_parser" | dts_demuxer_select="dca_parser" | ||||
dtshd_demuxer_select="dca_parser" | dtshd_demuxer_select="dca_parser" | ||||
dxa_demuxer_select="riffdec" | |||||
eac3_demuxer_select="ac3_parser" | eac3_demuxer_select="ac3_parser" | ||||
f4v_muxer_select="mov_muxer" | f4v_muxer_select="mov_muxer" | ||||
flac_demuxer_select="flac_parser" | flac_demuxer_select="flac_parser" | ||||
@@ -2040,9 +2046,11 @@ ismv_muxer_select="mov_muxer" | |||||
libnut_demuxer_deps="libnut" | libnut_demuxer_deps="libnut" | ||||
libnut_muxer_deps="libnut" | libnut_muxer_deps="libnut" | ||||
matroska_audio_muxer_select="matroska_muxer" | matroska_audio_muxer_select="matroska_muxer" | ||||
matroska_demuxer_select="riffdec" | |||||
matroska_demuxer_suggest="bzlib lzo zlib" | matroska_demuxer_suggest="bzlib lzo zlib" | ||||
matroska_muxer_select="riffenc" | matroska_muxer_select="riffenc" | ||||
mmf_muxer_select="riffenc" | mmf_muxer_select="riffenc" | ||||
mov_demuxer_select="riffdec" | |||||
mov_demuxer_suggest="zlib" | mov_demuxer_suggest="zlib" | ||||
mov_muxer_select="riffenc rtpenc_chain" | mov_muxer_select="riffenc rtpenc_chain" | ||||
mp3_demuxer_select="mpegaudio_parser" | mp3_demuxer_select="mpegaudio_parser" | ||||
@@ -2051,6 +2059,7 @@ mpegts_muxer_select="adts_muxer latm_muxer" | |||||
mpegtsraw_demuxer_select="mpegts_demuxer" | mpegtsraw_demuxer_select="mpegts_demuxer" | ||||
mxf_d10_muxer_select="mxf_muxer" | mxf_d10_muxer_select="mxf_muxer" | ||||
nut_muxer_select="riffenc" | nut_muxer_select="riffenc" | ||||
nuv_demuxer_select="riffdec" | |||||
ogg_demuxer_select="golomb" | ogg_demuxer_select="golomb" | ||||
psp_muxer_select="mov_muxer" | psp_muxer_select="mov_muxer" | ||||
rtp_demuxer_select="sdp_demuxer" | rtp_demuxer_select="sdp_demuxer" | ||||
@@ -2068,8 +2077,12 @@ tgp_muxer_select="mov_muxer" | |||||
vobsub_demuxer_select="mpegps_demuxer" | vobsub_demuxer_select="mpegps_demuxer" | ||||
w64_demuxer_deps="wav_demuxer" | w64_demuxer_deps="wav_demuxer" | ||||
w64_muxer_deps="wav_muxer" | w64_muxer_deps="wav_muxer" | ||||
wav_demuxer_select="riffdec" | |||||
wav_muxer_select="riffenc" | wav_muxer_select="riffenc" | ||||
webm_muxer_select="riffenc" | webm_muxer_select="riffenc" | ||||
wtv_demuxer_select="riffdec" | |||||
xmv_demuxer_select="riffdec" | |||||
xwma_demuxer_select="riffdec" | |||||
# indevs / outdevs | # indevs / outdevs | ||||
alsa_indev_deps="alsa_asoundlib_h snd_pcm_htimestamp" | alsa_indev_deps="alsa_asoundlib_h snd_pcm_htimestamp" | ||||
@@ -25,6 +25,7 @@ OBJS = allformats.o \ | |||||
utils.o \ | utils.o \ | ||||
OBJS-$(CONFIG_NETWORK) += network.o | OBJS-$(CONFIG_NETWORK) += network.o | ||||
OBJS-$(CONFIG_RIFFDEC) += riffdec.o | |||||
OBJS-$(CONFIG_RIFFENC) += riffenc.o | OBJS-$(CONFIG_RIFFENC) += riffenc.o | ||||
OBJS-$(CONFIG_RTPDEC) += rdt.o \ | OBJS-$(CONFIG_RTPDEC) += rdt.o \ | ||||
rtp.o \ | rtp.o \ | ||||
@@ -20,13 +20,9 @@ | |||||
*/ | */ | ||||
#include "libavutil/error.h" | #include "libavutil/error.h" | ||||
#include "libavutil/log.h" | |||||
#include "libavcodec/avcodec.h" | #include "libavcodec/avcodec.h" | ||||
#include "avformat.h" | #include "avformat.h" | ||||
#include "avio_internal.h" | |||||
#include "riff.h" | #include "riff.h" | ||||
#include "libavcodec/bytestream.h" | |||||
#include "libavutil/avassert.h" | |||||
/* Note: When encoding, the first matching tag is used, so order is | /* Note: When encoding, the first matching tag is used, so order is | ||||
* important if multiple tags are possible for a given codec. | * important if multiple tags are possible for a given codec. | ||||
@@ -422,14 +418,6 @@ const AVCodecTag ff_codec_wav_tags[] = { | |||||
{ AV_CODEC_ID_NONE, 0 }, | { AV_CODEC_ID_NONE, 0 }, | ||||
}; | }; | ||||
const AVCodecGuid ff_codec_wav_guids[] = { | |||||
{ AV_CODEC_ID_AC3, { 0x2C, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB, 0xEA } }, | |||||
{ AV_CODEC_ID_ATRAC3P, { 0xBF, 0xAA, 0x23, 0xE9, 0x58, 0xCB, 0x71, 0x44, 0xA1, 0x19, 0xFF, 0xFA, 0x01, 0xE4, 0xCE, 0x62 } }, | |||||
{ AV_CODEC_ID_EAC3, { 0xAF, 0x87, 0xFB, 0xA7, 0x02, 0x2D, 0xFB, 0x42, 0xA4, 0xD4, 0x05, 0xCD, 0x93, 0x84, 0x3B, 0xDD } }, | |||||
{ AV_CODEC_ID_MP2, { 0x2B, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB, 0xEA } }, | |||||
{ AV_CODEC_ID_NONE } | |||||
}; | |||||
const AVMetadataConv ff_riff_info_conv[] = { | const AVMetadataConv ff_riff_info_conv[] = { | ||||
{ "IART", "artist" }, | { "IART", "artist" }, | ||||
{ "ICMT", "comment" }, | { "ICMT", "comment" }, | ||||
@@ -447,22 +435,6 @@ const AVMetadataConv ff_riff_info_conv[] = { | |||||
{ 0 }, | { 0 }, | ||||
}; | }; | ||||
void ff_get_guid(AVIOContext *s, ff_asf_guid *g) | |||||
{ | |||||
av_assert0(sizeof(*g) == 16); //compiler will optimize this out | |||||
if (avio_read(s, *g, sizeof(*g)) < (int)sizeof(*g)) | |||||
memset(*g, 0, sizeof(*g)); | |||||
} | |||||
enum AVCodecID ff_codec_guid_get_id(const AVCodecGuid *guids, ff_asf_guid guid) | |||||
{ | |||||
int i; | |||||
for (i = 0; guids[i].id != AV_CODEC_ID_NONE; i++) | |||||
if (!ff_guidcmp(guids[i].guid, guid)) | |||||
return guids[i].id; | |||||
return AV_CODEC_ID_NONE; | |||||
} | |||||
const struct AVCodecTag *avformat_get_riff_video_tags(void) | const struct AVCodecTag *avformat_get_riff_video_tags(void) | ||||
{ | { | ||||
return ff_codec_bmp_tags; | return ff_codec_bmp_tags; | ||||
@@ -472,198 +444,3 @@ const struct AVCodecTag *avformat_get_riff_audio_tags(void) | |||||
{ | { | ||||
return ff_codec_wav_tags; | return ff_codec_wav_tags; | ||||
} | } | ||||
#if CONFIG_DEMUXERS | |||||
/* We could be given one of the three possible structures here: | |||||
* WAVEFORMAT, PCMWAVEFORMAT or WAVEFORMATEX. Each structure | |||||
* is an expansion of the previous one with the fields added | |||||
* at the bottom. PCMWAVEFORMAT adds 'WORD wBitsPerSample' and | |||||
* WAVEFORMATEX adds 'WORD cbSize' and basically makes itself | |||||
* an openended structure. | |||||
*/ | |||||
static void parse_waveformatex(AVIOContext *pb, AVCodecContext *c) | |||||
{ | |||||
ff_asf_guid subformat; | |||||
int bps = avio_rl16(pb); | |||||
if (bps) | |||||
c->bits_per_coded_sample = bps; | |||||
c->channel_layout = avio_rl32(pb); /* dwChannelMask */ | |||||
ff_get_guid(pb, &subformat); | |||||
if (!memcmp(subformat + 4, | |||||
(const uint8_t[]){ FF_MEDIASUBTYPE_BASE_GUID }, 12)) { | |||||
c->codec_tag = AV_RL32(subformat); | |||||
c->codec_id = ff_wav_codec_get_id(c->codec_tag, | |||||
c->bits_per_coded_sample); | |||||
} else { | |||||
c->codec_id = ff_codec_guid_get_id(ff_codec_wav_guids, subformat); | |||||
if (!c->codec_id) | |||||
av_log(c, AV_LOG_WARNING, | |||||
"unknown subformat:"FF_PRI_GUID"\n", | |||||
FF_ARG_GUID(subformat)); | |||||
} | |||||
} | |||||
int ff_get_wav_header(AVIOContext *pb, AVCodecContext *codec, int size) | |||||
{ | |||||
int id; | |||||
id = avio_rl16(pb); | |||||
codec->codec_type = AVMEDIA_TYPE_AUDIO; | |||||
codec->channels = avio_rl16(pb); | |||||
codec->sample_rate = avio_rl32(pb); | |||||
codec->bit_rate = avio_rl32(pb) * 8; | |||||
codec->block_align = avio_rl16(pb); | |||||
if (size == 14) { /* We're dealing with plain vanilla WAVEFORMAT */ | |||||
codec->bits_per_coded_sample = 8; | |||||
} else | |||||
codec->bits_per_coded_sample = avio_rl16(pb); | |||||
if (id == 0xFFFE) { | |||||
codec->codec_tag = 0; | |||||
} else { | |||||
codec->codec_tag = id; | |||||
codec->codec_id = ff_wav_codec_get_id(id, | |||||
codec->bits_per_coded_sample); | |||||
} | |||||
if (size >= 18) { /* We're obviously dealing with WAVEFORMATEX */ | |||||
int cbSize = avio_rl16(pb); /* cbSize */ | |||||
size -= 18; | |||||
cbSize = FFMIN(size, cbSize); | |||||
if (cbSize >= 22 && id == 0xfffe) { /* WAVEFORMATEXTENSIBLE */ | |||||
parse_waveformatex(pb, codec); | |||||
cbSize -= 22; | |||||
size -= 22; | |||||
} | |||||
codec->extradata_size = cbSize; | |||||
if (cbSize > 0) { | |||||
av_free(codec->extradata); | |||||
codec->extradata = av_mallocz(codec->extradata_size + | |||||
FF_INPUT_BUFFER_PADDING_SIZE); | |||||
if (!codec->extradata) | |||||
return AVERROR(ENOMEM); | |||||
avio_read(pb, codec->extradata, codec->extradata_size); | |||||
size -= cbSize; | |||||
} | |||||
/* It is possible for the chunk to contain garbage at the end */ | |||||
if (size > 0) | |||||
avio_skip(pb, size); | |||||
} | |||||
if (codec->codec_id == AV_CODEC_ID_AAC_LATM) { | |||||
/* Channels and sample_rate values are those prior to applying SBR | |||||
* and/or PS. */ | |||||
codec->channels = 0; | |||||
codec->sample_rate = 0; | |||||
} | |||||
/* override bits_per_coded_sample for G.726 */ | |||||
if (codec->codec_id == AV_CODEC_ID_ADPCM_G726 && codec->sample_rate) | |||||
codec->bits_per_coded_sample = codec->bit_rate / codec->sample_rate; | |||||
return 0; | |||||
} | |||||
enum AVCodecID ff_wav_codec_get_id(unsigned int tag, int bps) | |||||
{ | |||||
enum AVCodecID id; | |||||
id = ff_codec_get_id(ff_codec_wav_tags, tag); | |||||
if (id <= 0) | |||||
return id; | |||||
if (id == AV_CODEC_ID_PCM_S16LE) | |||||
id = ff_get_pcm_codec_id(bps, 0, 0, ~1); | |||||
else if (id == AV_CODEC_ID_PCM_F32LE) | |||||
id = ff_get_pcm_codec_id(bps, 1, 0, 0); | |||||
if (id == AV_CODEC_ID_ADPCM_IMA_WAV && bps == 8) | |||||
id = AV_CODEC_ID_PCM_ZORK; | |||||
return id; | |||||
} | |||||
int ff_get_bmp_header(AVIOContext *pb, AVStream *st, unsigned *esize) | |||||
{ | |||||
int tag1; | |||||
if(esize) *esize = avio_rl32(pb); | |||||
else avio_rl32(pb); | |||||
st->codec->width = avio_rl32(pb); | |||||
st->codec->height = (int32_t)avio_rl32(pb); | |||||
avio_rl16(pb); /* planes */ | |||||
st->codec->bits_per_coded_sample = avio_rl16(pb); /* depth */ | |||||
tag1 = avio_rl32(pb); | |||||
avio_rl32(pb); /* ImageSize */ | |||||
avio_rl32(pb); /* XPelsPerMeter */ | |||||
avio_rl32(pb); /* YPelsPerMeter */ | |||||
avio_rl32(pb); /* ClrUsed */ | |||||
avio_rl32(pb); /* ClrImportant */ | |||||
return tag1; | |||||
} | |||||
int ff_read_riff_info(AVFormatContext *s, int64_t size) | |||||
{ | |||||
int64_t start, end, cur; | |||||
AVIOContext *pb = s->pb; | |||||
start = avio_tell(pb); | |||||
end = start + size; | |||||
while ((cur = avio_tell(pb)) >= 0 && | |||||
cur <= end - 8 /* = tag + size */) { | |||||
uint32_t chunk_code; | |||||
int64_t chunk_size; | |||||
char key[5] = { 0 }; | |||||
char *value; | |||||
chunk_code = avio_rl32(pb); | |||||
chunk_size = avio_rl32(pb); | |||||
if (url_feof(pb)) { | |||||
if (chunk_code || chunk_size) { | |||||
av_log(s, AV_LOG_WARNING, "INFO subchunk truncated\n"); | |||||
return AVERROR_INVALIDDATA; | |||||
} | |||||
return AVERROR_EOF; | |||||
} | |||||
if (chunk_size > end || | |||||
end - chunk_size < cur || | |||||
chunk_size == UINT_MAX) { | |||||
avio_seek(pb, -9, SEEK_CUR); | |||||
chunk_code = avio_rl32(pb); | |||||
chunk_size = avio_rl32(pb); | |||||
if (chunk_size > end || end - chunk_size < cur || chunk_size == UINT_MAX) { | |||||
av_log(s, AV_LOG_WARNING, "too big INFO subchunk\n"); | |||||
return AVERROR_INVALIDDATA; | |||||
} | |||||
} | |||||
chunk_size += (chunk_size & 1); | |||||
if (!chunk_code) { | |||||
if (chunk_size) | |||||
avio_skip(pb, chunk_size); | |||||
else if (pb->eof_reached) { | |||||
av_log(s, AV_LOG_WARNING, "truncated file\n"); | |||||
return AVERROR_EOF; | |||||
} | |||||
continue; | |||||
} | |||||
value = av_mallocz(chunk_size + 1); | |||||
if (!value) { | |||||
av_log(s, AV_LOG_ERROR, | |||||
"out of memory, unable to read INFO tag\n"); | |||||
return AVERROR(ENOMEM); | |||||
} | |||||
AV_WL32(key, chunk_code); | |||||
if (avio_read(pb, value, chunk_size) != chunk_size) { | |||||
av_log(s, AV_LOG_WARNING, | |||||
"premature end of file while reading INFO tag\n"); | |||||
} | |||||
av_dict_set(&s->metadata, key, value, AV_DICT_DONT_STRDUP_VAL); | |||||
} | |||||
return 0; | |||||
} | |||||
#endif /* CONFIG_DEMUXERS */ |
@@ -0,0 +1,247 @@ | |||||
/* | |||||
* RIFF demuxing functions and data | |||||
* Copyright (c) 2000 Fabrice Bellard | |||||
* | |||||
* This file is part of FFmpeg. | |||||
* | |||||
* 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. | |||||
* | |||||
* 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 FFmpeg; if not, write to the Free Software | |||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||||
*/ | |||||
#include "libavutil/dict.h" | |||||
#include "libavutil/error.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" | |||||
const AVCodecGuid ff_codec_wav_guids[] = { | |||||
{ AV_CODEC_ID_AC3, { 0x2C, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB, 0xEA } }, | |||||
{ AV_CODEC_ID_ATRAC3P, { 0xBF, 0xAA, 0x23, 0xE9, 0x58, 0xCB, 0x71, 0x44, 0xA1, 0x19, 0xFF, 0xFA, 0x01, 0xE4, 0xCE, 0x62 } }, | |||||
{ AV_CODEC_ID_EAC3, { 0xAF, 0x87, 0xFB, 0xA7, 0x02, 0x2D, 0xFB, 0x42, 0xA4, 0xD4, 0x05, 0xCD, 0x93, 0x84, 0x3B, 0xDD } }, | |||||
{ AV_CODEC_ID_MP2, { 0x2B, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB, 0xEA } }, | |||||
{ AV_CODEC_ID_NONE } | |||||
}; | |||||
void ff_get_guid(AVIOContext *s, ff_asf_guid *g) | |||||
{ | |||||
av_assert0(sizeof(*g) == 16); //compiler will optimize this out | |||||
if (avio_read(s, *g, sizeof(*g)) < (int)sizeof(*g)) | |||||
memset(*g, 0, sizeof(*g)); | |||||
} | |||||
enum AVCodecID ff_codec_guid_get_id(const AVCodecGuid *guids, ff_asf_guid guid) | |||||
{ | |||||
int i; | |||||
for (i = 0; guids[i].id != AV_CODEC_ID_NONE; i++) | |||||
if (!ff_guidcmp(guids[i].guid, guid)) | |||||
return guids[i].id; | |||||
return AV_CODEC_ID_NONE; | |||||
} | |||||
/* We could be given one of the three possible structures here: | |||||
* WAVEFORMAT, PCMWAVEFORMAT or WAVEFORMATEX. Each structure | |||||
* is an expansion of the previous one with the fields added | |||||
* at the bottom. PCMWAVEFORMAT adds 'WORD wBitsPerSample' and | |||||
* WAVEFORMATEX adds 'WORD cbSize' and basically makes itself | |||||
* an openended structure. | |||||
*/ | |||||
static void parse_waveformatex(AVIOContext *pb, AVCodecContext *c) | |||||
{ | |||||
ff_asf_guid subformat; | |||||
int bps = avio_rl16(pb); | |||||
if (bps) | |||||
c->bits_per_coded_sample = bps; | |||||
c->channel_layout = avio_rl32(pb); /* dwChannelMask */ | |||||
ff_get_guid(pb, &subformat); | |||||
if (!memcmp(subformat + 4, | |||||
(const uint8_t[]){ FF_MEDIASUBTYPE_BASE_GUID }, 12)) { | |||||
c->codec_tag = AV_RL32(subformat); | |||||
c->codec_id = ff_wav_codec_get_id(c->codec_tag, | |||||
c->bits_per_coded_sample); | |||||
} else { | |||||
c->codec_id = ff_codec_guid_get_id(ff_codec_wav_guids, subformat); | |||||
if (!c->codec_id) | |||||
av_log(c, AV_LOG_WARNING, | |||||
"unknown subformat:"FF_PRI_GUID"\n", | |||||
FF_ARG_GUID(subformat)); | |||||
} | |||||
} | |||||
int ff_get_wav_header(AVIOContext *pb, AVCodecContext *codec, int size) | |||||
{ | |||||
int id; | |||||
id = avio_rl16(pb); | |||||
codec->codec_type = AVMEDIA_TYPE_AUDIO; | |||||
codec->channels = avio_rl16(pb); | |||||
codec->sample_rate = avio_rl32(pb); | |||||
codec->bit_rate = avio_rl32(pb) * 8; | |||||
codec->block_align = avio_rl16(pb); | |||||
if (size == 14) { /* We're dealing with plain vanilla WAVEFORMAT */ | |||||
codec->bits_per_coded_sample = 8; | |||||
} else | |||||
codec->bits_per_coded_sample = avio_rl16(pb); | |||||
if (id == 0xFFFE) { | |||||
codec->codec_tag = 0; | |||||
} else { | |||||
codec->codec_tag = id; | |||||
codec->codec_id = ff_wav_codec_get_id(id, | |||||
codec->bits_per_coded_sample); | |||||
} | |||||
if (size >= 18) { /* We're obviously dealing with WAVEFORMATEX */ | |||||
int cbSize = avio_rl16(pb); /* cbSize */ | |||||
size -= 18; | |||||
cbSize = FFMIN(size, cbSize); | |||||
if (cbSize >= 22 && id == 0xfffe) { /* WAVEFORMATEXTENSIBLE */ | |||||
parse_waveformatex(pb, codec); | |||||
cbSize -= 22; | |||||
size -= 22; | |||||
} | |||||
codec->extradata_size = cbSize; | |||||
if (cbSize > 0) { | |||||
av_free(codec->extradata); | |||||
codec->extradata = av_mallocz(codec->extradata_size + | |||||
FF_INPUT_BUFFER_PADDING_SIZE); | |||||
if (!codec->extradata) | |||||
return AVERROR(ENOMEM); | |||||
avio_read(pb, codec->extradata, codec->extradata_size); | |||||
size -= cbSize; | |||||
} | |||||
/* It is possible for the chunk to contain garbage at the end */ | |||||
if (size > 0) | |||||
avio_skip(pb, size); | |||||
} | |||||
if (codec->codec_id == AV_CODEC_ID_AAC_LATM) { | |||||
/* Channels and sample_rate values are those prior to applying SBR | |||||
* and/or PS. */ | |||||
codec->channels = 0; | |||||
codec->sample_rate = 0; | |||||
} | |||||
/* override bits_per_coded_sample for G.726 */ | |||||
if (codec->codec_id == AV_CODEC_ID_ADPCM_G726 && codec->sample_rate) | |||||
codec->bits_per_coded_sample = codec->bit_rate / codec->sample_rate; | |||||
return 0; | |||||
} | |||||
enum AVCodecID ff_wav_codec_get_id(unsigned int tag, int bps) | |||||
{ | |||||
enum AVCodecID id; | |||||
id = ff_codec_get_id(ff_codec_wav_tags, tag); | |||||
if (id <= 0) | |||||
return id; | |||||
if (id == AV_CODEC_ID_PCM_S16LE) | |||||
id = ff_get_pcm_codec_id(bps, 0, 0, ~1); | |||||
else if (id == AV_CODEC_ID_PCM_F32LE) | |||||
id = ff_get_pcm_codec_id(bps, 1, 0, 0); | |||||
if (id == AV_CODEC_ID_ADPCM_IMA_WAV && bps == 8) | |||||
id = AV_CODEC_ID_PCM_ZORK; | |||||
return id; | |||||
} | |||||
int ff_get_bmp_header(AVIOContext *pb, AVStream *st, unsigned *esize) | |||||
{ | |||||
int tag1; | |||||
if(esize) *esize = avio_rl32(pb); | |||||
else avio_rl32(pb); | |||||
st->codec->width = avio_rl32(pb); | |||||
st->codec->height = (int32_t)avio_rl32(pb); | |||||
avio_rl16(pb); /* planes */ | |||||
st->codec->bits_per_coded_sample = avio_rl16(pb); /* depth */ | |||||
tag1 = avio_rl32(pb); | |||||
avio_rl32(pb); /* ImageSize */ | |||||
avio_rl32(pb); /* XPelsPerMeter */ | |||||
avio_rl32(pb); /* YPelsPerMeter */ | |||||
avio_rl32(pb); /* ClrUsed */ | |||||
avio_rl32(pb); /* ClrImportant */ | |||||
return tag1; | |||||
} | |||||
int ff_read_riff_info(AVFormatContext *s, int64_t size) | |||||
{ | |||||
int64_t start, end, cur; | |||||
AVIOContext *pb = s->pb; | |||||
start = avio_tell(pb); | |||||
end = start + size; | |||||
while ((cur = avio_tell(pb)) >= 0 && | |||||
cur <= end - 8 /* = tag + size */) { | |||||
uint32_t chunk_code; | |||||
int64_t chunk_size; | |||||
char key[5] = { 0 }; | |||||
char *value; | |||||
chunk_code = avio_rl32(pb); | |||||
chunk_size = avio_rl32(pb); | |||||
if (url_feof(pb)) { | |||||
if (chunk_code || chunk_size) { | |||||
av_log(s, AV_LOG_WARNING, "INFO subchunk truncated\n"); | |||||
return AVERROR_INVALIDDATA; | |||||
} | |||||
return AVERROR_EOF; | |||||
} | |||||
if (chunk_size > end || | |||||
end - chunk_size < cur || | |||||
chunk_size == UINT_MAX) { | |||||
avio_seek(pb, -9, SEEK_CUR); | |||||
chunk_code = avio_rl32(pb); | |||||
chunk_size = avio_rl32(pb); | |||||
if (chunk_size > end || end - chunk_size < cur || chunk_size == UINT_MAX) { | |||||
av_log(s, AV_LOG_WARNING, "too big INFO subchunk\n"); | |||||
return AVERROR_INVALIDDATA; | |||||
} | |||||
} | |||||
chunk_size += (chunk_size & 1); | |||||
if (!chunk_code) { | |||||
if (chunk_size) | |||||
avio_skip(pb, chunk_size); | |||||
else if (pb->eof_reached) { | |||||
av_log(s, AV_LOG_WARNING, "truncated file\n"); | |||||
return AVERROR_EOF; | |||||
} | |||||
continue; | |||||
} | |||||
value = av_mallocz(chunk_size + 1); | |||||
if (!value) { | |||||
av_log(s, AV_LOG_ERROR, | |||||
"out of memory, unable to read INFO tag\n"); | |||||
return AVERROR(ENOMEM); | |||||
} | |||||
AV_WL32(key, chunk_code); | |||||
if (avio_read(pb, value, chunk_size) != chunk_size) { | |||||
av_log(s, AV_LOG_WARNING, | |||||
"premature end of file while reading INFO tag\n"); | |||||
} | |||||
av_dict_set(&s->metadata, key, value, AV_DICT_DONT_STRDUP_VAL); | |||||
} | |||||
return 0; | |||||
} |