[vlc-commits] [Git][videolan/vlc][master] 7 commits: demux: mp4: return only last sample dts
Steve Lhomme (@robUx4)
gitlab at videolan.org
Fri Mar 24 01:27:04 UTC 2023
Steve Lhomme pushed to branch master at VideoLAN / VLC
Commits:
7c94acd1 by Francois Cartegnie at 2023-03-24T01:04:39+00:00
demux: mp4: return only last sample dts
- - - - -
413ffdd3 by Francois Cartegnie at 2023-03-24T01:04:39+00:00
demux: libmp4: do not store elst version
- - - - -
90811de8 by Francois Cartegnie at 2023-03-24T01:04:39+00:00
demux: libmp4: restrict to known elst versions
- - - - -
3ef970a5 by Francois Cartegnie at 2023-03-24T01:04:39+00:00
demux: libmp4: rework edit list storage
- - - - -
06ce45c7 by Francois Cartegnie at 2023-03-24T01:04:39+00:00
demux: mp4: fix wrong edit list offset regression
- - - - -
bde20986 by Francois Cartegnie at 2023-03-24T01:04:39+00:00
demux: mp4: move edit list mapping to own functions
- - - - -
f7bb59d9 by Francois Cartegnie at 2023-03-24T01:04:39+00:00
demux: mp4: always check and use next edit list
directly skips empty edits and avoids stopping
on last track sample (fixes loop playback)
- - - - -
4 changed files:
- modules/demux/mp4/libmp4.c
- modules/demux/mp4/libmp4.h
- modules/demux/mp4/mp4.c
- src/input/input.c
Changes:
=====================================
modules/demux/mp4/libmp4.c
=====================================
@@ -3291,10 +3291,7 @@ static int MP4_ReadBox_stdp( stream_t *p_stream, MP4_Box_t *p_box )
static void MP4_FreeBox_elst( MP4_Box_t *p_box )
{
- free( p_box->data.p_elst->i_segment_duration );
- free( p_box->data.p_elst->i_media_time );
- free( p_box->data.p_elst->i_media_rate_integer );
- free( p_box->data.p_elst->i_media_rate_fraction );
+ free( p_box->data.p_elst->entries );
}
static int MP4_ReadBox_elst( stream_t *p_stream, MP4_Box_t *p_box )
@@ -3302,39 +3299,36 @@ static int MP4_ReadBox_elst( stream_t *p_stream, MP4_Box_t *p_box )
uint32_t count;
MP4_READBOX_ENTER( MP4_Box_data_elst_t, MP4_FreeBox_elst );
+ MP4_Box_data_elst_t *p_elst = p_box->data.p_elst;
- MP4_GETVERSIONFLAGS( p_box->data.p_elst );
- MP4_GET4BYTES( count );
+ uint8_t i_version;
+ uint32_t dummy;
+ MP4_GET1BYTE( i_version );
+ MP4_GET3BYTES( dummy ); VLC_UNUSED(dummy);
+
+ if( i_version > 1 )
+ MP4_READBOX_EXIT( 0 );
+ MP4_GET4BYTES( count );
if( count == 0 )
MP4_READBOX_EXIT( 1 );
- uint32_t i_entries_max = i_read / ((p_box->data.p_elst->i_version == 1) ? 20 : 12);
+ uint32_t i_entries_max = i_read / ((i_version == 1) ? 20 : 12);
if( count > i_entries_max )
count = i_entries_max;
- p_box->data.p_elst->i_segment_duration = vlc_alloc( count,
- sizeof(uint64_t) );
- p_box->data.p_elst->i_media_time = vlc_alloc( count, sizeof(int64_t) );
- p_box->data.p_elst->i_media_rate_integer = vlc_alloc( count,
- sizeof(uint16_t) );
- p_box->data.p_elst->i_media_rate_fraction = vlc_alloc( count,
- sizeof(uint16_t) );
- if( p_box->data.p_elst->i_segment_duration == NULL
- || p_box->data.p_elst->i_media_time == NULL
- || p_box->data.p_elst->i_media_rate_integer == NULL
- || p_box->data.p_elst->i_media_rate_fraction == NULL )
- {
+ p_elst->entries = vlc_alloc( count, sizeof(*p_elst->entries) );
+ if( !p_elst->entries )
MP4_READBOX_EXIT( 0 );
- }
- p_box->data.p_elst->i_entry_count = count;
+
+ p_elst->i_entry_count = count;
for( uint32_t i = 0; i < count; i++ )
{
uint64_t segment_duration;
int64_t media_time;
- if( p_box->data.p_elst->i_version == 1 )
+ if( i_version == 1 )
{
union { int64_t s; uint64_t u; } u;
@@ -3351,15 +3345,15 @@ static int MP4_ReadBox_elst( stream_t *p_stream, MP4_Box_t *p_box )
media_time = u.s;
}
- p_box->data.p_elst->i_segment_duration[i] = segment_duration;
- p_box->data.p_elst->i_media_time[i] = media_time;
- MP4_GET2BYTES( p_box->data.p_elst->i_media_rate_integer[i] );
- MP4_GET2BYTES( p_box->data.p_elst->i_media_rate_fraction[i] );
+ p_elst->entries[i].i_segment_duration = segment_duration;
+ p_elst->entries[i].i_media_time = media_time;
+ MP4_GET2BYTES( p_elst->entries[i].i_media_rate_integer );
+ MP4_GET2BYTES( p_elst->entries[i].i_media_rate_fraction );
}
#ifdef MP4_VERBOSE
msg_Dbg( p_stream, "read box: \"elst\" entry-count %" PRIu32,
- p_box->data.p_elst->i_entry_count );
+ p_elst->i_entry_count );
#endif
MP4_READBOX_EXIT( 1 );
}
=====================================
modules/demux/mp4/libmp4.h
=====================================
@@ -984,18 +984,19 @@ typedef struct MP4_Box_data_stdp_s
} MP4_Box_data_stdp_t;
-typedef struct MP4_Box_data_elst_s
+typedef struct
{
- uint8_t i_version;
- uint32_t i_flags;
+ uint64_t i_segment_duration; /* movie timescale */
+ int64_t i_media_time; /* media(track) timescale */
+ uint16_t i_media_rate_integer;
+ uint16_t i_media_rate_fraction;
+} MP4_Box_data_elst_entry_t;
+typedef struct MP4_Box_data_elst_s
+{
uint32_t i_entry_count;
- uint64_t *i_segment_duration; /* movie timescale */
- int64_t *i_media_time; /* media(track) timescale */
- uint16_t *i_media_rate_integer;
- uint16_t *i_media_rate_fraction;
-
+ MP4_Box_data_elst_entry_t *entries;
} MP4_Box_data_elst_t;
=====================================
modules/demux/mp4/mp4.c
=====================================
@@ -499,6 +499,52 @@ static const mp4_chunk_t * MP4_TrackChunkForSample( const mp4_track_t *p_track,
return NULL;
}
+static stime_t MP4_MapTrackTimeIntoTimeline( const mp4_track_t *p_track,
+ uint32_t i_movie_timescale,
+ stime_t i_time )
+{
+ if( !p_track->p_elst || p_track->BOXDATA(p_elst)->i_entry_count == 0 )
+ return i_time;
+
+ const MP4_Box_data_elst_entry_t *edit =
+ &p_track->BOXDATA(p_elst)->entries[p_track->i_elst];
+
+ /* convert to offset in our current edit */
+ if( edit->i_media_time > 0 && p_track->i_start_dts >= edit->i_media_time )
+ i_time -= edit->i_media_time;
+
+ /* convert media timeline to track timescale */
+ stime_t i_media_elst_start = MP4_rescale( p_track->i_elst_time,
+ i_movie_timescale,
+ p_track->i_timescale );
+ /* add to timeline start in current edit */
+ i_time += i_media_elst_start;
+
+ return i_time;
+}
+
+static stime_t MP4_MapMediaTimelineToTrackTime( const mp4_track_t *p_track,
+ uint32_t i_movie_timescale,
+ stime_t i_time )
+{
+ if( !p_track->p_elst || p_track->BOXDATA(p_elst)->i_entry_count == 0 )
+ return i_time;
+
+ const MP4_Box_data_elst_t *elst = p_track->BOXDATA(p_elst);
+ /* convert media timeline to track timescale */
+ stime_t i_media_elst_start = MP4_rescale( p_track->i_elst_time,
+ i_movie_timescale,
+ p_track->i_timescale );
+ /* convert to timeline offset in current edit */
+ i_time -= i_media_elst_start;
+
+ /* add edit start in track samples time to get track sample time */
+ if( elst->entries[p_track->i_elst].i_media_time > 0 )
+ i_time += elst->entries[p_track->i_elst].i_media_time;
+
+ return i_time;
+}
+
static stime_t MP4_ChunkGetSampleDTS( const mp4_chunk_t *p_chunk,
uint32_t i_sample )
{
@@ -548,25 +594,9 @@ static vlc_tick_t MP4_TrackGetDTSPTS( demux_t *p_demux, const mp4_track_t *p_tra
uint32_t delta = p_track->i_next_delta;
/* now handle elst */
- if( p_track->p_elst && p_track->BOXDATA(p_elst)->i_entry_count )
- {
- const MP4_Box_data_elst_t *elst = p_track->BOXDATA(p_elst);
-
- /* 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 ) )
- {
- if( p_track->i_start_dts >= elst->i_media_time[p_track->i_elst] )
- {
- sdts -= elst->i_media_time[p_track->i_elst];
- }
- }
- }
+ sdts = MP4_MapTrackTimeIntoTimeline( p_track, p_sys->i_timescale, sdts );
vlc_tick_t i_dts = MP4_rescale_mtime( sdts, p_track->i_timescale);
- /* add i_elst_time */
- i_dts += MP4_rescale_mtime( p_track->i_elst_time, p_sys->i_timescale );
if( pi_nzpts )
{
@@ -1813,8 +1843,8 @@ static int Seek( demux_t *p_demux, vlc_tick_t i_date, bool b_accurate )
}
}
- msg_Dbg( p_demux, "seeking with %"PRId64 "ms %s", MS_FROM_VLC_TICK(i_date - i_start),
- !b_accurate ? "alignment" : "preroll (use input-fast-seek to avoid)" );
+ msg_Dbg( p_demux, "seeking with %"PRId64 "ms %s to %ld", MS_FROM_VLC_TICK(i_date - i_start),
+ !b_accurate ? "alignment" : "preroll (use input-fast-seek to avoid)", i_date );
for( i_track = 0; i_track < p_sys->i_tracks; i_track++ )
{
@@ -3315,9 +3345,6 @@ static int TrackTimeToSampleChunk( demux_t *p_demux, mp4_track_t *p_track,
MP4_TrackSetELST( p_demux, p_track, start );
if( p_track->p_elst && p_track->BOXDATA(p_elst)->i_entry_count > 0 )
{
- MP4_Box_data_elst_t *elst = p_track->BOXDATA(p_elst);
- int64_t i_mvt= MP4_rescale_qtime( start, p_sys->i_timescale );
-
/* now calculate i_start for this elst */
/* offset */
if( start < MP4_rescale_mtime( p_track->i_elst_time, p_sys->i_timescale ) )
@@ -3328,18 +3355,13 @@ static int TrackTimeToSampleChunk( demux_t *p_demux, mp4_track_t *p_track,
return VLC_SUCCESS;
}
/* to track time scale */
- i_start = MP4_rescale_qtime( start, p_track->i_timescale );
- /* add elst 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 )
- {
- i_start += elst->i_media_time[p_track->i_elst];
- }
+ i_start = MP4_rescale_qtime( start, p_track->i_timescale );
+ /* map through elst offset */
+ i_start = MP4_MapMediaTimelineToTrackTime( p_track, p_sys->i_timescale, i_start );
msg_Dbg( p_demux, "elst (%d) gives %"PRId64"ms (movie)-> %"PRId64
"ms (track)", p_track->i_elst,
- MP4_rescale( i_mvt, p_sys->i_timescale, 1000 ),
+ MS_FROM_VLC_TICK(start),
MP4_rescale( i_start, p_track->i_timescale, 1000 ) );
}
else
@@ -3411,12 +3433,14 @@ static bool FormatIsCompatible( const es_format_t *p_fmt1, const es_format_t *p_
return es_format_IsSimilar( p_fmt1, p_fmt2 );
}
-static int TrackUpdateFormat( demux_t *p_demux, mp4_track_t *p_track, uint32_t i_chunk )
+static int TrackUpdateFormat( demux_t *p_demux, mp4_track_t *p_track,
+ uint32_t i_previous_chunk )
{
+ uint32_t i_chunk = p_track->i_chunk;
/* now see if actual es is ok */
- if( p_track->i_chunk >= p_track->i_chunk_count ||
- (p_track->chunk[p_track->i_chunk].i_sample_description_index !=
- p_track->chunk[i_chunk].i_sample_description_index ) )
+ if( i_previous_chunk != i_chunk &&
+ p_track->chunk[i_previous_chunk].i_sample_description_index !=
+ p_track->chunk[i_chunk].i_sample_description_index )
{
msg_Warn( p_demux, "recreate ES for track[Id 0x%x]",
p_track->i_track_ID );
@@ -3478,7 +3502,7 @@ static int TrackUpdateFormat( demux_t *p_demux, mp4_track_t *p_track, uint32_t i
static int TrackGotoChunkSample( demux_t *p_demux, mp4_track_t *p_track,
uint32_t i_chunk, uint32_t i_sample )
{
- if( TrackUpdateFormat( p_demux, p_track, i_chunk ) != VLC_SUCCESS )
+ if( TrackUpdateFormat( p_demux, p_track, p_track->i_chunk ) != VLC_SUCCESS )
return VLC_EGENERIC;
p_track->i_chunk = i_chunk;
@@ -3525,6 +3549,8 @@ static void TrackUpdateSampleAndTimes( mp4_track_t *p_track )
{
const mp4_chunk_t *p_chunk = &p_track->chunk[p_track->i_chunk];
uint32_t i_chunk_sample = p_track->i_sample - p_chunk->i_sample_first;
+ if( i_chunk_sample > p_chunk->i_sample_count && p_chunk->i_sample_count )
+ i_chunk_sample = p_chunk->i_sample_count - 1;
p_track->i_next_dts = MP4_ChunkGetSampleDTS( p_chunk, i_chunk_sample );
stime_t i_next_delta;
if( !MP4_ChunkGetSampleCTSDelta( p_chunk, i_chunk_sample, &i_next_delta ) )
@@ -3668,14 +3694,15 @@ static void MP4_TrackSetup( demux_t *p_demux, mp4_track_t *p_track,
msg_Warn( p_demux, "elst box found" );
for( i = 0; i < elst->i_entry_count; i++ )
{
+ const MP4_Box_data_elst_entry_t *edit = &elst->entries[i];
msg_Dbg( p_demux, " - [%d] duration=%"PRId64"ms media time=%"PRId64
"ms) rate=%d.%d", i,
- MP4_rescale( elst->i_segment_duration[i], p_sys->i_timescale, 1000 ),
- elst->i_media_time[i] >= 0 ?
- MP4_rescale( elst->i_media_time[i], p_track->i_timescale, 1000 ) :
+ MP4_rescale( edit->i_segment_duration, p_sys->i_timescale, 1000 ),
+ edit->i_media_time >= 0 ?
+ MP4_rescale( edit->i_media_time, p_track->i_timescale, 1000 ) :
INT64_C(-1),
- elst->i_media_rate_integer[i],
- elst->i_media_rate_fraction[i] );
+ edit->i_media_rate_integer,
+ edit->i_media_rate_fraction );
}
if( var_InheritBool( p_demux, CFG_PREFIX"editlist" ) )
@@ -3776,12 +3803,12 @@ static void MP4_TrackSetup( demux_t *p_demux, mp4_track_t *p_track,
#define MAX_SELECTABLE (INT_MAX - ES_PRIORITY_SELECTABLE_MIN)
for ( uint32_t i=0; i<p_track->BOXDATA(p_elst)->i_entry_count; i++ )
{
- if ( p_track->BOXDATA(p_elst)->i_media_time[i] >= 0 &&
- p_track->BOXDATA(p_elst)->i_segment_duration[i] )
+ const MP4_Box_data_elst_entry_t *edit = &p_track->BOXDATA(p_elst)->entries[i];
+ if ( edit->i_media_time >= 0 && edit->i_segment_duration )
{
/* We do selection by inverting start time into priority.
The track with earliest edit will have the highest prio */
- const int i_time = __MIN( MAX_SELECTABLE, p_track->BOXDATA(p_elst)->i_media_time[i] );
+ const int i_time = __MIN( MAX_SELECTABLE, edit->i_media_time );
p_track->fmt.i_priority = ES_PRIORITY_SELECTABLE_MIN + MAX_SELECTABLE - i_time;
break;
}
@@ -4195,52 +4222,99 @@ static uint64_t MP4_TrackGetPos( mp4_track_t *p_track )
return i_pos;
}
-static int MP4_TrackNextSample( demux_t *p_demux, mp4_track_t *p_track, uint32_t i_samples )
+
+static int MP4_TrackSetNextELST( mp4_track_t *tk )
{
- if ( UINT32_MAX - p_track->i_sample < i_samples )
- {
- p_track->i_sample = UINT32_MAX;
+ if( !tk->p_elst ||
+ tk->i_elst == UINT32_MAX - 1 ||
+ tk->i_elst + 1 >= tk->BOXDATA(p_elst)->i_entry_count )
return VLC_EGENERIC;
+
+ tk->i_elst_time += tk->BOXDATA(p_elst)->entries[tk->i_elst++].i_segment_duration;
+
+ return VLC_SUCCESS;
+}
+
+static int MP4_TrackUpdateELST( mp4_track_t *tk, uint32_t i_movie_timescale,
+ stime_t i_track_time, uint32_t i_track_sample )
+{
+ if( !tk->p_elst || tk->BOXDATA(p_elst)->i_entry_count == 0 )
+ return VLC_SUCCESS;
+
+ if( i_track_sample >= tk->i_sample_count )
+ return MP4_TrackSetNextELST( tk );
+
+ vlc_tick_t i_time = MP4_rescale_mtime( i_track_time, tk->i_timescale );
+ for(;;)
+ {
+ const MP4_Box_data_elst_entry_t *edit = &tk->BOXDATA(p_elst)->entries[tk->i_elst];
+ vlc_tick_t i_end = MP4_rescale_mtime( edit->i_media_time, tk->i_timescale ) +
+ MP4_rescale_mtime( edit->i_segment_duration, i_movie_timescale );
+ if ( i_time < i_end || MP4_TrackSetNextELST( tk ) )
+ break;
}
- p_track->i_sample += i_samples;
+ return VLC_SUCCESS;
+}
- if( p_track->i_sample >= p_track->i_sample_count )
- return VLC_EGENERIC;
+static int MP4_TrackNextSample( demux_t *p_demux, mp4_track_t *p_track, uint32_t i_samples )
+{
+ demux_sys_t *p_sys = p_demux->p_sys;
- /* Have we changed chunk ? */
- if( p_track->i_sample >=
- p_track->chunk[p_track->i_chunk].i_sample_first +
- p_track->chunk[p_track->i_chunk].i_sample_count )
+ if ( UINT32_MAX - p_track->i_sample < i_samples )
+ i_samples = UINT32_MAX - p_track->i_sample; /* Ensure we won't overflow next add */
+
+ p_track->i_sample += i_samples;
+ const uint32_t i_previous_chunk = p_track->i_chunk;
+
+ if( p_track->i_sample < p_track->i_sample_count )
{
- if( TrackGotoChunkSample( p_demux, p_track, p_track->i_chunk + 1,
- p_track->i_sample ) )
+ /* Have we changed chunk ? */
+ while( p_track->i_sample >=
+ p_track->chunk[p_track->i_chunk].i_sample_first +
+ p_track->chunk[p_track->i_chunk].i_sample_count &&
+ p_track->i_chunk < p_track->i_chunk_count - 1 )
{
- msg_Warn( p_demux, "track[0x%x] will be disabled "
- "(cannot restart decoder)", p_track->i_track_ID );
- MP4_TrackSelect( p_demux, p_track, false );
- return VLC_EGENERIC;
+ p_track->i_chunk++;
+ }
+ }
+
+ if( p_track->p_elst ) /* Update */
+ {
+ uint32_t i_prev_elst = p_track->i_elst;
+ TrackUpdateSampleAndTimes( p_track );
+ MP4_TrackUpdateELST( p_track, p_sys->i_timescale, p_track->i_next_dts, p_track->i_sample);
+ if( p_track->i_elst != i_prev_elst )
+ {
+ msg_Dbg( p_demux, "changed elst %u -> %u", i_prev_elst, p_track->i_elst);
+ /* *** find good chunk *** */
+ uint32_t i_sample, i_chunk;
+ stime_t i_start = p_track->BOXDATA(p_elst)->entries[p_track->i_elst].i_media_time;
+ 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=%"PRIu32" sample=%"PRIu32,
+ p_track->i_track_ID, i_chunk, i_sample );
+ return VLC_EGENERIC;
+ }
+ p_track->i_chunk = i_chunk;
+ p_track->i_sample = i_sample;
}
}
TrackUpdateSampleAndTimes( p_track );
- /* Have we changed elst */
- if( p_track->p_elst && p_track->BOXDATA(p_elst)->i_entry_count > 0 )
+ if( TrackUpdateFormat( p_demux, p_track, i_previous_chunk ) != VLC_SUCCESS )
{
- demux_sys_t *p_sys = p_demux->p_sys;
- MP4_Box_data_elst_t *elst = p_track->BOXDATA(p_elst);
- uint64_t i_mvt = MP4_rescale_qtime( MP4_TrackGetDTSPTS( p_demux, p_track, NULL ),
- p_sys->i_timescale );
- if( p_track->i_elst < elst->i_entry_count &&
- i_mvt >= p_track->i_elst_time +
- elst->i_segment_duration[p_track->i_elst] )
- {
- MP4_TrackSetELST( p_demux, p_track,
- MP4_TrackGetDTSPTS( p_demux, p_track, NULL ) );
- }
+ msg_Warn( p_demux, "track[0x%x] will be disabled "
+ "(cannot restart decoder)", p_track->i_track_ID );
+ MP4_TrackSelect( p_demux, p_track, false );
+ return VLC_EGENERIC;
}
+ if( !p_track->b_selected || p_track->i_sample >= p_track->i_sample_count )
+ return VLC_EGENERIC;
+
return VLC_SUCCESS;
}
@@ -4260,10 +4334,11 @@ static void MP4_TrackSetELST( demux_t *p_demux, mp4_track_t *tk,
for( tk->i_elst = 0; tk->i_elst < elst->i_entry_count; tk->i_elst++ )
{
- uint64_t i_dur = elst->i_segment_duration[tk->i_elst];
+ uint64_t i_dur = elst->entries[tk->i_elst].i_segment_duration;
- if( tk->i_elst_time <= i_mvt
- && i_mvt < (int64_t)(tk->i_elst_time + i_dur) )
+ if( elst->entries[tk->i_elst].i_media_time >=0 &&
+ tk->i_elst_time <= i_mvt &&
+ i_mvt < (int64_t)(tk->i_elst_time + i_dur) )
{
break;
}
@@ -4274,20 +4349,14 @@ static void MP4_TrackSetELST( demux_t *p_demux, mp4_track_t *tk,
{
/* msg_Dbg( p_demux, "invalid number of entry in elst" ); */
tk->i_elst = elst->i_entry_count - 1;
- tk->i_elst_time -= elst->i_segment_duration[tk->i_elst];
- }
-
- if( elst->i_media_time[tk->i_elst] < 0 )
- {
- /* track offset */
- tk->i_elst_time += elst->i_segment_duration[tk->i_elst];
+ tk->i_elst_time -= elst->entries[tk->i_elst].i_segment_duration;
}
if( i_elst_last != tk->i_elst )
{
msg_Warn( p_demux, "elst old=%d new=%"PRIu32, i_elst_last, tk->i_elst );
if( i_elst_last < elst->i_entry_count &&
- elst->i_media_time[i_elst_last] >= 0 )
+ elst->entries[i_elst_last].i_media_time >= 0 )
tk->i_next_block_flags |= BLOCK_FLAG_DISCONTINUITY;
}
}
=====================================
src/input/input.c
=====================================
@@ -2707,7 +2707,7 @@ static int InputSourceInit( input_source_t *in, input_thread_t *p_input,
if( in->p_demux == NULL )
{
if( !b_in_can_fail && !input_Stopped( p_input ) )
- vlc_dialog_display_error( p_input, _("Your input can't be opened"),
+ vlc_dialog_display_error( p_input, _("Your media can't be opened"),
_("VLC is unable to open the MRL '%s'."
" Check the log for details."), psz_mrl );
if( in->p_slave_es_out )
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/199de0535b7e53a90ba087a2918746df88e3d72d...f7bb59d9f51cc10b25ff86d34a3eff744e60c46e
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/199de0535b7e53a90ba087a2918746df88e3d72d...f7bb59d9f51cc10b25ff86d34a3eff744e60c46e
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