LCOV - code coverage report
Current view: top level - media_tools - media_import.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 649 858 75.6 %
Date: 2021-04-29 23:48:07 Functions: 11 12 91.7 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre, Romain Bouqueau, Cyril Concolato
       5             :  *                      Copyright (c) Telecom ParisTech 2000-2021
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / Media Tools sub-project
       9             :  *
      10             :  *  GPAC is free software; you can redistribute it and/or modify
      11             :  *  it under the terms of the GNU Lesser General Public License as published by
      12             :  *  the Free Software Foundation; either version 2, or (at your option)
      13             :  *  any later version.
      14             :  *
      15             :  *  GPAC is distributed in the hope that it will be useful,
      16             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :  *  GNU Lesser General Public License for more details.
      19             :  *
      20             :  *  You should have received a copy of the GNU Lesser General Public
      21             :  *  License along with this library; see the file COPYING.  If not, write to
      22             :  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
      23             :  *
      24             :  */
      25             : 
      26             : #include <gpac/filters.h>
      27             : #include <gpac/constants.h>
      28             : 
      29             : 
      30             : #include <gpac/internal/media_dev.h>
      31             : 
      32             : #include <gpac/xml.h>
      33             : #include <gpac/network.h>
      34             : 
      35             : 
      36             : #ifndef GPAC_DISABLE_MEDIA_IMPORT
      37             : 
      38          65 : GF_Err gf_import_message(GF_MediaImporter *import, GF_Err e, char *format, ...)
      39             : {
      40             : #ifndef GPAC_DISABLE_LOG
      41          65 :         if (gf_log_tool_level_on(GF_LOG_AUTHOR, e ? GF_LOG_WARNING : GF_LOG_INFO)) {
      42             :                 va_list args;
      43             :                 char szMsg[1024];
      44          65 :                 va_start(args, format);
      45             :                 vsnprintf(szMsg, 1024, format, args);
      46          65 :                 va_end(args);
      47          65 :                 GF_LOG((u32) (e ? GF_LOG_WARNING : GF_LOG_INFO), GF_LOG_AUTHOR, ("%s\n", szMsg) );
      48             :         }
      49             : #endif
      50          65 :         return e;
      51             : }
      52             : 
      53             : 
      54         948 : static void gf_media_update_bitrate_ex(GF_ISOFile *file, u32 track, Bool use_esd)
      55             : {
      56             : #ifndef GPAC_DISABLE_ISOM_WRITE
      57             :         u32 i, count, timescale, db_size, cdur, csize;
      58             :         u64 time_wnd, max_rate, avg_rate, bitrate;
      59             :         Double br;
      60             :         GF_ISOSample sample;
      61             : 
      62             :         db_size = 0;
      63             :         max_rate = avg_rate = time_wnd = bitrate = 0;
      64             : 
      65             :         csize = 0;
      66             :         cdur = 0;
      67         948 :         if (gf_isom_get_media_type(file, track)==GF_ISOM_MEDIA_AUDIO) {
      68         236 :                 csize = gf_isom_get_constant_sample_size(file, track);
      69         236 :                 cdur = gf_isom_get_constant_sample_duration(file, track);
      70         236 :                 if (cdur > 1) cdur = 0;
      71             :         }
      72             : 
      73             :         memset(&sample, 0, sizeof(GF_ISOSample));
      74         948 :         timescale = gf_isom_get_media_timescale(file, track);
      75         948 :         count = gf_isom_get_sample_count(file, track);
      76             : 
      77         948 :         if (csize && cdur) {
      78             :                 db_size = 0;
      79          16 :                 avg_rate = 8 * csize * timescale / cdur;
      80             :                 bitrate = avg_rate;
      81             :         } else {
      82             :                 u32 rate = 0;
      83      424314 :                 for (i=0; i<count; i++) {
      84             :                         u32 di;
      85      423386 :                         GF_ISOSample *samp = gf_isom_get_sample_info_ex(file, track, i+1, &di, NULL, &sample);
      86      423386 :                         if (!samp) break;
      87             : 
      88      423382 :                         if (samp->dataLength > db_size) db_size = samp->dataLength;
      89             : 
      90      423382 :                         avg_rate += samp->dataLength;
      91      423382 :                         rate += samp->dataLength;
      92      423382 :                         if (samp->DTS > time_wnd + timescale) {
      93       14566 :                                 if (rate > max_rate) max_rate = rate;
      94             :                                 time_wnd = samp->DTS;
      95             :                                 rate = 0;
      96             :                         }
      97             :                 }
      98             :         }
      99             : 
     100         948 :         br = (Double) (s64) gf_isom_get_media_duration(file, track);
     101         948 :         br /= timescale;
     102         948 :         if (br) {
     103             :                 GF_ESD *esd = NULL;
     104         942 :                 if (!csize || !cdur) {
     105         926 :                         bitrate = (u32) ((Double) (s64)avg_rate / br);
     106         926 :                         bitrate *= 8;
     107         926 :                         max_rate *= 8;
     108             :                 }
     109         942 :                 if (!max_rate) max_rate = bitrate;
     110             : 
     111         942 :                 if (use_esd) esd = gf_isom_get_esd(file, track, 1);
     112          61 :                 if (esd && esd->decoderConfig) {
     113          28 :                         esd->decoderConfig->avgBitrate = (u32) bitrate;
     114          28 :                         esd->decoderConfig->maxBitrate = (u32) max_rate;
     115          28 :                         esd->decoderConfig->bufferSizeDB = db_size;
     116          28 :                         gf_isom_change_mpeg4_description(file, track, 1, esd);
     117             :                 } else {
     118             :                         /*move to bps*/
     119         914 :                         gf_isom_update_bitrate(file, track, 1, (u32) bitrate, (u32) max_rate, db_size);
     120             :                 }
     121         942 :                 if (esd) gf_odf_desc_del((GF_Descriptor *)esd);
     122             :         }
     123             : #endif
     124         948 : }
     125             : 
     126             : GF_EXPORT
     127         887 : void gf_media_update_bitrate(GF_ISOFile *file, u32 track)
     128             : {
     129         887 :         gf_media_update_bitrate_ex(file, track, GF_FALSE);
     130             : 
     131         887 : }
     132          16 : void gf_media_get_video_timing(Double fps, u32 *timescale, u32 *dts_inc)
     133             : {
     134          16 :         u32 fps_1000 = (u32) (fps*1000 + 0.5);
     135             :         /*handle all drop-frame formats*/
     136          16 :         if (fps_1000==29970) {
     137           0 :                 *timescale = 30000;
     138           0 :                 *dts_inc = 1001;
     139             :         }
     140          16 :         else if (fps_1000==23976) {
     141           0 :                 *timescale = 24000;
     142           0 :                 *dts_inc = 1001;
     143             :         }
     144          16 :         else if (fps_1000==59940) {
     145           0 :                 *timescale = 60000;
     146           0 :                 *dts_inc = 1001;
     147             :         } else {
     148          16 :                 *timescale = fps_1000;
     149          16 :                 *dts_inc = 1000;
     150             :         }
     151          16 : }
     152             : 
     153             : 
     154           1 : static GF_Err gf_import_afx_sc3dmc(GF_MediaImporter *import, Bool mult_desc_allowed)
     155             : {
     156             :         GF_Err e;
     157             :         Bool destroy_esd;
     158             :         u32 size, track, di, dsi_len;
     159             :         GF_ISOSample *samp;
     160             :         u32 codecid;
     161             :         char *dsi, *data;
     162             : 
     163           1 :         if (import->flags & GF_IMPORT_PROBE_ONLY) {
     164           0 :                 import->tk_info[0].track_num = 1;
     165           0 :                 import->tk_info[0].stream_type = GF_STREAM_SCENE;
     166           0 :                 import->tk_info[0].codecid = GF_CODECID_AFX;
     167           0 :                 import->nb_tracks = 1;
     168           0 :                 return GF_OK;
     169             :         }
     170             : 
     171           1 :         e = gf_file_load_data(import->in_name, (u8 **) &data, &size);
     172           1 :         if (e) return gf_import_message(import, e, "Opening file %s failed", import->in_name);
     173             : 
     174           1 :         if ((s32) size < 0) return GF_IO_ERR;
     175             : 
     176             :         codecid = GF_CODECID_AFX;
     177             : 
     178           1 :         dsi = (char *)gf_malloc(1);
     179             :         dsi_len = 1;
     180           1 :         dsi[0] = GPAC_AFX_SCALABLE_COMPLEXITY;
     181             : 
     182             :         destroy_esd = GF_FALSE;
     183           1 :         if (!import->esd) {
     184           1 :                 import->esd = gf_odf_desc_esd_new(0);
     185             :                 destroy_esd = GF_TRUE;
     186             :         }
     187             :         /*update stream type/oti*/
     188           1 :         if (!import->esd->decoderConfig) import->esd->decoderConfig = (GF_DecoderConfig *) gf_odf_desc_new(GF_ODF_DCD_TAG);
     189           1 :         if (!import->esd->slConfig) import->esd->slConfig = (GF_SLConfig *) gf_odf_desc_new(GF_ODF_SLC_TAG);
     190           1 :         import->esd->decoderConfig->streamType = GF_STREAM_SCENE;
     191           1 :         import->esd->decoderConfig->objectTypeIndication = codecid;
     192           1 :         import->esd->decoderConfig->bufferSizeDB = size;
     193           1 :         import->esd->decoderConfig->avgBitrate = 8*size;
     194           1 :         import->esd->decoderConfig->maxBitrate = 8*size;
     195           1 :         import->esd->slConfig->timestampResolution = 1000;
     196             : 
     197           1 :         if (!import->esd->decoderConfig->decoderSpecificInfo) import->esd->decoderConfig->decoderSpecificInfo = (GF_DefaultDescriptor *) gf_odf_desc_new(GF_ODF_DSI_TAG);
     198           1 :         if (import->esd->decoderConfig->decoderSpecificInfo->data) gf_free(import->esd->decoderConfig->decoderSpecificInfo->data);
     199           1 :         import->esd->decoderConfig->decoderSpecificInfo->data = dsi;
     200           1 :         import->esd->decoderConfig->decoderSpecificInfo->dataLength = dsi_len;
     201             : 
     202             : 
     203             :         track = 0;
     204           1 :         if (mult_desc_allowed)
     205           1 :                 track = gf_isom_get_track_by_id(import->dest, import->esd->ESID);
     206           1 :         if (!track)
     207           1 :                 track = gf_isom_new_track(import->dest, import->esd->ESID, GF_ISOM_MEDIA_SCENE, 1000);
     208           1 :         if (!track) {
     209           0 :                 e = gf_isom_last_error(import->dest);
     210           0 :                 goto exit;
     211             :         }
     212           1 :         gf_isom_set_track_enabled(import->dest, track, GF_TRUE);
     213           1 :         if (!import->esd->ESID) import->esd->ESID = gf_isom_get_track_id(import->dest, track);
     214           1 :         import->final_trackID = import->esd->ESID;
     215             : 
     216           1 :         if (import->source_magic)
     217           1 :                 gf_isom_set_track_magic(import->dest, track, import->source_magic);
     218             : 
     219           1 :         e = gf_isom_new_mpeg4_description(import->dest, track, import->esd, (import->flags & GF_IMPORT_USE_DATAREF) ? import->in_name : NULL, NULL, &di);
     220           1 :         if (e) goto exit;
     221             :         //gf_isom_set_visual_info(import->dest, track, di, w, h);
     222           1 :         samp = gf_isom_sample_new();
     223           1 :         samp->IsRAP = RAP;
     224           1 :         samp->dataLength = size;
     225           1 :         if (import->initial_time_offset) samp->DTS = (u64) (import->initial_time_offset*1000);
     226             : 
     227           1 :         gf_import_message(import, GF_OK, "%s import %s", "SC3DMC", import->in_name);
     228             : 
     229             :         /*we must start a track from DTS = 0*/
     230           1 :         if (!gf_isom_get_sample_count(import->dest, track) && samp->DTS) {
     231             :                 /*todo - we could add an edit list*/
     232           0 :                 samp->DTS=0;
     233             :         }
     234             : 
     235           1 :         gf_set_progress("Importing SC3DMC", 0, 1);
     236           1 :         if (import->flags & GF_IMPORT_USE_DATAREF) {
     237           0 :                 e = gf_isom_add_sample_reference(import->dest, track, di, samp, (u64) 0);
     238             :         } else {
     239           1 :                 samp->data = data;
     240           1 :                 e = gf_isom_add_sample(import->dest, track, di, samp);
     241           1 :                 samp->data = NULL;
     242             :         }
     243           1 :         gf_set_progress("Importing SC3DMC", 1, 1);
     244             : 
     245           1 :         gf_isom_sample_del(&samp);
     246             : 
     247           1 : exit:
     248           1 :         gf_free(data);
     249           1 :         if (import->esd && destroy_esd) {
     250           1 :                 gf_odf_desc_del((GF_Descriptor *) import->esd);
     251           1 :                 import->esd = NULL;
     252             :         }
     253             :         return e;
     254             : }
     255             : 
     256          81 : static GF_Err gf_import_isomedia_track(GF_MediaImporter *import)
     257             : {
     258             :         GF_Err e;
     259             :         u64 offset, sampDTS, duration, dts_offset;
     260             :         Bool is_nalu_video=GF_FALSE;
     261             :         u32 track, di, trackID, track_in, i, num_samples, mtype, w, h, sr, sbr_sr, ch, mstype, cur_extract_mode, cdur, bps;
     262             :         u64 mtimescale;
     263             :         s32 trans_x, trans_y;
     264             :         s16 layer;
     265             :         char *lang;
     266          81 :         u8 *sai_buffer = NULL;
     267          81 :         u32 sai_buffer_size = 0, sai_buffer_alloc = 0;
     268          81 :         const char *orig_name = gf_url_get_resource_name(gf_isom_get_filename(import->orig));
     269             :         Bool sbr, ps;
     270             :         GF_ISOSample *samp;
     271             :         GF_ESD *origin_esd;
     272             :         GF_InitialObjectDescriptor *iod;
     273             :         Bool is_cenc;
     274             :         GF_ISOTrackCloneFlags clone_flags;
     275             :         sampDTS = 0;
     276          81 :         if (import->flags & GF_IMPORT_PROBE_ONLY) {
     277          60 :                 for (i=0; i<gf_isom_get_track_count(import->orig); i++) {
     278          40 :                         import->tk_info[i].track_num = gf_isom_get_track_id(import->orig, i+1);
     279          40 :                         mtype = gf_isom_get_media_type(import->orig, i+1);
     280          40 :                         switch (mtype) {
     281          12 :                         case GF_ISOM_MEDIA_VISUAL:
     282          12 :                                 import->tk_info[i].stream_type = GF_STREAM_VISUAL;
     283          12 :                                 break;
     284          20 :                         case GF_ISOM_MEDIA_AUDIO:
     285          20 :                                 import->tk_info[i].stream_type = GF_STREAM_AUDIO;
     286          20 :                                 break;
     287           8 :                         case GF_ISOM_MEDIA_TEXT:
     288           8 :                                 import->tk_info[i].stream_type = GF_STREAM_TEXT;
     289           8 :                                 break;
     290           0 :                         case GF_ISOM_MEDIA_SCENE:
     291           0 :                                 import->tk_info[i].stream_type = GF_STREAM_SCENE;
     292           0 :                                 break;
     293           0 :                         default:
     294           0 :                                 import->tk_info[i].stream_type = mtype;
     295           0 :                                 break;
     296             :                         }
     297          40 :                         if (import->tk_info[i].stream_type == GF_STREAM_VISUAL) {
     298          12 :                                 gf_isom_get_visual_info(import->orig, i+1, 1, &import->tk_info[i].video_info.width, &import->tk_info[i].video_info.height);
     299          28 :                         } else if (import->tk_info[i].stream_type == GF_STREAM_AUDIO) {
     300          20 :                                 gf_isom_get_audio_info(import->orig, i+1, 1, &import->tk_info[i].audio_info.sample_rate, &import->tk_info[i].audio_info.nb_channels, NULL);
     301             :                         }
     302          40 :                         lang = NULL;
     303          40 :                         gf_isom_get_media_language(import->orig, i+1, &lang);
     304          40 :                         if (lang) {
     305          40 :                                 import->tk_info[i].lang = GF_4CC(' ', lang[0], lang[1], lang[2]);
     306          40 :                                 gf_free(lang);
     307          40 :                                 lang = NULL;
     308             :                         }
     309          40 :                         gf_media_get_rfc_6381_codec_name(import->orig, i+1, import->tk_info[i].szCodecProfile, GF_FALSE, GF_FALSE);
     310             : 
     311          40 :                         import->nb_tracks ++;
     312             :                 }
     313             :                 return GF_OK;
     314             :         }
     315             : 
     316          61 :         trackID = import->trackID;
     317          61 :         if (!trackID) {
     318           0 :                 if (gf_isom_get_track_count(import->orig) != 1) return gf_import_message(import, GF_BAD_PARAM, "Several tracks in MP4 - please indicate track to import");
     319           0 :                 trackID = gf_isom_get_track_id(import->orig, 1);
     320             :         }
     321          61 :         track_in = gf_isom_get_track_by_id(import->orig, trackID);
     322          61 :         if (!track_in) return gf_import_message(import, GF_URL_ERROR, "Cannot find track ID %d in file", trackID);
     323             : 
     324          61 :         origin_esd = gf_isom_get_esd(import->orig, track_in, 1);
     325             : 
     326          61 :         if (import->esd && origin_esd) {
     327           0 :                 origin_esd->OCRESID = import->esd->OCRESID;
     328             :                 /*there may be other things to import...*/
     329             :         }
     330             :         ps = GF_FALSE;
     331             :         sbr = GF_FALSE;
     332             :         sbr_sr = 0;
     333          61 :         w = h = 0;
     334          61 :         cur_extract_mode = gf_isom_get_nalu_extract_mode(import->orig, track_in);
     335          61 :         iod = (GF_InitialObjectDescriptor *) gf_isom_get_root_od(import->orig);
     336          61 :         if (iod && (iod->tag != GF_ODF_IOD_TAG)) {
     337           0 :                 gf_odf_desc_del((GF_Descriptor *) iod);
     338             :                 iod = NULL;
     339             :         }
     340          61 :         mtype = gf_isom_get_media_type(import->orig, track_in);
     341          61 :         if (mtype==GF_ISOM_MEDIA_VISUAL) {
     342          26 :                 u8 PL = iod ? iod->visual_profileAndLevel : 0xFE;
     343          26 :                 gf_isom_get_visual_info(import->orig, track_in, 1, &w, &h);
     344             : #ifndef GPAC_DISABLE_AV_PARSERS
     345             :                 /*for MPEG-4 visual, always check size (don't trust input file)*/
     346          26 :                 if (origin_esd && (origin_esd->decoderConfig->objectTypeIndication==GF_CODECID_MPEG4_PART2)) {
     347             :                         GF_M4VDecSpecInfo dsi;
     348           2 :                         gf_m4v_get_config(origin_esd->decoderConfig->decoderSpecificInfo->data, origin_esd->decoderConfig->decoderSpecificInfo->dataLength, &dsi);
     349           2 :                         w = dsi.width;
     350           2 :                         h = dsi.height;
     351           2 :                         PL = dsi.VideoPL;
     352             :                 }
     353             : #endif
     354          26 :                 gf_isom_set_pl_indication(import->dest, GF_ISOM_PL_VISUAL, PL);
     355             :         }
     356          35 :         else if (mtype==GF_ISOM_MEDIA_AUDIO) {
     357          21 :                 u8 PL = iod ? iod->audio_profileAndLevel : 0xFE;
     358          21 :                 bps = 16;
     359          21 :                 sr = ch = sbr_sr = 0;
     360             :                 sbr = GF_FALSE;
     361             :                 ps = GF_FALSE;
     362          21 :                 gf_isom_get_audio_info(import->orig, track_in, 1, &sr, &ch, &bps);
     363             : #ifndef GPAC_DISABLE_AV_PARSERS
     364          21 :                 if (origin_esd && origin_esd->decoderConfig && (origin_esd->decoderConfig->objectTypeIndication==GF_CODECID_AAC_MPEG4)) {
     365           5 :                         if (origin_esd->decoderConfig->decoderSpecificInfo) {
     366             :                                 GF_M4ADecSpecInfo dsi;
     367           5 :                                 gf_m4a_get_config(origin_esd->decoderConfig->decoderSpecificInfo->data, origin_esd->decoderConfig->decoderSpecificInfo->dataLength, &dsi);
     368           5 :                                 sr = dsi.base_sr;
     369           5 :                                 if (dsi.has_sbr) sbr_sr = dsi.sbr_sr;
     370           5 :                                 ch = dsi.nb_chan;
     371           5 :                                 PL = dsi.audioPL;
     372           5 :                                 sbr = dsi.has_sbr ? ((dsi.base_object_type==GF_M4A_AAC_SBR || dsi.base_object_type==GF_M4A_AAC_PS) ? 2 : 1) : GF_FALSE;
     373           5 :                                 ps = dsi.has_ps;
     374             :                         } else {
     375           0 :                                 GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("Missing DecoderSpecificInfo in MPEG-4 AAC stream\n"));
     376             :                         }
     377             :                 }
     378             : #endif
     379          21 :                 gf_isom_set_pl_indication(import->dest, GF_ISOM_PL_AUDIO, PL);
     380             :         }
     381          14 :         else if (mtype==GF_ISOM_MEDIA_SUBPIC) {
     382           0 :                 w = h = 0;
     383           0 :                 trans_x = trans_y = 0;
     384           0 :                 layer = 0;
     385           0 :                 if (origin_esd && origin_esd->decoderConfig->objectTypeIndication == GF_CODECID_SUBPIC) {
     386           0 :                         gf_isom_get_track_layout_info(import->orig, track_in, &w, &h, &trans_x, &trans_y, &layer);
     387             :                 }
     388             :         }
     389             : 
     390          61 :         gf_odf_desc_del((GF_Descriptor *) iod);
     391          61 :         if ( ! gf_isom_get_track_count(import->dest)) {
     392             :                 u32 timescale;
     393          32 :                 if (import->moov_timescale<0)
     394           2 :                         timescale = gf_isom_get_media_timescale(import->orig, track_in);
     395             :                 else
     396          30 :                         timescale = gf_isom_get_timescale(import->orig);
     397          32 :                 gf_isom_set_timescale(import->dest, timescale);
     398             :         }
     399             :         clone_flags = GF_ISOM_CLONE_TRACK_NO_QT;
     400          61 :         if (import->asemode == GF_IMPORT_AUDIO_SAMPLE_ENTRY_v1_QTFF) {
     401             :                 clone_flags = 0;
     402             :         } else {
     403          50 :                 const char *dst = gf_isom_get_filename(import->dest);
     404          50 :                 if (dst && strstr(dst, ".mov"))
     405             :                         clone_flags = 0;
     406             :         }
     407             : 
     408          61 :         if (import->flags & GF_IMPORT_USE_DATAREF) clone_flags |= GF_ISOM_CLONE_TRACK_KEEP_DREF;
     409          61 :         e = gf_isom_clone_track(import->orig, track_in, import->dest, clone_flags, &track);
     410          61 :         if (e) goto exit;
     411             : 
     412             : 
     413          61 :         if ((gf_isom_get_track_count(import->dest)==1) && gf_isom_has_keep_utc_times(import->dest)) {
     414             :                 u64 cdate, mdate;
     415           0 :                 gf_isom_get_creation_time(import->orig, &cdate, &mdate);
     416           0 :                 gf_isom_set_creation_time(import->dest, cdate, mdate);
     417             :         }
     418             : 
     419          61 :         di = 1;
     420             : 
     421          61 :         if (import->esd && import->esd->ESID) {
     422           0 :                 e = gf_isom_set_track_id(import->dest, track, import->esd->ESID);
     423           0 :                 if (e) goto exit;
     424             :         }
     425             : 
     426          61 :         import->final_trackID = gf_isom_get_track_id(import->dest, track);
     427          61 :         if (import->esd && import->esd->dependsOnESID) {
     428           0 :                 gf_isom_set_track_reference(import->dest, track, GF_ISOM_REF_DECODE, import->esd->dependsOnESID);
     429             :         }
     430             : 
     431          61 :         if (import->trackID && !(import->flags & GF_IMPORT_KEEP_REFS)) {
     432          11 :                 gf_isom_remove_track_references(import->dest, track);
     433             :         }
     434             : 
     435          61 :         if (import->source_magic)
     436          61 :                 gf_isom_set_track_magic(import->dest, track, import->source_magic);
     437             : 
     438          61 :         mstype = gf_isom_get_media_subtype(import->orig, track_in, di);
     439          61 :         switch (mtype) {
     440          26 :         case GF_ISOM_MEDIA_VISUAL:
     441          26 :                 gf_import_message(import, GF_OK, "IsoMedia import %s - track ID %d - Video (size %d x %d)", orig_name, trackID, w, h);
     442          26 :                 break;
     443           0 :     case GF_ISOM_MEDIA_AUXV:
     444           0 :         gf_import_message(import, GF_OK, "IsoMedia import %s - track ID %d - Auxiliary Video (size %d x %d)", orig_name, trackID, w, h);
     445           0 :         break;
     446           0 :     case GF_ISOM_MEDIA_PICT:
     447           0 :         gf_import_message(import, GF_OK, "IsoMedia import %s - track ID %d - Picture sequence (size %d x %d)", orig_name, trackID, w, h);
     448           0 :         break;
     449          21 :         case GF_ISOM_MEDIA_AUDIO:
     450             :         {
     451          21 :                 if (ps) {
     452           0 :                         gf_import_message(import, GF_OK, "IsoMedia import %s - track ID %d - HE-AACv2 (SR %d - SBR-SR %d - %d channels)", orig_name, trackID, sr, sbr_sr, ch);
     453          21 :                 } else if (sbr) {
     454           0 :                         gf_import_message(import, GF_OK, "IsoMedia import %s - track ID %d - HE-AAC (SR %d - SBR-SR %d - %d channels)", orig_name, trackID, sr, sbr_sr, ch);
     455             :                 } else {
     456          21 :                         gf_import_message(import, GF_OK, "IsoMedia import %s - track ID %d - Audio (SR %d - %d channels)", orig_name, trackID, sr, ch);
     457             :                 }
     458          21 :                 if (import->asemode != GF_IMPORT_AUDIO_SAMPLE_ENTRY_NOT_SET) {
     459           8 :                         gf_isom_get_audio_info(import->orig, track_in, 1, &sr, &ch, &bps);
     460           8 :                         gf_isom_set_audio_info(import->dest, track, 1, sr, ch, bps, import->asemode);
     461             :                 }
     462             :         }
     463             :         break;
     464           0 :         case GF_ISOM_MEDIA_SUBPIC:
     465           0 :                 gf_import_message(import, GF_OK, "IsoMedia import %s - track ID %d - VobSub (size %d x %d)", orig_name, trackID, w, h);
     466           0 :                 break;
     467          14 :         default:
     468             :         {
     469             :                 char szT[GF_4CC_MSIZE];
     470          14 :                 mstype = gf_isom_get_mpeg4_subtype(import->orig, track_in, di);
     471          14 :                 if (!mstype) mstype = gf_isom_get_media_subtype(import->orig, track_in, di);
     472          14 :                 strcpy(szT, gf_4cc_to_str(mtype));
     473          14 :                 gf_import_message(import, GF_OK, "IsoMedia import %s - track ID %d - media type \"%s:%s\"", orig_name, trackID, szT, gf_4cc_to_str(mstype));
     474             :         }
     475          14 :         break;
     476             :         }
     477             : 
     478             :         //this may happen with fragmented files
     479             :         dts_offset = 0;
     480          61 :         samp = gf_isom_get_sample_info(import->orig, track_in, 1, &di, &offset);
     481          61 :         if (samp) {
     482          61 :                 dts_offset = samp->DTS;
     483          61 :                 gf_isom_sample_del(&samp);
     484             :         }
     485             : 
     486          61 :         is_cenc = gf_isom_is_cenc_media(import->orig, track_in, 0);
     487          61 :         if (gf_isom_is_media_encrypted(import->orig, track_in, 0)) {
     488           2 :                 gf_isom_get_original_format_type(import->orig, track_in, 0, &mstype);
     489             :         }
     490             : 
     491          61 :         cdur = gf_isom_get_constant_sample_duration(import->orig, track_in);
     492          61 :         gf_isom_enable_raw_pack(import->orig, track_in, 2048);
     493             : 
     494          61 :         mtimescale = gf_isom_get_media_timescale(import->orig, track_in);
     495             :         duration = 0;
     496          61 :         if ((import->duration.num>0) && import->duration.den) {
     497           3 :                 duration = (u64) (((Double)import->duration.num * mtimescale) / import->duration.den);
     498             :         }
     499          61 :         gf_isom_set_nalu_extract_mode(import->orig, track_in, GF_ISOM_NALU_EXTRACT_INSPECT);
     500             : 
     501          61 :         if (import->xps_inband) {
     502           0 :                 if (is_cenc ) {
     503           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[ISOM import] CENC media detected - cannot switch parameter set storage mode\n"));
     504           0 :                 } else if (import->flags & GF_IMPORT_USE_DATAREF) {
     505           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[ISOM import] Cannot switch parameter set storage mode when using data reference\n"));
     506             :                 } else {
     507           0 :                         switch (mstype) {
     508           0 :                         case GF_ISOM_SUBTYPE_AVC_H264:
     509           0 :                                 gf_isom_set_nalu_extract_mode(import->orig, track_in, GF_ISOM_NALU_EXTRACT_INSPECT | GF_ISOM_NALU_EXTRACT_INBAND_PS_FLAG);
     510           0 :                                 gf_isom_avc_set_inband_config(import->dest, track, 1, (import->xps_inband==2) ? GF_TRUE : GF_FALSE);
     511           0 :                                 break;
     512           0 :                         case GF_ISOM_SUBTYPE_HVC1:
     513           0 :                                 gf_isom_set_nalu_extract_mode(import->orig, track_in, GF_ISOM_NALU_EXTRACT_INSPECT | GF_ISOM_NALU_EXTRACT_INBAND_PS_FLAG);
     514           0 :                                 gf_isom_hevc_set_inband_config(import->dest, track, 1, (import->xps_inband==2) ? GF_TRUE : GF_FALSE);
     515           0 :                                 break;
     516           0 :                         case GF_ISOM_SUBTYPE_VVC1:
     517           0 :                                 gf_isom_set_nalu_extract_mode(import->orig, track_in, GF_ISOM_NALU_EXTRACT_INSPECT | GF_ISOM_NALU_EXTRACT_INBAND_PS_FLAG);
     518             :                                 //gf_isom_vvc_set_inband_config(import->dest, track, 1, (import->xps_inband==2) ? GF_TRUE : GF_FALSE);
     519           0 :                                 break;
     520             :                         }
     521             :                 }
     522             :         }
     523          61 :         switch (mstype) {
     524          19 :         case GF_ISOM_SUBTYPE_AVC_H264:
     525             :         case GF_ISOM_SUBTYPE_SVC_H264:
     526             :         case GF_ISOM_SUBTYPE_MVC_H264:
     527             :         case GF_ISOM_SUBTYPE_AVC2_H264:
     528             :         case GF_ISOM_SUBTYPE_AVC3_H264:
     529             :         case GF_ISOM_SUBTYPE_AVC4_H264:
     530             :         case GF_ISOM_SUBTYPE_HEV1:
     531             :         case GF_ISOM_SUBTYPE_HVC1:
     532             :         case GF_ISOM_SUBTYPE_LHE1:
     533             :         case GF_ISOM_SUBTYPE_LHV1:
     534             :         case GF_ISOM_SUBTYPE_HVT1:
     535             :         case GF_ISOM_SUBTYPE_VVC1:
     536             :         case GF_ISOM_SUBTYPE_VVI1:
     537             :                 is_nalu_video = GF_TRUE;
     538          19 :                 break;
     539             :         }
     540          61 :         num_samples = gf_isom_get_sample_count(import->orig, track_in);
     541             : 
     542          61 :         if (is_cenc) {
     543             :                 u32 container_type;
     544           2 :                 e = gf_isom_cenc_get_sample_aux_info(import->orig, track_in, 0, 1, &container_type, NULL, NULL);
     545           2 :                 if (e)
     546             :                         goto exit;
     547           2 :                 if (container_type==GF_ISOM_BOX_UUID_PSEC) {
     548           0 :                         e = gf_isom_piff_allocate_storage(import->dest, track, 0, 0, NULL);
     549             :                 } else {
     550           2 :                         e = gf_isom_cenc_allocate_storage(import->dest, track);
     551             :                 }
     552           2 :                 if (e) goto exit;
     553           2 :                 e = gf_isom_clone_pssh(import->dest, import->orig, GF_FALSE);
     554           2 :                 if (e) goto exit;
     555             :         }
     556        6771 :         for (i=0; i<num_samples; i++) {
     557        6713 :                 if (import->flags & GF_IMPORT_USE_DATAREF) {
     558         514 :                         samp = gf_isom_get_sample_info(import->orig, track_in, i+1, &di, &offset);
     559         514 :                         if (!samp) {
     560           0 :                                 e = gf_isom_last_error(import->orig);
     561           0 :                                 goto exit;
     562             :                         }
     563             : 
     564         514 :                         samp->DTS -= dts_offset;
     565         514 :                         if (duration && !gf_sys_old_arch_compat() && ((u64) samp->DTS * import->duration.den >= mtimescale * import->duration.num)) {
     566           0 :                                 gf_isom_sample_del(&samp);
     567           0 :                                 break;
     568             :                         }
     569         514 :                         e = gf_isom_add_sample_reference(import->dest, track, di, samp, offset);
     570             :                 } else {
     571        6199 :                         samp = gf_isom_get_sample(import->orig, track_in, i+1, &di);
     572        6199 :                         if (!samp) {
     573             :                                 /*couldn't get the sample, but still move on*/
     574             :                                 goto exit;
     575             :                         }
     576        6199 :                         samp->DTS -= dts_offset;
     577             : 
     578             :                         /*if packed samples (raw) and import duration is set, adjust the number of samples to add*/
     579        6199 :                         if (samp->nb_pack && duration && (samp->DTS + samp->nb_pack*cdur > duration) ) {
     580           0 :                                 u32 nb_samp = (u32) ( (duration - samp->DTS) / cdur);
     581           0 :                                 u32 csize = samp->dataLength / samp->nb_pack;
     582           0 :                                 if (!nb_samp) {
     583           0 :                                         gf_isom_sample_del(&samp);
     584           0 :                                         break;
     585             :                                 }
     586           0 :                                 samp->dataLength = csize*nb_samp;
     587           0 :                                 samp->nb_pack = nb_samp;
     588           0 :                                 duration = samp->DTS-1;
     589             :                         }
     590             : 
     591             :                         /*if not first sample and same DTS as previous sample, force DTS++*/
     592        6199 :                         if (i && (samp->DTS<=sampDTS)) {
     593           0 :                                 if (i+1 < num_samples) {
     594           0 :                                         GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[ISOM import] 0-duration sample detected at DTS %u - adjusting\n", samp->DTS));
     595             :                                 }
     596           0 :                                 samp->DTS = sampDTS + 1;
     597             :                         }
     598             : 
     599        6199 :                         if (duration && !gf_sys_old_arch_compat() && ((u64) samp->DTS * import->duration.den >= mtimescale * import->duration.num)) {
     600           0 :                                 gf_isom_sample_del(&samp);
     601           0 :                                 break;
     602             :                         }
     603             : 
     604        6199 :                         e = gf_isom_add_sample(import->dest, track, di, samp);
     605             :                 }
     606        6713 :                 sampDTS = samp->DTS;
     607        6713 :                 if (samp->nb_pack)
     608         400 :                         i+= samp->nb_pack-1;
     609        6713 :                 gf_isom_sample_del(&samp);
     610             : 
     611             :                 //this will also copy all sample to group mapping, including seig for CENC
     612        6713 :                 gf_isom_copy_sample_info(import->dest, track, import->orig, track_in, i+1);
     613             : 
     614        6713 :                 if (e)
     615             :                         goto exit;
     616        6713 :                 if (is_cenc) {
     617             :                         u32 container_type;
     618             :                         Bool Is_Encrypted;
     619             :                         Bool is_mkey=GF_FALSE;
     620             :                         u8 crypt_byte_block, skip_byte_block;
     621        1004 :                         const u8 *key_info=NULL;
     622        1004 :                         u32 key_info_len = 0;
     623             : 
     624        1004 :                         e = gf_isom_get_sample_cenc_info(import->orig, track_in, i+1, &Is_Encrypted, &crypt_byte_block, &skip_byte_block, &key_info, &key_info_len);
     625        1004 :                         if (e) goto exit;
     626        1004 :                         if (key_info) {
     627        1004 :                                 is_mkey = key_info[0];
     628             :                         }
     629             : 
     630        1004 :                         if (Is_Encrypted) {
     631        1004 :                                 sai_buffer_size = sai_buffer_alloc;
     632        1004 :                                 e = gf_isom_cenc_get_sample_aux_info(import->orig, track_in, i+1, di, &container_type, &sai_buffer, &sai_buffer_size);
     633        1004 :                                 if (e) goto exit;
     634        1004 :                                 if (sai_buffer_size > sai_buffer_alloc)
     635             :                                         sai_buffer_alloc = sai_buffer_size;
     636             : 
     637        1004 :                                 e = gf_isom_track_cenc_add_sample_info(import->dest, track, container_type, sai_buffer, sai_buffer_size, is_nalu_video, GF_FALSE, is_mkey);
     638             : 
     639             :                         } else {
     640             :                                 //we don't set container type since we don't add data to the container (senc/...)
     641           0 :                                 e = gf_isom_track_cenc_add_sample_info(import->dest, track, 0, NULL, 0, is_nalu_video, GF_FALSE, is_mkey);
     642             :                         }
     643        1004 :                         if (e)
     644             :                                 goto exit;
     645             :                 }
     646             : 
     647        6713 :                 gf_set_progress("Importing ISO File", i+1, num_samples);
     648             : 
     649        6713 :                 if (duration && gf_sys_old_arch_compat() && (sampDTS > duration))
     650             :                         break;
     651             :         }
     652             : 
     653             :         //adjust last sample duration
     654          61 :         if (i==num_samples) {
     655          58 :                 u32 dur = gf_isom_get_sample_duration(import->orig, track_in, num_samples);
     656          58 :                 gf_isom_set_last_sample_duration(import->dest, track, dur);
     657             :         } else {
     658             :                 s64 mediaOffset;
     659           3 :                 if (gf_isom_get_edit_list_type(import->orig, track_in, &mediaOffset)) {
     660           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[ISOBMF Import] Multiple edits found in source media, import may be broken\n"));
     661             :                 }
     662           3 :                 gf_isom_update_edit_list_duration(import->dest, track);
     663           3 :                 gf_isom_update_duration(import->dest);
     664             :         }
     665             : 
     666          61 :         if (gf_isom_has_time_offset(import->orig, track_in)==2) {
     667           0 :                 e = gf_isom_set_composition_offset_mode(import->dest, track, GF_TRUE);
     668           0 :                 if (e)
     669             :                         goto exit;
     670             :         }
     671             : 
     672             : 
     673          61 :         if (import->esd) {
     674           0 :                 if (!import->esd->slConfig) {
     675           0 :                         import->esd->slConfig = origin_esd ? origin_esd->slConfig : NULL;
     676           0 :                         if (origin_esd) origin_esd->slConfig = NULL;
     677             :                 }
     678           0 :                 if (!import->esd->decoderConfig) {
     679           0 :                         import->esd->decoderConfig = origin_esd ? origin_esd->decoderConfig : NULL;
     680           0 :                         if (origin_esd) origin_esd->decoderConfig = NULL;
     681             :                 }
     682             :         }
     683          61 :         gf_media_update_bitrate_ex(import->dest, track, GF_TRUE);
     684          61 :         if (mtype == GF_ISOM_MEDIA_VISUAL) {
     685          26 :                 if (import->is_alpha) {
     686           0 :                         e = gf_isom_set_image_sequence_alpha(import->dest, track, di, GF_FALSE);
     687             :                         if (e) goto exit;
     688             :                 }
     689             :         }
     690             : 
     691          61 : exit:
     692          61 :         if (sai_buffer) gf_free(sai_buffer);
     693          61 :         if (origin_esd) gf_odf_desc_del((GF_Descriptor *) origin_esd);
     694          61 :         gf_isom_set_nalu_extract_mode(import->orig, track_in, cur_extract_mode);
     695          61 :         return e;
     696             : }
     697             : 
     698          42 : static GF_Err gf_import_isomedia(GF_MediaImporter *import)
     699             : {
     700             :         u32 nb_tracks, i;
     701          42 :         if (import->trackID)
     702          10 :                 return gf_import_isomedia_track(import);
     703             : 
     704          32 :         if (!import->orig) return GF_BAD_PARAM;
     705             : 
     706          32 :         nb_tracks = gf_isom_get_track_count(import->orig);
     707         135 :         for (i=0; i<nb_tracks; i++) {
     708          71 :                 import->trackID = gf_isom_get_track_id(import->orig, i+1);
     709          71 :                 if (import->trackID) {
     710          71 :                         GF_Err e = gf_import_isomedia_track(import);
     711          71 :                         import->trackID = 0;
     712          71 :                         if (e) return e;
     713             :                 }
     714             :         }
     715             :         return GF_OK;
     716             : }
     717             : 
     718             : GF_EXPORT
     719           1 : GF_Err gf_media_nal_rewrite_samples(GF_ISOFile *file, u32 track, u32 new_size)
     720             : {
     721             :         u32 i, count, di, remain, msize;
     722             :         char *buffer;
     723             : 
     724             :         msize = 4096;
     725           1 :         buffer = (char*)gf_malloc(sizeof(char)*msize);
     726           1 :         count = gf_isom_get_sample_count(file, track);
     727         175 :         for (i=0; i<count; i++) {
     728         173 :                 GF_ISOSample *samp = gf_isom_get_sample(file, track, i+1, &di);
     729         173 :                 GF_BitStream *oldbs = gf_bs_new(samp->data, samp->dataLength, GF_BITSTREAM_READ);
     730         173 :                 GF_BitStream *newbs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     731         173 :                 u32 prev_size = 8*gf_isom_get_nalu_length_field(file, track, di);
     732         173 :                 if (!prev_size) return GF_NON_COMPLIANT_BITSTREAM;
     733             :                 
     734         173 :                 remain = samp->dataLength;
     735         520 :                 while (remain) {
     736         174 :                         u32 size = gf_bs_read_int(oldbs, prev_size);
     737         174 :                         gf_bs_write_int(newbs, size, new_size);
     738         174 :                         remain -= prev_size/8;
     739         174 :                         if (size>msize) {
     740             :                                 msize = size;
     741           0 :                                 buffer = (char*)gf_realloc(buffer, sizeof(char)*msize);
     742             :                         }
     743         174 :                         gf_bs_read_data(oldbs, buffer, size);
     744         174 :                         gf_bs_write_data(newbs, buffer, size);
     745         174 :                         remain -= size;
     746             :                 }
     747         173 :                 gf_bs_del(oldbs);
     748         173 :                 gf_free(samp->data);
     749         173 :                 samp->data = NULL;
     750         173 :                 samp->dataLength = 0;
     751         173 :                 gf_bs_get_content(newbs, &samp->data, &samp->dataLength);
     752         173 :                 gf_bs_del(newbs);
     753         173 :                 gf_isom_update_sample(file, track, i+1, samp, GF_TRUE);
     754         173 :                 gf_isom_sample_del(&samp);
     755             :         }
     756           1 :         gf_free(buffer);
     757           1 :         return GF_OK;
     758             : }
     759             : 
     760             : GF_EXPORT
     761           2 : GF_Err gf_media_import_chapters_file(GF_MediaImporter *import)
     762             : {
     763             :         s32 read=0;
     764             :         GF_Err e;
     765             :         u32 state, offset;
     766             :         u32 cur_chap;
     767             :         u64 ts;
     768             :         Bool found_chap = GF_FALSE;
     769             :         u32 i, h, m, s, ms, fr, fps;
     770             :         char line[1024];
     771             :         char szTitle[1024];
     772           2 :         FILE *f = gf_fopen(import->in_name, "rt");
     773           2 :         if (!f) return GF_URL_ERROR;
     774             : 
     775           2 :         read = (s32) gf_fread(line, 4, f);
     776           2 :         if (read < 0) {
     777             :                 e = GF_IO_ERR;
     778             :                 goto err_exit;
     779             :         }
     780           2 :         if (read < 4) {
     781             :                 e = GF_URL_ERROR;
     782             :                 goto err_exit;
     783             :         }
     784             : 
     785           2 :         if ((line[0]==(char)(0xFF)) && (line[1]==(char)(0xFE))) {
     786           0 :                 if (!line[2] && !line[3]) {
     787             :                         e = GF_NOT_SUPPORTED;
     788             :                         goto err_exit;
     789             :                 }
     790             :                 offset = 2;
     791           2 :         } else if ((line[0]==(char)(0xFE)) && (line[1]==(char)(0xFF))) {
     792           0 :                 if (!line[2] && !line[3]) {
     793             :                         e = GF_NOT_SUPPORTED;
     794             :                         goto err_exit;
     795             :                 }
     796             :                 offset = 2;
     797           2 :         } else if ((line[0]==(char)(0xEF)) && (line[1]==(char)(0xBB)) && (line[2]==(char)(0xBF))) {
     798             :                 /*we handle UTF8 as asci*/
     799             :                 offset = 3;
     800             :         } else {
     801             :                 offset = 0;
     802             :         }
     803           2 :         gf_fseek(f, offset, SEEK_SET);
     804             : 
     805           2 :         if (import->flags & GF_IMPORT_PROBE_ONLY) {
     806             :                 Bool is_chap_or_sub = GF_FALSE;
     807           0 :                 import->nb_tracks = 0;
     808           0 :                 while (!is_chap_or_sub && (gf_fgets(line, 1024, f) != NULL)) {
     809             :                         char *sep;
     810           0 :                         strlwr(line);
     811             : 
     812           0 :                         if (strstr(line, "addchapter(")) is_chap_or_sub = GF_TRUE;
     813           0 :                         else if (strstr(line, "-->")) is_chap_or_sub = GF_TRUE;
     814           0 :                         else if ((sep = strstr(line, "chapter")) != NULL) {
     815             :                                 sep+=7;
     816           0 :                                 if (!strncmp(sep+1, "name", 4)) is_chap_or_sub = GF_TRUE;
     817           0 :                                 else if (!strncmp(sep+2, "name", 4)) is_chap_or_sub = GF_TRUE;
     818           0 :                                 else if (!strncmp(sep+3, "name", 4)) is_chap_or_sub = GF_TRUE;
     819           0 :                                 else if (strstr(line, "Zoom") || strstr(line, "zoom")) is_chap_or_sub = GF_TRUE;
     820             :                         }
     821             :                 }
     822           0 :                 gf_fclose(f);
     823           0 :                 if (is_chap_or_sub) {
     824           0 :                         import->nb_tracks = 1;
     825           0 :                         import->tk_info[0].stream_type = GF_STREAM_TEXT;
     826           0 :                         import->tk_info[0].is_chapter = GF_TRUE;
     827           0 :                         return GF_OK;
     828             :                 }
     829             :                 return GF_NOT_SUPPORTED;
     830             :         }
     831             : 
     832           2 :         e = gf_isom_remove_chapter(import->dest, 0, 0);
     833           2 :         if (e) goto err_exit;
     834             : 
     835           2 :         if (!import->video_fps.num || !import->video_fps.den ) {
     836             :                 /*try to figure out the frame rate*/
     837           2 :                 for (i=0; i<gf_isom_get_track_count(import->dest); i++) {
     838             :                         GF_ISOSample *samp;
     839             :                         u32 timescale, inc;
     840           2 :             u32 mtype = gf_isom_get_media_type(import->dest, i+1);
     841           2 :                         if (!gf_isom_is_video_handler_type(mtype)) continue;
     842           2 :                         if (gf_isom_get_sample_count(import->dest, i+1) < 20) continue;
     843           2 :                         samp = gf_isom_get_sample_info(import->dest, 1, 2, NULL, NULL);
     844           2 :                         inc = (u32) samp->DTS;
     845           2 :                         if (!inc) inc=1;
     846           2 :                         timescale = gf_isom_get_media_timescale(import->dest, i+1);
     847           2 :                         import->video_fps.num = timescale;
     848           2 :                         import->video_fps.den = inc;
     849           2 :                         gf_isom_sample_del(&samp);
     850           2 :                         GF_LOG(GF_LOG_INFO, GF_LOG_AUTHOR, ("[Chapter import] Guessed video frame rate %u/%u\n", timescale, inc));
     851           2 :                         break;
     852             :                 }
     853           2 :                 if (!import->video_fps.num || !import->video_fps.den) {
     854           0 :                         import->video_fps.num = 25;
     855           0 :                         import->video_fps.den = 1;
     856             :                 }
     857             :         }
     858             : 
     859             :         cur_chap = 0;
     860             :         ts = 0;
     861             :         state = 0;
     862          17 :         while (gf_fgets(line, 1024, f) != NULL) {
     863             :                 char *title = NULL;
     864             :                 u32 off = 0;
     865             :                 char *sL;
     866          30 :                 while (1) {
     867          45 :                         u32 len = (u32) strlen(line);
     868          45 :                         if (!len) break;
     869          45 :                         switch (line[len-1]) {
     870          30 :                         case '\n':
     871             :                         case '\t':
     872             :                         case '\r':
     873             :                         case ' ':
     874          30 :                                 line[len-1] = 0;
     875          30 :                                 continue;
     876             :                         }
     877             :                         break;
     878             :                 }
     879             : 
     880           0 :                 while (line[off]==' ') off++;
     881          15 :                 if (!strlen(line+off)) continue;
     882             :                 sL = line+off;
     883             : 
     884          15 :                 szTitle[0] = 0;
     885             :                 /*ZoomPlayer chapters*/
     886          15 :                 if (!strnicmp(sL, "AddChapter(", 11)) {
     887             :                         u32 nb_fr;
     888           0 :                         sscanf(sL, "AddChapter(%u,%1023s)", &nb_fr, szTitle);
     889           0 :                         ts = nb_fr;
     890           0 :                         ts *= 1000;
     891           0 :                         ts = (u64) (((s64) ts )  *import->video_fps.den / import->video_fps.num);
     892           0 :                         sL = strchr(sL, ',');
     893           0 :                         strcpy(szTitle, sL+1);
     894           0 :                         sL = strrchr(szTitle, ')');
     895           0 :                         if (sL) sL[0] = 0;
     896          15 :                 } else if (!strnicmp(sL, "AddChapterBySecond(", 19)) {
     897             :                         u32 nb_s;
     898           0 :                         sscanf(sL, "AddChapterBySecond(%u,%1023s)", &nb_s, szTitle);
     899           0 :                         ts = nb_s;
     900           0 :                         ts *= 1000;
     901           0 :                         sL = strchr(sL, ',');
     902           0 :                         strcpy(szTitle, sL+1);
     903           0 :                         sL = strrchr(szTitle, ')');
     904           0 :                         if (sL) sL[0] = 0;
     905          15 :                 } else if (!strnicmp(sL, "AddChapterByTime(", 17)) {
     906           1 :                         sscanf(sL, "AddChapterByTime(%u,%u,%u,%1023s)", &h, &m, &s, szTitle);
     907           1 :                         ts = 3600*h + 60*m + s;
     908           1 :                         ts *= 1000;
     909           1 :                         sL = strchr(sL, ',');
     910           1 :                         if (sL) sL = strchr(sL+1, ',');
     911           1 :                         if (sL) sL = strchr(sL+1, ',');
     912           1 :                         if (sL) strcpy(szTitle, sL+1);
     913           1 :                         sL = strrchr(szTitle, ')');
     914           1 :                         if (sL) sL[0] = 0;
     915             :                 }
     916             :                 /*regular or SMPTE time codes*/
     917          14 :                 else if ((strlen(sL)>=8) && (sL[2]==':') && (sL[5]==':')) {
     918             :                         title = NULL;
     919           4 :                         if (strlen(sL)==8) {
     920           0 :                                 sscanf(sL, "%02u:%02u:%02u", &h, &m, &s);
     921           0 :                                 ts = (h*3600 + m*60+s)*1000;
     922             :                         }
     923             :                         else {
     924             :                                 char szTS[20], *tok;
     925             :                                 strncpy(szTS, sL, 19);
     926           4 :                                 szTS[19]=0;
     927           4 :                                 tok = strrchr(szTS, ' ');
     928           4 :                                 if (tok) {
     929           4 :                                         title = strchr(sL, ' ') + 1;
     930           4 :                                         while (title[0]==' ') title++;
     931           4 :                                         if (strlen(title)) strcpy(szTitle, title);
     932           4 :                                         tok[0] = 0;
     933             :                                 }
     934             :                                 ts = 0;
     935           4 :                                 h = m = s = ms = 0;
     936             : 
     937           4 :                                 if (sscanf(szTS, "%u:%u:%u;%u/%u", &h, &m, &s, &fr, &fps)==5) {
     938           1 :                                         ts = (h*3600 + m*60+s)*1000 + 1000*fr/fps;
     939           3 :                                 } else if (sscanf(szTS, "%u:%u:%u;%u", &h, &m, &s, &fr)==4) {
     940           1 :                                         ts = (h*3600 + m*60+s);
     941           1 :                                         ts = (s64) (((import->video_fps.num*((s64)ts) + import->video_fps.den*fr) * 1000 ) / import->video_fps.num ) ;
     942           2 :                                 } else if (sscanf(szTS, "%u:%u:%u.%u", &h, &m, &s, &ms) == 4) {
     943             :                                         //microseconds used
     944           0 :                                         if (ms>=1000) ms /= 1000;
     945           0 :                                         ts = (h*3600 + m*60+s)*1000+ms;
     946           2 :                                 } else if (sscanf(szTS, "%u:%u:%u.%u", &h, &m, &s, &ms) == 4) {
     947             :                                         //microseconds used
     948           0 :                                         if (ms>=1000) ms /= 1000;
     949           0 :                                         ts = (h*3600 + m*60+s)*1000+ms;
     950           2 :                                 } else if (sscanf(szTS, "%u:%u:%u:%u", &h, &m, &s, &ms) == 4) {
     951             :                                         //microseconds used
     952           2 :                                         if (ms>=1000) ms /= 1000;
     953           2 :                                         ts = (h*3600 + m*60+s)*1000+ms;
     954           0 :                                 } else if (sscanf(szTS, "%u:%u:%u", &h, &m, &s) == 3) {
     955           0 :                                         ts = (h*3600 + m*60+s) * 1000;
     956             :                                 }
     957             :                         }
     958             :                 }
     959             :                 /*CHAPTERX= and CHAPTERXNAME=*/
     960          10 :                 else if (!strnicmp(sL, "CHAPTER", 7)) {
     961             :                         u32 idx;
     962             :                         char szTemp[20], *str;
     963             :                         strncpy(szTemp, sL, 19);
     964           8 :                         szTemp[19] = 0;
     965           8 :                         str = strrchr(szTemp, '=');
     966          16 :                         if (!str) continue;
     967           8 :                         str[0] = 0;
     968           8 :                         strlwr(szTemp);
     969           8 :                         idx = cur_chap;
     970           8 :                         str = strchr(sL, '=');
     971           8 :                         str++;
     972           8 :                         if (strstr(szTemp, "name")) {
     973           4 :                                 sscanf(szTemp, "chapter%uname", &idx);
     974             :                                 strcpy(szTitle, str);
     975           4 :                                 if (idx!=cur_chap) {
     976             :                                         cur_chap=idx;
     977             :                                         state = 0;
     978             :                                 }
     979           4 :                                 state++;
     980             :                         } else {
     981           4 :                                 sscanf(szTemp, "chapter%u", &idx);
     982           4 :                                 if (idx!=cur_chap) {
     983             :                                         cur_chap=idx;
     984             :                                         state = 0;
     985             :                                 }
     986           4 :                                 state++;
     987             : 
     988             :                                 ts = 0;
     989           4 :                                 h = m = s = ms = 0;
     990           4 :                                 if (sscanf(str, "%u:%u:%u.%u", &h, &m, &s, &ms) == 4) {
     991             :                                         //microseconds used
     992           0 :                                         if (ms>=1000) ms/=1000;
     993           0 :                                         ts = (h*3600 + m*60+s)*1000+ms;
     994           4 :                                 } else if (sscanf(str, "%u:%u:%u:%u", &h, &m, &s, &ms) == 4) {
     995             :                                         //microseconds used
     996           4 :                                         if (ms>=1000) ms/=1000;
     997           4 :                                         ts = (h*3600 + m*60+s)*1000+ms;
     998           0 :                                 } else if (sscanf(str, "%u:%u:%u", &h, &m, &s) == 3) {
     999           0 :                                         ts = (h*3600 + m*60+s) * 1000;
    1000             :                                 }
    1001             :                         }
    1002           8 :                         if (state==2) {
    1003             :                                 found_chap = GF_TRUE;
    1004           4 :                                 e = gf_isom_add_chapter(import->dest, 0, ts, szTitle);
    1005           4 :                                 if (e) goto err_exit;
    1006             :                                 state = 0;
    1007             :                         }
    1008           8 :                         continue;
    1009             :                 }
    1010           2 :                 else continue;
    1011             : 
    1012             :                 found_chap = GF_TRUE;
    1013           5 :                 if (strlen(szTitle)) {
    1014           5 :                         e = gf_isom_add_chapter(import->dest, 0, ts, szTitle);
    1015             :                 } else {
    1016           0 :                         e = gf_isom_add_chapter(import->dest, 0, ts, NULL);
    1017             :                 }
    1018           5 :                 if (e) goto err_exit;
    1019             :         }
    1020             : 
    1021           2 : err_exit:
    1022           2 :         gf_fclose(f);
    1023           2 :         if (!found_chap) return GF_NOT_FOUND;
    1024           2 :         return e;
    1025             : }
    1026             : 
    1027             : GF_EXPORT
    1028           2 : GF_Err gf_media_import_chapters(GF_ISOFile *file, char *chap_file, GF_Fraction import_fps, Bool use_qt)
    1029             : {
    1030             :         GF_Err e;
    1031             :         u32 i;
    1032             :         GF_MediaImporter import;
    1033             :         //remove all chapter info
    1034           2 :         gf_isom_remove_chapter(file, 0, 0);
    1035             : 
    1036           2 : restart_check:
    1037             :         //remove all chapter tracks
    1038           6 :         for (i=0; i<gf_isom_get_track_count(file); i++) {
    1039           2 :                 if (gf_isom_get_reference_count(file, i+1, GF_ISOM_REF_CHAP)) {
    1040           0 :                         u32 chap_track=0;
    1041           0 :                         gf_isom_get_reference(file, i+1, GF_ISOM_REF_CHAP, 1, &chap_track);
    1042           0 :                         if (chap_track) {
    1043           0 :                                 gf_isom_remove_track(file, chap_track);
    1044           0 :                                 goto restart_check;
    1045             :                         }
    1046             :                 }
    1047             :         }
    1048             : 
    1049             :         memset(&import, 0, sizeof(GF_MediaImporter));
    1050           2 :         import.dest = file;
    1051           2 :         import.in_name = chap_file;
    1052           2 :         import.video_fps = import_fps;
    1053           2 :         import.streamFormat = "CHAP";
    1054           2 :         e = gf_media_import(&import);
    1055           2 :         if (e) return e;
    1056             : 
    1057           2 :         if (!import.final_trackID) return GF_OK;
    1058           0 :         if (use_qt) {
    1059           0 :                 u32 chap_track = gf_isom_get_track_by_id(file, import.final_trackID);
    1060           0 :                 u32 nb_sdesc = gf_isom_get_sample_description_count(file, chap_track);
    1061           0 :                 for (i=0; i<nb_sdesc; i++) {
    1062           0 :                         gf_isom_set_media_subtype(file, chap_track, i+1, GF_ISOM_SUBTYPE_TEXT);
    1063             :                 }
    1064             :         }
    1065             :         //imported chapter is a track, set reference
    1066           0 :         for (i=0; i<gf_isom_get_track_count(file); i++) {
    1067           0 :                 u32 mtype = gf_isom_get_media_type(file, i+1);
    1068           0 :                 switch (mtype) {
    1069           0 :                 case GF_ISOM_MEDIA_VISUAL:
    1070             :                 case GF_ISOM_MEDIA_AUXV:
    1071             :                 case GF_ISOM_MEDIA_PICT:
    1072             :                 case GF_ISOM_MEDIA_AUDIO:
    1073           0 :                         gf_isom_set_track_reference(file, i+1, GF_ISOM_REF_CHAP, import.final_trackID);
    1074           0 :                         break;
    1075             :                 }
    1076             :         }
    1077             :         return GF_OK;
    1078             : }
    1079             : 
    1080           0 : static void on_import_setup_failure(GF_Filter *f, void *on_setup_error_udta, GF_Err e)
    1081             : {
    1082             :         GF_MediaImporter *importer = (GF_MediaImporter *)on_setup_error_udta;
    1083           0 :         if (importer)
    1084           0 :                 importer->last_error = e;
    1085           0 : }
    1086             : 
    1087             : GF_EXPORT
    1088         717 : GF_Err gf_media_import(GF_MediaImporter *importer)
    1089             : {
    1090             :         GF_Err e;
    1091             :         u32 i, count;
    1092             :         GF_FilterSession *fsess=NULL;
    1093         717 :         char *args = NULL;
    1094             :         char szSubArg[1024];
    1095             :         char szFilterID[20];
    1096             :         Bool source_id_set = GF_FALSE;
    1097             :         Bool source_is_isom = GF_FALSE;
    1098             :         GF_Filter *isobmff_mux, *source;
    1099             :         GF_Filter *filter_orig;
    1100             :         char *ext;
    1101             :         char *fmt = NULL;
    1102             : 
    1103         717 :         if (!importer || (!importer->dest && (importer->flags!=GF_IMPORT_PROBE_ONLY)) || (!importer->in_name && !importer->orig) ) return GF_BAD_PARAM;
    1104             : 
    1105         717 :         if (importer->orig) return gf_import_isomedia(importer);
    1106             : 
    1107         717 :         if (importer->force_ext) {
    1108             :                 ext = importer->force_ext;
    1109             :         } else {
    1110         717 :                 ext = gf_file_ext_start(importer->in_name);
    1111         717 :                 if (!ext) ext = "";
    1112             :         }
    1113             : 
    1114         717 :         if (importer->streamFormat) fmt = importer->streamFormat;
    1115             : 
    1116             :         /*if isobmf and probing or no filter, direct copy*/
    1117         717 :         if (gf_isom_probe_file(importer->in_name)) {
    1118             :                 u64 magic = 1;
    1119             :                 magic <<= 32;
    1120          45 :                 magic |= (importer->source_magic & 0xFFFFFFFFUL);
    1121          45 :                 importer->source_magic = magic;
    1122             :                 source_is_isom = GF_TRUE;
    1123          45 :                 if ((!importer->filter_chain && !importer->filter_dst_opts && !importer->run_in_session && !importer->start_time)
    1124           0 :                         || (importer->flags & GF_IMPORT_PROBE_ONLY)
    1125             :                 ) {
    1126          45 :                         importer->orig = gf_isom_open(importer->in_name, GF_ISOM_OPEN_READ, NULL);
    1127          45 :                         if (importer->orig) {
    1128          42 :                                 e = gf_import_isomedia(importer);
    1129          42 :                                 gf_isom_delete(importer->orig);
    1130          42 :                                 importer->orig = NULL;
    1131          42 :                                 return e;
    1132             :                         }
    1133             :                 }
    1134             :         }
    1135             : 
    1136             :         /*SC3DMC*/
    1137         675 :         if (!strnicmp(ext, ".s3d", 4) || (fmt && !stricmp(fmt, "SC3DMC")) )
    1138           1 :                 return gf_import_afx_sc3dmc(importer, GF_TRUE);
    1139             :         /* chapter */
    1140         674 :         else if (!strnicmp(ext, ".txt", 4) || !strnicmp(ext, ".chap", 5) || (fmt && !stricmp(fmt, "CHAP")) ) {
    1141           2 :                 e =  gf_media_import_chapters_file(importer);
    1142           2 :                 if (!strnicmp(ext, ".txt", 4) && (e==GF_NOT_FOUND)) {
    1143             : 
    1144             :                 } else {
    1145             :                         return e;
    1146             :                 }
    1147             :         }
    1148             : 
    1149         672 :         e = GF_OK;
    1150         672 :         importer->last_error = GF_OK;
    1151             : 
    1152         672 :         if (importer->flags & GF_IMPORT_PROBE_ONLY) {
    1153             :                 GF_Filter *prober, *src_filter;
    1154             : 
    1155          63 :                 fsess = gf_fs_new_defaults(0);
    1156          63 :                 if (!fsess) {
    1157           0 :                         return gf_import_message(importer, GF_BAD_PARAM, "[Importer] Cannot load filter session for import");
    1158             :                 }
    1159          63 :                 prober = gf_fs_load_filter(fsess, "probe", &e);
    1160          63 :                 src_filter = gf_fs_load_source(fsess, importer->in_name, "index=0", NULL, &e);
    1161          63 :                 if (e) {
    1162           0 :                         gf_fs_run(fsess);
    1163           0 :                         gf_fs_del(fsess);
    1164           0 :                         return gf_import_message(importer, e, "[Importer] Cannot load filter for input file \"%s\"", importer->in_name);
    1165             :                 }
    1166             : #ifdef GPAC_ENABLE_COVERAGE
    1167          63 :                 if (gf_sys_is_cov_mode()) {
    1168             :                         on_import_setup_failure(NULL, NULL, GF_OK);
    1169             :                 }
    1170             : #endif
    1171             : 
    1172          63 :                 gf_filter_set_setup_failure_callback(prober, src_filter, on_import_setup_failure, importer);
    1173          63 :                 gf_fs_run(fsess);
    1174             : 
    1175          63 :                 if (importer->last_error) {
    1176           0 :                         gf_fs_del(fsess);
    1177           0 :                         return gf_import_message(importer, importer->last_error, "[Importer] Error probing %s", importer->in_name);
    1178             :                 }
    1179             : 
    1180          63 :                 importer->nb_tracks = 0;
    1181          63 :                 count = gf_filter_get_ipid_count(prober);
    1182         130 :                 for (i=0; i<count; i++) {
    1183             :                         const GF_PropertyValue *p;
    1184          67 :                         struct __track_import_info *tki = &importer->tk_info[importer->nb_tracks];
    1185          67 :                         GF_FilterPid *pid = gf_filter_get_ipid(prober, i);
    1186             : 
    1187          67 :                         p = gf_filter_pid_get_property(pid, GF_PROP_PID_STREAM_TYPE);
    1188          67 :                         tki->stream_type = p ? p->value.uint : GF_STREAM_UNKNOWN;
    1189          67 :                         p = gf_filter_pid_get_property(pid, GF_PROP_PID_CODECID);
    1190          67 :                         tki->codecid = p ? p->value.uint : GF_CODECID_NONE;
    1191          67 :                         p = gf_filter_pid_get_property(pid, GF_PROP_PID_LANGUAGE);
    1192          67 :                         if (p && p->value.string) tki->lang = GF_4CC(p->value.string[0], p->value.string[1], p->value.string[2], ' ');
    1193          67 :                         p = gf_filter_pid_get_property(pid, GF_PROP_PID_ID);
    1194          67 :                         tki->track_num = p ? p->value.uint : 1;
    1195          67 :                         p = gf_filter_pid_get_property(pid, GF_PROP_PID_ESID);
    1196          67 :                         if (p) tki->mpeg4_es_id = p->value.uint;
    1197          67 :                         p = gf_filter_pid_get_property(pid, GF_PROP_PID_SERVICE_ID);
    1198          67 :                         if (p) tki->prog_num = p->value.uint;
    1199             : 
    1200          67 :                         p = gf_filter_pid_get_property(pid, GF_PROP_PID_DURATION);
    1201          67 :                         if (p) {
    1202          19 :                                 Double d = (Double) p->value.lfrac.num;
    1203          19 :                                 d*=1000;
    1204          19 :                                 if (p->value.lfrac.den) d /= p->value.lfrac.den;
    1205          19 :                                 if (d > importer->probe_duration) importer->probe_duration = (u64) d;
    1206             :                         }
    1207             : 
    1208          67 :                         p = gf_filter_pid_get_property(pid, GF_PROP_PID_WIDTH);
    1209          67 :                         if (p) {
    1210          32 :                                 tki->video_info.width = p->value.uint;
    1211          32 :                                 p = gf_filter_pid_get_property(pid, GF_PROP_PID_HEIGHT);
    1212          32 :                                 if (p) tki->video_info.height = p->value.uint;
    1213          32 :                                 p = gf_filter_pid_get_property(pid, GF_PROP_PID_FPS);
    1214          32 :                                 if (p) {
    1215          28 :                                         tki->video_info.FPS = p->value.frac.num;
    1216          28 :                                         if (p->value.frac.den) tki->video_info.FPS /= p->value.frac.den;
    1217             :                                 }
    1218          32 :                                 p = gf_filter_pid_get_property(pid, GF_PROP_PID_SAR);
    1219          32 :                                 if (p) tki->video_info.par = (p->value.frac.num << 16) | p->value.frac.den;
    1220             :                         }
    1221          67 :                         p = gf_filter_pid_get_property(pid, GF_PROP_PID_SAMPLE_RATE);
    1222          67 :                         if (p) {
    1223          28 :                                 tki->audio_info.sample_rate = p->value.uint;
    1224          28 :                                 p = gf_filter_pid_get_property(pid, GF_PROP_PID_NUM_CHANNELS);
    1225          28 :                                 if (p) tki->audio_info.nb_channels = p->value.uint;
    1226          28 :                                 p = gf_filter_pid_get_property(pid, GF_PROP_PID_SAMPLES_PER_FRAME);
    1227          28 :                                 if (p) tki->audio_info.samples_per_frame = p->value.uint;
    1228             :                         }
    1229             : /*                      p = gf_filter_pid_get_property(pid, GF_PROP_PID_CAN_DATAREF);
    1230             :                         if (p) importer->flags |= GF_IMPORT_USE_DATAREF;
    1231             : */
    1232          67 :                         p = gf_filter_pid_get_property(pid, GF_PROP_PID_SUBTYPE);
    1233          67 :                         if (p) tki->media_subtype = p->value.uint;
    1234             : 
    1235          67 :                         importer->nb_tracks++;
    1236             :                 }
    1237          63 :                 gf_fs_del(fsess);
    1238          63 :                 return GF_OK;
    1239             :         }
    1240             : 
    1241         609 :         if (importer->run_in_session) {
    1242             :                 fsess = importer->run_in_session;
    1243             :         } else {
    1244         607 :                 fsess = gf_fs_new_defaults(fmt ? GF_FS_FLAG_NO_PROBE : 0);
    1245         607 :                 if (!fsess) {
    1246           0 :                         return gf_import_message(importer, GF_BAD_PARAM, "[Importer] Cannot load filter session for import");
    1247             :                 }
    1248             :         }
    1249             : 
    1250             :         filter_orig=NULL;
    1251             : 
    1252         609 :         if (importer->run_in_session) {
    1253           2 :                 sprintf(szFilterID, "%d", (u32) ( (importer->source_magic & 0xFFFFFFFFUL) ) );
    1254             :         } else {
    1255             :                 strcpy(szFilterID, "1");
    1256             :         }
    1257             : 
    1258         609 :         if (!importer->run_in_session) {
    1259             :                 //mux args
    1260         607 :                 e = gf_dynstrcat(&args, "mp4mx:importer", ":");
    1261         607 :                 sprintf(szSubArg, "file=%p", importer->dest);
    1262         607 :                 e |= gf_dynstrcat(&args, szSubArg, ":");
    1263             :         }
    1264             : 
    1265         609 :         if (importer->trackID) {
    1266             :                 sprintf(szSubArg, "SID=%s#PID=%d", szFilterID, importer->trackID);
    1267           0 :                 e |= gf_dynstrcat(&args, szSubArg, ":");
    1268             :         }
    1269         609 :         if (importer->filter_dst_opts)
    1270           1 :                 e |= gf_dynstrcat(&args, importer->filter_dst_opts, ":gfloc:");
    1271             : 
    1272         609 :         if (importer->flags & GF_IMPORT_FORCE_MPEG4)
    1273          49 :                 e |= gf_dynstrcat(&args, "m4sys", ":");
    1274         609 :         if (importer->flags & GF_IMPORT_USE_DATAREF)
    1275           0 :                 e |= gf_dynstrcat(&args, "dref", ":");
    1276         609 :         if (importer->flags & GF_IMPORT_NO_EDIT_LIST)
    1277           0 :                 e |= gf_dynstrcat(&args, "noedit", ":");
    1278         609 :         if (importer->flags & GF_IMPORT_FORCE_PACKED)
    1279           0 :                 e |= gf_dynstrcat(&args, "pack_nal", ":");
    1280         609 :         if (importer->xps_inband==1)
    1281           8 :                 e |= gf_dynstrcat(&args, "xps_inband=all", ":");
    1282         601 :         else if (importer->xps_inband==2)
    1283           0 :                 e |= gf_dynstrcat(&args, "xps_inband=both", ":");
    1284         609 :         if (importer->esd && importer->esd->ESID) {
    1285          47 :                 sprintf(szSubArg, "trackid=%d", importer->esd->ESID);
    1286          47 :                 e |= gf_dynstrcat(&args, szSubArg, ":");
    1287             :         }
    1288         609 :         if (importer->flags & GF_IMPORT_FORCE_SYNC)
    1289           1 :                 e |= gf_dynstrcat(&args, ":forcesync", NULL);
    1290             : 
    1291         609 :         if (importer->duration.den) {
    1292          91 :                 sprintf(szSubArg, "idur=%d/%d", importer->duration.num, importer->duration.den);
    1293          91 :                 e |= gf_dynstrcat(&args, szSubArg, ":");
    1294             :         }
    1295         609 :         if (importer->frames_per_sample) {
    1296             :                 sprintf(szSubArg, "pack3gp=%d", importer->frames_per_sample);
    1297           0 :                 e |= gf_dynstrcat(&args, szSubArg, ":");
    1298             :         }
    1299         609 :         if (importer->moov_timescale) {
    1300             :                 sprintf(szSubArg, "moovts=%d", importer->moov_timescale);
    1301           2 :                 e |= gf_dynstrcat(&args, szSubArg, ":");
    1302             :         }
    1303         609 :         if (importer->asemode==GF_IMPORT_AUDIO_SAMPLE_ENTRY_v0_2) { e |= gf_dynstrcat(&args, "ase=v0s", ":"); }
    1304         608 :         else if (importer->asemode==GF_IMPORT_AUDIO_SAMPLE_ENTRY_v1_MPEG) { e |= gf_dynstrcat(&args, "ase=v1", ":"); }
    1305         607 :         else if (importer->asemode==GF_IMPORT_AUDIO_SAMPLE_ENTRY_v1_QTFF) { e |= gf_dynstrcat(&args, "ase=v1qt", ":"); }
    1306             : 
    1307         609 :         if (source_is_isom && gf_isom_has_keep_utc_times(importer->dest) ) { e |= gf_dynstrcat(&args, "keep_utc", ":"); }
    1308             : 
    1309         609 :         if (importer->start_time) {
    1310             :                 sprintf(szSubArg, "start=%f", importer->start_time);
    1311           0 :                 e |= gf_dynstrcat(&args, szSubArg, ":");
    1312             :         }
    1313         609 :         if (e) {
    1314           0 :                 gf_fs_del(fsess);
    1315           0 :                 gf_free(args);
    1316           0 :                 return gf_import_message(importer, e, "[Importer] Cannot load ISOBMFF muxer arguments");
    1317             :         }
    1318             : 
    1319         609 :         if (!importer->run_in_session) {
    1320         607 :                 isobmff_mux = gf_fs_load_filter(fsess, args, &e);
    1321         607 :                 gf_free(args);
    1322         607 :                 args = NULL;
    1323             : 
    1324         607 :                 if (!isobmff_mux) {
    1325           0 :                         gf_fs_del(fsess);
    1326           0 :                         gf_free(args);
    1327           0 :                         return gf_import_message(importer, e, "[Importer] Cannot load ISOBMFF muxer");
    1328             :                 }
    1329             :         } else {
    1330           2 :                 importer->update_mux_args = args;
    1331           2 :                 args = NULL;
    1332             :                 isobmff_mux = NULL;
    1333             :         }
    1334             : 
    1335             :         //filter chain
    1336         609 :         if (importer->filter_chain) {
    1337             :                 GF_Filter *prev_filter=NULL;
    1338             :                 char *fargs = (char *) importer->filter_chain;
    1339           2 :                 char *sep1 = strstr(fargs, "@@");
    1340           2 :                 char *sep2 = strstr(fargs, "@");
    1341             :                 Bool old_syntax = GF_FALSE;
    1342           2 :                 if (sep1 && sep2 && (sep1==sep2))
    1343             :                         old_syntax = GF_TRUE;
    1344             : 
    1345           2 :                 while (fargs) {
    1346             :                         GF_Filter *f;
    1347             :                         char *sep;
    1348             :                         Bool end_of_sub_chain = GF_FALSE;
    1349           2 :                         if (old_syntax) {
    1350           0 :                                 sep = strstr(fargs, "@@");
    1351             :                         } else {
    1352           2 :                                 sep = strstr(fargs, "@");
    1353           2 :                                 if (sep && (sep[1] == '@'))
    1354             :                                         end_of_sub_chain = GF_TRUE;
    1355             :                         }
    1356           2 :                         if (sep) sep[0] = 0;
    1357           2 :                         f = gf_fs_load_filter(fsess, fargs, &e);
    1358           2 :                         if (!f) {
    1359           0 :                                 if (!importer->run_in_session)
    1360           0 :                                         gf_fs_del(fsess);
    1361           0 :                                 return gf_import_message(importer, e, "[Importer] Cannot load filter %s", fargs);
    1362             :                         }
    1363           2 :                         if (prev_filter) {
    1364           0 :                                 gf_filter_set_source(f, prev_filter, NULL);
    1365             :                         }
    1366             :                         prev_filter = f;
    1367           2 :                         if (!filter_orig) filter_orig = f;
    1368             : 
    1369           2 :                         if (!sep) end_of_sub_chain = GF_TRUE;
    1370             :                         //we cannot directly set the source id in case we run in an existing session
    1371           2 :                         if (end_of_sub_chain && prev_filter) {
    1372             :                                 const char *prev_id;
    1373           2 :                                 if (importer->trackID) {
    1374           0 :                                         if (gf_filter_get_id(prev_filter)) {
    1375           0 :                                                 if (!importer->run_in_session)
    1376           0 :                                                         gf_fs_del(fsess);
    1377           0 :                                                 return gf_import_message(importer, GF_FILTER_NOT_FOUND, "[Importer] last filter in chain cannot use filter ID (%s)", fargs);
    1378             :                                         }
    1379           0 :                                         gf_filter_assign_id(prev_filter, szFilterID);
    1380             :                                         source_id_set=GF_TRUE;
    1381             :                                 }
    1382           2 :                                 prev_id = gf_filter_get_id(prev_filter);
    1383           2 :                                 if (!prev_id) {
    1384           2 :                                         gf_filter_assign_id(prev_filter, NULL);
    1385           2 :                                         prev_id = gf_filter_get_id(prev_filter);
    1386             :                                 }
    1387           2 :                                 if (importer->run_in_session) {
    1388           0 :                                         gf_dynstrcat(&importer->update_mux_args, ":SID=", NULL);
    1389           0 :                                         gf_dynstrcat(&importer->update_mux_args, prev_id, NULL);
    1390             :                                 } else {
    1391             :                                         assert(isobmff_mux);
    1392           2 :                                         gf_filter_set_source(isobmff_mux, prev_filter, NULL);
    1393             :                                 }
    1394             :                                 prev_filter = NULL;
    1395             :                         }
    1396             : 
    1397           2 :                         if (!sep) break;
    1398           0 :                         sep[0] = '@';
    1399             : 
    1400           0 :                         if (old_syntax || end_of_sub_chain) {
    1401           0 :                                 fargs = sep+2;
    1402             :                         } else {
    1403           0 :                                 fargs = sep+1;
    1404             :                         }
    1405             :                 }
    1406             :         }
    1407             : 
    1408             :         //source args
    1409         609 :         e = gf_dynstrcat(&args, "importer:index=0", ":");
    1410         609 :         if (importer->trackID && !source_id_set) {
    1411             :                 sprintf(szSubArg, "FID=%s", szFilterID);
    1412           0 :                 e |= gf_dynstrcat(&args, szSubArg, ":");
    1413             :         }
    1414         609 :         if (fmt) {
    1415             :                 sprintf(szSubArg, "ext=%s", fmt);
    1416           5 :                 e |= gf_dynstrcat(&args, szSubArg, ":");
    1417             :         }
    1418         609 :         if (importer->filter_src_opts) e |= gf_dynstrcat(&args, importer->filter_src_opts, ":");
    1419             : 
    1420         609 :         if (importer->flags & GF_IMPORT_SBR_IMPLICIT) e |= gf_dynstrcat(&args, "sbr=imp", ":");
    1421         606 :         else if (importer->flags & GF_IMPORT_SBR_EXPLICIT) e |= gf_dynstrcat(&args, "sbr=exp", ":");
    1422         609 :         if (importer->flags & GF_IMPORT_PS_IMPLICIT) e |= gf_dynstrcat(&args, "ps=imp", ":");
    1423         606 :         else if (importer->flags & GF_IMPORT_PS_EXPLICIT) e |= gf_dynstrcat(&args, "ps=exp", ":");
    1424         609 :         if (importer->flags & GF_IMPORT_OVSBR) e |= gf_dynstrcat(&args, "ovsbr", ":");
    1425             :         //avoids message at end of import
    1426         609 :         if (importer->flags & GF_IMPORT_FORCE_PACKED) e |= gf_dynstrcat(&args, "nal_length=0", ":");
    1427         609 :         if (importer->flags & GF_IMPORT_SET_SUBSAMPLES) e |= gf_dynstrcat(&args, "subsamples", ":");
    1428         609 :         if (importer->flags & GF_IMPORT_NO_SEI) e |= gf_dynstrcat(&args, "nosei", ":");
    1429         609 :         if (importer->flags & GF_IMPORT_SVC_NONE) e |= gf_dynstrcat(&args, "nosvc", ":");
    1430         609 :         if (importer->flags & GF_IMPORT_SAMPLE_DEPS) e |= gf_dynstrcat(&args, "deps", ":");
    1431         609 :         if (importer->flags & GF_IMPORT_FORCE_MPEG4) e |= gf_dynstrcat(&args, "mpeg4", ":");
    1432         609 :         if (importer->keep_audelim) e |= gf_dynstrcat(&args, "audelim", ":");
    1433         609 :         if (importer->video_fps.num && importer->video_fps.den) {
    1434             :                 sprintf(szSubArg, "fps=%d/%d", importer->video_fps.num, importer->video_fps.den);
    1435           0 :                 e |= gf_dynstrcat(&args, szSubArg, ":");
    1436             :         }
    1437         609 :         if (importer->is_alpha) e |= gf_dynstrcat(&args, "#Alpha", ":");
    1438             : 
    1439         609 :         if (importer->streamFormat && !strcmp(importer->streamFormat, "VTT")) e |= gf_dynstrcat(&args, "webvtt", ":");
    1440             : 
    1441         609 :         if (importer->source_magic) {
    1442             :                 sprintf(szSubArg, "#SrcMagic="LLU, importer->source_magic);
    1443         555 :                 e |= gf_dynstrcat(&args, szSubArg, ":");
    1444             :         }
    1445         609 :         if (importer->track_index) {
    1446             :                 sprintf(szSubArg, "#MuxIndex=%d", importer->track_index);
    1447         455 :                 e |= gf_dynstrcat(&args, szSubArg, ":");
    1448             :         }
    1449             : 
    1450         609 :         if (e) {
    1451           0 :                 if (!importer->run_in_session)
    1452           0 :                         gf_fs_del(fsess);
    1453           0 :                 gf_free(args);
    1454           0 :                 return gf_import_message(importer, e, "[Importer] Cannot load arguments for input %s", importer->in_name);
    1455             :         }
    1456             : 
    1457         609 :         source = gf_fs_load_source(fsess, importer->in_name, args, NULL, &e);
    1458         609 :         gf_free(args);
    1459         609 :         args = NULL;
    1460             : 
    1461         609 :         if (e) {
    1462           0 :                 if (!importer->run_in_session)
    1463           0 :                         gf_fs_del(fsess);
    1464           0 :                 return gf_import_message(importer, e, "[Importer] Cannot load filter for input file \"%s\"", importer->in_name);
    1465             :         }
    1466             : 
    1467         609 :         if (filter_orig)
    1468           2 :                 gf_filter_set_source(filter_orig, source, NULL);
    1469             : 
    1470             :         //source is setup, we run in an external session, nothing left to do
    1471         609 :         if (importer->run_in_session)
    1472             :                 return GF_OK;
    1473             : 
    1474         607 :         gf_fs_run(fsess);
    1475             : 
    1476         607 :         if (!importer->last_error) importer->last_error = gf_fs_get_last_connect_error(fsess);
    1477         607 :         if (!importer->last_error) importer->last_error = gf_fs_get_last_process_error(fsess);
    1478             : 
    1479         607 :         if (importer->last_error) {
    1480           3 :                 gf_fs_print_non_connected(fsess);
    1481           3 :                 if (importer->print_stats_graph & 1) gf_fs_print_stats(fsess);
    1482           3 :                 if (importer->print_stats_graph & 2) gf_fs_print_connections(fsess);
    1483           3 :                 if (!importer->run_in_session)
    1484           3 :                         gf_fs_del(fsess);
    1485           3 :                 return gf_import_message(importer, importer->last_error, "[Importer] Error importing %s", importer->in_name);
    1486             :         }
    1487             : 
    1488         604 :         importer->final_trackID = gf_isom_get_last_created_track_id(importer->dest);
    1489             : 
    1490         604 :         if (importer->esd && importer->final_trackID) {
    1491          49 :                 u32 tk_num = gf_isom_get_track_by_id(importer->dest, importer->final_trackID);
    1492          49 :                 GF_ESD *esd = gf_isom_get_esd(importer->dest, tk_num, 1);
    1493          49 :                 if (esd && !importer->esd->decoderConfig) {
    1494          30 :                         importer->esd->decoderConfig = esd->decoderConfig;
    1495          30 :                         esd->decoderConfig = NULL;
    1496             :                 }
    1497          49 :                 if (esd && !importer->esd->slConfig) {
    1498          30 :                         importer->esd->slConfig = esd->slConfig;
    1499          30 :                         esd->slConfig = NULL;
    1500             :                 }
    1501          49 :                 if (esd) {
    1502          48 :                         gf_odf_desc_del((GF_Descriptor *) esd);
    1503             :                 }
    1504             : 
    1505          49 :                 if (!importer->esd->ESID) {
    1506           2 :                         importer->esd->ESID = importer->final_trackID;
    1507             :                 }
    1508             :         }
    1509             : 
    1510         604 :         if (!e) gf_fs_print_unused_args(fsess, "index,fps");
    1511         604 :         gf_fs_print_non_connected(fsess);
    1512         604 :         if (importer->print_stats_graph & 1) gf_fs_print_stats(fsess);
    1513         604 :         if (importer->print_stats_graph & 2) gf_fs_print_connections(fsess);
    1514         604 :         gf_fs_del(fsess);
    1515         604 :         if (!importer->final_trackID) {
    1516           0 :                 return gf_import_message(importer, GF_NOT_SUPPORTED, "[Importer] No valid track to import in input file \"%s\"", importer->in_name);
    1517             :         }
    1518             :         return GF_OK;
    1519             : }
    1520             : 
    1521             : #endif /*GPAC_DISABLE_MEDIA_IMPORT*/

Generated by: LCOV version 1.13