changeset 1528:32d49970f01a libavformat

Divide first audio buffer chunk into atomary bufffers. This slightly simplifies decoder and removes potential audio buffer overrun.
author kostya
date Sun, 19 Nov 2006 05:30:43 +0000
parents 185cafb49ae8
children 07898e88c5b9
files sierravmd.c
diffstat 1 files changed, 34 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/sierravmd.c	Sat Nov 18 20:34:24 2006 +0000
+++ b/sierravmd.c	Sun Nov 19 05:30:43 2006 +0000
@@ -87,6 +87,7 @@
     int64_t current_video_pts = 0, current_audio_pts = 0;
     unsigned char chunk[BYTES_PER_FRAME_RECORD];
     int num, den;
+    int sound_buffers;
 
     /* fetch the main header, including the 2 header length bytes */
     url_fseek(pb, 0, SEEK_SET);
@@ -146,13 +147,14 @@
 
     raw_frame_table = NULL;
     vmd->frame_table = NULL;
+    sound_buffers = LE_16(&vmd->vmd_header[808]);
     raw_frame_table_size = vmd->frame_count * 6;
     raw_frame_table = av_malloc(raw_frame_table_size);
     if(vmd->frame_count * vmd->frames_per_block  >= UINT_MAX / sizeof(vmd_frame_t)){
         av_log(s, AV_LOG_ERROR, "vmd->frame_count * vmd->frames_per_block too large\n");
         return -1;
     }
-    vmd->frame_table = av_malloc(vmd->frame_count * vmd->frames_per_block * sizeof(vmd_frame_t));
+    vmd->frame_table = av_malloc((vmd->frame_count * vmd->frames_per_block + sound_buffers) * sizeof(vmd_frame_t));
     if (!raw_frame_table || !vmd->frame_table) {
         av_free(raw_frame_table);
         av_free(vmd->frame_table);
@@ -182,14 +184,43 @@
                 continue;
             switch(type) {
             case 1: /* Audio Chunk */
+                /* first audio chunk contains several audio buffers */
+                if(current_audio_pts){
                 vmd->frame_table[total_frames].frame_offset = current_offset;
                 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;
+                current_audio_pts += pts_inc;
+                }else{
+                    uint32_t flags;
+                    int k;
+                    int noff;
+                    int64_t pos;
+
+                    pos = url_ftell(pb);
+                    url_fseek(pb, current_offset, SEEK_SET);
+                    flags = get_le32(pb);
+                    noff = 4;
+                    url_fseek(pb, pos, SEEK_SET);
+                    av_log(s, AV_LOG_DEBUG, "Sound mapping = %08X (%i bufs)\n", flags, sound_buffers);
+                    for(k = 0; k < sound_buffers - 1; k++){
+                        if(flags & 1) { /* silent block */
+                            vmd->frame_table[total_frames].frame_size = 0;
+                        }else{
+                            vmd->frame_table[total_frames].frame_size = st->codec->block_align + (st->codec->block_align & 1);
+                        }
+                        noff += vmd->frame_table[total_frames].frame_size;
+                        vmd->frame_table[total_frames].frame_offset = current_offset + noff;
+                        vmd->frame_table[total_frames].stream_index = vmd->audio_stream_index;
+                        memcpy(vmd->frame_table[total_frames].frame_record, chunk, BYTES_PER_FRAME_RECORD);
+                        vmd->frame_table[total_frames].pts = current_audio_pts;
+                        total_frames++;
+                        current_audio_pts += pts_inc;
+                        flags >>= 1;
+                    }
+                }
                 break;
             case 2: /* Video Chunk */
                 vmd->frame_table[total_frames].frame_offset = current_offset;