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