X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Faiff.c;h=4343e79c48b90842facd8d822ea3f293c43f4197;hb=28da7981d0965558d490780a984cb927019f0c06;hp=1fcfd881b48b74f120457d62f4f69913772e7ad0;hpb=3a957df49e636a3ddd8cbc2bd82917c733573384;p=ffmpeg diff --git a/libavformat/aiff.c b/libavformat/aiff.c index 1fcfd881b48..4343e79c48b 100644 --- a/libavformat/aiff.c +++ b/libavformat/aiff.c @@ -29,15 +29,14 @@ static const AVCodecTag codec_aiff_tags[] = { { CODEC_ID_PCM_S24BE, MKTAG('N','O','N','E') }, { CODEC_ID_PCM_S32BE, MKTAG('N','O','N','E') }, { CODEC_ID_PCM_ALAW, MKTAG('a','l','a','w') }, - { CODEC_ID_PCM_ALAW, MKTAG('A','L','A','W') }, { CODEC_ID_PCM_MULAW, MKTAG('u','l','a','w') }, - { CODEC_ID_PCM_MULAW, MKTAG('U','L','A','W') }, { CODEC_ID_MACE3, MKTAG('M','A','C','3') }, { CODEC_ID_MACE6, MKTAG('M','A','C','6') }, { CODEC_ID_GSM, MKTAG('G','S','M',' ') }, { CODEC_ID_ADPCM_G726, MKTAG('G','7','2','6') }, { CODEC_ID_PCM_S16LE, MKTAG('s','o','w','t') }, { CODEC_ID_ADPCM_IMA_QT, MKTAG('i','m','a','4') }, + { CODEC_ID_QDM2, MKTAG('Q','D','M','2') }, { 0, 0 }, }; @@ -105,10 +104,8 @@ static unsigned int get_aiff_header(ByteIOContext *pb, AVCodecContext *codec, double sample_rate; unsigned int num_frames; - if (size & 1) size++; - codec->codec_type = CODEC_TYPE_AUDIO; codec->channels = get_be16(pb); num_frames = get_be32(pb); @@ -122,15 +119,20 @@ static unsigned int get_aiff_header(ByteIOContext *pb, AVCodecContext *codec, /* Got an AIFF-C? */ if (version == AIFF_C_VERSION1) { codec->codec_tag = get_le32(pb); - codec->codec_id = codec_get_id (codec_aiff_tags, codec->codec_tag); + codec->codec_id = codec_get_id(codec_aiff_tags, codec->codec_tag); switch (codec->codec_id) { case CODEC_ID_PCM_S16BE: - codec->codec_id = aiff_codec_get_id (codec->bits_per_sample); + codec->codec_id = aiff_codec_get_id(codec->bits_per_sample); codec->bits_per_sample = av_get_bits_per_sample(codec->codec_id); break; case CODEC_ID_ADPCM_IMA_QT: codec->block_align = 34*codec->channels; + codec->frame_size = 64; + break; + case CODEC_ID_MACE3: + case CODEC_ID_MACE6: + codec->frame_size = 6; break; default: break; @@ -138,7 +140,7 @@ static unsigned int get_aiff_header(ByteIOContext *pb, AVCodecContext *codec, size -= 4; } else { /* Need the codec type */ - codec->codec_id = aiff_codec_get_id (codec->bits_per_sample); + codec->codec_id = aiff_codec_get_id(codec->bits_per_sample); codec->bits_per_sample = av_get_bits_per_sample(codec->codec_id); } @@ -150,7 +152,8 @@ static unsigned int get_aiff_header(ByteIOContext *pb, AVCodecContext *codec, if (!codec->block_align) codec->block_align = (codec->bits_per_sample * codec->channels) >> 3; - codec->bit_rate = codec->sample_rate * (codec->block_align << 3); + codec->bit_rate = (codec->frame_size ? codec->sample_rate/codec->frame_size : + codec->sample_rate) * (codec->block_align << 3); /* Chunk is over */ if (size) @@ -175,10 +178,8 @@ static int aiff_write_header(AVFormatContext *s) int aifc = 0; /* First verify if format is ok */ - if (!enc->codec_tag) { + if (!enc->codec_tag) return -1; - } - if (enc->codec_tag != MKTAG('N','O','N','E')) aifc = 1; @@ -188,7 +189,12 @@ static int aiff_write_header(AVFormatContext *s) put_be32(pb, 0); /* file length */ put_tag(pb, aifc ? "AIFC" : "AIFF"); - if (aifc) { + if (aifc) { // compressed audio + enc->bits_per_sample = 16; + if (!enc->block_align) { + av_log(s, AV_LOG_ERROR, "block align not set\n"); + return -1; + } /* Version chunk */ put_tag(pb, "FVER"); put_be32(pb, 4); @@ -198,10 +204,10 @@ static int aiff_write_header(AVFormatContext *s) /* Common chunk */ put_tag(pb, "COMM"); put_be32(pb, aifc ? 24 : 18); /* size */ - put_be16(pb, enc->channels); /* Number of channels */ + put_be16(pb, enc->channels); /* Number of channels */ aiff->frames = url_ftell(pb); - put_be32(pb, 0); /* Number of frames */ + put_be32(pb, 0); /* Number of frames */ if (!enc->bits_per_sample) enc->bits_per_sample = av_get_bits_per_sample(enc->codec_id); @@ -261,15 +267,15 @@ static int aiff_write_trailer(AVFormatContext *s) if (!url_is_streamed(s->pb)) { /* File length */ url_fseek(pb, aiff->form, SEEK_SET); - put_be32(pb, (uint32_t)(file_size - aiff->form - 4)); + put_be32(pb, file_size - aiff->form - 4); /* Number of sample frames */ url_fseek(pb, aiff->frames, SEEK_SET); - put_be32(pb, ((uint32_t)(file_size-aiff->ssnd-12))/enc->block_align); + put_be32(pb, (file_size-aiff->ssnd-12)/enc->block_align); /* Sound Data chunk size */ url_fseek(pb, aiff->ssnd, SEEK_SET); - put_be32(pb, (uint32_t)(file_size - aiff->ssnd - 4)); + put_be32(pb, file_size - aiff->ssnd - 4); /* return to the end */ url_fseek(pb, end_size, SEEK_SET); @@ -331,52 +337,54 @@ static int aiff_read_header(AVFormatContext *s, filesize -= size + 8; switch (tag) { - case MKTAG('C', 'O', 'M', 'M'): /* Common chunk */ - /* Then for the complete header info */ - st->nb_frames = get_aiff_header (pb, st->codec, size, version); - if (st->nb_frames < 0) - return st->nb_frames; - if (offset > 0) // COMM is after SSND - goto got_sound; - break; - - case MKTAG('F', 'V', 'E', 'R'): /* Version chunk */ - version = get_be32(pb); - break; - - case MKTAG('N', 'A', 'M', 'E'): /* Sample name chunk */ - get_meta (pb, s->title, sizeof(s->title), size); - break; - - case MKTAG('A', 'U', 'T', 'H'): /* Author chunk */ - get_meta (pb, s->author, sizeof(s->author), size); - break; - - case MKTAG('(', 'c', ')', ' '): /* Copyright chunk */ - get_meta (pb, s->copyright, sizeof(s->copyright), size); - break; - - case MKTAG('A', 'N', 'N', 'O'): /* Annotation chunk */ - get_meta (pb, s->comment, sizeof(s->comment), size); - break; - - case MKTAG('S', 'S', 'N', 'D'): /* Sampled sound chunk */ - offset = get_be32(pb); /* Offset of sound data */ - get_be32(pb); /* BlockSize... don't care */ - offset += url_ftell(pb); /* Compute absolute data offset */ - if (st->codec->codec_id) /* Assume COMM already parsed */ - goto got_sound; - if (url_is_streamed(pb)) { - av_log(s, AV_LOG_ERROR, "file is not seekable\n"); - return -1; - } - url_fskip(pb, size - 8); - break; - - default: /* Jump */ - if (size & 1) /* Always even aligned */ - size++; - url_fskip (pb, size); + case MKTAG('C', 'O', 'M', 'M'): /* Common chunk */ + /* Then for the complete header info */ + st->nb_frames = get_aiff_header (pb, st->codec, size, version); + if (st->nb_frames < 0) + return st->nb_frames; + if (offset > 0) // COMM is after SSND + goto got_sound; + break; + case MKTAG('F', 'V', 'E', 'R'): /* Version chunk */ + version = get_be32(pb); + break; + case MKTAG('N', 'A', 'M', 'E'): /* Sample name chunk */ + get_meta (pb, s->title, sizeof(s->title), size); + break; + case MKTAG('A', 'U', 'T', 'H'): /* Author chunk */ + get_meta (pb, s->author, sizeof(s->author), size); + break; + case MKTAG('(', 'c', ')', ' '): /* Copyright chunk */ + get_meta (pb, s->copyright, sizeof(s->copyright), size); + break; + case MKTAG('A', 'N', 'N', 'O'): /* Annotation chunk */ + get_meta (pb, s->comment, sizeof(s->comment), size); + break; + case MKTAG('S', 'S', 'N', 'D'): /* Sampled sound chunk */ + offset = get_be32(pb); /* Offset of sound data */ + get_be32(pb); /* BlockSize... don't care */ + offset += url_ftell(pb); /* Compute absolute data offset */ + if (st->codec->codec_id) /* Assume COMM already parsed */ + goto got_sound; + if (url_is_streamed(pb)) { + av_log(s, AV_LOG_ERROR, "file is not seekable\n"); + return -1; + } + url_fskip(pb, size - 8); + break; + case MKTAG('w', 'a', 'v', 'e'): + if ((uint64_t)size > (1<<30)) + return -1; + st->codec->extradata = av_mallocz(size + FF_INPUT_BUFFER_PADDING_SIZE); + if (!st->codec->extradata) + return AVERROR(ENOMEM); + st->codec->extradata_size = size; + get_buffer(pb, st->codec->extradata, size); + break; + default: /* Jump */ + if (size & 1) /* Always even aligned */ + size++; + url_fskip (pb, size); } } @@ -390,7 +398,8 @@ got_sound: av_set_pts_info(st, 64, 1, st->codec->sample_rate); st->start_time = 0; - st->duration = st->nb_frames; + st->duration = st->codec->frame_size ? + st->nb_frames * st->codec->frame_size : st->nb_frames; /* Position the stream at the first block */ url_fseek(pb, offset, SEEK_SET); @@ -420,11 +429,6 @@ static int aiff_read_packet(AVFormatContext *s, return 0; } -static int aiff_read_close(AVFormatContext *s) -{ - return 0; -} - static int aiff_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) { @@ -439,7 +443,7 @@ AVInputFormat aiff_demuxer = { aiff_probe, aiff_read_header, aiff_read_packet, - aiff_read_close, + NULL, aiff_read_seek, .codec_tag= (const AVCodecTag*[]){codec_aiff_tags, 0}, };