Ticket #1432: avi-mp3-v2.patch

File avi-mp3-v2.patch, 3.7 KB (added by mjs973, 4 years ago)
  • libavformat/avidec.c

    From 9b49a37769c7a80906e9ac3fae2c4d971f855587 Mon Sep 17 00:00:00 2001
    From: Mike Scheutzow <mjs973@optonline.net>
    Date: Wed,  4 Jul 2012 11:28:07 -0400
    Subject: [PATCH] avidec: Fix timestamp calc for MP3 frames.
    
    Correctly handle the demuxing of variable length MP3 frames from an
    .avi container. The bad code was using the frame byte length to calculate
    a timestamp, which is completely broken. The existing avi muxer already
    properly handles the muxing and index creation for variable length MP3 
    audio frames.
    
    Fixes the sample file in trac 1432. Fate passes. Tested with both Constant
    Frame Rate and Variable Frame Rate avi files.
    
    Signed-off-by: Mike Scheutzow <mjs973@optonline.net>
    ---
     libavformat/avidec.c |   22 ++++++++++++++++++++++
     1 files changed, 22 insertions(+), 0 deletions(-)
    
    diff --git a/libavformat/avidec.c b/libavformat/avidec.c
    index fea0694..1fca257 100644
    a b static int guess_ni_flag(AVFormatContext *s); 
    116116           (tag >> 24) & 0xff,                          \ 
    117117           size) 
    118118 
     119/* calculate the duration of the current frame, in units of AVStream.time_base. 
     120 * For video, or audio frames with variable byte length, the output value 
     121 * is defined to be '1'. 
     122 */ 
    119123static inline int get_duration(AVIStream *ast, int len){ 
    120124    if(ast->sample_size){ 
    121125        return len; 
    static int avi_read_header(AVFormatContext *s) 
    656660                    if (ret < 0) 
    657661                        return ret; 
    658662                    ast->dshow_block_align= st->codec->block_align; 
     663                    if (st->codec->codec_id == CODEC_ID_MP3 && !ast->sample_size) { 
     664                        /* st->time_base gives index entry play duration */ 
     665                        int fps = 0; 
     666                        if (st->time_base.num) { 
     667                            fps = st->time_base.den / st->time_base.num; 
     668                        } 
     669                        if (fps > 41) { 
     670                            // highest valid frame per sec is 48000/1152 
     671                            av_log(s, AV_LOG_WARNING, "st%d: MP3 frame rate is invalid (%d FPS)\n", st->id, fps); 
     672                        } else { 
     673                            /* handle frames as variable byte length */ 
     674                            ast->dshow_block_align = 0; 
     675                        } 
     676                    } 
    659677                    if(ast->sample_size && st->codec->block_align && ast->sample_size != st->codec->block_align){ 
    660678                        av_log(s, AV_LOG_WARNING, "sample size (%d) != block align (%d)\n", ast->sample_size, st->codec->block_align); 
    661679                        ast->sample_size= st->codec->block_align; 
    resync: 
    11771195                int index; 
    11781196                assert(st->index_entries); 
    11791197 
     1198                /* retrieve index of next key frame >= ast->frame_offset */ 
    11801199                index= av_index_search_timestamp(st, ast->frame_offset, 0); 
    11811200                e= &st->index_entries[index]; 
    11821201 
    resync: 
    12041223            } else { 
    12051224                pkt->flags |= AV_PKT_FLAG_KEY; 
    12061225            } 
     1226            /* update stream time to frame timestamp to be retrieved next. */ 
    12071227            ast->frame_offset += get_duration(ast, pkt->size); 
    12081228        } 
    12091229        ast->remaining -= size; 
    static int avi_read_idx1(AVFormatContext *s, int size) 
    12941314        // switch to non-interleaved to get correct timestamps 
    12951315        if(last_pos == pos) 
    12961316            avi->non_interleaved= 1; 
     1317        // in the file index, variable-frame-rate is emulated by using 
     1318        // index entries with len==0 
    12971319        if(last_idx != pos && len) { 
    12981320            av_add_index_entry(st, pos, ast->cum_len, len, 0, (flags&AVIIF_INDEX) ? AVINDEX_KEYFRAME : 0); 
    12991321            last_idx= pos;