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