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 / NALU (AVC, HEVC, VVC) reframer 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 : #include <gpac/avparse.h>
27 : #include <gpac/constants.h>
28 : #include <gpac/filters.h>
29 : #include <gpac/internal/media_dev.h>
30 : //for oinf stuff
31 : #include <gpac/internal/isomedia_dev.h>
32 :
33 : #ifndef GPAC_DISABLE_AV_PARSERS
34 :
35 : #define CTS_POC_OFFSET_SAFETY 1000
36 :
37 : GF_Err gf_bs_set_logger(GF_BitStream *bs, void (*on_bs_log)(void *udta, const char *field_name, u32 nb_bits, u64 field_val, s32 idx1, s32 idx2, s32 idx3), void *udta);
38 :
39 : typedef struct
40 : {
41 : u64 pos;
42 : Double duration;
43 : } NALUIdx;
44 :
45 :
46 : typedef struct
47 : {
48 : u32 layer_id_plus_one;
49 : u32 min_temporal_id, max_temporal_id;
50 : } LHVCLayerInfo;
51 :
52 : enum {
53 : STRICT_POC_OFF = 0,
54 : STRICT_POC_ON,
55 : STRICT_POC_ERROR,
56 : };
57 :
58 : typedef struct
59 : {
60 : //filter args
61 : GF_Fraction fps;
62 : Double index;
63 : Bool explicit, force_sync, nosei, importer, subsamples, nosvc, novpsext, deps, seirw, audelim, analyze;
64 : u32 nal_length;
65 : u32 strict_poc;
66 : u32 bsdbg;
67 : GF_Fraction idur;
68 :
69 : //only one input pid declared
70 : GF_FilterPid *ipid;
71 : //only one output pid declared
72 : GF_FilterPid *opid;
73 :
74 : //read bitstream for AVC/HEVC parsing
75 : GF_BitStream *bs_r;
76 : //write bitstream for nalus size length rewrite
77 : GF_BitStream *bs_w;
78 : //current CTS/DTS of the stream, may be overridden by input packet if not file (eg TS PES)
79 : u64 cts, dts, prev_dts, prev_cts;
80 : u32 pck_duration;
81 : //basic config stored here: with, height CRC of base and enh layer decoder config, sample aspect ratio
82 : //when changing, a new pid config will be emitted
83 : u32 width, height;
84 : u32 crc_cfg, crc_cfg_enh;
85 : GF_Fraction sar;
86 : GF_Fraction cur_fps;
87 :
88 : //duration of the file if known
89 : GF_Fraction64 duration;
90 : //playback start range
91 : Double start_range;
92 : //indicates we are in seek, packets before start range should be marked
93 : Bool in_seek;
94 : //set once we play something
95 : Bool is_playing;
96 : //is a file, is a file fully loaded on disk (local or download done)
97 : Bool is_file, file_loaded;
98 : //initial PLAY command found
99 : Bool initial_play_done;
100 :
101 : //list of RAP entry points
102 : NALUIdx *indexes;
103 : u32 index_alloc_size, index_size;
104 :
105 :
106 : //timescale of the input pid if any, 0 otherwise
107 : u32 timescale;
108 : //framing flag of input packet when input pid has timing (eg is not a file)
109 : Bool input_is_au_start;
110 :
111 : GF_FilterPacket *src_pck;
112 :
113 : Bool full_au_source;
114 :
115 : //total delay in frames between decode and presentation
116 : s32 max_total_delay;
117 : //max size codable with our nal_length setting
118 : u32 max_nalu_size_allowed;
119 :
120 : //position in input packet from which we resume parsing
121 : u32 resume_from;
122 : //prevents message about possible NAL size optimizaion at finalization
123 : Bool nal_adjusted;
124 :
125 : //avc/hevc switch
126 : u32 codecid;
127 : //name of the logger
128 : const char *log_name;
129 :
130 : //list of packet (in decode order !!) not yet dispatched.
131 : //Dispatch depends on the mode:
132 : //strict_poc=0: we wait after each IDR until we find a stable poc diff between pictures, controled by poc_probe_done
133 : //strict_poc>=1: we dispatch only after IDR or at the end (huge delay)
134 : GF_List *pck_queue;
135 : //dts of the last IDR found
136 : u64 dts_last_IDR;
137 : //max size of NALUs in the bitstream
138 : u32 max_nalu_size;
139 :
140 :
141 : u8 *nal_store;
142 : u32 nal_store_size, nal_store_alloc;
143 :
144 : //list of param sets found
145 : GF_List *sps, *pps, *vps, *sps_ext, *pps_svc, *vvc_aps_pre, *vvc_dci;
146 : //set to true if one of the PS has been modified, will potentially trigger a PID reconfigure
147 : Bool ps_modified;
148 :
149 : //stats
150 : u32 nb_idr, nb_i, nb_p, nb_b, nb_sp, nb_si, nb_sei, nb_nalus, nb_aud;
151 :
152 : //frame has intra slice
153 : Bool has_islice;
154 : //AU is rap
155 : GF_FilterSAPType au_sap;
156 : //frame first slice
157 : Bool first_slice_in_au;
158 : //paff used - NEED FURTHER CHECKING
159 : Bool is_paff;
160 : Bool bottom_field_flag;
161 : //SEI recovery count - if 0 and I slice only frame, openGOP detection (avc)
162 : s32 sei_recovery_frame_count;
163 : u32 use_opengop_gdr;
164 : //poc compute variables
165 : s32 last_poc, max_last_poc, max_last_b_poc, poc_diff, prev_last_poc, min_poc, poc_shift;
166 : //set to TRUE once 3 frames with same min poc diff are found, enabling dispatch of the frames
167 : Bool poc_probe_done;
168 : //pointer to the first packet of the current frame (the one holding timing info)
169 : //this packet is in the packet queue
170 : GF_FilterPacket *first_pck_in_au;
171 : //frame has slices used as reference
172 : Bool has_ref_slices;
173 : //frame has redundant coding
174 : Bool has_redundant;
175 :
176 : Bool last_frame_is_idr;
177 :
178 : //buffer to store SEI messages
179 : //for AVC: we have to rewrite the SEI to remove some of the messages according to the spec
180 : //for HEVC: we store prefix SEI here and dispatch them once the first VCL is found
181 : char *sei_buffer;
182 : u32 sei_buffer_size, sei_buffer_alloc;
183 :
184 : //subsample buffer, only used for SVC for now
185 : u32 subsamp_buffer_alloc, subsamp_buffer_size, subs_mapped_bytes;
186 : char *subsamp_buffer;
187 :
188 : //AVC specific
189 : //avc bitstream state
190 : AVCState *avc_state;
191 :
192 : //SVC specific
193 : char *svc_prefix_buffer;
194 : u32 svc_prefix_buffer_size, svc_prefix_buffer_alloc;
195 : u32 svc_nalu_prefix_reserved;
196 : u8 svc_nalu_prefix_priority;
197 :
198 : //HEVC specific
199 : HEVCState *hevc_state;
200 : //shvc stats
201 : u32 nb_e_idr, nb_e_i, nb_e_p, nb_e_b;
202 : Bool vvc_no_stats;
203 :
204 : LHVCLayerInfo linf[64];
205 : u8 max_temporal_id[64];
206 : u8 min_layer_id;
207 :
208 : //VVC specific
209 : VVCState *vvc_state;
210 :
211 : Bool has_initial_aud;
212 : char init_aud[3];
213 :
214 : Bool interlaced;
215 :
216 : Bool is_mvc;
217 :
218 : u32 bitrate;
219 : u32 nb_frames;
220 : } GF_NALUDmxCtx;
221 :
222 : static void naludmx_enqueue_or_dispatch(GF_NALUDmxCtx *ctx, GF_FilterPacket *n_pck, Bool flush_ref);
223 : static void naludmx_finalize_au_flags(GF_NALUDmxCtx *ctx);
224 :
225 :
226 445 : GF_Err naludmx_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
227 : {
228 : const GF_PropertyValue *p;
229 445 : GF_NALUDmxCtx *ctx = gf_filter_get_udta(filter);
230 :
231 445 : if (is_remove) {
232 1 : ctx->ipid = NULL;
233 1 : if (ctx->opid) {
234 1 : gf_filter_pid_remove(ctx->opid);
235 1 : ctx->opid = NULL;
236 : }
237 : return GF_OK;
238 : }
239 444 : if (! gf_filter_pid_check_caps(pid))
240 : return GF_NOT_SUPPORTED;
241 :
242 444 : ctx->ipid = pid;
243 444 : p = gf_filter_pid_get_property(pid, GF_PROP_PID_TIMESCALE);
244 444 : if (p) {
245 30 : ctx->timescale = p->value.uint;
246 : //if we have a FPS prop, use it
247 30 : p = gf_filter_pid_get_property(pid, GF_PROP_PID_FPS);
248 30 : if (p) {
249 16 : ctx->cur_fps = p->value.frac;
250 : } else {
251 14 : ctx->cur_fps.den = 0;
252 14 : ctx->cur_fps.num = ctx->timescale;
253 : }
254 : }
255 :
256 444 : p = gf_filter_pid_get_property(pid, GF_PROP_PID_CODECID);
257 444 : if (p) {
258 30 : switch (p->value.uint) {
259 0 : case GF_CODECID_HEVC:
260 : case GF_CODECID_LHVC:
261 0 : ctx->codecid = GF_CODECID_HEVC;
262 0 : break;
263 0 : case GF_CODECID_VVC:
264 0 : ctx->codecid = GF_CODECID_VVC;
265 0 : break;
266 30 : case GF_CODECID_AVC:
267 : case GF_CODECID_AVC_PS:
268 : case GF_CODECID_SVC:
269 : case GF_CODECID_MVC:
270 30 : ctx->codecid = GF_CODECID_AVC;
271 30 : break;
272 : default:
273 : return GF_NOT_SUPPORTED;
274 : }
275 : }
276 : else {
277 414 : p = gf_filter_pid_get_property(pid, GF_PROP_PID_MIME);
278 825 : if (p && p->value.string && (
279 411 : strstr(p->value.string, "hvc")
280 411 : || strstr(p->value.string, "hevc")
281 247 : || strstr(p->value.string, "265")
282 247 : || strstr(p->value.string, "shvc")
283 247 : || strstr(p->value.string, "mhvc")
284 247 : || strstr(p->value.string, "lhvc")
285 : ) )
286 164 : ctx->codecid = GF_CODECID_HEVC;
287 497 : else if (p && p->value.string && (
288 247 : strstr(p->value.string, "vvc")
289 : ) )
290 0 : ctx->codecid = GF_CODECID_VVC;
291 : else {
292 250 : p = gf_filter_pid_get_property(pid, GF_PROP_PID_FILE_EXT);
293 500 : if (p && p->value.string && (
294 250 : strstr(p->value.string, "hvc")
295 250 : || strstr(p->value.string, "hevc")
296 247 : || strstr(p->value.string, "265")
297 247 : || strstr(p->value.string, "shvc")
298 247 : || strstr(p->value.string, "mhvc")
299 247 : || strstr(p->value.string, "lhvc")
300 : ) )
301 3 : ctx->codecid = GF_CODECID_HEVC;
302 494 : else if (p && p->value.string && (
303 247 : strstr(p->value.string, "vvc")
304 247 : || strstr(p->value.string, "266")
305 247 : || strstr(p->value.string, "lvvc")
306 : ) )
307 0 : ctx->codecid = GF_CODECID_VVC;
308 : else
309 247 : ctx->codecid = GF_CODECID_AVC;
310 : }
311 : }
312 444 : if (ctx->codecid==GF_CODECID_HEVC) {
313 : #ifdef GPAC_DISABLE_HEVC
314 : return GF_NOT_SUPPORTED;
315 : #else
316 167 : ctx->log_name = "HEVC";
317 167 : if (ctx->avc_state) gf_free(ctx->avc_state);
318 167 : if (ctx->vvc_state) gf_free(ctx->vvc_state);
319 167 : if (!ctx->hevc_state) GF_SAFEALLOC(ctx->hevc_state, HEVCState);
320 167 : ctx->min_layer_id = 0xFF;
321 : #endif
322 277 : } else if (ctx->codecid==GF_CODECID_VVC) {
323 0 : ctx->log_name = "VVC";
324 0 : if (ctx->hevc_state) gf_free(ctx->hevc_state);
325 0 : if (ctx->avc_state) gf_free(ctx->avc_state);
326 0 : if (!ctx->vvc_state) GF_SAFEALLOC(ctx->vvc_state, VVCState);
327 : } else {
328 277 : ctx->log_name = "AVC|H264";
329 277 : if (ctx->hevc_state) gf_free(ctx->hevc_state);
330 277 : if (ctx->vvc_state) gf_free(ctx->vvc_state);
331 277 : if (!ctx->avc_state) GF_SAFEALLOC(ctx->avc_state, AVCState);
332 : }
333 444 : if (ctx->timescale && !ctx->opid) {
334 22 : ctx->opid = gf_filter_pid_new(filter);
335 22 : ctx->first_slice_in_au = GF_TRUE;
336 : }
337 444 : ctx->full_au_source = GF_FALSE;
338 444 : p = gf_filter_pid_get_property(pid, GF_PROP_PID_UNFRAMED_FULL_AU);
339 444 : if (p && p->value.boolean) {
340 : GF_FilterEvent fevt;
341 : //this is a reframer used after an encoder, we want to make sure we have enough frames to compute POC otherwise we might block the chain
342 : //by holding input packets - ask 1s by default
343 16 : GF_FEVT_INIT(fevt, GF_FEVT_BUFFER_REQ, ctx->ipid);
344 16 : fevt.buffer_req.pid_only = GF_TRUE;
345 16 : fevt.buffer_req.max_buffer_us = 1000000;
346 16 : gf_filter_pid_send_event(ctx->ipid, &fevt);
347 16 : ctx->full_au_source = GF_TRUE;
348 : }
349 :
350 : //copy properties at init or reconfig
351 444 : if (ctx->opid) {
352 60 : if (ctx->poc_probe_done) {
353 : //full frame mode, flush everything before signaling discontinuity
354 : //for other modes discontinuity we signal disconntinuity before the current AU being reconstructed
355 30 : if (ctx->full_au_source && ctx->first_pck_in_au)
356 0 : naludmx_finalize_au_flags(ctx);
357 :
358 30 : naludmx_enqueue_or_dispatch(ctx, NULL, GF_TRUE);
359 : }
360 60 : gf_filter_pid_copy_properties(ctx->opid, ctx->ipid);
361 60 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_STREAM_TYPE, & PROP_UINT(GF_STREAM_VISUAL));
362 60 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_CODECID, & PROP_UINT(ctx->codecid));
363 :
364 60 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_UNFRAMED, NULL);
365 60 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_UNFRAMED_FULL_AU, NULL);
366 60 : if (!gf_filter_pid_get_property(ctx->ipid, GF_PROP_PID_ID))
367 34 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_ID, &PROP_UINT(1));
368 :
369 60 : ctx->ps_modified = GF_TRUE;
370 60 : ctx->crc_cfg = ctx->crc_cfg_enh = 0;
371 : }
372 :
373 : return GF_OK;
374 : }
375 :
376 :
377 14678 : static void naludmx_check_dur(GF_Filter *filter, GF_NALUDmxCtx *ctx)
378 : {
379 : FILE *stream;
380 : GF_BitStream *bs;
381 : u64 duration, cur_dur, nal_start, start_code_pos, rate;
382 : AVCState *avc_state = NULL;
383 : HEVCState *hevc_state = NULL;
384 : VVCState *vvc_state = NULL;
385 : Bool first_slice_in_pic = GF_TRUE;
386 : const GF_PropertyValue *p;
387 : const char *filepath = NULL;
388 14678 : if (!ctx->opid || ctx->timescale || ctx->file_loaded) return;
389 :
390 384 : p = gf_filter_pid_get_property(ctx->ipid, GF_PROP_PID_FILEPATH);
391 384 : if (!p || !p->value.string || !strncmp(p->value.string, "gmem://", 7)) {
392 0 : ctx->is_file = GF_FALSE;
393 0 : ctx->file_loaded = GF_TRUE;
394 : return;
395 : }
396 : filepath = p->value.string;
397 384 : ctx->is_file = GF_TRUE;
398 :
399 384 : if (ctx->index<0) {
400 166 : if (gf_opts_get_bool("temp", "force_indexing")) {
401 0 : ctx->index = 1.0;
402 : } else {
403 166 : p = gf_filter_pid_get_property(ctx->ipid, GF_PROP_PID_DOWN_SIZE);
404 166 : if (!p || (p->value.longuint > 20000000)) {
405 2 : GF_LOG(GF_LOG_INFO, GF_LOG_PARSER, ("[%s] Source file larger than 20M, skipping indexing\n", ctx->log_name));
406 : } else {
407 164 : ctx->index = -ctx->index;
408 : }
409 : }
410 : }
411 384 : if (ctx->index<=0) {
412 220 : ctx->duration.num = 1;
413 220 : ctx->file_loaded = GF_TRUE;
414 : return;
415 : }
416 :
417 164 : if (ctx->codecid==GF_CODECID_HEVC) {
418 67 : GF_SAFEALLOC(hevc_state, HEVCState);
419 67 : if (!hevc_state) return;
420 97 : } else if (ctx->codecid==GF_CODECID_VVC) {
421 0 : GF_SAFEALLOC(vvc_state, VVCState);
422 0 : if (!vvc_state) return;
423 : } else {
424 97 : GF_SAFEALLOC(avc_state, AVCState);
425 97 : if (!avc_state) return;
426 : }
427 :
428 164 : stream = gf_fopen(filepath, "rb");
429 164 : if (!stream) {
430 0 : if (hevc_state) gf_free(hevc_state);
431 0 : if (vvc_state) gf_free(vvc_state);
432 0 : if (avc_state) gf_free(avc_state);
433 : return;
434 : }
435 164 : ctx->index_size = 0;
436 : duration = 0;
437 : cur_dur = 0;
438 :
439 164 : bs = gf_bs_from_file(stream, GF_BITSTREAM_READ);
440 164 : gf_bs_enable_emulation_byte_removal(bs, GF_TRUE);
441 :
442 164 : start_code_pos = gf_bs_get_position(bs);
443 164 : if (!gf_media_nalu_is_start_code(bs)) {
444 0 : if (hevc_state) gf_free(hevc_state);
445 0 : if (avc_state) gf_free(avc_state);
446 0 : gf_bs_del(bs);
447 0 : gf_fclose(stream);
448 0 : ctx->duration.num = 1;
449 0 : ctx->file_loaded = GF_TRUE;
450 : return;
451 : }
452 :
453 164 : nal_start = gf_bs_get_position(bs);
454 :
455 251235 : while (gf_bs_available(bs)) {
456 : u32 nal_size;
457 : s32 res;
458 : Bool is_rap = GF_FALSE;
459 : Bool is_slice = GF_FALSE;
460 251235 : nal_size = gf_media_nalu_next_start_code_bs(bs);
461 :
462 251235 : gf_bs_seek(bs, nal_start);
463 251235 : if (hevc_state) {
464 : #ifndef GPAC_DISABLE_HEVC
465 : u8 temporal_id, layer_id, nal_type;
466 :
467 207001 : res = gf_hevc_parse_nalu_bs(bs, hevc_state, &nal_type, &temporal_id, &layer_id);
468 207001 : if (res>0) first_slice_in_pic = GF_TRUE;
469 207001 : switch (nal_type) {
470 6074 : case GF_HEVC_NALU_SLICE_IDR_N_LP:
471 : case GF_HEVC_NALU_SLICE_IDR_W_DLP:
472 : case GF_HEVC_NALU_SLICE_CRA:
473 : case GF_HEVC_NALU_SLICE_BLA_N_LP:
474 : case GF_HEVC_NALU_SLICE_BLA_W_LP:
475 : case GF_HEVC_NALU_SLICE_BLA_W_DLP:
476 : is_rap = GF_TRUE;
477 : is_slice = GF_TRUE;
478 : break;
479 141306 : case GF_HEVC_NALU_SLICE_STSA_N:
480 : case GF_HEVC_NALU_SLICE_STSA_R:
481 : case GF_HEVC_NALU_SLICE_RADL_R:
482 : case GF_HEVC_NALU_SLICE_RASL_R:
483 : case GF_HEVC_NALU_SLICE_RADL_N:
484 : case GF_HEVC_NALU_SLICE_RASL_N:
485 : case GF_HEVC_NALU_SLICE_TRAIL_N:
486 : case GF_HEVC_NALU_SLICE_TRAIL_R:
487 : case GF_HEVC_NALU_SLICE_TSA_N:
488 : case GF_HEVC_NALU_SLICE_TSA_R:
489 : is_slice = GF_TRUE;
490 : break;
491 : }
492 : #endif // GPAC_DISABLE_HEVC
493 44234 : } else if (vvc_state) {
494 :
495 : } else {
496 : u32 nal_type;
497 44234 : u64 pos = gf_bs_get_position(bs);
498 44234 : res = gf_avc_parse_nalu(bs, avc_state);
499 44234 : if (res>0) first_slice_in_pic = GF_TRUE;
500 :
501 44234 : nal_type = avc_state->last_nal_type_parsed;
502 :
503 44234 : switch (nal_type) {
504 1085 : case GF_AVC_NALU_SEQ_PARAM:
505 1085 : gf_bs_seek(bs, pos);
506 1085 : gf_avc_read_sps_bs(bs, avc_state, GF_FALSE, NULL);
507 : break;
508 2000 : case GF_AVC_NALU_PIC_PARAM:
509 2000 : gf_bs_seek(bs, pos);
510 2000 : gf_avc_read_pps_bs(bs, avc_state);
511 : break;
512 1133 : case GF_AVC_NALU_IDR_SLICE:
513 : is_rap = GF_TRUE;
514 : is_slice = GF_TRUE;
515 : break;
516 37075 : case GF_AVC_NALU_NON_IDR_SLICE:
517 : case GF_AVC_NALU_DP_A_SLICE:
518 : case GF_AVC_NALU_DP_B_SLICE:
519 : case GF_AVC_NALU_DP_C_SLICE:
520 : is_slice = GF_TRUE;
521 : break;
522 : }
523 : }
524 :
525 251235 : if (is_rap && first_slice_in_pic && (cur_dur >= ctx->index * ctx->cur_fps.num) ) {
526 2291 : if (!ctx->index_alloc_size) ctx->index_alloc_size = 10;
527 2130 : else if (ctx->index_alloc_size == ctx->index_size) ctx->index_alloc_size *= 2;
528 2291 : ctx->indexes = gf_realloc(ctx->indexes, sizeof(NALUIdx)*ctx->index_alloc_size);
529 2291 : ctx->indexes[ctx->index_size].pos = start_code_pos;
530 2291 : ctx->indexes[ctx->index_size].duration = (Double) duration;
531 2291 : ctx->indexes[ctx->index_size].duration /= ctx->cur_fps.num;
532 2291 : ctx->index_size ++;
533 : cur_dur = 0;
534 : }
535 :
536 251235 : if (is_slice && first_slice_in_pic) {
537 69524 : duration += ctx->cur_fps.den;
538 69524 : cur_dur += ctx->cur_fps.den;
539 : first_slice_in_pic = GF_FALSE;
540 : }
541 :
542 251235 : gf_bs_seek(bs, nal_start + nal_size);
543 : /* nal_start = gf_media_nalu_next_start_code_bs(bs);
544 : if (nal_start) gf_bs_skip_bytes(bs, nal_start);
545 : */
546 251235 : if (gf_bs_available(bs)<4)
547 : break;
548 :
549 251071 : start_code_pos = gf_bs_get_position(bs);
550 251071 : nal_start = gf_media_nalu_is_start_code(bs);
551 251071 : if (!nal_start) {
552 : break;
553 : }
554 251071 : nal_start = gf_bs_get_position(bs);
555 : }
556 :
557 164 : rate = gf_bs_get_position(bs);
558 164 : gf_bs_del(bs);
559 164 : gf_fclose(stream);
560 164 : if (hevc_state) gf_free(hevc_state);
561 164 : if (vvc_state) gf_free(vvc_state);
562 164 : if (avc_state) gf_free(avc_state);
563 :
564 164 : if (!ctx->duration.num || (ctx->duration.num * ctx->cur_fps.num != duration * ctx->duration.den)) {
565 164 : ctx->duration.num = (s32) duration;
566 164 : ctx->duration.den = ctx->cur_fps.num;
567 :
568 164 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_DURATION, & PROP_FRAC64(ctx->duration));
569 :
570 164 : if (duration && (!gf_sys_is_test_mode() || gf_opts_get_bool("temp", "force_indexing"))) {
571 3 : rate *= 8 * ctx->duration.den;
572 3 : rate /= ctx->duration.num;
573 3 : ctx->bitrate = (u32) rate;
574 : }
575 : }
576 :
577 :
578 164 : p = gf_filter_pid_get_property(ctx->ipid, GF_PROP_PID_FILE_CACHED);
579 164 : if (p && p->value.boolean) ctx->file_loaded = GF_TRUE;
580 164 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_CAN_DATAREF, & PROP_BOOL(GF_TRUE ) );
581 : }
582 :
583 :
584 913374 : static void naludmx_enqueue_or_dispatch(GF_NALUDmxCtx *ctx, GF_FilterPacket *n_pck, Bool flush_ref)
585 : {
586 : //TODO: we are dispatching frames in "negctts mode", ie we may have DTS>CTS
587 : //need to signal this for consumers using DTS (eg MPEG-2 TS)
588 913374 : if (flush_ref && ctx->pck_queue && ctx->poc_diff) {
589 : u32 dts_inc=0;
590 : s32 last_poc = 0;
591 : Bool patch_missing_frame = GF_FALSE;
592 : //send all reference packet queued
593 246400 : if (ctx->strict_poc==STRICT_POC_ERROR) {
594 : u32 i;
595 : u32 nb_bframes = 0;
596 0 : for (i=0; i<gf_list_count(ctx->pck_queue); i++) {
597 : s32 poc;
598 : u64 poc_ts, dts;
599 0 : GF_FilterPacket *q_pck = gf_list_get(ctx->pck_queue, i);
600 :
601 0 : if (q_pck == ctx->first_pck_in_au) break;
602 :
603 0 : dts = gf_filter_pck_get_dts(q_pck);
604 0 : if (dts == GF_FILTER_NO_TS) continue;
605 0 : poc_ts = gf_filter_pck_get_cts(q_pck);
606 : assert(poc_ts != GF_FILTER_NO_TS);
607 0 : poc = (s32) ((s64) poc_ts - CTS_POC_OFFSET_SAFETY);
608 :
609 0 : if (i) {
610 0 : if (last_poc>poc) nb_bframes ++;
611 0 : else if (last_poc + ctx->poc_diff<poc)
612 : patch_missing_frame = GF_TRUE;
613 : }
614 : last_poc = poc;
615 : }
616 0 : if (nb_bframes>1)
617 : patch_missing_frame = GF_FALSE;
618 0 : else if (nb_bframes)
619 : patch_missing_frame = GF_TRUE;
620 : }
621 : last_poc = GF_INT_MIN;
622 :
623 1158167 : while (gf_list_count(ctx->pck_queue) ) {
624 : u64 dts;
625 901191 : GF_FilterPacket *q_pck = gf_list_get(ctx->pck_queue, 0);
626 :
627 901191 : if (q_pck == ctx->first_pck_in_au) break;
628 :
629 665367 : dts = gf_filter_pck_get_dts(q_pck);
630 665367 : if (dts != GF_FILTER_NO_TS) {
631 : s32 poc;
632 : u64 poc_ts, cts;
633 245169 : u8 carousel_info = gf_filter_pck_get_carousel_version(q_pck);
634 :
635 : //we reused timing from source packets
636 245169 : if (!carousel_info) {
637 : assert(ctx->timescale);
638 5659 : gf_list_rem(ctx->pck_queue, 0);
639 5659 : gf_filter_pck_send(q_pck);
640 5659 : continue;
641 : }
642 239510 : gf_filter_pck_set_carousel_version(q_pck, 0);
643 :
644 :
645 239510 : poc_ts = gf_filter_pck_get_cts(q_pck);
646 : assert(poc_ts != GF_FILTER_NO_TS);
647 239510 : poc = (s32) ((s64) poc_ts - CTS_POC_OFFSET_SAFETY);
648 :
649 239510 : if (patch_missing_frame) {
650 0 : if (last_poc!=GF_INT_MIN) {
651 : //check if we missed an IDR (poc reset)
652 0 : if (poc && (last_poc > poc) ) {
653 : last_poc = 0;
654 0 : dts_inc += ctx->cur_fps.den;
655 0 : ctx->dts_last_IDR = dts;
656 0 : ctx->dts += ctx->cur_fps.den;
657 : }
658 : //check if we miss a frame
659 0 : while (last_poc + ctx->poc_diff < poc) {
660 : last_poc += ctx->poc_diff;
661 0 : dts_inc += ctx->cur_fps.den;
662 0 : ctx->dts += ctx->cur_fps.den;
663 : }
664 : }
665 : last_poc = poc;
666 0 : dts += dts_inc;
667 : }
668 : //poc is stored as diff since last IDR which has min_poc
669 239510 : cts = ( (ctx->min_poc + (s32) poc) * ctx->cur_fps.den ) / ctx->poc_diff + ctx->dts_last_IDR;
670 :
671 : /*if PAFF, 2 pictures (eg poc) <=> 1 aggregated frame (eg sample), divide by 2*/
672 239510 : if (ctx->is_paff) {
673 0 : cts /= 2;
674 : /*in some cases the poc is not on the top field - if that is the case, round up*/
675 0 : if (cts % ctx->cur_fps.den) {
676 0 : cts = ((cts/ctx->cur_fps.den)+1) * ctx->cur_fps.den;
677 : }
678 : }
679 :
680 239510 : gf_filter_pck_set_cts(q_pck, cts);
681 239510 : GF_LOG(GF_LOG_DEBUG, GF_LOG_PARSER, ("[%s] Frame timestamps computed dts "LLU" cts "LLU" (poc %d min poc %d poc_diff %d last IDR DTS "LLU")\n", ctx->log_name, dts, cts, poc, ctx->min_poc, ctx->poc_diff, ctx->dts_last_IDR));
682 :
683 239510 : if (ctx->importer && ctx->cur_fps.den) {
684 175718 : poc = (s32) ( (s64) cts - (s64) dts);
685 175718 : if (poc<0) poc = -poc;
686 175718 : poc /= ctx->cur_fps.den;
687 175718 : if (poc > ctx->max_total_delay)
688 196 : ctx->max_total_delay = poc;
689 : }
690 : }
691 659708 : gf_list_rem(ctx->pck_queue, 0);
692 659708 : gf_filter_pck_send(q_pck);
693 : }
694 : }
695 913374 : if (!n_pck) return;
696 :
697 665557 : if (!ctx->pck_queue) ctx->pck_queue = gf_list_new();
698 665557 : gf_list_add(ctx->pck_queue, n_pck);
699 : }
700 :
701 1026 : static void naludmx_add_param_nalu(GF_List *param_list, GF_NALUFFParam *sl, u8 nal_type)
702 : {
703 : GF_NALUFFParamArray *pa = NULL;
704 : u32 i, count;
705 1026 : count = gf_list_count(param_list);
706 1770 : for (i=0; i<count; i++) {
707 744 : pa = gf_list_get(param_list, i);
708 744 : if (pa->type == nal_type) break;
709 : pa = NULL;
710 : }
711 1026 : if (!pa) {
712 1026 : GF_SAFEALLOC(pa, GF_NALUFFParamArray);
713 1026 : if (!pa) return;
714 :
715 1026 : pa->array_completeness = 1;
716 1026 : pa->type = nal_type;
717 1026 : pa->nalus = gf_list_new();
718 1026 : gf_list_add(param_list, pa);
719 : }
720 1026 : gf_list_add(pa->nalus, sl);
721 : }
722 :
723 : #ifndef GPAC_DISABLE_HEVC
724 :
725 489 : static void naludmx_hevc_set_parall_type(GF_NALUDmxCtx *ctx, GF_HEVCConfig *hevc_cfg)
726 : {
727 : u32 use_tiles, use_wpp, nb_pps, i, count;
728 : HEVCState hevc;
729 :
730 489 : count = gf_list_count(ctx->pps);
731 :
732 : memset(&hevc, 0, sizeof(HEVCState));
733 489 : hevc.sps_active_idx = -1;
734 :
735 : use_tiles = 0;
736 : use_wpp = 0;
737 : nb_pps = 0;
738 :
739 227 : for (i=0; i<count; i++) {
740 227 : GF_NALUFFParam *slc = (GF_NALUFFParam*)gf_list_get(ctx->pps, i);
741 227 : s32 idx = gf_hevc_read_pps(slc->data, slc->size, &hevc);
742 :
743 227 : if (idx>=0) {
744 : HEVC_PPS *pps;
745 227 : nb_pps++;
746 : pps = &hevc.pps[idx];
747 227 : if (!pps->entropy_coding_sync_enabled_flag && pps->tiles_enabled_flag)
748 120 : use_tiles++;
749 107 : else if (pps->entropy_coding_sync_enabled_flag && !pps->tiles_enabled_flag)
750 34 : use_wpp++;
751 : }
752 : }
753 489 : if (!use_tiles && !use_wpp) hevc_cfg->parallelismType = 1;
754 154 : else if (!use_wpp && (use_tiles==nb_pps) ) hevc_cfg->parallelismType = 2;
755 34 : else if (!use_tiles && (use_wpp==nb_pps) ) hevc_cfg->parallelismType = 3;
756 0 : else hevc_cfg->parallelismType = 0;
757 489 : }
758 : #endif // GPAC_DISABLE_HEVC
759 :
760 711 : GF_Err naludmx_set_hevc_oinf(GF_NALUDmxCtx *ctx, u8 *max_temporal_id)
761 : {
762 : GF_OperatingPointsInformation *oinf;
763 : GF_BitStream *bs;
764 : u8 *data;
765 : u32 data_size;
766 : u32 i;
767 : HEVC_VPS *vps;
768 711 : GF_NALUFFParam *vps_sl = gf_list_get(ctx->vps, 0);
769 711 : if (!vps_sl) return GF_SERVICE_ERROR;
770 :
771 711 : vps = &ctx->hevc_state->vps[vps_sl->id];
772 :
773 711 : if (!vps->vps_extension_found) return GF_OK;
774 36 : if (vps->max_layers<2) return GF_OK;
775 :
776 36 : oinf = gf_isom_oinf_new_entry();
777 36 : if (!oinf) return GF_OUT_OF_MEM;
778 :
779 36 : oinf->scalability_mask = 0;
780 612 : for (i = 0; i < 16; i++) {
781 576 : if (vps->scalability_mask[i])
782 36 : oinf->scalability_mask |= 1 << i;
783 : }
784 :
785 108 : for (i = 0; i < vps->num_profile_tier_level; i++) {
786 108 : HEVC_ProfileTierLevel ptl = (i == 0) ? vps->ptl : vps->ext_ptl[i-1];
787 : LHEVC_ProfileTierLevel *lhevc_ptl;
788 108 : GF_SAFEALLOC(lhevc_ptl, LHEVC_ProfileTierLevel);
789 108 : if (!lhevc_ptl) return GF_OUT_OF_MEM;
790 :
791 108 : lhevc_ptl->general_profile_space = ptl.profile_space;
792 108 : lhevc_ptl->general_tier_flag = ptl.tier_flag;
793 108 : lhevc_ptl->general_profile_idc = ptl.profile_idc;
794 108 : lhevc_ptl->general_profile_compatibility_flags = ptl.profile_compatibility_flag;
795 108 : lhevc_ptl->general_constraint_indicator_flags = 0;
796 108 : if (ptl.general_progressive_source_flag)
797 0 : lhevc_ptl->general_constraint_indicator_flags |= ((u64)1) << 47;
798 108 : if (ptl.general_interlaced_source_flag)
799 0 : lhevc_ptl->general_constraint_indicator_flags |= ((u64)1) << 46;
800 108 : if (ptl.general_non_packed_constraint_flag)
801 0 : lhevc_ptl->general_constraint_indicator_flags |= ((u64)1) << 45;
802 108 : if (ptl.general_frame_only_constraint_flag)
803 0 : lhevc_ptl->general_constraint_indicator_flags |= ((u64)1) << 44;
804 108 : lhevc_ptl->general_constraint_indicator_flags |= ptl.general_reserved_44bits;
805 108 : lhevc_ptl->general_level_idc = ptl.level_idc;
806 108 : gf_list_add(oinf->profile_tier_levels, lhevc_ptl);
807 : }
808 :
809 72 : for (i = 0; i < vps->num_output_layer_sets; i++) {
810 : LHEVC_OperatingPoint *op;
811 : u32 j;
812 : u16 minPicWidth, minPicHeight, maxPicWidth, maxPicHeight;
813 : u8 maxChromaFormat, maxBitDepth;
814 : u8 maxTemporalId;
815 72 : GF_SAFEALLOC(op, LHEVC_OperatingPoint);
816 72 : if (!op) return GF_OUT_OF_MEM;
817 :
818 72 : op->output_layer_set_idx = i;
819 72 : op->layer_count = vps->num_necessary_layers[i];
820 : minPicWidth = minPicHeight = maxPicWidth = maxPicHeight = maxTemporalId = 0;
821 : maxChromaFormat = maxBitDepth = 0;
822 180 : for (j = 0; j < op->layer_count; j++) {
823 : u32 format_idx;
824 : u32 bitDepth;
825 108 : op->layers_info[j].ptl_idx = vps->profile_tier_level_idx[i][j];
826 108 : op->layers_info[j].layer_id = j;
827 108 : op->layers_info[j].is_outputlayer = vps->output_layer_flag[i][j];
828 : //FIXME: we consider that this flag is never set
829 108 : op->layers_info[j].is_alternate_outputlayer = GF_FALSE;
830 :
831 108 : if (max_temporal_id) {
832 18 : if (!maxTemporalId || (maxTemporalId < max_temporal_id[op->layers_info[j].layer_id]))
833 15 : maxTemporalId = max_temporal_id[op->layers_info[j].layer_id];
834 : } else {
835 90 : maxTemporalId = vps->max_sub_layers;
836 : }
837 :
838 108 : format_idx = vps->rep_format_idx[op->layers_info[j].layer_id];
839 108 : if (!minPicWidth || (minPicWidth > vps->rep_formats[format_idx].pic_width_luma_samples))
840 72 : minPicWidth = vps->rep_formats[format_idx].pic_width_luma_samples;
841 108 : if (!minPicHeight || (minPicHeight > vps->rep_formats[format_idx].pic_height_luma_samples))
842 72 : minPicHeight = vps->rep_formats[format_idx].pic_height_luma_samples;
843 108 : if (!maxPicWidth || (maxPicWidth < vps->rep_formats[format_idx].pic_width_luma_samples))
844 90 : maxPicWidth = vps->rep_formats[format_idx].pic_width_luma_samples;
845 108 : if (!maxPicHeight || (maxPicHeight < vps->rep_formats[format_idx].pic_height_luma_samples))
846 90 : maxPicHeight = vps->rep_formats[format_idx].pic_height_luma_samples;
847 108 : if (!maxChromaFormat || (maxChromaFormat < vps->rep_formats[format_idx].chroma_format_idc))
848 72 : maxChromaFormat = vps->rep_formats[format_idx].chroma_format_idc;
849 108 : bitDepth = vps->rep_formats[format_idx].bit_depth_chroma > vps->rep_formats[format_idx].bit_depth_luma ? vps->rep_formats[format_idx].bit_depth_chroma : vps->rep_formats[format_idx].bit_depth_luma;
850 108 : if (!maxChromaFormat || (maxChromaFormat < bitDepth))
851 72 : maxChromaFormat = bitDepth;
852 : }
853 72 : op->max_temporal_id = maxTemporalId;
854 72 : op->minPicWidth = minPicWidth;
855 72 : op->minPicHeight = minPicHeight;
856 72 : op->maxPicWidth = maxPicWidth;
857 72 : op->maxPicHeight = maxPicHeight;
858 72 : op->maxChromaFormat = maxChromaFormat;
859 72 : op->maxBitDepth = maxBitDepth;
860 72 : op->frame_rate_info_flag = GF_FALSE; //FIXME: should fetch this info from VUI
861 72 : op->bit_rate_info_flag = GF_FALSE; //we don't use it
862 72 : gf_list_add(oinf->operating_points, op);
863 : }
864 :
865 72 : for (i = 0; i < vps->max_layers; i++) {
866 : LHEVC_DependentLayer *dep;
867 : u32 j, k;
868 72 : GF_SAFEALLOC(dep, LHEVC_DependentLayer);
869 72 : if (!dep) return GF_OUT_OF_MEM;
870 :
871 72 : dep->dependent_layerID = vps->layer_id_in_nuh[i];
872 216 : for (j = 0; j < vps->max_layers; j++) {
873 144 : if (vps->direct_dependency_flag[dep->dependent_layerID][j]) {
874 36 : dep->dependent_on_layerID[dep->num_layers_dependent_on] = j;
875 36 : dep->num_layers_dependent_on ++;
876 : }
877 : }
878 : k = 0;
879 1152 : for (j = 0; j < 16; j++) {
880 1152 : if (oinf->scalability_mask & (1 << j)) {
881 72 : dep->dimension_identifier[j] = vps->dimension_id[i][k];
882 72 : k++;
883 : }
884 : }
885 72 : gf_list_add(oinf->dependency_layers, dep);
886 : }
887 :
888 : //write Operating Points Information Sample Group
889 36 : bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
890 36 : gf_isom_oinf_write_entry(oinf, bs);
891 36 : gf_bs_get_content(bs, &data, &data_size);
892 36 : gf_bs_del(bs);
893 36 : gf_isom_oinf_del_entry(oinf);
894 :
895 36 : gf_filter_pid_set_info_str(ctx->opid, "hevc:oinf", &PROP_DATA_NO_COPY(data, data_size) );
896 36 : return GF_OK;
897 : }
898 :
899 711 : static void naludmx_set_hevc_linf(GF_NALUDmxCtx *ctx)
900 : {
901 : u32 i, nb_layers=0, nb_sublayers=0;
902 : u8 *data;
903 : u32 data_size;
904 : GF_BitStream *bs;
905 :
906 46215 : for (i=0; i<64; i++) {
907 45504 : if (ctx->linf[i].layer_id_plus_one) nb_layers++;
908 45504 : if (ctx->linf[i].min_temporal_id != ctx->linf[i].max_temporal_id) nb_sublayers++;
909 : }
910 711 : if (!nb_layers && !nb_sublayers)
911 411 : return;
912 :
913 300 : bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
914 :
915 300 : gf_bs_write_int(bs, 0, 2);
916 300 : gf_bs_write_int(bs, nb_layers, 6);
917 606 : for (i=0; i<nb_layers; i++) {
918 306 : if (! ctx->linf[i].layer_id_plus_one) continue;
919 306 : gf_bs_write_int(bs, 0, 4);
920 306 : gf_bs_write_int(bs, ctx->linf[i].layer_id_plus_one - 1, 6);
921 306 : gf_bs_write_int(bs, ctx->linf[i].min_temporal_id, 3);
922 306 : gf_bs_write_int(bs, ctx->linf[i].max_temporal_id, 3);
923 306 : gf_bs_write_int(bs, 0, 1);
924 306 : gf_bs_write_int(bs, 0xFF, 7);
925 :
926 : }
927 300 : gf_bs_get_content(bs, &data, &data_size);
928 300 : gf_bs_del(bs);
929 300 : gf_filter_pid_set_info_str(ctx->opid, "hevc:linf", &PROP_DATA_NO_COPY(data, data_size) );
930 : }
931 :
932 477 : static void naludmx_create_hevc_decoder_config(GF_NALUDmxCtx *ctx, u8 **dsi, u32 *dsi_size, u8 **dsi_enh, u32 *dsi_enh_size, u32 *max_width, u32 *max_height, u32 *max_enh_width, u32 *max_enh_height, GF_Fraction *sar, Bool *has_hevc_base)
933 : {
934 : #ifndef GPAC_DISABLE_HEVC
935 : u32 i, count;
936 : u8 layer_id;
937 : Bool first = GF_TRUE;
938 : Bool first_lhvc = GF_TRUE;
939 : GF_HEVCConfig *cfg;
940 : GF_HEVCConfig *hvcc;
941 : GF_HEVCConfig *lvcc;
942 : u32 max_w, max_h, max_ew, max_eh;
943 :
944 477 : *has_hevc_base = GF_FALSE;
945 :
946 :
947 : max_w = max_h = 0;
948 : max_ew = max_eh = 0;
949 477 : sar->num = sar->den = 0;
950 :
951 477 : hvcc = gf_odf_hevc_cfg_new();
952 477 : lvcc = gf_odf_hevc_cfg_new();
953 477 : hvcc->nal_unit_size = ctx->nal_length;
954 477 : lvcc->nal_unit_size = ctx->nal_length;
955 477 : lvcc->is_lhvc = GF_TRUE;
956 : //check we have one pps or sps in base layer
957 477 : count = gf_list_count(ctx->sps);
958 477 : for (i=0; i<count; i++) {
959 340 : GF_NALUFFParam *sl = gf_list_get(ctx->sps, i);
960 340 : layer_id = ((sl->data[0] & 0x1) << 5) | (sl->data[1] >> 3);
961 340 : if (!layer_id) {
962 340 : *has_hevc_base = GF_TRUE;
963 340 : break;
964 : }
965 : }
966 477 : count = gf_list_count(ctx->pps);
967 477 : for (i=0; i<count; i++) {
968 203 : GF_NALUFFParam *sl = gf_list_get(ctx->pps, i);
969 203 : layer_id = ((sl->data[0] & 0x1) << 5) | (sl->data[1] >> 3);
970 203 : if (!layer_id) {
971 203 : *has_hevc_base = GF_TRUE;
972 203 : break;
973 : }
974 : }
975 : //assign vps first so that they are serialized first
976 477 : count = gf_list_count(ctx->vps);
977 954 : for (i=0; i<count; i++) {
978 477 : GF_NALUFFParam *sl = gf_list_get(ctx->vps, i);
979 477 : HEVC_VPS *vps = &ctx->hevc_state->vps[sl->id];
980 :
981 477 : if (!i) {
982 477 : hvcc->avgFrameRate = lvcc->avgFrameRate = vps->rates[0].avg_pic_rate;
983 477 : hvcc->constantFrameRate = lvcc->constantFrameRate = vps->rates[0].constand_pic_rate_idc;
984 477 : hvcc->numTemporalLayers = lvcc->numTemporalLayers = vps->max_sub_layers;
985 477 : hvcc->temporalIdNested = lvcc->temporalIdNested = vps->temporal_id_nesting;
986 : }
987 : //TODO set scalability mask
988 477 : if (!ctx->analyze)
989 471 : naludmx_add_param_nalu((ctx->explicit || ! (*has_hevc_base) ) ? lvcc->param_array : hvcc->param_array, sl, GF_HEVC_NALU_VID_PARAM);
990 : }
991 :
992 477 : count = gf_list_count(ctx->sps);
993 829 : for (i=0; i<count; i++) {
994 : Bool is_lhvc = GF_FALSE;
995 352 : GF_NALUFFParam *sl = gf_list_get(ctx->sps, i);
996 352 : HEVC_SPS *sps = &ctx->hevc_state->sps[sl->id];
997 352 : layer_id = ((sl->data[0] & 0x1) << 5) | (sl->data[1] >> 3);
998 352 : if (!layer_id) *has_hevc_base = GF_TRUE;
999 :
1000 352 : if (ctx->explicit || layer_id) {
1001 : cfg = lvcc;
1002 : is_lhvc = GF_TRUE;
1003 : } else {
1004 : cfg = hvcc;
1005 : }
1006 :
1007 352 : if (first || (is_lhvc && first_lhvc) ) {
1008 352 : cfg->configurationVersion = 1;
1009 352 : cfg->profile_space = sps->ptl.profile_space;
1010 352 : cfg->tier_flag = sps->ptl.tier_flag;
1011 352 : cfg->profile_idc = sps->ptl.profile_idc;
1012 352 : cfg->general_profile_compatibility_flags = sps->ptl.profile_compatibility_flag;
1013 352 : cfg->progressive_source_flag = sps->ptl.general_progressive_source_flag;
1014 352 : cfg->interlaced_source_flag = sps->ptl.general_interlaced_source_flag;
1015 352 : cfg->non_packed_constraint_flag = sps->ptl.general_non_packed_constraint_flag;
1016 352 : cfg->frame_only_constraint_flag = sps->ptl.general_frame_only_constraint_flag;
1017 352 : cfg->constraint_indicator_flags = sps->ptl.general_reserved_44bits;
1018 352 : cfg->level_idc = sps->ptl.level_idc;
1019 352 : cfg->chromaFormat = sps->chroma_format_idc;
1020 352 : cfg->luma_bit_depth = sps->bit_depth_luma;
1021 352 : cfg->chroma_bit_depth = sps->bit_depth_chroma;
1022 352 : ctx->interlaced = cfg->interlaced_source_flag ? GF_TRUE : GF_FALSE;
1023 :
1024 352 : if (sps->aspect_ratio_info_present_flag && sps->sar_width && sps->sar_height) {
1025 40 : sar->num = sps->sar_width;
1026 40 : sar->den = sps->sar_height;
1027 : }
1028 :
1029 : /*disable frame rate scan, most bitstreams have wrong values there*/
1030 352 : if (!ctx->timescale && first && (!ctx->fps.num || !ctx->fps.den) && sps->has_timing_info
1031 : /*if detected FPS is greater than 1000, assume wrong timing info*/
1032 33 : && (sps->time_scale <= 1000*sps->num_units_in_tick)
1033 : ) {
1034 33 : ctx->cur_fps.num = sps->time_scale;
1035 33 : ctx->cur_fps.den = sps->num_units_in_tick;
1036 :
1037 33 : if (!ctx->fps.num && ctx->dts==ctx->fps.den)
1038 0 : ctx->dts = ctx->cur_fps.den;
1039 : }
1040 352 : ctx->fps = ctx->cur_fps;
1041 : }
1042 : first = GF_FALSE;
1043 352 : if (is_lhvc) {
1044 : first_lhvc = GF_FALSE;
1045 12 : if (sps->width > max_ew) max_ew = sps->width;
1046 12 : if (sps->height > max_eh) max_eh = sps->height;
1047 : } else {
1048 340 : if (sps->width > max_w) max_w = sps->width;
1049 340 : if (sps->height > max_h) max_h = sps->height;
1050 : }
1051 352 : if (!ctx->analyze)
1052 348 : naludmx_add_param_nalu(cfg->param_array, sl, GF_HEVC_NALU_SEQ_PARAM);
1053 : }
1054 :
1055 477 : cfg = ctx->explicit ? lvcc : hvcc;
1056 477 : count = gf_list_count(ctx->pps);
1057 686 : for (i=0; i<count; i++) {
1058 209 : GF_NALUFFParam *sl = gf_list_get(ctx->pps, i);
1059 209 : layer_id = ((sl->data[0] & 0x1) << 5) | (sl->data[1] >> 3);
1060 209 : if (!layer_id) *has_hevc_base = GF_TRUE;
1061 209 : if (!ctx->analyze)
1062 207 : naludmx_add_param_nalu(layer_id ? lvcc->param_array : cfg->param_array, sl, GF_HEVC_NALU_PIC_PARAM);
1063 : }
1064 :
1065 477 : *dsi = *dsi_enh = NULL;
1066 477 : *dsi_size = *dsi_enh_size = 0;
1067 :
1068 477 : if (ctx->explicit || ! (*has_hevc_base) ) {
1069 137 : naludmx_hevc_set_parall_type(ctx, lvcc);
1070 137 : gf_odf_hevc_cfg_write(lvcc, dsi, dsi_size);
1071 137 : *max_width = *max_enh_width = max_ew;
1072 137 : *max_height = *max_enh_height = max_eh;
1073 : } else {
1074 340 : naludmx_hevc_set_parall_type(ctx, hvcc);
1075 340 : gf_odf_hevc_cfg_write(hvcc, dsi, dsi_size);
1076 340 : if (gf_list_count(lvcc->param_array) ) {
1077 12 : naludmx_hevc_set_parall_type(ctx, lvcc);
1078 12 : gf_odf_hevc_cfg_write(lvcc, dsi_enh, dsi_enh_size);
1079 : }
1080 340 : *max_width = max_w;
1081 340 : *max_height = max_h;
1082 340 : *max_enh_width = max_ew;
1083 340 : *max_enh_height = max_eh;
1084 : }
1085 477 : count = gf_list_count(hvcc->param_array);
1086 1350 : for (i=0; i<count; i++) {
1087 873 : GF_NALUFFParamArray *pa = gf_list_get(hvcc->param_array, i);
1088 873 : gf_list_reset(pa->nalus);
1089 : }
1090 477 : count = gf_list_count(lvcc->param_array);
1091 630 : for (i=0; i<count; i++) {
1092 153 : GF_NALUFFParamArray *pa = gf_list_get(lvcc->param_array, i);
1093 153 : gf_list_reset(pa->nalus);
1094 : }
1095 477 : gf_odf_hevc_cfg_del(hvcc);
1096 477 : gf_odf_hevc_cfg_del(lvcc);
1097 : #endif // GPAC_DISABLE_HEVC
1098 477 : }
1099 :
1100 :
1101 0 : static void naludmx_create_vvc_decoder_config(GF_NALUDmxCtx *ctx, u8 **dsi, u32 *dsi_size, u8 **dsi_enh, u32 *dsi_enh_size, u32 *max_width, u32 *max_height, u32 *max_enh_width, u32 *max_enh_height, GF_Fraction *sar, Bool *has_vvc_base)
1102 : {
1103 : u32 i, count;
1104 : u8 layer_id;
1105 : Bool first = GF_TRUE;
1106 : Bool first_lvvc = GF_TRUE;
1107 : GF_VVCConfig *cfg;
1108 : u32 max_w, max_h, max_ew, max_eh;
1109 :
1110 0 : *has_vvc_base = GF_FALSE;
1111 :
1112 : max_w = max_h = 0;
1113 : max_ew = max_eh = 0;
1114 0 : sar->num = sar->den = 0;
1115 :
1116 0 : cfg = gf_odf_vvc_cfg_new();
1117 0 : cfg->nal_unit_size = ctx->nal_length;
1118 :
1119 : //check we have one pps or sps in base layer
1120 0 : count = gf_list_count(ctx->sps);
1121 0 : for (i=0; i<count; i++) {
1122 0 : GF_NALUFFParam *sl = gf_list_get(ctx->sps, i);
1123 0 : layer_id = (sl->data[0] & 0x3f);
1124 : //todo, base is not always 0 !
1125 0 : if (!layer_id) {
1126 0 : *has_vvc_base = GF_TRUE;
1127 0 : break;
1128 : }
1129 : }
1130 0 : count = gf_list_count(ctx->pps);
1131 0 : for (i=0; i<count; i++) {
1132 0 : GF_NALUFFParam *sl = gf_list_get(ctx->pps, i);
1133 0 : layer_id = (sl->data[0] & 0x3f);
1134 : //todo, base is not always 0 !
1135 0 : if (!layer_id) {
1136 0 : *has_vvc_base = GF_TRUE;
1137 0 : break;
1138 : }
1139 : }
1140 : //assign vps first so that they are serialized first
1141 0 : count = gf_list_count(ctx->vps);
1142 0 : for (i=0; i<count; i++) {
1143 0 : GF_NALUFFParam *sl = gf_list_get(ctx->vps, i);
1144 0 : VVC_VPS *vps = &ctx->vvc_state->vps[sl->id];
1145 :
1146 0 : if (!i) {
1147 0 : cfg->avgFrameRate = vps->rates[0].avg_pic_rate;
1148 0 : cfg->constantFrameRate = vps->rates[0].constand_pic_rate_idc;
1149 0 : cfg->numTemporalLayers = vps->max_sub_layers;
1150 : }
1151 0 : if (!ctx->analyze)
1152 0 : naludmx_add_param_nalu(cfg->param_array, sl, GF_VVC_NALU_VID_PARAM);
1153 : }
1154 :
1155 0 : count = gf_list_count(ctx->sps);
1156 0 : for (i=0; i<count; i++) {
1157 : Bool is_lvvc = GF_FALSE;
1158 0 : GF_NALUFFParam *sl = gf_list_get(ctx->sps, i);
1159 0 : VVC_SPS *sps = &ctx->vvc_state->sps[sl->id];
1160 0 : layer_id = sl->data[0] & 0x3f;
1161 0 : if (!layer_id) *has_vvc_base = GF_TRUE;
1162 :
1163 0 : if (ctx->explicit || layer_id) {
1164 : is_lvvc = GF_TRUE;
1165 : }
1166 :
1167 0 : if (first || (is_lvvc && first_lvvc) ) {
1168 0 : VVC_VPS *vps = &ctx->vvc_state->vps[sps->vps_id];
1169 0 : cfg->configurationVersion = 1;
1170 0 : cfg->avgFrameRate = 0;
1171 0 : cfg->constantFrameRate = 1;
1172 0 : cfg->numTemporalLayers = sps->max_sublayers;
1173 0 : cfg->nal_unit_size = ctx->nal_length;
1174 0 : cfg->ptl_present = vps->num_ptl ? 1 : 0;
1175 :
1176 0 : if (vps->num_ptl) {
1177 0 : cfg->num_constraint_info = vps->ptl[0].gci_present ? 1 : 12;
1178 0 : cfg->general_profile_idc = vps->ptl[0].general_profile_idc;
1179 0 : cfg->general_tier_flag = vps->ptl[0].general_tier_flag;
1180 0 : cfg->general_level_idc = vps->ptl[0].general_level_idc;
1181 0 : cfg->ptl_frame_only_constraint = vps->ptl[0].frame_only_constraint;
1182 0 : cfg->ptl_multilayer_enabled = vps->ptl[0].multilayer_enabled;
1183 :
1184 0 : cfg->general_constraint_info = gf_malloc(sizeof(u8) * cfg-> num_constraint_info);
1185 0 : if (cfg->general_constraint_info)
1186 0 : memcpy(cfg->general_constraint_info, vps->ptl[0].gci, cfg->num_constraint_info);
1187 :
1188 : //todo set temporal sublayers
1189 0 : cfg->ptl_sublayer_present_mask = 0;
1190 0 : cfg->num_sub_profiles = 0;
1191 0 : cfg->ols_idx = 0;
1192 : }
1193 0 : cfg->chromaformat_plus_one = 1 + sps->chroma_format_idc;
1194 0 : cfg->bit_depth_plus_one = 1 + sps->bitdepth;
1195 :
1196 0 : if (sps->aspect_ratio_info_present_flag && sps->sar_width && sps->sar_height) {
1197 0 : sar->num = sps->sar_width;
1198 0 : sar->den = sps->sar_height;
1199 : }
1200 :
1201 : /*disable frame rate scan, most bitstreams have wrong values there*/
1202 0 : if (!ctx->timescale && first && (!ctx->fps.num || !ctx->fps.den) && sps->has_timing_info
1203 : /*if detected FPS is greater than 1000, assume wrong timing info*/
1204 0 : && (sps->time_scale <= 1000*sps->num_units_in_tick)
1205 : ) {
1206 0 : ctx->cur_fps.num = sps->time_scale;
1207 0 : ctx->cur_fps.den = sps->num_units_in_tick;
1208 :
1209 0 : if (!ctx->fps.num && ctx->dts==ctx->fps.den)
1210 0 : ctx->dts = ctx->cur_fps.den;
1211 : }
1212 0 : ctx->fps = ctx->cur_fps;
1213 : }
1214 : first = GF_FALSE;
1215 0 : if (is_lvvc) {
1216 : first_lvvc = GF_FALSE;
1217 0 : if (sps->width > max_ew) max_ew = sps->width;
1218 0 : if (sps->height > max_eh) max_eh = sps->height;
1219 : } else {
1220 0 : if (sps->width > max_w) max_w = sps->width;
1221 0 : if (sps->height > max_h) max_h = sps->height;
1222 : }
1223 0 : if (!ctx->analyze)
1224 0 : naludmx_add_param_nalu(cfg->param_array, sl, GF_VVC_NALU_SEQ_PARAM);
1225 : }
1226 :
1227 0 : count = gf_list_count(ctx->pps);
1228 0 : for (i=0; i<count; i++) {
1229 0 : GF_NALUFFParam *sl = gf_list_get(ctx->pps, i);
1230 0 : layer_id = sl->data[0] & 0x3F;
1231 0 : if (!layer_id) *has_vvc_base = GF_TRUE;
1232 0 : if (!ctx->analyze)
1233 0 : naludmx_add_param_nalu(cfg->param_array, sl, GF_VVC_NALU_PIC_PARAM);
1234 : }
1235 :
1236 0 : count = gf_list_count(ctx->vvc_dci);
1237 0 : for (i=0; i<count; i++) {
1238 0 : GF_NALUFFParam *sl = gf_list_get(ctx->vvc_dci, i);
1239 0 : layer_id = sl->data[0] & 0x3F;
1240 0 : if (!layer_id) *has_vvc_base = GF_TRUE;
1241 0 : if (!ctx->analyze)
1242 0 : naludmx_add_param_nalu(cfg->param_array, sl, GF_VVC_NALU_DEC_PARAM);
1243 : }
1244 :
1245 0 : count = gf_list_count(ctx->vvc_aps_pre);
1246 0 : for (i=0; i<count; i++) {
1247 0 : GF_NALUFFParam *sl = gf_list_get(ctx->vvc_aps_pre, i);
1248 0 : layer_id = sl->data[0] & 0x3F;
1249 0 : if (!layer_id) *has_vvc_base = GF_TRUE;
1250 0 : if (!ctx->analyze)
1251 0 : naludmx_add_param_nalu(cfg->param_array, sl, GF_VVC_NALU_APS_PREFIX);
1252 : }
1253 :
1254 0 : *dsi = *dsi_enh = NULL;
1255 0 : *dsi_size = *dsi_enh_size = 0;
1256 :
1257 0 : gf_odf_vvc_cfg_write(cfg, dsi, dsi_size);
1258 0 : *max_width = max_w;
1259 0 : *max_height = max_h;
1260 0 : *max_enh_width = max_ew;
1261 0 : *max_enh_height = max_eh;
1262 :
1263 0 : count = gf_list_count(cfg->param_array);
1264 0 : for (i=0; i<count; i++) {
1265 0 : GF_NALUFFParamArray *pa = gf_list_get(cfg->param_array, i);
1266 0 : gf_list_reset(pa->nalus);
1267 : }
1268 0 : gf_odf_vvc_cfg_del(cfg);
1269 0 : }
1270 :
1271 592 : void naludmx_create_avc_decoder_config(GF_NALUDmxCtx *ctx, u8 **dsi, u32 *dsi_size, u8 **dsi_enh, u32 *dsi_enh_size, u32 *max_width, u32 *max_height, u32 *max_enh_width, u32 *max_enh_height, GF_Fraction *sar)
1272 : {
1273 : u32 i, count;
1274 : Bool first = GF_TRUE;
1275 : Bool first_svc = GF_TRUE;
1276 : GF_AVCConfig *cfg;
1277 : GF_AVCConfig *avcc;
1278 : GF_AVCConfig *svcc;
1279 : u32 max_w, max_h, max_ew, max_eh;
1280 :
1281 :
1282 : max_w = max_h = max_ew = max_eh = 0;
1283 592 : sar->num = sar->den = 0;
1284 :
1285 592 : avcc = gf_odf_avc_cfg_new();
1286 592 : svcc = gf_odf_avc_cfg_new();
1287 592 : avcc->nal_unit_size = ctx->nal_length;
1288 592 : svcc->nal_unit_size = ctx->nal_length;
1289 :
1290 592 : ctx->is_mvc = GF_FALSE;
1291 592 : count = gf_list_count(ctx->sps);
1292 1206 : for (i=0; i<count; i++) {
1293 : Bool is_svc = GF_FALSE;
1294 614 : GF_NALUFFParam *sl = gf_list_get(ctx->sps, i);
1295 614 : AVC_SPS *sps = &ctx->avc_state->sps[sl->id];
1296 614 : u32 nal_type = sl->data[0] & 0x1F;
1297 :
1298 614 : if ((sps->profile_idc == 118) || (sps->profile_idc == 128)) {
1299 0 : ctx->is_mvc = GF_TRUE;
1300 : }
1301 :
1302 614 : if (ctx->explicit) {
1303 : cfg = svcc;
1304 614 : } else if (nal_type == GF_AVC_NALU_SVC_SUBSEQ_PARAM) {
1305 : cfg = svcc;
1306 : is_svc = GF_TRUE;
1307 : } else {
1308 : cfg = avcc;
1309 : }
1310 :
1311 614 : if (first || (is_svc && first_svc) ) {
1312 596 : cfg->configurationVersion = 1;
1313 596 : cfg->profile_compatibility = sps->prof_compat;
1314 596 : cfg->AVCProfileIndication = sps->profile_idc;
1315 596 : cfg->AVCLevelIndication = sps->level_idc;
1316 596 : cfg->chroma_format = sps->chroma_format;
1317 596 : cfg->luma_bit_depth = 8 + sps->luma_bit_depth_m8;
1318 596 : cfg->chroma_bit_depth = 8 + sps->chroma_bit_depth_m8;
1319 : /*try to patch ?*/
1320 596 : if (!gf_avc_is_rext_profile(cfg->AVCProfileIndication)
1321 208 : && ((cfg->chroma_format>1) || (cfg->luma_bit_depth>8) || (cfg->chroma_bit_depth>8))
1322 : ) {
1323 0 : if ((cfg->luma_bit_depth>8) || (cfg->chroma_bit_depth>8)) {
1324 0 : cfg->AVCProfileIndication = 110;
1325 : } else {
1326 0 : cfg->AVCProfileIndication = (cfg->chroma_format==3) ? 244 : 122;
1327 : }
1328 : }
1329 596 : if (sps->vui_parameters_present_flag && sps->vui.par_num && sps->vui.par_den) {
1330 74 : sar->num = sps->vui.par_num;
1331 74 : sar->den = sps->vui.par_den;
1332 : }
1333 596 : ctx->interlaced = sps->frame_mbs_only_flag ? GF_FALSE : GF_TRUE;
1334 :
1335 :
1336 : /*disable frame rate scan, most bitstreams have wrong values there*/
1337 596 : if (first && (!ctx->fps.num || !ctx->fps.den) && sps->vui.timing_info_present_flag
1338 : /*if detected FPS is greater than 1000, assume wrong timing info*/
1339 269 : && (sps->vui.time_scale <= 1000*sps->vui.num_units_in_tick)
1340 : ) {
1341 : /*ISO/IEC 14496-10 n11084 Table E-6*/
1342 : /* not used : u8 DeltaTfiDivisorTable[] = {1,1,1,2,2,2,2,3,3,4,6}; */
1343 : u8 DeltaTfiDivisorIdx;
1344 269 : if (!sps->vui.pic_struct_present_flag) {
1345 261 : DeltaTfiDivisorIdx = 1 + (1 - ctx->avc_state->s_info.field_pic_flag);
1346 : } else {
1347 8 : if (!ctx->avc_state->sei.pic_timing.pic_struct)
1348 : DeltaTfiDivisorIdx = 2;
1349 0 : else if (ctx->avc_state->sei.pic_timing.pic_struct == 8)
1350 : DeltaTfiDivisorIdx = 6;
1351 : else
1352 0 : DeltaTfiDivisorIdx = (ctx->avc_state->sei.pic_timing.pic_struct+1) / 2;
1353 : }
1354 269 : if (!ctx->timescale) {
1355 241 : ctx->cur_fps.num = 2 * sps->vui.time_scale;
1356 241 : ctx->cur_fps.den = 2 * sps->vui.num_units_in_tick * DeltaTfiDivisorIdx;
1357 :
1358 241 : if (!ctx->fps.num && ctx->dts==ctx->fps.den)
1359 2 : ctx->dts = ctx->cur_fps.den;
1360 : }
1361 269 : if (! sps->vui.fixed_frame_rate_flag)
1362 108 : GF_LOG(GF_LOG_INFO, GF_LOG_PARSER, ("[%s] Possible Variable Frame Rate: VUI \"fixed_frame_rate_flag\" absent\n", ctx->log_name));
1363 : }
1364 596 : ctx->fps = ctx->cur_fps;
1365 : }
1366 : first = GF_FALSE;
1367 614 : if (is_svc) {
1368 : first_svc = GF_FALSE;
1369 30 : if (sps->width > max_ew) max_ew = sps->width;
1370 30 : if (sps->height > max_eh) max_eh = sps->height;
1371 : } else {
1372 584 : if (sps->width > max_w) max_w = sps->width;
1373 584 : if (sps->height > max_h) max_h = sps->height;
1374 : }
1375 614 : if (!ctx->analyze)
1376 610 : gf_list_add(cfg->sequenceParameterSets, sl);
1377 : }
1378 :
1379 592 : cfg = ctx->explicit ? svcc : avcc;
1380 592 : count = gf_list_count(ctx->sps_ext);
1381 592 : for (i=0; i<count; i++) {
1382 0 : GF_NALUFFParam *sl = gf_list_get(ctx->sps_ext, i);
1383 0 : if (!cfg->sequenceParameterSetExtensions) cfg->sequenceParameterSetExtensions = gf_list_new();
1384 0 : if (!ctx->analyze)
1385 0 : gf_list_add(cfg->sequenceParameterSetExtensions, sl);
1386 : }
1387 :
1388 592 : cfg = ctx->explicit ? svcc : avcc;
1389 592 : count = gf_list_count(ctx->pps);
1390 911 : for (i=0; i<count; i++) {
1391 319 : GF_NALUFFParam *sl = gf_list_get(ctx->pps, i);
1392 319 : if (!ctx->analyze)
1393 317 : gf_list_add(cfg->pictureParameterSets, sl);
1394 : }
1395 :
1396 : cfg = svcc;
1397 592 : count = gf_list_count(ctx->pps_svc);
1398 600 : for (i=0; i<count; i++) {
1399 8 : GF_NALUFFParam *sl = gf_list_get(ctx->pps_svc, i);
1400 8 : if (!ctx->analyze)
1401 8 : gf_list_add(cfg->pictureParameterSets, sl);
1402 : }
1403 :
1404 592 : *dsi = *dsi_enh = NULL;
1405 592 : *dsi_size = *dsi_enh_size = 0;
1406 :
1407 592 : if (ctx->explicit) {
1408 0 : gf_odf_avc_cfg_write(svcc, dsi, dsi_size);
1409 : } else {
1410 592 : gf_odf_avc_cfg_write(avcc, dsi, dsi_size);
1411 592 : if (gf_list_count(svcc->sequenceParameterSets) || svcc->sequenceParameterSetExtensions) {
1412 20 : gf_odf_avc_cfg_write(svcc, dsi_enh, dsi_enh_size);
1413 : }
1414 : }
1415 592 : gf_list_reset(avcc->sequenceParameterSets);
1416 592 : gf_list_reset(avcc->sequenceParameterSetExtensions);
1417 592 : gf_list_reset(avcc->pictureParameterSets);
1418 592 : gf_list_reset(svcc->sequenceParameterSets);
1419 592 : gf_list_reset(svcc->sequenceParameterSetExtensions);
1420 592 : gf_list_reset(svcc->pictureParameterSets);
1421 592 : gf_odf_avc_cfg_del(avcc);
1422 592 : gf_odf_avc_cfg_del(svcc);
1423 592 : *max_width = max_w;
1424 592 : *max_height = max_h;
1425 592 : *max_enh_width = max_ew;
1426 592 : *max_enh_height = max_eh;
1427 592 : }
1428 :
1429 710594 : static void naludmx_check_pid(GF_Filter *filter, GF_NALUDmxCtx *ctx)
1430 : {
1431 : u32 w, h, ew, eh;
1432 : u8 *dsi, *dsi_enh;
1433 : u32 dsi_size, dsi_enh_size;
1434 : u32 crc_cfg, crc_cfg_enh;
1435 : GF_Fraction sar;
1436 710594 : Bool has_hevc_base = GF_TRUE;
1437 : Bool has_colr_info = GF_FALSE;
1438 :
1439 710594 : if (ctx->analyze) {
1440 714977 : if (ctx->opid && !ctx->ps_modified) return;
1441 : } else {
1442 705144 : if (!ctx->ps_modified) return;
1443 : }
1444 1069 : ctx->ps_modified = GF_FALSE;
1445 :
1446 1069 : dsi = dsi_enh = NULL;
1447 :
1448 1069 : if (!ctx->timescale) {
1449 1011 : ctx->cur_fps = ctx->fps;
1450 1011 : if (!ctx->cur_fps.num || !ctx->cur_fps.den) {
1451 523 : ctx->cur_fps.num = 25000;
1452 523 : ctx->cur_fps.den = 1000;
1453 : }
1454 : }
1455 :
1456 1069 : if (ctx->codecid==GF_CODECID_HEVC) {
1457 477 : naludmx_create_hevc_decoder_config(ctx, &dsi, &dsi_size, &dsi_enh, &dsi_enh_size, &w, &h, &ew, &eh, &sar, &has_hevc_base);
1458 592 : } else if (ctx->codecid==GF_CODECID_VVC) {
1459 0 : naludmx_create_vvc_decoder_config(ctx, &dsi, &dsi_size, &dsi_enh, &dsi_enh_size, &w, &h, &ew, &eh, &sar, &has_hevc_base);
1460 : } else {
1461 592 : naludmx_create_avc_decoder_config(ctx, &dsi, &dsi_size, &dsi_enh, &dsi_enh_size, &w, &h, &ew, &eh, &sar);
1462 : }
1463 : crc_cfg = crc_cfg_enh = 0;
1464 1069 : if (dsi) crc_cfg = gf_crc_32(dsi, dsi_size);
1465 1069 : if (dsi_enh) crc_cfg_enh = gf_crc_32(dsi_enh, dsi_enh_size);
1466 :
1467 1069 : if (!ctx->opid) {
1468 384 : ctx->opid = gf_filter_pid_new(filter);
1469 :
1470 384 : naludmx_check_dur(filter, ctx);
1471 384 : ctx->first_slice_in_au = GF_TRUE;
1472 : }
1473 :
1474 1069 : if ((ctx->crc_cfg == crc_cfg) && (ctx->crc_cfg_enh == crc_cfg_enh)
1475 2 : && (ctx->width==w) && (ctx->height==h)
1476 2 : && (ctx->sar.num * sar.den == ctx->sar.den * sar.num)
1477 : ) {
1478 2 : if (dsi) gf_free(dsi);
1479 2 : if (dsi_enh) gf_free(dsi_enh);
1480 : return;
1481 : }
1482 :
1483 1067 : naludmx_enqueue_or_dispatch(ctx, NULL, GF_TRUE);
1484 1067 : if (!ctx->analyze && (gf_list_count(ctx->pck_queue)>1)) {
1485 6 : GF_LOG(dsi_enh ? GF_LOG_DEBUG : GF_LOG_ERROR, GF_LOG_PARSER, ("[%s] xPS changed but could not flush frames before signaling state change %s\n", ctx->log_name, dsi_enh ? "- likely scalable xPS update" : "!"));
1486 : }
1487 :
1488 : //copy properties at init or reconfig
1489 1067 : gf_filter_pid_copy_properties(ctx->opid, ctx->ipid);
1490 1067 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_STREAM_TYPE, & PROP_UINT(GF_STREAM_VISUAL));
1491 1067 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_UNFRAMED, NULL);
1492 1067 : if (!gf_filter_pid_get_property(ctx->ipid, GF_PROP_PID_ID))
1493 1013 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_ID, &PROP_UINT(1));
1494 :
1495 1067 : ctx->width = w;
1496 1067 : ctx->height = h;
1497 1067 : ctx->sar = sar;
1498 1067 : ctx->crc_cfg = crc_cfg;
1499 1067 : ctx->crc_cfg_enh = crc_cfg_enh;
1500 :
1501 1067 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_WIDTH, & PROP_UINT( ctx->width));
1502 1067 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_HEIGHT, & PROP_UINT( ctx->height));
1503 1067 : if (ew && eh) {
1504 32 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_WIDTH_MAX, & PROP_UINT( ew ));
1505 32 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_HEIGHT_MAX, & PROP_UINT( eh ));
1506 : }
1507 1067 : if (ctx->sar.den)
1508 106 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_SAR, & PROP_FRAC(ctx->sar));
1509 : else
1510 961 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_SAR, NULL);
1511 :
1512 1067 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_FPS, & PROP_FRAC(ctx->cur_fps));
1513 1067 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_TIMESCALE, & PROP_UINT(ctx->timescale ? ctx->timescale : ctx->cur_fps.num));
1514 :
1515 1067 : if (ctx->explicit || !has_hevc_base) {
1516 : u32 enh_cid = GF_CODECID_SVC;
1517 137 : if (ctx->codecid==GF_CODECID_HEVC) enh_cid = GF_CODECID_LHVC;
1518 137 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_CODECID, & PROP_UINT(enh_cid));
1519 137 : if (dsi) gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_DECODER_CONFIG, &PROP_DATA_NO_COPY(dsi, dsi_size) );
1520 : } else {
1521 930 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_CODECID, & PROP_UINT(ctx->codecid));
1522 930 : if (dsi) gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_DECODER_CONFIG, &PROP_DATA_NO_COPY(dsi, dsi_size) );
1523 930 : if (dsi_enh) gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_DECODER_CONFIG_ENHANCEMENT, &PROP_DATA_NO_COPY(dsi_enh, dsi_enh_size) );
1524 : }
1525 :
1526 1067 : if (ctx->bitrate) {
1527 6 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_BITRATE, & PROP_UINT(ctx->bitrate));
1528 : }
1529 :
1530 1067 : if ((ctx->codecid==GF_CODECID_HEVC) && gf_list_count(ctx->vps) ) {
1531 477 : GF_Err e = naludmx_set_hevc_oinf(ctx, NULL);
1532 477 : if (e) {
1533 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[%s] Failed to create OINF chunk\n", ctx->log_name));
1534 : }
1535 477 : naludmx_set_hevc_linf(ctx);
1536 : }
1537 1067 : if (ctx->duration.num)
1538 1009 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_DURATION, & PROP_FRAC64(ctx->duration));
1539 :
1540 1067 : if (ctx->is_file /* && ctx->index*/) {
1541 1009 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_PLAYBACK_MODE, & PROP_UINT(GF_PLAYBACK_MODE_FASTFORWARD) );
1542 : }
1543 : //set interlaced or remove interlaced property
1544 1067 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_INTERLACED, ctx->interlaced ? & PROP_UINT(GF_TRUE) : NULL);
1545 :
1546 1067 : if (ctx->codecid==GF_CODECID_HEVC) {
1547 477 : HEVC_SPS *sps = &ctx->hevc_state->sps[ctx->hevc_state->sps_active_idx];
1548 477 : if (sps->colour_description_present_flag) {
1549 0 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_COLR_PRIMARIES, & PROP_UINT(sps->colour_primaries) );
1550 0 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_COLR_TRANSFER, & PROP_UINT(sps->transfer_characteristic) );
1551 0 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_COLR_MX, & PROP_UINT(sps->matrix_coeffs) );
1552 0 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_COLR_RANGE, & PROP_BOOL(sps->video_full_range_flag) );
1553 : has_colr_info = GF_TRUE;
1554 : }
1555 590 : } else if (ctx->codecid==GF_CODECID_VVC) {
1556 : } else {
1557 : /*use the last active SPS*/
1558 590 : if (ctx->avc_state->sps[ctx->avc_state->sps_active_idx].vui_parameters_present_flag
1559 464 : && ctx->avc_state->sps[ctx->avc_state->sps_active_idx].vui.colour_description_present_flag) {
1560 : AVC_VUI *vui = &ctx->avc_state->sps[ctx->avc_state->sps_active_idx].vui;
1561 :
1562 30 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_COLR_PRIMARIES, & PROP_UINT(vui->colour_primaries) );
1563 30 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_COLR_TRANSFER, & PROP_UINT(vui->transfer_characteristics) );
1564 30 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_COLR_MX, & PROP_UINT(vui->matrix_coefficients) );
1565 30 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_COLR_RANGE, & PROP_BOOL(vui->video_full_range_flag) );
1566 : has_colr_info = GF_TRUE;
1567 : }
1568 : }
1569 :
1570 : if (!has_colr_info) {
1571 1037 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_COLR_PRIMARIES, NULL);
1572 1037 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_COLR_TRANSFER, NULL);
1573 1037 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_COLR_MX, NULL);
1574 1037 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_COLR_RANGE, NULL);
1575 : }
1576 : }
1577 :
1578 436594 : static Bool naludmx_process_event(GF_Filter *filter, const GF_FilterEvent *evt)
1579 : {
1580 : u32 i;
1581 : u64 file_pos = 0;
1582 : GF_FilterEvent fevt;
1583 436594 : GF_NALUDmxCtx *ctx = gf_filter_get_udta(filter);
1584 :
1585 436594 : switch (evt->base.type) {
1586 407 : case GF_FEVT_PLAY:
1587 407 : if (!ctx->is_playing) {
1588 407 : ctx->is_playing = GF_TRUE;
1589 407 : ctx->cts = ctx->dts = 0;
1590 : }
1591 407 : if (! ctx->is_file) {
1592 22 : if (!ctx->initial_play_done) {
1593 22 : ctx->initial_play_done = GF_TRUE;
1594 22 : if (evt->play.start_range<0.1)
1595 : return GF_FALSE;
1596 : }
1597 0 : ctx->resume_from = 0;
1598 0 : ctx->nal_store_size = 0;
1599 0 : return GF_FALSE;
1600 : }
1601 385 : if (ctx->start_range && (ctx->index<0)) {
1602 0 : ctx->index = -ctx->index;
1603 0 : ctx->file_loaded = GF_FALSE;
1604 0 : ctx->duration.den = ctx->duration.num = 0;
1605 0 : GF_LOG(GF_LOG_INFO, GF_LOG_PARSER, ("[%s] Play request from %d, building index\n", ctx->log_name, ctx->start_range));
1606 0 : naludmx_check_dur(filter, ctx);
1607 : }
1608 385 : ctx->start_range = evt->play.start_range;
1609 385 : ctx->in_seek = GF_TRUE;
1610 :
1611 385 : if (ctx->start_range) {
1612 1 : ctx->nb_nalus = ctx->nb_i = ctx->nb_p = ctx->nb_b = ctx->nb_sp = ctx->nb_si = ctx->nb_sei = ctx->nb_idr = 0;
1613 1 : for (i=1; i<ctx->index_size; i++) {
1614 0 : if (ctx->indexes[i].duration>ctx->start_range) {
1615 0 : ctx->cts = ctx->dts = (u64) (ctx->indexes[i-1].duration * ctx->cur_fps.num);
1616 0 : file_pos = ctx->indexes[i-1].pos;
1617 0 : break;
1618 : }
1619 : }
1620 : }
1621 385 : if (!ctx->initial_play_done) {
1622 384 : ctx->initial_play_done = GF_TRUE;
1623 : //seek will not change the current source state, don't send a seek
1624 384 : if (!file_pos) {
1625 : //very short streams, input is done before we get notified for play and everything stored in memory: flush
1626 384 : if (gf_filter_pid_is_eos(ctx->ipid) && (ctx->nal_store_size)) {
1627 1 : gf_filter_post_process_task(filter);
1628 : }
1629 : return GF_TRUE;
1630 : }
1631 : }
1632 1 : ctx->nb_frames = 0;
1633 1 : ctx->nb_nalus = 0;
1634 1 : ctx->resume_from = 0;
1635 1 : ctx->nal_store_size = 0;
1636 :
1637 : //post a seek
1638 1 : GF_FEVT_INIT(fevt, GF_FEVT_SOURCE_SEEK, ctx->ipid);
1639 1 : fevt.seek.start_offset = file_pos;
1640 1 : gf_filter_pid_send_event(ctx->ipid, &fevt);
1641 :
1642 : //cancel event
1643 1 : return GF_TRUE;
1644 :
1645 68 : case GF_FEVT_STOP:
1646 : //don't cancel event
1647 68 : ctx->is_playing = GF_FALSE;
1648 68 : ctx->nal_store_size = 0;
1649 68 : ctx->resume_from = 0;
1650 68 : return GF_FALSE;
1651 :
1652 : case GF_FEVT_SET_SPEED:
1653 : //cancel event
1654 : return GF_TRUE;
1655 : default:
1656 : break;
1657 : }
1658 : //by default don't cancel event - to rework once we have downloading in place
1659 436118 : return GF_FALSE;
1660 : }
1661 :
1662 : static GFINLINE void naludmx_update_time(GF_NALUDmxCtx *ctx)
1663 : {
1664 : assert(ctx->cur_fps.num);
1665 :
1666 245303 : if (ctx->timescale) {
1667 : //very first frame, no dts diff, assume 3000/90k. It should only hurt if we have several frames packet in the first packet sent
1668 5663 : u64 dts_inc = ctx->cur_fps.den ? ctx->cur_fps.den : 3000;
1669 5663 : ctx->cts += dts_inc;
1670 5663 : ctx->dts += dts_inc;
1671 : } else {
1672 : assert(ctx->cur_fps.den);
1673 239640 : ctx->cts += ctx->cur_fps.den;
1674 239640 : ctx->dts += ctx->cur_fps.den;
1675 : }
1676 : }
1677 :
1678 11667 : static void naludmx_queue_param_set(GF_NALUDmxCtx *ctx, char *data, u32 size, u32 ps_type, s32 ps_id)
1679 : {
1680 : GF_List *list = NULL, *alt_list = NULL;
1681 : GF_NALUFFParam *sl;
1682 : u32 i, count;
1683 11667 : u32 crc = gf_crc_32(data, size);
1684 :
1685 11667 : if (ctx->codecid==GF_CODECID_HEVC) {
1686 5393 : switch (ps_type) {
1687 1795 : case GF_HEVC_NALU_VID_PARAM:
1688 1795 : if (!ctx->vps) ctx->vps = gf_list_new();
1689 1795 : list = ctx->vps;
1690 1795 : break;
1691 1799 : case GF_HEVC_NALU_SEQ_PARAM:
1692 1799 : list = ctx->sps;
1693 1799 : break;
1694 1799 : case GF_HEVC_NALU_PIC_PARAM:
1695 1799 : list = ctx->pps;
1696 1799 : break;
1697 : default:
1698 : assert(0);
1699 : return;
1700 : }
1701 6274 : } else if (ctx->codecid==GF_CODECID_VVC) {
1702 0 : switch (ps_type) {
1703 0 : case GF_VVC_NALU_VID_PARAM:
1704 0 : if (!ctx->vps) ctx->vps = gf_list_new();
1705 0 : list = ctx->vps;
1706 0 : break;
1707 0 : case GF_VVC_NALU_SEQ_PARAM:
1708 0 : list = ctx->sps;
1709 0 : break;
1710 0 : case GF_VVC_NALU_PIC_PARAM:
1711 0 : list = ctx->pps;
1712 0 : break;
1713 0 : case GF_VVC_NALU_DEC_PARAM:
1714 0 : if (!ctx->vvc_dci) ctx->vvc_dci = gf_list_new();
1715 0 : list = ctx->vvc_dci;
1716 0 : break;
1717 0 : case GF_VVC_NALU_APS_PREFIX:
1718 0 : if (!ctx->vvc_aps_pre) ctx->vvc_aps_pre = gf_list_new();
1719 0 : list = ctx->vvc_aps_pre;
1720 0 : break;
1721 : default:
1722 : assert(0);
1723 : return;
1724 : }
1725 : } else {
1726 6274 : switch (ps_type) {
1727 2236 : case GF_AVC_NALU_SVC_SUBSEQ_PARAM:
1728 : case GF_AVC_NALU_SEQ_PARAM:
1729 2236 : list = ctx->sps;
1730 2236 : break;
1731 4038 : case GF_AVC_NALU_PIC_PARAM:
1732 4038 : list = ctx->pps;
1733 4038 : alt_list = ctx->pps_svc;
1734 4038 : break;
1735 0 : case GF_AVC_NALU_SEQ_PARAM_EXT:
1736 0 : if (!ctx->sps_ext) ctx->sps_ext = gf_list_new();
1737 0 : list = ctx->sps_ext;
1738 0 : break;
1739 : default:
1740 : assert(0);
1741 : return;
1742 : }
1743 : }
1744 : sl = NULL;
1745 11667 : count = gf_list_count(list);
1746 11805 : for (i=0; i<count; i++) {
1747 10797 : sl = gf_list_get(list, i);
1748 10797 : if (sl->id != ps_id) {
1749 : sl = NULL;
1750 138 : continue;
1751 : }
1752 : //same ID, same CRC, we don't change our state
1753 10659 : if (sl->crc == crc) return;
1754 : break;
1755 : }
1756 : //handle alt PPS list for SVC
1757 1044 : if (!sl && alt_list) {
1758 27 : count = gf_list_count(alt_list);
1759 35 : for (i=0; i<count; i++) {
1760 35 : sl = gf_list_get(alt_list, i);
1761 35 : if (sl->id != ps_id) {
1762 : sl = NULL;
1763 8 : continue;
1764 : }
1765 : //same ID, same CRC, we don't change our state
1766 27 : if (sl->crc == crc) return;
1767 : break;
1768 : }
1769 : }
1770 :
1771 1017 : if (sl) {
1772 : //otherwise we keep this new param set
1773 36 : sl->data = gf_realloc(sl->data, size);
1774 : memcpy(sl->data, data, size);
1775 36 : sl->size = size;
1776 36 : sl->crc = crc;
1777 36 : ctx->ps_modified = GF_TRUE;
1778 36 : return;
1779 : }
1780 : //TODO we might want to purge the list after a while !!
1781 :
1782 981 : GF_SAFEALLOC(sl, GF_NALUFFParam);
1783 981 : if (!sl) return;
1784 981 : sl->data = gf_malloc(sizeof(char) * size);
1785 981 : if (!sl->data) {
1786 0 : gf_free(sl);
1787 0 : return;
1788 : }
1789 : memcpy(sl->data, data, size);
1790 981 : sl->size = size;
1791 981 : sl->id = ps_id;
1792 981 : sl->crc = crc;
1793 :
1794 981 : ctx->ps_modified = GF_TRUE;
1795 981 : gf_list_add(list, sl);
1796 : }
1797 :
1798 246790 : static void naludmx_finalize_au_flags(GF_NALUDmxCtx *ctx)
1799 : {
1800 : u64 ts;
1801 : Bool is_rap = GF_FALSE;
1802 :
1803 246790 : if (!ctx->first_pck_in_au)
1804 : return;
1805 245237 : if (ctx->au_sap) {
1806 9200 : gf_filter_pck_set_sap(ctx->first_pck_in_au, ctx->au_sap);
1807 9200 : if (ctx->au_sap == GF_FILTER_SAP_1) {
1808 8894 : ctx->dts_last_IDR = gf_filter_pck_get_dts(ctx->first_pck_in_au);
1809 8894 : if (ctx->is_paff)
1810 0 : ctx->dts_last_IDR *= 2;
1811 : }
1812 9200 : if (ctx->au_sap <= GF_FILTER_SAP_3) {
1813 : is_rap = GF_TRUE;
1814 : }
1815 : }
1816 236037 : else if (ctx->has_islice && ctx->force_sync && (ctx->sei_recovery_frame_count==0)) {
1817 0 : gf_filter_pck_set_sap(ctx->first_pck_in_au, GF_FILTER_SAP_1);
1818 0 : if (!ctx->use_opengop_gdr) {
1819 0 : ctx->use_opengop_gdr = 1;
1820 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[%s] Forcing non-IDR samples with I slices to be marked as sync points - resulting file will not be ISOBMFF conformant\n", ctx->log_name));
1821 : }
1822 : is_rap = GF_TRUE;
1823 : }
1824 : /*set roll info sampleGroups info*/
1825 236037 : else if (!ctx->au_sap && ( (ctx->sei_recovery_frame_count >= 0) || ctx->has_islice) ) {
1826 : /*generic GDR*/
1827 330 : if (ctx->sei_recovery_frame_count > 0) {
1828 93 : if (!ctx->use_opengop_gdr) ctx->use_opengop_gdr = 1;
1829 93 : gf_filter_pck_set_sap(ctx->first_pck_in_au, GF_FILTER_SAP_4);
1830 93 : gf_filter_pck_set_roll_info(ctx->first_pck_in_au, ctx->sei_recovery_frame_count);
1831 : }
1832 : /*open-GOP*/
1833 237 : else if ((ctx->sei_recovery_frame_count == 0) && ctx->has_islice) {
1834 227 : if (!ctx->use_opengop_gdr) ctx->use_opengop_gdr = 2;
1835 227 : gf_filter_pck_set_sap(ctx->first_pck_in_au, GF_FILTER_SAP_3);
1836 : is_rap = GF_TRUE;
1837 : }
1838 : }
1839 245237 : if (ctx->is_paff) {
1840 458 : gf_filter_pck_set_interlaced(ctx->first_pck_in_au, ctx->bottom_field_flag ? 2 : 1);
1841 : }
1842 :
1843 : //if TS is set, the packet was the first in AU in the input timed packet (eg PES), we reuse the input timing
1844 245237 : ts = gf_filter_pck_get_cts(ctx->first_pck_in_au);
1845 245237 : if (ts == GF_FILTER_NO_TS) {
1846 : /*we store the POC (last POC minus the poc shift) as the CTS offset and re-update the CTS when dispatching*/
1847 : assert(ctx->last_poc >= ctx->poc_shift);
1848 239576 : gf_filter_pck_set_cts(ctx->first_pck_in_au, CTS_POC_OFFSET_SAFETY + ctx->last_poc - ctx->poc_shift);
1849 : //we use the carousel flag temporarly to indicate the cts must be recomputed
1850 239576 : gf_filter_pck_set_carousel_version(ctx->first_pck_in_au, 1);
1851 : }
1852 :
1853 245237 : if (ctx->subsamp_buffer_size) {
1854 762 : gf_filter_pck_set_property(ctx->first_pck_in_au, GF_PROP_PCK_SUBS, &PROP_DATA(ctx->subsamp_buffer, ctx->subsamp_buffer_size) );
1855 762 : ctx->subsamp_buffer_size = 0;
1856 762 : ctx->subs_mapped_bytes = 0;
1857 : }
1858 245237 : if (ctx->deps) {
1859 : u8 flags = 0;
1860 : //dependsOn
1861 3346 : flags = (is_rap) ? 2 : 1;
1862 3346 : flags <<= 2;
1863 : //dependedOn
1864 3346 : flags |= ctx->has_ref_slices ? 1 : 2;
1865 3346 : flags <<= 2;
1866 : //hasRedundant
1867 3346 : flags |= ctx->has_redundant ? 1 : 2;
1868 3346 : gf_filter_pck_set_dependency_flags(ctx->first_pck_in_au, flags);
1869 : }
1870 245237 : ctx->has_ref_slices = GF_FALSE;
1871 245237 : ctx->has_redundant = GF_FALSE;
1872 :
1873 : //if we reuse input packets timing, we can dispatch asap.
1874 : //otherwise if poc probe is done (we know the min_poc_diff between images) and we are not in strict mode, dispatch asap
1875 : //otherwise we will need to wait for the next ref frame to make sure we know all pocs ...
1876 245237 : if (ctx->timescale || (!ctx->strict_poc && ctx->poc_probe_done) )
1877 235822 : naludmx_enqueue_or_dispatch(ctx, NULL, GF_TRUE);
1878 :
1879 245237 : ctx->first_pck_in_au = NULL;
1880 : }
1881 :
1882 665557 : static void naludmx_update_nalu_maxsize(GF_NALUDmxCtx *ctx, u32 size)
1883 : {
1884 665557 : if (ctx->max_nalu_size < size) {
1885 2635 : ctx->max_nalu_size = size;
1886 2635 : if (size > ctx->max_nalu_size_allowed) {
1887 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[%s] nal size %d larger than max allowed size %d - change import settings\n", ctx->log_name, size, ctx->max_nalu_size_allowed ));
1888 : }
1889 : }
1890 665557 : }
1891 :
1892 :
1893 0 : GF_Err naludmx_realloc_last_pck(GF_NALUDmxCtx *ctx, u32 nb_bytes_to_add, u8 **data_ptr)
1894 : {
1895 : GF_Err e;
1896 : u8 *pck_data;
1897 : u32 full_size;
1898 0 : GF_FilterPacket *pck = gf_list_last(ctx->pck_queue);
1899 0 : *data_ptr = NULL;
1900 0 : if (!pck) {
1901 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[%s] attempt to reallocate a non-existing packet!\n", ctx->log_name));
1902 : return GF_SERVICE_ERROR;
1903 : }
1904 0 : e = gf_filter_pck_expand(pck, nb_bytes_to_add, &pck_data, data_ptr, &full_size);
1905 0 : if (e) {
1906 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[%s] Failed to reallocate packet buffer: %s\n", ctx->log_name, gf_error_to_string(e) ));
1907 : return e;
1908 : }
1909 : assert(ctx->bs_w);
1910 : //rewrite NALU size length
1911 0 : full_size -= ctx->nal_length;
1912 0 : gf_bs_reassign_buffer(ctx->bs_w, pck_data, ctx->nal_length);
1913 0 : gf_bs_write_int(ctx->bs_w, full_size, 8*ctx->nal_length);
1914 0 : naludmx_update_nalu_maxsize(ctx, full_size);
1915 : //rewrite subsample size
1916 0 : if (ctx->subsamples) {
1917 : assert(ctx->subsamp_buffer_size>=14);
1918 : //reassign to beginning of size field (after first u32 flags)
1919 0 : gf_bs_reassign_buffer(ctx->bs_w, ctx->subsamp_buffer + ctx->subsamp_buffer_size-14 + 4, 14 - 4);
1920 0 : gf_bs_write_u32(ctx->bs_w, full_size + ctx->nal_length);
1921 : }
1922 : return GF_OK;
1923 : }
1924 :
1925 665557 : GF_FilterPacket *naludmx_start_nalu(GF_NALUDmxCtx *ctx, u32 nal_size, Bool skip_nal_field, Bool *au_start, u8 **pck_data)
1926 : {
1927 665557 : GF_FilterPacket *dst_pck = gf_filter_pck_new_alloc(ctx->opid, nal_size + (skip_nal_field ? 0 : ctx->nal_length), pck_data);
1928 665557 : if (!dst_pck) return NULL;
1929 :
1930 665557 : if (!skip_nal_field) {
1931 659938 : if (!ctx->bs_w) ctx->bs_w = gf_bs_new(*pck_data, ctx->nal_length, GF_BITSTREAM_WRITE);
1932 659910 : else gf_bs_reassign_buffer(ctx->bs_w, *pck_data, ctx->nal_length);
1933 659938 : gf_bs_write_int(ctx->bs_w, nal_size, 8*ctx->nal_length);
1934 : }
1935 :
1936 665557 : if (*au_start) {
1937 245303 : ctx->first_pck_in_au = dst_pck;
1938 245303 : if (ctx->src_pck) gf_filter_pck_merge_properties(ctx->src_pck, dst_pck);
1939 :
1940 245303 : gf_filter_pck_set_framing(dst_pck, GF_TRUE, GF_FALSE);
1941 : //we reuse the timing of the input packet for the first nal of the first frame starting in this packet
1942 245303 : if (ctx->input_is_au_start) {
1943 5607 : ctx->input_is_au_start = GF_FALSE;
1944 5607 : gf_filter_pck_set_dts(dst_pck, ctx->dts);
1945 5607 : gf_filter_pck_set_cts(dst_pck, ctx->cts);
1946 : } else {
1947 : //we don't set the CTS, it will be set once we detect frame end
1948 239696 : gf_filter_pck_set_dts(dst_pck, ctx->dts);
1949 : }
1950 : //we use the carousel flag temporarly to indicate the cts must be recomputed
1951 245303 : gf_filter_pck_set_carousel_version(dst_pck, ctx->timescale ? 0 : 1);
1952 :
1953 245303 : gf_filter_pck_set_duration(dst_pck, ctx->pck_duration ? ctx->pck_duration : ctx->cur_fps.den);
1954 245303 : if (ctx->in_seek) gf_filter_pck_set_seek_flag(dst_pck, GF_TRUE);
1955 :
1956 : naludmx_update_time(ctx);
1957 245303 : *au_start = GF_FALSE;
1958 245303 : ctx->nb_frames++;
1959 : } else {
1960 420254 : gf_filter_pck_set_framing(dst_pck, GF_FALSE, GF_FALSE);
1961 : }
1962 665557 : naludmx_update_nalu_maxsize(ctx, nal_size);
1963 :
1964 665557 : naludmx_enqueue_or_dispatch(ctx, dst_pck, GF_FALSE);
1965 :
1966 665557 : return dst_pck;
1967 : }
1968 :
1969 1523 : void naludmx_add_subsample(GF_NALUDmxCtx *ctx, u32 subs_size, u8 subs_priority, u32 subs_reserved)
1970 : {
1971 1523 : if (ctx->subsamp_buffer_alloc < ctx->subsamp_buffer_size+14 ) {
1972 2 : ctx->subsamp_buffer_alloc = ctx->subsamp_buffer_size+14;
1973 2 : ctx->subsamp_buffer = gf_realloc(ctx->subsamp_buffer, ctx->subsamp_buffer_alloc);
1974 : }
1975 : assert(ctx->subsamp_buffer);
1976 1523 : gf_bs_reassign_buffer(ctx->bs_w, ctx->subsamp_buffer + ctx->subsamp_buffer_size, 14);
1977 1523 : gf_bs_write_u32(ctx->bs_w, 0); //flags
1978 1523 : gf_bs_write_u32(ctx->bs_w, subs_size + ctx->nal_length);
1979 1523 : gf_bs_write_u32(ctx->bs_w, subs_reserved); //reserved
1980 1523 : gf_bs_write_u8(ctx->bs_w, subs_priority); //priority
1981 1523 : gf_bs_write_u8(ctx->bs_w, 0); //discardable - todo
1982 1523 : ctx->subsamp_buffer_size += 14;
1983 1523 : ctx->subs_mapped_bytes += subs_size + ctx->nal_length;
1984 1523 : }
1985 :
1986 521703 : static s32 naludmx_parse_nal_hevc(GF_NALUDmxCtx *ctx, char *data, u32 size, Bool *skip_nal, Bool *is_slice, Bool *is_islice)
1987 : {
1988 : #ifdef GPAC_DISABLE_HEVC
1989 : return -1;
1990 : #else
1991 : s32 ps_idx = 0;
1992 : s32 res;
1993 : u8 nal_unit_type, temporal_id, layer_id;
1994 521703 : *skip_nal = GF_FALSE;
1995 :
1996 521703 : gf_bs_reassign_buffer(ctx->bs_r, data, size);
1997 521703 : res = gf_hevc_parse_nalu_bs(ctx->bs_r, ctx->hevc_state, &nal_unit_type, &temporal_id, &layer_id);
1998 521703 : ctx->nb_nalus++;
1999 :
2000 521703 : if (res < 0) {
2001 0 : if (res == -1) {
2002 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[%s] Warning: Error parsing NAL unit\n", ctx->log_name));
2003 : }
2004 0 : *skip_nal = GF_TRUE;
2005 : }
2006 :
2007 521703 : if (layer_id && ctx->nosvc) {
2008 0 : *skip_nal = GF_TRUE;
2009 0 : return 0;
2010 : }
2011 :
2012 521703 : switch (nal_unit_type) {
2013 1795 : case GF_HEVC_NALU_VID_PARAM:
2014 1795 : if (ctx->novpsext) {
2015 : //this may modify nal_size, but we don't use it for bitstream reading
2016 11 : ps_idx = gf_hevc_read_vps_ex(data, &size, ctx->hevc_state, GF_TRUE);
2017 : } else {
2018 1784 : ps_idx = ctx->hevc_state->last_parsed_vps_id;
2019 : }
2020 1795 : if (ps_idx<0) {
2021 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[%s] Error parsing Video Param Set\n", ctx->log_name));
2022 : } else {
2023 1795 : naludmx_queue_param_set(ctx, data, size, GF_HEVC_NALU_VID_PARAM, ps_idx);
2024 : }
2025 1795 : *skip_nal = GF_TRUE;
2026 1795 : break;
2027 1799 : case GF_HEVC_NALU_SEQ_PARAM:
2028 1799 : ps_idx = ctx->hevc_state->last_parsed_sps_id;
2029 1799 : if (ps_idx<0) {
2030 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[%s] Error parsing Sequence Param Set\n", ctx->log_name));
2031 : } else {
2032 1799 : naludmx_queue_param_set(ctx, data, size, GF_HEVC_NALU_SEQ_PARAM, ps_idx);
2033 : }
2034 1799 : *skip_nal = GF_TRUE;
2035 1799 : break;
2036 1799 : case GF_HEVC_NALU_PIC_PARAM:
2037 1799 : ps_idx = ctx->hevc_state->last_parsed_pps_id;
2038 1799 : if (ps_idx<0) {
2039 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[%s] Error parsing Picture Param Set\n", ctx->log_name));
2040 : } else {
2041 1799 : naludmx_queue_param_set(ctx, data, size, GF_HEVC_NALU_PIC_PARAM, ps_idx);
2042 : }
2043 1799 : *skip_nal = GF_TRUE;
2044 1799 : break;
2045 2099 : case GF_HEVC_NALU_SEI_PREFIX:
2046 2099 : gf_hevc_parse_sei(data, size, ctx->hevc_state);
2047 2099 : if (!ctx->nosei) {
2048 2099 : ctx->nb_sei++;
2049 :
2050 2099 : if (ctx->sei_buffer_alloc < ctx->sei_buffer_size + size + ctx->nal_length) {
2051 127 : ctx->sei_buffer_alloc = ctx->sei_buffer_size + size + ctx->nal_length;
2052 127 : ctx->sei_buffer = gf_realloc(ctx->sei_buffer, ctx->sei_buffer_alloc);
2053 : }
2054 :
2055 2099 : if (!ctx->bs_w) ctx->bs_w = gf_bs_new(ctx->sei_buffer + ctx->sei_buffer_size, ctx->nal_length + size, GF_BITSTREAM_WRITE);
2056 1982 : else gf_bs_reassign_buffer(ctx->bs_w, ctx->sei_buffer + ctx->sei_buffer_size, ctx->nal_length + size);
2057 2099 : gf_bs_write_int(ctx->bs_w, size, 8*ctx->nal_length);
2058 2099 : memcpy(ctx->sei_buffer + ctx->sei_buffer_size + ctx->nal_length, data, size);
2059 2099 : ctx->sei_buffer_size += size + ctx->nal_length;
2060 : } else {
2061 0 : ctx->nb_nalus--;
2062 : }
2063 2099 : *skip_nal = GF_TRUE;
2064 2099 : break;
2065 64126 : case GF_HEVC_NALU_SEI_SUFFIX:
2066 64126 : if (! ctx->is_playing) return 0;
2067 64126 : if (ctx->nosei) {
2068 0 : *skip_nal = GF_TRUE;
2069 0 : ctx->nb_nalus--;
2070 : } else {
2071 64126 : ctx->nb_sei++;
2072 : }
2073 : break;
2074 :
2075 : /*slice_segment_layer_rbsp*/
2076 423222 : case GF_HEVC_NALU_SLICE_STSA_N:
2077 : case GF_HEVC_NALU_SLICE_STSA_R:
2078 : case GF_HEVC_NALU_SLICE_RADL_R:
2079 : case GF_HEVC_NALU_SLICE_RASL_R:
2080 : case GF_HEVC_NALU_SLICE_RADL_N:
2081 : case GF_HEVC_NALU_SLICE_RASL_N:
2082 : case GF_HEVC_NALU_SLICE_TRAIL_N:
2083 : case GF_HEVC_NALU_SLICE_TRAIL_R:
2084 : case GF_HEVC_NALU_SLICE_TSA_N:
2085 : case GF_HEVC_NALU_SLICE_TSA_R:
2086 : case GF_HEVC_NALU_SLICE_BLA_W_LP:
2087 : case GF_HEVC_NALU_SLICE_BLA_W_DLP:
2088 : case GF_HEVC_NALU_SLICE_BLA_N_LP:
2089 : case GF_HEVC_NALU_SLICE_IDR_W_DLP:
2090 : case GF_HEVC_NALU_SLICE_IDR_N_LP:
2091 : case GF_HEVC_NALU_SLICE_CRA:
2092 423222 : if (! ctx->is_playing) return 0;
2093 423097 : *is_slice = GF_TRUE;
2094 423097 : if (! *skip_nal) {
2095 423097 : switch (ctx->hevc_state->s_info.slice_type) {
2096 384137 : case GF_HEVC_SLICE_TYPE_P:
2097 384137 : if (layer_id) ctx->nb_e_p++;
2098 383873 : else ctx->nb_p++;
2099 : break;
2100 17318 : case GF_HEVC_SLICE_TYPE_I:
2101 17318 : if (layer_id) ctx->nb_e_i++;
2102 17318 : else ctx->nb_i++;
2103 17318 : *is_islice = GF_TRUE;
2104 17318 : break;
2105 21642 : case GF_HEVC_SLICE_TYPE_B:
2106 21642 : if (layer_id) ctx->nb_e_b++;
2107 18117 : else ctx->nb_b++;
2108 : break;
2109 : }
2110 : }
2111 : break;
2112 :
2113 26863 : case GF_HEVC_NALU_ACCESS_UNIT:
2114 26863 : ctx->nb_aud++;
2115 26863 : if (!ctx->audelim) {
2116 26359 : *skip_nal = GF_TRUE;
2117 504 : } else if (!ctx->opid) {
2118 2 : ctx->has_initial_aud = GF_TRUE;
2119 2 : memcpy(ctx->init_aud, data, 3);
2120 : }
2121 : break;
2122 : /*remove*/
2123 0 : case GF_HEVC_NALU_FILLER_DATA:
2124 : case GF_HEVC_NALU_END_OF_SEQ:
2125 : case GF_HEVC_NALU_END_OF_STREAM:
2126 0 : *skip_nal = GF_TRUE;
2127 0 : break;
2128 :
2129 : //parsing is partial, see https://github.com/DolbyLaboratories/dlb_mp4base/blob/70a2e1d4d99a8439b7b8087bf50dd503eeea2291/src/esparser/parser_hevc.c#L1233
2130 0 : case GF_HEVC_NALU_DV_RPU:
2131 0 : ctx->hevc_state->dv_rpu = GF_TRUE;
2132 0 : break;
2133 0 : case GF_HEVC_NALU_DV_EL:
2134 0 : ctx->hevc_state->dv_el = GF_TRUE;
2135 0 : break;
2136 :
2137 0 : default:
2138 0 : if (! ctx->is_playing) return 0;
2139 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[%s] NAL Unit type %d not handled - adding\n", ctx->log_name, nal_unit_type));
2140 : break;
2141 : }
2142 521578 : if (*skip_nal) return res;
2143 :
2144 487727 : ctx->linf[layer_id].layer_id_plus_one = layer_id + 1;
2145 487727 : if (! ctx->linf[layer_id].max_temporal_id ) ctx->linf[layer_id].max_temporal_id = temporal_id;
2146 14964 : else if (ctx->linf[layer_id].max_temporal_id < temporal_id) ctx->linf[layer_id].max_temporal_id = temporal_id;
2147 :
2148 487727 : if (! ctx->linf[layer_id].min_temporal_id ) ctx->linf[layer_id].min_temporal_id = temporal_id;
2149 9744 : else if (ctx->linf[layer_id].min_temporal_id > temporal_id) ctx->linf[layer_id].min_temporal_id = temporal_id;
2150 :
2151 487727 : if (ctx->max_temporal_id[layer_id] < temporal_id)
2152 24 : ctx->max_temporal_id[layer_id] = temporal_id;
2153 487727 : if (ctx->min_layer_id > layer_id) ctx->min_layer_id = layer_id;
2154 : return res;
2155 : #endif // GPAC_DISABLE_HEVC
2156 : }
2157 :
2158 :
2159 0 : static s32 naludmx_parse_nal_vvc(GF_NALUDmxCtx *ctx, char *data, u32 size, Bool *skip_nal, Bool *is_slice, Bool *is_islice)
2160 : {
2161 : s32 ps_idx = 0;
2162 : s32 res;
2163 : u8 nal_unit_type, temporal_id, layer_id;
2164 0 : *skip_nal = GF_FALSE;
2165 :
2166 0 : gf_bs_reassign_buffer(ctx->bs_r, data, size);
2167 0 : res = gf_media_vvc_parse_nalu_bs(ctx->bs_r, ctx->vvc_state, &nal_unit_type, &temporal_id, &layer_id);
2168 0 : ctx->nb_nalus++;
2169 :
2170 0 : if (res < 0) {
2171 0 : if (res == -1) {
2172 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[%s] Warning: Error parsing NAL unit\n", ctx->log_name));
2173 : }
2174 0 : *skip_nal = GF_TRUE;
2175 : }
2176 :
2177 0 : if (layer_id && ctx->nosvc) {
2178 0 : *skip_nal = GF_TRUE;
2179 0 : return 0;
2180 : }
2181 :
2182 0 : switch (nal_unit_type) {
2183 0 : case GF_VVC_NALU_VID_PARAM:
2184 0 : if (ctx->novpsext) {
2185 : //this may modify nal_size, but we don't use it for bitstream reading
2186 : // ps_idx = gf_hevc_read_vps_ex(data, &size, ctx->hevc_state, GF_TRUE);
2187 0 : ps_idx = ctx->vvc_state->last_parsed_vps_id;
2188 : } else {
2189 0 : ps_idx = ctx->vvc_state->last_parsed_vps_id;
2190 : }
2191 0 : if (ps_idx<0) {
2192 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[%s] Error parsing Video Param Set\n", ctx->log_name));
2193 : } else {
2194 0 : naludmx_queue_param_set(ctx, data, size, GF_VVC_NALU_VID_PARAM, ps_idx);
2195 : }
2196 0 : *skip_nal = GF_TRUE;
2197 0 : break;
2198 0 : case GF_VVC_NALU_SEQ_PARAM:
2199 0 : ps_idx = ctx->vvc_state->last_parsed_sps_id;
2200 0 : if (ps_idx<0) {
2201 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[%s] Error parsing Sequence Param Set\n", ctx->log_name));
2202 : } else {
2203 0 : naludmx_queue_param_set(ctx, data, size, GF_VVC_NALU_SEQ_PARAM, ps_idx);
2204 : }
2205 0 : *skip_nal = GF_TRUE;
2206 0 : break;
2207 0 : case GF_VVC_NALU_PIC_PARAM:
2208 0 : ps_idx = ctx->vvc_state->last_parsed_pps_id;
2209 0 : if (ps_idx<0) {
2210 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[%s] Error parsing Picture Param Set\n", ctx->log_name));
2211 : } else {
2212 0 : naludmx_queue_param_set(ctx, data, size, GF_VVC_NALU_PIC_PARAM, ps_idx);
2213 : }
2214 0 : *skip_nal = GF_TRUE;
2215 0 : break;
2216 0 : case GF_VVC_NALU_DEC_PARAM:
2217 : ps_idx = 0;
2218 0 : naludmx_queue_param_set(ctx, data, size, GF_VVC_NALU_DEC_PARAM, ps_idx);
2219 0 : *skip_nal = GF_TRUE;
2220 0 : break;
2221 : case GF_VVC_NALU_APS_PREFIX:
2222 : //for now we keep APS in the stream
2223 : #if 0
2224 : ps_idx = ctx->vvc_state->last_parsed_aps_id;
2225 : if (ps_idx<0) {
2226 : GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[%s] Error parsing Decoder Param Set\n", ctx->log_name));
2227 : } else {
2228 : naludmx_queue_param_set(ctx, data, size, GF_VVC_NALU_APS_PREFIX, ps_idx);
2229 : }
2230 : *skip_nal = GF_TRUE;
2231 : #endif
2232 : break;
2233 0 : case GF_VVC_NALU_SEI_PREFIX:
2234 0 : gf_media_vvc_parse_sei(data, size, ctx->vvc_state);
2235 0 : if (!ctx->nosei) {
2236 0 : ctx->nb_sei++;
2237 :
2238 0 : if (ctx->sei_buffer_alloc < ctx->sei_buffer_size + size + ctx->nal_length) {
2239 0 : ctx->sei_buffer_alloc = ctx->sei_buffer_size + size + ctx->nal_length;
2240 0 : ctx->sei_buffer = gf_realloc(ctx->sei_buffer, ctx->sei_buffer_alloc);
2241 : }
2242 :
2243 0 : if (!ctx->bs_w) ctx->bs_w = gf_bs_new(ctx->sei_buffer + ctx->sei_buffer_size, ctx->nal_length + size, GF_BITSTREAM_WRITE);
2244 0 : else gf_bs_reassign_buffer(ctx->bs_w, ctx->sei_buffer + ctx->sei_buffer_size, ctx->nal_length + size);
2245 0 : gf_bs_write_int(ctx->bs_w, size, 8*ctx->nal_length);
2246 0 : memcpy(ctx->sei_buffer + ctx->sei_buffer_size + ctx->nal_length, data, size);
2247 0 : ctx->sei_buffer_size += size + ctx->nal_length;
2248 : } else {
2249 0 : ctx->nb_nalus--;
2250 : }
2251 0 : *skip_nal = GF_TRUE;
2252 0 : break;
2253 0 : case GF_VVC_NALU_SEI_SUFFIX:
2254 0 : if (! ctx->is_playing) return 0;
2255 0 : if (ctx->nosei) {
2256 0 : *skip_nal = GF_TRUE;
2257 0 : ctx->nb_nalus--;
2258 : } else {
2259 0 : ctx->nb_sei++;
2260 : }
2261 : break;
2262 :
2263 0 : case GF_VVC_NALU_PIC_HEADER:
2264 0 : if (! ctx->is_playing) return 0;
2265 : break;
2266 :
2267 : /*slice_segment_layer_rbsp*/
2268 0 : case GF_VVC_NALU_SLICE_TRAIL:
2269 : case GF_VVC_NALU_SLICE_STSA:
2270 : case GF_VVC_NALU_SLICE_RADL:
2271 : case GF_VVC_NALU_SLICE_RASL:
2272 : case GF_VVC_NALU_SLICE_IDR_W_RADL:
2273 : case GF_VVC_NALU_SLICE_IDR_N_LP:
2274 : case GF_VVC_NALU_SLICE_CRA:
2275 : case GF_VVC_NALU_SLICE_GDR:
2276 0 : if (! ctx->is_playing) return 0;
2277 0 : *is_slice = GF_TRUE;
2278 0 : if (! *skip_nal) {
2279 0 : switch (ctx->vvc_state->s_info.slice_type) {
2280 0 : case GF_VVC_SLICE_TYPE_P:
2281 0 : if (layer_id) ctx->nb_e_p++;
2282 0 : else ctx->nb_p++;
2283 : break;
2284 0 : case GF_VVC_SLICE_TYPE_I:
2285 0 : if (layer_id) ctx->nb_e_i++;
2286 0 : else ctx->nb_i++;
2287 0 : *is_islice = GF_TRUE;
2288 0 : break;
2289 0 : case GF_VVC_SLICE_TYPE_B:
2290 0 : if (layer_id) ctx->nb_e_b++;
2291 0 : else ctx->nb_b++;
2292 : break;
2293 0 : case GF_VVC_SLICE_TYPE_UNKNOWN:
2294 0 : ctx->vvc_no_stats = GF_TRUE;
2295 0 : break;
2296 : }
2297 : }
2298 : break;
2299 :
2300 0 : case GF_VVC_NALU_ACCESS_UNIT:
2301 0 : ctx->nb_aud++;
2302 : //no skip AUD in VVC
2303 :
2304 0 : if (!ctx->opid) {
2305 0 : ctx->has_initial_aud = GF_TRUE;
2306 0 : memcpy(ctx->init_aud, data, 3);
2307 : }
2308 : break;
2309 : /*remove*/
2310 0 : case GF_VVC_NALU_FILLER_DATA:
2311 : case GF_VVC_NALU_END_OF_SEQ:
2312 : case GF_VVC_NALU_END_OF_STREAM:
2313 0 : *skip_nal = GF_TRUE;
2314 0 : break;
2315 :
2316 0 : case GF_VVC_NALU_OPI:
2317 0 : if (! ctx->is_playing) return 0;
2318 : break;
2319 :
2320 0 : default:
2321 0 : if (! ctx->is_playing) return 0;
2322 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[%s] NAL Unit type %d not handled - adding\n", ctx->log_name, nal_unit_type));
2323 : break;
2324 : }
2325 0 : if (*skip_nal) return res;
2326 :
2327 0 : ctx->linf[layer_id].layer_id_plus_one = layer_id + 1;
2328 0 : if (! ctx->linf[layer_id].max_temporal_id ) ctx->linf[layer_id].max_temporal_id = temporal_id;
2329 0 : else if (ctx->linf[layer_id].max_temporal_id < temporal_id) ctx->linf[layer_id].max_temporal_id = temporal_id;
2330 :
2331 0 : if (! ctx->linf[layer_id].min_temporal_id ) ctx->linf[layer_id].min_temporal_id = temporal_id;
2332 0 : else if (ctx->linf[layer_id].min_temporal_id > temporal_id) ctx->linf[layer_id].min_temporal_id = temporal_id;
2333 :
2334 0 : if (ctx->max_temporal_id[layer_id] < temporal_id)
2335 0 : ctx->max_temporal_id[layer_id] = temporal_id;
2336 0 : if (ctx->min_layer_id > layer_id) ctx->min_layer_id = layer_id;
2337 : return res;
2338 : }
2339 :
2340 188891 : static s32 naludmx_parse_nal_avc(GF_NALUDmxCtx *ctx, char *data, u32 size, u32 nal_type, Bool *skip_nal, Bool *is_slice, Bool *is_islice)
2341 : {
2342 : s32 ps_idx = 0;
2343 : s32 res = 0;
2344 :
2345 188891 : gf_bs_reassign_buffer(ctx->bs_r, data, size);
2346 188891 : *skip_nal = GF_FALSE;
2347 188891 : res = gf_avc_parse_nalu(ctx->bs_r, ctx->avc_state);
2348 188891 : if (res < 0) {
2349 26 : if (res == -1) {
2350 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[%s] Warning: Error parsing NAL unit\n", ctx->log_name));
2351 : }
2352 26 : *skip_nal = GF_TRUE;
2353 : }
2354 188891 : ctx->nb_nalus++;
2355 :
2356 188891 : switch (nal_type) {
2357 2236 : case GF_AVC_NALU_SVC_SUBSEQ_PARAM:
2358 : case GF_AVC_NALU_SEQ_PARAM:
2359 2236 : ps_idx = ctx->avc_state->last_ps_idx;
2360 2236 : if (ps_idx<0) {
2361 0 : if (ctx->avc_state->sps[0].profile_idc) {
2362 0 : GF_LOG(ctx->avc_state->sps[0].profile_idc ? GF_LOG_WARNING : GF_LOG_ERROR, GF_LOG_PARSER, ("[%s] Error parsing Sequence Param Set\n", ctx->log_name));
2363 : }
2364 : } else {
2365 2236 : naludmx_queue_param_set(ctx, data, size, GF_AVC_NALU_SEQ_PARAM, ps_idx);
2366 : }
2367 2236 : *skip_nal = GF_TRUE;
2368 2236 : return 0;
2369 :
2370 4038 : case GF_AVC_NALU_PIC_PARAM:
2371 4038 : ps_idx = ctx->avc_state->last_ps_idx;
2372 4038 : if (ps_idx<0) {
2373 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[%s] Error parsing Picture Param Set\n", ctx->log_name));
2374 : } else {
2375 4038 : naludmx_queue_param_set(ctx, data, size, GF_AVC_NALU_PIC_PARAM, ps_idx);
2376 : }
2377 4038 : *skip_nal = GF_TRUE;
2378 4038 : return 0;
2379 :
2380 0 : case GF_AVC_NALU_SEQ_PARAM_EXT:
2381 0 : ps_idx = ctx->avc_state->last_ps_idx;
2382 0 : if (ps_idx<0) {
2383 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[%s] Error parsing Sequence Param Set Extension\n", ctx->log_name));
2384 : } else {
2385 0 : naludmx_queue_param_set(ctx, data, size, GF_AVC_NALU_SEQ_PARAM_EXT, ps_idx);
2386 : }
2387 0 : *skip_nal = GF_TRUE;
2388 0 : return 0;
2389 :
2390 3760 : case GF_AVC_NALU_SEI:
2391 3760 : if (ctx->avc_state->sps_active_idx != -1) {
2392 : u32 rw_sei_size, sei_size = size;
2393 3760 : if (ctx->sei_buffer_alloc < ctx->sei_buffer_size + sei_size + ctx->nal_length) {
2394 300 : ctx->sei_buffer_alloc = ctx->sei_buffer_size + sei_size + ctx->nal_length;
2395 300 : ctx->sei_buffer = gf_realloc(ctx->sei_buffer, ctx->sei_buffer_alloc);
2396 : }
2397 :
2398 3760 : if (!ctx->bs_w) ctx->bs_w = gf_bs_new(ctx->sei_buffer + ctx->sei_buffer_size, ctx->nal_length + sei_size, GF_BITSTREAM_WRITE);
2399 3499 : else gf_bs_reassign_buffer(ctx->bs_w, ctx->sei_buffer + ctx->sei_buffer_size, ctx->nal_length + sei_size);
2400 3760 : gf_bs_write_int(ctx->bs_w, sei_size, 8*ctx->nal_length);
2401 :
2402 3760 : memcpy(ctx->sei_buffer + ctx->sei_buffer_size + ctx->nal_length, data, sei_size);
2403 3760 : rw_sei_size = gf_media_avc_reformat_sei(ctx->sei_buffer + ctx->sei_buffer_size + ctx->nal_length, sei_size, ctx->seirw, ctx->avc_state);
2404 3760 : if (rw_sei_size < sei_size) {
2405 0 : gf_bs_seek(ctx->bs_w, 0);
2406 0 : gf_bs_write_int(ctx->bs_w, rw_sei_size, 8*ctx->nal_length);
2407 : }
2408 :
2409 3760 : *skip_nal = GF_TRUE;
2410 3760 : ctx->sei_buffer_size += rw_sei_size + ctx->nal_length;
2411 :
2412 3760 : if (ctx->nosei) {
2413 0 : ctx->sei_buffer_size = 0;
2414 : } else {
2415 3760 : ctx->nb_sei++;
2416 : }
2417 : }
2418 : return 0;
2419 :
2420 6789 : case GF_AVC_NALU_ACCESS_UNIT:
2421 6789 : ctx->nb_aud++;
2422 6789 : if (!ctx->audelim) {
2423 6443 : *skip_nal = GF_TRUE;
2424 346 : } else if (!ctx->opid) {
2425 2 : ctx->has_initial_aud = GF_TRUE;
2426 2 : memcpy(ctx->init_aud, data, 2);
2427 : }
2428 : return 1;
2429 : /*remove*/
2430 96 : case GF_AVC_NALU_FILLER_DATA:
2431 : case GF_AVC_NALU_END_OF_SEQ:
2432 : case GF_AVC_NALU_END_OF_STREAM:
2433 96 : *skip_nal = GF_TRUE;
2434 96 : return 0;
2435 :
2436 : //update stats
2437 169459 : case GF_AVC_NALU_NON_IDR_SLICE:
2438 : case GF_AVC_NALU_DP_A_SLICE:
2439 : case GF_AVC_NALU_DP_B_SLICE:
2440 : case GF_AVC_NALU_DP_C_SLICE:
2441 : case GF_AVC_NALU_IDR_SLICE:
2442 169459 : *is_slice = GF_TRUE;
2443 169459 : switch (ctx->avc_state->s_info.slice_type) {
2444 86980 : case GF_AVC_TYPE_P:
2445 : case GF_AVC_TYPE2_P:
2446 86980 : ctx->nb_p++;
2447 86980 : break;
2448 6514 : case GF_AVC_TYPE_I:
2449 : case GF_AVC_TYPE2_I:
2450 6514 : ctx->nb_i++;
2451 6514 : *is_islice = GF_TRUE;
2452 6514 : break;
2453 75965 : case GF_AVC_TYPE_B:
2454 : case GF_AVC_TYPE2_B:
2455 75965 : ctx->nb_b++;
2456 75965 : break;
2457 0 : case GF_AVC_TYPE_SP:
2458 : case GF_AVC_TYPE2_SP:
2459 0 : ctx->nb_sp++;
2460 0 : break;
2461 0 : case GF_AVC_TYPE_SI:
2462 : case GF_AVC_TYPE2_SI:
2463 0 : ctx->nb_si++;
2464 0 : break;
2465 : }
2466 : break;
2467 :
2468 1502 : case GF_AVC_NALU_SVC_SLICE:
2469 1502 : if (!ctx->explicit) {
2470 : u32 i;
2471 1510 : for (i = 0; i < gf_list_count(ctx->pps); i ++) {
2472 1510 : GF_NALUFFParam *slc = (GF_NALUFFParam*)gf_list_get(ctx->pps, i);
2473 1510 : if (ctx->avc_state->s_info.pps->id == slc->id) {
2474 : /* This PPS is used by an SVC NAL unit, it should be moved to the SVC Config Record) */
2475 6 : gf_list_rem(ctx->pps, i);
2476 6 : i--;
2477 6 : if (!ctx->pps_svc) ctx->pps_svc = gf_list_new(ctx->pps_svc);
2478 6 : gf_list_add(ctx->pps_svc, slc);
2479 6 : ctx->ps_modified = GF_TRUE;
2480 : }
2481 : }
2482 : }
2483 1502 : *is_slice = GF_TRUE;
2484 : //we disable temporal scalability when parsing mvc - never used and many encoders screw up POC in enhancemen
2485 1502 : if (ctx->is_mvc && (res>=0)) {
2486 : res=0;
2487 0 : ctx->avc_state->s_info.poc = ctx->last_poc;
2488 : }
2489 1502 : if (ctx->avc_state->s_info.sps) {
2490 1502 : switch (ctx->avc_state->s_info.slice_type) {
2491 247 : case GF_AVC_TYPE_P:
2492 : case GF_AVC_TYPE2_P:
2493 247 : ctx->avc_state->s_info.sps->nb_ep++;
2494 247 : break;
2495 51 : case GF_AVC_TYPE_I:
2496 : case GF_AVC_TYPE2_I:
2497 51 : ctx->avc_state->s_info.sps->nb_ei++;
2498 51 : break;
2499 1204 : case GF_AVC_TYPE_B:
2500 : case GF_AVC_TYPE2_B:
2501 1204 : ctx->avc_state->s_info.sps->nb_eb++;
2502 1204 : break;
2503 : }
2504 : }
2505 : break;
2506 0 : case GF_AVC_NALU_SLICE_AUX:
2507 0 : *is_slice = GF_TRUE;
2508 0 : break;
2509 : }
2510 : return res;
2511 : }
2512 :
2513 57653 : static void naldmx_switch_timestamps(GF_NALUDmxCtx *ctx, GF_FilterPacket *pck)
2514 : {
2515 : //input pid sets some timescale - we flushed pending data , update cts
2516 57653 : if (ctx->timescale) {
2517 5633 : u64 ts = gf_filter_pck_get_cts(pck);
2518 5633 : if (ts != GF_FILTER_NO_TS) {
2519 5633 : ctx->prev_cts = ctx->cts;
2520 5633 : ctx->cts = ts;
2521 : }
2522 5633 : ts = gf_filter_pck_get_dts(pck);
2523 5633 : if (ts != GF_FILTER_NO_TS) {
2524 5633 : GF_FilterClockType ck_type = gf_filter_pid_get_clock_info(ctx->ipid, NULL, NULL);
2525 5633 : if (ck_type==GF_FILTER_CLOCK_PCR_DISC)
2526 0 : ctx->dts = ts;
2527 5633 : else if (ctx->dts<ts)
2528 57 : ctx->dts=ts;
2529 :
2530 5633 : if (!ctx->prev_dts) ctx->prev_dts = ts;
2531 5600 : else if (ctx->prev_dts != ts) {
2532 : u64 diff = ts;
2533 5600 : diff -= ctx->prev_dts;
2534 5600 : if (!ctx->cur_fps.den)
2535 14 : ctx->cur_fps.den = (u32) diff;
2536 5586 : else if (ctx->cur_fps.den > diff)
2537 0 : ctx->cur_fps.den = (u32) diff;
2538 :
2539 5600 : ctx->prev_dts = ts;
2540 : }
2541 : }
2542 5633 : ctx->pck_duration = gf_filter_pck_get_duration(pck);
2543 5633 : if (ctx->src_pck) gf_filter_pck_unref(ctx->src_pck);
2544 5633 : ctx->src_pck = pck;
2545 5633 : gf_filter_pck_ref_props(&ctx->src_pck);
2546 : //store framing flags. If input_is_au_start, the first NAL of the first frame beginning in this packet will
2547 : //use the DTS/CTS of the input packet, otherwise we will use our internal POC recompute
2548 5633 : gf_filter_pck_get_framing(pck, &ctx->input_is_au_start, NULL);
2549 : }
2550 57653 : }
2551 :
2552 709299 : static void naldmx_check_timestamp_switch(GF_NALUDmxCtx *ctx, u32 *nalu_store_before, u32 bytes_drop, Bool *drop_packet, GF_FilterPacket *pck)
2553 : {
2554 709299 : if (*nalu_store_before) {
2555 550270 : if (*nalu_store_before > bytes_drop) {
2556 494589 : *nalu_store_before -= bytes_drop;
2557 : } else {
2558 : //all data from previous frame consumed, update timestamps with info from current packet
2559 55681 : *nalu_store_before = 0;
2560 55681 : naldmx_switch_timestamps(ctx, pck);
2561 55681 : if (*drop_packet) {
2562 55681 : gf_filter_pid_drop_packet(ctx->ipid);
2563 55681 : *drop_packet = GF_FALSE;
2564 : }
2565 : }
2566 : }
2567 709299 : }
2568 :
2569 0 : static void naldmx_bs_log(void *udta, const char *field_name, u32 nb_bits, u64 field_val, s32 idx1, s32 idx2, s32 idx3)
2570 : {
2571 : GF_NALUDmxCtx *ctx = (GF_NALUDmxCtx *) udta;
2572 0 : GF_LOG(GF_LOG_DEBUG, GF_LOG_PARSER, (" %s", field_name));
2573 0 : if (idx1>=0) {
2574 0 : GF_LOG(GF_LOG_DEBUG, GF_LOG_PARSER, ("_%d", idx1));
2575 0 : if (idx2>=0) {
2576 0 : GF_LOG(GF_LOG_DEBUG, GF_LOG_PARSER, ("_%d", idx2));
2577 0 : if (idx3>=0) {
2578 0 : GF_LOG(GF_LOG_DEBUG, GF_LOG_PARSER, ("_%d", idx3));
2579 : }
2580 : }
2581 : }
2582 0 : GF_LOG(GF_LOG_DEBUG, GF_LOG_PARSER, ("=\""LLD, field_val));
2583 0 : if ((ctx->bsdbg==2) && ((s32) nb_bits > 1) )
2584 0 : GF_LOG(GF_LOG_DEBUG, GF_LOG_PARSER, ("(%u)", nb_bits));
2585 :
2586 0 : GF_LOG(GF_LOG_DEBUG, GF_LOG_PARSER, ("\" "));
2587 0 : }
2588 :
2589 450165 : GF_Err naludmx_process(GF_Filter *filter)
2590 : {
2591 450165 : GF_NALUDmxCtx *ctx = gf_filter_get_udta(filter);
2592 : GF_FilterPacket *pck;
2593 : GF_Err e;
2594 : u8 *start;
2595 450165 : u32 nalu_before = ctx->nb_nalus;
2596 450165 : u32 nalu_store_before = 0;
2597 : s32 remain;
2598 : Bool is_eos = GF_FALSE;
2599 450165 : Bool drop_packet = GF_FALSE;
2600 : u64 byte_offset = GF_FILTER_NO_BO;
2601 :
2602 : //always reparse duration
2603 450165 : if (!ctx->file_loaded)
2604 14294 : naludmx_check_dur(filter, ctx);
2605 :
2606 450165 : pck = gf_filter_pid_get_packet(ctx->ipid);
2607 450165 : if (!ctx->resume_from && !pck) {
2608 4702 : if (gf_filter_pid_is_eos(ctx->ipid)) {
2609 677 : if (ctx->nal_store_size) {
2610 137 : if (!ctx->is_playing)
2611 : return GF_OK;
2612 :
2613 137 : start = ctx->nal_store;
2614 137 : remain = ctx->nal_store_size;
2615 : is_eos = GF_TRUE;
2616 137 : goto naldmx_flush;
2617 : }
2618 540 : if (ctx->first_pck_in_au) {
2619 361 : naludmx_finalize_au_flags(ctx);
2620 : }
2621 : //single-frame stream
2622 540 : if (!ctx->poc_diff) ctx->poc_diff = 1;
2623 540 : ctx->strict_poc = STRICT_POC_OFF;
2624 540 : naludmx_enqueue_or_dispatch(ctx, NULL, GF_TRUE);
2625 540 : if (ctx->src_pck) gf_filter_pck_unref(ctx->src_pck);
2626 540 : ctx->src_pck = NULL;
2627 540 : if (!ctx->opid) return GF_EOS;
2628 :
2629 540 : gf_filter_pid_set_info(ctx->opid, GF_PROP_PID_MAX_NALU_SIZE, &PROP_UINT(ctx->max_nalu_size) );
2630 540 : if (ctx->codecid==GF_CODECID_HEVC) {
2631 234 : naludmx_set_hevc_oinf(ctx, ctx->max_temporal_id);
2632 234 : naludmx_set_hevc_linf(ctx);
2633 234 : gf_filter_pid_set_property_str(ctx->opid, "hevc:min_lid", &PROP_UINT(ctx->min_layer_id) );
2634 : }
2635 540 : if (ctx->opid)
2636 540 : gf_filter_pid_set_eos(ctx->opid);
2637 : return GF_EOS;
2638 : }
2639 : return GF_OK;
2640 : }
2641 :
2642 445463 : if (!ctx->is_playing && ctx->opid)
2643 : return GF_OK;
2644 :
2645 : //if we have bytes from previous packet in the header, we cannot switch timing until we know what these bytes are
2646 297471 : if (!ctx->nal_store_size)
2647 1972 : naldmx_switch_timestamps(ctx, pck);
2648 :
2649 297471 : nalu_store_before = ctx->nal_store_size;
2650 297471 : if (!ctx->resume_from && pck) {
2651 : u32 pck_size;
2652 74178 : const u8 *data = gf_filter_pck_get_data(pck, &pck_size);
2653 74178 : if (ctx->nal_store_alloc < ctx->nal_store_size + pck_size) {
2654 3039 : ctx->nal_store_alloc = ctx->nal_store_size + pck_size;
2655 3039 : ctx->nal_store = gf_realloc(ctx->nal_store, sizeof(char)*ctx->nal_store_alloc);
2656 3039 : if (!ctx->nal_store) {
2657 0 : ctx->nal_store_alloc = 0;
2658 0 : return GF_OUT_OF_MEM;
2659 : }
2660 : }
2661 74178 : byte_offset = gf_filter_pck_get_byte_offset(pck);
2662 74178 : if (byte_offset != GF_FILTER_NO_BO)
2663 69045 : byte_offset -= ctx->nal_store_size;
2664 74178 : memcpy(ctx->nal_store + ctx->nal_store_size, data, sizeof(char)*pck_size);
2665 74178 : ctx->nal_store_size += pck_size;
2666 74178 : drop_packet = GF_TRUE;
2667 : }
2668 297471 : start = ctx->nal_store;
2669 297471 : remain = ctx->nal_store_size;
2670 :
2671 297471 : if (ctx->resume_from) {
2672 223293 : if (ctx->opid && gf_filter_pid_would_block(ctx->opid))
2673 : return GF_OK;
2674 :
2675 : assert(ctx->resume_from < ctx->nal_store_size);
2676 221179 : start += ctx->resume_from;
2677 221179 : remain -= ctx->resume_from;
2678 221179 : ctx->resume_from = 0;
2679 :
2680 222898 : if (!pck && gf_filter_pid_is_eos(ctx->ipid))
2681 : is_eos = GF_TRUE;
2682 : }
2683 :
2684 293732 : naldmx_flush:
2685 295494 : if (!ctx->bs_r) {
2686 406 : ctx->bs_r = gf_bs_new(start, remain, GF_BITSTREAM_READ);
2687 :
2688 : #ifndef GPAC_DISABLE_LOG
2689 406 : if (ctx->bsdbg && gf_log_tool_level_on(GF_LOG_PARSER, GF_LOG_DEBUG))
2690 0 : gf_bs_set_logger(ctx->bs_r, naldmx_bs_log, ctx);
2691 : #endif
2692 :
2693 : } else {
2694 295088 : gf_bs_reassign_buffer(ctx->bs_r, start, remain);
2695 : }
2696 :
2697 : assert(remain>=0);
2698 :
2699 784890 : while (remain) {
2700 : u8 *pck_data;
2701 : u8 *nal_data;
2702 : u32 nal_size;
2703 : s32 current;
2704 782987 : Bool skip_nal = GF_FALSE;
2705 782987 : u32 sc_size=0;
2706 : u32 nal_type = 0;
2707 : u32 nal_ref_idc = 0;
2708 : s32 next=0;
2709 782987 : u32 next_sc_size=0;
2710 : s32 nal_parse_result;
2711 : Bool slice_is_ref, slice_force_ref;
2712 782987 : Bool is_slice = GF_FALSE;
2713 782987 : Bool is_islice = GF_FALSE;
2714 : Bool bottom_field_flag = GF_FALSE;
2715 : Bool au_start;
2716 : u32 avc_svc_subs_reserved = 0;
2717 : u8 avc_svc_subs_priority = 0;
2718 : Bool recovery_point_valid = GF_FALSE;
2719 : u32 recovery_point_frame_cnt = 0;
2720 : Bool bIntraSlice = GF_FALSE;
2721 : GF_FilterSAPType au_sap_type = GF_FILTER_SAP_NONE;
2722 : Bool slice_is_b = GF_FALSE;
2723 : Bool check_dep = GF_FALSE;
2724 : s32 slice_poc = 0;
2725 :
2726 : //not enough bytes to parse start code + nal hdr
2727 782987 : if (!is_eos && (remain<6)) {
2728 : break;
2729 : }
2730 :
2731 : //locate next start code
2732 782695 : current = gf_media_nalu_next_start_code(start, remain, &sc_size);
2733 782695 : if (current == remain)
2734 : current = -1;
2735 :
2736 : //no start code: if eos or full AU dispatch mode, send remaining otherwise gather
2737 782695 : if (current<0) {
2738 0 : if (!is_eos && !ctx->full_au_source) {
2739 : break;
2740 : }
2741 0 : e = naludmx_realloc_last_pck(ctx, (u32) remain, &pck_data);
2742 0 : if (e==GF_OK)
2743 0 : memcpy(pck_data, start, (size_t) remain);
2744 : remain = 0;
2745 : break;
2746 : }
2747 :
2748 : assert(current>=0);
2749 :
2750 : //skip if no output pid
2751 782695 : if (!ctx->opid && current) {
2752 : assert(remain>=current);
2753 : assert((s32) current >= 0);
2754 :
2755 0 : start += current;
2756 0 : remain -= current;
2757 : current = 0;
2758 : }
2759 :
2760 : //dispatch remaining bytes
2761 782695 : if (current>0) {
2762 : //flush remaining bytes in NAL
2763 0 : if (gf_list_count(ctx->pck_queue)) {
2764 0 : e = naludmx_realloc_last_pck(ctx, current, &pck_data);
2765 0 : if (e==GF_OK) {
2766 0 : memcpy(pck_data, start, current);
2767 : }
2768 : }
2769 : assert(remain>=current);
2770 0 : start += current;
2771 0 : remain -= current;
2772 0 : naldmx_check_timestamp_switch(ctx, &nalu_store_before, current, &drop_packet, pck);
2773 : }
2774 782695 : if (!remain)
2775 : break;
2776 :
2777 : //not enough bytes to parse start code + nal hdr
2778 782695 : if (!is_eos && (remain<6)) {
2779 : break;
2780 : }
2781 :
2782 782695 : nal_data = start + sc_size;
2783 782695 : nal_size = remain - sc_size;
2784 :
2785 : //figure out which nal we need to completely load
2786 782695 : if (ctx->codecid==GF_CODECID_HEVC) {
2787 559261 : nal_type = nal_data[0];
2788 559261 : nal_type = (nal_type & 0x7E) >> 1;
2789 :
2790 : switch (nal_type) {
2791 : case GF_HEVC_NALU_VID_PARAM:
2792 : case GF_HEVC_NALU_SEQ_PARAM:
2793 : case GF_HEVC_NALU_PIC_PARAM:
2794 : case GF_HEVC_NALU_SEI_PREFIX:
2795 : case GF_HEVC_NALU_SEI_SUFFIX:
2796 : break;
2797 : case GF_HEVC_NALU_SLICE_TRAIL_N:
2798 : case GF_HEVC_NALU_SLICE_TSA_N:
2799 : case GF_HEVC_NALU_SLICE_STSA_N:
2800 : case GF_HEVC_NALU_SLICE_RADL_N:
2801 : case GF_HEVC_NALU_SLICE_RASL_N:
2802 : case GF_HEVC_NALU_SLICE_RSV_VCL_N10:
2803 : case GF_HEVC_NALU_SLICE_RSV_VCL_N12:
2804 : case GF_HEVC_NALU_SLICE_RSV_VCL_N14:
2805 : check_dep = GF_TRUE;
2806 : break;
2807 475749 : default:
2808 475749 : if (nal_type<GF_HEVC_NALU_VID_PARAM)
2809 : nal_ref_idc = GF_TRUE;
2810 : break;
2811 : }
2812 223434 : } else if (ctx->codecid==GF_CODECID_VVC) {
2813 0 : nal_type = nal_data[1]>>3;
2814 : switch (nal_type) {
2815 : case GF_VVC_NALU_OPI:
2816 : case GF_VVC_NALU_DEC_PARAM:
2817 : case GF_VVC_NALU_VID_PARAM:
2818 : case GF_VVC_NALU_SEQ_PARAM:
2819 : case GF_VVC_NALU_PIC_PARAM:
2820 : case GF_VVC_NALU_SEI_PREFIX:
2821 : case GF_VVC_NALU_SEI_SUFFIX:
2822 : case GF_VVC_NALU_APS_PREFIX:
2823 : case GF_VVC_NALU_APS_SUFFIX:
2824 : case GF_VVC_NALU_PIC_HEADER:
2825 : break;
2826 :
2827 0 : case GF_VVC_NALU_SLICE_TRAIL:
2828 : case GF_VVC_NALU_SLICE_STSA:
2829 : case GF_VVC_NALU_SLICE_RADL:
2830 : case GF_VVC_NALU_SLICE_RASL:
2831 : case GF_VVC_NALU_SLICE_IDR_W_RADL:
2832 : case GF_VVC_NALU_SLICE_IDR_N_LP:
2833 : case GF_VVC_NALU_SLICE_CRA:
2834 : case GF_VVC_NALU_SLICE_GDR:
2835 0 : if (ctx->deps) {
2836 : check_dep = GF_TRUE;
2837 : }
2838 : break;
2839 : default:
2840 : if (nal_type<GF_HEVC_NALU_VID_PARAM)
2841 : nal_ref_idc = GF_TRUE;
2842 : break;
2843 : }
2844 : } else {
2845 223434 : nal_type = nal_data[0] & 0x1F;
2846 223434 : nal_ref_idc = (nal_data[0] & 0x60) >> 5;
2847 : }
2848 :
2849 : //locate next NAL start
2850 782695 : next = gf_media_nalu_next_start_code(nal_data, nal_size, &next_sc_size);
2851 782695 : if (!is_eos && (next == nal_size) && !ctx->full_au_source) {
2852 : next = -1;
2853 : }
2854 :
2855 : //next nal start not found, wait
2856 710594 : if (next<0) {
2857 : break;
2858 : }
2859 :
2860 : //this is our exact NAL size, without start code
2861 : nal_size = next;
2862 :
2863 710594 : if (ctx->codecid==GF_CODECID_HEVC) {
2864 521703 : nal_parse_result = naludmx_parse_nal_hevc(ctx, nal_data, nal_size, &skip_nal, &is_slice, &is_islice);
2865 188891 : } else if (ctx->codecid==GF_CODECID_VVC) {
2866 0 : nal_parse_result = naludmx_parse_nal_vvc(ctx, nal_data, nal_size, &skip_nal, &is_slice, &is_islice);
2867 : } else {
2868 188891 : nal_parse_result = naludmx_parse_nal_avc(ctx, nal_data, nal_size, nal_type, &skip_nal, &is_slice, &is_islice);
2869 : }
2870 :
2871 : //dispatch right away if analyze
2872 710594 : if (ctx->analyze) {
2873 5450 : skip_nal = GF_FALSE;
2874 5450 : ctx->sei_buffer_size = 0;
2875 : }
2876 :
2877 : //new frame - if no slices, we detected the new frame on AU delimiter, don't flush new frame !
2878 710594 : if ((nal_parse_result>0) && !ctx->first_slice_in_au) {
2879 : //new frame - we flush later on
2880 244965 : naludmx_finalize_au_flags(ctx);
2881 :
2882 244965 : ctx->has_islice = GF_FALSE;
2883 244965 : ctx->first_slice_in_au = GF_TRUE;
2884 244965 : ctx->sei_recovery_frame_count = -1;
2885 244965 : ctx->au_sap = GF_FILTER_SAP_NONE;
2886 244965 : ctx->bottom_field_flag = GF_FALSE;
2887 : }
2888 :
2889 710594 : naludmx_check_pid(filter, ctx);
2890 710594 : if (!ctx->opid) skip_nal = GF_TRUE;
2891 :
2892 710594 : if (skip_nal) {
2893 50372 : nal_size += sc_size;
2894 : assert((u32) remain >= nal_size);
2895 50372 : start += nal_size;
2896 50372 : remain -= nal_size;
2897 50372 : naldmx_check_timestamp_switch(ctx, &nalu_store_before, nal_size, &drop_packet, pck);
2898 101751 : continue;
2899 : }
2900 :
2901 660222 : if (!ctx->is_playing) {
2902 288 : ctx->resume_from = (u32) (start - ctx->nal_store);
2903 : assert(ctx->resume_from<=ctx->nal_store_size);
2904 288 : GF_LOG(GF_LOG_DEBUG, GF_LOG_PARSER, ("[%s] not yet playing\n", ctx->log_name));
2905 :
2906 288 : if (drop_packet)
2907 288 : gf_filter_pid_drop_packet(ctx->ipid);
2908 221198 : return GF_OK;
2909 : }
2910 659934 : if (ctx->in_seek) {
2911 419 : u64 nb_frames_at_seek = (u64) (ctx->start_range * ctx->cur_fps.num);
2912 419 : if (ctx->cts + ctx->cur_fps.den >= nb_frames_at_seek) {
2913 : //u32 samples_to_discard = (ctx->cts + ctx->dts_inc) - nb_samples_at_seek;
2914 384 : ctx->in_seek = GF_FALSE;
2915 : }
2916 : }
2917 :
2918 659934 : if (nal_parse_result<0) {
2919 0 : if (byte_offset != GF_FILTER_NO_BO) {
2920 : u64 bo = byte_offset;
2921 0 : bo += (start - ctx->nal_store);
2922 :
2923 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[%s] Error parsing NAL Unit %d (byte offset "LLU" size %d type %d frame %d last POC %d) - skipping\n", ctx->log_name, ctx->nb_nalus, bo, nal_size, nal_type, ctx->nb_frames, ctx->last_poc));
2924 : } else {
2925 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[%s] Error parsing NAL Unit %d (size %d type %d frame %d last POC %d) - skipping\n", ctx->log_name, ctx->nb_nalus, nal_size, nal_type, ctx->nb_frames, ctx->last_poc));
2926 : }
2927 0 : nal_size += sc_size;
2928 : assert((u32) remain >= nal_size);
2929 0 : start += nal_size;
2930 0 : remain -= nal_size;
2931 0 : naldmx_check_timestamp_switch(ctx, &nalu_store_before, nal_size, &drop_packet, pck);
2932 0 : continue;
2933 : }
2934 :
2935 659934 : if (check_dep) {
2936 9408 : if ((ctx->codecid==GF_CODECID_HEVC) && ctx->hevc_state->s_info.sps) {
2937 : HEVC_VPS *vps;
2938 9408 : u32 temporal_id = nal_data[1] & 0x7;
2939 9408 : vps = & ctx->hevc_state->vps[ctx->hevc_state->s_info.sps->vps_id];
2940 9408 : if (temporal_id + 1 < vps->max_sub_layers) {
2941 : nal_ref_idc = GF_TRUE;
2942 : }
2943 0 : } else if (ctx->codecid==GF_CODECID_VVC) {
2944 0 : if (ctx->vvc_state->s_info.non_ref_pic) {
2945 : nal_ref_idc = GF_FALSE;
2946 : } else {
2947 : //todo
2948 : nal_ref_idc = GF_TRUE;
2949 : }
2950 : }
2951 : }
2952 :
2953 :
2954 659934 : if (is_islice) ctx->has_islice = GF_TRUE;
2955 :
2956 : //store all variables needed to compute POC/CTS and sample SAP and recovery info
2957 659934 : if (ctx->codecid==GF_CODECID_HEVC) {
2958 : #ifndef GPAC_DISABLE_HEVC
2959 487793 : slice_is_ref = gf_hevc_slice_is_IDR(ctx->hevc_state);
2960 :
2961 487793 : recovery_point_valid = ctx->hevc_state->sei.recovery_point.valid;
2962 487793 : recovery_point_frame_cnt = ctx->hevc_state->sei.recovery_point.frame_cnt;
2963 487793 : bIntraSlice = gf_hevc_slice_is_intra(ctx->hevc_state);
2964 :
2965 : au_sap_type = GF_FILTER_SAP_NONE;
2966 487793 : if (gf_hevc_slice_is_IDR(ctx->hevc_state)) {
2967 : au_sap_type = GF_FILTER_SAP_1;
2968 : }
2969 : else {
2970 470706 : switch (ctx->hevc_state->s_info.nal_unit_type) {
2971 : case GF_HEVC_NALU_SLICE_BLA_W_LP:
2972 : case GF_HEVC_NALU_SLICE_BLA_W_DLP:
2973 : au_sap_type = GF_FILTER_SAP_3;
2974 : break;
2975 : case GF_HEVC_NALU_SLICE_BLA_N_LP:
2976 : au_sap_type = GF_FILTER_SAP_1;
2977 : break;
2978 : case GF_HEVC_NALU_SLICE_CRA:
2979 : au_sap_type = GF_FILTER_SAP_3;
2980 : break;
2981 : }
2982 : }
2983 :
2984 487793 : slice_poc = ctx->hevc_state->s_info.poc;
2985 :
2986 : /*need to store TS offsets*/
2987 487793 : switch (ctx->hevc_state->s_info.slice_type) {
2988 443640 : case GF_AVC_TYPE_B:
2989 : case GF_AVC_TYPE2_B:
2990 : slice_is_b = GF_TRUE;
2991 443640 : break;
2992 : }
2993 : #endif // GPAC_DISABLE_HEVC
2994 172141 : } else if (ctx->codecid==GF_CODECID_VVC) {
2995 0 : slice_is_ref = gf_media_vvc_slice_is_ref(ctx->vvc_state);
2996 0 : recovery_point_valid = ctx->vvc_state->s_info.recovery_point_valid;
2997 0 : recovery_point_frame_cnt = ctx->vvc_state->s_info.gdr_recovery_count;
2998 :
2999 : // commented, set below
3000 : // if (ctx->vvc_state->s_info.irap_or_gdr_pic && !ctx->vvc_state->s_info.gdr_pic)
3001 : // bIntraSlice = GF_TRUE; //gf_hevc_slice_is_intra(ctx->hevc_state);
3002 :
3003 : au_sap_type = GF_FILTER_SAP_NONE;
3004 0 : if (ctx->vvc_state->s_info.irap_or_gdr_pic && !ctx->vvc_state->s_info.gdr_pic) {
3005 : au_sap_type = GF_FILTER_SAP_1;
3006 : bIntraSlice = GF_TRUE;
3007 : slice_is_ref = 1;
3008 : } else {
3009 0 : switch (ctx->vvc_state->s_info.nal_unit_type) {
3010 0 : case GF_VVC_NALU_SLICE_IDR_N_LP:
3011 : au_sap_type = GF_FILTER_SAP_1;
3012 : slice_is_ref = 1;
3013 : bIntraSlice = GF_TRUE;
3014 0 : break;
3015 0 : case GF_VVC_NALU_SLICE_CRA:
3016 : au_sap_type = GF_FILTER_SAP_3;
3017 : bIntraSlice = GF_TRUE;
3018 0 : break;
3019 0 : case GF_VVC_NALU_SLICE_IDR_W_RADL:
3020 : bIntraSlice = GF_TRUE;
3021 0 : if (ctx->vvc_state->s_info.gdr_pic) {
3022 : au_sap_type = GF_FILTER_SAP_3;
3023 : } else {
3024 : au_sap_type = GF_FILTER_SAP_1;
3025 : slice_is_ref = 1;
3026 : }
3027 : break;
3028 : }
3029 : }
3030 :
3031 0 : slice_poc = ctx->vvc_state->s_info.poc;
3032 :
3033 : /*need to store TS offsets*/
3034 0 : switch (ctx->vvc_state->s_info.slice_type) {
3035 0 : case GF_AVC_TYPE_B:
3036 : case GF_AVC_TYPE2_B:
3037 : slice_is_b = GF_TRUE;
3038 0 : break;
3039 : }
3040 : } else {
3041 :
3042 : /*fixme - we need finer grain for priority*/
3043 172141 : if ((nal_type==GF_AVC_NALU_SVC_PREFIX_NALU) || (nal_type==GF_AVC_NALU_SVC_SLICE)) {
3044 2509 : if (!ctx->is_mvc) {
3045 : unsigned char *p = (unsigned char *) start;
3046 : // RefPicFlag
3047 2509 : avc_svc_subs_reserved |= (p[0] & 0x60) ? 0x80000000 : 0;
3048 : // RedPicFlag TODO: not supported, would require to parse NAL unit payload
3049 : avc_svc_subs_reserved |= (0) ? 0x40000000 : 0;
3050 : // VclNALUnitFlag
3051 2509 : avc_svc_subs_reserved |= (1<=nal_type && nal_type<=5) || (nal_type==GF_AVC_NALU_SVC_PREFIX_NALU) || (nal_type==GF_AVC_NALU_SVC_SLICE) ? 0x20000000 : 0;
3052 : // use values of IdrFlag and PriorityId directly from SVC extension header
3053 2509 : avc_svc_subs_reserved |= p[1] << 16;
3054 : // use values of DependencyId and QualityId directly from SVC extension header
3055 2509 : avc_svc_subs_reserved |= p[2] << 8;
3056 : // use values of TemporalId and UseRefBasePicFlag directly from SVC extension header
3057 2509 : avc_svc_subs_reserved |= p[3] & 0xFC;
3058 : // StoreBaseRepFlag TODO: SVC FF mentions a store_base_rep_flag which cannot be found in SVC spec
3059 : avc_svc_subs_reserved |= (0) ? 0x00000002 : 0;
3060 :
3061 : // priority_id (6 bits) in SVC has inverse meaning -> lower value means higher priority - invert it and scale it to 8 bits
3062 2509 : avc_svc_subs_priority = (63 - (p[1] & 0x3F)) << 2;
3063 : }
3064 2509 : if (nal_type==GF_AVC_NALU_SVC_PREFIX_NALU) {
3065 1007 : if (ctx->svc_prefix_buffer_size) {
3066 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[%s] broken bitstream, two consecutive SVC prefix NALU without SVC slice in-between\n", ctx->log_name));
3067 : ctx->svc_prefix_buffer_size = 0;
3068 : }
3069 :
3070 : /* remember reserved and priority value */
3071 1007 : ctx->svc_nalu_prefix_reserved = avc_svc_subs_reserved;
3072 1007 : ctx->svc_nalu_prefix_priority = avc_svc_subs_priority;
3073 :
3074 1007 : ctx->svc_prefix_buffer_size = nal_size;
3075 1007 : if (ctx->svc_prefix_buffer_size > ctx->svc_prefix_buffer_alloc) {
3076 4 : ctx->svc_prefix_buffer_alloc = ctx->svc_prefix_buffer_size;
3077 4 : ctx->svc_prefix_buffer = gf_realloc(ctx->svc_prefix_buffer, ctx->svc_prefix_buffer_size);
3078 : }
3079 1007 : memcpy(ctx->svc_prefix_buffer, start+sc_size, ctx->svc_prefix_buffer_size);
3080 :
3081 : assert( (u32) remain >= sc_size + nal_size);
3082 1007 : start += sc_size + nal_size;
3083 1007 : remain -= sc_size + nal_size;
3084 1007 : continue;
3085 : }
3086 169632 : } else if (is_slice) {
3087 : // RefPicFlag
3088 169278 : avc_svc_subs_reserved |= (start[0] & 0x60) ? 0x80000000 : 0;
3089 : // VclNALUnitFlag
3090 169278 : avc_svc_subs_reserved |= (1<=nal_type && nal_type<=5) || (nal_type==GF_AVC_NALU_SVC_PREFIX_NALU) || (nal_type==GF_AVC_NALU_SVC_SLICE) ? 0x20000000 : 0;
3091 : avc_svc_subs_priority = 0;
3092 : }
3093 :
3094 171134 : if (is_slice && ctx->avc_state->s_info.field_pic_flag) {
3095 112 : ctx->is_paff = GF_TRUE;
3096 112 : bottom_field_flag = ctx->avc_state->s_info.bottom_field_flag;
3097 : }
3098 :
3099 171134 : slice_is_ref = (ctx->avc_state->s_info.nal_unit_type==GF_AVC_NALU_IDR_SLICE) ? GF_TRUE : GF_FALSE;
3100 :
3101 171134 : recovery_point_valid = ctx->avc_state->sei.recovery_point.valid;
3102 171134 : recovery_point_frame_cnt = ctx->avc_state->sei.recovery_point.frame_cnt;
3103 171134 : bIntraSlice = gf_media_avc_slice_is_intra(ctx->avc_state);
3104 :
3105 : au_sap_type = GF_FILTER_SAP_NONE;
3106 171134 : if (ctx->avc_state->s_info.nal_unit_type == GF_AVC_NALU_IDR_SLICE)
3107 : au_sap_type = GF_FILTER_SAP_1;
3108 :
3109 171134 : slice_poc = ctx->avc_state->s_info.poc;
3110 : /*need to store TS offsets*/
3111 171134 : switch (ctx->avc_state->s_info.slice_type) {
3112 77317 : case GF_AVC_TYPE_B:
3113 : case GF_AVC_TYPE2_B:
3114 : slice_is_b = GF_TRUE;
3115 77317 : break;
3116 : }
3117 : }
3118 :
3119 658927 : if (is_slice) {
3120 593877 : Bool first_in_au = ctx->first_slice_in_au;
3121 :
3122 593877 : if (slice_is_ref)
3123 23065 : ctx->nb_idr++;
3124 : slice_force_ref = GF_FALSE;
3125 :
3126 : /*we only indicate TRUE IDRs for sync samples (cf AVC file format spec).
3127 : SEI recovery should be used to build sampleToGroup & RollRecovery tables*/
3128 593877 : if (ctx->first_slice_in_au) {
3129 245303 : ctx->first_slice_in_au = GF_FALSE;
3130 245303 : if (recovery_point_valid) {
3131 336 : ctx->sei_recovery_frame_count = recovery_point_frame_cnt;
3132 :
3133 : /*we allow to mark I-frames as sync on open-GOPs (with sei_recovery_frame_count=0) when forcing sync even when the SEI RP is not available*/
3134 336 : if (!recovery_point_frame_cnt && bIntraSlice) {
3135 243 : ctx->has_islice = 1;
3136 243 : if (ctx->use_opengop_gdr == 1) {
3137 0 : ctx->use_opengop_gdr = 2; /*avoid message flooding*/
3138 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[%s] No valid SEI Recovery Point found although needed - forcing\n", ctx->log_name));
3139 : }
3140 : }
3141 336 : if (ctx->codecid==GF_CODECID_HEVC) {
3142 0 : ctx->hevc_state->sei.recovery_point.valid = 0;
3143 336 : } else if (ctx->codecid==GF_CODECID_VVC) {
3144 0 : ctx->vvc_state->s_info.recovery_point_valid = 0;
3145 : } else {
3146 336 : ctx->avc_state->sei.recovery_point.valid = 0;
3147 : }
3148 336 : if (bIntraSlice && ctx->force_sync && (ctx->sei_recovery_frame_count==0))
3149 : slice_force_ref = GF_TRUE;
3150 : }
3151 245303 : ctx->au_sap = au_sap_type;
3152 245303 : ctx->bottom_field_flag = bottom_field_flag;
3153 : }
3154 :
3155 593877 : if (slice_poc < ctx->poc_shift) {
3156 :
3157 213 : u32 i, count = gf_list_count(ctx->pck_queue);
3158 1049 : for (i=0; i<count; i++) {
3159 : u64 dts, cts;
3160 836 : GF_FilterPacket *q_pck = gf_list_get(ctx->pck_queue, i);
3161 : assert(q_pck);
3162 836 : dts = gf_filter_pck_get_dts(q_pck);
3163 836 : if (dts == GF_FILTER_NO_TS) continue;
3164 418 : cts = gf_filter_pck_get_cts(q_pck);
3165 418 : cts += ctx->poc_shift;
3166 418 : cts -= slice_poc;
3167 418 : gf_filter_pck_set_cts(q_pck, cts);
3168 : }
3169 :
3170 213 : ctx->poc_shift = slice_poc;
3171 : }
3172 :
3173 : /*if #pics, compute smallest POC increase*/
3174 593877 : if (slice_poc != ctx->last_poc) {
3175 244899 : s32 pdiff = ABS(ctx->last_poc - slice_poc);
3176 :
3177 244899 : if ((slice_poc < 0) && !ctx->last_poc)
3178 71 : ctx->poc_diff = 0;
3179 :
3180 244899 : if (!ctx->poc_diff || (ctx->poc_diff > (s32) pdiff ) ) {
3181 721 : ctx->poc_diff = pdiff;
3182 721 : ctx->poc_probe_done = GF_FALSE;
3183 244178 : } else if (first_in_au) {
3184 : //second frame with the same poc diff, we should be able to properly recompute CTSs
3185 244178 : ctx->poc_probe_done = GF_TRUE;
3186 : }
3187 244899 : ctx->last_poc = slice_poc;
3188 : }
3189 593877 : GF_LOG(GF_LOG_DEBUG, GF_LOG_PARSER, ("[%s] POC is %d - min poc diff %d - slice is ref %d\n", ctx->log_name, slice_poc, ctx->poc_diff, slice_is_ref));
3190 :
3191 : /*ref slice, reset poc*/
3192 593877 : if (slice_is_ref) {
3193 23065 : if (first_in_au) {
3194 : //two consecutive IDRs, force poc_diff to 1 if 0 (when we have intra-only) to force frame dispatch
3195 8894 : if (ctx->last_frame_is_idr && !ctx->poc_diff)
3196 0 : ctx->poc_diff=1;
3197 : //new ref frame, dispatch all pending packets
3198 8894 : naludmx_enqueue_or_dispatch(ctx, NULL, GF_TRUE);
3199 :
3200 8894 : ctx->max_last_poc = ctx->last_poc = ctx->max_last_b_poc = 0;
3201 8894 : ctx->poc_shift = 0;
3202 : //force probing of POC diff, this will prevent dispatching frames with wrong CTS until we have a clue of min poc_diff used
3203 8894 : ctx->poc_probe_done = 0;
3204 8894 : ctx->last_frame_is_idr = GF_TRUE;
3205 : }
3206 : }
3207 : /*forced ref slice*/
3208 570812 : else if (slice_force_ref) {
3209 0 : ctx->last_frame_is_idr = GF_FALSE;
3210 0 : if (first_in_au) {
3211 : //new ref frame, dispatch all pending packets
3212 0 : naludmx_enqueue_or_dispatch(ctx, NULL, GF_TRUE);
3213 :
3214 : /*adjust POC shift as sample will now be marked as sync, so we must store poc as if IDR (eg POC=0) for our CTS offset computing to be correct*/
3215 0 : ctx->poc_shift = slice_poc;
3216 :
3217 : //force probing of POC diff, this will prevent dispatching frames with wrong CTS until we have a clue of min poc_diff used
3218 0 : ctx->poc_probe_done = 0;
3219 : }
3220 : }
3221 : /*strictly less - this is a new P slice*/
3222 570812 : else if (ctx->max_last_poc < ctx->last_poc) {
3223 148979 : ctx->max_last_b_poc = 0;
3224 148979 : ctx->max_last_poc = ctx->last_poc;
3225 148979 : ctx->last_frame_is_idr = GF_FALSE;
3226 : }
3227 : /*stricly greater*/
3228 421833 : else if (slice_is_b && (ctx->max_last_poc > ctx->last_poc)) {
3229 77169 : ctx->last_frame_is_idr = GF_FALSE;
3230 77169 : if (!ctx->max_last_b_poc) {
3231 32622 : ctx->max_last_b_poc = ctx->last_poc;
3232 : }
3233 : /*if same poc than last max, this is a B-slice*/
3234 44547 : else if (ctx->last_poc > ctx->max_last_b_poc) {
3235 25518 : ctx->max_last_b_poc = ctx->last_poc;
3236 : }
3237 : /*otherwise we had a B-slice reference: do nothing*/
3238 : } else {
3239 344664 : ctx->last_frame_is_idr = GF_FALSE;
3240 : }
3241 :
3242 :
3243 593877 : if (ctx->deps) {
3244 3346 : if (nal_ref_idc) {
3245 2716 : ctx->has_ref_slices = GF_TRUE;
3246 : }
3247 3346 : if ((ctx->codecid==GF_CODECID_AVC) && (ctx->avc_state->s_info.redundant_pic_cnt) ) {
3248 0 : ctx->has_redundant = GF_TRUE;
3249 : }
3250 : }
3251 : }
3252 :
3253 :
3254 658927 : au_start = ctx->first_pck_in_au ? GF_FALSE : GF_TRUE;
3255 :
3256 658927 : if (ctx->has_initial_aud) {
3257 4 : u32 audelim_size = (ctx->codecid!=GF_CODECID_AVC) ? 3 : 2;
3258 4 : /*dst_pck = */naludmx_start_nalu(ctx, audelim_size, GF_FALSE, &au_start, &pck_data);
3259 4 : memcpy(pck_data + ctx->nal_length , ctx->init_aud, audelim_size);
3260 4 : ctx->has_initial_aud = GF_FALSE;
3261 4 : if (ctx->subsamples) {
3262 0 : naludmx_add_subsample(ctx, audelim_size, avc_svc_subs_priority, avc_svc_subs_reserved);
3263 : }
3264 : }
3265 658927 : if (ctx->sei_buffer_size) {
3266 : //sei buffer is already nal size prefixed
3267 5619 : /*dst_pck = */naludmx_start_nalu(ctx, ctx->sei_buffer_size, GF_TRUE, &au_start, &pck_data);
3268 5619 : memcpy(pck_data, ctx->sei_buffer, ctx->sei_buffer_size);
3269 5619 : if (ctx->subsamples) {
3270 0 : naludmx_add_subsample(ctx, ctx->sei_buffer_size - ctx->nal_length, avc_svc_subs_priority, avc_svc_subs_reserved);
3271 : }
3272 5619 : ctx->sei_buffer_size = 0;
3273 : }
3274 :
3275 658927 : if (ctx->svc_prefix_buffer_size) {
3276 1007 : /*dst_pck = */naludmx_start_nalu(ctx, ctx->svc_prefix_buffer_size, GF_FALSE, &au_start, &pck_data);
3277 1007 : memcpy(pck_data + ctx->nal_length, ctx->svc_prefix_buffer, ctx->svc_prefix_buffer_size);
3278 1007 : if (ctx->subsamples) {
3279 0 : naludmx_add_subsample(ctx, ctx->svc_prefix_buffer_size, ctx->svc_nalu_prefix_priority, ctx->svc_nalu_prefix_reserved);
3280 : }
3281 1007 : ctx->svc_prefix_buffer_size = 0;
3282 : }
3283 :
3284 : //nalu size field
3285 658927 : /*dst_pck = */naludmx_start_nalu(ctx, (u32) nal_size, GF_FALSE, &au_start, &pck_data);
3286 658927 : pck_data += ctx->nal_length;
3287 :
3288 : //add subsample info before touching the size
3289 658927 : if (ctx->subsamples) {
3290 1523 : naludmx_add_subsample(ctx, (u32) nal_size, avc_svc_subs_priority, avc_svc_subs_reserved);
3291 : }
3292 :
3293 :
3294 : //bytes only come from the data packet
3295 658927 : memcpy(pck_data, nal_data, (size_t) nal_size);
3296 :
3297 658927 : nal_size += sc_size;
3298 658927 : start += nal_size;
3299 658927 : remain -= nal_size;
3300 658927 : naldmx_check_timestamp_switch(ctx, &nalu_store_before, nal_size, &drop_packet, pck);
3301 :
3302 : //don't demux too much of input, abort when we would block. This avoid dispatching
3303 : //a huge number of frames in a single call
3304 658927 : if (remain && gf_filter_pid_would_block(ctx->opid)) {
3305 220910 : ctx->resume_from = (u32) (start - ctx->nal_store);
3306 : assert(ctx->resume_from <= ctx->nal_store_size);
3307 : assert(ctx->resume_from == ctx->nal_store_size - remain);
3308 220910 : if (drop_packet)
3309 127 : gf_filter_pid_drop_packet(ctx->ipid);
3310 : return GF_OK;
3311 : }
3312 : }
3313 :
3314 74296 : if (remain) {
3315 72393 : if (is_eos && (remain == ctx->nal_store_size)) {
3316 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[%s] Incomplete last NAL and eos, discarding\n", ctx->log_name));
3317 : remain = 0;
3318 : } else {
3319 : assert((u32) remain<=ctx->nal_store_size);
3320 72393 : memmove(ctx->nal_store, start, remain);
3321 : }
3322 : }
3323 74296 : ctx->nal_store_size = remain;
3324 :
3325 74296 : if (drop_packet)
3326 18082 : gf_filter_pid_drop_packet(ctx->ipid);
3327 :
3328 74296 : if (is_eos)
3329 365 : return naludmx_process(filter);
3330 :
3331 73931 : if ((ctx->nb_nalus>nalu_before) && gf_filter_reporting_enabled(filter)) {
3332 : char szStatus[1024];
3333 :
3334 4 : sprintf(szStatus, "%s %dx%d % 10d NALU % 8d I % 8d P % 8d B % 8d SEI", ctx->log_name, ctx->width, ctx->height, ctx->nb_nalus, ctx->nb_i, ctx->nb_p, ctx->nb_b, ctx->nb_sei);
3335 4 : gf_filter_update_status(filter, -1, szStatus);
3336 : }
3337 73931 : if (ctx->full_au_source && ctx->poc_probe_done) {
3338 1464 : if (ctx->first_pck_in_au)
3339 1464 : naludmx_finalize_au_flags(ctx);
3340 :
3341 1464 : naludmx_enqueue_or_dispatch(ctx, NULL, GF_TRUE);
3342 : }
3343 : return GF_OK;
3344 : }
3345 :
3346 406 : static GF_Err naludmx_initialize(GF_Filter *filter)
3347 : {
3348 406 : GF_NALUDmxCtx *ctx = gf_filter_get_udta(filter);
3349 406 : ctx->sps = gf_list_new();
3350 406 : ctx->pps = gf_list_new();
3351 406 : switch (ctx->nal_length) {
3352 0 : case 1:
3353 0 : ctx->max_nalu_size_allowed = 0xFF;
3354 0 : break;
3355 0 : case 2:
3356 0 : ctx->max_nalu_size_allowed = 0xFFFF;
3357 0 : break;
3358 406 : case 4:
3359 406 : ctx->max_nalu_size_allowed = 0xFFFFFFFF;
3360 406 : break;
3361 0 : case 0:
3362 0 : ctx->max_nalu_size_allowed = 0xFFFFFFFF;
3363 0 : ctx->nal_length = 4;
3364 0 : ctx->nal_adjusted = GF_TRUE;
3365 0 : break;
3366 0 : default:
3367 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[%s] NAL size length %d is not allowed, defaulting to 4 bytes\n", ctx->log_name));
3368 0 : ctx->max_nalu_size_allowed = 0xFFFFFFFF;
3369 0 : ctx->nal_length = 4;
3370 0 : break;
3371 : }
3372 406 : return GF_OK;
3373 : }
3374 :
3375 2842 : static void naludmx_del_param_list(GF_List *ps)
3376 : {
3377 2842 : if (!ps) return;
3378 1934 : while (gf_list_count(ps)) {
3379 981 : GF_NALUFFParam *sl = gf_list_pop_back(ps);
3380 981 : if (sl->data) gf_free(sl->data);
3381 981 : gf_free(sl);
3382 : }
3383 953 : gf_list_del(ps);
3384 : }
3385 :
3386 213 : static void naludmx_log_stats(GF_NALUDmxCtx *ctx)
3387 : {
3388 : u32 i, count;
3389 : const char *msg_import;
3390 : u32 nb_frames = 0;
3391 213 : if (ctx->cur_fps.den)
3392 213 : nb_frames = (u32) (ctx->dts / ctx->cur_fps.den);
3393 :
3394 213 : if (ctx->idur.den && ctx->idur.num) {
3395 30 : GF_LOG(GF_LOG_INFO, GF_LOG_AUTHOR, ("%s duration specified at import time, may have parsed more frames than imported\n", ctx->log_name));
3396 : msg_import = "parsed";
3397 : } else {
3398 : msg_import = "Import results:";
3399 : }
3400 :
3401 213 : if (ctx->nb_si || ctx->nb_sp) {
3402 0 : GF_LOG(GF_LOG_INFO, GF_LOG_AUTHOR, ("%s %s %d frames (%d NALUs) - Slices: %d I %d P %d B %d SP %d SI - %d SEI - %d IDR\n", ctx->log_name, msg_import, nb_frames, ctx->nb_nalus, ctx->nb_i, ctx->nb_p, ctx->nb_b, ctx->nb_sp, ctx->nb_si, ctx->nb_sei, ctx->nb_idr ));
3403 213 : } else if (ctx->vvc_no_stats) {
3404 0 : GF_LOG(GF_LOG_INFO, GF_LOG_AUTHOR, ("%s %s %d samples (%d NALUs) - %d SEI - %d IDR\n",
3405 : ctx->log_name, msg_import, nb_frames, ctx->nb_nalus, ctx->nb_sei, ctx->nb_idr));
3406 : } else {
3407 213 : GF_LOG(GF_LOG_INFO, GF_LOG_AUTHOR, ("%s %s %d samples (%d NALUs) - Slices: %d I %d P %d B - %d SEI - %d IDR\n",
3408 : ctx->log_name, msg_import, nb_frames, ctx->nb_nalus, ctx->nb_i, ctx->nb_p, ctx->nb_b, ctx->nb_sei, ctx->nb_idr));
3409 : }
3410 :
3411 213 : if (ctx->codecid==GF_CODECID_AVC) {
3412 144 : count = gf_list_count(ctx->sps);
3413 293 : for (i=0; i<count; i++) {
3414 : AVC_SPS *sps;
3415 149 : GF_NALUFFParam *svcc = (GF_NALUFFParam*)gf_list_get(ctx->sps, i);
3416 149 : sps = & ctx->avc_state->sps[svcc->id];
3417 149 : if (sps->nb_ei || sps->nb_ep) {
3418 5 : GF_LOG(GF_LOG_INFO, GF_LOG_AUTHOR, ("%s SVC (SSPS ID %d, %dx%d) %s Slices: %d I %d P %d B\n", ctx->log_name, svcc->id - GF_SVC_SSPS_ID_SHIFT, sps->width, sps->height, msg_import, sps->nb_ei, sps->nb_ep, sps->nb_eb ));
3419 : }
3420 : }
3421 69 : } else if (ctx->nb_e_i || ctx->nb_e_p || ctx->nb_e_b) {
3422 6 : GF_LOG(GF_LOG_INFO, GF_LOG_AUTHOR, ("%s L-HEVC %s Slices: %d I %d P %d B\n", ctx->log_name, msg_import, ctx->nb_e_i, ctx->nb_e_p, ctx->nb_e_b ));
3423 : }
3424 :
3425 213 : if (ctx->max_total_delay>1) {
3426 112 : GF_LOG(GF_LOG_INFO, GF_LOG_AUTHOR, ("%s Stream uses forward prediction - stream CTS offset: %d frames\n", ctx->log_name, ctx->max_total_delay));
3427 : }
3428 :
3429 213 : if (!ctx->nal_adjusted) {
3430 213 : if ((ctx->max_nalu_size < 0xFF) && (ctx->nal_length>1) ){
3431 0 : GF_LOG(GF_LOG_INFO, GF_LOG_AUTHOR, ("%s Max NALU size is %d - stream could be optimized by setting nal_length=1\n", ctx->log_name, ctx->max_nalu_size));
3432 213 : } else if ((ctx->max_nalu_size < 0xFFFF) && (ctx->nal_length>2) ){
3433 206 : GF_LOG(GF_LOG_INFO, GF_LOG_AUTHOR, ("%s Max NALU size is %d - stream could be optimized by setting nal_length=2\n", ctx->log_name, ctx->max_nalu_size));
3434 : }
3435 : }
3436 213 : }
3437 :
3438 406 : static void naludmx_finalize(GF_Filter *filter)
3439 : {
3440 406 : GF_NALUDmxCtx *ctx = gf_filter_get_udta(filter);
3441 :
3442 406 : if (ctx->importer) naludmx_log_stats(ctx);
3443 :
3444 406 : if (ctx->bs_r) gf_bs_del(ctx->bs_r);
3445 406 : if (ctx->bs_w) gf_bs_del(ctx->bs_w);
3446 406 : if (ctx->indexes) gf_free(ctx->indexes);
3447 406 : if (ctx->nal_store) gf_free(ctx->nal_store);
3448 406 : if (ctx->pck_queue) {
3449 596 : while (gf_list_count(ctx->pck_queue)) {
3450 190 : GF_FilterPacket *pck = gf_list_pop_back(ctx->pck_queue);
3451 190 : gf_filter_pck_discard(pck);
3452 : }
3453 406 : gf_list_del(ctx->pck_queue);
3454 : }
3455 406 : if (ctx->sei_buffer) gf_free(ctx->sei_buffer);
3456 406 : if (ctx->svc_prefix_buffer) gf_free(ctx->svc_prefix_buffer);
3457 406 : if (ctx->subsamp_buffer) gf_free(ctx->subsamp_buffer);
3458 :
3459 406 : if (ctx->src_pck) gf_filter_pck_unref(ctx->src_pck);
3460 406 : ctx->src_pck = NULL;
3461 :
3462 406 : naludmx_del_param_list(ctx->sps);
3463 406 : naludmx_del_param_list(ctx->pps);
3464 406 : naludmx_del_param_list(ctx->vps);
3465 406 : naludmx_del_param_list(ctx->sps_ext);
3466 406 : naludmx_del_param_list(ctx->pps_svc);
3467 406 : naludmx_del_param_list(ctx->vvc_aps_pre);
3468 406 : naludmx_del_param_list(ctx->vvc_dci);
3469 :
3470 406 : if (ctx->avc_state) gf_free(ctx->avc_state);
3471 406 : if (ctx->hevc_state) gf_free(ctx->hevc_state);
3472 406 : if (ctx->vvc_state) gf_free(ctx->vvc_state);
3473 406 : }
3474 :
3475 :
3476 3072 : static const char *naludmx_probe_data(const u8 *data, u32 size, GF_FilterProbeScore *score)
3477 : {
3478 : u32 sc, sc_size;
3479 : u32 not_hevc=0;
3480 : u32 not_avc=0;
3481 : u32 not_vvc=0;
3482 : u32 nb_hevc=0;
3483 : u32 nb_avc=0;
3484 : u32 nb_vvc=0;
3485 : u32 nb_nalus=0;
3486 : u32 nb_hevc_zero=0;
3487 : u32 nb_avc_zero=0;
3488 : u32 nb_vvc_zero=0;
3489 : u32 nb_sps_hevc=0,nb_pps_hevc=0,nb_vps_hevc=0;
3490 : u32 nb_sps_avc=0,nb_pps_avc=0;
3491 : u32 nb_sps_vvc=0,nb_pps_vvc=0,nb_vps_vvc=0;
3492 :
3493 87551 : while (size>3) {
3494 : u32 nal_type=0;
3495 84451 : sc = gf_media_nalu_next_start_code(data, size, &sc_size);
3496 84451 : if (!sc_size) break;
3497 :
3498 82946 : data += sc + sc_size;
3499 82946 : if (size <= sc + sc_size) break;
3500 81407 : size -= sc + sc_size;
3501 :
3502 81407 : if (data[0] & 0x80) {
3503 15042 : not_avc++;
3504 15042 : not_hevc++;
3505 15042 : not_vvc++;
3506 15042 : continue;
3507 : }
3508 : nb_nalus++;
3509 :
3510 66365 : nal_type = (data[0] & 0x7E) >> 1;
3511 66365 : if (nal_type<=40) {
3512 61715 : nb_hevc++;
3513 61715 : switch (nal_type) {
3514 946 : case GF_HEVC_NALU_PIC_PARAM:
3515 946 : if (nb_sps_hevc)
3516 715 : nb_pps_hevc++;
3517 : break;
3518 316 : case GF_HEVC_NALU_SEQ_PARAM:
3519 316 : nb_sps_hevc++;
3520 316 : break;
3521 3895 : case GF_HEVC_NALU_VID_PARAM:
3522 3895 : nb_vps_hevc++;
3523 3895 : break;
3524 40245 : case 0:
3525 40245 : nb_hevc_zero++;
3526 40245 : break;
3527 : }
3528 : } else {
3529 4650 : not_hevc++;
3530 : }
3531 :
3532 66365 : nal_type = data[0] & 0x1F;
3533 66365 : if (nal_type && nal_type<=24) {
3534 24560 : nb_avc++;
3535 24560 : switch (nal_type) {
3536 930 : case GF_AVC_NALU_PIC_PARAM:
3537 930 : if (nb_sps_avc)
3538 594 : nb_pps_avc++;
3539 : break;
3540 729 : case GF_AVC_NALU_SEQ_PARAM:
3541 729 : nb_sps_avc++;
3542 729 : break;
3543 0 : case 0:
3544 0 : nb_avc_zero++;
3545 0 : break;
3546 : }
3547 : } else {
3548 41805 : not_avc++;
3549 : }
3550 :
3551 : //check vvc - 2nd bit reserved to 0
3552 66365 : if (data[0] & 0x40) {
3553 13247 : not_vvc++;
3554 13247 : continue;
3555 : }
3556 53118 : nal_type = data[1] >> 3;
3557 : if (nal_type>31) {
3558 : not_vvc++;
3559 : continue;
3560 : }
3561 53118 : nb_vvc++;
3562 53118 : switch (nal_type) {
3563 32 : case GF_VVC_NALU_PIC_PARAM:
3564 32 : if (nb_sps_vvc)
3565 6 : nb_pps_vvc++;
3566 : break;
3567 14 : case GF_VVC_NALU_SEQ_PARAM:
3568 14 : nb_sps_vvc++;
3569 14 : break;
3570 180 : case GF_VVC_NALU_VID_PARAM:
3571 180 : nb_vps_vvc++;
3572 180 : break;
3573 48876 : case 0:
3574 48876 : nb_vvc_zero++;
3575 48876 : break;
3576 : }
3577 : }
3578 :
3579 3072 : if (!nb_sps_avc || !nb_pps_avc) nb_avc=0;
3580 3072 : if (!nb_sps_hevc || !nb_pps_hevc || !nb_vps_hevc) nb_hevc=0;
3581 3072 : if (!nb_sps_vvc || !nb_pps_vvc || !nb_vps_vvc) nb_vvc=0;
3582 3072 : if (not_avc) nb_avc=0;
3583 3072 : if (not_hevc) nb_hevc=0;
3584 3072 : if (not_vvc) nb_vvc=0;
3585 :
3586 3072 : if (not_avc && not_hevc && not_vvc) return NULL;
3587 1981 : if (nb_avc==nb_avc_zero) nb_avc=0;
3588 1981 : if (nb_hevc==nb_hevc_zero) nb_hevc=0;
3589 1981 : if (nb_vvc==nb_vvc_zero) nb_vvc=0;
3590 :
3591 1981 : if (!nb_hevc && !nb_avc && !nb_vvc) return NULL;
3592 381 : *score = GF_FPROBE_SUPPORTED;
3593 381 : if (!nb_hevc) return (nb_vvc>nb_avc) ? "video/vvc" : "video/avc";
3594 134 : if (!nb_avc) return (nb_vvc>nb_hevc) ? "video/vvc" : "video/hevc";
3595 0 : if (!nb_vvc) return (nb_avc>nb_hevc) ? "video/avc" : "video/hevc";
3596 :
3597 0 : if ((nb_hevc>nb_avc) && (nb_hevc>nb_vvc)) return "video/hevc";
3598 0 : if ((nb_vvc>nb_avc) && (nb_vvc>nb_hevc)) return "video/vvc";
3599 0 : return "video/avc";
3600 : }
3601 :
3602 : static const GF_FilterCapability NALUDmxCaps[] =
3603 : {
3604 : CAP_UINT(GF_CAPS_INPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
3605 : CAP_STRING(GF_CAPS_INPUT, GF_PROP_PID_FILE_EXT, "264|h264|26L|h26L|h26l|avc|svc|mvc|hevc|hvc|265|h265|shvc|lvhc|mhvc|266|vvc|lvvc"),
3606 : CAP_STRING(GF_CAPS_INPUT, GF_PROP_PID_MIME, "video/avc|video/h264|video/svc|video/mvc|video/hevc|video/lhvc|video/shvc|video/mhvc|video/vvc"),
3607 : CAP_UINT(GF_CAPS_OUTPUT_STATIC, GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
3608 : CAP_UINT(GF_CAPS_OUTPUT_STATIC, GF_PROP_PID_CODECID, GF_CODECID_AVC),
3609 : CAP_UINT(GF_CAPS_OUTPUT_STATIC, GF_PROP_PID_CODECID, GF_CODECID_AVC_PS),
3610 : CAP_UINT(GF_CAPS_OUTPUT_STATIC, GF_PROP_PID_CODECID, GF_CODECID_SVC),
3611 : CAP_UINT(GF_CAPS_OUTPUT_STATIC, GF_PROP_PID_CODECID, GF_CODECID_MVC),
3612 : CAP_UINT(GF_CAPS_OUTPUT_STATIC, GF_PROP_PID_CODECID, GF_CODECID_HEVC),
3613 : CAP_UINT(GF_CAPS_OUTPUT_STATIC, GF_PROP_PID_CODECID, GF_CODECID_LHVC),
3614 : CAP_UINT(GF_CAPS_OUTPUT_STATIC, GF_PROP_PID_CODECID, GF_CODECID_VVC),
3615 : CAP_BOOL(GF_CAPS_OUTPUT_STATIC_EXCLUDED, GF_PROP_PID_UNFRAMED, GF_TRUE),
3616 : CAP_BOOL(GF_CAPS_OUTPUT_STATIC_EXCLUDED, GF_PROP_PID_TILE_BASE, GF_TRUE),
3617 : {0},
3618 : CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
3619 : CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AVC),
3620 : CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AVC_PS),
3621 : CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_SVC),
3622 : CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_MVC),
3623 : CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_HEVC),
3624 : CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_LHVC),
3625 : CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_VVC),
3626 : CAP_BOOL(GF_CAPS_INPUT,GF_PROP_PID_UNFRAMED, GF_TRUE),
3627 : CAP_BOOL(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_TILE_BASE, GF_TRUE),
3628 : };
3629 :
3630 : #define OFFS(_n) #_n, offsetof(GF_NALUDmxCtx, _n)
3631 : static const GF_FilterArgs NALUDmxArgs[] =
3632 : {
3633 : { OFFS(fps), "import frame rate (0 default to FPS from bitstream or 25 Hz)", GF_PROP_FRACTION, "0/1000", NULL, 0},
3634 : { OFFS(index), "indexing window length. If 0, bitstream is not probed for duration. A negative value skips the indexing if the source file is larger than 100M (slows down importers) unless a play with start range > 0 is issued, otherwise uses the positive value", GF_PROP_DOUBLE, "-1.0", NULL, 0},
3635 : { OFFS(explicit), "use explicit layered (SVC/LHVC) import", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED},
3636 : { OFFS(strict_poc), "delay frame output of an entire GOP to ensure CTS info is correct when POC suddenly changes\n"
3637 : "- off: disable GOP buffering\n"
3638 : "- on: enable GOP buffering, assuming no error in POC\n"
3639 : "- error: enable GOP buffering and try to detect lost frames", GF_PROP_UINT, "off", "off|on|error", GF_FS_ARG_HINT_ADVANCED},
3640 : { OFFS(nosei), "remove all sei messages", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED},
3641 : { OFFS(nosvc), "remove all SVC/MVC/LHVC data", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED},
3642 : { OFFS(novpsext), "remove all VPS extensions", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED},
3643 : { OFFS(importer), "compatibility with old importer, displays import results", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED},
3644 : { OFFS(idur), "compatibility with old importer to log imported frames only", GF_PROP_FRACTION, "0", NULL, GF_FS_ARG_HINT_HIDE},
3645 : { OFFS(nal_length), "set number of bytes used to code length field: 1, 2 or 4", GF_PROP_UINT, "4", NULL, GF_FS_ARG_HINT_EXPERT},
3646 : { OFFS(subsamples), "import subsamples information", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_EXPERT},
3647 : { OFFS(deps), "import samples dependencies information", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_EXPERT},
3648 : { OFFS(seirw), "rewrite AVC sei messages for ISOBMFF constraints", GF_PROP_BOOL, "true", NULL, GF_FS_ARG_HINT_EXPERT},
3649 : { OFFS(audelim), "keep Access Unit delimiter in payload", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_EXPERT},
3650 : { OFFS(analyze), "skip reformat of decoder config and SEI and dispatch all NAL in input order - shall only be used with inspect filter analyze mode!", GF_PROP_UINT, "off", "off|on|bs|full", GF_FS_ARG_HINT_HIDE},
3651 :
3652 : { OFFS(bsdbg), "debug NAL parsing in parser@debug logs\n"
3653 : "- off: not enabled\n"
3654 : "- on: enabled\n"
3655 : "- full: enable with number of bits dumped", GF_PROP_UINT, "off", "off|on|full", GF_FS_ARG_HINT_EXPERT},
3656 : {0}
3657 : };
3658 :
3659 :
3660 : GF_FilterRegister NALUDmxRegister = {
3661 : .name = "rfnalu",
3662 : GF_FS_SET_DESCRIPTION("AVC/HEVC reframer")
3663 : GF_FS_SET_HELP("This filter parses AVC|H264 and HEVC files/data and outputs corresponding video PID and frames.\n"
3664 : "This demuxer only produces ISOBMFF-compatible output: start codes are removed, NALU length field added and avcC/hvcC config created.\nNote: The demux uses negative CTS offsets: CTS is corrrect, but some frames may have DTS greater than CTS.")
3665 : .private_size = sizeof(GF_NALUDmxCtx),
3666 : .args = NALUDmxArgs,
3667 : .initialize = naludmx_initialize,
3668 : .finalize = naludmx_finalize,
3669 : SETCAPS(NALUDmxCaps),
3670 : .configure_pid = naludmx_configure_pid,
3671 : .process = naludmx_process,
3672 : .process_event = naludmx_process_event,
3673 : .probe_data = naludmx_probe_data,
3674 : };
3675 :
3676 :
3677 2877 : const GF_FilterRegister *naludmx_register(GF_FilterSession *session)
3678 : {
3679 2877 : return &NALUDmxRegister;
3680 : }
3681 :
3682 : #else
3683 : const GF_FilterRegister *naludmx_register(GF_FilterSession *session)
3684 : {
3685 : return NULL;
3686 : }
3687 : #endif //GPAC_DISABLE_AV_PARSERS
|