[vlc-commits] [Git][videolan/vlc][master] 2 commits: demux: mp4: split STTS lookup
François Cartegnie (@fcartegnie)
gitlab at videolan.org
Wed Feb 22 21:30:39 UTC 2023
François Cartegnie pushed to branch master at VideoLAN / VLC
Commits:
5a898df7 by Francois Cartegnie at 2023-02-22T21:07:42+00:00
demux: mp4: split STTS lookup
- - - - -
0801b577 by Francois Cartegnie at 2023-02-22T21:07:42+00:00
demux: mp4: use binary search for chunk
- - - - -
1 changed file:
- modules/demux/mp4/mp4.c
Changes:
=====================================
modules/demux/mp4/mp4.c
=====================================
@@ -43,6 +43,8 @@
#include "../../codec/cc.h"
#include "../av1_unpack.h"
+#include <stdlib.h>
+
/*****************************************************************************
* Module descriptor
*****************************************************************************/
@@ -3213,6 +3215,88 @@ static int TrackGetNearestSeekPoint( demux_t *p_demux, mp4_track_t *p_track,
return i_ret;
}
+struct cmplowestchunkdts_ctx
+{
+ uint64_t dts;
+ const mp4_chunk_t **pp_lowest;
+};
+
+static int cmplowestchunkdts( const void *key, const void *other )
+{
+ const struct cmplowestchunkdts_ctx *ctx = key;
+ const mp4_chunk_t *ck = other;
+ if(ctx->dts > ck->i_first_dts)
+ {
+ *ctx->pp_lowest = ck;
+ return 1;
+ }
+ else if(ctx->dts < ck->i_first_dts)
+ {
+ return -1;
+ }
+ else
+ {
+ *ctx->pp_lowest = ck;
+ return 0;
+ }
+}
+
+static int STTSToSampleChunk(const mp4_track_t *p_track, uint64_t i_dts,
+ uint32_t *pi_chunk, uint32_t *pi_sample)
+{
+ const mp4_chunk_t *ck = NULL;
+
+ if( p_track->i_chunk_count > 1 && /* start heuristic */
+ (uint64_t) i_dts < p_track->chunk[1].i_first_dts )
+ {
+ ck = &p_track->chunk[0];
+ }
+ else
+ {
+ const mp4_chunk_t *lowestchunk = NULL;
+ struct cmplowestchunkdts_ctx bsearchkeyctx = { .dts = i_dts,
+ .pp_lowest = &lowestchunk };
+ ck = bsearch( &bsearchkeyctx, p_track->chunk, p_track->i_chunk_count,
+ sizeof(*p_track->chunk), cmplowestchunkdts );
+ if( ck == NULL )
+ ck = lowestchunk;
+ if( unlikely(ck == NULL) )
+ /* if we default to last chunk, it will be checked searching i_sample */
+ ck = &p_track->chunk[p_track->i_chunk_count - 1];
+ }
+
+ /* *** find sample in the chunk *** */
+ uint32_t i_sample = ck->i_sample_first;
+ uint64_t i_entrydts = ck->i_first_dts;
+
+ for( uint_fast32_t i = 0;
+ i < ck->i_entries_dts && i_sample < ck->i_sample_count;
+ i++ )
+ {
+ uint64_t i_entry_duration = ck->p_sample_count_dts[i] * (uint64_t)
+ ck->p_sample_delta_dts[i];
+ if( i_entrydts + i_entry_duration < i_dts )
+ {
+ i_entrydts += i_entry_duration;
+ i_sample += ck->p_sample_count_dts[i];
+ }
+ else
+ {
+ if( ck->p_sample_delta_dts[i] > 0 )
+ i_sample += ( i_dts - i_entrydts ) / ck->p_sample_delta_dts[i];
+ break;
+ }
+ }
+
+ *pi_chunk = ck - p_track->chunk;
+ *pi_sample = i_sample;
+
+ if( i_sample >= p_track->i_sample_count )
+ return VLC_EGENERIC;
+
+ return VLC_SUCCESS;
+}
+
/* given a time it return sample/chunk
* it also update elst field of the track
*/
@@ -3221,9 +3305,6 @@ static int TrackTimeToSampleChunk( demux_t *p_demux, mp4_track_t *p_track,
uint32_t *pi_sample )
{
demux_sys_t *p_sys = p_demux->p_sys;
- uint64_t i_dts;
- unsigned int i_sample;
- unsigned int i_chunk;
stime_t i_start;
/* FIXME see if it's needed to check p_track->i_chunk_count */
@@ -3267,60 +3348,12 @@ static int TrackTimeToSampleChunk( demux_t *p_demux, mp4_track_t *p_track,
i_start = MP4_rescale_qtime( start, p_track->i_timescale );
}
- /* we start from sample 0/chunk 0, hope it won't take too much time */
/* *** find good chunk *** */
- for( i_chunk = 0; ; i_chunk++ )
- {
- if( i_chunk + 1 >= p_track->i_chunk_count )
- {
- /* at the end and can't check if i_start in this chunk,
- it will be check while searching i_sample */
- i_chunk = p_track->i_chunk_count - 1;
- break;
- }
-
- if( (uint64_t)i_start >= p_track->chunk[i_chunk].i_first_dts &&
- (uint64_t)i_start < p_track->chunk[i_chunk + 1].i_first_dts )
- {
- break;
- }
- }
-
- /* *** find sample in the chunk *** */
- i_sample = p_track->chunk[i_chunk].i_sample_first;
- i_dts = p_track->chunk[i_chunk].i_first_dts;
-
- for( uint_fast32_t i_index = 0;
- i_index < p_track->chunk[i_chunk].i_entries_dts &&
- i_sample < p_track->chunk[i_chunk].i_sample_count;
- i_index++ )
- {
- if( i_dts +
- (uint64_t)p_track->chunk[i_chunk].p_sample_count_dts[i_index] *
- p_track->chunk[i_chunk].p_sample_delta_dts[i_index] < (uint64_t)i_start )
- {
- i_dts +=
- (uint64_t)p_track->chunk[i_chunk].p_sample_count_dts[i_index] *
- p_track->chunk[i_chunk].p_sample_delta_dts[i_index];
-
- i_sample += p_track->chunk[i_chunk].p_sample_count_dts[i_index];
- }
- else
- {
- if( p_track->chunk[i_chunk].p_sample_delta_dts[i_index] <= 0 )
- {
- break;
- }
- i_sample += ( i_start - i_dts ) /
- p_track->chunk[i_chunk].p_sample_delta_dts[i_index];
- break;
- }
- }
-
- if( i_sample >= p_track->i_sample_count )
+ uint32_t i_sample, i_chunk;
+ if( STTSToSampleChunk( p_track, i_start, &i_chunk, &i_sample ) != VLC_SUCCESS )
{
msg_Warn( p_demux, "track[Id 0x%x] will be disabled "
- "(seeking too far) chunk=%d sample=%d",
+ "(seeking too far) chunk=%"PRIu32" sample=%"PRIu32,
p_track->i_track_ID, i_chunk, i_sample );
return( VLC_EGENERIC );
}
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/24465d371f61c895aeb617e5d985ff4dcdf36301...0801b577b2133de11b917b54f9e6680c76c7c51c
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/24465d371f61c895aeb617e5d985ff4dcdf36301...0801b577b2133de11b917b54f9e6680c76c7c51c
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