* AIFF/AIFF-C demuxer
* Copyright (c) 2006 Patrick Guimond
*
- * 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
*/
#include "internal.h"
#include "pcm.h"
#include "aiff.h"
+#include "isom.h"
#define AIFF 0
#define AIFF_C_VERSION1 0xA2805140
{
int size;
- if (pb->eof_reached)
+ if (url_feof(pb))
return AVERROR(EIO);
*tag = avio_rl32(pb);
static void get_meta(AVFormatContext *s, const char *key, int size)
{
uint8_t *str = av_malloc(size+1);
- int res;
- if (!str) {
- avio_skip(s->pb, size);
- return;
- }
-
- res = avio_read(s->pb, str, size);
- if (res < 0)
- return;
+ if (str) {
+ int res = avio_read(s->pb, str, size);
+ if (res < 0){
+ av_free(str);
+ return;
+ }
+ size += (size&1)-res;
+ str[res] = 0;
+ av_dict_set(&s->metadata, key, str, AV_DICT_DONT_STRDUP_VAL);
+ }else
+ size+= size&1;
- str[res] = 0;
- av_dict_set(&s->metadata, key, str, AV_DICT_DONT_STRDUP_VAL);
+ avio_skip(s->pb, size);
}
/* Returns the number of sound data frames or negative on error */
codec->sample_rate = sample_rate;
size -= 18;
- /* Got an AIFF-C? */
+ /* get codec id for AIFF-C */
if (version == AIFF_C_VERSION1) {
codec->codec_tag = avio_rl32(pb);
codec->codec_id = ff_codec_get_id(ff_codec_aiff_tags, codec->codec_tag);
+ size -= 4;
+ }
+ if (version != AIFF_C_VERSION1 || codec->codec_id == CODEC_ID_PCM_S16BE) {
+ codec->codec_id = aiff_codec_get_id(codec->bits_per_coded_sample);
+ codec->bits_per_coded_sample = av_get_bits_per_sample(codec->codec_id);
+ aiff->block_duration = 1;
+ } else {
switch (codec->codec_id) {
- case CODEC_ID_PCM_S16BE:
- codec->codec_id = aiff_codec_get_id(codec->bits_per_coded_sample);
- codec->bits_per_coded_sample = av_get_bits_per_sample(codec->codec_id);
+ case CODEC_ID_PCM_F32BE:
+ case CODEC_ID_PCM_F64BE:
+ case CODEC_ID_PCM_S16LE:
+ case CODEC_ID_PCM_ALAW:
+ case CODEC_ID_PCM_MULAW:
aiff->block_duration = 1;
break;
case CODEC_ID_ADPCM_IMA_QT:
codec->block_align = 34*codec->channels;
- aiff->block_duration = 64;
break;
case CODEC_ID_MACE3:
codec->block_align = 2*codec->channels;
- aiff->block_duration = 6;
break;
case CODEC_ID_MACE6:
codec->block_align = 1*codec->channels;
- aiff->block_duration = 6;
break;
case CODEC_ID_GSM:
codec->block_align = 33;
- aiff->block_duration = 160;
break;
case CODEC_ID_QCELP:
codec->block_align = 35;
- aiff->block_duration = 160;
break;
default:
+ aiff->block_duration = 1;
break;
}
- size -= 4;
- } else {
- /* Need the codec type */
- codec->codec_id = aiff_codec_get_id(codec->bits_per_coded_sample);
- codec->bits_per_coded_sample = av_get_bits_per_sample(codec->codec_id);
- aiff->block_duration = 1;
+ if (codec->block_align > 0)
+ aiff->block_duration = av_get_audio_frame_duration(codec,
+ codec->block_align);
}
/* Block align needs to be computed in all cases, as the definition
if (!codec->block_align)
codec->block_align = (codec->bits_per_coded_sample * codec->channels) >> 3;
- codec->bit_rate = codec->sample_rate * (codec->block_align << 3) /
- aiff->block_duration;
+ if (aiff->block_duration) {
+ codec->bit_rate = codec->sample_rate * (codec->block_align << 3) /
+ aiff->block_duration;
+ }
/* Chunk is over */
if (size)
st->codec->extradata_size = size;
avio_read(pb, st->codec->extradata, size);
break;
+ case MKTAG('C','H','A','N'):
+ if (size < 12)
+ return AVERROR_INVALIDDATA;
+ ff_mov_read_chan(s, size, st->codec);
+ break;
default: /* Jump */
if (size & 1) /* Always even aligned */
size++;
.read_header = aiff_read_header,
.read_packet = aiff_read_packet,
.read_seek = ff_pcm_read_seek,
- .codec_tag= (const AVCodecTag* const []){ff_codec_aiff_tags, 0},
+ .codec_tag = (const AVCodecTag* const []){ ff_codec_aiff_tags, 0 },
};