*/
static int process_audio_header_elements(AVFormatContext *s)
{
- int inHeader = 1;
EaDemuxContext *ea = s->priv_data;
- AVIOContext *pb = s->pb;
+ AVIOContext *pb = s->pb;
+ int inHeader = 1;
int compression_type = -1, revision = -1, revision2 = -1;
- ea->bytes = 2;
- ea->sample_rate = -1;
+ ea->bytes = 2;
+ ea->sample_rate = -1;
ea->num_channels = 1;
- while (!pb->eof_reached && inHeader) {
+ while (!url_feof(pb) && inHeader) {
int inSubheader;
uint8_t byte;
byte = avio_r8(pb);
switch (byte) {
case 0xFD:
- av_log (s, AV_LOG_DEBUG, "entered audio subheader\n");
+ av_log(s, AV_LOG_DEBUG, "entered audio subheader\n");
inSubheader = 1;
- while (!pb->eof_reached && inSubheader) {
+ while (!url_feof(pb) && inSubheader) {
uint8_t subbyte;
subbyte = avio_r8(pb);
}
switch (compression_type) {
- case 0: ea->audio_codec = AV_CODEC_ID_PCM_S16LE; break;
- case 7: ea->audio_codec = AV_CODEC_ID_ADPCM_EA; break;
+ case 0:
+ ea->audio_codec = AV_CODEC_ID_PCM_S16LE;
+ break;
+ case 7:
+ ea->audio_codec = AV_CODEC_ID_ADPCM_EA;
+ break;
case -1:
switch (revision) {
- case 1: ea->audio_codec = AV_CODEC_ID_ADPCM_EA_R1; break;
- case 2: ea->audio_codec = AV_CODEC_ID_ADPCM_EA_R2; break;
- case 3: ea->audio_codec = AV_CODEC_ID_ADPCM_EA_R3; break;
- case -1: break;
+ case 1:
+ ea->audio_codec = AV_CODEC_ID_ADPCM_EA_R1;
+ break;
+ case 2:
+ ea->audio_codec = AV_CODEC_ID_ADPCM_EA_R2;
+ break;
+ case 3:
+ ea->audio_codec = AV_CODEC_ID_ADPCM_EA_R3;
+ break;
+ case -1:
+ break;
default:
- av_log(s, AV_LOG_ERROR,
- "unsupported stream type; revision=%i\n", revision);
+ avpriv_request_sample(s, "stream type; revision=%i", revision);
return 0;
}
switch (revision2) {
- case 8: ea->audio_codec = AV_CODEC_ID_PCM_S16LE_PLANAR; break;
+ case 8:
+ ea->audio_codec = AV_CODEC_ID_PCM_S16LE_PLANAR;
+ break;
case 10:
- ea->audio_codec = AV_CODEC_ID_ADPCM_EA_R2;
+ switch (revision) {
+ case -1:
+ case 2: ea->audio_codec = AV_CODEC_ID_ADPCM_EA_R1; break;
+ case 3: ea->audio_codec = AV_CODEC_ID_ADPCM_EA_R2; break;
+ default:
+ avpriv_request_sample(s, "stream type; revision=%i, revision2=%i", revision, revision2);
+ return 0;
+ }
break;
- case 16: ea->audio_codec = AV_CODEC_ID_MP3; break;
- case -1: break;
+ case 16:
+ ea->audio_codec = AV_CODEC_ID_MP3;
+ break;
+ case -1:
+ break;
default:
ea->audio_codec = AV_CODEC_ID_NONE;
- av_log(s, AV_LOG_ERROR,
- "unsupported stream type; revision2=%i\n", revision2);
+ avpriv_request_sample(s, "stream type; revision2=%i", revision2);
return 0;
}
break;
default:
- avpriv_request_sample(s, "stream type; compression_type=%i", compression_type);
- av_log(s, AV_LOG_ERROR,
- "unsupported stream type; compression_type=%i\n",
- compression_type);
++ avpriv_request_sample(s,
++ "stream type; compression_type=%i",
++ compression_type);
return 0;
}
switch (compression_type) {
case 0:
switch (ea->bytes) {
- case 1: ea->audio_codec = AV_CODEC_ID_PCM_S8; break;
- case 2: ea->audio_codec = AV_CODEC_ID_PCM_S16LE; break;
+ case 1:
+ ea->audio_codec = AV_CODEC_ID_PCM_S8;
+ break;
+ case 2:
+ ea->audio_codec = AV_CODEC_ID_PCM_S16LE;
+ break;
}
break;
- case 1: ea->audio_codec = AV_CODEC_ID_PCM_MULAW; ea->bytes = 1; break;
- case 2: ea->audio_codec = AV_CODEC_ID_ADPCM_IMA_EA_EACS; break;
+ case 1:
+ ea->audio_codec = AV_CODEC_ID_PCM_MULAW;
+ ea->bytes = 1;
+ break;
+ case 2:
+ ea->audio_codec = AV_CODEC_ID_ADPCM_IMA_EA_EACS;
+ break;
default:
- avpriv_request_sample(s, "stream type; audio compression_type=%i", compression_type);
- av_log(s, AV_LOG_ERROR,
- "unsupported stream type; audio compression_type=%i\n",
- compression_type);
++ avpriv_request_sample(s,
++ "stream type; audio compression_type=%i",
++ compression_type);
}
return 1;
static int process_video_header_vp6(AVFormatContext *s)
{
EaDemuxContext *ea = s->priv_data;
- AVIOContext *pb = s->pb;
+ AVIOContext *pb = s->pb;
- avio_skip(pb, 16);
+ avio_skip(pb, 8);
+ ea->nb_frames = avio_rl32(pb);
+ avio_skip(pb, 4);
ea->time_base.den = avio_rl32(pb);
ea->time_base.num = avio_rl32(pb);
- ea->video_codec = AV_CODEC_ID_VP6;
+ if (ea->time_base.den <= 0 || ea->time_base.num <= 0) {
+ av_log(s, AV_LOG_ERROR, "Timebase is invalid\n");
+ return AVERROR_INVALIDDATA;
+ }
+ ea->video_codec = AV_CODEC_ID_VP6;
return 1;
}
size = av_bswap32(size);
switch (blockid) {
- case ISNh_TAG:
- if (avio_rl32(pb) != EACS_TAG) {
- avpriv_request_sample(s, "unknown 1SNh headerid");
- return 0;
- }
- err = process_audio_header_eacs(s);
- break;
+ case ISNh_TAG:
+ if (avio_rl32(pb) != EACS_TAG) {
- av_log(s, AV_LOG_ERROR, "unknown 1SNh headerid\n");
++ avpriv_request_sample(s, "unknown 1SNh headerid");
+ return 0;
+ }
+ err = process_audio_header_eacs(s);
+ break;
- case SCHl_TAG :
- case SHEN_TAG :
- blockid = avio_rl32(pb);
- if (blockid == GSTR_TAG) {
- avio_skip(pb, 4);
- } else if ((blockid & 0xFFFF)!=PT00_TAG) {
- avpriv_request_sample(s, "unknown SCHl headerid");
- return 0;
- }
- err = process_audio_header_elements(s);
- break;
+ case SCHl_TAG:
+ case SHEN_TAG:
+ blockid = avio_rl32(pb);
+ if (blockid == GSTR_TAG) {
+ avio_skip(pb, 4);
+ } else if ((blockid & 0xFFFF) != PT00_TAG) {
- av_log(s, AV_LOG_ERROR, "unknown SCHl headerid\n");
++ avpriv_request_sample(s, "unknown SCHl headerid");
+ return 0;
+ }
+ err = process_audio_header_elements(s);
+ break;
- case SEAD_TAG:
- err = process_audio_header_sead(s);
- break;
+ case SEAD_TAG:
+ err = process_audio_header_sead(s);
+ break;
- case MVIh_TAG :
- err = process_video_header_cmv(s);
- break;
+ case MVIh_TAG:
+ err = process_video_header_cmv(s);
+ break;
- case kVGT_TAG:
- ea->video_codec = AV_CODEC_ID_TGV;
- break;
+ case kVGT_TAG:
+ ea->video_codec = AV_CODEC_ID_TGV;
- ea->time_base = (AVRational) { 1, 15 };
+ break;
- case mTCD_TAG :
- err = process_video_header_mdec(s);
- break;
+ case mTCD_TAG:
+ err = process_video_header_mdec(s);
+ break;
- case MPCh_TAG:
- ea->video_codec = AV_CODEC_ID_MPEG2VIDEO;
- break;
+ case MPCh_TAG:
+ ea->video_codec = AV_CODEC_ID_MPEG2VIDEO;
+ break;
- case pQGT_TAG:
- case TGQs_TAG:
- ea->video_codec = AV_CODEC_ID_TGQ;
- break;
+ case pQGT_TAG:
+ case TGQs_TAG:
+ ea->video_codec = AV_CODEC_ID_TGQ;
+ break;
- case pIQT_TAG:
- ea->video_codec = AV_CODEC_ID_TQI;
- break;
+ case pIQT_TAG:
+ ea->video_codec = AV_CODEC_ID_TQI;
+ break;
- case MADk_TAG :
- ea->video_codec = AV_CODEC_ID_MAD;
- break;
+ case MADk_TAG:
+ ea->video_codec = AV_CODEC_ID_MAD;
+ break;
- case MVhd_TAG :
- err = process_video_header_vp6(s);
- break;
+ case MVhd_TAG:
+ err = process_video_header_vp6(s);
+ break;
}
if (err < 0) {
if (!st)
return AVERROR(ENOMEM);
ea->video_stream_index = st->index;
- st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
- st->codec->codec_id = ea->video_codec;
+ st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
+ st->codec->codec_id = ea->video_codec;
+ // parsing is necessary to make FFmpeg generate correct timestamps
+ if (st->codec->codec_id == AV_CODEC_ID_MPEG2VIDEO)
+ st->need_parsing = AVSTREAM_PARSE_HEADERS;
- st->codec->codec_tag = 0; /* no fourcc */
- st->codec->width = ea->width;
- st->codec->height = ea->height;
- st->duration = st->nb_frames = ea->nb_frames;
+ st->codec->codec_tag = 0; /* no fourcc */
+ st->codec->width = ea->width;
+ st->codec->height = ea->height;
- avpriv_set_pts_info(st, 33, ea->time_base.num, ea->time_base.den);
- st->avg_frame_rate = (AVRational) { ea->time_base.den,
- ea->time_base.num };
++ st->duration = st->nb_frames = ea->nb_frames;
+ if (ea->time_base.num)
+ avpriv_set_pts_info(st, 64, ea->time_base.num, ea->time_base.den);
- st->r_frame_rate =
- st->avg_frame_rate = av_inv_q(ea->time_base);
++ st->r_frame_rate =
++ st->avg_frame_rate = av_inv_q(ea->time_base);
}
if (ea->audio_codec) {
return 1;
}
- static int ea_read_packet(AVFormatContext *s,
- AVPacket *pkt)
+ static int ea_read_packet(AVFormatContext *s, AVPacket *pkt)
{
EaDemuxContext *ea = s->priv_data;
- AVIOContext *pb = s->pb;
- int ret = 0;
- int packet_read = 0;
+ AVIOContext *pb = s->pb;
+ int partial_packet = 0;
unsigned int chunk_type, chunk_size;
- int key = 0;
+ int ret = 0, packet_read = 0, key = 0;
int av_uninit(num_samples);
- while (!packet_read) {
+ while (!packet_read || partial_packet) {
chunk_type = avio_rl32(pb);
chunk_size = ea->big_endian ? avio_rb32(pb) : avio_rl32(pb);
if (chunk_size <= 8)
key = AV_PKT_FLAG_KEY;
case MV0F_TAG:
get_video_packet:
- ret = av_get_packet(pb, pkt, chunk_size);
- if (ret < 0)
- return ret;
+ if (partial_packet) {
+ ret = av_append_packet(pb, pkt, chunk_size);
+ } else
+ ret = av_get_packet(pb, pkt, chunk_size);
+ if (ret < 0) {
+ packet_read = 1;
+ break;
+ }
+ partial_packet = chunk_type == MVIh_TAG;
pkt->stream_index = ea->video_stream_index;
- pkt->flags |= key;
- packet_read = 1;
+ pkt->flags |= key;
+ packet_read = 1;
break;
default: