Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Jean Le Feuvre
5 : * Copyright (c) Telecom ParisTech 2000-2021
6 : * All rights reserved
7 : *
8 : * This file is part of GPAC / ISOBMFF reader filter
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 :
27 : #include "isoffin.h"
28 :
29 : #ifndef GPAC_DISABLE_ISOM
30 : #include <gpac/network.h>
31 : #include <gpac/avparse.h>
32 :
33 :
34 2676 : void isor_reset_reader(ISOMChannel *ch)
35 : {
36 2676 : ch->last_state = GF_OK;
37 : isor_reader_release_sample(ch);
38 :
39 2676 : if (ch->static_sample) {
40 1190 : ch->static_sample->dataLength = ch->static_sample->alloc_size;
41 1190 : gf_isom_sample_del(&ch->static_sample);
42 : }
43 2676 : ch->sample = NULL;
44 2676 : ch->sample_num = 0;
45 2676 : ch->speed = 1.0;
46 2676 : ch->start = ch->end = 0;
47 2676 : ch->to_init = 1;
48 2676 : ch->playing = GF_FALSE;
49 2676 : if (ch->sai_buffer) gf_free(ch->sai_buffer);
50 2676 : ch->sai_buffer = NULL;
51 2676 : ch->sai_alloc_size = 0;
52 2676 : ch->dts = ch->cts = 0;
53 2676 : ch->seek_flag = 0;
54 2676 : }
55 :
56 6379 : void isor_check_producer_ref_time(ISOMReader *read)
57 : {
58 : GF_ISOTrackID trackID;
59 : u64 ntp;
60 : u64 timestamp;
61 :
62 6379 : if (gf_sys_is_test_mode()) {
63 6110 : return;
64 : }
65 :
66 269 : if (gf_isom_get_last_producer_time_box(read->mov, &trackID, &ntp, ×tamp, GF_TRUE)) {
67 : #if !defined(_WIN32_WCE) && !defined(GPAC_DISABLE_LOG)
68 :
69 0 : if (gf_log_tool_level_on(GF_LOG_DASH, GF_LOG_DEBUG)) {
70 : time_t secs;
71 : struct tm t;
72 :
73 0 : s32 diff = gf_net_get_ntp_diff_ms(ntp);
74 :
75 0 : secs = (ntp>>32) - GF_NTP_SEC_1900_TO_1970;
76 0 : t = *gf_gmtime(&secs);
77 :
78 0 : GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[IsoMedia] TrackID %d: Timestamp "LLU" matches sender NTP time %d-%02d-%02dT%02d:%02d:%02dZ - NTP clock diff (local - remote): %d ms\n", trackID, timestamp, 1900+t.tm_year, t.tm_mon+1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, diff));
79 : }
80 : #endif
81 0 : read->last_sender_ntp = ntp;
82 0 : read->cts_for_last_sender_ntp = timestamp;
83 0 : read->ntp_at_last_sender_ntp = gf_net_get_ntp_ts();
84 : }
85 : }
86 :
87 :
88 1185 : static void init_reader(ISOMChannel *ch)
89 : {
90 1185 : u32 sample_desc_index=0;
91 :
92 1185 : ch->au_seq_num = 1;
93 :
94 : assert(ch->sample==NULL);
95 1185 : if (!ch->static_sample) {
96 1144 : ch->static_sample = gf_isom_sample_new();
97 : }
98 :
99 1185 : if (ch->streamType==GF_STREAM_OCR) {
100 : assert(!ch->sample);
101 0 : ch->sample = gf_isom_sample_new();
102 0 : ch->sample->IsRAP = RAP;
103 0 : ch->sample->DTS = ch->start;
104 0 : ch->last_state=GF_OK;
105 1185 : } else if (ch->sample_num) {
106 10 : ch->sample = gf_isom_get_sample_ex(ch->owner->mov, ch->track, ch->sample_num, &sample_desc_index, ch->static_sample, &ch->sample_data_offset);
107 10 : ch->disable_seek = GF_TRUE;
108 10 : ch->au_seq_num = ch->sample_num;
109 : } else {
110 : //if seek is disabled, get the next closest sample for this time; otherwise, get the previous RAP sample for this time
111 1175 : u32 mode = ch->disable_seek ? GF_ISOM_SEARCH_BACKWARD : GF_ISOM_SEARCH_SYNC_BACKWARD;
112 :
113 : /*take care of seeking out of the track range*/
114 1175 : if (!ch->owner->frag_type && (ch->duration<=ch->start)) {
115 10 : ch->last_state = gf_isom_get_sample_for_movie_time(ch->owner->mov, ch->track, ch->duration-1, &sample_desc_index, mode, &ch->static_sample, &ch->sample_num, &ch->sample_data_offset);
116 1165 : } else if (ch->start || ch->has_edit_list) {
117 50 : ch->last_state = gf_isom_get_sample_for_movie_time(ch->owner->mov, ch->track, ch->start, &sample_desc_index, mode, &ch->static_sample, &ch->sample_num, &ch->sample_data_offset);
118 : } else {
119 1115 : ch->sample_num = 1;
120 1115 : if (ch->owner->nodata) {
121 0 : ch->sample = gf_isom_get_sample_info_ex(ch->owner->mov, ch->track, ch->sample_num, &sample_desc_index, &ch->sample_data_offset, ch->static_sample);
122 : } else {
123 1115 : ch->sample = gf_isom_get_sample_ex(ch->owner->mov, ch->track, ch->sample_num, &sample_desc_index, ch->static_sample, &ch->sample_data_offset);
124 : }
125 1115 : if (!ch->sample) ch->last_state = GF_EOS;
126 : }
127 1175 : if (ch->last_state) {
128 287 : ch->sample = NULL;
129 287 : ch->last_state = GF_OK;
130 : } else {
131 888 : ch->sample = ch->static_sample;
132 : }
133 :
134 1175 : if (ch->has_rap && ch->has_edit_list) {
135 0 : ch->edit_sync_frame = ch->sample_num;
136 : }
137 :
138 1175 : if (ch->sample && !ch->sample->data && ch->owner->frag_type && !ch->has_edit_list) {
139 0 : ch->sample = NULL;
140 0 : ch->sample_num = 1;
141 0 : ch->sample = gf_isom_get_sample_ex(ch->owner->mov, ch->track, ch->sample_num, &sample_desc_index, ch->static_sample, &ch->sample_data_offset);
142 : }
143 : }
144 :
145 :
146 : /*no sample means we're not in the track range - stop*/
147 1185 : if (!ch->sample) {
148 : /*incomplete file - check if we're still downloading or not*/
149 287 : if (gf_isom_get_missing_bytes(ch->owner->mov, ch->track)) {
150 28 : if (!ch->owner->input_loaded) {
151 20 : ch->last_state = GF_OK;
152 307 : return;
153 : }
154 8 : ch->last_state = GF_ISOM_INCOMPLETE_FILE;
155 259 : } else if (ch->sample_num) {
156 246 : ch->last_state = (ch->owner->frag_type==1) ? GF_OK : GF_EOS;
157 246 : ch->to_init = 0;
158 : }
159 : return;
160 : }
161 :
162 898 : ch->sample_time = ch->sample->DTS;
163 :
164 898 : ch->to_init = GF_FALSE;
165 :
166 898 : ch->seek_flag = 0;
167 898 : if (ch->disable_seek) {
168 20 : ch->dts = ch->sample->DTS;
169 20 : ch->cts = ch->sample->DTS + ch->sample->CTS_Offset;
170 20 : ch->start = 0;
171 : } else {
172 : s64 cts;
173 878 : ch->dts = ch->start;
174 878 : ch->cts = ch->start;
175 :
176 878 : cts = ch->sample->DTS + ch->sample->CTS_Offset;
177 878 : if (ch->ts_offset<0)
178 204 : cts += ch->ts_offset;
179 :
180 : //TODO - we need to notify scene decoder how many secs elapsed between RAP and seek point
181 878 : if (ch->cts != cts) {
182 21 : ch->seek_flag = 1;
183 : }
184 : }
185 898 : if (!sample_desc_index) sample_desc_index = 1;
186 898 : ch->last_sample_desc_index = sample_desc_index;
187 898 : ch->owner->no_order_check = ch->speed < 0 ? GF_TRUE : GF_FALSE;
188 : }
189 :
190 :
191 37940 : static void isor_update_cenc_info(ISOMChannel *ch, Bool for_item)
192 : {
193 : GF_Err e;
194 : Bool Is_Encrypted;
195 : u32 out_size;
196 : u8 crypt_byte_block, skip_byte_block;
197 : u8 piff_info[20];
198 37940 : u8 *key_info = NULL;
199 37940 : u32 key_info_size = 0;
200 : u8 item_mkey = 0;
201 :
202 : //this will be skipped anyways, don't fectch ...
203 37940 : if (ch->owner->stsd && (ch->last_sample_desc_index != ch->owner->stsd) && ch->sample) {
204 0 : return;
205 : }
206 :
207 :
208 37940 : out_size = ch->sai_alloc_size;
209 37940 : if (for_item) {
210 13 : u32 aux_info_param=0;
211 13 : e = gf_isom_extract_meta_item_get_cenc_info(ch->owner->mov, GF_TRUE, 0, ch->item_id, &Is_Encrypted, &skip_byte_block, &crypt_byte_block, (const u8 **) &key_info, &key_info_size, &aux_info_param, &ch->sai_buffer, &out_size, &ch->sai_alloc_size);
212 :
213 : /*The ienc property is always exposed as a multiple key info in GPAC
214 : However the type of SAI may be single-key (aux_info_param==0) or multiple-key (aux_info_param==1) for the same ienc used
215 : We therefore temporary force the key info type to single key if v0 SAI CENC are used
216 : Note that this is thread safe as this filter is the only one using the opened file
217 : */
218 13 : if (aux_info_param==0) {
219 10 : item_mkey = key_info[0];
220 : }
221 : } else {
222 37927 : e = gf_isom_get_sample_cenc_info(ch->owner->mov, ch->track, ch->sample_num, &Is_Encrypted, &crypt_byte_block, &skip_byte_block, (const u8 **) &key_info, &key_info_size);
223 : }
224 37940 : if (!key_info) {
225 0 : piff_info[0] = 0;
226 0 : piff_info[1] = 0;
227 0 : piff_info[2] = 0;
228 0 : piff_info[3] = key_info_size;
229 : memset(piff_info + 4, 0, 16);
230 0 : key_info_size = 20;
231 0 : key_info = (u8 *) piff_info;
232 : }
233 :
234 :
235 37940 : if (!for_item && (e==GF_OK) && Is_Encrypted) {
236 33661 : e = gf_isom_cenc_get_sample_aux_info(ch->owner->mov, ch->track, ch->sample_num, ch->last_sample_desc_index, NULL, &ch->sai_buffer, &out_size);
237 : }
238 :
239 37940 : if (out_size > ch->sai_alloc_size) ch->sai_alloc_size = out_size;
240 37940 : ch->sai_buffer_size = out_size;
241 :
242 37940 : if (e) {
243 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[IsoMedia] Failed to fetch CENC auxiliary info for %s %d: %s\n", for_item ? "item" : "track", for_item ? ch->item_id : ch->track, gf_error_to_string(e) ));
244 : return;
245 : }
246 :
247 37940 : ch->pck_encrypted = Is_Encrypted;
248 :
249 : /*notify change of IV/KID only when packet is encrypted
250 : 1- these info are ignored when packet is not encrypted
251 : 2- this allows us to define the initial CENC state for multi-stsd cases*/
252 37940 : if (Is_Encrypted) {
253 : u32 ki_crc;
254 :
255 33674 : if ((ch->crypt_byte_block != crypt_byte_block) || (ch->skip_byte_block != skip_byte_block)) {
256 4 : ch->crypt_byte_block = crypt_byte_block;
257 4 : ch->skip_byte_block = skip_byte_block;
258 :
259 4 : gf_filter_pid_set_property(ch->pid, GF_PROP_PID_CENC_PATTERN, &PROP_FRAC_INT(ch->skip_byte_block, ch->crypt_byte_block) );
260 : }
261 33674 : if (item_mkey)
262 10 : key_info[0] = 0;
263 :
264 33674 : ki_crc = gf_crc_32(key_info, key_info_size);
265 33674 : if (ch->key_info_crc != ki_crc) {
266 343 : ch->key_info_crc = ki_crc;
267 343 : gf_filter_pid_set_property(ch->pid, GF_PROP_PID_CENC_KEY_INFO, &PROP_DATA((u8 *)key_info, key_info_size) );
268 : }
269 :
270 33674 : if (item_mkey)
271 10 : key_info[0] = item_mkey;
272 : }
273 : }
274 :
275 118 : void isor_reader_get_sample_from_item(ISOMChannel *ch)
276 : {
277 118 : if (ch->au_seq_num) {
278 72 : if (!ch->owner->itt || !isor_declare_item_properties(ch->owner, ch, 1+ch->au_seq_num)) {
279 46 : ch->last_state = GF_EOS;
280 46 : return;
281 : }
282 : }
283 72 : ch->sample_time = 0;
284 72 : ch->last_state = GF_OK;
285 72 : if (!ch->static_sample) {
286 46 : ch->static_sample = gf_isom_sample_new();
287 : }
288 :
289 72 : ch->sample = ch->static_sample;
290 72 : ch->sample->IsRAP = RAP;
291 72 : ch->au_duration = 1000;
292 72 : ch->dts = ch->cts = 1000 * ch->au_seq_num;
293 72 : gf_isom_extract_meta_item_mem(ch->owner->mov, GF_TRUE, 0, ch->item_id, &ch->sample->data, &ch->sample->dataLength, &ch->static_sample->alloc_size, NULL, GF_FALSE);
294 :
295 72 : if (ch->is_encrypted && ch->is_cenc) {
296 13 : isor_update_cenc_info(ch, GF_TRUE);
297 : }
298 : }
299 :
300 642314 : void isor_reader_get_sample(ISOMChannel *ch)
301 : {
302 : GF_Err e;
303 : u32 sample_desc_index;
304 887782 : if (ch->sample) return;
305 :
306 642314 : if (ch->next_track) {
307 0 : ch->track = ch->next_track;
308 0 : ch->next_track = 0;
309 : }
310 :
311 642314 : if (ch->to_init) {
312 1185 : init_reader(ch);
313 1185 : sample_desc_index = ch->last_sample_desc_index;
314 641129 : } else if (ch->speed < 0) {
315 47 : if (ch->last_state == GF_EOS) {
316 2 : ch->sample = NULL;
317 2 : return;
318 : }
319 :
320 45 : if (ch->static_sample->IsRAP) {
321 20 : ch->last_rap_sample_time = ch->sample_time;
322 : }
323 :
324 45 : e = gf_isom_get_sample_for_movie_time(ch->owner->mov, ch->track, ch->sample_time + 1, &sample_desc_index, GF_ISOM_SEARCH_FORWARD, &ch->static_sample, &ch->sample_num, NULL);
325 :
326 45 : if ((e==GF_EOS) || (ch->static_sample->IsRAP)) {
327 20 : if (!ch->last_rap_sample_time) {
328 : e = GF_EOS;
329 : } else {
330 18 : e = gf_isom_get_sample_for_movie_time(ch->owner->mov, ch->track, ch->last_rap_sample_time - 1, &sample_desc_index, GF_ISOM_SEARCH_SYNC_BACKWARD, &ch->static_sample, &ch->sample_num, NULL);
331 : }
332 : }
333 :
334 43 : if (e) {
335 2 : if ((e==GF_EOS) && !ch->owner->frag_type) {
336 2 : ch->last_state = GF_EOS;
337 : }
338 2 : ch->sample = NULL;
339 2 : return;
340 : }
341 43 : ch->sample = ch->static_sample;
342 :
343 43 : if (ch->sample->DTS == ch->sample_time) {
344 0 : if (!ch->owner->frag_type) {
345 0 : ch->last_state = GF_EOS;
346 : }
347 : }
348 : if (ch->sample) {
349 43 : ch->sample_time = ch->sample->DTS;
350 : }
351 :
352 641082 : } else if (ch->has_edit_list) {
353 0 : u32 prev_sample = ch->sample_num;
354 0 : e = gf_isom_get_sample_for_movie_time(ch->owner->mov, ch->track, ch->sample_time + 1, &sample_desc_index, GF_ISOM_SEARCH_FORWARD, &ch->static_sample, &ch->sample_num, &ch->sample_data_offset);
355 :
356 0 : if (e == GF_OK) {
357 0 : ch->sample = ch->static_sample;
358 :
359 : /*we are in forced seek mode: fetch all samples before the one matching the sample time*/
360 0 : if (ch->edit_sync_frame) {
361 0 : ch->edit_sync_frame++;
362 0 : if (ch->edit_sync_frame < ch->sample_num) {
363 0 : ch->sample = gf_isom_get_sample_ex(ch->owner->mov, ch->track, ch->edit_sync_frame, &sample_desc_index, ch->static_sample, &ch->sample_data_offset);
364 0 : ch->sample->DTS = ch->sample_time;
365 0 : ch->sample->CTS_Offset = 0;
366 : } else {
367 0 : ch->edit_sync_frame = 0;
368 0 : if (ch->sample) ch->sample_time = ch->sample->DTS;
369 : }
370 : } else {
371 : /*if we get the same sample, figure out next interesting time (current sample + DTS gap to next sample should be a good bet)*/
372 0 : if (prev_sample == ch->sample_num) {
373 0 : if (ch->owner->frag_type && (ch->sample_num==gf_isom_get_sample_count(ch->owner->mov, ch->track))) {
374 0 : ch->sample = NULL;
375 : } else {
376 0 : u32 sample_num = ch->sample_num ? ch->sample_num : 1;
377 :
378 0 : if (sample_num >= gf_isom_get_sample_count(ch->owner->mov, ch->track) ) {
379 : //e = GF_EOS;
380 : } else {
381 0 : u32 time_diff = gf_isom_get_sample_duration(ch->owner->mov, ch->track, sample_num);
382 0 : e = gf_isom_get_sample_for_movie_time(ch->owner->mov, ch->track, ch->sample_time + time_diff, &sample_desc_index, GF_ISOM_SEARCH_FORWARD, &ch->static_sample, &ch->sample_num, &ch->sample_data_offset);
383 0 : if (e==GF_OK) {
384 0 : if (ch->sample_num == prev_sample) {
385 0 : ch->sample_time += time_diff;
386 0 : ch->sample = NULL;
387 0 : return;
388 : } else {
389 0 : ch->sample = ch->static_sample;
390 : }
391 : }
392 : }
393 : }
394 : }
395 :
396 : /*we jumped to another segment - if RAP is needed look for closest rap in decoding order and
397 : force seek mode*/
398 0 : if (ch->sample && !ch->sample->IsRAP && ch->has_rap && (ch->sample_num != prev_sample+1)) {
399 0 : GF_ISOSample *found = ch->static_sample;
400 : u32 samp_num = ch->sample_num;
401 0 : ch->sample = NULL;
402 0 : e = gf_isom_get_sample_for_movie_time(ch->owner->mov, ch->track, ch->sample_time + 1, &sample_desc_index, GF_ISOM_SEARCH_SYNC_BACKWARD, &ch->static_sample, &ch->sample_num, &ch->sample_data_offset);
403 :
404 0 : if (e == GF_OK) ch->sample = ch->static_sample;
405 :
406 : /*if no sync point in the past, use the first non-sync for the given time*/
407 0 : if (!ch->sample || !ch->sample->data) {
408 0 : ch->sample = ch->static_sample = found;
409 0 : ch->sample_time = ch->sample->DTS;
410 0 : ch->sample_num = samp_num;
411 : } else {
412 0 : ch->sample = ch->static_sample;
413 0 : ch->edit_sync_frame = ch->sample_num;
414 0 : ch->sample->DTS = ch->sample_time;
415 0 : ch->sample->CTS_Offset = 0;
416 : }
417 : } else {
418 0 : if (ch->sample) ch->sample_time = ch->sample->DTS;
419 : }
420 : }
421 : }
422 : } else {
423 : Bool do_fetch = GF_TRUE;
424 641082 : ch->sample_num++;
425 :
426 641082 : if (ch->sap_only) {
427 72 : Bool is_rap = gf_isom_get_sample_sync(ch->owner->mov, ch->track, ch->sample_num);
428 72 : if (!is_rap) {
429 : GF_ISOSampleRollType roll_type;
430 6 : gf_isom_get_sample_rap_roll_info(ch->owner->mov, ch->track, ch->sample_num, &is_rap, &roll_type, NULL);
431 6 : if (roll_type) is_rap = GF_TRUE;
432 : }
433 :
434 72 : if (!is_rap) {
435 : do_fetch = GF_FALSE;
436 66 : } else if (ch->sap_only==2) {
437 0 : ch->sap_only = 0;
438 : }
439 : }
440 : if (do_fetch) {
441 641076 : if (ch->owner->nodata) {
442 0 : ch->sample = gf_isom_get_sample_info_ex(ch->owner->mov, ch->track, ch->sample_num, &sample_desc_index, &ch->sample_data_offset, ch->static_sample);
443 : } else {
444 641076 : ch->sample = gf_isom_get_sample_ex(ch->owner->mov, ch->track, ch->sample_num, &sample_desc_index, ch->static_sample, &ch->sample_data_offset);
445 : }
446 : /*if sync shadow / carousel RAP skip*/
447 641076 : if (ch->sample && (ch->sample->IsRAP==RAP_REDUNDANT)) {
448 0 : ch->sample = NULL;
449 0 : ch->sample_num++;
450 0 : isor_reader_get_sample(ch);
451 0 : return;
452 : }
453 : }
454 : }
455 :
456 : //check scalable track change
457 642310 : if (ch->sample && ch->sample->IsRAP && ch->next_track) {
458 0 : ch->track = ch->next_track;
459 0 : ch->next_track = 0;
460 0 : ch->sample = NULL;
461 0 : isor_reader_get_sample(ch);
462 0 : return;
463 : }
464 :
465 642310 : if (!ch->sample) {
466 245464 : u32 sample_count = gf_isom_get_sample_count(ch->owner->mov, ch->track);
467 245464 : ch->sample_data_offset = 0;
468 : /*incomplete file - check if we're still downloading or not*/
469 245464 : if (gf_isom_get_missing_bytes(ch->owner->mov, ch->track)) {
470 1527 : ch->last_state = GF_ISOM_INCOMPLETE_FILE;
471 1527 : if (ch->owner->mem_load_mode==2)
472 418 : ch->owner->force_fetch = GF_TRUE;
473 :
474 1527 : if (!ch->owner->input_loaded) {
475 1467 : ch->last_state = GF_OK;
476 1467 : if (!ch->has_edit_list && ch->sample_num)
477 1450 : ch->sample_num--;
478 : } else {
479 60 : if (ch->sample_num >= gf_isom_get_sample_count(ch->owner->mov, ch->track)) {
480 0 : ch->last_state = GF_EOS;
481 : }
482 : }
483 : }
484 243937 : else if (!ch->sample_num
485 243924 : || ((ch->speed >= 0) && (ch->sample_num >= sample_count))
486 6 : || ((ch->speed < 0) && (ch->sample_time == gf_isom_get_current_tfdt(ch->owner->mov, ch->track) ))
487 : ) {
488 :
489 243931 : if (ch->owner->frag_type==1) {
490 : /*if sample cannot be found and file is fragmented, rewind sample*/
491 230279 : if (ch->sample_num) ch->sample_num--;
492 230279 : ch->last_state = GF_EOS;
493 13652 : } else if (ch->last_state != GF_EOS) {
494 782 : GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[IsoMedia] Track #%d end of stream reached\n", ch->track));
495 782 : ch->last_state = GF_EOS;
496 782 : if (ch->sample_num>sample_count) ch->sample_num = sample_count;
497 : } else {
498 12870 : if (ch->sample_num>sample_count) ch->sample_num = sample_count;
499 : }
500 : } else {
501 6 : GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[IsoMedia] Track #%d fail to fetch sample %d / %d: %s\n", ch->track, ch->sample_num, gf_isom_get_sample_count(ch->owner->mov, ch->track), gf_error_to_string(gf_isom_last_error(ch->owner->mov)) ));
502 : }
503 : return;
504 : }
505 :
506 396846 : if (sample_desc_index != ch->last_sample_desc_index) {
507 247 : if (!ch->owner->stsd) {
508 : //we used sample entry 1 by default to setup, if no active prev sample (edit list might trigger this)
509 : //and new sample desc is 1, do not reconfigure
510 247 : if (!ch->last_sample_desc_index && (sample_desc_index==1)) {
511 :
512 : } else {
513 5 : ch->needs_pid_reconfig = GF_TRUE;
514 : }
515 : }
516 247 : ch->last_sample_desc_index = sample_desc_index;
517 : }
518 :
519 396846 : ch->last_state = GF_OK;
520 396846 : ch->au_duration = gf_isom_get_sample_duration(ch->owner->mov, ch->track, ch->sample_num);
521 :
522 396846 : ch->sap_3 = GF_FALSE;
523 396846 : ch->sap_4_type = 0;
524 396846 : ch->roll = 0;
525 396846 : ch->set_disc = ch->owner->clock_discontinuity ? 2 : 0;
526 396846 : ch->owner->clock_discontinuity = 0;
527 :
528 396846 : if (ch->sample) {
529 396846 : gf_isom_get_sample_rap_roll_info(ch->owner->mov, ch->track, ch->sample_num, &ch->sap_3, &ch->sap_4_type, &ch->roll);
530 :
531 : /*still seeking or not ?
532 : 1- when speed is negative, the RAP found is "after" the seek point in playback order since we used backward RAP search: nothing to do
533 : 2- otherwise set DTS+CTS to start value
534 : */
535 396846 : if ((ch->speed < 0) || (ch->start <= ch->sample->DTS + ch->sample->CTS_Offset)) {
536 396807 : ch->dts = ch->sample->DTS;
537 396807 : ch->cts = ch->sample->DTS + ch->sample->CTS_Offset;
538 396807 : ch->seek_flag = 0;
539 : } else {
540 39 : ch->cts = ch->start;
541 39 : ch->seek_flag = 1;
542 39 : ch->dts = ch->start;
543 : }
544 :
545 396846 : if (ch->end && (ch->end < ch->sample->DTS + ch->sample->CTS_Offset + ch->au_duration)) {
546 0 : GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[IsoMedia] End of Channel "LLD" (CTS "LLD")\n", ch->end, ch->sample->DTS + ch->sample->CTS_Offset));
547 0 : ch->sample = NULL;
548 0 : ch->last_state = GF_EOS;
549 0 : ch->playing = 2;
550 0 : return;
551 : }
552 : }
553 :
554 396846 : if (ch->owner->last_sender_ntp && ch->cts==ch->owner->cts_for_last_sender_ntp) {
555 0 : ch->sender_ntp = ch->owner->last_sender_ntp;
556 0 : ch->ntp_at_server_ntp = ch->owner->ntp_at_last_sender_ntp;
557 396846 : } else if (ch->owner->last_sender_ntp && ch->dts==ch->owner->cts_for_last_sender_ntp) {
558 0 : ch->sender_ntp = ch->owner->last_sender_ntp;
559 0 : ch->ntp_at_server_ntp = ch->owner->ntp_at_last_sender_ntp;
560 : } else {
561 396846 : ch->sender_ntp = ch->ntp_at_server_ntp = 0;
562 : }
563 :
564 396846 : if (!ch->sample_num) return;
565 :
566 396846 : gf_isom_get_sample_flags(ch->owner->mov, ch->track, ch->sample_num, &ch->isLeading, &ch->dependsOn, &ch->dependedOn, &ch->redundant);
567 :
568 396846 : if (ch->is_encrypted) {
569 : /*in case of CENC: we write sample auxiliary information to slh->sai; its size is in saiz*/
570 42342 : if (gf_isom_is_cenc_media(ch->owner->mov, ch->track, ch->last_sample_desc_index)) {
571 37927 : isor_update_cenc_info(ch, GF_FALSE);
572 :
573 4415 : } else if (gf_isom_is_media_encrypted(ch->owner->mov, ch->track, ch->last_sample_desc_index)) {
574 3869 : ch->pck_encrypted = GF_TRUE;
575 : } else {
576 546 : ch->pck_encrypted = GF_FALSE;
577 : }
578 : }
579 396846 : if (ch->sample && ch->sample->nb_pack)
580 482 : ch->sample_num += ch->sample->nb_pack-1;
581 : }
582 :
583 396918 : void isor_reader_release_sample(ISOMChannel *ch)
584 : {
585 399594 : if (ch->sample)
586 396918 : ch->au_seq_num++;
587 399594 : ch->sample = NULL;
588 399594 : ch->sai_buffer_size = 0;
589 396918 : }
590 :
591 40 : static void isor_reset_seq_list(GF_List *list)
592 : {
593 106 : while (gf_list_count(list)) {
594 26 : GF_NALUFFParam *sl = gf_list_pop_back(list);
595 26 : gf_free(sl->data);
596 26 : gf_free(sl);
597 : }
598 40 : }
599 :
600 : enum
601 : {
602 : RESET_STATE_VPS=1,
603 : RESET_STATE_SPS=1<<1,
604 : RESET_STATE_PPS=1<<2,
605 : RESET_STATE_SPS_EXT=1<<3,
606 : RESET_STATE_DCI=1<<4,
607 : };
608 :
609 2070 : static void isor_replace_nal(GF_AVCConfig *avcc, GF_HEVCConfig *hvcc, GF_VVCConfig *vvcc, u8 *data, u32 size, u8 nal_type, u32 *reset_state)
610 : {
611 : u32 i, count, state=0;
612 : GF_NALUFFParam *sl;
613 : GF_List *list=NULL;
614 2070 : if (avcc) {
615 2022 : if (nal_type==GF_AVC_NALU_PIC_PARAM) {
616 1992 : list = avcc->pictureParameterSets;
617 : state=RESET_STATE_PPS;
618 30 : } else if (nal_type==GF_AVC_NALU_SEQ_PARAM) {
619 30 : list = avcc->sequenceParameterSets;
620 : state=RESET_STATE_SPS;
621 0 : } else if (nal_type==GF_AVC_NALU_SEQ_PARAM_EXT) {
622 0 : list = avcc->sequenceParameterSetExtensions;
623 : state=RESET_STATE_SPS_EXT;
624 : } else return;
625 : }
626 48 : else if (hvcc) {
627 : GF_NALUFFParamArray *hvca=NULL;
628 48 : count = gf_list_count(hvcc->param_array);
629 96 : for (i=0; i<count; i++) {
630 90 : hvca = gf_list_get(hvcc->param_array, i);
631 90 : if (hvca->type==nal_type) {
632 42 : list = hvca->nalus;
633 42 : break;
634 : }
635 : hvca = NULL;
636 : }
637 48 : if (!hvca) {
638 6 : GF_SAFEALLOC(hvca, GF_NALUFFParamArray);
639 6 : if (hvca) {
640 6 : list = hvca->nalus = gf_list_new();
641 6 : hvca->type = nal_type;
642 6 : gf_list_add(hvcc->param_array, hvca);
643 : }
644 : }
645 48 : switch (nal_type) {
646 16 : case GF_HEVC_NALU_VID_PARAM:
647 : state = RESET_STATE_VPS;
648 16 : break;
649 16 : case GF_HEVC_NALU_SEQ_PARAM:
650 : state = RESET_STATE_SPS;
651 16 : break;
652 16 : case GF_HEVC_NALU_PIC_PARAM:
653 : state = RESET_STATE_PPS;
654 16 : break;
655 : }
656 : }
657 0 : else if (vvcc) {
658 : GF_NALUFFParamArray *vvca=NULL;
659 0 : count = gf_list_count(vvcc->param_array);
660 0 : for (i=0; i<count; i++) {
661 0 : vvca = gf_list_get(vvcc->param_array, i);
662 0 : if (vvca->type==nal_type) {
663 0 : list = vvca->nalus;
664 0 : break;
665 : }
666 : vvca = NULL;
667 : }
668 0 : if (!vvca) {
669 0 : GF_SAFEALLOC(vvca, GF_NALUFFParamArray);
670 0 : if (vvca) {
671 0 : list = vvca->nalus = gf_list_new();
672 0 : vvca->type = nal_type;
673 0 : gf_list_add(vvcc->param_array, vvca);
674 : }
675 : }
676 0 : switch (nal_type) {
677 0 : case GF_VVC_NALU_VID_PARAM:
678 : state = RESET_STATE_VPS;
679 0 : break;
680 0 : case GF_VVC_NALU_SEQ_PARAM:
681 : state = RESET_STATE_SPS;
682 0 : break;
683 0 : case GF_VVC_NALU_PIC_PARAM:
684 : state = RESET_STATE_PPS;
685 0 : break;
686 0 : case GF_VVC_NALU_DEC_PARAM:
687 : state = RESET_STATE_DCI;
688 0 : break;
689 : }
690 : }
691 :
692 2070 : count = gf_list_count(list);
693 2322 : for (i=0; i<count; i++) {
694 2278 : sl = gf_list_get(list, i);
695 2278 : if ((sl->size==size) && !memcmp(sl->data, data, size)) return;
696 : }
697 44 : if (! (*reset_state & state)) {
698 40 : isor_reset_seq_list(list);
699 40 : *reset_state |= state;
700 : }
701 44 : GF_SAFEALLOC(sl, GF_NALUFFParam);
702 44 : if (!sl) return;
703 44 : sl->data = gf_malloc(sizeof(char)*size);
704 : memcpy(sl->data, data, size);
705 44 : sl->size = size;
706 44 : gf_list_add(list, sl);
707 : }
708 :
709 396918 : void isor_reader_check_config(ISOMChannel *ch)
710 : {
711 : u32 nalu_len, reset_state;
712 621806 : if (!ch->check_hevc_ps && !ch->check_avc_ps && !ch->check_vvc_ps && !ch->check_mhas_pl) return;
713 :
714 185450 : if (!ch->sample) return;
715 : //we cannot touch the payload if encrypted !!
716 : //TODO, in CENC try to remove non-encrypted NALUs and update saiz accordingly
717 185450 : if (ch->is_encrypted) return;
718 :
719 172030 : if (ch->check_mhas_pl) {
720 0 : u64 ch_layout = 0;
721 0 : s32 PL = gf_mpegh_get_mhas_pl(ch->sample->data, ch->sample->dataLength, &ch_layout);
722 0 : if (PL>0) {
723 0 : gf_filter_pid_set_property(ch->pid, GF_PROP_PID_PROFILE_LEVEL, &PROP_UINT((u32) PL));
724 0 : ch->check_mhas_pl = GF_FALSE;
725 0 : if (ch_layout)
726 0 : gf_filter_pid_set_property(ch->pid, GF_PROP_PID_CHANNEL_LAYOUT, &PROP_LONGUINT(ch_layout));
727 : }
728 : return;
729 : }
730 :
731 172030 : if (ch->owner->analyze) return;
732 :
733 : nalu_len = 4;
734 172030 : if (ch->avcc) nalu_len = ch->avcc->nal_unit_size;
735 12067 : else if (ch->hvcc) nalu_len = ch->hvcc->nal_unit_size;
736 0 : else if (ch->vvcc) nalu_len = ch->vvcc->nal_unit_size;
737 :
738 172030 : reset_state = 0;
739 :
740 172030 : if (!ch->nal_bs) ch->nal_bs = gf_bs_new(ch->sample->data, ch->sample->dataLength, GF_BITSTREAM_READ);
741 171750 : else gf_bs_reassign_buffer(ch->nal_bs, ch->sample->data, ch->sample->dataLength);
742 :
743 393251 : while (gf_bs_available(ch->nal_bs)) {
744 : Bool replace_nal = GF_FALSE;
745 : u8 nal_type=0;
746 221221 : u32 pos = (u32) gf_bs_get_position(ch->nal_bs);
747 221221 : u32 size = gf_bs_read_int(ch->nal_bs, nalu_len*8);
748 : //this takes care of size + pos + nalu_len > 0 but (s32) size < 0 ...
749 221221 : if (ch->sample->dataLength < size) break;
750 221221 : if (ch->sample->dataLength < size + pos + nalu_len) break;
751 221221 : if (ch->check_avc_ps) {
752 166766 : u8 hdr = gf_bs_peek_bits(ch->nal_bs, 8, 0);
753 166766 : nal_type = hdr & 0x1F;
754 : switch (nal_type) {
755 : case GF_AVC_NALU_SEQ_PARAM:
756 : case GF_AVC_NALU_SEQ_PARAM_EXT:
757 : case GF_AVC_NALU_PIC_PARAM:
758 : replace_nal = GF_TRUE;
759 : break;
760 : }
761 : }
762 54455 : else if (ch->check_hevc_ps) {
763 54455 : u8 hdr = gf_bs_peek_bits(ch->nal_bs, 8, 0);
764 54455 : nal_type = (hdr & 0x7E) >> 1;
765 54455 : switch (nal_type) {
766 48 : case GF_HEVC_NALU_VID_PARAM:
767 : case GF_HEVC_NALU_SEQ_PARAM:
768 : case GF_HEVC_NALU_PIC_PARAM:
769 : replace_nal = GF_TRUE;
770 48 : break;
771 : }
772 : }
773 0 : else if (ch->check_vvc_ps) {
774 0 : u8 hdr = gf_bs_peek_bits(ch->nal_bs, 8, 1);
775 0 : nal_type = hdr >> 3;
776 0 : switch (nal_type) {
777 0 : case GF_VVC_NALU_VID_PARAM:
778 : case GF_VVC_NALU_SEQ_PARAM:
779 : case GF_VVC_NALU_PIC_PARAM:
780 : case GF_VVC_NALU_DEC_PARAM:
781 : replace_nal = GF_TRUE;
782 0 : break;
783 : }
784 : }
785 221221 : gf_bs_skip_bytes(ch->nal_bs, size);
786 :
787 221221 : if (replace_nal) {
788 2070 : u32 move_size = ch->sample->dataLength - size - pos - nalu_len;
789 2070 : isor_replace_nal(ch->avcc, ch->hvcc, ch->vvcc, ch->sample->data + pos + nalu_len, size, nal_type, &reset_state);
790 2070 : if (move_size)
791 108 : memmove(ch->sample->data + pos, ch->sample->data + pos + size + nalu_len, ch->sample->dataLength - size - pos - nalu_len);
792 :
793 2070 : ch->sample->dataLength -= size + nalu_len;
794 2070 : gf_bs_reassign_buffer(ch->nal_bs, ch->sample->data, ch->sample->dataLength);
795 2070 : gf_bs_seek(ch->nal_bs, pos);
796 : }
797 : }
798 :
799 172030 : if (reset_state) {
800 22 : u8 *dsi=NULL;
801 22 : u32 dsi_size=0;
802 22 : if (ch->check_avc_ps) {
803 14 : gf_odf_avc_cfg_write(ch->avcc, &dsi, &dsi_size);
804 : }
805 8 : else if (ch->check_hevc_ps) {
806 8 : gf_odf_hevc_cfg_write(ch->hvcc, &dsi, &dsi_size);
807 : }
808 0 : else if (ch->check_vvc_ps) {
809 0 : gf_odf_vvc_cfg_write(ch->vvcc, &dsi, &dsi_size);
810 : }
811 22 : if (dsi && dsi_size) {
812 22 : u32 dsi_crc = gf_crc_32(dsi, dsi_size);
813 22 : if (ch->dsi_crc == dsi_crc) {
814 0 : gf_free(dsi);
815 : } else {
816 22 : ch->dsi_crc = dsi_crc;
817 22 : gf_filter_pid_set_property(ch->pid, GF_PROP_PID_DECODER_CONFIG, &PROP_DATA_NO_COPY(dsi, dsi_size) );
818 : }
819 : }
820 : }
821 : }
822 :
823 : #endif /*GPAC_DISABLE_ISOM*/
|