LCOV - code coverage report
Current view: top level - filters - reframe_nalu.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1398 1894 73.8 %
Date: 2021-04-29 23:48:07 Functions: 27 31 87.1 %

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

Generated by: LCOV version 1.13