5656typedef struct IMFVirtualTrackResourcePlaybackCtx {
5757 IMFAssetLocator * locator ;
5858 IMFTrackFileResource * resource ;
59+ AVFormatContext * ctx ;
5960} IMFVirtualTrackResourcePlaybackCtx ;
6061
6162typedef struct IMFVirtualTrackPlaybackCtx {
@@ -118,7 +119,6 @@ int parse_imf_asset_map_from_xml_dom(AVFormatContext *s, xmlDocPtr doc, IMFAsset
118119 }
119120
120121 asset = av_malloc (sizeof (IMFAssetLocator ));
121- asset -> ctx = NULL ;
122122
123123 if (xml_read_UUID (xml_get_child_element_by_name (node , "Id" ), asset -> uuid )) {
124124 av_log (s , AV_LOG_ERROR , "Could not parse UUID from asset in asset map.\n" );
@@ -172,7 +172,6 @@ void imf_asset_locator_map_free(IMFAssetLocatorMap *asset_map) {
172172 }
173173
174174 for (int i = 0 ; i < asset_map -> asset_count ; ++ i ) {
175- avformat_free_context (asset_map -> assets [i ]-> ctx );
176175 av_free (asset_map -> assets [i ]);
177176 }
178177
@@ -252,31 +251,33 @@ static IMFAssetLocator *find_asset_map_locator(IMFAssetLocatorMap *asset_map, UU
252251 return NULL ;
253252}
254253
255- static int open_resource_locator_context (AVFormatContext * s , IMFAssetLocator * asset_locator ) {
254+ static int open_track_resource_context (AVFormatContext * s , IMFVirtualTrackResourcePlaybackCtx * track_resource ) {
256255 int ret = 0 ;
257256
258- if (asset_locator -> ctx ) {
259- avformat_free_context ( asset_locator -> ctx );
257+ if (! track_resource -> ctx ) {
258+ track_resource -> ctx = avformat_alloc_context ( );
260259 }
261- asset_locator -> ctx = avformat_alloc_context ();
262260
263- ret = avformat_open_input (& asset_locator -> ctx , asset_locator -> absolute_uri , NULL , NULL );
261+ if (track_resource -> ctx -> iformat ) {
262+ av_log (s , AV_LOG_DEBUG , "Input context already opened for %s.\n" , track_resource -> locator -> absolute_uri );
263+ return ret ;
264+ }
265+
266+ ret = avformat_open_input (& track_resource -> ctx , track_resource -> locator -> absolute_uri , NULL , NULL );
264267 if (ret < 0 ) {
265- av_log (s , AV_LOG_ERROR , "Could not open %s input context. \n" , asset_locator -> absolute_uri );
268+ av_log (s , AV_LOG_ERROR , "Could not open %s input context: %s \n" , track_resource -> locator -> absolute_uri , av_err2str ( ret ) );
266269 goto cleanup ;
267270 }
268271
269- ret = avformat_find_stream_info (asset_locator -> ctx , NULL );
272+ ret = avformat_find_stream_info (track_resource -> ctx , NULL );
270273 if (ret < 0 ) {
271- av_log (s , AV_LOG_ERROR , "Could not find %s stream information. \n" , asset_locator -> absolute_uri );
274+ av_log (s , AV_LOG_ERROR , "Could not find %s stream information: %s \n" , track_resource -> locator -> absolute_uri , av_err2str ( ret ) );
272275 goto cleanup ;
273276 }
274277
275278 return ret ;
276279cleanup :
277- avformat_free_context (asset_locator -> ctx );
278- av_freep (& asset_locator );
279-
280+ avformat_free_context (track_resource -> ctx );
280281 return ret ;
281282}
282283
@@ -294,17 +295,17 @@ static int open_track_file_resource(AVFormatContext *s, IMFTrackFileResource *tr
294295
295296 av_log (s , AV_LOG_DEBUG , "Found locator for " UUID_FORMAT ": %s\n" , UID_ARG (asset_locator -> uuid ), asset_locator -> absolute_uri );
296297
297- if ((ret = open_resource_locator_context (s , asset_locator )) != 0 ) {
298- return ret ;
299- }
300-
301298 track_resource = av_mallocz (sizeof (IMFVirtualTrackResourcePlaybackCtx ));
302299 track_resource -> locator = asset_locator ;
303300 track_resource -> resource = track_file_resource ;
304301
302+ if ((ret = open_track_resource_context (s , track_resource )) != 0 ) {
303+ return ret ;
304+ }
305+
305306 track -> resources = av_realloc (track -> resources , track -> resource_count + 1 * sizeof (IMFVirtualTrackResourcePlaybackCtx ));
306307 track -> resources [track -> resource_count ++ ] = track_resource ;
307- track -> duration += track_resource -> locator -> ctx -> duration ;
308+ track -> duration += track_resource -> ctx -> duration ;
308309
309310 return ret ;
310311}
@@ -331,6 +332,22 @@ static int open_virtual_track(AVFormatContext *s, IMFTrackFileVirtualTrack *virt
331332 return ret ;
332333}
333334
335+ static void imf_virtual_track_playback_context_free (IMFVirtualTrackPlaybackCtx * track ) {
336+ if (!track ) {
337+ return ;
338+ }
339+
340+ for (int i = 0 ; i < track -> resource_count ; ++ i ) {
341+ if (!track -> resources [i ]) {
342+ continue ;
343+ }
344+
345+ if (track -> resources [i ]-> ctx && track -> resources [i ]-> ctx -> iformat ) {
346+ avformat_free_context (track -> resources [i ]-> ctx );
347+ }
348+ }
349+ }
350+
334351static int set_context_streams_from_tracks (AVFormatContext * s ) {
335352 IMFContext * c = s -> priv_data ;
336353
@@ -341,7 +358,7 @@ static int set_context_streams_from_tracks(AVFormatContext *s) {
341358
342359 for (int i = 0 ; i < c -> track_count ; ++ i ) {
343360 // Open the first resource of the track to get stream information
344- first_resource_stream = c -> tracks [i ]-> resources [0 ]-> locator -> ctx -> streams [0 ];
361+ first_resource_stream = c -> tracks [i ]-> resources [0 ]-> ctx -> streams [0 ];
345362
346363 av_log (s , AV_LOG_DEBUG , "Open the first resource of track %d\n" , c -> tracks [i ]-> index );
347364
@@ -449,11 +466,11 @@ static IMFVirtualTrackResourcePlaybackCtx *get_resource_context_for_timestamp(AV
449466
450467 if (track -> current_resource != track -> resources [i ]) {
451468 av_log (s , AV_LOG_DEBUG , "Switch resource on track %d: re-open context\n" , track -> index );
452- if (open_resource_locator_context ( s , track -> resources [ i ] -> locator ) != 0 ) {
453- return NULL ;
469+ if (track -> current_resource != NULL ) {
470+ avformat_close_input ( & track -> current_resource -> ctx ) ;
454471 }
455- if ( track -> current_resource != NULL ) {
456- avformat_close_input ( & track -> current_resource -> locator -> ctx ) ;
472+ if ( open_track_resource_context ( s , track -> resources [ i ]) != 0 ) {
473+ return NULL ;
457474 }
458475 track -> current_resource = track -> resources [i ];
459476 }
@@ -469,7 +486,6 @@ static int ff_imf_read_packet(AVFormatContext *s, AVPacket *pkt) {
469486 IMFVirtualTrackPlaybackCtx * track ;
470487 IMFVirtualTrackPlaybackCtx * track_to_read = NULL ;
471488 IMFVirtualTrackResourcePlaybackCtx * resource_to_read = NULL ;
472- AVFormatContext * read_context = NULL ;
473489
474490 int64_t minimum_timestamp = get_minimum_track_timestamp (c );
475491 int ret = 0 , i ;
@@ -502,16 +518,15 @@ static int ff_imf_read_packet(AVFormatContext *s, AVPacket *pkt) {
502518 }
503519
504520 while (!ff_check_interrupt (c -> interrupt_callback ) && !ret ) {
505- read_context = resource_to_read -> locator -> ctx ;
506- ret = av_read_frame (read_context , pkt );
521+ ret = av_read_frame (resource_to_read -> ctx , pkt );
507522 av_log (s , AV_LOG_DEBUG , "Got packet: pts=%ld, dts=%ld, duration=%ld, stream_index=%d, pos=%ld,\n" , pkt -> pts , pkt -> dts , pkt -> duration , pkt -> stream_index , pkt -> pos );
508523 if (ret >= 0 ) {
509524 // Update packet info from track
510525 pkt -> pts = track_to_read -> last_pts ;
511526 pkt -> stream_index = track_to_read -> index ;
512527
513528 // Update track cursors
514- track_to_read -> current_timestamp += av_rescale (pkt -> duration , (int64_t )read_context -> streams [0 ]-> time_base .num * AV_TIME_BASE , read_context -> streams [0 ]-> time_base .den );
529+ track_to_read -> current_timestamp += av_rescale (pkt -> duration , (int64_t )resource_to_read -> ctx -> streams [0 ]-> time_base .num * AV_TIME_BASE , resource_to_read -> ctx -> streams [0 ]-> time_base .den );
515530 track_to_read -> last_pts += pkt -> duration ;
516531
517532 return 0 ;
@@ -533,6 +548,10 @@ static int imf_close(AVFormatContext *s) {
533548 imf_asset_locator_map_free (c -> asset_locator_map );
534549 imf_cpl_free (c -> cpl );
535550
551+ for (int i = 0 ; i < c -> track_count ; ++ i ) {
552+ imf_virtual_track_playback_context_free (c -> tracks [i ]);
553+ }
554+
536555 return 0 ;
537556}
538557
0 commit comments