diff options
| author | Tim Redfern <tim@eclectronics.org> | 2013-09-05 17:57:22 +0100 |
|---|---|---|
| committer | Tim Redfern <tim@eclectronics.org> | 2013-09-05 17:57:22 +0100 |
| commit | 8992cb1d0d07edc33d274f6d7924ecdf6f83d994 (patch) | |
| tree | 3a2c86846b7eec8137c1507e623fc7018f13d453 /ffmpeg/libavformat/xa.c | |
| parent | 741fb4b9e135cfb161a749db88713229038577bb (diff) | |
making act segmenter
Diffstat (limited to 'ffmpeg/libavformat/xa.c')
| -rw-r--r-- | ffmpeg/libavformat/xa.c | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/ffmpeg/libavformat/xa.c b/ffmpeg/libavformat/xa.c new file mode 100644 index 0000000..e3d36e6 --- /dev/null +++ b/ffmpeg/libavformat/xa.c @@ -0,0 +1,128 @@ +/* + * Maxis XA (.xa) File Demuxer + * Copyright (c) 2008 Robert Marston + * + * 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 + * Maxis XA File Demuxer + * by Robert Marston (rmarston@gmail.com) + * for more information on the XA audio format see + * http://wiki.multimedia.cx/index.php?title=Maxis_XA + */ + +#include "libavutil/intreadwrite.h" +#include "avformat.h" +#include "internal.h" + +#define XA00_TAG MKTAG('X', 'A', 0, 0) +#define XAI0_TAG MKTAG('X', 'A', 'I', 0) +#define XAJ0_TAG MKTAG('X', 'A', 'J', 0) + +typedef struct MaxisXADemuxContext { + uint32_t out_size; + uint32_t sent_bytes; +} MaxisXADemuxContext; + +static int xa_probe(AVProbeData *p) +{ + int channels, srate, bits_per_sample; + if (p->buf_size < 24) + return 0; + switch(AV_RL32(p->buf)) { + case XA00_TAG: + case XAI0_TAG: + case XAJ0_TAG: + break; + default: + return 0; + } + channels = AV_RL16(p->buf + 10); + srate = AV_RL32(p->buf + 12); + bits_per_sample = AV_RL16(p->buf + 22); + if (!channels || channels > 8 || !srate || srate > 192000 || + bits_per_sample < 4 || bits_per_sample > 32) + return 0; + return AVPROBE_SCORE_MAX/2; +} + +static int xa_read_header(AVFormatContext *s) +{ + MaxisXADemuxContext *xa = s->priv_data; + AVIOContext *pb = s->pb; + AVStream *st; + + /*Set up the XA Audio Decoder*/ + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + + st->codec->codec_type = AVMEDIA_TYPE_AUDIO; + st->codec->codec_id = AV_CODEC_ID_ADPCM_EA_MAXIS_XA; + avio_skip(pb, 4); /* Skip the XA ID */ + xa->out_size = avio_rl32(pb); + avio_skip(pb, 2); /* Skip the tag */ + st->codec->channels = avio_rl16(pb); + st->codec->sample_rate = avio_rl32(pb); + avio_skip(pb, 4); /* Skip average byte rate */ + avio_skip(pb, 2); /* Skip block align */ + avio_skip(pb, 2); /* Skip bits-per-sample */ + + st->codec->bit_rate = av_clip(15LL * st->codec->channels * 8 * + st->codec->sample_rate / 28, 0, INT_MAX); + + avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); + st->start_time = 0; + + return 0; +} + +static int xa_read_packet(AVFormatContext *s, + AVPacket *pkt) +{ + MaxisXADemuxContext *xa = s->priv_data; + AVStream *st = s->streams[0]; + AVIOContext *pb = s->pb; + unsigned int packet_size; + int ret; + + if (xa->sent_bytes >= xa->out_size) + return AVERROR_EOF; + /* 1 byte header and 14 bytes worth of samples * number channels per block */ + packet_size = 15*st->codec->channels; + + ret = av_get_packet(pb, pkt, packet_size); + if(ret < 0) + return ret; + + pkt->stream_index = st->index; + xa->sent_bytes += packet_size; + pkt->duration = 28; + + return ret; +} + +AVInputFormat ff_xa_demuxer = { + .name = "xa", + .long_name = NULL_IF_CONFIG_SMALL("Maxis XA"), + .priv_data_size = sizeof(MaxisXADemuxContext), + .read_probe = xa_probe, + .read_header = xa_read_header, + .read_packet = xa_read_packet, +}; |
