[vlc-commits] [Git][videolan/vlc][3.0.x] 4 commits: demux: mp4: only have unsigned pts offsets

Steve Lhomme (@robUx4) gitlab at videolan.org
Thu Sep 1 14:08:58 UTC 2022



Steve Lhomme pushed to branch 3.0.x at VideoLAN / VLC


Commits:
ae37b995 by Francois Cartegnie at 2022-09-01T13:40:33+00:00
demux: mp4: only have unsigned pts offsets

since dts_shift is always computed, that should be
always positive.

(cherry picked from commit 5132db8ad6840d04fbca1a0ea23db5cd1e5ac0a6)
Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>

- - - - -
0aecdcab by Francois Cartegnie at 2022-09-01T13:40:33+00:00
demux: mp4: refactor getting sample timings

(cherry picked from commit fa6e7fed73becb9f73362e8013860a2708b6f9dd) (edited)
edited:
* 3.0 uses mtime_t
Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>

- - - - -
21373dd1 by Zhao Zhili at 2022-09-01T13:40:33+00:00
demux: mp4: remove unused variable

(cherry picked from commit 0ecf4e819bff81290fd3e218ad7eb47fd0051312)
Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>

- - - - -
4508d659 by Zhao Zhili at 2022-09-01T13:40:33+00:00
demux: mp4: optimize mp4_chunk memory allocation

1. Avoid dynamic memory allocation for small samples_per_chunk
(less or equal to 2 sample per chunk). Depends on the test file
and OS, the time taking by MP4_TrackClean can be reduced from a
few seconds to dozens of milliseconds.

2. Merge some allocation to single memory chunk. For mp4 files
with a lot of chunks, the time taking by MP4_TrackClean can be
reduced by half.

(cherry picked from commit 979bca40665e33227d88d8b4329fe68ce54b3fc0) (rebased)
rebased:
* on 3.0 MP4_ChunkGetSampleDTS() has a different signature
Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>

- - - - -


2 changed files:

- modules/demux/mp4/mp4.c
- modules/demux/mp4/mp4.h


Changes:

=====================================
modules/demux/mp4/mp4.c
=====================================
@@ -294,80 +294,141 @@ static es_out_id_t * MP4_AddTrackES( es_out_t *out, mp4_track_t *p_track )
     return p_es;
 }
 
-/* Return time in microsecond of a track */
-static inline int64_t MP4_TrackGetDTS( demux_t *p_demux, mp4_track_t *p_track )
+static int MP4_ChunkAllocDtsEntries( mp4_chunk_t *ck )
 {
-    demux_sys_t *p_sys = p_demux->p_sys;
-    const mp4_chunk_t *p_chunk = &p_track->chunk[p_track->i_chunk];
+    size_t entries = ck->i_entries_dts;
+
+    if( entries <= ARRAY_SIZE(ck->small_dts_buf) / 2 )
+    {
+        ck->p_sample_count_dts = ck->small_dts_buf;
+        ck->p_sample_delta_dts = ck->small_dts_buf + entries;
+        return 0;
+    }
+
+    uint32_t *buf = calloc( entries, sizeof( buf[0] ) * 2 );
+    if( unlikely(buf == NULL) )
+        return VLC_ENOMEM;
 
-    unsigned int i_index = 0;
-    unsigned int i_sample = p_track->i_sample - p_chunk->i_sample_first;
-    int64_t i_dts = p_chunk->i_first_dts;
+    ck->p_sample_count_dts = buf;
+    ck->p_sample_delta_dts = buf + entries;
+    return 0;
+}
+
+static int MP4_ChunkAllocPtsEntries( mp4_chunk_t *ck )
+{
+    size_t entries = ck->i_entries_pts;
+
+    if( entries <= ARRAY_SIZE(ck->small_pts_buf) / 2 )
+    {
+        ck->p_sample_count_pts = ck->small_pts_buf;
+        ck->p_sample_offset_pts = ck->small_pts_buf + entries;
+        return 0;
+    }
 
+    uint32_t *buf = calloc( entries, sizeof( buf[0] ) * 2 );
+    if( unlikely(buf == NULL) )
+        return VLC_ENOMEM;
+
+    ck->p_sample_count_pts = buf;
+    ck->p_sample_offset_pts = buf + entries;
+    return 0;
+}
+
+static void MP4_ChunkDestroy( mp4_chunk_t *ck )
+{
+    if( ck->p_sample_count_dts != ck->small_dts_buf )
+        free( ck->p_sample_count_dts );
+    if( ck->p_sample_count_pts != ck->small_pts_buf )
+        free( ck->p_sample_count_pts );
+}
+
+static stime_t MP4_ChunkGetSampleDTS( const mp4_chunk_t *p_chunk,
+                                      uint32_t i_sample )
+{
+    uint32_t i_index = 0;
+    stime_t sdts = p_chunk->i_first_dts;
     while( i_sample > 0 && i_index < p_chunk->i_entries_dts )
     {
         if( i_sample > p_chunk->p_sample_count_dts[i_index] )
         {
-            i_dts += p_chunk->p_sample_count_dts[i_index] *
+            sdts += p_chunk->p_sample_count_dts[i_index] *
                 p_chunk->p_sample_delta_dts[i_index];
-            i_sample -= p_chunk->p_sample_count_dts[i_index];
-            i_index++;
+            i_sample -= p_chunk->p_sample_count_dts[i_index++];
         }
         else
         {
-            i_dts += i_sample * p_chunk->p_sample_delta_dts[i_index];
+            sdts += i_sample * p_chunk->p_sample_delta_dts[i_index];
             break;
         }
     }
+    return sdts;
+}
 
-    i_dts = MP4_rescale( i_dts, p_track->i_timescale, CLOCK_FREQ );
-
-    /* now handle elst */
-    if( p_track->p_elst && p_track->BOXDATA(p_elst)->i_entry_count )
+static bool MP4_ChunkGetSampleCTSDelta( const mp4_chunk_t *p_chunk,
+                                        uint32_t i_sample, stime_t *pi_delta )
+{
+    if( p_chunk->p_sample_count_pts && p_chunk->p_sample_offset_pts )
     {
-        MP4_Box_data_elst_t *elst = p_track->BOXDATA(p_elst);
-
-        /* convert to offset */
-        if( ( elst->i_media_rate_integer[p_track->i_elst] > 0 ||
-              elst->i_media_rate_fraction[p_track->i_elst] > 0 ) &&
-            elst->i_media_time[p_track->i_elst] > 0 )
+        for( uint32_t i_index = 0; i_index < p_chunk->i_entries_pts ; i_index++ )
         {
-            i_dts -= MP4_rescale( elst->i_media_time[p_track->i_elst], p_track->i_timescale, CLOCK_FREQ );
+            if( i_sample < p_chunk->p_sample_count_pts[i_index] )
+            {
+                *pi_delta = p_chunk->p_sample_offset_pts[i_index];
+                return true;
+            }
+            i_sample -= p_chunk->p_sample_count_pts[i_index];
         }
+    }
+    return false;
+}
+
+static void MP4_TrackTimeApplyELST( const mp4_track_t *p_track,
+                                    stime_t *pi_dts )
+{
+    if( !p_track->p_elst || !p_track->BOXDATA(p_elst)->i_entry_count )
+        return;
 
-        /* add i_elst_time */
-        i_dts += MP4_rescale( p_track->i_elst_time, p_sys->i_timescale, CLOCK_FREQ );
+    const MP4_Box_data_elst_t *elst = p_track->BOXDATA(p_elst);
 
-        if( i_dts < 0 ) i_dts = 0;
+    /* convert to offset */
+    if( elst->i_media_time[p_track->i_elst] > 0 &&
+        ( elst->i_media_rate_integer[p_track->i_elst] > 0 ||
+          elst->i_media_rate_fraction[p_track->i_elst] > 0 ) )
+    {
+        *pi_dts -= elst->i_media_time[p_track->i_elst];
     }
 
-    return i_dts;
+    /* add i_elst_time */
+    *pi_dts += p_track->i_elst_time;
+
+    if( *pi_dts < 0 ) *pi_dts = 0;
 }
 
-static inline bool MP4_TrackGetPTSDelta( demux_t *p_demux, mp4_track_t *p_track,
-                                         int64_t *pi_delta )
+/* Return time in microsecond of a track */
+static inline mtime_t MP4_TrackGetDTS( demux_t *p_demux, mp4_track_t *p_track )
 {
-    VLC_UNUSED( p_demux );
-    mp4_chunk_t *ck = &p_track->chunk[p_track->i_chunk];
+    VLC_UNUSED(p_demux);
+    const mp4_chunk_t *p_chunk = &p_track->chunk[p_track->i_chunk];
 
-    unsigned int i_index = 0;
-    unsigned int i_sample = p_track->i_sample - ck->i_sample_first;
+    stime_t sdts = MP4_ChunkGetSampleDTS( p_chunk,
+                                          p_track->i_sample - p_chunk->i_sample_first );
 
-    if( ck->p_sample_count_pts == NULL || ck->p_sample_offset_pts == NULL )
-        return false;
+    /* now handle elst */
+    MP4_TrackTimeApplyELST( p_track, &sdts );
 
-    for( i_index = 0; i_index < ck->i_entries_pts ; i_index++ )
-    {
-        if( i_sample < ck->p_sample_count_pts[i_index] )
-        {
-            *pi_delta = MP4_rescale( ck->p_sample_offset_pts[i_index],
-                                     p_track->i_timescale, CLOCK_FREQ );
-            return true;
-        }
+    return MP4_rescale( sdts, p_track->i_timescale, CLOCK_FREQ );
+}
 
-        i_sample -= ck->p_sample_count_pts[i_index];
-    }
-    return false;
+static inline bool MP4_TrackGetPTSDelta( demux_t *p_demux, const mp4_track_t *p_track,
+                                         mtime_t *pi_delta )
+{
+    VLC_UNUSED( p_demux );
+    const mp4_chunk_t *ck = &p_track->chunk[p_track->i_chunk];
+    stime_t delta;
+    if( !MP4_ChunkGetSampleCTSDelta( ck, p_track->i_sample - ck->i_sample_first, &delta ) )
+        return false;
+    *pi_delta = MP4_rescale( delta, p_track->i_timescale, CLOCK_FREQ );
+    return true;
 }
 
 static inline int64_t MP4_GetMoviePTS(demux_sys_t *p_sys )
@@ -2551,15 +2612,12 @@ static int TrackCreateSamplesIndex( demux_t *p_demux,
                 return i_ret;
 
             /* allocate them */
-            ck->p_sample_count_dts = calloc( ck->i_entries_dts, sizeof( uint32_t ) );
-            ck->p_sample_delta_dts = calloc( ck->i_entries_dts, sizeof( uint32_t ) );
-            if( !ck->p_sample_count_dts || !ck->p_sample_delta_dts )
+            i_ret = MP4_ChunkAllocDtsEntries( ck );
+            if( i_ret )
             {
-                free( ck->p_sample_count_dts );
-                free( ck->p_sample_delta_dts );
                 msg_Err( p_demux, "can't allocate memory for i_entry=%"PRIu32, ck->i_entries_dts );
                 ck->i_entries_dts = 0;
-                return VLC_ENOMEM;
+                return i_ret;
             }
 
             /* now copy */
@@ -2656,15 +2714,12 @@ static int TrackCreateSamplesIndex( demux_t *p_demux,
                 return i_ret;
 
             /* allocate them */
-            ck->p_sample_count_pts = calloc( ck->i_entries_pts, sizeof( uint32_t ) );
-            ck->p_sample_offset_pts = calloc( ck->i_entries_pts, sizeof( int32_t ) );
-            if( !ck->p_sample_count_pts || !ck->p_sample_offset_pts )
+            i_ret = MP4_ChunkAllocPtsEntries( ck );
+            if( i_ret )
             {
-                free( ck->p_sample_count_pts );
-                free( ck->p_sample_offset_pts );
                 msg_Err( p_demux, "can't allocate memory for i_entry=%"PRIu32, ck->i_entries_pts );
                 ck->i_entries_pts = 0;
-                return VLC_ENOMEM;
+                return i_ret;
             }
 
             /* now copy */
@@ -2672,12 +2727,15 @@ static int TrackCreateSamplesIndex( demux_t *p_demux,
 
             for( uint32_t i = 0; i < ck->i_entries_pts; i++ )
             {
+                int64_t i_ctsdelta = ctts->pi_sample_offset[i_index] + i_cts_shift;
+                if( i_ctsdelta < 0 ) /* should not */
+                    i_ctsdelta = 0;
                 if ( i_current_index_samples_left )
                 {
                     if ( i_current_index_samples_left > i_sample_count )
                     {
                         ck->p_sample_count_pts[i] = i_sample_count;
-                        ck->p_sample_offset_pts[i] = ctts->pi_sample_offset[i_index] + i_cts_shift;
+                        ck->p_sample_offset_pts[i] = i_ctsdelta;
                         i_current_index_samples_left -= i_sample_count;
                         i_sample_count = 0;
                         assert( i == ck->i_entries_pts - 1 );
@@ -2686,7 +2744,7 @@ static int TrackCreateSamplesIndex( demux_t *p_demux,
                     else
                     {
                         ck->p_sample_count_pts[i] = i_current_index_samples_left;
-                        ck->p_sample_offset_pts[i] = ctts->pi_sample_offset[i_index] + i_cts_shift;
+                        ck->p_sample_offset_pts[i] = i_ctsdelta;
                         i_sample_count -= i_current_index_samples_left;
                         i_current_index_samples_left = 0;
                         i_index++;
@@ -2697,7 +2755,7 @@ static int TrackCreateSamplesIndex( demux_t *p_demux,
                     if ( ctts->pi_sample_count[i_index] > i_sample_count )
                     {
                         ck->p_sample_count_pts[i] = i_sample_count;
-                        ck->p_sample_offset_pts[i] = ctts->pi_sample_offset[i_index] + i_cts_shift;
+                        ck->p_sample_offset_pts[i] = i_ctsdelta;
                         i_current_index_samples_left = ctts->pi_sample_count[i_index] - i_sample_count;
                         i_sample_count = 0;
                         assert( i == ck->i_entries_pts - 1 );
@@ -2706,7 +2764,7 @@ static int TrackCreateSamplesIndex( demux_t *p_demux,
                     else
                     {
                         ck->p_sample_count_pts[i] = ctts->pi_sample_count[i_index];
-                        ck->p_sample_offset_pts[i] = ctts->pi_sample_offset[i_index] + i_cts_shift;
+                        ck->p_sample_offset_pts[i] = i_ctsdelta;
                         i_sample_count -= ctts->pi_sample_count[i_index];
                         i_index++;
                     }
@@ -3487,15 +3545,6 @@ static void MP4_TrackSetup( demux_t *p_demux, mp4_track_t *p_track,
     p_track->b_ok = true;
 }
 
-static void DestroyChunk( mp4_chunk_t *ck )
-{
-    free( ck->p_sample_count_dts );
-    free( ck->p_sample_delta_dts );
-    free( ck->p_sample_count_pts );
-    free( ck->p_sample_offset_pts );
-    free( ck->p_sample_size );
-}
-
 /****************************************************************************
  * MP4_TrackClean:
  ****************************************************************************
@@ -3511,7 +3560,7 @@ static void MP4_TrackClean( es_out_t *out, mp4_track_t *p_track )
     if( p_track->chunk )
     {
         for( unsigned int i_chunk = 0; i_chunk < p_track->i_chunk_count; i_chunk++ )
-            DestroyChunk( &p_track->chunk[i_chunk] );
+            MP4_ChunkDestroy( &p_track->chunk[i_chunk] );
     }
     free( p_track->chunk );
 


=====================================
modules/demux/mp4/mp4.h
=====================================
@@ -50,12 +50,13 @@ typedef struct
     uint32_t     i_entries_dts;
     uint32_t     *p_sample_count_dts;
     uint32_t     *p_sample_delta_dts;   /* dts delta */
+    uint32_t     small_dts_buf[4];
 
     uint32_t     i_entries_pts;
     uint32_t     *p_sample_count_pts;
-    int32_t      *p_sample_offset_pts;  /* pts-dts */
+    uint32_t     *p_sample_offset_pts;  /* pts-dts */
+    uint32_t     small_pts_buf[4];
 
-    uint32_t     *p_sample_size;
     /* TODO if needed add pts
         but quickly *add* support for edts and seeking */
 



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/373fd1433bd75abc22fa98677042562dc56414f5...4508d659e18745207e6684b236e00ceed6fd6d55

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/373fd1433bd75abc22fa98677042562dc56414f5...4508d659e18745207e6684b236e00ceed6fd6d55
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list