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*/
|