X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fipmovie.c;h=372a926266403ede4264c83695264e0496b49c54;hb=8bf0f969547ec694a314764e7ca3d883bf416b21;hp=2b0d955df965dbedddc53b37911be3c98c8aca13;hpb=bad5537e2c2caeb5deb1ff9d771ea01058b8010c;p=ffmpeg diff --git a/libavformat/ipmovie.c b/libavformat/ipmovie.c index 2b0d955df96..372a9262664 100644 --- a/libavformat/ipmovie.c +++ b/libavformat/ipmovie.c @@ -20,7 +20,7 @@ */ /** - * @file libavformat/ipmovie.c + * @file * Interplay MVE file demuxer * by Mike Melanson (melanson@pcisys.net) * For more information regarding the Interplay MVE file format, visit: @@ -40,13 +40,12 @@ #define DEBUG_IPMOVIE 0 #if DEBUG_IPMOVIE +#undef printf #define debug_ipmovie printf #else static inline void debug_ipmovie(const char *format, ...) { } #endif -#define IPMOVIE_SIGNATURE "Interplay MVE File\x1A\0" -#define IPMOVIE_SIGNATURE_SIZE 20 #define CHUNK_PREAMBLE_SIZE 4 #define OPCODE_PREAMBLE_SIZE 4 @@ -92,9 +91,9 @@ typedef struct IPMVEContext { unsigned char *buf; int buf_size; - float fps; - int frame_pts_inc; + uint64_t frame_pts_inc; + unsigned int video_bpp; unsigned int video_width; unsigned int video_height; int64_t video_pts; @@ -125,7 +124,6 @@ static int load_ipmovie_packet(IPMVEContext *s, ByteIOContext *pb, AVPacket *pkt) { int chunk_type; - int64_t audio_pts = 0; if (s->audio_chunk_offset) { @@ -138,16 +136,11 @@ static int load_ipmovie_packet(IPMVEContext *s, ByteIOContext *pb, url_fseek(pb, s->audio_chunk_offset, SEEK_SET); s->audio_chunk_offset = 0; - /* figure out the audio pts */ - audio_pts = 90000; - audio_pts *= s->audio_frame_count; - audio_pts /= s->audio_sample_rate; - if (s->audio_chunk_size != av_get_packet(pb, pkt, s->audio_chunk_size)) return CHUNK_EOF; pkt->stream_index = s->audio_stream_index; - pkt->pts = audio_pts; + pkt->pts = s->audio_frame_count; /* audio frame maintenance */ if (s->audio_type != CODEC_ID_INTERPLAY_DPCM) @@ -158,7 +151,7 @@ static int load_ipmovie_packet(IPMVEContext *s, ByteIOContext *pb, (s->audio_chunk_size - 6) / s->audio_channels; debug_ipmovie("sending audio frame with pts %"PRId64" (%d audio frames)\n", - audio_pts, s->audio_frame_count); + pkt->pts, s->audio_frame_count); chunk_type = CHUNK_VIDEO; @@ -326,10 +319,9 @@ static int process_ipmovie_chunk(IPMVEContext *s, ByteIOContext *pb, chunk_type = CHUNK_BAD; break; } - s->fps = 1000000.0 / (AV_RL32(&scratch[0]) * AV_RL16(&scratch[4])); - s->frame_pts_inc = 90000 / s->fps; + s->frame_pts_inc = ((uint64_t)AV_RL32(&scratch[0])) * AV_RL16(&scratch[4]); debug_ipmovie(" %.2f frames/second (timer div = %d, subdiv = %d)\n", - s->fps, AV_RL32(&scratch[0]), AV_RL16(&scratch[4])); + 1000000.0/s->frame_pts_inc, AV_RL32(&scratch[0]), AV_RL16(&scratch[4])); break; case OPCODE_INIT_AUDIO_BUFFERS: @@ -384,6 +376,11 @@ static int process_ipmovie_chunk(IPMVEContext *s, ByteIOContext *pb, } s->video_width = AV_RL16(&scratch[0]) * 8; s->video_height = AV_RL16(&scratch[2]) * 8; + if (opcode_version < 2 || !AV_RL16(&scratch[6])) { + s->video_bpp = 8; + } else { + s->video_bpp = 16; + } debug_ipmovie("video resolution: %d x %d\n", s->video_width, s->video_height); break; @@ -506,12 +503,18 @@ static int process_ipmovie_chunk(IPMVEContext *s, ByteIOContext *pb, return chunk_type; } +static const char signature[] = "Interplay MVE File\x1A\0\x1A"; + static int ipmovie_probe(AVProbeData *p) { - if (strncmp(p->buf, IPMOVIE_SIGNATURE, IPMOVIE_SIGNATURE_SIZE) != 0) - return 0; + uint8_t *b = p->buf; + uint8_t *b_end = p->buf + p->buf_size - sizeof(signature); + do { + if (memcmp(b++, signature, sizeof(signature)) == 0) + return AVPROBE_SCORE_MAX; + } while (b < b_end); - return AVPROBE_SCORE_MAX; + return 0; } static int ipmovie_read_header(AVFormatContext *s, @@ -523,14 +526,22 @@ static int ipmovie_read_header(AVFormatContext *s, AVStream *st; unsigned char chunk_preamble[CHUNK_PREAMBLE_SIZE]; int chunk_type; - + uint8_t signature_buffer[sizeof(signature)]; + + get_buffer(pb, signature_buffer, sizeof(signature_buffer)); + while (memcmp(signature_buffer, signature, sizeof(signature))) { + memmove(signature_buffer, signature_buffer + 1, sizeof(signature_buffer) - 1); + signature_buffer[sizeof(signature_buffer) - 1] = get_byte(pb); + if (url_feof(pb)) + return AVERROR_EOF; + } /* initialize private context members */ ipmovie->video_pts = ipmovie->audio_frame_count = 0; ipmovie->audio_chunk_offset = ipmovie->video_chunk_offset = ipmovie->decode_map_chunk_offset = 0; /* on the first read, this will position the stream at the first chunk */ - ipmovie->next_chunk_offset = IPMOVIE_SIGNATURE_SIZE + 6; + ipmovie->next_chunk_offset = url_ftell(pb) + 4; /* process the first chunk which should be CHUNK_INIT_VIDEO */ if (process_ipmovie_chunk(ipmovie, pb, &pkt) != CHUNK_INIT_VIDEO) @@ -553,13 +564,14 @@ static int ipmovie_read_header(AVFormatContext *s, st = av_new_stream(s, 0); if (!st) return AVERROR(ENOMEM); - av_set_pts_info(st, 33, 1, 90000); + av_set_pts_info(st, 63, 1, 1000000); ipmovie->video_stream_index = st->index; - st->codec->codec_type = CODEC_TYPE_VIDEO; + st->codec->codec_type = AVMEDIA_TYPE_VIDEO; st->codec->codec_id = CODEC_ID_INTERPLAY_VIDEO; st->codec->codec_tag = 0; /* no fourcc */ st->codec->width = ipmovie->video_width; st->codec->height = ipmovie->video_height; + st->codec->bits_per_coded_sample = ipmovie->video_bpp; /* palette considerations */ st->codec->palctrl = &ipmovie->palette_control; @@ -568,9 +580,9 @@ static int ipmovie_read_header(AVFormatContext *s, st = av_new_stream(s, 0); if (!st) return AVERROR(ENOMEM); - av_set_pts_info(st, 33, 1, 90000); + av_set_pts_info(st, 32, 1, ipmovie->audio_sample_rate); ipmovie->audio_stream_index = st->index; - st->codec->codec_type = CODEC_TYPE_AUDIO; + st->codec->codec_type = AVMEDIA_TYPE_AUDIO; st->codec->codec_id = ipmovie->audio_type; st->codec->codec_tag = 0; /* no tag */ st->codec->channels = ipmovie->audio_channels;