00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00031 #include "avformat.h"
00032 #include "internal.h"
00033
00034 typedef struct {
00035 unsigned int channels;
00036 unsigned int audio_pts;
00037 } CdataDemuxContext;
00038
00039 static int cdata_probe(AVProbeData *p)
00040 {
00041 const uint8_t *b = p->buf;
00042
00043 if (b[0] == 0x04 && (b[1] == 0x00 || b[1] == 0x04 || b[1] == 0x0C || b[1] == 0x14))
00044 return AVPROBE_SCORE_MAX/8;
00045 return 0;
00046 }
00047
00048 static int cdata_read_header(AVFormatContext *s, AVFormatParameters *ap)
00049 {
00050 CdataDemuxContext *cdata = s->priv_data;
00051 AVIOContext *pb = s->pb;
00052 unsigned int sample_rate, header;
00053 AVStream *st;
00054 int64_t channel_layout = 0;
00055
00056 header = avio_rb16(pb);
00057 switch (header) {
00058 case 0x0400: cdata->channels = 1; break;
00059 case 0x0404: cdata->channels = 2; break;
00060 case 0x040C: cdata->channels = 4; channel_layout = AV_CH_LAYOUT_QUAD; break;
00061 case 0x0414: cdata->channels = 6; channel_layout = AV_CH_LAYOUT_5POINT1_BACK; break;
00062 default:
00063 av_log(s, AV_LOG_INFO, "unknown header 0x%04x\n", header);
00064 return -1;
00065 };
00066
00067 sample_rate = avio_rb16(pb);
00068 avio_skip(pb, (avio_r8(pb) & 0x20) ? 15 : 11);
00069
00070 st = avformat_new_stream(s, NULL);
00071 if (!st)
00072 return AVERROR(ENOMEM);
00073 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00074 st->codec->codec_tag = 0;
00075 st->codec->codec_id = CODEC_ID_ADPCM_EA_XAS;
00076 st->codec->channels = cdata->channels;
00077 st->codec->channel_layout = channel_layout;
00078 st->codec->sample_rate = sample_rate;
00079 st->codec->sample_fmt = AV_SAMPLE_FMT_S16;
00080 avpriv_set_pts_info(st, 64, 1, sample_rate);
00081
00082 cdata->audio_pts = 0;
00083 return 0;
00084 }
00085
00086 static int cdata_read_packet(AVFormatContext *s, AVPacket *pkt)
00087 {
00088 CdataDemuxContext *cdata = s->priv_data;
00089 int packet_size = 76*cdata->channels;
00090
00091 int ret = av_get_packet(s->pb, pkt, packet_size);
00092 if (ret < 0)
00093 return ret;
00094 pkt->pts = cdata->audio_pts++;
00095 return 0;
00096 }
00097
00098 AVInputFormat ff_ea_cdata_demuxer = {
00099 .name = "ea_cdata",
00100 .long_name = NULL_IF_CONFIG_SMALL("Electronic Arts cdata"),
00101 .priv_data_size = sizeof(CdataDemuxContext),
00102 .read_probe = cdata_probe,
00103 .read_header = cdata_read_header,
00104 .read_packet = cdata_read_packet,
00105 .extensions = "cdata",
00106 };