[vlc-devel] commit: Fixed ES frame rate estimation in mp4 file. (Laurent Aimar )

git version control git at videolan.org
Tue Oct 13 21:09:50 CEST 2009


vlc | branch: master | Laurent Aimar <fenrir at videolan.org> | Tue Oct 13 21:05:06 2009 +0200| [ebf27e98de4b870e3f4d8033b3918e417e738bd7] | committer: Laurent Aimar 

Fixed ES frame rate estimation in mp4 file.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=ebf27e98de4b870e3f4d8033b3918e417e738bd7
---

 modules/demux/mp4/mp4.c |   82 ++++++++++++++++++++++++++++++++++------------
 1 files changed, 60 insertions(+), 22 deletions(-)

diff --git a/modules/demux/mp4/mp4.c b/modules/demux/mp4/mp4.c
index 4353912..8cf0e3b 100644
--- a/modules/demux/mp4/mp4.c
+++ b/modules/demux/mp4/mp4.c
@@ -77,7 +77,8 @@ typedef struct
         much memory and with fast access */
 
     /* with this we can calculate dts/pts without waste memory */
-    uint64_t     i_first_dts;
+    uint64_t     i_first_dts;   /* DTS of the first sample */
+    uint64_t     i_last_dts;    /* DTS of the last sample */
     uint32_t     *p_sample_count_dts;
     uint32_t     *p_sample_delta_dts;   /* dts delta */
 
@@ -1204,7 +1205,7 @@ static int TrackCreateSamplesIndex( demux_t *p_demux,
     int64_t i_index;
     int64_t i_index_sample_used;
 
-    int64_t i_last_dts;
+    int64_t i_next_dts;
 
     /* Find stsz
      *  Gives the sample size for each samples. There is also a stz2 table
@@ -1259,15 +1260,16 @@ static int TrackCreateSamplesIndex( demux_t *p_demux,
      *  for fast research (problem with raw stream where a sample is sometime
      *  just channels*bits_per_sample/8 */
 
-    i_last_dts = 0;
+    i_next_dts = 0;
     i_index = 0; i_index_sample_used = 0;
     for( i_chunk = 0; i_chunk < p_demux_track->i_chunk_count; i_chunk++ )
     {
         mp4_chunk_t *ck = &p_demux_track->chunk[i_chunk];
         int64_t i_entry, i_sample_count, i;
 
-        /* save last dts */
-        ck->i_first_dts = i_last_dts;
+        /* save first dts */
+        ck->i_first_dts = i_next_dts;
+        ck->i_last_dts  = i_next_dts;
 
         /* count how many entries are needed for this chunk
          * for p_sample_delta_dts and p_sample_count_dts */
@@ -1304,11 +1306,12 @@ static int TrackCreateSamplesIndex( demux_t *p_demux,
 
             i_index_sample_used += i_used;
             i_sample_count -= i_used;
+            i_next_dts += i_used * stts->i_sample_delta[i_index];
 
             ck->p_sample_count_dts[i] = i_used;
             ck->p_sample_delta_dts[i] = stts->i_sample_delta[i_index];
-
-            i_last_dts += i_used * ck->p_sample_delta_dts[i];
+            if( i_used > 0 )
+                ck->i_last_dts = i_next_dts - ck->p_sample_delta_dts[i];
 
             if( i_index_sample_used >= stts->i_sample_count[i_index] )
             {
@@ -1386,11 +1389,53 @@ static int TrackCreateSamplesIndex( demux_t *p_demux,
 
     msg_Dbg( p_demux, "track[Id 0x%x] read %d samples length:%"PRId64"s",
              p_demux_track->i_track_ID, p_demux_track->i_sample_count,
-             i_last_dts / p_demux_track->i_timescale );
+             i_next_dts / p_demux_track->i_timescale );
 
     return VLC_SUCCESS;
 }
 
+/**
+ * It computes the sample rate for a video track using the given sample
+ * description index
+ */
+static void TrackGetESSampleRate( unsigned *pi_num, unsigned *pi_den,
+                                  const mp4_track_t *p_track,
+                                  unsigned i_sd_index,
+                                  unsigned i_chunk )
+{
+    *pi_num = 0;
+    *pi_den = 0;
+
+    if( p_track->i_chunk_count <= 0 )
+        return;
+
+    /* */
+    const mp4_chunk_t *p_chunk = &p_track->chunk[i_chunk];
+    while( p_chunk > &p_track->chunk[0] &&
+           p_chunk[-1].i_sample_description_index == i_sd_index )
+    {
+        p_chunk--;
+    }
+
+    uint64_t i_sample = 0;
+    uint64_t i_first_dts = p_chunk->i_first_dts;
+    uint64_t i_last_dts;
+    do
+    {
+        i_sample += p_chunk->i_sample_count;
+        i_last_dts = p_chunk->i_last_dts;
+        p_chunk++;
+    }
+    while( p_chunk < &p_track->chunk[p_track->i_chunk_count] &&
+           p_chunk->i_sample_description_index == i_sd_index );
+
+    if( i_sample > 1 && i_first_dts < i_last_dts )
+        vlc_ureduce( pi_num, pi_den,
+                     ( i_sample - 1) *  p_track->i_timescale,
+                     i_last_dts - i_first_dts,
+                     UINT16_MAX);
+}
+
 /*
  * TrackCreateES:
  * Create ES and PES to init decoder if needed, for a track starting at i_chunk
@@ -1398,15 +1443,16 @@ static int TrackCreateSamplesIndex( demux_t *p_demux,
 static int TrackCreateES( demux_t *p_demux, mp4_track_t *p_track,
                           unsigned int i_chunk, es_out_id_t **pp_es )
 {
+    const unsigned i_sample_description_index =
+        p_track->chunk[i_chunk].i_sample_description_index;
     MP4_Box_t   *p_sample;
     MP4_Box_t   *p_esds;
-    MP4_Box_t   *p_box;
     MP4_Box_t   *p_frma;
 
     if( pp_es )
         *pp_es = NULL;
 
-    if( !p_track->chunk[i_chunk].i_sample_description_index )
+    if( !i_sample_description_index )
     {
         msg_Warn( p_demux, "invalid SampleEntry index (track[Id 0x%x])",
                   p_track->i_track_ID );
@@ -1414,7 +1460,7 @@ static int TrackCreateES( demux_t *p_demux, mp4_track_t *p_track,
     }
 
     p_sample = MP4_BoxGet(  p_track->p_stsd, "[%d]",
-                p_track->chunk[i_chunk].i_sample_description_index - 1 );
+                            i_sample_description_index - 1 );
 
     if( !p_sample ||
         ( !p_sample->data.p_data && p_track->fmt.i_cat != SPU_ES ) )
@@ -1513,17 +1559,9 @@ static int TrackCreateES( demux_t *p_demux, mp4_track_t *p_track,
         p_track->fmt.video.i_visible_height = p_track->fmt.video.i_height;
 
         /* Frame rate */
-        p_track->fmt.video.i_frame_rate = p_track->i_timescale;
-        p_track->fmt.video.i_frame_rate_base = 1;
-
-        if( p_track->fmt.video.i_frame_rate &&
-            (p_box = MP4_BoxGet( p_track->p_stbl, "stts" )) &&
-            p_box->data.p_stts->i_entry_count >= 1 )
-        {
-            p_track->fmt.video.i_frame_rate_base =
-                p_box->data.p_stts->i_sample_delta[0];
-        }
-
+        TrackGetESSampleRate( &p_track->fmt.video.i_frame_rate,
+                              &p_track->fmt.video.i_frame_rate_base,
+                              p_track, i_sample_description_index, i_chunk );
         break;
 
     case AUDIO_ES:




More information about the vlc-devel mailing list