electronicarts.c

Go to the documentation of this file.
00001 /* Electronic Arts Multimedia File Demuxer
00002  * Copyright (c) 2004  The ffmpeg Project
00003  * Copyright (c) 2006-2008 Peter Ross
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * FFmpeg is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00022 /**
00023  * @file electronicarts.c
00024  * Electronic Arts Multimedia file demuxer (WVE/UV2/etc.)
00025  * by Robin Kay (komadori at gekkou.co.uk)
00026  */
00027 
00028 #include "avformat.h"
00029 
00030 #define SCHl_TAG MKTAG('S', 'C', 'H', 'l')
00031 #define SEAD_TAG MKTAG('S', 'E', 'A', 'D')    /* Sxxx header */
00032 #define SNDC_TAG MKTAG('S', 'N', 'D', 'C')    /* Sxxx data */
00033 #define SEND_TAG MKTAG('S', 'E', 'N', 'D')    /* Sxxx end */
00034 #define ISNh_TAG MKTAG('1', 'S', 'N', 'h')    /* 1SNx header */
00035 #define EACS_TAG MKTAG('E', 'A', 'C', 'S')
00036 #define ISNd_TAG MKTAG('1', 'S', 'N', 'd')    /* 1SNx data */
00037 #define ISNe_TAG MKTAG('1', 'S', 'N', 'e')    /* 1SNx end */
00038 #define PT00_TAG MKTAG('P', 'T', 0x0, 0x0)
00039 #define GSTR_TAG MKTAG('G', 'S', 'T', 'R')
00040 #define SCDl_TAG MKTAG('S', 'C', 'D', 'l')
00041 #define SCEl_TAG MKTAG('S', 'C', 'E', 'l')
00042 #define kVGT_TAG MKTAG('k', 'V', 'G', 'T')    /* TGV i-frame */
00043 #define MADk_TAG MKTAG('M', 'A', 'D', 'k')    /* MAD i-frame */
00044 #define MPCh_TAG MKTAG('M', 'P', 'C', 'h')    /* MPEG2 */
00045 #define MVhd_TAG MKTAG('M', 'V', 'h', 'd')
00046 #define MV0K_TAG MKTAG('M', 'V', '0', 'K')
00047 #define MV0F_TAG MKTAG('M', 'V', '0', 'F')
00048 #define MVIh_TAG MKTAG('M', 'V', 'I', 'h')    /* CMV header */
00049 #define MVIf_TAG MKTAG('M', 'V', 'I', 'f')    /* CMV i-frame */
00050 
00051 typedef struct EaDemuxContext {
00052     int big_endian;
00053 
00054     enum CodecID video_codec;
00055     AVRational time_base;
00056     int video_stream_index;
00057 
00058     enum CodecID audio_codec;
00059     int audio_stream_index;
00060     int audio_frame_counter;
00061 
00062     int64_t audio_pts;
00063 
00064     int bytes;
00065     int sample_rate;
00066     int num_channels;
00067     int num_samples;
00068 } EaDemuxContext;
00069 
00070 static uint32_t read_arbitary(ByteIOContext *pb) {
00071     uint8_t size, byte;
00072     int i;
00073     uint32_t word;
00074 
00075     size = get_byte(pb);
00076 
00077     word = 0;
00078     for (i = 0; i < size; i++) {
00079         byte = get_byte(pb);
00080         word <<= 8;
00081         word |= byte;
00082     }
00083 
00084     return word;
00085 }
00086 
00087 /*
00088  * Process PT/GSTR sound header
00089  * return 1 if success, 0 if invalid format, otherwise AVERROR_xxx
00090  */
00091 static int process_audio_header_elements(AVFormatContext *s)
00092 {
00093     int inHeader = 1;
00094     EaDemuxContext *ea = s->priv_data;
00095     ByteIOContext *pb = s->pb;
00096     int compression_type = -1, revision = -1, revision2 = -1;
00097 
00098     ea->bytes = 2;
00099     ea->sample_rate = -1;
00100     ea->num_channels = 1;
00101 
00102     while (inHeader) {
00103         int inSubheader;
00104         uint8_t byte;
00105         byte = get_byte(pb);
00106 
00107         switch (byte) {
00108         case 0xFD:
00109             av_log (s, AV_LOG_INFO, "entered audio subheader\n");
00110             inSubheader = 1;
00111             while (inSubheader) {
00112                 uint8_t subbyte;
00113                 subbyte = get_byte(pb);
00114 
00115                 switch (subbyte) {
00116                 case 0x80:
00117                     revision = read_arbitary(pb);
00118                     av_log (s, AV_LOG_INFO, "revision (element 0x80) set to 0x%08x\n", revision);
00119                     break;
00120                 case 0x82:
00121                     ea->num_channels = read_arbitary(pb);
00122                     av_log (s, AV_LOG_INFO, "num_channels (element 0x82) set to 0x%08x\n", ea->num_channels);
00123                     break;
00124                 case 0x83:
00125                     compression_type = read_arbitary(pb);
00126                     av_log (s, AV_LOG_INFO, "compression_type (element 0x83) set to 0x%08x\n", compression_type);
00127                     break;
00128                 case 0x84:
00129                     ea->sample_rate = read_arbitary(pb);
00130                     av_log (s, AV_LOG_INFO, "sample_rate (element 0x84) set to %i\n", ea->sample_rate);
00131                     break;
00132                 case 0x85:
00133                     ea->num_samples = read_arbitary(pb);
00134                     av_log (s, AV_LOG_INFO, "num_samples (element 0x85) set to 0x%08x\n", ea->num_samples);
00135                     break;
00136                 case 0x8A:
00137                     av_log (s, AV_LOG_INFO, "element 0x%02x set to 0x%08x\n", subbyte, read_arbitary(pb));
00138                     av_log (s, AV_LOG_INFO, "exited audio subheader\n");
00139                     inSubheader = 0;
00140                     break;
00141                 case 0xA0:
00142                     revision2 = read_arbitary(pb);
00143                     av_log (s, AV_LOG_INFO, "revision2 (element 0xA0) set to 0x%08x\n", revision2);
00144                     break;
00145                 case 0xFF:
00146                     av_log (s, AV_LOG_INFO, "end of header block reached (within audio subheader)\n");
00147                     inSubheader = 0;
00148                     inHeader = 0;
00149                     break;
00150                 default:
00151                     av_log (s, AV_LOG_INFO, "element 0x%02x set to 0x%08x\n", subbyte, read_arbitary(pb));
00152                     break;
00153                 }
00154             }
00155             break;
00156         case 0xFF:
00157             av_log (s, AV_LOG_INFO, "end of header block reached\n");
00158             inHeader = 0;
00159             break;
00160         default:
00161             av_log (s, AV_LOG_INFO, "header element 0x%02x set to 0x%08x\n", byte, read_arbitary(pb));
00162             break;
00163         }
00164     }
00165 
00166     switch (compression_type) {
00167     case  0: ea->audio_codec = CODEC_ID_PCM_S16LE; break;
00168     case  7: ea->audio_codec = CODEC_ID_ADPCM_EA; break;
00169     case -1:
00170         switch (revision) {
00171         case  1: ea->audio_codec = CODEC_ID_ADPCM_EA_R1; break;
00172         case  2: ea->audio_codec = CODEC_ID_ADPCM_EA_R2; break;
00173         case  3: ea->audio_codec = CODEC_ID_ADPCM_EA_R3; break;
00174         case -1: break;
00175         default:
00176             av_log(s, AV_LOG_ERROR, "unsupported stream type; revision=%i\n", revision);
00177             return 0;
00178         }
00179         switch (revision2) {
00180         case  8: ea->audio_codec = CODEC_ID_PCM_S16LE_PLANAR; break;
00181         default:
00182             av_log(s, AV_LOG_ERROR, "unsupported stream type; revision2=%i\n", revision2);
00183             return 0;
00184         }
00185         break;
00186     default:
00187         av_log(s, AV_LOG_ERROR, "unsupported stream type; compression_type=%i\n", compression_type);
00188         return 0;
00189     }
00190 
00191     if (ea->sample_rate == -1)
00192         ea->sample_rate = revision==3 ? 48000 : 22050;
00193 
00194     return 1;
00195 }
00196 
00197 /*
00198  * Process EACS sound header
00199  * return 1 if success, 0 if invalid format, otherwise AVERROR_xxx
00200  */
00201 static int process_audio_header_eacs(AVFormatContext *s)
00202 {
00203     EaDemuxContext *ea = s->priv_data;
00204     ByteIOContext *pb = s->pb;
00205     int compression_type;
00206 
00207     ea->sample_rate  = ea->big_endian ? get_be32(pb) : get_le32(pb);
00208     ea->bytes        = get_byte(pb);   /* 1=8-bit, 2=16-bit */
00209     ea->num_channels = get_byte(pb);
00210     compression_type = get_byte(pb);
00211     url_fskip(pb, 13);
00212 
00213     switch (compression_type) {
00214     case 0:
00215         switch (ea->bytes) {
00216         case 1: ea->audio_codec = CODEC_ID_PCM_S8;    break;
00217         case 2: ea->audio_codec = CODEC_ID_PCM_S16LE; break;
00218         }
00219         break;
00220     case 1: ea->audio_codec = CODEC_ID_PCM_MULAW; ea->bytes = 1; break;
00221     case 2: ea->audio_codec = CODEC_ID_ADPCM_IMA_EA_EACS; break;
00222     default:
00223         av_log (s, AV_LOG_ERROR, "unsupported stream type; audio compression_type=%i\n", compression_type);
00224     }
00225 
00226     return 1;
00227 }
00228 
00229 /*
00230  * Process SEAD sound header
00231  * return 1 if success, 0 if invalid format, otherwise AVERROR_xxx
00232  */
00233 static int process_audio_header_sead(AVFormatContext *s)
00234 {
00235     EaDemuxContext *ea = s->priv_data;
00236     ByteIOContext *pb = s->pb;
00237 
00238     ea->sample_rate  = get_le32(pb);
00239     ea->bytes        = get_le32(pb);  /* 1=8-bit, 2=16-bit */
00240     ea->num_channels = get_le32(pb);
00241     ea->audio_codec  = CODEC_ID_ADPCM_IMA_EA_SEAD;
00242 
00243     return 1;
00244 }
00245 
00246 static int process_video_header_vp6(AVFormatContext *s)
00247 {
00248     EaDemuxContext *ea = s->priv_data;
00249     ByteIOContext *pb = s->pb;
00250 
00251     url_fskip(pb, 16);
00252     ea->time_base.den = get_le32(pb);
00253     ea->time_base.num = get_le32(pb);
00254     ea->video_codec = CODEC_ID_VP6;
00255 
00256     return 1;
00257 }
00258 
00259 /*
00260  * Process EA file header
00261  * Returns 1 if the EA file is valid and successfully opened, 0 otherwise
00262  */
00263 static int process_ea_header(AVFormatContext *s) {
00264     uint32_t blockid, size = 0;
00265     EaDemuxContext *ea = s->priv_data;
00266     ByteIOContext *pb = s->pb;
00267     int i;
00268 
00269     for (i=0; i<5 && (!ea->audio_codec || !ea->video_codec); i++) {
00270         unsigned int startpos = url_ftell(pb);
00271         int err = 0;
00272 
00273         blockid = get_le32(pb);
00274         size = get_le32(pb);
00275         if (i == 0)
00276             ea->big_endian = size > 0x000FFFFF;
00277         if (ea->big_endian)
00278             size = bswap_32(size);
00279 
00280         switch (blockid) {
00281             case ISNh_TAG:
00282                 if (get_le32(pb) != EACS_TAG) {
00283                     av_log (s, AV_LOG_ERROR, "unknown 1SNh headerid\n");
00284                     return 0;
00285                 }
00286                 err = process_audio_header_eacs(s);
00287                 break;
00288 
00289             case SCHl_TAG :
00290                 blockid = get_le32(pb);
00291                 if (blockid == GSTR_TAG) {
00292                     url_fskip(pb, 4);
00293                 } else if (blockid != PT00_TAG) {
00294                     av_log (s, AV_LOG_ERROR, "unknown SCHl headerid\n");
00295                     return 0;
00296                 }
00297                 err = process_audio_header_elements(s);
00298                 break;
00299 
00300             case SEAD_TAG:
00301                 err = process_audio_header_sead(s);
00302                 break;
00303 
00304             case MVIh_TAG :
00305                 ea->video_codec = CODEC_ID_CMV;
00306                 ea->time_base = (AVRational){0,0};
00307                 break;
00308 
00309             case MVhd_TAG :
00310                 err = process_video_header_vp6(s);
00311                 break;
00312         }
00313 
00314         if (err < 0) {
00315             av_log(s, AV_LOG_ERROR, "error parsing header: %i\n", err);
00316             return err;
00317         }
00318 
00319         url_fseek(pb, startpos + size, SEEK_SET);
00320     }
00321 
00322     url_fseek(pb, 0, SEEK_SET);
00323 
00324     return 1;
00325 }
00326 
00327 
00328 static int ea_probe(AVProbeData *p)
00329 {
00330     switch (AV_RL32(&p->buf[0])) {
00331     case ISNh_TAG:
00332     case SCHl_TAG:
00333     case SEAD_TAG:
00334     case kVGT_TAG:
00335     case MADk_TAG:
00336     case MPCh_TAG:
00337     case MVhd_TAG:
00338     case MVIh_TAG:
00339         return AVPROBE_SCORE_MAX;
00340     }
00341     return 0;
00342 }
00343 
00344 static int ea_read_header(AVFormatContext *s,
00345                           AVFormatParameters *ap)
00346 {
00347     EaDemuxContext *ea = s->priv_data;
00348     AVStream *st;
00349 
00350     if (!process_ea_header(s))
00351         return AVERROR(EIO);
00352 
00353     if (ea->video_codec) {
00354         /* initialize the video decoder stream */
00355         st = av_new_stream(s, 0);
00356         if (!st)
00357             return AVERROR(ENOMEM);
00358         ea->video_stream_index = st->index;
00359         st->codec->codec_type = CODEC_TYPE_VIDEO;
00360         st->codec->codec_id = ea->video_codec;
00361         st->codec->codec_tag = 0;  /* no fourcc */
00362         st->codec->time_base = ea->time_base;
00363     }
00364 
00365     if (ea->audio_codec) {
00366         /* initialize the audio decoder stream */
00367         st = av_new_stream(s, 0);
00368         if (!st)
00369             return AVERROR(ENOMEM);
00370         av_set_pts_info(st, 33, 1, ea->sample_rate);
00371         st->codec->codec_type = CODEC_TYPE_AUDIO;
00372         st->codec->codec_id = ea->audio_codec;
00373         st->codec->codec_tag = 0;  /* no tag */
00374         st->codec->channels = ea->num_channels;
00375         st->codec->sample_rate = ea->sample_rate;
00376         st->codec->bits_per_sample = ea->bytes * 8;
00377         st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
00378             st->codec->bits_per_sample / 4;
00379         st->codec->block_align = st->codec->channels*st->codec->bits_per_sample;
00380         ea->audio_stream_index = st->index;
00381         ea->audio_frame_counter = 0;
00382     }
00383 
00384     return 1;
00385 }
00386 
00387 static int ea_read_packet(AVFormatContext *s,
00388                           AVPacket *pkt)
00389 {
00390     EaDemuxContext *ea = s->priv_data;
00391     ByteIOContext *pb = s->pb;
00392     int ret = 0;
00393     int packet_read = 0;
00394     unsigned int chunk_type, chunk_size;
00395     int key = 0;
00396 
00397     while (!packet_read) {
00398         chunk_type = get_le32(pb);
00399         chunk_size = (ea->big_endian ? get_be32(pb) : get_le32(pb)) - 8;
00400 
00401         switch (chunk_type) {
00402         /* audio data */
00403         case ISNh_TAG:
00404             /* header chunk also contains data; skip over the header portion*/
00405             url_fskip(pb, 32);
00406             chunk_size -= 32;
00407         case ISNd_TAG:
00408         case SCDl_TAG:
00409         case SNDC_TAG:
00410             if (!ea->audio_codec) {
00411                 url_fskip(pb, chunk_size);
00412                 break;
00413             } else if (ea->audio_codec == CODEC_ID_PCM_S16LE_PLANAR) {
00414                 url_fskip(pb, 12);  /* planar header */
00415                 chunk_size -= 12;
00416             }
00417             ret = av_get_packet(pb, pkt, chunk_size);
00418             if (ret != chunk_size)
00419                 ret = AVERROR(EIO);
00420             else {
00421                     pkt->stream_index = ea->audio_stream_index;
00422                     pkt->pts = 90000;
00423                     pkt->pts *= ea->audio_frame_counter;
00424                     pkt->pts /= ea->sample_rate;
00425 
00426                     switch (ea->audio_codec) {
00427                     case CODEC_ID_ADPCM_EA:
00428                     /* 2 samples/byte, 1 or 2 samples per frame depending
00429                      * on stereo; chunk also has 12-byte header */
00430                     ea->audio_frame_counter += ((chunk_size - 12) * 2) /
00431                         ea->num_channels;
00432                         break;
00433                     default:
00434                         ea->audio_frame_counter += chunk_size /
00435                             (ea->bytes * ea->num_channels);
00436                     }
00437             }
00438 
00439             packet_read = 1;
00440             break;
00441 
00442         /* ending tag */
00443         case 0:
00444         case ISNe_TAG:
00445         case SCEl_TAG:
00446         case SEND_TAG:
00447             ret = AVERROR(EIO);
00448             packet_read = 1;
00449             break;
00450 
00451         case MVIh_TAG:
00452             key = PKT_FLAG_KEY;
00453         case MVIf_TAG:
00454             url_fseek(pb, -8, SEEK_CUR);     // include chunk preamble
00455             chunk_size += 8;
00456             goto get_video_packet;
00457 
00458         case MV0K_TAG:
00459             key = PKT_FLAG_KEY;
00460         case MV0F_TAG:
00461 get_video_packet:
00462             ret = av_get_packet(pb, pkt, chunk_size);
00463             if (ret != chunk_size)
00464                 ret = AVERROR_IO;
00465             else {
00466                 pkt->stream_index = ea->video_stream_index;
00467                 pkt->flags |= key;
00468             }
00469             packet_read = 1;
00470             break;
00471 
00472         default:
00473             url_fseek(pb, chunk_size, SEEK_CUR);
00474             break;
00475         }
00476     }
00477 
00478     return ret;
00479 }
00480 
00481 AVInputFormat ea_demuxer = {
00482     "ea",
00483     NULL_IF_CONFIG_SMALL("Electronic Arts Multimedia Format"),
00484     sizeof(EaDemuxContext),
00485     ea_probe,
00486     ea_read_header,
00487     ea_read_packet,
00488 };

Generated on Fri Jan 9 15:44:27 2009 for libextractor by  doxygen 1.5.1