+ if (ea->sample_rate == -1)
+ ea->sample_rate = revision==3 ? 48000 : 22050;
+
+ return 1;
+}
+
+/*
+ * Process EACS sound header
+ * return 1 if success, 0 if invalid format, otherwise AVERROR_xxx
+ */
+static int process_audio_header_eacs(AVFormatContext *s)
+{
+ EaDemuxContext *ea = s->priv_data;
+ ByteIOContext *pb = s->pb;
+ int compression_type;
+
+ ea->sample_rate = ea->big_endian ? get_be32(pb) : get_le32(pb);
+ ea->bytes = get_byte(pb); /* 1=8-bit, 2=16-bit */
+ ea->num_channels = get_byte(pb);
+ compression_type = get_byte(pb);
+ url_fskip(pb, 13);
+
+ switch (compression_type) {
+ case 0:
+ switch (ea->bytes) {
+ case 1: ea->audio_codec = CODEC_ID_PCM_S8; break;
+ case 2: ea->audio_codec = CODEC_ID_PCM_S16LE; break;
+ }
+ break;
+ case 1: ea->audio_codec = CODEC_ID_PCM_MULAW; ea->bytes = 1; break;
+ case 2: ea->audio_codec = CODEC_ID_ADPCM_IMA_EA_EACS; break;
+ default:
+ av_log (s, AV_LOG_ERROR, "unsupported stream type; audio compression_type=%i\n", compression_type);
+ }
+
+ return 1;
+}
+
+/*
+ * Process SEAD sound header
+ * return 1 if success, 0 if invalid format, otherwise AVERROR_xxx
+ */
+static int process_audio_header_sead(AVFormatContext *s)
+{
+ EaDemuxContext *ea = s->priv_data;
+ ByteIOContext *pb = s->pb;
+
+ ea->sample_rate = get_le32(pb);
+ ea->bytes = get_le32(pb); /* 1=8-bit, 2=16-bit */
+ ea->num_channels = get_le32(pb);
+ ea->audio_codec = CODEC_ID_ADPCM_IMA_EA_SEAD;
+
+ return 1;
+}
+
+static int process_video_header_mdec(AVFormatContext *s)
+{
+ EaDemuxContext *ea = s->priv_data;
+ ByteIOContext *pb = s->pb;
+ url_fskip(pb, 4);
+ ea->width = get_le16(pb);
+ ea->height = get_le16(pb);
+ ea->time_base = (AVRational){1,15};
+ ea->video_codec = CODEC_ID_MDEC;
+ return 1;
+}
+
+static int process_video_header_vp6(AVFormatContext *s)
+{
+ EaDemuxContext *ea = s->priv_data;
+ ByteIOContext *pb = s->pb;
+
+ url_fskip(pb, 16);
+ ea->time_base.den = get_le32(pb);
+ ea->time_base.num = get_le32(pb);
+ ea->video_codec = CODEC_ID_VP6;
+
+ return 1;
+}
+
+/*
+ * Process EA file header
+ * Returns 1 if the EA file is valid and successfully opened, 0 otherwise
+ */
+static int process_ea_header(AVFormatContext *s) {
+ uint32_t blockid, size = 0;
+ EaDemuxContext *ea = s->priv_data;
+ ByteIOContext *pb = s->pb;
+ int i;
+
+ for (i=0; i<5 && (!ea->audio_codec || !ea->video_codec); i++) {
+ unsigned int startpos = url_ftell(pb);
+ int err = 0;
+
+ blockid = get_le32(pb);
+ size = get_le32(pb);
+ if (i == 0)
+ ea->big_endian = size > 0x000FFFFF;
+ if (ea->big_endian)
+ size = av_bswap32(size);
+
+ switch (blockid) {
+ case ISNh_TAG:
+ if (get_le32(pb) != EACS_TAG) {
+ av_log (s, AV_LOG_ERROR, "unknown 1SNh headerid\n");
+ return 0;
+ }
+ err = process_audio_header_eacs(s);
+ break;
+
+ case SCHl_TAG :
+ case SHEN_TAG :
+ blockid = get_le32(pb);
+ if (blockid == GSTR_TAG) {
+ url_fskip(pb, 4);
+ } else if ((blockid & 0xFFFF)!=PT00_TAG) {
+ av_log (s, AV_LOG_ERROR, "unknown SCHl headerid\n");
+ return 0;
+ }
+ err = process_audio_header_elements(s);
+ break;
+
+ case SEAD_TAG:
+ err = process_audio_header_sead(s);
+ break;
+
+ case MVIh_TAG :
+ ea->video_codec = CODEC_ID_CMV;
+ ea->time_base = (AVRational){0,0};
+ break;
+
+ case kVGT_TAG:
+ ea->video_codec = CODEC_ID_TGV;
+ ea->time_base = (AVRational){0,0};
+ break;
+
+ case mTCD_TAG :
+ err = process_video_header_mdec(s);
+ break;
+
+ case MPCh_TAG:
+ ea->video_codec = CODEC_ID_MPEG2VIDEO;
+ break;
+
+ case pQGT_TAG:
+ case TGQs_TAG:
+ ea->video_codec = CODEC_ID_TGQ;
+ break;
+
+ case pIQT_TAG:
+ ea->video_codec = CODEC_ID_TQI;
+ break;
+
+ case MADk_TAG :
+ ea->video_codec = CODEC_ID_MAD;
+ break;
+
+ case MVhd_TAG :
+ err = process_video_header_vp6(s);
+ break;
+ }
+
+ if (err < 0) {
+ av_log(s, AV_LOG_ERROR, "error parsing header: %i\n", err);
+ return err;
+ }
+
+ url_fseek(pb, startpos + size, SEEK_SET);
+ }
+
+ url_fseek(pb, 0, SEEK_SET);