diff --git a/libavformat/Makefile b/libavformat/Makefile index 19a331123f..dd2c54a7d2 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -63,6 +63,7 @@ OBJS-$(CONFIG_H263_MUXER) += raw.o OBJS-$(CONFIG_H264_DEMUXER) += raw.o OBJS-$(CONFIG_H264_MUXER) += raw.o OBJS-$(CONFIG_IDCIN_DEMUXER) += idcin.o +OBJS-$(CONFIG_IFF_DEMUXER) += iff.o OBJS-$(CONFIG_IMAGE2_DEMUXER) += img2.o OBJS-$(CONFIG_IMAGE2_MUXER) += img2.o OBJS-$(CONFIG_IMAGE2PIPE_DEMUXER) += img2.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 24608a516f..98b2a3fcef 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -86,6 +86,7 @@ void av_register_all(void) REGISTER_MUXDEMUX (H263, h263); REGISTER_MUXDEMUX (H264, h264); REGISTER_DEMUXER (IDCIN, idcin); + REGISTER_DEMUXER (IFF, iff); REGISTER_MUXDEMUX (IMAGE2, image2); REGISTER_MUXDEMUX (IMAGE2PIPE, image2pipe); REGISTER_DEMUXER (INGENIENT, ingenient); diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 76c1578ba7..3c20e64ce0 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -22,7 +22,7 @@ #define FFMPEG_AVFORMAT_H #define LIBAVFORMAT_VERSION_MAJOR 52 -#define LIBAVFORMAT_VERSION_MINOR 12 +#define LIBAVFORMAT_VERSION_MINOR 13 #define LIBAVFORMAT_VERSION_MICRO 0 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ diff --git a/libavformat/iff.c b/libavformat/iff.c new file mode 100644 index 0000000000..aafd626c02 --- /dev/null +++ b/libavformat/iff.c @@ -0,0 +1,174 @@ +/* + * Iff (.iff) File Demuxer + * Copyright (c) 2008 Jaikrishnan Menon + * + * 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 + */ + +/** + * @file iff.c + * iff file demuxer + * by Jaikrishnan Menon + * for more information on the .iff file format, visit: + * http://wiki.multimedia.cx/index.php?title=IFF + */ + +#include "avformat.h" + +#define ID_8SVX MKTAG('8','S','V','X') +#define ID_VHDR MKTAG('V','H','D','R') +#define ID_ATAK MKTAG('A','T','A','K') +#define ID_RLSE MKTAG('R','L','S','E') +#define ID_CHAN MKTAG('C','H','A','N') + +#define ID_FORM MKTAG('F','O','R','M') +#define ID_ANNO MKTAG('A','N','N','O') +#define ID_AUTH MKTAG('A','U','T','H') +#define ID_CHRS MKTAG('C','H','R','S') +#define ID_COPYRIGHT MKTAG('(','c',')',' ') +#define ID_CSET MKTAG('C','S','E','T') +#define ID_FVER MKTAG('F','V','E','R') +#define ID_NAME MKTAG('N','A','M','E') +#define ID_TEXT MKTAG('T','E','X','T') +#define ID_BODY MKTAG('B','O','D','Y') + +#define LEFT 2 +#define RIGHT 4 +#define STEREO 6 + +#define PACKET_SIZE 1024 + +typedef enum {COMP_NONE, COMP_FIB, COMP_EXP} svx8_compression_t; + +typedef struct { + uint32_t body_size; + uint32_t sent_bytes; + uint32_t audio_frame_count; +} IffDemuxContext; + +static int iff_probe(AVProbeData *p) +{ + const uint8_t *d = p->buf; + + if ( AV_RL32(d) == ID_FORM && + AV_RL32(d+8) == ID_8SVX) + return AVPROBE_SCORE_MAX; + return 0; +} + +static int iff_read_header(AVFormatContext *s, + AVFormatParameters *ap) +{ + IffDemuxContext *iff = s->priv_data; + ByteIOContext *pb = s->pb; + AVStream *st; + uint32_t chunk_id, data_size; + int padding, ret, done = 0; + + st = av_new_stream(s, 0); + if (!st) + return AVERROR(ENOMEM); + + st->codec->channels = 1; + url_fskip(pb, 12); + + while(!done && !url_feof(pb)) { + chunk_id = get_le32(pb); + data_size = get_be32(pb); + padding = data_size & 1; + + switch(chunk_id) { + case ID_VHDR: + url_fskip(pb, 12); + st->codec->sample_rate = get_be16(pb); + url_fskip(pb, 1); + st->codec->codec_tag = get_byte(pb); + url_fskip(pb, 4); + break; + + case ID_BODY: + iff->body_size = data_size; + done = 1; + break; + + case ID_CHAN: + st->codec->channels = (get_be32(pb) < 6) ? 1 : 2; + break; + + default: + url_fseek(pb, data_size + padding, SEEK_CUR); + break; + } + } + + if(!st->codec->sample_rate) + return AVERROR_INVALIDDATA; + + av_set_pts_info(st, 32, 1, st->codec->sample_rate); + st->codec->codec_type = CODEC_TYPE_AUDIO; + + switch(st->codec->codec_tag) { + case COMP_NONE: + st->codec->codec_id = CODEC_ID_PCM_S8; + break; + case COMP_FIB: + st->codec->codec_id = CODEC_ID_8SVX_FIB; + break; + case COMP_EXP: + st->codec->codec_id = CODEC_ID_8SVX_EXP; + break; + default: + av_log(s, AV_LOG_ERROR, "iff: unknown compression method\n"); + return -1; + } + + st->codec->bits_per_sample = 8; + st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * st->codec->bits_per_sample; + st->codec->block_align = st->codec->channels * st->codec->bits_per_sample; + + return 0; +} + +static int iff_read_packet(AVFormatContext *s, + AVPacket *pkt) +{ + IffDemuxContext *iff = s->priv_data; + ByteIOContext *pb = s->pb; + int ret; + + if(iff->sent_bytes > iff->body_size) + return AVERROR(EIO); + ret = av_get_packet(pb, pkt, PACKET_SIZE); + + if(iff->sent_bytes == 0) + pkt->flags |= PKT_FLAG_KEY; + + iff->sent_bytes += PACKET_SIZE; + pkt->stream_index = 0; + pkt->pts = iff->audio_frame_count; + iff->audio_frame_count += ret / s->streams[0]->codec->channels; + return ret; +} + +AVInputFormat iff_demuxer = { + "IFF", + "IFF format", + sizeof(IffDemuxContext), + iff_probe, + iff_read_header, + iff_read_packet, +};