Commit ebf27e98 authored by Laurent Aimar's avatar Laurent Aimar

Fixed ES frame rate estimation in mp4 file.

parent 8844919a
...@@ -77,7 +77,8 @@ typedef struct ...@@ -77,7 +77,8 @@ typedef struct
much memory and with fast access */ much memory and with fast access */
/* with this we can calculate dts/pts without waste memory */ /* 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_count_dts;
uint32_t *p_sample_delta_dts; /* dts delta */ uint32_t *p_sample_delta_dts; /* dts delta */
...@@ -1204,7 +1205,7 @@ static int TrackCreateSamplesIndex( demux_t *p_demux, ...@@ -1204,7 +1205,7 @@ static int TrackCreateSamplesIndex( demux_t *p_demux,
int64_t i_index; int64_t i_index;
int64_t i_index_sample_used; int64_t i_index_sample_used;
int64_t i_last_dts; int64_t i_next_dts;
/* Find stsz /* Find stsz
* Gives the sample size for each samples. There is also a stz2 table * Gives the sample size for each samples. There is also a stz2 table
...@@ -1259,15 +1260,16 @@ static int TrackCreateSamplesIndex( demux_t *p_demux, ...@@ -1259,15 +1260,16 @@ static int TrackCreateSamplesIndex( demux_t *p_demux,
* for fast research (problem with raw stream where a sample is sometime * for fast research (problem with raw stream where a sample is sometime
* just channels*bits_per_sample/8 */ * just channels*bits_per_sample/8 */
i_last_dts = 0; i_next_dts = 0;
i_index = 0; i_index_sample_used = 0; i_index = 0; i_index_sample_used = 0;
for( i_chunk = 0; i_chunk < p_demux_track->i_chunk_count; i_chunk++ ) for( i_chunk = 0; i_chunk < p_demux_track->i_chunk_count; i_chunk++ )
{ {
mp4_chunk_t *ck = &p_demux_track->chunk[i_chunk]; mp4_chunk_t *ck = &p_demux_track->chunk[i_chunk];
int64_t i_entry, i_sample_count, i; int64_t i_entry, i_sample_count, i;
/* save last dts */ /* save first dts */
ck->i_first_dts = i_last_dts; ck->i_first_dts = i_next_dts;
ck->i_last_dts = i_next_dts;
/* count how many entries are needed for this chunk /* count how many entries are needed for this chunk
* for p_sample_delta_dts and p_sample_count_dts */ * for p_sample_delta_dts and p_sample_count_dts */
...@@ -1304,11 +1306,12 @@ static int TrackCreateSamplesIndex( demux_t *p_demux, ...@@ -1304,11 +1306,12 @@ static int TrackCreateSamplesIndex( demux_t *p_demux,
i_index_sample_used += i_used; i_index_sample_used += i_used;
i_sample_count -= 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_count_dts[i] = i_used;
ck->p_sample_delta_dts[i] = stts->i_sample_delta[i_index]; ck->p_sample_delta_dts[i] = stts->i_sample_delta[i_index];
if( i_used > 0 )
i_last_dts += i_used * ck->p_sample_delta_dts[i]; ck->i_last_dts = i_next_dts - ck->p_sample_delta_dts[i];
if( i_index_sample_used >= stts->i_sample_count[i_index] ) if( i_index_sample_used >= stts->i_sample_count[i_index] )
{ {
...@@ -1386,11 +1389,53 @@ static int TrackCreateSamplesIndex( demux_t *p_demux, ...@@ -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", 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, 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; 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: * TrackCreateES:
* Create ES and PES to init decoder if needed, for a track starting at i_chunk * 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, ...@@ -1398,15 +1443,16 @@ static int TrackCreateSamplesIndex( demux_t *p_demux,
static int TrackCreateES( demux_t *p_demux, mp4_track_t *p_track, static int TrackCreateES( demux_t *p_demux, mp4_track_t *p_track,
unsigned int i_chunk, es_out_id_t **pp_es ) 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_sample;
MP4_Box_t *p_esds; MP4_Box_t *p_esds;
MP4_Box_t *p_box;
MP4_Box_t *p_frma; MP4_Box_t *p_frma;
if( pp_es ) if( pp_es )
*pp_es = NULL; *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])", msg_Warn( p_demux, "invalid SampleEntry index (track[Id 0x%x])",
p_track->i_track_ID ); p_track->i_track_ID );
...@@ -1414,7 +1460,7 @@ static int TrackCreateES( demux_t *p_demux, mp4_track_t *p_track, ...@@ -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_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 || if( !p_sample ||
( !p_sample->data.p_data && p_track->fmt.i_cat != SPU_ES ) ) ( !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, ...@@ -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; p_track->fmt.video.i_visible_height = p_track->fmt.video.i_height;
/* Frame rate */ /* Frame rate */
p_track->fmt.video.i_frame_rate = p_track->i_timescale; TrackGetESSampleRate( &p_track->fmt.video.i_frame_rate,
p_track->fmt.video.i_frame_rate_base = 1; &p_track->fmt.video.i_frame_rate_base,
p_track, i_sample_description_index, i_chunk );
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];
}
break; break;
case AUDIO_ES: case AUDIO_ES:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment