# HG changeset patch # User kostya # Date 1163395099 0 # Node ID deaec052eec4b2bc31f9f7da85d27694af729e44 # Parent 89f88d324eeaccf2b1cc9e1716661f219793a698 Simplify VMD demuxer (but it still does not work right) diff -r 89f88d324eea -r deaec052eec4 sierravmd.c --- a/sierravmd.c Sun Nov 12 20:08:09 2006 +0000 +++ b/sierravmd.c Mon Nov 13 05:18:19 2006 +0000 @@ -45,11 +45,6 @@ int video_stream_index; int audio_stream_index; - unsigned int audio_type; - unsigned int audio_samplerate; - unsigned int audio_bits; - unsigned int audio_channels; - unsigned int frame_count; unsigned int frames_per_block; vmd_frame_t *frame_table; @@ -57,8 +52,6 @@ int sample_rate; int64_t audio_sample_counter; - int audio_frame_divisor; - int audio_block_align; int skiphdr; unsigned char vmd_header[VMD_HEADER_SIZE]; @@ -78,79 +71,42 @@ return AVPROBE_SCORE_MAX / 2; } -/* This is a support function to determine the duration, in sample - * frames, of a particular audio chunk, taking into account silent - * encodings. */ -static int vmd_calculate_audio_duration(unsigned char *audio_chunk, - int audio_chunk_size, int block_align) -{ - unsigned char *p = audio_chunk + 16; - unsigned char *p_end = audio_chunk + audio_chunk_size; - int total_samples = 0; - unsigned int sound_flags; - - if (audio_chunk_size < 16) - return 0; - if (audio_chunk_size == block_align + 16) - return block_align; - if (audio_chunk_size == block_align + 17) - return block_align; - - sound_flags = LE_32(p); - p += 4; - while (p < p_end) { - total_samples += block_align; - if ((sound_flags & 0x01) == 0) - p += block_align; - sound_flags >>= 1; - } - av_log(NULL,0,"Got %i samples for size %i map %08X\n", total_samples, audio_chunk_size, LE_32(audio_chunk)); - - return total_samples; -} - static int vmd_read_header(AVFormatContext *s, AVFormatParameters *ap) { VmdDemuxContext *vmd = (VmdDemuxContext *)s->priv_data; ByteIOContext *pb = &s->pb; - AVStream *st; + AVStream *st, *vst; unsigned int toc_offset; unsigned char *raw_frame_table; int raw_frame_table_size; offset_t current_offset; int i, j; unsigned int total_frames; - int64_t video_pts_inc = 0; - int64_t current_video_pts = 0; + int64_t pts_inc = 1; + int64_t current_video_pts = 0, current_audio_pts = 0; unsigned char chunk[BYTES_PER_FRAME_RECORD]; - int lastframe = 0; + int num, den; /* fetch the main header, including the 2 header length bytes */ url_fseek(pb, 0, SEEK_SET); if (get_buffer(pb, vmd->vmd_header, VMD_HEADER_SIZE) != VMD_HEADER_SIZE) return AVERROR_IO; - vmd->audio_sample_counter = 0; - vmd->audio_frame_divisor = 1; - vmd->audio_block_align = 1; - /* start up the decoders */ - st = av_new_stream(s, 0); - if (!st) + vst = av_new_stream(s, 0); + if (!vst) return AVERROR_NOMEM; - av_set_pts_info(st, 33, 1, 90000); - vmd->video_stream_index = st->index; - st->codec->codec_type = CODEC_TYPE_VIDEO; - st->codec->codec_id = CODEC_ID_VMDVIDEO; - st->codec->codec_tag = 0; /* no fourcc */ - st->codec->width = LE_16(&vmd->vmd_header[12]); - st->codec->height = LE_16(&vmd->vmd_header[14]); - st->codec->time_base.num = 1; - st->codec->time_base.den = 10; - st->codec->extradata_size = VMD_HEADER_SIZE; - st->codec->extradata = av_mallocz(VMD_HEADER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE); - memcpy(st->codec->extradata, vmd->vmd_header, VMD_HEADER_SIZE); + av_set_pts_info(vst, 33, 1, 10); + vmd->video_stream_index = vst->index; + vst->codec->codec_type = CODEC_TYPE_VIDEO; + vst->codec->codec_id = CODEC_ID_VMDVIDEO; + vst->codec->codec_tag = 0; /* no fourcc */ + vst->codec->width = LE_16(&vmd->vmd_header[12]); + vst->codec->height = LE_16(&vmd->vmd_header[14]); + vst->codec->extradata_size = VMD_HEADER_SIZE; + vst->codec->extradata = av_mallocz(VMD_HEADER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE); + memcpy(vst->codec->extradata, vmd->vmd_header, VMD_HEADER_SIZE); /* if sample rate is 0, assume no audio */ vmd->sample_rate = LE_16(&vmd->vmd_header[804]); @@ -158,35 +114,29 @@ st = av_new_stream(s, 0); if (!st) return AVERROR_NOMEM; - av_set_pts_info(st, 33, 1, 90000); vmd->audio_stream_index = st->index; st->codec->codec_type = CODEC_TYPE_AUDIO; st->codec->codec_id = CODEC_ID_VMDAUDIO; st->codec->codec_tag = 0; /* no fourcc */ - st->codec->channels = vmd->audio_channels = (vmd->vmd_header[811] & 0x80) ? 2 : 1; + st->codec->channels = (vmd->vmd_header[811] & 0x80) ? 2 : 1; st->codec->sample_rate = vmd->sample_rate; - st->codec->block_align = vmd->audio_block_align = - LE_16(&vmd->vmd_header[806]); + st->codec->block_align = LE_16(&vmd->vmd_header[806]); if (st->codec->block_align & 0x8000) { st->codec->bits_per_sample = 16; st->codec->block_align = -(st->codec->block_align - 0x10000); - vmd->audio_block_align = -(vmd->audio_block_align - 0x10000); } else { st->codec->bits_per_sample = 8; } st->codec->bit_rate = st->codec->sample_rate * st->codec->bits_per_sample * st->codec->channels; - /* for calculating pts */ - vmd->audio_frame_divisor = st->codec->channels; - - video_pts_inc = 90000; - video_pts_inc *= st->codec->block_align; - video_pts_inc /= st->codec->sample_rate; - video_pts_inc /= st->codec->channels; - } else { - /* if no audio, assume 10 frames/second */ - video_pts_inc = 90000 / 10; + /* calculate pts */ + num = st->codec->block_align; + den = st->codec->sample_rate * st->codec->channels; + av_reduce(&den, &num, den, num, (1UL<<31)-1); + av_set_pts_info(vst, 33, num, den); + av_set_pts_info(st, 33, num, den); + pts_inc = num; } toc_offset = LE_32(&vmd->vmd_header[812]); @@ -236,24 +186,23 @@ vmd->frame_table[total_frames].stream_index = vmd->audio_stream_index; vmd->frame_table[total_frames].frame_size = size; memcpy(vmd->frame_table[total_frames].frame_record, chunk, BYTES_PER_FRAME_RECORD); + vmd->frame_table[total_frames].pts = current_audio_pts; total_frames++; + /* first audio chunk contains several audio buffers */ + current_audio_pts += (current_audio_pts == 0) ? LE_16(&vmd->vmd_header[808]) * pts_inc : pts_inc; break; case 2: /* Video Chunk */ vmd->frame_table[total_frames].frame_offset = current_offset; + vmd->frame_table[total_frames].stream_index = vmd->video_stream_index; vmd->frame_table[total_frames].frame_size = size; - vmd->frame_table[total_frames].stream_index = vmd->video_stream_index; memcpy(vmd->frame_table[total_frames].frame_record, chunk, BYTES_PER_FRAME_RECORD); vmd->frame_table[total_frames].pts = current_video_pts; - if (lastframe) { - vmd->frame_table[lastframe].pts = current_video_pts - video_pts_inc; - } - lastframe = total_frames; total_frames++; break; } current_offset += size; } - current_video_pts += video_pts_inc; + current_video_pts += pts_inc; } av_free(raw_frame_table); @@ -291,21 +240,11 @@ ret = AVERROR_IO; } pkt->stream_index = frame->stream_index; - if (frame->frame_record[0] == 0x02) - pkt->pts = frame->pts; - else { - pkt->pts = vmd->audio_sample_counter; - pkt->pts *= 90000; - pkt->pts /= vmd->sample_rate; - pkt->pts /= vmd->audio_channels; - vmd->audio_sample_counter += vmd_calculate_audio_duration( - pkt->data, pkt->size, vmd->audio_block_align); - - } - av_log(NULL, AV_LOG_INFO, " dispatching %s frame with %d bytes and pts %"PRId64" (%0.1f sec)\n", + pkt->pts = frame->pts; + av_log(NULL, AV_LOG_INFO, " dispatching %s frame with %d bytes and pts %"PRId64"\n", (frame->frame_record[0] == 0x02) ? "video" : "audio", frame->frame_size + BYTES_PER_FRAME_RECORD, - pkt->pts, (float)(pkt->pts / 90000.0)); + pkt->pts); vmd->current_frame++;