@ -2215,8 +2215,7 @@ static int mov_skip_multiple_stsd(MOVContext *c, AVIOContext *pb,
avio_skip ( pb , size ) ;
return 1 ;
}
if ( codec_tag = = AV_RL32 ( " avc1 " ) | |
codec_tag = = AV_RL32 ( " hvc1 " ) | |
if ( codec_tag = = AV_RL32 ( " hvc1 " ) | |
codec_tag = = AV_RL32 ( " hev1 " )
)
av_log ( c - > fc , AV_LOG_WARNING , " Concatenated H.264 or H.265 might not play correctly. \n " ) ;
@ -2294,6 +2293,19 @@ int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries)
return ret ;
} else if ( a . size > 0 )
avio_skip ( pb , a . size ) ;
if ( sc - > extradata ) {
int extra_size = st - > codecpar - > extradata_size ;
/* Move the current stream extradata to the stream context one. */
sc - > extradata_size [ pseudo_stream_id ] = extra_size ;
sc - > extradata [ pseudo_stream_id ] = av_malloc ( extra_size + AV_INPUT_BUFFER_PADDING_SIZE ) ;
if ( ! sc - > extradata [ pseudo_stream_id ] )
return AVERROR ( ENOMEM ) ;
memcpy ( sc - > extradata [ pseudo_stream_id ] , st - > codecpar - > extradata , extra_size ) ;
av_freep ( & st - > codecpar - > extradata ) ;
st - > codecpar - > extradata_size = 0 ;
}
}
if ( pb - > eof_reached )
@ -2304,13 +2316,41 @@ int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries)
static int mov_read_stsd ( MOVContext * c , AVIOContext * pb , MOVAtom atom )
{
int entries ;
AVStream * st ;
MOVStreamContext * sc ;
int ret ;
if ( c - > fc - > nb_streams < 1 )
return 0 ;
st = c - > fc - > streams [ c - > fc - > nb_streams - 1 ] ;
sc = st - > priv_data ;
avio_r8 ( pb ) ; /* version */
avio_rb24 ( pb ) ; /* flags */
entries = avio_rb32 ( pb ) ;
sc - > stsd_count = avio_rb32 ( pb ) ; /* entries */
/* Prepare space for hosting multiple extradata. */
sc - > extradata = av_mallocz_array ( sc - > stsd_count , sizeof ( * sc - > extradata ) ) ;
if ( ! sc - > extradata )
return AVERROR ( ENOMEM ) ;
sc - > extradata_size = av_mallocz_array ( sc - > stsd_count , sizeof ( sc - > extradata_size ) ) ;
if ( ! sc - > extradata_size )
return AVERROR ( ENOMEM ) ;
ret = ff_mov_read_stsd_entries ( c , pb , sc - > stsd_count ) ;
if ( ret < 0 )
return ret ;
/* Restore back the primary extradata. */
av_free ( st - > codecpar - > extradata ) ;
st - > codecpar - > extradata_size = sc - > extradata_size [ 0 ] ;
st - > codecpar - > extradata = av_mallocz ( sc - > extradata_size [ 0 ] + AV_INPUT_BUFFER_PADDING_SIZE ) ;
if ( ! st - > codecpar - > extradata )
return AVERROR ( ENOMEM ) ;
memcpy ( st - > codecpar - > extradata , sc - > extradata [ 0 ] , sc - > extradata_size [ 0 ] ) ;
return ff_mov_read_stsd_entries ( c , pb , entries ) ;
return 0 ;
}
static int mov_read_stsc ( MOVContext * c , AVIOContext * pb , MOVAtom atom )
@ -2355,6 +2395,19 @@ static int mov_read_stsc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
return 0 ;
}
/* Compute the samples value for the stsc entry at the given index. */
static inline int mov_get_stsc_samples ( MOVStreamContext * sc , int index )
{
int chunk_count ;
if ( index < sc - > stsc_count - 1 )
chunk_count = sc - > stsc_data [ index + 1 ] . first - sc - > stsc_data [ index ] . first ;
else
chunk_count = sc - > chunk_count - ( sc - > stsc_data [ index ] . first - 1 ) ;
return sc - > stsc_data [ index ] . count * chunk_count ;
}
static int mov_read_stps ( MOVContext * c , AVIOContext * pb , MOVAtom atom )
{
AVStream * st ;
@ -3212,7 +3265,6 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
}
/* Do not need those anymore. */
av_freep ( & sc - > chunk_offsets ) ;
av_freep ( & sc - > stsc_data ) ;
av_freep ( & sc - > sample_sizes ) ;
av_freep ( & sc - > keyframes ) ;
av_freep ( & sc - > stts_data ) ;
@ -4773,6 +4825,11 @@ static int mov_read_close(AVFormatContext *s)
av_freep ( & sc - > rap_group ) ;
av_freep ( & sc - > display_matrix ) ;
for ( j = 0 ; j < sc - > stsd_count ; j + + )
av_free ( sc - > extradata [ j ] ) ;
av_freep ( & sc - > extradata ) ;
av_freep ( & sc - > extradata_size ) ;
av_freep ( & sc - > cenc . auxiliary_info ) ;
av_freep ( & sc - > cenc . auxiliary_info_sizes ) ;
av_aes_ctr_free ( sc - > cenc . aes_ctr ) ;
@ -5190,6 +5247,29 @@ static int mov_switch_root(AVFormatContext *s, int64_t target)
return 1 ;
}
static int mov_change_extradata ( MOVStreamContext * sc , AVPacket * pkt )
{
uint8_t * side , * extradata ;
int extradata_size ;
/* Save the current index. */
sc - > last_stsd_index = sc - > stsc_data [ sc - > stsc_index ] . id - 1 ;
/* Notify the decoder that extradata changed. */
extradata_size = sc - > extradata_size [ sc - > last_stsd_index ] ;
extradata = sc - > extradata [ sc - > last_stsd_index ] ;
if ( extradata_size > 0 & & extradata ) {
side = av_packet_new_side_data ( pkt ,
AV_PKT_DATA_NEW_EXTRADATA ,
extradata_size ) ;
if ( ! side )
return AVERROR ( ENOMEM ) ;
memcpy ( side , extradata , extradata_size ) ;
}
return 0 ;
}
static int mov_read_packet ( AVFormatContext * s , AVPacket * pkt )
{
MOVContext * mov = s - > priv_data ;
@ -5282,6 +5362,25 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
pkt - > flags | = sample - > flags & AVINDEX_KEYFRAME ? AV_PKT_FLAG_KEY : 0 ;
pkt - > pos = sample - > pos ;
/* Multiple stsd handling. */
if ( sc - > stsc_data ) {
/* Keep track of the stsc index for the given sample, then check
* if the stsd index is different from the last used one . */
sc - > stsc_sample + + ;
if ( sc - > stsc_index < sc - > stsc_count - 1 & &
mov_get_stsc_samples ( sc , sc - > stsc_index ) = = sc - > stsc_sample ) {
sc - > stsc_index + + ;
sc - > stsc_sample = 0 ;
/* Do not check indexes after a switch. */
} else if ( sc - > stsc_data [ sc - > stsc_index ] . id > 0 & &
sc - > stsc_data [ sc - > stsc_index ] . id - 1 < sc - > stsd_count & &
sc - > stsc_data [ sc - > stsc_index ] . id - 1 ! = sc - > last_stsd_index ) {
ret = mov_change_extradata ( sc , pkt ) ;
if ( ret < 0 )
return ret ;
}
}
if ( mov - > aax_mode )
aax_filter ( pkt - > data , pkt - > size , mov ) ;
@ -5352,6 +5451,18 @@ static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp,
}
}
/* adjust stsd index */
time_sample = 0 ;
for ( i = 0 ; i < sc - > stsc_count ; i + + ) {
int next = time_sample + mov_get_stsc_samples ( sc , i ) ;
if ( next > sc - > current_sample ) {
sc - > stsc_index = i ;
sc - > stsc_sample = sc - > current_sample - time_sample ;
break ;
}
time_sample = next ;
}
ret = mov_seek_auxiliary_info ( s , sc ) ;
if ( ret < 0 ) {
return ret ;