LCOV - code coverage report
Current view: top level - isomedia - avc_ext.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1457 1946 74.9 %
Date: 2021-04-29 23:48:07 Functions: 108 119 90.8 %

          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 / ISO Media File Format sub-project
       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/internal/isomedia_dev.h>
      27             : #include <gpac/constants.h>
      28             : #include <gpac/internal/media_dev.h>
      29             : 
      30             : #ifndef GPAC_DISABLE_ISOM
      31             : 
      32             : 
      33      510717 : Bool gf_isom_is_nalu_based_entry(GF_MediaBox *mdia, GF_SampleEntryBox *_entry)
      34             : {
      35             :         GF_MPEGVisualSampleEntryBox *entry;
      36      510717 :         if (!gf_isom_is_video_handler_type(mdia->handler->handlerType))
      37             :                 return GF_FALSE;
      38      366686 :         if (!_entry) return GF_FALSE;
      39             :         entry = (GF_MPEGVisualSampleEntryBox*)_entry;
      40             : 
      41      366686 :         switch (_entry->type) {
      42             :         case GF_ISOM_BOX_TYPE_AVC1:
      43             :         case GF_ISOM_BOX_TYPE_AVC2:
      44             :         case GF_ISOM_BOX_TYPE_AVC3:
      45             :         case GF_ISOM_BOX_TYPE_AVC4:
      46             :         case GF_ISOM_BOX_TYPE_SVC1:
      47             :         case GF_ISOM_BOX_TYPE_SVC2:
      48             :         case GF_ISOM_BOX_TYPE_MVC1:
      49             :         case GF_ISOM_BOX_TYPE_MVC2:
      50             :         case GF_ISOM_BOX_TYPE_HVC1:
      51             :         case GF_ISOM_BOX_TYPE_HEV1:
      52             :         case GF_ISOM_BOX_TYPE_HVC2:
      53             :         case GF_ISOM_BOX_TYPE_HEV2:
      54             :         case GF_ISOM_BOX_TYPE_LHV1:
      55             :         case GF_ISOM_BOX_TYPE_LHE1:
      56             :         case GF_ISOM_BOX_TYPE_MHV1:
      57             :         case GF_ISOM_BOX_TYPE_MHC1:
      58             :         case GF_ISOM_BOX_TYPE_HVT1:
      59             :         case GF_ISOM_BOX_TYPE_LHT1:
      60             :                 return GF_TRUE;
      61           0 :         case GF_ISOM_BOX_TYPE_GNRV:
      62             :         case GF_ISOM_BOX_TYPE_GNRA:
      63             :         case GF_ISOM_BOX_TYPE_GNRM:
      64           0 :                 return GF_FALSE;
      65             :         default:
      66             :                 break;
      67             :         }
      68             : 
      69       66570 :         if (!gf_isom_is_video_handler_type(entry->internal_type))
      70             :                 return GF_FALSE;
      71             : 
      72       66570 :         if (entry->avc_config || entry->svc_config || entry->mvc_config || entry->hevc_config || entry->lhvc_config) {
      73       22733 :                 GF_ProtectionSchemeInfoBox *schi = (GF_ProtectionSchemeInfoBox *) gf_isom_box_find_child(entry->child_boxes, GF_ISOM_BOX_TYPE_SINF);
      74       22733 :                 if (!schi || !schi->scheme_type) return GF_TRUE;
      75       22733 :                 switch (schi->scheme_type->scheme_type) {
      76             :                 case GF_ISOM_CENC_SCHEME:
      77             :                 case GF_ISOM_CBC_SCHEME:
      78             :                 case GF_ISOM_CENS_SCHEME:
      79             :                 case GF_ISOM_CBCS_SCHEME:
      80             :                         return GF_TRUE;
      81             :                 default:
      82             :                         break;
      83             :                 }
      84       43837 :         }
      85             :         return GF_FALSE;
      86             : }
      87             : 
      88             : 
      89         630 : static void rewrite_nalus_list(GF_List *nalus, GF_BitStream *bs, Bool rewrite_start_codes, u32 nal_unit_size_field)
      90             : {
      91         630 :         u32 i, count = gf_list_count(nalus);
      92        1200 :         for (i=0; i<count; i++) {
      93         570 :                 GF_NALUFFParam *sl = (GF_NALUFFParam*)gf_list_get(nalus, i);
      94         570 :                 if (rewrite_start_codes) gf_bs_write_u32(bs, 1);
      95         570 :                 else gf_bs_write_int(bs, sl->size, 8*nal_unit_size_field);
      96         570 :                 gf_bs_write_data(bs, sl->data, sl->size);
      97             :         }
      98         630 : }
      99             : 
     100             : 
     101        1262 : static GF_Err process_extractor(GF_ISOFile *file, GF_MediaBox *mdia, u32 sampleNumber, u64 sampleDTS, u32 nal_size, u16 nal_hdr, u32 nal_unit_size_field, Bool is_hevc, Bool rewrite_ps, Bool rewrite_start_codes, u32 extractor_mode)
     102             : {
     103             :         GF_Err e;
     104             :         u32 di, ref_track_index, ref_track_num, data_offset, data_length, cur_extract_mode, ref_extract_mode, ref_nalu_size, nb_bytes_nalh;
     105             :         GF_TrackReferenceTypeBox *dpnd;
     106             :         GF_TrackBox *ref_trak;
     107             :         s8 sample_offset;
     108             :         u32 last_byte, ref_sample_num, prev_ref_sample_num;
     109             :         Bool header_written = GF_FALSE;
     110        1262 :         nb_bytes_nalh = is_hevc ? 2 : 1;
     111             : 
     112        1262 :         switch (extractor_mode) {
     113           0 :         case 0:
     114           0 :                 last_byte = (u32) gf_bs_get_position(mdia->nalu_parser) + nal_size - (is_hevc ? 2 : 1);
     115           0 :                 if (!is_hevc) gf_bs_read_int(mdia->nalu_parser, 24); //1 byte for HEVC , 3 bytes for AVC of NALUHeader in extractor
     116           0 :                 while (gf_bs_get_position(mdia->nalu_parser) < last_byte) {
     117             :                         u32 xmode = 0;
     118             :                         //hevc extractors use constructors
     119           0 :                         if (is_hevc) xmode = gf_bs_read_u8(mdia->nalu_parser);
     120           0 :                         if (xmode) {
     121           0 :                                 u8 done=0, len = gf_bs_read_u8(mdia->nalu_parser);
     122           0 :                                 while (done<len) {
     123           0 :                                         u8 c = gf_bs_read_u8(mdia->nalu_parser);
     124           0 :                                         done++;
     125           0 :                                         if (header_written) {
     126           0 :                                                 gf_bs_write_u8(mdia->nalu_out_bs, c);
     127           0 :                                         } else if (done==nal_unit_size_field) {
     128           0 :                                                 if (rewrite_start_codes) {
     129           0 :                                                         gf_bs_write_int(mdia->nalu_out_bs, 1, 32);
     130             :                                                 } else {
     131           0 :                                                         gf_bs_write_u8(mdia->nalu_out_bs, c);
     132             :                                                 }
     133             :                                                 header_written = GF_TRUE;
     134           0 :                                         } else if (!rewrite_start_codes) {
     135           0 :                                                 gf_bs_write_u8(mdia->nalu_out_bs, c);
     136             :                                         }
     137             :                                 }
     138           0 :                                 continue;
     139             :                         }
     140             : 
     141           0 :                         ref_track_index = gf_bs_read_u8(mdia->nalu_parser);
     142           0 :                         sample_offset = (s8) gf_bs_read_int(mdia->nalu_parser, 8);
     143           0 :                         data_offset = gf_bs_read_int(mdia->nalu_parser, nal_unit_size_field*8);
     144           0 :                         data_length = gf_bs_read_int(mdia->nalu_parser, nal_unit_size_field*8);
     145             : 
     146           0 :                         Track_FindRef(mdia->mediaTrack, GF_ISOM_REF_SCAL, &dpnd);
     147             :                         ref_track_num = 0;
     148           0 :                         if (dpnd && ref_track_index && (ref_track_index<=dpnd->trackIDCount))
     149           0 :                                 ref_track_num = gf_isom_get_track_by_id(file, dpnd->trackIDs[ref_track_index-1]);
     150             : 
     151           0 :                         if (!ref_track_num) {
     152           0 :                                 GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("ISOBMF: Extractor target track is not present in file - skipping.\n"));
     153             :                                 return GF_OK;
     154             :                         }
     155             : 
     156           0 :                         cur_extract_mode = gf_isom_get_nalu_extract_mode(file, ref_track_num);
     157             : 
     158             :                         //we must be in inspect mode only otherwise the reference sample will not be the one stored on file (change in start codes, PS inserted or other NALUs inserted)
     159             :                         //and this will corrupt extraction (wrong data offsets)
     160             :                         ref_extract_mode = GF_ISOM_NALU_EXTRACT_INSPECT;
     161           0 :                         gf_isom_set_nalu_extract_mode(file, ref_track_num, ref_extract_mode);
     162             : 
     163           0 :                         ref_trak = gf_isom_get_track_from_file(file, ref_track_num);
     164           0 :                         if (!ref_trak) return GF_ISOM_INVALID_FILE;
     165             : 
     166           0 :                         if (!mdia->extracted_samp) {
     167           0 :                                 mdia->extracted_samp = gf_isom_sample_new();
     168           0 :                                 if (!mdia->extracted_samp) return GF_IO_ERR;
     169             :                         }
     170           0 :                         if (!mdia->extracted_bs) {
     171           0 :                                 mdia->extracted_bs = gf_bs_new("a", 1, GF_BITSTREAM_READ);
     172           0 :                                 if (!mdia->extracted_bs) return GF_IO_ERR;
     173             :                         }
     174             : 
     175           0 :                         e = stbl_findEntryForTime(ref_trak->Media->information->sampleTable, sampleDTS, 0, &ref_sample_num, &prev_ref_sample_num);
     176           0 :                         if (e) return e;
     177           0 :                         if (!ref_sample_num) ref_sample_num = prev_ref_sample_num;
     178           0 :                         if (!ref_sample_num) return GF_ISOM_INVALID_FILE;
     179           0 :                         if ((sample_offset<0) && (ref_sample_num > (u32) -sample_offset)) return GF_ISOM_INVALID_FILE;
     180           0 :                         ref_sample_num = (u32) ( (s32) ref_sample_num + sample_offset);
     181             : 
     182           0 :                         e = Media_GetSample(ref_trak->Media, ref_sample_num, &mdia->extracted_samp, &di, GF_FALSE, NULL);
     183           0 :                         if (e) return e;
     184           0 :                         if (!mdia->extracted_samp->alloc_size)
     185           0 :                                 mdia->extracted_samp->alloc_size = mdia->extracted_samp->dataLength;
     186             : #if 0
     187             :                         if (!header_written && rewrite_start_codes) {
     188             :                                 gf_bs_write_int(dst_bs, 1, 32);
     189             :                                 if (is_hevc) {
     190             :                                         gf_bs_write_int(dst_bs, 0, 1);
     191             :                                         gf_bs_write_int(dst_bs, GF_HEVC_NALU_ACCESS_UNIT, 6);
     192             :                                         gf_bs_write_int(dst_bs, 0, 9);
     193             :                                         /*pic-type - by default we signal all slice types possible*/
     194             :                                         gf_bs_write_int(dst_bs, 2, 3);
     195             :                                         gf_bs_write_int(dst_bs, 0, 5);
     196             :                                 } else {
     197             :                                         gf_bs_write_int(dst_bs, (ref_samp->data[0] & 0x60) | GF_AVC_NALU_ACCESS_UNIT, 8);
     198             :                                         gf_bs_write_int(dst_bs, 0xF0 , 8); /*7 "all supported NALUs" (=111) + rbsp trailing (10000)*/;
     199             :                                 }
     200             :                         }
     201             : #endif
     202           0 :                         gf_bs_reassign_buffer(mdia->extracted_bs, mdia->extracted_samp->data + data_offset, mdia->extracted_samp->dataLength - data_offset);
     203             : 
     204           0 :                         if (mdia->extracted_samp->dataLength - data_offset >= data_length) {
     205             : 
     206           0 :                                 while (data_length && gf_bs_available(mdia->extracted_bs)) {
     207           0 :                                         if (!header_written) {
     208           0 :                                                 ref_nalu_size = gf_bs_read_int(mdia->extracted_bs, 8*nal_unit_size_field);
     209             : 
     210             :                                                 assert(data_length>nal_unit_size_field);
     211           0 :                                                 data_length -= nal_unit_size_field;
     212           0 :                                                 if (data_length > gf_bs_available(mdia->extracted_bs)) {
     213           0 :                                                         data_length = (u32)gf_bs_available(mdia->extracted_bs);
     214             :                                                 }
     215             :                                         } else {
     216             :                                                 ref_nalu_size = data_length;
     217             :                                         }
     218             : 
     219           0 :                                         if (ref_nalu_size > mdia->tmp_nal_copy_buffer_alloc) {
     220           0 :                                                 mdia->tmp_nal_copy_buffer_alloc = ref_nalu_size;
     221           0 :                                                 mdia->tmp_nal_copy_buffer = (char*) gf_realloc(mdia->tmp_nal_copy_buffer, sizeof(char) * ref_nalu_size );
     222             :                                         }
     223           0 :                                         gf_bs_read_data(mdia->extracted_bs, mdia->tmp_nal_copy_buffer, ref_nalu_size);
     224             : 
     225           0 :                                         if (!header_written) {
     226           0 :                                                 if (rewrite_start_codes)
     227           0 :                                                         gf_bs_write_u32(mdia->nalu_out_bs, 1);
     228             :                                                 else
     229           0 :                                                         gf_bs_write_int(mdia->nalu_out_bs, ref_nalu_size, 8*nal_unit_size_field);
     230             :                                         }
     231             :                                         assert(data_length >= ref_nalu_size);
     232           0 :                                         gf_bs_write_data(mdia->nalu_out_bs, mdia->tmp_nal_copy_buffer, ref_nalu_size);
     233           0 :                                         data_length -= ref_nalu_size;
     234             : 
     235             :                                         header_written = GF_FALSE;
     236             : 
     237             :                                 }
     238             :                         } else {
     239           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("ISOBMF: Extractor size is larger than referred sample size - skipping.\n"));
     240             :                         }
     241           0 :                         gf_isom_set_nalu_extract_mode(file, ref_track_num, cur_extract_mode);
     242             : 
     243           0 :                         if (!is_hevc) break;
     244             :                 }
     245             :                 break;
     246        1262 :         case 1:
     247             :                 //skip to end of this NALU
     248        1262 :                 gf_bs_skip_bytes(mdia->nalu_parser, nal_size - nb_bytes_nalh);
     249        1262 :                 break;
     250           0 :         case 2:
     251           0 :                 if (nal_size - nb_bytes_nalh > mdia->tmp_nal_copy_buffer_alloc) {
     252           0 :                         mdia->tmp_nal_copy_buffer_alloc = nal_size - nb_bytes_nalh;
     253           0 :                         mdia->tmp_nal_copy_buffer = (char*) gf_realloc(mdia->tmp_nal_copy_buffer, sizeof(char) * (nal_size - nb_bytes_nalh) );
     254             :                 }
     255           0 :                 gf_bs_read_data(mdia->nalu_parser, mdia->tmp_nal_copy_buffer, nal_size - nb_bytes_nalh);
     256           0 :                 if (rewrite_start_codes)
     257           0 :                         gf_bs_write_u32(mdia->nalu_out_bs, 1);
     258             :                 else
     259           0 :                         gf_bs_write_int(mdia->nalu_out_bs, nal_size, 8*nal_unit_size_field);
     260             : 
     261           0 :                 gf_bs_write_u8(mdia->nalu_out_bs, nal_hdr);
     262           0 :                 gf_bs_write_data(mdia->nalu_out_bs, mdia->tmp_nal_copy_buffer, nal_size - nb_bytes_nalh);
     263           0 :                 break;
     264             :         }
     265             :         return GF_OK;
     266             : }
     267             : 
     268             : #ifndef GPAC_DISABLE_HEVC
     269             : /* returns the SAP type as defined in the 14496-12 specification */
     270             : static GF_ISOSAPType sap_type_from_nal_type(u8 nal_type) {
     271             :         switch (nal_type) {
     272             :         case GF_HEVC_NALU_SLICE_CRA:
     273             :                 return SAP_TYPE_3;
     274             :         case GF_HEVC_NALU_SLICE_IDR_N_LP:
     275             :         case GF_HEVC_NALU_SLICE_BLA_N_LP:
     276             :                 return SAP_TYPE_1;
     277             :         case GF_HEVC_NALU_SLICE_IDR_W_DLP:
     278             :         case GF_HEVC_NALU_SLICE_BLA_W_DLP:
     279             :         case GF_HEVC_NALU_SLICE_BLA_W_LP:
     280             :                 return SAP_TYPE_2;
     281           0 :         default:
     282             :                 return RAP_NO;
     283             :         }
     284             : }
     285             : #endif
     286             : 
     287      288873 : static GF_ISOSAPType is_sample_idr(GF_MediaBox *mdia, GF_ISOSample *sample, GF_MPEGVisualSampleEntryBox *entry)
     288             : {
     289             :         Bool is_hevc = GF_FALSE;
     290             :         u32 nalu_size_field = 0;
     291      288873 :         if (entry->avc_config && entry->avc_config->config) nalu_size_field = entry->avc_config->config->nal_unit_size;
     292       96608 :         else if (entry->svc_config && entry->svc_config->config) nalu_size_field = entry->svc_config->config->nal_unit_size;
     293       94391 :         else if (entry->mvc_config && entry->mvc_config->config) nalu_size_field = entry->mvc_config->config->nal_unit_size;
     294       94391 :         else if (entry->hevc_config && entry->hevc_config->config) {
     295       94391 :                 nalu_size_field = entry->hevc_config->config->nal_unit_size;
     296             :                 is_hevc = GF_TRUE;
     297             :         }
     298           0 :         else if (entry->lhvc_config && entry->lhvc_config->config) {
     299           0 :                 nalu_size_field = entry->lhvc_config->config->nal_unit_size;
     300             :                 is_hevc = GF_TRUE;
     301             :         }
     302      288873 :         if (!nalu_size_field) return RAP_NO;
     303             : 
     304      288873 :         if (!mdia->nalu_parser)
     305         576 :                 mdia->nalu_parser = gf_bs_new(sample->data, sample->dataLength, GF_BITSTREAM_READ);
     306             :         else
     307      288297 :                 gf_bs_reassign_buffer(mdia->nalu_parser, sample->data, sample->dataLength);
     308             : 
     309      288873 :         if (!mdia->nalu_parser) return RAP_NO;
     310             : 
     311      301673 :         while (gf_bs_available(mdia->nalu_parser)) {
     312             :                 u8 nal_type;
     313      299456 :                 u32 size = gf_bs_read_int(mdia->nalu_parser, 8*nalu_size_field);
     314             : 
     315      299456 :                 if (is_hevc) {
     316             : #ifndef GPAC_DISABLE_HEVC
     317       95335 :                         u16 nal_hdr = gf_bs_read_u16(mdia->nalu_parser);
     318       95335 :                         nal_type = (nal_hdr&0x7E00) >> 9;
     319             : 
     320       95335 :                         switch (nal_type) {
     321             :                         case GF_HEVC_NALU_SLICE_CRA:
     322             :                                 return SAP_TYPE_3;
     323           0 :                         case GF_HEVC_NALU_SLICE_IDR_N_LP:
     324             :                         case GF_HEVC_NALU_SLICE_BLA_N_LP:
     325             :                                 return SAP_TYPE_1;
     326           9 :                         case GF_HEVC_NALU_SLICE_IDR_W_DLP:
     327             :                         case GF_HEVC_NALU_SLICE_BLA_W_DLP:
     328             :                         case GF_HEVC_NALU_SLICE_BLA_W_LP:
     329             :                                 return SAP_TYPE_2;
     330             :                         case GF_HEVC_NALU_ACCESS_UNIT:
     331             :                         case GF_HEVC_NALU_FILLER_DATA:
     332             :                         case GF_HEVC_NALU_SEI_PREFIX:
     333             :                         case GF_HEVC_NALU_VID_PARAM:
     334             :                         case GF_HEVC_NALU_SEQ_PARAM:
     335             :                         case GF_HEVC_NALU_PIC_PARAM:
     336             :                                 break;
     337       94320 :                         default:
     338             :                                 return RAP_NO;
     339             :                         }
     340         944 :                         gf_bs_skip_bytes(mdia->nalu_parser, size - 2);
     341             : #endif
     342             :                 } else {
     343      204121 :                         u8 nal_hdr = gf_bs_read_u8(mdia->nalu_parser);
     344      204121 :                         nal_type = nal_hdr & 0x1F;
     345             : 
     346      204121 :                         if (nal_type==GF_AVC_NALU_IDR_SLICE) return SAP_TYPE_1;
     347      204107 :                         if (nal_type<GF_AVC_NALU_IDR_SLICE) return RAP_NO;
     348       11856 :                         gf_bs_skip_bytes(mdia->nalu_parser, size - 1);
     349             :                 }
     350             :         }
     351             :         return RAP_NO;
     352             : }
     353             : 
     354         210 : static void nalu_merge_ps(GF_BitStream *ps_bs, Bool rewrite_start_codes, u32 nal_unit_size_field, GF_MPEGVisualSampleEntryBox *entry, Bool is_hevc, Bool *has_vps)
     355             : {
     356             :         u32 i, count;
     357         210 :         if (is_hevc) {
     358         150 :                 if (entry->hevc_config) {
     359         150 :                         count = gf_list_count(entry->hevc_config->config->param_array);
     360         600 :                         for (i=0; i<count; i++) {
     361         450 :                                 GF_NALUFFParamArray *ar = (GF_NALUFFParamArray*)gf_list_get(entry->hevc_config->config->param_array, i);
     362         450 :                                 if (ar->type == GF_HEVC_NALU_VID_PARAM) {
     363         150 :                                         if (! *has_vps)  *has_vps = GF_TRUE;
     364           0 :                                         else continue;
     365             :                                 }
     366         450 :                                 rewrite_nalus_list(ar->nalus, ps_bs, rewrite_start_codes, nal_unit_size_field);
     367             :                         }
     368             :                 }
     369         150 :                 if (entry->lhvc_config) {
     370           0 :                         count = gf_list_count(entry->lhvc_config->config->param_array);
     371           0 :                         for (i=0; i<count; i++) {
     372           0 :                                 GF_NALUFFParamArray *ar = (GF_NALUFFParamArray*)gf_list_get(entry->lhvc_config->config->param_array, i);
     373           0 :                                 if (ar->type == GF_HEVC_NALU_VID_PARAM) {
     374           0 :                                         if (! *has_vps)  *has_vps = GF_TRUE;
     375           0 :                                         else continue;
     376             :                                 }
     377           0 :                                 rewrite_nalus_list(ar->nalus, ps_bs, rewrite_start_codes, nal_unit_size_field);
     378             :                         }
     379             :                 }
     380             :         } else {
     381          60 :                 if (entry->avc_config) {
     382          60 :                         rewrite_nalus_list(entry->avc_config->config->sequenceParameterSets, ps_bs, rewrite_start_codes, nal_unit_size_field);
     383          60 :                         rewrite_nalus_list(entry->avc_config->config->sequenceParameterSetExtensions, ps_bs, rewrite_start_codes, nal_unit_size_field);
     384          60 :                         rewrite_nalus_list(entry->avc_config->config->pictureParameterSets, ps_bs, rewrite_start_codes, nal_unit_size_field);
     385             :                 }
     386             : 
     387             :                 /*add svc config */
     388          60 :                 if (entry->svc_config) {
     389           0 :                         rewrite_nalus_list(entry->svc_config->config->sequenceParameterSets, ps_bs, rewrite_start_codes, nal_unit_size_field);
     390           0 :                         rewrite_nalus_list(entry->svc_config->config->pictureParameterSets, ps_bs, rewrite_start_codes, nal_unit_size_field);
     391             :                 }
     392             :                 /*add mvc config */
     393          60 :                 if (entry->mvc_config) {
     394           0 :                         rewrite_nalus_list(entry->mvc_config->config->sequenceParameterSets, ps_bs, rewrite_start_codes, nal_unit_size_field);
     395           0 :                         rewrite_nalus_list(entry->mvc_config->config->pictureParameterSets, ps_bs, rewrite_start_codes, nal_unit_size_field);
     396             :                 }
     397             :         }
     398         210 : }
     399             : 
     400             : 
     401      299951 : GF_Err gf_isom_nalu_sample_rewrite(GF_MediaBox *mdia, GF_ISOSample *sample, u32 sampleNumber, GF_MPEGVisualSampleEntryBox *entry)
     402             : {
     403             :         Bool is_hevc = GF_FALSE;
     404             :         //if only one sync given in the sample sync table, insert sps/pps/vps before cra/bla in hevc
     405             : //      Bool check_cra_bla = (mdia->information->sampleTable->SyncSample && mdia->information->sampleTable->SyncSample->nb_entries>1) ? 0 : 1;
     406             :         Bool check_cra_bla = GF_TRUE;
     407             :         Bool insert_nalu_delim = GF_TRUE;
     408             :         Bool force_sei_inspect = GF_FALSE;
     409             :         GF_Err e = GF_OK;
     410             :         GF_BitStream *sei_suffix_bs = NULL;
     411             :         Bool ps_transfered = GF_FALSE;
     412             :         u32 nal_size, nal_unit_size_field, extractor_mode;
     413             :         Bool rewrite_ps, rewrite_start_codes, insert_vdrd_code;
     414             :         u8 nal_type;
     415             :         u32 nal_hdr, sabt_ref, i, track_num;
     416             :         u32 temporal_id = 0;
     417      299951 :         GF_ISOFile *file = mdia->mediaTrack->moov->mov;
     418      299951 :         GF_TrackReferenceTypeBox *scal = NULL;
     419             : 
     420      299951 :         Track_FindRef(mdia->mediaTrack, GF_ISOM_REF_SCAL, &scal);
     421             : 
     422      299951 :         rewrite_ps = (mdia->mediaTrack->extractor_mode & GF_ISOM_NALU_EXTRACT_INBAND_PS_FLAG) ? GF_TRUE : GF_FALSE;
     423      299951 :         rewrite_start_codes = (mdia->mediaTrack->extractor_mode & GF_ISOM_NALU_EXTRACT_ANNEXB_FLAG) ? GF_TRUE : GF_FALSE;
     424             :         insert_vdrd_code = (mdia->mediaTrack->extractor_mode & GF_ISOM_NALU_EXTRACT_VDRD_FLAG) ? GF_TRUE : GF_FALSE;
     425      299951 :         if (!entry->svc_config && !entry->mvc_config && !entry->lhvc_config) insert_vdrd_code = GF_FALSE;
     426      299951 :         extractor_mode = mdia->mediaTrack->extractor_mode&0x0000FFFF;
     427             : 
     428      299951 :         if (mdia->mediaTrack->extractor_mode & GF_ISOM_NALU_EXTRACT_TILE_ONLY) {
     429             :                 insert_nalu_delim = GF_FALSE;
     430             :         }
     431             : 
     432      299951 :         track_num = 1 + gf_list_find(mdia->mediaTrack->moov->trackList, mdia->mediaTrack);
     433             : 
     434      299951 :         if ( (extractor_mode != GF_ISOM_NALU_EXTRACT_INSPECT) && !(mdia->mediaTrack->extractor_mode & GF_ISOM_NALU_EXTRACT_TILE_ONLY) ) {
     435             :                 u32 ref_track, di;
     436             :                 //aggregate all sabt samples with the same DTS
     437       17328 :                 if (entry->lhvc_config && !entry->hevc_config && !(mdia->mediaTrack->extractor_mode & GF_ISOM_NALU_EXTRACT_LAYER_ONLY)) {
     438           0 :                         if (gf_isom_get_reference_count(mdia->mediaTrack->moov->mov, track_num, GF_ISOM_REF_SCAL) <= 0) {
     439             :                                 //FIXME - for now we only support two layers (base + enh) in implicit
     440           0 :                                 if ( gf_isom_get_reference_count(mdia->mediaTrack->moov->mov, track_num, GF_ISOM_REF_BASE) >= 1) {
     441             :                                         GF_ISOSample *base_samp;
     442           0 :                                         gf_isom_get_reference(mdia->mediaTrack->moov->mov, track_num, GF_ISOM_REF_BASE, 1, &ref_track);
     443           0 :                                         switch (gf_isom_get_media_subtype(mdia->mediaTrack->moov->mov , ref_track, 1)) {
     444           0 :                                         case GF_ISOM_SUBTYPE_HVC1:
     445             :                                         case GF_ISOM_SUBTYPE_HVC2:
     446             :                                         case GF_ISOM_SUBTYPE_HEV1:
     447             :                                         case GF_ISOM_SUBTYPE_HEV2:
     448             : 
     449           0 :                                                 if (!mdia->extracted_samp) {
     450           0 :                                                         mdia->extracted_samp = gf_isom_sample_new();
     451           0 :                                                         if (!mdia->extracted_samp) return GF_OUT_OF_MEM;
     452             :                                                 }
     453             : 
     454           0 :                                                 base_samp = gf_isom_get_sample_ex(mdia->mediaTrack->moov->mov, ref_track, sampleNumber + mdia->mediaTrack->sample_count_at_seg_start, &di, mdia->extracted_samp, NULL);
     455           0 :                                                 if (base_samp && base_samp->data) {
     456           0 :                                                         if (!sample->alloc_size || (sample->alloc_size<sample->dataLength+base_samp->dataLength) ) {
     457           0 :                                                                 sample->data = gf_realloc(sample->data, sample->dataLength+base_samp->dataLength);
     458           0 :                                                                 if (sample->alloc_size) sample->alloc_size = sample->dataLength+base_samp->dataLength;
     459             :                                                         }
     460           0 :                                                         memmove(sample->data + base_samp->dataLength, sample->data , sample->dataLength);
     461           0 :                                                         memcpy(sample->data, base_samp->data, base_samp->dataLength);
     462           0 :                                                         sample->dataLength += base_samp->dataLength;
     463             :                                                 }
     464           0 :                                                 Track_FindRef(mdia->mediaTrack, GF_ISOM_REF_BASE, &scal);
     465           0 :                                                 break;
     466             :                                         }
     467             :                                 }
     468             :                         }
     469             :                 }
     470             : 
     471       17328 :                 sabt_ref = gf_isom_get_reference_count(mdia->mediaTrack->moov->mov, track_num, GF_ISOM_REF_SABT);
     472       17328 :                 if ((s32) sabt_ref > 0) {
     473             :                         force_sei_inspect = GF_TRUE;
     474       29960 :                         for (i=0; i<sabt_ref; i++) {
     475             :                                 GF_ISOSample *tile_samp;
     476       26964 :                                 gf_isom_get_reference(mdia->mediaTrack->moov->mov, track_num, GF_ISOM_REF_SABT, i+1, &ref_track);
     477             : 
     478       26964 :                                 if (!mdia->extracted_samp) {
     479           4 :                                         mdia->extracted_samp = gf_isom_sample_new();
     480           4 :                                         if (!mdia->extracted_samp) return GF_OUT_OF_MEM;
     481             :                                 }
     482             : 
     483       26964 :                                 tile_samp = gf_isom_get_sample_ex(mdia->mediaTrack->moov->mov, ref_track, sampleNumber + mdia->mediaTrack->sample_count_at_seg_start, &di, mdia->extracted_samp, NULL);
     484       26964 :                                 if (tile_samp  && tile_samp ->data) {
     485           0 :                                         if (!sample->alloc_size || (sample->alloc_size<sample->dataLength+tile_samp->dataLength) ) {
     486           0 :                                                 sample->data = gf_realloc(sample->data, sample->dataLength+tile_samp->dataLength);
     487           0 :                                                 if (sample->alloc_size) sample->alloc_size = sample->dataLength+tile_samp->dataLength;
     488             :                                         }
     489           0 :                                         memcpy(sample->data + sample->dataLength, tile_samp->data, tile_samp->dataLength);
     490           0 :                                         sample->dataLength += tile_samp->dataLength;
     491             :                                 }
     492             :                         }
     493             :                 }
     494             :         }
     495             : 
     496      299951 :         if ( gf_isom_get_reference_count(mdia->mediaTrack->moov->mov, track_num, GF_ISOM_REF_TBAS) >= 1) {
     497             :                 u32 ref_track;
     498       67659 :                 u32 idx = gf_list_find(mdia->information->sampleTable->SampleDescription->child_boxes, entry);
     499             :                 GF_TrackBox *tbas;
     500       67659 :                 gf_isom_get_reference(mdia->mediaTrack->moov->mov, track_num, GF_ISOM_REF_TBAS, 1, &ref_track);
     501       67659 :                 tbas = (GF_TrackBox *)gf_list_get(mdia->mediaTrack->moov->trackList, ref_track-1);
     502       67659 :                 entry = gf_list_get(tbas->Media->information->sampleTable->SampleDescription->child_boxes, idx);
     503             :         }
     504             : 
     505             : 
     506      299951 :         if (sample->IsRAP < SAP_TYPE_2) {
     507      299941 :                 if (mdia->information->sampleTable->no_sync_found || (!sample->IsRAP && check_cra_bla) ) {
     508      288873 :                         sample->IsRAP = is_sample_idr(mdia, sample, entry);
     509             :                 }
     510             :         }
     511      299951 :         if (!sample->IsRAP)
     512             :                 rewrite_ps = GF_FALSE;
     513             : 
     514      299951 :         if (extractor_mode != GF_ISOM_NALU_EXTRACT_LAYER_ONLY)
     515             :                 insert_vdrd_code = GF_FALSE;
     516             : 
     517      299951 :         if (!entry) return GF_BAD_PARAM;
     518             : 
     519             :         //this is a compatible HEVC, don't insert VDRD, insert NALU delim
     520      299951 :         if (entry->lhvc_config && entry->hevc_config)
     521             :                 insert_vdrd_code = GF_FALSE;
     522             : 
     523      299951 :         if (extractor_mode == GF_ISOM_NALU_EXTRACT_INSPECT) {
     524       61319 :                 if (!rewrite_ps && !rewrite_start_codes)
     525             :                         return GF_OK;
     526             :         }
     527             : 
     528             :         nal_unit_size_field = 0;
     529             :         /*if svc rewrite*/
     530      238632 :         if (entry->svc_config && entry->svc_config->config)
     531        1101 :                 nal_unit_size_field = entry->svc_config->config->nal_unit_size;
     532             :         /*if mvc rewrite*/
     533      238632 :         if (entry->mvc_config && entry->mvc_config->config)
     534           0 :                 nal_unit_size_field = entry->mvc_config->config->nal_unit_size;
     535             : 
     536             :         /*if lhvc rewrite*/
     537      238632 :         else if (entry->lhvc_config && entry->lhvc_config->config)  {
     538             :                 is_hevc = GF_TRUE;
     539        1274 :                 nal_unit_size_field = entry->lhvc_config->config->nal_unit_size;
     540             :         }
     541             : 
     542             :         /*otherwise do nothing*/
     543      237358 :         else if (!rewrite_ps && !rewrite_start_codes && !scal && !force_sei_inspect) {
     544             :                 return GF_OK;
     545             :         }
     546             : 
     547        4980 :         if (!nal_unit_size_field) {
     548        3206 :                 if (entry->avc_config && entry->avc_config->config)
     549          60 :                         nal_unit_size_field = entry->avc_config->config->nal_unit_size;
     550        3146 :                 else if (entry->lhvc_config && entry->lhvc_config->config) {
     551           0 :                         nal_unit_size_field = entry->lhvc_config->config->nal_unit_size;
     552           0 :                         is_hevc = GF_TRUE;
     553             :                 }
     554        3146 :                 else if (entry->hevc_config && entry->hevc_config->config) {
     555        3146 :                         nal_unit_size_field = entry->hevc_config->config->nal_unit_size;
     556             :                         is_hevc = GF_TRUE;
     557             :                 }
     558             :         }
     559             : 
     560        4980 :         if (!nal_unit_size_field) return GF_ISOM_INVALID_FILE;
     561             : 
     562             :         //setup PS rewriter
     563        4980 :         if (!mdia->nalu_ps_bs)
     564          15 :                 mdia->nalu_ps_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     565        4980 :         gf_bs_seek(mdia->nalu_ps_bs, 0);
     566             : 
     567             :         //setup sample reader
     568        4980 :         if (mdia->in_sample_buffer_alloc<sample->dataLength) {
     569          97 :                 mdia->in_sample_buffer_alloc = sample->dataLength;
     570          97 :                 mdia->in_sample_buffer = gf_realloc(mdia->in_sample_buffer, sample->dataLength);
     571             :         }
     572        4980 :         memcpy(mdia->in_sample_buffer, sample->data, sample->dataLength);
     573             : 
     574        4980 :         if (!mdia->nalu_parser) {
     575          11 :                 mdia->nalu_parser = gf_bs_new(mdia->in_sample_buffer, sample->dataLength, GF_BITSTREAM_READ);
     576          11 :                 if (!mdia->nalu_parser && sample->data) return GF_ISOM_INVALID_FILE;
     577             :         } else {
     578        4969 :                 e = gf_bs_reassign_buffer(mdia->nalu_parser, mdia->in_sample_buffer, sample->dataLength);
     579        4969 :                 if (e) return e;
     580             :         }
     581             :         //setup ouput
     582        4980 :         if (!mdia->nalu_out_bs) {
     583             :                 u8 *output;
     584             :                 u32 outSize;
     585          15 :                 mdia->nalu_out_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     586          15 :                 gf_bs_get_content(mdia->nalu_out_bs, &output, &outSize);
     587             :         }
     588             : 
     589        4980 :         gf_bs_reassign_buffer(mdia->nalu_out_bs, sample->data, sample->alloc_size ? sample->alloc_size : sample->dataLength);
     590             : 
     591             :         /*rewrite start code with NALU delim*/
     592        4980 :         if (rewrite_start_codes) {
     593             : 
     594             :                 //we are SVC, don't write NALU delim, only insert VDRD NALU
     595           0 :                 if (insert_vdrd_code) {
     596           0 :                         if (is_hevc) {
     597             :                                 //spec is not clear here, we don't insert an NALU AU delimiter before the layer starts since it breaks openHEVC
     598             : //                              insert_nalu_delim=0;
     599             :                         } else {
     600           0 :                                 gf_bs_write_int(mdia->nalu_out_bs, 1, 32);
     601           0 :                                 gf_bs_write_int(mdia->nalu_out_bs, GF_AVC_NALU_VDRD , 8);
     602             :                                 insert_nalu_delim=0;
     603             :                         }
     604             :                 }
     605             : 
     606             :                 //AVC/HEVC base, insert NALU delim
     607           0 :                 if (insert_nalu_delim) {
     608           0 :                         gf_bs_write_int(mdia->nalu_out_bs, 1, 32);
     609           0 :                         if (is_hevc) {
     610             : #ifndef GPAC_DISABLE_HEVC
     611           0 :                                 gf_bs_write_int(mdia->nalu_out_bs, 0, 1);
     612           0 :                                 gf_bs_write_int(mdia->nalu_out_bs, GF_HEVC_NALU_ACCESS_UNIT, 6);
     613           0 :                                 gf_bs_write_int(mdia->nalu_out_bs, insert_vdrd_code ? 1 : 0, 6); //we should pick the layerID of the following nalus ...
     614           0 :                                 gf_bs_write_int(mdia->nalu_out_bs, 1, 3); //nuh_temporal_id_plus1 - cannot be 0, we use 1 by default, and overwrite it if needed at the end
     615             : 
     616             :                                 /*pic-type - by default we signal all slice types possible*/
     617           0 :                                 gf_bs_write_int(mdia->nalu_out_bs, 2, 3);
     618           0 :                                 gf_bs_write_int(mdia->nalu_out_bs, 0, 5);
     619             : #endif
     620             :                         } else {
     621           0 :                                 gf_bs_write_int(mdia->nalu_out_bs, (sample->data[0] & 0x60) | GF_AVC_NALU_ACCESS_UNIT, 8);
     622           0 :                                 gf_bs_write_int(mdia->nalu_out_bs, 0xF0 , 8); /*7 "all supported NALUs" (=111) + rbsp trailing (10000)*/;
     623             :                         }
     624             :                 }
     625             :         }
     626             : 
     627        4980 :         if (rewrite_ps) {
     628         210 :                 Bool has_vps = GF_FALSE;
     629             :                 //in inspect mode or single-layer mode just use the xPS from this layer
     630         210 :                 if (extractor_mode == GF_ISOM_NALU_EXTRACT_DEFAULT) {
     631         210 :                         if (scal) {
     632           0 :                                 for (i=0; i<scal->trackIDCount; i++) {
     633           0 :                                         GF_TrackBox *a_track = GetTrackbyID(mdia->mediaTrack->moov, scal->trackIDs[i]);
     634             :                                         GF_MPEGVisualSampleEntryBox *an_entry = NULL;
     635           0 :                                         if (a_track && a_track->Media && a_track->Media->information && a_track->Media->information->sampleTable && a_track->Media->information->sampleTable->SampleDescription)
     636           0 :                                                 an_entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(a_track->Media->information->sampleTable->SampleDescription->child_boxes, 0);
     637             : 
     638           0 :                                         if (an_entry)
     639           0 :                                                 nalu_merge_ps(mdia->nalu_ps_bs, rewrite_start_codes, nal_unit_size_field, an_entry, is_hevc, &has_vps);
     640             :                                 }
     641             :                         }
     642             :                 }
     643         210 :                 nalu_merge_ps(mdia->nalu_ps_bs, rewrite_start_codes, nal_unit_size_field, entry, is_hevc, &has_vps);
     644             : 
     645             : 
     646         210 :                 if (is_hevc) {
     647             :                         /*little optimization if we are not asked to start codes: copy over the sample*/
     648         150 :                         if (!rewrite_start_codes && !entry->lhvc_config && !scal) {
     649             :                                 if (! ps_transfered) {
     650         150 :                                         nal_type = (sample->data[nal_unit_size_field] & 0x7E) >> 1;
     651             :                                         //temp fix - if we detect xPS in the beginning of the sample do NOT copy the ps bitstream
     652             :                                         //this is not correct since we are not sure whether they are the same xPS or not, but it crashes openHEVC ...
     653         150 :                                         switch (nal_type) {
     654             : #ifndef GPAC_DISABLE_HEVC
     655             :                                         case GF_HEVC_NALU_VID_PARAM:
     656             :                                         case GF_HEVC_NALU_SEQ_PARAM:
     657             :                                         case GF_HEVC_NALU_PIC_PARAM:
     658             :                                                 break;
     659             : #endif
     660         150 :                                         default:
     661         150 :                                                 gf_bs_transfer(mdia->nalu_out_bs, mdia->nalu_ps_bs, GF_TRUE);
     662         150 :                                                 break;
     663             :                                         }
     664             :                                 }
     665         150 :                                 gf_bs_write_data(mdia->nalu_out_bs, mdia->in_sample_buffer, sample->dataLength);
     666         150 :                                 gf_bs_get_content_no_truncate(mdia->nalu_out_bs, &sample->data, &sample->dataLength, &sample->alloc_size);
     667             : 
     668         150 :                                 return GF_OK;
     669             :                         }
     670             :                 }
     671             :         } else {
     672             :                 ps_transfered = GF_TRUE;
     673             :         }
     674             : 
     675             :         /*little optimization if we are not asked to rewrite extractors or start codes: copy over the sample*/
     676        4830 :         if (!scal && !rewrite_start_codes && !rewrite_ps && !force_sei_inspect) {
     677         762 :                 if (! ps_transfered)
     678             :                 {
     679           0 :                         gf_bs_transfer(mdia->nalu_out_bs, mdia->nalu_ps_bs, GF_TRUE);
     680             :                 }
     681         762 :                 gf_bs_write_data(mdia->nalu_out_bs, mdia->in_sample_buffer, sample->dataLength);
     682         762 :                 gf_bs_get_content_no_truncate(mdia->nalu_out_bs, &sample->data, &sample->dataLength, &sample->alloc_size);
     683         762 :                 return GF_OK;
     684             :         }
     685             : 
     686        4068 :         if (!mdia->tmp_nal_copy_buffer) {
     687           9 :                 mdia->tmp_nal_copy_buffer = gf_malloc(sizeof(char) * 4096);
     688           9 :                 mdia->tmp_nal_copy_buffer_alloc = 4096;
     689             :         }
     690             : 
     691             : 
     692       36854 :         while (gf_bs_available(mdia->nalu_parser)) {
     693       32796 :                 nal_size = gf_bs_read_int(mdia->nalu_parser, 8*nal_unit_size_field);
     694       32796 :                 if (gf_bs_get_position(mdia->nalu_parser) + nal_size > sample->dataLength) {
     695           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("Sample %u (size %u) rewrite: corrupted NAL Unit (size %u)\n", sampleNumber, sample->dataLength, nal_size));
     696             :                         goto exit;
     697             :                 }
     698       32796 :                 if (nal_size > mdia->tmp_nal_copy_buffer_alloc) {
     699          38 :                         mdia->tmp_nal_copy_buffer_alloc = nal_size;
     700          38 :                         mdia->tmp_nal_copy_buffer = (char*) gf_realloc(mdia->tmp_nal_copy_buffer, sizeof(char)*nal_size);
     701             :                 }
     702       32796 :                 if (is_hevc) {
     703       31486 :                         nal_hdr = gf_bs_read_u16(mdia->nalu_parser);
     704       31486 :                         nal_type = (nal_hdr&0x7E00) >> 9;
     705             :                 } else {
     706        1310 :                         nal_hdr = gf_bs_read_u8(mdia->nalu_parser);
     707        1310 :                         nal_type = nal_hdr & 0x1F;
     708             :                 }
     709             : 
     710       32796 :                 if (is_hevc) {
     711             : #ifndef GPAC_DISABLE_HEVC
     712       31486 :                         GF_BitStream *write_to_bs = mdia->nalu_out_bs;
     713             : #endif
     714             : 
     715       31486 :                         if (!ps_transfered) {
     716           0 :                                 gf_bs_transfer(mdia->nalu_out_bs, mdia->nalu_ps_bs, GF_TRUE);
     717             :                                 ps_transfered = GF_TRUE;
     718             :                         }
     719             : 
     720             : #ifndef GPAC_DISABLE_HEVC
     721             :                         /*we already wrote this stuff*/
     722       31486 :                         if (nal_type==GF_HEVC_NALU_ACCESS_UNIT) {
     723           0 :                                 gf_bs_skip_bytes(mdia->nalu_parser, nal_size-2);
     724           0 :                                 continue;
     725             :                         }
     726       31486 :                         switch (nal_type) {
     727             :                         //extractor
     728         512 :                         case 49:
     729         512 :                                 e = process_extractor(file, mdia, sampleNumber, sample->DTS, nal_size, nal_hdr, nal_unit_size_field, GF_TRUE, rewrite_ps, rewrite_start_codes, extractor_mode);
     730         512 :                                 if (e) goto exit;
     731             :                                 break;
     732             : 
     733         421 :                         case GF_HEVC_NALU_SLICE_TSA_N:
     734             :                         case GF_HEVC_NALU_SLICE_STSA_N:
     735             :                         case GF_HEVC_NALU_SLICE_TSA_R:
     736             :                         case GF_HEVC_NALU_SLICE_STSA_R:
     737         421 :                                 if (temporal_id < (nal_hdr & 0x7))
     738             :                                         temporal_id = (nal_hdr & 0x7);
     739             :                                 /*rewrite nal*/
     740         421 :                                 gf_bs_read_data(mdia->nalu_parser, mdia->tmp_nal_copy_buffer, nal_size-2);
     741         421 :                                 if (rewrite_start_codes)
     742           0 :                                         gf_bs_write_u32(mdia->nalu_out_bs, 1);
     743             :                                 else
     744         421 :                                         gf_bs_write_int(mdia->nalu_out_bs, nal_size, 8*nal_unit_size_field);
     745             : 
     746         421 :                                 gf_bs_write_u16(mdia->nalu_out_bs, nal_hdr);
     747         421 :                                 gf_bs_write_data(mdia->nalu_out_bs, mdia->tmp_nal_copy_buffer, nal_size-2);
     748         421 :                                 break;
     749             : 
     750             :                         case GF_HEVC_NALU_SLICE_BLA_W_LP:
     751             :                         case GF_HEVC_NALU_SLICE_BLA_W_DLP:
     752             :                         case GF_HEVC_NALU_SLICE_BLA_N_LP:
     753             :                         case GF_HEVC_NALU_SLICE_IDR_W_DLP:
     754             :                         case GF_HEVC_NALU_SLICE_IDR_N_LP:
     755             :                         case GF_HEVC_NALU_SLICE_CRA:
     756             :                                 //insert xPS before CRA/BLA
     757        1065 :                                 if (check_cra_bla && !sample->IsRAP) {
     758          10 :                                         sample->IsRAP = sap_type_from_nal_type(nal_type);
     759          10 :                                         if (sei_suffix_bs) gf_bs_del(sei_suffix_bs);
     760          10 :                                         return gf_isom_nalu_sample_rewrite(mdia, sample, sampleNumber, entry);
     761             :                                 }
     762             :                         default:
     763             :                                 /*rewrite nal*/
     764       30543 :                                 if (nal_size<2) {
     765           0 :                                         GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Invalid nal size %d in sample %d\n", nal_type, sampleNumber));
     766             :                                         e = GF_NON_COMPLIANT_BITSTREAM;
     767             :                                         goto exit;
     768             :                                 }
     769             : 
     770       30543 :                                 gf_bs_read_data(mdia->nalu_parser, mdia->tmp_nal_copy_buffer, nal_size-2);
     771             : 
     772       30543 :                                 if (nal_type==GF_HEVC_NALU_SEI_SUFFIX) {
     773        3498 :                                         if (!sei_suffix_bs) sei_suffix_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     774             :                                         write_to_bs = sei_suffix_bs;
     775             :                                 }
     776             : 
     777       30543 :                                 if (rewrite_start_codes)
     778           0 :                                         gf_bs_write_u32(write_to_bs, 1);
     779             :                                 else
     780       30543 :                                         gf_bs_write_int(write_to_bs, nal_size, 8*nal_unit_size_field);
     781             : 
     782       30543 :                                 gf_bs_write_u16(write_to_bs, nal_hdr);
     783       30543 :                                 gf_bs_write_data(write_to_bs, mdia->tmp_nal_copy_buffer, nal_size-2);
     784             :                         }
     785             : #endif
     786             : 
     787             :                         //done with HEVC
     788       31476 :                         continue;
     789             :                 }
     790             : 
     791             :                 switch(nal_type) {
     792           0 :                 case GF_AVC_NALU_ACCESS_UNIT:
     793             :                         /*we already wrote this stuff*/
     794           0 :                         gf_bs_skip_bytes(mdia->nalu_parser, nal_size-1);
     795           0 :                         continue;
     796             :                 //extractor
     797         750 :                 case 31:
     798         750 :                         e = process_extractor(file, mdia, sampleNumber, sample->DTS, nal_size, nal_hdr, nal_unit_size_field, GF_FALSE, rewrite_ps, rewrite_start_codes, extractor_mode);
     799         750 :                         if (e) goto exit;
     800             :                         break;
     801             : //                      case GF_AVC_NALU_SEI:
     802           0 :                 case GF_AVC_NALU_SEQ_PARAM:
     803             :                 case GF_AVC_NALU_PIC_PARAM:
     804             :                 case GF_AVC_NALU_SEQ_PARAM_EXT:
     805             :                 case GF_AVC_NALU_SVC_SUBSEQ_PARAM:
     806             :                         // we will rewrite the sps/pps if and only if there is no sps/pps in bistream
     807           0 :                         if (!ps_transfered) {
     808             :                                 ps_transfered = GF_TRUE;
     809             :                         }
     810             :                 default:
     811         560 :                         if (!ps_transfered) {
     812          60 :                                 gf_bs_transfer(mdia->nalu_out_bs, mdia->nalu_ps_bs, GF_TRUE);
     813             :                                 ps_transfered = GF_TRUE;
     814             :                         }
     815         560 :                         gf_bs_read_data(mdia->nalu_parser, mdia->tmp_nal_copy_buffer, nal_size-1);
     816         560 :                         if (rewrite_start_codes)
     817           0 :                                 gf_bs_write_u32(mdia->nalu_out_bs, 1);
     818             :                         else
     819         560 :                                 gf_bs_write_int(mdia->nalu_out_bs, nal_size, 8*nal_unit_size_field);
     820             : 
     821         560 :                         gf_bs_write_u8(mdia->nalu_out_bs, nal_hdr);
     822         560 :                         gf_bs_write_data(mdia->nalu_out_bs, mdia->tmp_nal_copy_buffer, nal_size-1);
     823             :                 }
     824             :         }
     825             : 
     826        4058 :         if (sei_suffix_bs) {
     827        3498 :                 gf_bs_transfer(mdia->nalu_out_bs, sei_suffix_bs, GF_FALSE);
     828             :         }
     829             :         /*done*/
     830        4058 :         gf_bs_get_content_no_truncate(mdia->nalu_out_bs, &sample->data, &sample->dataLength, &sample->alloc_size);
     831             : 
     832             :         /*rewrite temporal ID of AU Ddelim NALU (first one)*/
     833        4058 :         if (rewrite_start_codes && is_hevc && temporal_id) {
     834           0 :                 sample->data[6] = (sample->data[6] & 0xF8) | (temporal_id+1);
     835             :         }
     836             : 
     837             : 
     838        8116 : exit:
     839        4058 :         if (sei_suffix_bs)
     840        3498 :                 gf_bs_del(sei_suffix_bs);
     841             : 
     842             :         return e;
     843             : }
     844             : 
     845        1266 : GF_HEVCConfig *HEVC_DuplicateConfig(GF_HEVCConfig *cfg)
     846             : {
     847             :         u8 *data;
     848             :         u32 data_size;
     849             :         GF_HEVCConfig *new_cfg;
     850             :         GF_BitStream *bs;
     851             : 
     852        1266 :         if (!cfg) return NULL;
     853        1152 :         bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     854        1152 :         gf_odf_hevc_cfg_write_bs(cfg, bs);
     855             : 
     856        1152 :         gf_bs_get_content(bs, &data, &data_size);
     857        1152 :         gf_bs_del(bs);
     858        1152 :         bs = gf_bs_new(data, data_size, GF_BITSTREAM_READ);
     859             : 
     860        1152 :         new_cfg = gf_odf_hevc_cfg_read_bs(bs, cfg->is_lhvc);
     861        1152 :         new_cfg->is_lhvc = cfg->is_lhvc;
     862        1152 :         gf_bs_del(bs);
     863        1152 :         gf_free(data);
     864        1152 :         return new_cfg;
     865             : }
     866             : 
     867           0 : GF_VVCConfig *VVC_DuplicateConfig(GF_VVCConfig *cfg)
     868             : {
     869             :         u8 *data;
     870             :         u32 data_size;
     871             :         GF_VVCConfig *new_cfg;
     872             :         GF_BitStream *bs;
     873             : 
     874           0 :         if (!cfg) return NULL;
     875           0 :         bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     876           0 :         gf_odf_vvc_cfg_write_bs(cfg, bs);
     877             : 
     878           0 :         gf_bs_get_content(bs, &data, &data_size);
     879           0 :         gf_bs_del(bs);
     880           0 :         bs = gf_bs_new(data, data_size, GF_BITSTREAM_READ);
     881             : 
     882           0 :         new_cfg = gf_odf_vvc_cfg_read_bs(bs);
     883           0 :         gf_bs_del(bs);
     884           0 :         gf_free(data);
     885           0 :         return new_cfg;
     886             : }
     887             : 
     888        2773 : static GF_AVCConfig *AVC_DuplicateConfig(GF_AVCConfig *cfg)
     889             : {
     890             :         u32 i, count;
     891             :         GF_NALUFFParam *p1, *p2;
     892             :         GF_AVCConfig *cfg_new;
     893        2773 :         if (!cfg)
     894             :                 return NULL;
     895        2773 :         cfg_new = gf_odf_avc_cfg_new();
     896        2773 :         cfg_new->AVCLevelIndication = cfg->AVCLevelIndication;
     897        2773 :         cfg_new->AVCProfileIndication = cfg->AVCProfileIndication;
     898        2773 :         cfg_new->configurationVersion = cfg->configurationVersion;
     899        2773 :         cfg_new->nal_unit_size = cfg->nal_unit_size;
     900        2773 :         cfg_new->profile_compatibility = cfg->profile_compatibility;
     901        2773 :         cfg_new->complete_representation = cfg->complete_representation;
     902        2773 :         cfg_new->chroma_bit_depth = cfg->chroma_bit_depth;
     903        2773 :         cfg_new->luma_bit_depth = cfg->luma_bit_depth;
     904        2773 :         cfg_new->chroma_format = cfg->chroma_format;
     905             : 
     906        2773 :         count = gf_list_count(cfg->sequenceParameterSets);
     907        5646 :         for (i=0; i<count; i++) {
     908        2873 :                 p1 = (GF_NALUFFParam*)gf_list_get(cfg->sequenceParameterSets, i);
     909        2873 :                 p2 = (GF_NALUFFParam*)gf_malloc(sizeof(GF_NALUFFParam));
     910        2873 :                 p2->size = p1->size;
     911        2873 :                 p2->id = p1->id;
     912        2873 :                 p2->data = (char *)gf_malloc(sizeof(char)*p1->size);
     913        2873 :                 memcpy(p2->data, p1->data, sizeof(char)*p1->size);
     914        2873 :                 gf_list_add(cfg_new->sequenceParameterSets, p2);
     915             :         }
     916             : 
     917        2773 :         count = gf_list_count(cfg->pictureParameterSets);
     918        5651 :         for (i=0; i<count; i++) {
     919        2878 :                 p1 = (GF_NALUFFParam*)gf_list_get(cfg->pictureParameterSets, i);
     920        2878 :                 p2 = (GF_NALUFFParam*)gf_malloc(sizeof(GF_NALUFFParam));
     921        2878 :                 p2->size = p1->size;
     922        2878 :                 p2->id = p1->id;
     923        2878 :                 p2->data = (char*)gf_malloc(sizeof(char)*p1->size);
     924        2878 :                 memcpy(p2->data, p1->data, sizeof(char)*p1->size);
     925        2878 :                 gf_list_add(cfg_new->pictureParameterSets, p2);
     926             :         }
     927             : 
     928        2773 :         if (cfg->sequenceParameterSetExtensions) {
     929           0 :                 cfg_new->sequenceParameterSetExtensions = gf_list_new();
     930           0 :                 count = gf_list_count(cfg->sequenceParameterSetExtensions);
     931           0 :                 for (i=0; i<count; i++) {
     932           0 :                         p1 = (GF_NALUFFParam*)gf_list_get(cfg->sequenceParameterSetExtensions, i);
     933           0 :                         p2 = (GF_NALUFFParam*)gf_malloc(sizeof(GF_NALUFFParam));
     934           0 :                         p2->size = p1->size;
     935           0 :                         p2->id = p1->id;
     936           0 :                         p2->data = (char*)gf_malloc(sizeof(char)*p1->size);
     937           0 :                         memcpy(p2->data, p1->data, sizeof(char)*p1->size);
     938           0 :                         gf_list_add(cfg_new->sequenceParameterSetExtensions, p2);
     939             :                 }
     940             :         }
     941             :         return cfg_new;
     942             : }
     943             : 
     944          62 : static void merge_avc_config(GF_AVCConfig *dst_cfg, GF_AVCConfig *src_cfg)
     945             : {
     946             :         GF_AVCConfig *cfg;
     947          62 :         if (!src_cfg || !dst_cfg) return;
     948          62 :         cfg = AVC_DuplicateConfig(src_cfg);
     949          62 :         if (!cfg) return;
     950             :         
     951         129 :         while (gf_list_count(cfg->sequenceParameterSets)) {
     952          67 :                 GF_NALUFFParam *p = (GF_NALUFFParam*)gf_list_get(cfg->sequenceParameterSets, 0);
     953          67 :                 gf_list_rem(cfg->sequenceParameterSets, 0);
     954          67 :                 gf_list_insert(dst_cfg->sequenceParameterSets, p, 0);
     955             :         }
     956         124 :         while (gf_list_count(cfg->pictureParameterSets)) {
     957          62 :                 GF_NALUFFParam *p = (GF_NALUFFParam*)gf_list_get(cfg->pictureParameterSets, 0);
     958          62 :                 gf_list_rem(cfg->pictureParameterSets, 0);
     959          62 :                 gf_list_insert(dst_cfg->pictureParameterSets, p, 0);
     960             :         }
     961          62 :         gf_odf_avc_cfg_del(cfg);
     962             : }
     963             : 
     964          21 : void merge_hevc_config(GF_HEVCConfig *dst_cfg, GF_HEVCConfig *src_cfg, Bool force_insert)
     965             : {
     966          21 :         GF_HEVCConfig *cfg = HEVC_DuplicateConfig(src_cfg);
     967             :         //merge all xPS
     968          21 :         u32 i, j, count = cfg->param_array ? gf_list_count(cfg->param_array) : 0;
     969          42 :         for (i=0; i<count; i++) {
     970             :                 GF_NALUFFParamArray *ar_h = NULL;
     971          42 :                 u32 count2 = dst_cfg->param_array ? gf_list_count(dst_cfg->param_array) : 0;
     972          42 :                 GF_NALUFFParamArray *ar = (GF_NALUFFParamArray*)gf_list_get(cfg->param_array, i);
     973         105 :                 for (j=0; j<count2; j++) {
     974         105 :                         ar_h = (GF_NALUFFParamArray*)gf_list_get(dst_cfg->param_array, j);
     975         105 :                         if (ar_h->type==ar->type) {
     976             :                                 break;
     977             :                         }
     978             :                         ar_h = NULL;
     979             :                 }
     980          42 :                 if (!ar_h) {
     981           0 :                         gf_list_add(dst_cfg->param_array, ar);
     982           0 :                         gf_list_rem(cfg->param_array, i);
     983           0 :                         count--;
     984           0 :                         i--;
     985             :                 } else {
     986          84 :                         while (gf_list_count(ar->nalus)) {
     987          42 :                                 GF_NALUFFParam *p = (GF_NALUFFParam*)gf_list_get(ar->nalus, 0);
     988          42 :                                 gf_list_rem(ar->nalus, 0);
     989          42 :                                 if (force_insert)
     990           0 :                                         gf_list_insert(ar_h->nalus, p, 0);
     991             :                                 else
     992          42 :                                         gf_list_add(ar_h->nalus, p);
     993             :                         }
     994             : 
     995             :                 }
     996             :         }
     997          21 :         gf_odf_hevc_cfg_del(cfg);
     998             : 
     999             : #define CHECK_CODE(__code)      if (dst_cfg->__code < src_cfg->__code) dst_cfg->__code = src_cfg->__code;
    1000             : 
    1001          21 :         CHECK_CODE(configurationVersion)
    1002          21 :         CHECK_CODE(profile_idc)
    1003          21 :         CHECK_CODE(profile_space)
    1004          21 :         CHECK_CODE(tier_flag)
    1005          21 :         CHECK_CODE(general_profile_compatibility_flags)
    1006          21 :         CHECK_CODE(progressive_source_flag)
    1007          21 :         CHECK_CODE(interlaced_source_flag)
    1008          21 :         CHECK_CODE(constraint_indicator_flags)
    1009          21 :         CHECK_CODE(level_idc)
    1010          21 :         CHECK_CODE(min_spatial_segmentation_idc)
    1011             : 
    1012          21 : }
    1013             : 
    1014          33 : void merge_all_config(GF_AVCConfig *avc_cfg, GF_HEVCConfig *hevc_cfg, GF_MediaBox *mdia)
    1015             : {
    1016             :         u32 i;
    1017          33 :         GF_TrackReferenceTypeBox *scal = NULL;
    1018          33 :         Track_FindRef(mdia->mediaTrack, GF_ISOM_REF_SCAL, &scal);
    1019             : 
    1020          33 :         if (!scal) return;
    1021             : 
    1022          49 :         for (i=0; i<scal->trackIDCount; i++) {
    1023          49 :                 GF_TrackBox *a_track = GetTrackbyID(mdia->mediaTrack->moov, scal->trackIDs[i]);
    1024             :                 GF_MPEGVisualSampleEntryBox *an_entry = NULL;
    1025          49 :                 if (a_track && a_track->Media && a_track->Media->information && a_track->Media->information->sampleTable && a_track->Media->information->sampleTable->SampleDescription)
    1026          47 :                         an_entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(a_track->Media->information->sampleTable->SampleDescription->child_boxes, 0);
    1027             : 
    1028          47 :                 if (!an_entry) continue;
    1029             : 
    1030          47 :                 if (avc_cfg && an_entry->svc_config && an_entry->svc_config->config)
    1031          14 :                         merge_avc_config(avc_cfg, an_entry->svc_config->config);
    1032             : 
    1033          47 :                 if (avc_cfg && an_entry->mvc_config && an_entry->mvc_config->config)
    1034           0 :                         merge_avc_config(avc_cfg, an_entry->mvc_config->config);
    1035             : 
    1036          47 :                 if (avc_cfg && an_entry->avc_config && an_entry->avc_config->config)
    1037          33 :                         merge_avc_config(avc_cfg, an_entry->avc_config->config);
    1038             : 
    1039          47 :                 if (hevc_cfg && an_entry->lhvc_config && an_entry->lhvc_config->config)
    1040           0 :                         merge_hevc_config(hevc_cfg, an_entry->lhvc_config->config, GF_TRUE);
    1041             : 
    1042          47 :                 if (hevc_cfg && an_entry->hevc_config && an_entry->hevc_config->config)
    1043           0 :                         merge_hevc_config(hevc_cfg, an_entry->hevc_config->config, GF_TRUE);
    1044             :         }
    1045             : 
    1046          33 :         if (hevc_cfg) hevc_cfg->is_lhvc = GF_FALSE;
    1047             : }
    1048             : 
    1049        1423 : void AVC_RewriteESDescriptorEx(GF_MPEGVisualSampleEntryBox *avc, GF_MediaBox *mdia)
    1050             : {
    1051        1423 :         GF_BitRateBox *btrt = gf_isom_sample_entry_get_bitrate((GF_SampleEntryBox *)avc, GF_FALSE);
    1052             : 
    1053        1423 :         if (avc->emul_esd) gf_odf_desc_del((GF_Descriptor *)avc->emul_esd);
    1054        1423 :         avc->emul_esd = gf_odf_desc_esd_new(2);
    1055        1423 :         avc->emul_esd->decoderConfig->streamType = GF_STREAM_VISUAL;
    1056             :         /*AVC OTI is 0x21, AVC parameter set stream OTI (not supported in gpac) is 0x22, SVC OTI is 0x24*/
    1057             :         /*if we have only SVC stream, set objectTypeIndication to AVC OTI; else set it to AVC OTI*/
    1058        1423 :         if (avc->svc_config && !avc->avc_config)
    1059          55 :                 avc->emul_esd->decoderConfig->objectTypeIndication = GF_CODECID_SVC;
    1060        1368 :         else if (avc->mvc_config && !avc->avc_config)
    1061           0 :                 avc->emul_esd->decoderConfig->objectTypeIndication = GF_CODECID_MVC;
    1062             :         else
    1063        1368 :                 avc->emul_esd->decoderConfig->objectTypeIndication = GF_CODECID_AVC;
    1064             : 
    1065        1423 :         if (btrt) {
    1066         879 :                 avc->emul_esd->decoderConfig->bufferSizeDB = btrt->bufferSizeDB;
    1067         879 :                 avc->emul_esd->decoderConfig->avgBitrate = btrt->avgBitrate;
    1068         879 :                 avc->emul_esd->decoderConfig->maxBitrate = btrt->maxBitrate;
    1069             :         }
    1070        1423 :         GF_MPEG4ExtensionDescriptorsBox *mdesc = (GF_MPEG4ExtensionDescriptorsBox *) gf_isom_box_find_child(avc->child_boxes, GF_ISOM_BOX_TYPE_M4DS);
    1071        1423 :         if (mdesc) {
    1072           5 :                 u32 i=0;
    1073             :                 GF_Descriptor *desc,*clone;
    1074             :                 i=0;
    1075          15 :                 while ((desc = (GF_Descriptor *)gf_list_enum(mdesc->descriptors, &i))) {
    1076           5 :                         clone = NULL;
    1077           5 :                         gf_odf_desc_copy(desc, &clone);
    1078           5 :                         if (gf_odf_desc_add_desc((GF_Descriptor *)avc->emul_esd, clone) != GF_OK)
    1079           0 :                                 gf_odf_desc_del(clone);
    1080             :                 }
    1081             :         }
    1082        1423 :         if (avc->avc_config) {
    1083        1368 :                 GF_AVCConfig *avcc = avc->avc_config->config ? AVC_DuplicateConfig(avc->avc_config->config) : NULL;
    1084             :                 /*merge SVC config*/
    1085        1368 :                 if (avc->svc_config) {
    1086          15 :                         merge_avc_config(avcc, avc->svc_config->config);
    1087             :                 }
    1088             :                 /*merge MVC config*/
    1089        1368 :                 if (avc->mvc_config) {
    1090           0 :                         merge_avc_config(avcc, avc->mvc_config->config);
    1091             :                 }
    1092        1368 :                 if (avcc) {
    1093        1368 :                         if (mdia) merge_all_config(avcc, NULL, mdia);
    1094             : 
    1095        1368 :                         gf_odf_avc_cfg_write(avcc, &avc->emul_esd->decoderConfig->decoderSpecificInfo->data, &avc->emul_esd->decoderConfig->decoderSpecificInfo->dataLength);
    1096        1368 :                         gf_odf_avc_cfg_del(avcc);
    1097             :                 }
    1098          55 :         } else if (avc->svc_config) {
    1099          55 :                 GF_AVCConfig *svcc = AVC_DuplicateConfig(avc->svc_config->config);
    1100             : 
    1101          55 :                 if (mdia) merge_all_config(svcc, NULL, mdia);
    1102             : 
    1103          55 :                 gf_odf_avc_cfg_write(svcc, &avc->emul_esd->decoderConfig->decoderSpecificInfo->data, &avc->emul_esd->decoderConfig->decoderSpecificInfo->dataLength);
    1104          55 :                 gf_odf_avc_cfg_del(svcc);
    1105             :         }
    1106           0 :         else if (avc->mvc_config) {
    1107           0 :                 GF_AVCConfig *mvcc = AVC_DuplicateConfig(avc->mvc_config->config);
    1108             : 
    1109           0 :                 if (mdia) merge_all_config(mvcc, NULL, mdia);
    1110             : 
    1111           0 :                 gf_odf_avc_cfg_write(mvcc, &avc->emul_esd->decoderConfig->decoderSpecificInfo->data, &avc->emul_esd->decoderConfig->decoderSpecificInfo->dataLength);
    1112           0 :                 gf_odf_avc_cfg_del(mvcc);
    1113             :         }
    1114        1423 : }
    1115             : 
    1116         939 : void AVC_RewriteESDescriptor(GF_MPEGVisualSampleEntryBox *avc)
    1117             : {
    1118        1390 :         AVC_RewriteESDescriptorEx(avc, NULL);
    1119         939 : }
    1120             : 
    1121         866 : void HEVC_RewriteESDescriptorEx(GF_MPEGVisualSampleEntryBox *hevc, GF_MediaBox *mdia)
    1122             : {
    1123         866 :         GF_BitRateBox *btrt = gf_isom_sample_entry_get_bitrate((GF_SampleEntryBox *)hevc, GF_FALSE);
    1124             : 
    1125         866 :         if (hevc->emul_esd) gf_odf_desc_del((GF_Descriptor *)hevc->emul_esd);
    1126         866 :         hevc->emul_esd = gf_odf_desc_esd_new(2);
    1127         866 :         hevc->emul_esd->decoderConfig->streamType = GF_STREAM_VISUAL;
    1128         866 :         hevc->emul_esd->decoderConfig->objectTypeIndication = GF_CODECID_HEVC;
    1129             : 
    1130         866 :         if (btrt) {
    1131         517 :                 hevc->emul_esd->decoderConfig->bufferSizeDB = btrt->bufferSizeDB;
    1132         517 :                 hevc->emul_esd->decoderConfig->avgBitrate = btrt->avgBitrate;
    1133         517 :                 hevc->emul_esd->decoderConfig->maxBitrate = btrt->maxBitrate;
    1134             :         }
    1135         866 :         GF_MPEG4ExtensionDescriptorsBox *mdesc = (GF_MPEG4ExtensionDescriptorsBox *) gf_isom_box_find_child(hevc->child_boxes, GF_ISOM_BOX_TYPE_M4DS);
    1136         866 :         if (mdesc) {
    1137           0 :                 u32 i=0;
    1138             :                 GF_Descriptor *desc,*clone;
    1139             :                 i=0;
    1140           0 :                 while ((desc = (GF_Descriptor *)gf_list_enum(mdesc->descriptors, &i))) {
    1141           0 :                         clone = NULL;
    1142           0 :                         gf_odf_desc_copy(desc, &clone);
    1143           0 :                         if (gf_odf_desc_add_desc((GF_Descriptor *)hevc->emul_esd, clone) != GF_OK)
    1144           0 :                                 gf_odf_desc_del(clone);
    1145             :                 }
    1146             :         }
    1147             : 
    1148         866 :         if (hevc->hevc_config || hevc->lhvc_config) {
    1149         715 :                 GF_HEVCConfig *hcfg = HEVC_DuplicateConfig(hevc->hevc_config ? hevc->hevc_config->config : hevc->lhvc_config->config);
    1150             : 
    1151         715 :                 if (hevc->hevc_config && hevc->lhvc_config) {
    1152             :                         //merge LHVC config to HEVC conf, so we add entry rather than insert
    1153          21 :                         merge_hevc_config(hcfg, hevc->lhvc_config->config, GF_FALSE);
    1154             :                 }
    1155             : 
    1156         715 :                 if (mdia) merge_all_config(NULL, hcfg, mdia);
    1157             : 
    1158         715 :                 if (hcfg) {
    1159         601 :                         if (mdia && ((mdia->mediaTrack->extractor_mode&0x0000FFFF) != GF_ISOM_NALU_EXTRACT_INSPECT)) {
    1160           0 :                                 hcfg->is_lhvc=GF_FALSE;
    1161             :                         }
    1162             : 
    1163         601 :                         gf_odf_hevc_cfg_write(hcfg, &hevc->emul_esd->decoderConfig->decoderSpecificInfo->data, &hevc->emul_esd->decoderConfig->decoderSpecificInfo->dataLength);
    1164         601 :                         gf_odf_hevc_cfg_del(hcfg);
    1165             :                 }
    1166             :         }
    1167         866 : }
    1168         483 : void HEVC_RewriteESDescriptor(GF_MPEGVisualSampleEntryBox *hevc)
    1169             : {
    1170         866 :         HEVC_RewriteESDescriptorEx(hevc, NULL);
    1171         483 : }
    1172             : 
    1173          30 : GF_Err AVC_HEVC_UpdateESD(GF_MPEGVisualSampleEntryBox *avc, GF_ESD *esd)
    1174             : {
    1175          30 :         GF_BitRateBox *btrt = gf_isom_sample_entry_get_bitrate((GF_SampleEntryBox *)avc, GF_TRUE);
    1176             : 
    1177          30 :         GF_MPEG4ExtensionDescriptorsBox *mdesc = (GF_MPEG4ExtensionDescriptorsBox *) gf_isom_box_find_child(avc->child_boxes, GF_ISOM_BOX_TYPE_M4DS);
    1178          30 :         if (mdesc) {
    1179           0 :                 gf_isom_box_del_parent(&avc->child_boxes, (GF_Box *) mdesc);
    1180             :         }
    1181          30 :         btrt->avgBitrate = esd->decoderConfig->avgBitrate;
    1182          30 :         btrt->maxBitrate = esd->decoderConfig->maxBitrate;
    1183          30 :         btrt->bufferSizeDB = esd->decoderConfig->bufferSizeDB;
    1184             : 
    1185          30 :         if (gf_list_count(esd->IPIDataSet)
    1186          30 :                 || gf_list_count(esd->IPMPDescriptorPointers)
    1187          30 :                 || esd->langDesc
    1188          30 :                 || gf_list_count(esd->extensionDescriptors)
    1189          30 :                 || esd->ipiPtr || esd->qos || esd->RegDescriptor) {
    1190             : 
    1191           0 :                 mdesc = (GF_MPEG4ExtensionDescriptorsBox *) gf_isom_box_new_parent(&avc->child_boxes, GF_ISOM_BOX_TYPE_M4DS);
    1192           0 :                 if (!mdesc) return GF_OUT_OF_MEM;
    1193             : 
    1194           0 :                 if (esd->RegDescriptor) {
    1195           0 :                         gf_list_add(mdesc->descriptors, esd->RegDescriptor);
    1196           0 :                         esd->RegDescriptor = NULL;
    1197             :                 }
    1198           0 :                 if (esd->qos) {
    1199           0 :                         gf_list_add(mdesc->descriptors, esd->qos);
    1200           0 :                         esd->qos = NULL;
    1201             :                 }
    1202           0 :                 if (esd->ipiPtr) {
    1203           0 :                         gf_list_add(mdesc->descriptors, esd->ipiPtr);
    1204           0 :                         esd->ipiPtr= NULL;
    1205             :                 }
    1206             : 
    1207           0 :                 while (gf_list_count(esd->IPIDataSet)) {
    1208           0 :                         GF_Descriptor *desc = (GF_Descriptor *)gf_list_get(esd->IPIDataSet, 0);
    1209           0 :                         gf_list_rem(esd->IPIDataSet, 0);
    1210           0 :                         gf_list_add(mdesc->descriptors, desc);
    1211             :                 }
    1212           0 :                 while (gf_list_count(esd->IPMPDescriptorPointers)) {
    1213           0 :                         GF_Descriptor *desc = (GF_Descriptor *)gf_list_get(esd->IPMPDescriptorPointers, 0);
    1214           0 :                         gf_list_rem(esd->IPMPDescriptorPointers, 0);
    1215           0 :                         gf_list_add(mdesc->descriptors, desc);
    1216             :                 }
    1217           0 :                 if (esd->langDesc) {
    1218           0 :                         gf_list_add(mdesc->descriptors, esd->langDesc);
    1219           0 :                         esd->langDesc = NULL;
    1220             :                 }
    1221           0 :                 while (gf_list_count(esd->extensionDescriptors)) {
    1222           0 :                         GF_Descriptor *desc = (GF_Descriptor *)gf_list_get(esd->extensionDescriptors, 0);
    1223           0 :                         gf_list_rem(esd->extensionDescriptors, 0);
    1224           0 :                         gf_list_add(mdesc->descriptors, desc);
    1225             :                 }
    1226             :         }
    1227             : 
    1228             : 
    1229          30 :         if (!avc->lhvc_config && (esd->decoderConfig->objectTypeIndication==GF_CODECID_HEVC)) {
    1230           3 :                 if (!avc->hevc_config) {
    1231           0 :                         avc->hevc_config = (GF_HEVCConfigurationBox *)gf_isom_box_new_parent(&avc->child_boxes, GF_ISOM_BOX_TYPE_HVCC);
    1232           0 :                         if (!avc->hevc_config) return GF_OUT_OF_MEM;
    1233             :                 }
    1234           3 :                 if (esd->decoderConfig->decoderSpecificInfo && esd->decoderConfig->decoderSpecificInfo->data) {
    1235           3 :                         if (avc->hevc_config->config) gf_odf_hevc_cfg_del(avc->hevc_config->config);
    1236           3 :                         avc->hevc_config->config = gf_odf_hevc_cfg_read(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, GF_FALSE);
    1237             :                 }
    1238             :         }
    1239          27 :         else if (!avc->svc_config && !avc->mvc_config && (esd->decoderConfig->objectTypeIndication==GF_CODECID_AVC)) {
    1240          24 :                 if (!avc->avc_config) {
    1241           4 :                         avc->avc_config = (GF_AVCConfigurationBox *)gf_isom_box_new_parent(&avc->child_boxes, GF_ISOM_BOX_TYPE_AVCC);
    1242           4 :                         if (!avc->avc_config) return GF_OUT_OF_MEM;
    1243             :                 }
    1244          24 :                 if (esd->decoderConfig->decoderSpecificInfo && esd->decoderConfig->decoderSpecificInfo->data) {
    1245          24 :                         if (avc->avc_config->config) gf_odf_avc_cfg_del(avc->avc_config->config);
    1246          24 :                         avc->avc_config->config = gf_odf_avc_cfg_read(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength);
    1247             :                 }
    1248             :         }
    1249             : 
    1250          30 :         gf_odf_desc_del((GF_Descriptor *)esd);
    1251          30 :         if (avc->hevc_config) {
    1252             :                 HEVC_RewriteESDescriptor(avc);
    1253             :         } else {
    1254             :                 AVC_RewriteESDescriptor(avc);
    1255             :         }
    1256             :         return GF_OK;
    1257             : }
    1258             : 
    1259             : #if !defined(GPAC_DISABLE_AV_PARSERS) && !defined(GPAC_DISABLE_HEVC)
    1260         223 : void gf_hevc_parse_ps(GF_HEVCConfig* hevccfg, HEVCState* hevc, u32 nal_type)
    1261             : {
    1262             :         u32 i, j;
    1263         223 :         if (!hevccfg) return;
    1264             :         
    1265         603 :         for (i = 0; i < gf_list_count(hevccfg->param_array); i++) {
    1266         603 :                 GF_NALUFFParamArray* ar = gf_list_get(hevccfg->param_array, i);
    1267         603 :                 if (ar->type != nal_type) continue;
    1268         201 :                 for (j = 0; j < gf_list_count(ar->nalus); j++) {
    1269             :                         u8 ntype, tid, lid;
    1270         201 :                         GF_NALUFFParam* sl = gf_list_get(ar->nalus, j);
    1271         201 :                         gf_hevc_parse_nalu(sl->data, sl->size, hevc, &ntype, &tid, &lid);
    1272             :                 }
    1273             :         }
    1274             : }
    1275             : #endif
    1276             : 
    1277             : 
    1278           0 : static GF_Err gf_isom_check_mvc(GF_ISOFile *the_file, GF_TrackBox *trak, GF_MPEGVisualSampleEntryBox *entry)
    1279             : {
    1280             :         u32 i;
    1281             :         GF_Box *mvci;
    1282             :         GF_MultiviewGroupBox *mvcg;
    1283             :         GF_ViewIdentifierBox *vwid;
    1284             : 
    1285           0 :         if (entry->mvc_config) {}
    1286           0 :         else if (entry->avc_config && entry->avc_config->config && entry->avc_config->config->sequenceParameterSetExtensions) {}
    1287             :         else
    1288             :                 return GF_OK;
    1289             : 
    1290           0 :         mvci = gf_isom_box_find_child(trak->Media->information->child_boxes, GF_ISOM_BOX_TYPE_MVCI);
    1291           0 :         if (!mvci) {
    1292           0 :                 mvci = gf_isom_box_new_parent(&trak->Media->information->child_boxes, GF_ISOM_BOX_TYPE_MVCI);
    1293           0 :                 if (!mvci) return GF_OUT_OF_MEM;
    1294             :         }
    1295           0 :         mvcg = (GF_MultiviewGroupBox *) gf_isom_box_find_child(mvci->child_boxes, GF_ISOM_BOX_TYPE_MVCG);
    1296           0 :         if (!mvcg) {
    1297           0 :                 mvcg = (GF_MultiviewGroupBox *)gf_isom_box_new_parent(&mvci->child_boxes, GF_ISOM_BOX_TYPE_MVCG);
    1298           0 :                 if (!mvcg) return GF_OUT_OF_MEM;
    1299             :         }
    1300             :         //this is very crude, we should try to parse the bitstream to fill these
    1301           0 :         mvcg->num_entries = 0;
    1302           0 :         if (mvcg->entries) {
    1303           0 :                 gf_free(mvcg->entries);
    1304           0 :                 mvcg->entries = NULL;
    1305             :         }
    1306           0 :         if (entry->avc_config) {
    1307           0 :                 if (gf_list_count(entry->avc_config->config->sequenceParameterSets))
    1308           0 :                         mvcg->num_entries += 1;
    1309           0 :                 mvcg->num_entries += gf_list_count(entry->avc_config->config->sequenceParameterSetExtensions);
    1310             :         }
    1311           0 :         if (entry->mvc_config && entry->mvc_config->config) {
    1312           0 :                 mvcg->num_entries += gf_list_count(entry->mvc_config->config->sequenceParameterSets);
    1313             :         }
    1314           0 :         mvcg->entries = gf_malloc(sizeof(MVCIEntry)*mvcg->num_entries);
    1315           0 :         if (!mvcg->entries) return GF_OUT_OF_MEM;
    1316           0 :         memset(mvcg->entries, 0, sizeof(MVCIEntry)*mvcg->num_entries);
    1317           0 :         for (i=0; i<mvcg->num_entries; i++) {
    1318           0 :                 mvcg->entries[i].entry_type = 2;
    1319           0 :                 mvcg->entries[i].output_view_id = i;
    1320             :         }
    1321           0 :         vwid = (GF_ViewIdentifierBox *) gf_isom_box_find_child(entry->child_boxes, GF_ISOM_BOX_TYPE_VWID);
    1322           0 :         if (!vwid) {
    1323           0 :                 vwid = (GF_ViewIdentifierBox *)gf_isom_box_new_parent(&entry->child_boxes, GF_ISOM_BOX_TYPE_VWID);
    1324             :                 if (!mvcg) return GF_OUT_OF_MEM;
    1325             :         }
    1326           0 :         if (vwid->views) gf_free(vwid->views);
    1327           0 :         vwid->num_views = mvcg->num_entries;
    1328           0 :         vwid->views = gf_malloc(sizeof(ViewIDEntry)*vwid->num_views);
    1329           0 :         if (!vwid->views) return GF_OUT_OF_MEM;
    1330           0 :         memset(vwid->views, 0, sizeof(ViewIDEntry)*vwid->num_views);
    1331             : 
    1332           0 :         for (i=0; i<vwid->num_views; i++) {
    1333           0 :                 vwid->views[i].base_view_type = i ? 0 : 1;
    1334           0 :                 vwid->views[i].view_id = i;
    1335           0 :                 vwid->views[i].view_order_index = i;
    1336             :         }
    1337             : 
    1338             :         return GF_OK;
    1339             : }
    1340             : 
    1341         767 : static GF_AV1Config* AV1_DuplicateConfig(GF_AV1Config const * const cfg)
    1342             : {
    1343             :         u32 i = 0;
    1344         767 :         GF_AV1Config *out = gf_malloc(sizeof(GF_AV1Config));
    1345             : 
    1346         767 :         out->marker = cfg->marker;
    1347         767 :         out->version = cfg->version;
    1348         767 :         out->seq_profile = cfg->seq_profile;
    1349         767 :         out->seq_level_idx_0 = cfg->seq_level_idx_0;
    1350         767 :         out->seq_tier_0 = cfg->seq_tier_0;
    1351         767 :         out->high_bitdepth = cfg->high_bitdepth;
    1352         767 :         out->twelve_bit = cfg->twelve_bit;
    1353         767 :         out->monochrome = cfg->monochrome;
    1354         767 :         out->chroma_subsampling_x = cfg->chroma_subsampling_x;
    1355         767 :         out->chroma_subsampling_y = cfg->chroma_subsampling_y;
    1356         767 :         out->chroma_sample_position = cfg->chroma_sample_position;
    1357             : 
    1358         767 :         out->initial_presentation_delay_present = cfg->initial_presentation_delay_present;
    1359         767 :         out->initial_presentation_delay_minus_one = cfg->initial_presentation_delay_minus_one;
    1360         767 :         out->obu_array = gf_list_new();
    1361        1534 :         for (i = 0; i<gf_list_count(cfg->obu_array); ++i) {
    1362         767 :                 GF_AV1_OBUArrayEntry *dst = gf_malloc(sizeof(GF_AV1_OBUArrayEntry)), *src = gf_list_get(cfg->obu_array, i);
    1363         767 :                 dst->obu_length = src->obu_length;
    1364         767 :                 dst->obu_type = src->obu_type;
    1365         767 :                 dst->obu = gf_malloc((size_t)dst->obu_length);
    1366         767 :                 memcpy(dst->obu, src->obu, (size_t)src->obu_length);
    1367         767 :                 gf_list_add(out->obu_array, dst);
    1368             :         }
    1369         767 :         return out;
    1370             : }
    1371             : 
    1372         477 : void AV1_RewriteESDescriptorEx(GF_MPEGVisualSampleEntryBox *av1, GF_MediaBox *mdia)
    1373             : {
    1374         477 :         GF_BitRateBox *btrt = gf_isom_sample_entry_get_bitrate((GF_SampleEntryBox *)av1, GF_FALSE);
    1375             : 
    1376         477 :         if (av1->emul_esd) gf_odf_desc_del((GF_Descriptor *)av1->emul_esd);
    1377         477 :         av1->emul_esd = gf_odf_desc_esd_new(2);
    1378         477 :         av1->emul_esd->decoderConfig->streamType = GF_STREAM_VISUAL;
    1379         477 :         av1->emul_esd->decoderConfig->objectTypeIndication = GF_CODECID_AV1;
    1380             : 
    1381         477 :         if (btrt) {
    1382         474 :                 av1->emul_esd->decoderConfig->bufferSizeDB = btrt->bufferSizeDB;
    1383         474 :                 av1->emul_esd->decoderConfig->avgBitrate = btrt->avgBitrate;
    1384         474 :                 av1->emul_esd->decoderConfig->maxBitrate = btrt->maxBitrate;
    1385             :         }
    1386         477 :         if (av1->av1_config && av1->av1_config->config) {
    1387         477 :                 GF_AV1Config *av1_cfg = AV1_DuplicateConfig(av1->av1_config->config);
    1388         477 :                 if (av1_cfg) {
    1389         477 :                         gf_odf_av1_cfg_write(av1_cfg, &av1->emul_esd->decoderConfig->decoderSpecificInfo->data, &av1->emul_esd->decoderConfig->decoderSpecificInfo->dataLength);
    1390         477 :                         gf_odf_av1_cfg_del(av1_cfg);
    1391             :                 }
    1392             :         }
    1393         477 : }
    1394             : 
    1395         329 : void AV1_RewriteESDescriptor(GF_MPEGVisualSampleEntryBox *av1)
    1396             : {
    1397         329 :         AV1_RewriteESDescriptorEx(av1, NULL);
    1398         329 : }
    1399             : 
    1400             : 
    1401             : 
    1402         253 : static GF_VPConfig* VP_DuplicateConfig(GF_VPConfig const * const cfg)
    1403             : {
    1404         253 :         GF_VPConfig *out = gf_odf_vp_cfg_new();
    1405         253 :         if (out) {
    1406         253 :                 out->profile = cfg->profile;
    1407         253 :                 out->level = cfg->level;
    1408         253 :                 out->bit_depth = cfg->bit_depth;
    1409         253 :                 out->chroma_subsampling = cfg->chroma_subsampling;
    1410         253 :                 out->video_fullRange_flag = cfg->video_fullRange_flag;
    1411         253 :                 out->colour_primaries = cfg->colour_primaries;
    1412         253 :                 out->transfer_characteristics = cfg->transfer_characteristics;
    1413         253 :                 out->matrix_coefficients = cfg->matrix_coefficients;
    1414             :         }
    1415             : 
    1416         253 :         return out;
    1417             : }
    1418             : 
    1419         214 : void VP9_RewriteESDescriptorEx(GF_MPEGVisualSampleEntryBox *vp9, GF_MediaBox *mdia)
    1420             : {
    1421         214 :         GF_BitRateBox *btrt = gf_isom_sample_entry_get_bitrate((GF_SampleEntryBox *)vp9, GF_FALSE);
    1422             : 
    1423         214 :         if (vp9->emul_esd) gf_odf_desc_del((GF_Descriptor *)vp9->emul_esd);
    1424         214 :         vp9->emul_esd = gf_odf_desc_esd_new(2);
    1425         214 :         vp9->emul_esd->decoderConfig->streamType = GF_STREAM_VISUAL;
    1426         214 :         if (vp9->type == GF_ISOM_BOX_TYPE_VP08)
    1427           7 :                 vp9->emul_esd->decoderConfig->objectTypeIndication = GF_CODECID_VP8;
    1428             :         else
    1429         207 :                 vp9->emul_esd->decoderConfig->objectTypeIndication = GF_CODECID_VP9;
    1430             : 
    1431         214 :         if (btrt) {
    1432         214 :                 vp9->emul_esd->decoderConfig->bufferSizeDB = btrt->bufferSizeDB;
    1433         214 :                 vp9->emul_esd->decoderConfig->avgBitrate = btrt->avgBitrate;
    1434         214 :                 vp9->emul_esd->decoderConfig->maxBitrate = btrt->maxBitrate;
    1435             :         }
    1436             : 
    1437         214 :         if (vp9->vp_config) {
    1438         214 :                 GF_VPConfig *vp9_cfg = VP_DuplicateConfig(vp9->vp_config->config);
    1439         214 :                 if (vp9_cfg) {
    1440         214 :                         gf_odf_vp_cfg_write(vp9_cfg, &vp9->emul_esd->decoderConfig->decoderSpecificInfo->data, &vp9->emul_esd->decoderConfig->decoderSpecificInfo->dataLength, GF_FALSE);
    1441         214 :                         gf_odf_vp_cfg_del(vp9_cfg);
    1442             :                 }
    1443             :         }
    1444         214 : }
    1445             : 
    1446         176 : void VP9_RewriteESDescriptor(GF_MPEGVisualSampleEntryBox *vp9)
    1447             : {
    1448         176 :         VP9_RewriteESDescriptorEx(vp9, NULL);
    1449         176 : }
    1450             : 
    1451             : 
    1452             : 
    1453           1 : static GF_DOVIDecoderConfigurationRecord* DOVI_DuplicateConfig(GF_DOVIDecoderConfigurationRecord *cfg)
    1454             : {
    1455             :         GF_DOVIDecoderConfigurationRecord* out = NULL;
    1456           1 :         GF_SAFEALLOC(out, GF_DOVIDecoderConfigurationRecord);
    1457           1 :         if (!out) return NULL;
    1458             : 
    1459           1 :         out->dv_version_major = cfg->dv_version_major;
    1460           1 :         out->dv_version_minor = cfg->dv_version_minor;
    1461           1 :         out->dv_profile = cfg->dv_profile;
    1462           1 :         out->dv_level = cfg->dv_level;
    1463           1 :         out->rpu_present_flag = cfg->rpu_present_flag;
    1464           1 :         out->el_present_flag = cfg->el_present_flag;
    1465           1 :         out->bl_present_flag = cfg->bl_present_flag;
    1466             : 
    1467           1 :         return out;
    1468             : }
    1469             : 
    1470             : 
    1471             : 
    1472             : #ifndef GPAC_DISABLE_ISOM_WRITE
    1473             : GF_EXPORT
    1474         391 : GF_Err gf_isom_avc_config_new(GF_ISOFile *the_file, u32 trackNumber, GF_AVCConfig *cfg, const char *URLname, const char *URNname, u32 *outDescriptionIndex)
    1475             : {
    1476             :         GF_TrackBox *trak;
    1477             :         GF_Err e;
    1478             :         GF_SampleDescriptionBox *stsd;
    1479             :         u32 dataRefIndex;
    1480             :         GF_MPEGVisualSampleEntryBox *entry;
    1481             : 
    1482         391 :         e = CanAccessMovie(the_file, GF_ISOM_OPEN_WRITE);
    1483         391 :         if (e) return e;
    1484             : 
    1485         391 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
    1486         391 :         if (!trak || !trak->Media || !cfg) return GF_BAD_PARAM;
    1487             : 
    1488             :         //get or create the data ref
    1489         391 :         e = Media_FindDataRef(trak->Media->information->dataInformation->dref, (char *)URLname, (char *)URNname, &dataRefIndex);
    1490         391 :         if (e) return e;
    1491         391 :         if (!dataRefIndex) {
    1492         383 :                 e = Media_CreateDataRef(the_file, trak->Media->information->dataInformation->dref, (char *)URLname, (char *)URNname, &dataRefIndex);
    1493         383 :                 if (e) return e;
    1494             :         }
    1495         391 :         if (!the_file->keep_utc && !gf_sys_is_test_mode() )
    1496           1 :                 trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time();
    1497             : 
    1498         391 :         stsd = trak->Media->information->sampleTable->SampleDescription;
    1499             : 
    1500             :         //create a new entry
    1501         391 :         entry = (GF_MPEGVisualSampleEntryBox *) gf_isom_box_new_parent(&stsd->child_boxes, GF_ISOM_BOX_TYPE_AVC1);
    1502         391 :         if (!entry) return GF_OUT_OF_MEM;
    1503         391 :         *outDescriptionIndex = gf_list_count(stsd->child_boxes);
    1504             : 
    1505         391 :         entry->avc_config = (GF_AVCConfigurationBox*)gf_isom_box_new_parent(&entry->child_boxes, GF_ISOM_BOX_TYPE_AVCC);
    1506         391 :         if (!entry->avc_config) return GF_OUT_OF_MEM;
    1507         391 :         entry->avc_config->config = AVC_DuplicateConfig(cfg);
    1508         391 :         if (!entry->avc_config->config) return GF_OUT_OF_MEM;
    1509         391 :         entry->dataReferenceIndex = dataRefIndex;
    1510             :         AVC_RewriteESDescriptor(entry);
    1511         391 :         return e;
    1512             : }
    1513             : 
    1514          30 : static GF_Err gf_isom_avc_config_update_ex(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex, GF_AVCConfig *cfg, u32 op_type, Bool keep_xps)
    1515             : {
    1516             :         GF_TrackBox *trak;
    1517             :         GF_Err e;
    1518             :         u32 i;
    1519             :         GF_MPEGVisualSampleEntryBox *entry;
    1520             : 
    1521          30 :         e = CanAccessMovie(the_file, GF_ISOM_OPEN_WRITE);
    1522          30 :         if (e) return e;
    1523          30 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
    1524          30 :         if (!trak || !trak->Media || !DescriptionIndex) return GF_BAD_PARAM;
    1525          29 :         entry = (GF_MPEGVisualSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, DescriptionIndex-1);
    1526          29 :         if (!entry) return GF_BAD_PARAM;
    1527          29 :         switch (entry->type) {
    1528             :         case GF_ISOM_BOX_TYPE_AVC1:
    1529             :         case GF_ISOM_BOX_TYPE_AVC2:
    1530             :         case GF_ISOM_BOX_TYPE_AVC3:
    1531             :         case GF_ISOM_BOX_TYPE_AVC4:
    1532             :         case GF_ISOM_BOX_TYPE_SVC1:
    1533             :         case GF_ISOM_BOX_TYPE_MVC1:
    1534             :                 break;
    1535             :         default:
    1536             :                 return GF_BAD_PARAM;
    1537             :         }
    1538             : 
    1539          29 :         switch (op_type) {
    1540             :         /*AVCC replacement*/
    1541           4 :         case 0:
    1542           4 :                 if (!cfg) return GF_BAD_PARAM;
    1543           4 :                 if (!entry->avc_config) {
    1544           0 :                         entry->avc_config = (GF_AVCConfigurationBox*)gf_isom_box_new_parent(&entry->child_boxes, GF_ISOM_BOX_TYPE_AVCC);
    1545           0 :                         if (!entry->avc_config) return GF_OUT_OF_MEM;
    1546             :                 }
    1547           4 :                 if (entry->avc_config->config) gf_odf_avc_cfg_del(entry->avc_config->config);
    1548           4 :                 entry->avc_config->config = AVC_DuplicateConfig(cfg);
    1549           4 :                 if (!entry->avc_config->config) return GF_OUT_OF_MEM;
    1550           4 :                 entry->type = GF_ISOM_BOX_TYPE_AVC1;
    1551           4 :                 break;
    1552             :         /*SVCC replacement*/
    1553           8 :         case 1:
    1554           8 :                 if (!cfg) return GF_BAD_PARAM;
    1555           8 :                 if (!entry->svc_config) {
    1556           7 :                         entry->svc_config = (GF_AVCConfigurationBox*)gf_isom_box_new_parent(&entry->child_boxes, GF_ISOM_BOX_TYPE_SVCC);
    1557           7 :                         if (!entry->svc_config) return GF_OUT_OF_MEM;
    1558             :                 }
    1559           8 :                 if (entry->svc_config->config) gf_odf_avc_cfg_del(entry->svc_config->config);
    1560           8 :                 entry->svc_config->config = AVC_DuplicateConfig(cfg);
    1561           8 :                 if (!entry->svc_config->config) return GF_OUT_OF_MEM;
    1562           8 :                 entry->type = GF_ISOM_BOX_TYPE_AVC1;
    1563           8 :                 break;
    1564             :         /*SVCC replacement and AVC removal*/
    1565           2 :         case 2:
    1566           2 :                 if (!cfg) return GF_BAD_PARAM;
    1567           2 :                 if (entry->avc_config) {
    1568           0 :                         gf_isom_box_del_parent(&entry->child_boxes, (GF_Box*)entry->avc_config);
    1569           0 :                         entry->avc_config = NULL;
    1570             :                 }
    1571           2 :                 if (!entry->svc_config) {
    1572           0 :                         entry->svc_config = (GF_AVCConfigurationBox*)gf_isom_box_new_parent(&entry->child_boxes, GF_ISOM_BOX_TYPE_SVCC);
    1573           0 :                         if (!entry->svc_config) return GF_OUT_OF_MEM;
    1574             :                 }
    1575           2 :                 if (entry->svc_config->config) gf_odf_avc_cfg_del(entry->svc_config->config);
    1576           2 :                 entry->svc_config->config = AVC_DuplicateConfig(cfg);
    1577           2 :                 if (!entry->svc_config->config) return GF_OUT_OF_MEM;
    1578           2 :                 entry->type = GF_ISOM_BOX_TYPE_SVC1;
    1579           2 :                 break;
    1580             :         /*AVCC removal and switch to avc3*/
    1581          15 :         case 3:
    1582          15 :                 if (!entry->avc_config || !entry->avc_config->config)
    1583             :                         return GF_BAD_PARAM;
    1584          15 :                 if (!keep_xps) {
    1585          39 :                         for (i=0; i<3; i++) {
    1586          39 :                                 GF_AVCConfigurationBox *a_cfg = entry->avc_config;
    1587          39 :                                 if (i==1) a_cfg = entry->svc_config;
    1588          26 :                                 else if (i==2) a_cfg = entry->mvc_config;
    1589          39 :                                 if (!a_cfg) continue;
    1590             : 
    1591             : 
    1592          22 :                                 while (gf_list_count(a_cfg->config->sequenceParameterSets)) {
    1593           9 :                                         GF_NALUFFParam *sl = (GF_NALUFFParam*)gf_list_get(a_cfg->config->sequenceParameterSets, 0);
    1594           9 :                                         gf_list_rem(a_cfg->config->sequenceParameterSets, 0);
    1595           9 :                                         if (sl->data) gf_free(sl->data);
    1596           9 :                                         gf_free(sl);
    1597             :                                 }
    1598             : 
    1599          22 :                                 while (gf_list_count(a_cfg->config->pictureParameterSets)) {
    1600           9 :                                         GF_NALUFFParam *sl = (GF_NALUFFParam*)gf_list_get(a_cfg->config->pictureParameterSets, 0);
    1601           9 :                                         gf_list_rem(a_cfg->config->pictureParameterSets, 0);
    1602           9 :                                         if (sl->data) gf_free(sl->data);
    1603           9 :                                         gf_free(sl);
    1604             :                                 }
    1605             : 
    1606          13 :                                 while (gf_list_count(a_cfg->config->sequenceParameterSetExtensions)) {
    1607           0 :                                         GF_NALUFFParam *sl = (GF_NALUFFParam*)gf_list_get(a_cfg->config->sequenceParameterSetExtensions, 0);
    1608           0 :                                         gf_list_rem(a_cfg->config->sequenceParameterSetExtensions, 0);
    1609           0 :                                         if (sl->data) gf_free(sl->data);
    1610           0 :                                         gf_free(sl);
    1611             :                                 }
    1612             :                         }
    1613             :                 }
    1614             : 
    1615          15 :                 if (entry->type == GF_ISOM_BOX_TYPE_AVC1)
    1616          11 :                         entry->type = GF_ISOM_BOX_TYPE_AVC3;
    1617           4 :                 else if (entry->type == GF_ISOM_BOX_TYPE_AVC2)
    1618           0 :                         entry->type = GF_ISOM_BOX_TYPE_AVC4;
    1619             :                 break;
    1620             :         /*MVCC replacement*/
    1621           0 :         case 4:
    1622           0 :                 if (!cfg) return GF_BAD_PARAM;
    1623           0 :                 if (!entry->mvc_config) {
    1624           0 :                         entry->mvc_config = (GF_AVCConfigurationBox*)gf_isom_box_new_parent(&entry->child_boxes, GF_ISOM_BOX_TYPE_MVCC);
    1625           0 :                         if (!entry->mvc_config) return GF_OUT_OF_MEM;
    1626             :                 }
    1627           0 :                 if (entry->mvc_config->config) gf_odf_avc_cfg_del(entry->mvc_config->config);
    1628           0 :                 entry->mvc_config->config = AVC_DuplicateConfig(cfg);
    1629           0 :                 if (!entry->mvc_config->config) return GF_OUT_OF_MEM;
    1630           0 :                 entry->type = GF_ISOM_BOX_TYPE_AVC1;
    1631           0 :                 e = gf_isom_check_mvc(the_file, trak, entry);
    1632           0 :                 if (e) return e;
    1633             :                 break;
    1634             :         /*MVCC replacement and AVC removal*/
    1635           0 :         case 5:
    1636           0 :                 if (!cfg) return GF_BAD_PARAM;
    1637           0 :                 if (entry->avc_config) {
    1638           0 :                         gf_isom_box_del_parent(&entry->child_boxes, (GF_Box*)entry->avc_config);
    1639           0 :                         entry->avc_config = NULL;
    1640             :                 }
    1641           0 :                 if (!entry->mvc_config) {
    1642           0 :                         entry->mvc_config = (GF_AVCConfigurationBox*)gf_isom_box_new_parent(&entry->child_boxes, GF_ISOM_BOX_TYPE_MVCC);
    1643           0 :                         if (!entry->mvc_config) return GF_OUT_OF_MEM;
    1644             :                 }
    1645           0 :                 if (entry->mvc_config->config) gf_odf_avc_cfg_del(entry->mvc_config->config);
    1646           0 :                 entry->mvc_config->config = AVC_DuplicateConfig(cfg);
    1647           0 :                 if (!entry->mvc_config->config) return GF_OUT_OF_MEM;
    1648           0 :                 entry->type = GF_ISOM_BOX_TYPE_MVC1;
    1649           0 :                 e = gf_isom_check_mvc(the_file, trak, entry);
    1650           0 :                 if (e) return e;
    1651             :                 break;
    1652             :         }
    1653             :         AVC_RewriteESDescriptor(entry);
    1654          29 :         return GF_OK;
    1655             : }
    1656             : 
    1657             : GF_EXPORT
    1658          15 : GF_Err gf_isom_avc_set_inband_config(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex, Bool keep_xps)
    1659             : {
    1660          15 :         return gf_isom_avc_config_update_ex(the_file, trackNumber, DescriptionIndex, NULL, 3, keep_xps);
    1661             : }
    1662             : 
    1663             : GF_EXPORT
    1664           5 : GF_Err gf_isom_avc_config_update(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex, GF_AVCConfig *cfg)
    1665             : {
    1666           5 :         return gf_isom_avc_config_update_ex(the_file, trackNumber, DescriptionIndex, cfg, 0, GF_FALSE);
    1667             : }
    1668             : 
    1669             : GF_EXPORT
    1670          10 : GF_Err gf_isom_svc_config_update(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex, GF_AVCConfig *cfg, Bool is_add)
    1671             : {
    1672          10 :         return gf_isom_avc_config_update_ex(the_file, trackNumber, DescriptionIndex, cfg, is_add ? 1 : 2, GF_FALSE);
    1673             : }
    1674             : 
    1675           0 : GF_Err gf_isom_mvc_config_update(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex, GF_AVCConfig *cfg, Bool is_add)
    1676             : {
    1677           0 :         return gf_isom_avc_config_update_ex(the_file, trackNumber, DescriptionIndex, cfg, is_add ? 4 : 5, GF_FALSE);
    1678             : }
    1679             : 
    1680           1 : static GF_Err gf_isom_svc_mvc_config_del(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex, Bool is_mvc)
    1681             : {
    1682             :         GF_TrackBox *trak;
    1683             :         GF_Err e;
    1684             :         GF_MPEGVisualSampleEntryBox *entry;
    1685             : 
    1686           1 :         e = CanAccessMovie(the_file, GF_ISOM_OPEN_WRITE);
    1687           1 :         if (e) return e;
    1688           1 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
    1689           1 :         if (!trak || !trak->Media || !DescriptionIndex) return GF_BAD_PARAM;
    1690           1 :         entry = (GF_MPEGVisualSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, DescriptionIndex-1);
    1691           1 :         if (!entry) return GF_BAD_PARAM;
    1692           1 :         switch (entry->type) {
    1693             :         case GF_ISOM_BOX_TYPE_AVC1:
    1694             :         case GF_ISOM_BOX_TYPE_AVC2:
    1695             :         case GF_ISOM_BOX_TYPE_AVC3:
    1696             :         case GF_ISOM_BOX_TYPE_AVC4:
    1697             :         case GF_ISOM_BOX_TYPE_SVC1:
    1698             :         case GF_ISOM_BOX_TYPE_MVC1:
    1699             :                 break;
    1700             :         default:
    1701             :                 return GF_BAD_PARAM;
    1702             :         }
    1703             : 
    1704           1 :         if (is_mvc && entry->mvc_config) {
    1705           0 :                 gf_isom_box_del_parent(&entry->child_boxes, (GF_Box*)entry->mvc_config);
    1706           0 :                 entry->mvc_config = NULL;
    1707             :         }
    1708           1 :         else if (!is_mvc && entry->svc_config) {
    1709           1 :                 gf_isom_box_del_parent(&entry->child_boxes, (GF_Box*)entry->svc_config);
    1710           1 :                 entry->svc_config = NULL;
    1711             :         }
    1712             :         AVC_RewriteESDescriptor(entry);
    1713           1 :         return GF_OK;
    1714             : }
    1715             : 
    1716           1 : GF_Err gf_isom_svc_config_del(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
    1717             : {
    1718           1 :         return gf_isom_svc_mvc_config_del(the_file, trackNumber, DescriptionIndex, GF_FALSE);
    1719             : }
    1720             : 
    1721           0 : GF_Err gf_isom_mvc_config_del(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
    1722             : {
    1723           0 :         return gf_isom_svc_mvc_config_del(the_file, trackNumber, DescriptionIndex, GF_TRUE);
    1724             : }
    1725             : 
    1726           4 : static GF_Err gf_isom_svc_mvc_config_new(GF_ISOFile *the_file, u32 trackNumber, GF_AVCConfig *cfg, Bool is_mvc, char *URLname, char *URNname, u32 *outDescriptionIndex)
    1727             : {
    1728             :         GF_TrackBox *trak;
    1729             :         GF_Err e;
    1730             :         u32 dataRefIndex;
    1731             :         GF_SampleDescriptionBox *stsd;
    1732             :         GF_MPEGVisualSampleEntryBox *entry;
    1733             : 
    1734           4 :         e = CanAccessMovie(the_file, GF_ISOM_OPEN_WRITE);
    1735           4 :         if (e) return e;
    1736             : 
    1737           4 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
    1738           4 :         if (!trak || !trak->Media || !cfg) return GF_BAD_PARAM;
    1739             : 
    1740             :         //get or create the data ref
    1741           4 :         e = Media_FindDataRef(trak->Media->information->dataInformation->dref, URLname, URNname, &dataRefIndex);
    1742           4 :         if (e) return e;
    1743           4 :         if (!dataRefIndex) {
    1744           4 :                 e = Media_CreateDataRef(the_file, trak->Media->information->dataInformation->dref, URLname, URNname, &dataRefIndex);
    1745           4 :                 if (e) return e;
    1746             :         }
    1747           4 :         if (!the_file->keep_utc)
    1748           4 :                 trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time();
    1749             : 
    1750           4 :         stsd = trak->Media->information->sampleTable->SampleDescription;
    1751             :         //create a new entry
    1752           4 :         if (is_mvc) {
    1753           0 :                 entry = (GF_MPEGVisualSampleEntryBox *) gf_isom_box_new_parent(&stsd->child_boxes, GF_ISOM_BOX_TYPE_MVC1);
    1754           0 :                 if (!entry) return GF_OUT_OF_MEM;
    1755           0 :                 entry->mvc_config = (GF_AVCConfigurationBox*)gf_isom_box_new_parent(&entry->child_boxes, GF_ISOM_BOX_TYPE_MVCC);
    1756           0 :                 if (!entry->mvc_config) return GF_OUT_OF_MEM;
    1757           0 :                 entry->mvc_config->config = AVC_DuplicateConfig(cfg);
    1758           0 :                 if (!entry->mvc_config->config) return GF_OUT_OF_MEM;
    1759             :         } else {
    1760           4 :                 entry = (GF_MPEGVisualSampleEntryBox *) gf_isom_box_new_parent(&stsd->child_boxes,GF_ISOM_BOX_TYPE_SVC1);
    1761           4 :                 if (!entry) return GF_OUT_OF_MEM;
    1762           4 :                 entry->svc_config = (GF_AVCConfigurationBox*)gf_isom_box_new_parent(&entry->child_boxes,GF_ISOM_BOX_TYPE_SVCC);
    1763           4 :                 if (!entry->svc_config) return GF_OUT_OF_MEM;
    1764           4 :                 entry->svc_config->config = AVC_DuplicateConfig(cfg);
    1765           4 :                 if (!entry->svc_config->config) return GF_OUT_OF_MEM;
    1766             :         }
    1767           4 :         entry->dataReferenceIndex = dataRefIndex;
    1768           4 :         *outDescriptionIndex = gf_list_count(stsd->child_boxes);
    1769             :         AVC_RewriteESDescriptor(entry);
    1770           4 :         return e;
    1771             : }
    1772             : 
    1773             : GF_EXPORT
    1774           4 : GF_Err gf_isom_svc_config_new(GF_ISOFile *the_file, u32 trackNumber, GF_AVCConfig *cfg, const char *URLname, const char *URNname, u32 *outDescriptionIndex)
    1775             : {
    1776           4 :         return gf_isom_svc_mvc_config_new(the_file, trackNumber, cfg, GF_FALSE, (char *) URLname, (char *) URNname,outDescriptionIndex);
    1777             : }
    1778             : 
    1779             : GF_EXPORT
    1780           0 : GF_Err gf_isom_mvc_config_new(GF_ISOFile *the_file, u32 trackNumber, GF_AVCConfig *cfg, const char *URLname, const char *URNname, u32 *outDescriptionIndex)
    1781             : {
    1782           0 :         return gf_isom_svc_mvc_config_new(the_file, trackNumber, cfg, GF_TRUE, (char *) URLname, (char *) URNname,outDescriptionIndex);
    1783             : }
    1784             : 
    1785             : 
    1786             : GF_EXPORT
    1787         229 : GF_Err gf_isom_hevc_config_new(GF_ISOFile *the_file, u32 trackNumber, GF_HEVCConfig *cfg, const char *URLname, const char *URNname, u32 *outDescriptionIndex)
    1788             : {
    1789             :         GF_TrackBox *trak;
    1790             :         GF_Err e;
    1791             :         u32 dataRefIndex;
    1792             :         GF_SampleDescriptionBox *stsd;
    1793             :         GF_MPEGVisualSampleEntryBox *entry;
    1794             : 
    1795         229 :         e = CanAccessMovie(the_file, GF_ISOM_OPEN_WRITE);
    1796         229 :         if (e) return e;
    1797             : 
    1798         229 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
    1799         229 :         if (!trak || !trak->Media || !cfg) return GF_BAD_PARAM;
    1800             : 
    1801             :         //get or create the data ref
    1802         229 :         e = Media_FindDataRef(trak->Media->information->dataInformation->dref, (char *)URLname, (char *)URNname, &dataRefIndex);
    1803         229 :         if (e) return e;
    1804         229 :         if (!dataRefIndex) {
    1805         223 :                 e = Media_CreateDataRef(the_file, trak->Media->information->dataInformation->dref, (char *)URLname, (char *)URNname, &dataRefIndex);
    1806         223 :                 if (e) return e;
    1807             :         }
    1808         229 :         if (!the_file->keep_utc)
    1809         229 :                 trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time();
    1810             : 
    1811         229 :         stsd = trak->Media->information->sampleTable->SampleDescription;
    1812             :         //create a new entry
    1813         229 :         entry = (GF_MPEGVisualSampleEntryBox *) gf_isom_box_new_parent(&stsd->child_boxes, GF_ISOM_BOX_TYPE_HVC1);
    1814         229 :         if (!entry) return GF_OUT_OF_MEM;
    1815         229 :         entry->hevc_config = (GF_HEVCConfigurationBox*)gf_isom_box_new_parent(&entry->child_boxes, GF_ISOM_BOX_TYPE_HVCC);
    1816         229 :         if (!entry->hevc_config) return GF_OUT_OF_MEM;
    1817         229 :         entry->hevc_config->config = HEVC_DuplicateConfig(cfg);
    1818         229 :         if (!entry->hevc_config->config) return GF_OUT_OF_MEM;
    1819         229 :         entry->dataReferenceIndex = dataRefIndex;
    1820         229 :         *outDescriptionIndex = gf_list_count(stsd->child_boxes);
    1821             :         HEVC_RewriteESDescriptor(entry);
    1822         229 :         return e;
    1823             : }
    1824             : 
    1825             : 
    1826             : GF_EXPORT
    1827           0 : GF_Err gf_isom_vvc_config_new(GF_ISOFile *the_file, u32 trackNumber, GF_VVCConfig *cfg, const char *URLname, const char *URNname, u32 *outDescriptionIndex)
    1828             : {
    1829             :         GF_TrackBox *trak;
    1830             :         GF_Err e;
    1831             :         u32 dataRefIndex;
    1832             :         GF_SampleDescriptionBox *stsd;
    1833             :         GF_MPEGVisualSampleEntryBox *entry;
    1834             : 
    1835           0 :         e = CanAccessMovie(the_file, GF_ISOM_OPEN_WRITE);
    1836           0 :         if (e) return e;
    1837             : 
    1838           0 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
    1839           0 :         if (!trak || !trak->Media || !cfg) return GF_BAD_PARAM;
    1840             : 
    1841             :         //get or create the data ref
    1842           0 :         e = Media_FindDataRef(trak->Media->information->dataInformation->dref, (char *)URLname, (char *)URNname, &dataRefIndex);
    1843           0 :         if (e) return e;
    1844           0 :         if (!dataRefIndex) {
    1845           0 :                 e = Media_CreateDataRef(the_file, trak->Media->information->dataInformation->dref, (char *)URLname, (char *)URNname, &dataRefIndex);
    1846           0 :                 if (e) return e;
    1847             :         }
    1848           0 :         if (!the_file->keep_utc)
    1849           0 :                 trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time();
    1850             : 
    1851           0 :         stsd = trak->Media->information->sampleTable->SampleDescription;
    1852             :         //create a new entry
    1853           0 :         entry = (GF_MPEGVisualSampleEntryBox *) gf_isom_box_new_parent(&stsd->child_boxes, GF_ISOM_BOX_TYPE_VVC1);
    1854           0 :         if (!entry) return GF_OUT_OF_MEM;
    1855           0 :         entry->vvc_config = (GF_VVCConfigurationBox*)gf_isom_box_new_parent(&entry->child_boxes, GF_ISOM_BOX_TYPE_VVCC);
    1856           0 :         if (!entry->vvc_config) return GF_OUT_OF_MEM;
    1857           0 :         entry->vvc_config->config = VVC_DuplicateConfig(cfg);
    1858           0 :         if (!entry->vvc_config->config) return GF_OUT_OF_MEM;
    1859           0 :         entry->dataReferenceIndex = dataRefIndex;
    1860           0 :         *outDescriptionIndex = gf_list_count(stsd->child_boxes);
    1861           0 :         return e;
    1862             : }
    1863             : 
    1864             : GF_EXPORT
    1865          28 : GF_Err gf_isom_vp_config_new(GF_ISOFile *the_file, u32 trackNumber, GF_VPConfig *cfg, const char *URLname, const char *URNname, u32 *outDescriptionIndex, u32 vpx_type)
    1866             : {
    1867             :         GF_TrackBox *trak;
    1868             :         GF_Err e;
    1869             :         u32 dataRefIndex;
    1870             :         GF_SampleDescriptionBox *stsd;
    1871             :         GF_MPEGVisualSampleEntryBox *entry;
    1872             : 
    1873          28 :         e = CanAccessMovie(the_file, GF_ISOM_OPEN_WRITE);
    1874          28 :         if (e) return e;
    1875             : 
    1876          28 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
    1877          28 :         if (!trak || !trak->Media || !cfg) return GF_BAD_PARAM;
    1878             : 
    1879             :         //get or create the data ref
    1880          28 :         e = Media_FindDataRef(trak->Media->information->dataInformation->dref, (char *)URLname, (char *)URNname, &dataRefIndex);
    1881          28 :         if (e) return e;
    1882          28 :         if (!dataRefIndex) {
    1883          28 :                 e = Media_CreateDataRef(the_file, trak->Media->information->dataInformation->dref, (char *)URLname, (char *)URNname, &dataRefIndex);
    1884          28 :                 if (e) return e;
    1885             :         }
    1886          28 :         if (!the_file->keep_utc)
    1887          28 :                 trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time();
    1888             : 
    1889          28 :         stsd = trak->Media->information->sampleTable->SampleDescription;
    1890             :         //create a new entry
    1891          28 :         entry = (GF_MPEGVisualSampleEntryBox *)gf_isom_box_new_parent(&stsd->child_boxes, vpx_type);
    1892          28 :         if (!entry) return GF_OUT_OF_MEM;
    1893             :         
    1894          28 :         entry->vp_config = (GF_VPConfigurationBox*)gf_isom_box_new_parent(&entry->child_boxes, GF_ISOM_BOX_TYPE_VPCC);
    1895          28 :         if (!entry->vp_config) return GF_OUT_OF_MEM;
    1896          28 :         entry->vp_config->config = VP_DuplicateConfig(cfg);
    1897          28 :         if (!entry->vp_config->config) return GF_OUT_OF_MEM;
    1898          28 :         strncpy(entry->compressor_name, "\012VPC Coding", sizeof(entry->compressor_name)-1);
    1899          28 :         entry->dataReferenceIndex = dataRefIndex;
    1900          28 :         *outDescriptionIndex = gf_list_count(stsd->child_boxes);
    1901          28 :         return e;
    1902             : }
    1903             : 
    1904             : GF_EXPORT
    1905         154 : GF_Err gf_isom_av1_config_new(GF_ISOFile *the_file, u32 trackNumber, GF_AV1Config *cfg, const char *URLname, const char *URNname, u32 *outDescriptionIndex)
    1906             : {
    1907             :         GF_TrackBox *trak;
    1908             :         GF_Err e;
    1909             :         u32 dataRefIndex;
    1910             :         GF_MPEGVisualSampleEntryBox *entry;
    1911             :         GF_SampleDescriptionBox *stsd;
    1912             : 
    1913         154 :         e = CanAccessMovie(the_file, GF_ISOM_OPEN_WRITE);
    1914         154 :         if (e) return e;
    1915             : 
    1916         154 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
    1917         154 :         if (!trak || !trak->Media || !cfg) return GF_BAD_PARAM;
    1918             : 
    1919             :         //get or create the data ref
    1920         154 :         e = Media_FindDataRef(trak->Media->information->dataInformation->dref, (char *)URLname, (char *)URNname, &dataRefIndex);
    1921         154 :         if (e) return e;
    1922         154 :         if (!dataRefIndex) {
    1923         154 :                 e = Media_CreateDataRef(the_file, trak->Media->information->dataInformation->dref, (char *)URLname, (char *)URNname, &dataRefIndex);
    1924         154 :                 if (e) return e;
    1925             :         }
    1926         154 :         if (!the_file->keep_utc)
    1927         154 :                 trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time();
    1928             : 
    1929         154 :         stsd = trak->Media->information->sampleTable->SampleDescription;
    1930             :         //create a new entry
    1931         154 :         entry = (GF_MPEGVisualSampleEntryBox *)gf_isom_box_new_parent(&stsd->child_boxes, GF_ISOM_BOX_TYPE_AV01);
    1932         154 :         if (!entry) return GF_OUT_OF_MEM;
    1933         154 :         entry->av1_config = (GF_AV1ConfigurationBox*)gf_isom_box_new_parent(&entry->child_boxes, GF_ISOM_BOX_TYPE_AV1C);
    1934         154 :         if (!entry->av1_config) return GF_OUT_OF_MEM;
    1935         154 :         entry->av1_config->config = AV1_DuplicateConfig(cfg);
    1936         154 :         if (!entry->av1_config->config) return GF_OUT_OF_MEM;
    1937         154 :         entry->dataReferenceIndex = dataRefIndex;
    1938         154 :         *outDescriptionIndex = gf_list_count(stsd->child_boxes);
    1939         154 :         return e;
    1940             : }
    1941             : 
    1942             : 
    1943             : typedef enum
    1944             : {
    1945             :         GF_ISOM_HVCC_UPDATE = 0,
    1946             :         GF_ISOM_HVCC_SET_INBAND,
    1947             :         GF_ISOM_HVCC_SET_TILE,
    1948             :         GF_ISOM_HVCC_SET_TILE_BASE_TRACK,
    1949             :         GF_ISOM_HVCC_SET_LHVC,
    1950             :         GF_ISOM_HVCC_SET_LHVC_WITH_BASE,
    1951             :         GF_ISOM_HVCC_SET_LHVC_WITH_BASE_BACKWARD,
    1952             :         GF_ISOM_HVCC_SET_HEVC_TILE_BASE,
    1953             :         GF_ISOM_LHCC_SET_INBAND
    1954             : } HevcConfigUpdateType;
    1955             : 
    1956          16 : static Bool nalu_cleanup_config(GF_List *param_array, Bool set_inband, Bool keep_xps)
    1957             : {
    1958             :         u32 i;
    1959             :         Bool array_incomplete = set_inband;
    1960          16 :         if (!param_array) return 0;
    1961             : 
    1962          30 :         for (i=0; i<gf_list_count(param_array); i++) {
    1963          30 :                 GF_NALUFFParamArray *ar = (GF_NALUFFParamArray*)gf_list_get(param_array, i);
    1964             : 
    1965             :                 /*we want to force inband signaling*/
    1966          30 :                 if (set_inband) {
    1967          27 :                         ar->array_completeness = 0;
    1968          27 :                         if (keep_xps) {
    1969             :                                 array_incomplete=1;
    1970           3 :                                 continue;
    1971             :                         }
    1972             : 
    1973          48 :                         while (gf_list_count(ar->nalus)) {
    1974          24 :                                 GF_NALUFFParam *sl = (GF_NALUFFParam*)gf_list_get(ar->nalus, 0);
    1975          24 :                                 gf_list_rem(ar->nalus, 0);
    1976          24 :                                 if (sl->data) gf_free(sl->data);
    1977          24 :                                 gf_free(sl);
    1978             :                         }
    1979          24 :                         gf_list_del(ar->nalus);
    1980          24 :                         gf_free(ar);
    1981             :                         ar=NULL;
    1982          24 :                         gf_list_rem(param_array, i);
    1983          24 :                         i--;
    1984          24 :                         continue;
    1985             :                 }
    1986           3 :                 if (ar && !ar->array_completeness)
    1987             :                         array_incomplete = 1;
    1988             :         }
    1989             :         return array_incomplete;
    1990             : }
    1991             : 
    1992             : static
    1993         150 : GF_Err gf_isom_hevc_config_update_ex(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex, GF_HEVCConfig *cfg, u32 operand_type, Bool keep_xps)
    1994             : {
    1995             :         u32 array_incomplete;
    1996             :         GF_TrackBox *trak;
    1997             :         GF_Err e;
    1998             :         GF_MPEGVisualSampleEntryBox *entry;
    1999             :         GF_SampleDescriptionBox *stsd;
    2000             : 
    2001         150 :         e = CanAccessMovie(the_file, GF_ISOM_OPEN_WRITE);
    2002         150 :         if (e) return e;
    2003         150 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
    2004         150 :         if (!trak || !trak->Media || !DescriptionIndex) return GF_BAD_PARAM;
    2005         150 :         stsd = trak->Media->information->sampleTable->SampleDescription;
    2006         150 :         entry = (GF_MPEGVisualSampleEntryBox *)gf_list_get(stsd->child_boxes, DescriptionIndex-1);
    2007         150 :         if (!entry) return GF_BAD_PARAM;
    2008         150 :         switch (entry->type) {
    2009             :         case GF_ISOM_BOX_TYPE_HVC1:
    2010             :         case GF_ISOM_BOX_TYPE_HEV1:
    2011             :         case GF_ISOM_BOX_TYPE_HVC2:
    2012             :         case GF_ISOM_BOX_TYPE_HEV2:
    2013             :         case GF_ISOM_BOX_TYPE_LHV1:
    2014             :         case GF_ISOM_BOX_TYPE_LHE1:
    2015             :         case GF_ISOM_BOX_TYPE_HVT1:
    2016             :                 break;
    2017             :         default:
    2018             :                 return GF_BAD_PARAM;
    2019             :         }
    2020             : 
    2021             : 
    2022         150 :         if (operand_type == GF_ISOM_HVCC_SET_TILE_BASE_TRACK) {
    2023           5 :                 if (entry->type==GF_ISOM_BOX_TYPE_HVC1)
    2024           5 :                         entry->type = GF_ISOM_BOX_TYPE_HVC2;
    2025           0 :                 else if (entry->type==GF_ISOM_BOX_TYPE_HEV1)
    2026           0 :                         entry->type = GF_ISOM_BOX_TYPE_HEV2;
    2027         145 :         } else if (operand_type == GF_ISOM_HVCC_SET_TILE) {
    2028         114 :                 if (!entry->hevc_config) entry->hevc_config = (GF_HEVCConfigurationBox*)gf_isom_box_new_parent(&entry->child_boxes, GF_ISOM_BOX_TYPE_HVCC);
    2029         114 :                 if (!entry->hevc_config) return GF_OUT_OF_MEM;
    2030         114 :                 if (entry->hevc_config->config) gf_odf_hevc_cfg_del(entry->hevc_config->config);
    2031         114 :                 entry->hevc_config->config = NULL;
    2032         114 :                 entry->type = GF_ISOM_BOX_TYPE_HVT1;
    2033          31 :         } else if (operand_type < GF_ISOM_HVCC_SET_LHVC) {
    2034          16 :                 if ((operand_type != GF_ISOM_HVCC_SET_INBAND) && !entry->hevc_config) {
    2035           0 :                         entry->hevc_config = (GF_HEVCConfigurationBox*)gf_isom_box_new_parent(&entry->child_boxes, GF_ISOM_BOX_TYPE_HVCC);
    2036           0 :                         if (!entry->hevc_config) return GF_OUT_OF_MEM;
    2037             :                 }
    2038             : 
    2039          16 :                 if (cfg) {
    2040           1 :                         if (entry->hevc_config->config) gf_odf_hevc_cfg_del(entry->hevc_config->config);
    2041           1 :                         entry->hevc_config->config = HEVC_DuplicateConfig(cfg);
    2042             :                 } else {
    2043             :                         operand_type=GF_ISOM_HVCC_SET_INBAND;
    2044             :                 }
    2045          16 :                 array_incomplete = (operand_type==GF_ISOM_HVCC_SET_INBAND) ? 1 : 0;
    2046          16 :                 if (entry->hevc_config && nalu_cleanup_config(entry->hevc_config->config ? entry->hevc_config->config->param_array : NULL,
    2047             :                         (operand_type==GF_ISOM_HVCC_SET_INBAND) ? GF_TRUE:GF_FALSE,
    2048             :                         keep_xps)
    2049             :                 ) {
    2050             :                         array_incomplete=1;
    2051             :                 }
    2052             : 
    2053          16 :                 if (entry->lhvc_config && nalu_cleanup_config(entry->lhvc_config->config ? entry->lhvc_config->config->param_array : NULL,
    2054             :                         (operand_type==GF_ISOM_HVCC_SET_INBAND),
    2055             :                         keep_xps)
    2056             :                 )
    2057             :                         array_incomplete=1;
    2058             : 
    2059          16 :                 switch (entry->type) {
    2060          16 :                 case GF_ISOM_BOX_TYPE_HEV1:
    2061             :                 case GF_ISOM_BOX_TYPE_HVC1:
    2062          16 :                         entry->type = array_incomplete ? GF_ISOM_BOX_TYPE_HEV1 : GF_ISOM_BOX_TYPE_HVC1;
    2063          16 :                         break;
    2064           0 :                 case GF_ISOM_BOX_TYPE_HEV2:
    2065             :                 case GF_ISOM_BOX_TYPE_HVC2:
    2066           0 :                         entry->type = array_incomplete ? GF_ISOM_BOX_TYPE_HEV2 : GF_ISOM_BOX_TYPE_HVC2;
    2067           0 :                         break;
    2068           0 :                 case GF_ISOM_BOX_TYPE_LHE1:
    2069             :                 case GF_ISOM_BOX_TYPE_LHV1:
    2070           0 :                         entry->type = array_incomplete ? GF_ISOM_BOX_TYPE_LHE1 : GF_ISOM_BOX_TYPE_LHV1;
    2071           0 :                         break;
    2072             :                 }
    2073             :         } else {
    2074             : 
    2075             :                 /*SVCC replacement/removal with HEVC base, backward compatible signaling*/
    2076          15 :                 if ((operand_type==GF_ISOM_HVCC_SET_LHVC_WITH_BASE_BACKWARD) || (operand_type==GF_ISOM_HVCC_SET_LHVC_WITH_BASE) || (operand_type==GF_ISOM_HVCC_SET_HEVC_TILE_BASE) ) {
    2077          15 :                         if (!entry->hevc_config) return GF_BAD_PARAM;
    2078          15 :                         if (!cfg) {
    2079           1 :                                 if (entry->lhvc_config) {
    2080           1 :                                         gf_isom_box_del_parent(&entry->child_boxes, (GF_Box*)entry->lhvc_config);
    2081           1 :                                         entry->lhvc_config = NULL;
    2082             :                                 }
    2083           1 :                                 if (entry->type==GF_ISOM_BOX_TYPE_LHE1) entry->type = (operand_type==GF_ISOM_HVCC_SET_LHVC_WITH_BASE) ? GF_ISOM_BOX_TYPE_HEV2 : GF_ISOM_BOX_TYPE_HEV1;
    2084           1 :                                 else if (entry->type==GF_ISOM_BOX_TYPE_HEV1) entry->type = (operand_type==GF_ISOM_HVCC_SET_LHVC_WITH_BASE) ? GF_ISOM_BOX_TYPE_HEV2 : GF_ISOM_BOX_TYPE_HEV1;
    2085           1 :                                 else entry->type =  (operand_type==GF_ISOM_HVCC_SET_LHVC_WITH_BASE) ? GF_ISOM_BOX_TYPE_HVC2 : GF_ISOM_BOX_TYPE_HVC1;
    2086             :                         } else {
    2087          14 :                                 if (operand_type != GF_ISOM_HVCC_SET_HEVC_TILE_BASE) {
    2088           9 :                                         if (!entry->lhvc_config) {
    2089           9 :                                                 entry->lhvc_config = (GF_HEVCConfigurationBox*)gf_isom_box_new_parent(&entry->child_boxes, GF_ISOM_BOX_TYPE_LHVC);
    2090           9 :                                                 if (!entry->lhvc_config) return GF_OUT_OF_MEM;
    2091             :                                         }
    2092           9 :                                         if (entry->lhvc_config->config) gf_odf_hevc_cfg_del(entry->lhvc_config->config);
    2093           9 :                                         entry->lhvc_config->config = HEVC_DuplicateConfig(cfg);
    2094           9 :                                         if (!entry->lhvc_config->config) return GF_OUT_OF_MEM;
    2095             :                                 }
    2096             :                                 
    2097          14 :                                 if (operand_type==GF_ISOM_HVCC_SET_LHVC_WITH_BASE_BACKWARD) {
    2098           8 :                                         if (entry->type==GF_ISOM_BOX_TYPE_HEV2) entry->type = GF_ISOM_BOX_TYPE_HEV1;
    2099           8 :                                         else entry->type = GF_ISOM_BOX_TYPE_HVC1;
    2100             :                                 } else {
    2101           6 :                                         if (entry->type==GF_ISOM_BOX_TYPE_HEV1) entry->type = GF_ISOM_BOX_TYPE_HEV2;
    2102           6 :                                         else entry->type = GF_ISOM_BOX_TYPE_HVC2;
    2103             :                                 }
    2104             :                         }
    2105             :                 }
    2106             :                 /*LHEVC track without base*/
    2107           0 :                 else if (operand_type==GF_ISOM_HVCC_SET_LHVC) {
    2108           0 :                         if (entry->hevc_config) {
    2109           0 :                                 gf_isom_box_del_parent(&entry->child_boxes, (GF_Box*)entry->hevc_config);
    2110           0 :                                 entry->hevc_config=NULL;
    2111             :                         }
    2112           0 :                         if (!cfg) return GF_BAD_PARAM;
    2113             : 
    2114           0 :                         if (!entry->lhvc_config) {
    2115           0 :                                 entry->lhvc_config = (GF_HEVCConfigurationBox*)gf_isom_box_new_parent(&entry->child_boxes, GF_ISOM_BOX_TYPE_LHVC);
    2116           0 :                                 if (!entry->lhvc_config) return GF_OUT_OF_MEM;
    2117             :                         }
    2118           0 :                         if (entry->lhvc_config->config) gf_odf_hevc_cfg_del(entry->lhvc_config->config);
    2119           0 :                         entry->lhvc_config->config = HEVC_DuplicateConfig(cfg);
    2120           0 :                         if (!entry->lhvc_config->config) return GF_OUT_OF_MEM;
    2121             : 
    2122           0 :                         if ((entry->type==GF_ISOM_BOX_TYPE_HEV1) || (entry->type==GF_ISOM_BOX_TYPE_HEV2)) entry->type = GF_ISOM_BOX_TYPE_LHE1;
    2123           0 :                         else entry->type = GF_ISOM_BOX_TYPE_LHV1;
    2124             :                 }
    2125             :                 /*LHEVC inband, no config change*/
    2126           0 :                 else if (operand_type==GF_ISOM_LHCC_SET_INBAND) {
    2127           0 :                         entry->type = GF_ISOM_BOX_TYPE_LHE1;
    2128             :                 }
    2129             :         }
    2130             : 
    2131             :         HEVC_RewriteESDescriptor(entry);
    2132         150 :         return GF_OK;
    2133             : }
    2134             : 
    2135             : GF_EXPORT
    2136           1 : GF_Err gf_isom_hevc_config_update(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex, GF_HEVCConfig *cfg)
    2137             : {
    2138           1 :         return gf_isom_hevc_config_update_ex(the_file, trackNumber, DescriptionIndex, cfg, GF_ISOM_HVCC_UPDATE, GF_FALSE);
    2139             : }
    2140             : 
    2141             : GF_EXPORT
    2142          15 : GF_Err gf_isom_hevc_set_inband_config(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex, Bool keep_xps)
    2143             : {
    2144          15 :         return gf_isom_hevc_config_update_ex(the_file, trackNumber, DescriptionIndex, NULL, GF_ISOM_HVCC_SET_INBAND, keep_xps);
    2145             : }
    2146             : 
    2147             : GF_EXPORT
    2148           0 : GF_Err gf_isom_lhvc_force_inband_config(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
    2149             : {
    2150           0 :         return gf_isom_hevc_config_update_ex(the_file, trackNumber, DescriptionIndex, NULL, GF_ISOM_LHCC_SET_INBAND, GF_FALSE);
    2151             : }
    2152             : 
    2153             : 
    2154             : GF_EXPORT
    2155         119 : GF_Err gf_isom_hevc_set_tile_config(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex, GF_HEVCConfig *cfg, Bool is_base_track)
    2156             : {
    2157         119 :         return gf_isom_hevc_config_update_ex(the_file, trackNumber, DescriptionIndex, cfg, is_base_track ? GF_ISOM_HVCC_SET_TILE_BASE_TRACK : GF_ISOM_HVCC_SET_TILE, GF_FALSE);
    2158             : }
    2159             : 
    2160             : GF_EXPORT
    2161          15 : GF_Err gf_isom_lhvc_config_update(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex, GF_HEVCConfig *cfg, GF_ISOMLHEVCTrackType track_type)
    2162             : {
    2163          15 :         if (cfg) cfg->is_lhvc = GF_TRUE;
    2164          15 :         switch (track_type) {
    2165           0 :         case GF_ISOM_LEHVC_ONLY:
    2166           0 :                 return gf_isom_hevc_config_update_ex(the_file, trackNumber, DescriptionIndex, cfg, GF_ISOM_HVCC_SET_LHVC, GF_FALSE);
    2167           1 :         case GF_ISOM_LEHVC_WITH_BASE:
    2168           1 :                 return gf_isom_hevc_config_update_ex(the_file, trackNumber, DescriptionIndex, cfg, GF_ISOM_HVCC_SET_LHVC_WITH_BASE, GF_FALSE);
    2169           9 :         case GF_ISOM_LEHVC_WITH_BASE_BACKWARD:
    2170           9 :                 return gf_isom_hevc_config_update_ex(the_file, trackNumber, DescriptionIndex, cfg, GF_ISOM_HVCC_SET_LHVC_WITH_BASE_BACKWARD, GF_FALSE);
    2171           5 :         case GF_ISOM_HEVC_TILE_BASE:
    2172           5 :                 return gf_isom_hevc_config_update_ex(the_file, trackNumber, DescriptionIndex, cfg, GF_ISOM_HVCC_SET_HEVC_TILE_BASE, GF_FALSE);
    2173             :         default:
    2174             :                 return GF_BAD_PARAM;
    2175             :         }
    2176             : }
    2177             : 
    2178             : 
    2179             : typedef enum
    2180             : {
    2181             :         GF_ISOM_VVCC_UPDATE = 0,
    2182             :         GF_ISOM_VVCC_SET_INBAND,
    2183             : } VvcConfigUpdateType;
    2184             : 
    2185             : 
    2186             : static
    2187           0 : GF_Err gf_isom_vvc_config_update_ex(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex, GF_VVCConfig *cfg, u32 operand_type, Bool keep_xps)
    2188             : {
    2189             :         u32 array_incomplete;
    2190             :         GF_TrackBox *trak;
    2191             :         GF_Err e;
    2192             :         GF_MPEGVisualSampleEntryBox *entry;
    2193             :         GF_SampleDescriptionBox *stsd;
    2194             : 
    2195           0 :         e = CanAccessMovie(the_file, GF_ISOM_OPEN_WRITE);
    2196           0 :         if (e) return e;
    2197           0 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
    2198           0 :         if (!trak || !trak->Media || !DescriptionIndex) return GF_BAD_PARAM;
    2199           0 :         stsd = trak->Media->information->sampleTable->SampleDescription;
    2200           0 :         entry = (GF_MPEGVisualSampleEntryBox *)gf_list_get(stsd->child_boxes, DescriptionIndex-1);
    2201           0 :         if (!entry) return GF_BAD_PARAM;
    2202           0 :         switch (entry->type) {
    2203             :         case GF_ISOM_BOX_TYPE_VVC1:
    2204             :         case GF_ISOM_BOX_TYPE_VVI1:
    2205             :                 break;
    2206             :         default:
    2207             :                 return GF_BAD_PARAM;
    2208             :         }
    2209             : 
    2210             : 
    2211           0 :         if (operand_type <= GF_ISOM_VVCC_SET_INBAND) {
    2212           0 :                 if ((operand_type != GF_ISOM_VVCC_SET_INBAND) && !entry->hevc_config) {
    2213           0 :                         entry->vvc_config = (GF_VVCConfigurationBox*)gf_isom_box_new_parent(&entry->child_boxes, GF_ISOM_BOX_TYPE_VVCC);
    2214           0 :                         if (!entry->vvc_config) return GF_OUT_OF_MEM;
    2215             :                 }
    2216             : 
    2217           0 :                 if (cfg) {
    2218           0 :                         if (entry->vvc_config->config) gf_odf_vvc_cfg_del(entry->vvc_config->config);
    2219           0 :                         entry->vvc_config->config = VVC_DuplicateConfig(cfg);
    2220             :                 } else {
    2221             :                         operand_type = GF_ISOM_VVCC_SET_INBAND;
    2222             :                 }
    2223           0 :                 array_incomplete = (operand_type==GF_ISOM_VVCC_SET_INBAND) ? 1 : 0;
    2224           0 :                 if (entry->vvc_config && nalu_cleanup_config(entry->vvc_config->config ? entry->vvc_config->config->param_array : NULL,
    2225             :                         (operand_type==GF_ISOM_VVCC_SET_INBAND),
    2226             :                         keep_xps)
    2227             :                 ) {
    2228             :                         array_incomplete=1;
    2229             :                 }
    2230           0 :                 switch (entry->type) {
    2231           0 :                 case GF_ISOM_BOX_TYPE_VVC1:
    2232             :                 case GF_ISOM_BOX_TYPE_VVI1:
    2233           0 :                         entry->type = array_incomplete ? GF_ISOM_BOX_TYPE_VVI1 : GF_ISOM_BOX_TYPE_VVC1;
    2234           0 :                         break;
    2235             :                 }
    2236             :         }
    2237             :         return GF_OK;
    2238             : }
    2239             : 
    2240             : GF_EXPORT
    2241           0 : GF_Err gf_isom_vvc_set_inband_config(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex, Bool keep_xps)
    2242             : {
    2243           0 :         return gf_isom_vvc_config_update_ex(the_file, trackNumber, DescriptionIndex, NULL, GF_ISOM_VVCC_SET_INBAND, keep_xps);
    2244             : }
    2245             : 
    2246             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
    2247             : 
    2248             : GF_EXPORT
    2249          84 : GF_Box *gf_isom_clone_config_box(GF_Box *box)
    2250             : {
    2251          84 :         u8 *data=NULL;
    2252          84 :         u32 size=0;
    2253             :         GF_Err e;
    2254          84 :         GF_Box *clone=NULL;
    2255          84 :         GF_BitStream *bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
    2256          84 :         e = gf_isom_box_size(box);
    2257          84 :         if (!e)
    2258          84 :                 e = gf_isom_box_write(box, bs);
    2259             : 
    2260          84 :         gf_bs_get_content(bs, &data, &size);
    2261          84 :         gf_bs_del(bs);
    2262          84 :         if (!e) {
    2263          84 :                 bs = gf_bs_new(data, size, GF_BITSTREAM_READ);
    2264          84 :                 e = gf_isom_box_parse(&clone, bs);
    2265          84 :                 gf_bs_del(bs);
    2266             :         }
    2267          84 :         if (data)
    2268          84 :                 gf_free(data);
    2269          84 :         if (e) {
    2270           0 :                 if (clone)
    2271           0 :                         gf_isom_box_del(clone);
    2272           0 :                 clone = NULL;
    2273             :         }
    2274          84 :         return clone;
    2275             : }
    2276             : 
    2277             : GF_EXPORT
    2278         876 : GF_AVCConfig *gf_isom_avc_config_get(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
    2279             : {
    2280             :         GF_TrackBox *trak;
    2281             :         GF_MPEGVisualSampleEntryBox *entry;
    2282         876 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
    2283         876 :         if (!trak || !trak->Media || !DescriptionIndex) return NULL;
    2284         876 :         if (gf_isom_get_avc_svc_type(the_file, trackNumber, DescriptionIndex)==GF_ISOM_AVCTYPE_NONE)
    2285             :                 return NULL;
    2286             : 
    2287         867 :         entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, DescriptionIndex-1);
    2288         867 :         if (!entry) return NULL;
    2289             : 
    2290         867 :         if (!entry->avc_config) return NULL;
    2291         860 :         return AVC_DuplicateConfig(entry->avc_config->config);
    2292             : }
    2293             : 
    2294             : GF_EXPORT
    2295         295 : GF_HEVCConfig *gf_isom_hevc_config_get(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
    2296             : {
    2297             :         GF_TrackBox *trak;
    2298             :         GF_MPEGVisualSampleEntryBox *entry;
    2299         295 :         if (gf_isom_get_reference_count(the_file, trackNumber, GF_ISOM_REF_TBAS)) {
    2300             :                 u32 ref_track;
    2301           9 :                 GF_Err e = gf_isom_get_reference(the_file, trackNumber, GF_ISOM_REF_TBAS, 1, &ref_track);
    2302           9 :                 if (e == GF_OK) {
    2303           9 :                         trackNumber = ref_track;
    2304             :                 }
    2305             :         }
    2306         295 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
    2307         295 :         if (!trak || !trak->Media || !DescriptionIndex) return NULL;
    2308         295 :         if (gf_isom_get_hevc_lhvc_type(the_file, trackNumber, DescriptionIndex)==GF_ISOM_HEVCTYPE_NONE)
    2309             :                 return NULL;
    2310         283 :         entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, DescriptionIndex-1);
    2311         283 :         if (!entry) return NULL;
    2312         283 :         if (!entry->hevc_config) return NULL;
    2313         283 :         return HEVC_DuplicateConfig(entry->hevc_config->config);
    2314             : }
    2315             : 
    2316             : GF_EXPORT
    2317          12 : GF_ISOMVVCType gf_isom_get_vvc_type(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
    2318             : {
    2319             :         u32 type;
    2320             :         GF_TrackBox *trak;
    2321             :         GF_MPEGVisualSampleEntryBox *entry;
    2322          12 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
    2323          12 :         if (!trak || !trak->Media || !DescriptionIndex) return GF_ISOM_VVCTYPE_NONE;
    2324          12 :         if (!gf_isom_is_video_handler_type(trak->Media->handler->handlerType))
    2325             :                 return GF_ISOM_VVCTYPE_NONE;
    2326          12 :         entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, DescriptionIndex-1);
    2327          12 :         if (!entry) return GF_ISOM_VVCTYPE_NONE;
    2328          12 :         type = entry->type;
    2329             : 
    2330          12 :         if (type == GF_ISOM_BOX_TYPE_ENCV) {
    2331           1 :                 GF_ProtectionSchemeInfoBox *sinf = (GF_ProtectionSchemeInfoBox *) gf_isom_box_find_child(entry->child_boxes, GF_ISOM_BOX_TYPE_SINF);
    2332           1 :                 if (sinf && sinf->original_format) type = sinf->original_format->data_format;
    2333             :         }
    2334          11 :         else if (type == GF_ISOM_BOX_TYPE_RESV) {
    2335           0 :                 if (entry->rinf && entry->rinf->original_format) type = entry->rinf->original_format->data_format;
    2336             :         }
    2337             : 
    2338          12 :         switch (type) {
    2339             :         case GF_ISOM_BOX_TYPE_VVC1:
    2340             :         case GF_ISOM_BOX_TYPE_VVI1:
    2341             :                 return GF_ISOM_VVCTYPE_ONLY;
    2342          12 :         default:
    2343          12 :                 return GF_ISOM_VVCTYPE_NONE;
    2344             :         }
    2345             :         return GF_ISOM_VVCTYPE_NONE;
    2346             : }
    2347             : 
    2348             : GF_EXPORT
    2349          12 : GF_VVCConfig *gf_isom_vvc_config_get(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
    2350             : {
    2351             :         GF_TrackBox *trak;
    2352             :         GF_MPEGVisualSampleEntryBox *entry;
    2353             :         /*todo, add support for subpic track and nvcl tracks*/
    2354          12 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
    2355          12 :         if (!trak || !trak->Media || !DescriptionIndex) return NULL;
    2356          12 :         if (gf_isom_get_vvc_type(the_file, trackNumber, DescriptionIndex)==GF_ISOM_VVCTYPE_NONE)
    2357             :                 return NULL;
    2358           0 :         entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, DescriptionIndex-1);
    2359           0 :         if (!entry) return NULL;
    2360           0 :         if (!entry->vvc_config) return NULL;
    2361           0 :         return VVC_DuplicateConfig(entry->vvc_config->config);
    2362             : }
    2363             : 
    2364             : GF_EXPORT
    2365         492 : GF_AVCConfig *gf_isom_svc_config_get(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
    2366             : {
    2367             :         GF_TrackBox *trak;
    2368             :         GF_MPEGVisualSampleEntryBox *entry;
    2369         492 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
    2370         492 :         if (!trak || !trak->Media || !DescriptionIndex) return NULL;
    2371         492 :         if (gf_isom_get_avc_svc_type(the_file, trackNumber, DescriptionIndex)==GF_ISOM_AVCTYPE_NONE)
    2372             :                 return NULL;
    2373         484 :         entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, DescriptionIndex-1);
    2374         484 :         if (!entry) return NULL;
    2375         484 :         if (!entry->svc_config) return NULL;
    2376          19 :         return AVC_DuplicateConfig(entry->svc_config->config);
    2377             : }
    2378             : 
    2379             : 
    2380             : GF_EXPORT
    2381         465 : GF_AVCConfig *gf_isom_mvc_config_get(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
    2382             : {
    2383             :         GF_TrackBox *trak;
    2384             :         GF_MPEGVisualSampleEntryBox *entry;
    2385         465 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
    2386         465 :         if (!trak || !trak->Media || !DescriptionIndex) return NULL;
    2387         465 :         if (gf_isom_get_avc_svc_type(the_file, trackNumber, DescriptionIndex)==GF_ISOM_AVCTYPE_NONE)
    2388             :                 return NULL;
    2389         457 :         entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, DescriptionIndex-1);
    2390         457 :         if (!entry) return NULL;
    2391         457 :         if (!entry->mvc_config) return NULL;
    2392           0 :         return AVC_DuplicateConfig(entry->mvc_config->config);
    2393             : }
    2394             : 
    2395             : GF_EXPORT
    2396         136 : GF_AV1Config *gf_isom_av1_config_get(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
    2397             : {
    2398             :         GF_TrackBox *trak;
    2399             :         GF_MPEGVisualSampleEntryBox *entry;
    2400         136 :         if (gf_isom_get_reference_count(the_file, trackNumber, GF_ISOM_REF_TBAS)) {
    2401             :                 u32 ref_track;
    2402           0 :                 GF_Err e = gf_isom_get_reference(the_file, trackNumber, GF_ISOM_REF_TBAS, 1, &ref_track);
    2403           0 :                 if (e == GF_OK) {
    2404           0 :                         trackNumber = ref_track;
    2405             :                 }
    2406             :         }
    2407         136 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
    2408         136 :         if (!trak || !trak->Media || !DescriptionIndex) return NULL;
    2409         136 :         entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, DescriptionIndex - 1);
    2410         136 :         if (!entry || !entry->av1_config|| !entry->av1_config->config) return NULL;
    2411         136 :         return AV1_DuplicateConfig(entry->av1_config->config);
    2412             : }
    2413             : 
    2414             : GF_EXPORT
    2415          11 : GF_VPConfig *gf_isom_vp_config_get(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
    2416             : {
    2417             :         GF_TrackBox *trak;
    2418             :         GF_MPEGVisualSampleEntryBox *entry;
    2419          11 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
    2420          11 :         if (!trak || !trak->Media || !DescriptionIndex) return NULL;
    2421          11 :         entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, DescriptionIndex - 1);
    2422          11 :         if (!entry || !entry->vp_config) return NULL;
    2423          11 :         return VP_DuplicateConfig(entry->vp_config->config);
    2424             : }
    2425             : 
    2426             : GF_EXPORT
    2427           1 : GF_DOVIDecoderConfigurationRecord *gf_isom_dovi_config_get(GF_ISOFile* the_file, u32 trackNumber, u32 DescriptionIndex)
    2428             : {
    2429             :         GF_TrackBox* trak;
    2430             :         GF_MPEGVisualSampleEntryBox *entry;
    2431           1 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
    2432           1 :         if (!trak || !trak->Media || !DescriptionIndex) return NULL;
    2433           1 :         entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, DescriptionIndex - 1);
    2434           1 :         if (!entry || !entry->dovi_config) return NULL;
    2435           1 :         return DOVI_DuplicateConfig(&entry->dovi_config->DOVIConfig);
    2436             : }
    2437             : 
    2438             : GF_EXPORT
    2439        3255 : GF_ISOMAVCType gf_isom_get_avc_svc_type(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
    2440             : {
    2441             :         u32 type;
    2442             :         GF_TrackBox *trak;
    2443             :         GF_MPEGVisualSampleEntryBox *entry;
    2444        3255 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
    2445        3255 :         if (!trak || !trak->Media || !trak->Media->handler || !DescriptionIndex) return GF_ISOM_AVCTYPE_NONE;
    2446        2510 :         if (!gf_isom_is_video_handler_type(trak->Media->handler->handlerType))
    2447             :                 return GF_ISOM_AVCTYPE_NONE;
    2448             : 
    2449        2241 :         entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, DescriptionIndex-1);
    2450        2241 :         if (!entry) return GF_ISOM_AVCTYPE_NONE;
    2451             : 
    2452        2241 :         type = entry->type;
    2453             : 
    2454        2241 :         if (type == GF_ISOM_BOX_TYPE_ENCV) {
    2455         357 :                 GF_ProtectionSchemeInfoBox *sinf = (GF_ProtectionSchemeInfoBox *) gf_isom_box_find_child(entry->child_boxes, GF_ISOM_BOX_TYPE_SINF);
    2456         357 :                 if (sinf && sinf->original_format) type = sinf->original_format->data_format;
    2457             :         }
    2458        1884 :         else if (type == GF_ISOM_BOX_TYPE_RESV) {
    2459           0 :                 if (entry->rinf && entry->rinf->original_format) type = entry->rinf->original_format->data_format;
    2460             :         }
    2461             : 
    2462        2241 :         switch (type) {
    2463             :         case GF_ISOM_BOX_TYPE_AVC1:
    2464             :         case GF_ISOM_BOX_TYPE_AVC2:
    2465             :         case GF_ISOM_BOX_TYPE_AVC3:
    2466             :         case GF_ISOM_BOX_TYPE_AVC4:
    2467             :         case GF_ISOM_BOX_TYPE_SVC1:
    2468             :         case GF_ISOM_BOX_TYPE_MVC1:
    2469             :                 break;
    2470             :         default:
    2471             :                 return GF_ISOM_AVCTYPE_NONE;
    2472             :         }
    2473        1999 :         if (entry->avc_config && !entry->svc_config && !entry->mvc_config) return GF_ISOM_AVCTYPE_AVC_ONLY;
    2474          46 :         if (entry->avc_config && entry->svc_config) return GF_ISOM_AVCTYPE_AVC_SVC;
    2475          22 :         if (entry->avc_config && entry->mvc_config) return GF_ISOM_AVCTYPE_AVC_MVC;
    2476          22 :         if (!entry->avc_config && entry->svc_config) return GF_ISOM_AVCTYPE_SVC_ONLY;
    2477           0 :         if (!entry->avc_config && entry->mvc_config) return GF_ISOM_AVCTYPE_MVC_ONLY;
    2478           0 :         return GF_ISOM_AVCTYPE_NONE;
    2479             : }
    2480             : 
    2481             : GF_EXPORT
    2482        2176 : GF_ISOMHEVCType gf_isom_get_hevc_lhvc_type(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
    2483             : {
    2484             :         u32 type;
    2485             :         GF_TrackBox *trak;
    2486             :         GF_MPEGVisualSampleEntryBox *entry;
    2487        2176 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
    2488        2176 :         if (!trak || !trak->Media || !DescriptionIndex) return GF_ISOM_HEVCTYPE_NONE;
    2489        2176 :         if (!gf_isom_is_video_handler_type(trak->Media->handler->handlerType))
    2490             :                 return GF_ISOM_HEVCTYPE_NONE;
    2491        1520 :         entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, DescriptionIndex-1);
    2492        1520 :         if (!entry) return GF_ISOM_HEVCTYPE_NONE;
    2493        1520 :         type = entry->type;
    2494             : 
    2495        1520 :         if (type == GF_ISOM_BOX_TYPE_ENCV) {
    2496         303 :                 GF_ProtectionSchemeInfoBox *sinf = (GF_ProtectionSchemeInfoBox *) gf_isom_box_find_child(entry->child_boxes, GF_ISOM_BOX_TYPE_SINF);
    2497         303 :                 if (sinf && sinf->original_format) type = sinf->original_format->data_format;
    2498             :         }
    2499        1217 :         else if (type == GF_ISOM_BOX_TYPE_RESV) {
    2500           0 :                 if (entry->rinf && entry->rinf->original_format) type = entry->rinf->original_format->data_format;
    2501             :         }
    2502             : 
    2503        1520 :         if (type == GF_ISOM_BOX_TYPE_DVHE) {
    2504             :                 type = GF_ISOM_BOX_TYPE_HEV1;
    2505             :         }
    2506             : 
    2507        1514 :         switch (type) {
    2508             :         case GF_ISOM_BOX_TYPE_HVC1:
    2509             :         case GF_ISOM_BOX_TYPE_HEV1:
    2510             :         case GF_ISOM_BOX_TYPE_HVC2:
    2511             :         case GF_ISOM_BOX_TYPE_HEV2:
    2512             :         case GF_ISOM_BOX_TYPE_LHV1:
    2513             :         case GF_ISOM_BOX_TYPE_LHE1:
    2514             :         case GF_ISOM_BOX_TYPE_HVT1:
    2515             :                 break;
    2516             :         default:
    2517             :                 return GF_ISOM_HEVCTYPE_NONE;
    2518             :         }
    2519         654 :         if (entry->hevc_config && !entry->lhvc_config) return GF_ISOM_HEVCTYPE_HEVC_ONLY;
    2520         133 :         if (entry->hevc_config && entry->lhvc_config) return GF_ISOM_HEVCTYPE_HEVC_LHVC;
    2521         105 :         if (!entry->hevc_config && entry->lhvc_config) return GF_ISOM_HEVCTYPE_LHVC_ONLY;
    2522         105 :         return GF_ISOM_HEVCTYPE_NONE;
    2523             : }
    2524             : 
    2525             : GF_EXPORT
    2526         118 : GF_HEVCConfig *gf_isom_lhvc_config_get(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
    2527             : {
    2528             :         GF_HEVCConfig *lhvc;
    2529         118 :         GF_OperatingPointsInformation *oinf=NULL;
    2530             :         GF_TrackBox *trak;
    2531             :         GF_MPEGVisualSampleEntryBox *entry;
    2532         118 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
    2533         118 :         if (!trak || !trak->Media || !DescriptionIndex) return NULL;
    2534         118 :         if (gf_isom_get_hevc_lhvc_type(the_file, trackNumber, DescriptionIndex)==GF_ISOM_HEVCTYPE_NONE)
    2535             :                 return NULL;
    2536         107 :         entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, DescriptionIndex-1);
    2537         107 :         if (!entry) return NULL;
    2538         107 :         if (!entry->lhvc_config) return NULL;
    2539           8 :         lhvc = HEVC_DuplicateConfig(entry->lhvc_config->config);
    2540           8 :         if (!lhvc) return NULL;
    2541             : 
    2542           8 :         gf_isom_get_oinf_info(the_file, trackNumber, &oinf);
    2543           8 :         if (oinf) {
    2544           7 :                 LHEVC_ProfileTierLevel *ptl = (LHEVC_ProfileTierLevel *)gf_list_last(oinf->profile_tier_levels);
    2545           7 :                 if (ptl) {
    2546           7 :                         lhvc->profile_space  = ptl->general_profile_space;
    2547           7 :                         lhvc->tier_flag = ptl->general_tier_flag;
    2548           7 :                         lhvc->profile_idc = ptl->general_profile_idc;
    2549           7 :                         lhvc->general_profile_compatibility_flags = ptl->general_profile_compatibility_flags;
    2550           7 :                         lhvc->constraint_indicator_flags = ptl->general_constraint_indicator_flags;
    2551             :                 }
    2552             :         }
    2553             :         return lhvc;
    2554             : }
    2555             : 
    2556             : 
    2557        2971 : void btrt_box_del(GF_Box *s)
    2558             : {
    2559             :         GF_BitRateBox *ptr = (GF_BitRateBox *)s;
    2560        2971 :         if (ptr) gf_free(ptr);
    2561        2971 : }
    2562        2147 : GF_Err btrt_box_read(GF_Box *s, GF_BitStream *bs)
    2563             : {
    2564             :         GF_BitRateBox *ptr = (GF_BitRateBox *)s;
    2565        2147 :         ISOM_DECREASE_SIZE(ptr, 12)
    2566        2147 :         ptr->bufferSizeDB = gf_bs_read_u32(bs);
    2567        2147 :         ptr->maxBitrate = gf_bs_read_u32(bs);
    2568        2147 :         ptr->avgBitrate = gf_bs_read_u32(bs);
    2569        2147 :         return GF_OK;
    2570             : }
    2571        2971 : GF_Box *btrt_box_new()
    2572             : {
    2573        2971 :         GF_BitRateBox *tmp = (GF_BitRateBox *) gf_malloc(sizeof(GF_BitRateBox));
    2574        2971 :         if (tmp == NULL) return NULL;
    2575             :         memset(tmp, 0, sizeof(GF_BitRateBox));
    2576        2971 :         tmp->type = GF_ISOM_BOX_TYPE_BTRT;
    2577        2971 :         return (GF_Box *)tmp;
    2578             : }
    2579             : 
    2580             : #ifndef GPAC_DISABLE_ISOM_WRITE
    2581        1835 : GF_Err btrt_box_write(GF_Box *s, GF_BitStream *bs)
    2582             : {
    2583             :         GF_Err e;
    2584             :         GF_BitRateBox *ptr = (GF_BitRateBox *) s;
    2585        1835 :         if (!s) return GF_BAD_PARAM;
    2586        1835 :         e = gf_isom_box_write_header(s, bs);
    2587        1835 :         if (e) return e;
    2588        1835 :         gf_bs_write_u32(bs, ptr->bufferSizeDB);
    2589        1835 :         gf_bs_write_u32(bs, ptr->maxBitrate);
    2590        1835 :         gf_bs_write_u32(bs, ptr->avgBitrate);
    2591        1835 :         return GF_OK;
    2592             : }
    2593        3255 : GF_Err btrt_box_size(GF_Box *s)
    2594             : {
    2595             :         GF_BitRateBox *ptr = (GF_BitRateBox *)s;
    2596        3255 :         ptr->size += 12;
    2597        3255 :         return GF_OK;
    2598             : }
    2599             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
    2600             : 
    2601             : 
    2602             : 
    2603           9 : void m4ds_box_del(GF_Box *s)
    2604             : {
    2605             :         GF_MPEG4ExtensionDescriptorsBox *ptr = (GF_MPEG4ExtensionDescriptorsBox *)s;
    2606           9 :         gf_odf_desc_list_del(ptr->descriptors);
    2607           9 :         gf_list_del(ptr->descriptors);
    2608           9 :         gf_free(ptr);
    2609           9 : }
    2610           6 : GF_Err m4ds_box_read(GF_Box *s, GF_BitStream *bs)
    2611             : {
    2612             :         GF_Err e;
    2613             :         char *enc_od;
    2614             :         GF_MPEG4ExtensionDescriptorsBox *ptr = (GF_MPEG4ExtensionDescriptorsBox *)s;
    2615           6 :         u32 od_size = (u32) ptr->size;
    2616           6 :         if (!od_size) return GF_OK;
    2617           5 :         enc_od = (char *)gf_malloc(sizeof(char) * od_size);
    2618           5 :         gf_bs_read_data(bs, enc_od, od_size);
    2619           5 :         e = gf_odf_desc_list_read((char *)enc_od, od_size, ptr->descriptors);
    2620           5 :         gf_free(enc_od);
    2621           5 :         return e;
    2622             : }
    2623           9 : GF_Box *m4ds_box_new()
    2624             : {
    2625           9 :         GF_MPEG4ExtensionDescriptorsBox *tmp = (GF_MPEG4ExtensionDescriptorsBox *) gf_malloc(sizeof(GF_MPEG4ExtensionDescriptorsBox));
    2626           9 :         if (tmp == NULL) return NULL;
    2627             :         memset(tmp, 0, sizeof(GF_MPEG4ExtensionDescriptorsBox));
    2628           9 :         tmp->type = GF_ISOM_BOX_TYPE_M4DS;
    2629           9 :         tmp->descriptors = gf_list_new();
    2630           9 :         return (GF_Box *)tmp;
    2631             : }
    2632             : 
    2633             : #ifndef GPAC_DISABLE_ISOM_WRITE
    2634           2 : GF_Err m4ds_box_write(GF_Box *s, GF_BitStream *bs)
    2635             : {
    2636             :         GF_Err e;
    2637             :         u8 *enc_ods;
    2638             :         u32 enc_od_size;
    2639             :         GF_MPEG4ExtensionDescriptorsBox *ptr = (GF_MPEG4ExtensionDescriptorsBox *) s;
    2640           2 :         if (!s) return GF_BAD_PARAM;
    2641           2 :         e = gf_isom_box_write_header(s, bs);
    2642           2 :         if (e) return e;
    2643           2 :         enc_ods = NULL;
    2644           2 :         enc_od_size = 0;
    2645           2 :         e = gf_odf_desc_list_write(ptr->descriptors, &enc_ods, &enc_od_size);
    2646           2 :         if (e) return e;
    2647           2 :         if (enc_od_size) {
    2648           1 :                 gf_bs_write_data(bs, enc_ods, enc_od_size);
    2649           1 :                 gf_free(enc_ods);
    2650             :         }
    2651             :         return GF_OK;
    2652             : }
    2653           4 : GF_Err m4ds_box_size(GF_Box *s)
    2654             : {
    2655             :         GF_Err e;
    2656           4 :         u32 descSize = 0;
    2657             :         GF_MPEG4ExtensionDescriptorsBox *ptr = (GF_MPEG4ExtensionDescriptorsBox *)s;
    2658           4 :         e = gf_odf_desc_list_size(ptr->descriptors, &descSize);
    2659           4 :         ptr->size += descSize;
    2660           4 :         return e;
    2661             : }
    2662             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
    2663             : 
    2664             : 
    2665             : 
    2666        1453 : void avcc_box_del(GF_Box *s)
    2667             : {
    2668             :         GF_AVCConfigurationBox *ptr = (GF_AVCConfigurationBox *)s;
    2669        1453 :         if (ptr->config) gf_odf_avc_cfg_del(ptr->config);
    2670        1453 :         ptr->config = NULL;
    2671        1453 :         gf_free(ptr);
    2672        1453 : }
    2673             : 
    2674        1006 : GF_Err avcc_box_read(GF_Box *s, GF_BitStream *bs)
    2675             : {
    2676             :         u32 i, count;
    2677             :         GF_AVCConfigurationBox *ptr = (GF_AVCConfigurationBox *)s;
    2678             : 
    2679        1006 :         if (ptr->config) gf_odf_avc_cfg_del(ptr->config);
    2680        1006 :         ptr->config = gf_odf_avc_cfg_new();
    2681             : 
    2682        1006 :         ISOM_DECREASE_SIZE(ptr, 7) //7 includes the 2 counts of sps and pps
    2683             : 
    2684        1006 :         ptr->config->configurationVersion = gf_bs_read_u8(bs);
    2685        1006 :         ptr->config->AVCProfileIndication = gf_bs_read_u8(bs);
    2686        1006 :         ptr->config->profile_compatibility = gf_bs_read_u8(bs);
    2687        1006 :         ptr->config->AVCLevelIndication = gf_bs_read_u8(bs);
    2688        1006 :         if (ptr->type==GF_ISOM_BOX_TYPE_AVCC) {
    2689         985 :                 gf_bs_read_int(bs, 6);
    2690             :         } else {
    2691          21 :                 ptr->config->complete_representation = gf_bs_read_int(bs, 1);
    2692          21 :                 gf_bs_read_int(bs, 5);
    2693             :         }
    2694        1006 :         ptr->config->nal_unit_size = 1 + gf_bs_read_int(bs, 2);
    2695        1006 :         gf_bs_read_int(bs, 3);
    2696        1006 :         count = gf_bs_read_int(bs, 5);
    2697             : 
    2698        2045 :         for (i=0; i<count; i++) {
    2699        1039 :                 ISOM_DECREASE_SIZE(ptr, 2)
    2700        1039 :                 GF_NALUFFParam *sl = (GF_NALUFFParam *) gf_malloc(sizeof(GF_NALUFFParam));
    2701        1039 :                 sl->size = gf_bs_read_u16(bs);
    2702        1039 :                 if (!sl->size || (gf_bs_available(bs) < sl->size) || (ptr->size < sl->size) ) {
    2703           0 :                         gf_free(sl);
    2704           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("AVCC: Not enough bits to parse. Aborting.\n"));
    2705             :                         return GF_ISOM_INVALID_FILE;
    2706             :                 }
    2707        1039 :                 sl->data = (char *)gf_malloc(sizeof(char) * sl->size);
    2708        1039 :                 gf_bs_read_data(bs, sl->data, sl->size);
    2709        1039 :                 gf_list_add(ptr->config->sequenceParameterSets, sl);
    2710        1039 :                 ptr->size -= sl->size;
    2711             :         }
    2712             : 
    2713        1006 :         count = gf_bs_read_u8(bs);
    2714        2045 :         for (i=0; i<count; i++) {
    2715        1039 :                 ISOM_DECREASE_SIZE(ptr, 2)
    2716        1039 :                 GF_NALUFFParam *sl = (GF_NALUFFParam *)gf_malloc(sizeof(GF_NALUFFParam));
    2717        1039 :                 sl->size = gf_bs_read_u16(bs);
    2718        1039 :                 if (!sl->size || (gf_bs_available(bs) < sl->size) || (ptr->size<sl->size)) {
    2719           0 :                         gf_free(sl);
    2720           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("AVCC: Not enough bits to parse. Aborting.\n"));
    2721             :                         return GF_ISOM_INVALID_FILE;
    2722             :                 }
    2723        1039 :                 sl->data = (char *)gf_malloc(sizeof(char) * sl->size);
    2724        1039 :                 gf_bs_read_data(bs, sl->data, sl->size);
    2725        1039 :                 gf_list_add(ptr->config->pictureParameterSets, sl);
    2726        1039 :                 ptr->size -= sl->size;
    2727             :         }
    2728             : 
    2729        1006 :         if (ptr->type==GF_ISOM_BOX_TYPE_AVCC) {
    2730         985 :                 if (gf_avc_is_rext_profile(ptr->config->AVCProfileIndication)) {
    2731         635 :                         if (!ptr->size) {
    2732             : #ifndef GPAC_DISABLE_AV_PARSERS
    2733             :                                 AVCState avc;
    2734             :                                 s32 idx;
    2735           1 :                                 GF_NALUFFParam *sl = (GF_NALUFFParam*)gf_list_get(ptr->config->sequenceParameterSets, 0);
    2736           1 :                                 idx = sl ? gf_avc_read_sps(sl->data+1, sl->size-1, &avc, 0, NULL) : -1;
    2737             : 
    2738           1 :                                 if (idx>=0) {
    2739           0 :                                         ptr->config->chroma_format = avc.sps[idx].chroma_format;
    2740           0 :                                         ptr->config->luma_bit_depth = 8 + avc.sps[idx].luma_bit_depth_m8;
    2741           0 :                                         ptr->config->chroma_bit_depth = 8 + avc.sps[idx].chroma_bit_depth_m8;
    2742             :                                 }
    2743             : #else
    2744             :                                 /*set default values ...*/
    2745             :                                 ptr->config->chroma_format = 1;
    2746             :                                 ptr->config->luma_bit_depth = 8;
    2747             :                                 ptr->config->chroma_bit_depth = 8;
    2748             : #endif
    2749             :                                 return GF_OK;
    2750             :                         }
    2751         634 :                         ISOM_DECREASE_SIZE(ptr, 4)
    2752         634 :                         gf_bs_read_int(bs, 6);
    2753         634 :                         ptr->config->chroma_format = gf_bs_read_int(bs, 2);
    2754         634 :                         gf_bs_read_int(bs, 5);
    2755         634 :                         ptr->config->luma_bit_depth = 8 + gf_bs_read_int(bs, 3);
    2756         634 :                         gf_bs_read_int(bs, 5);
    2757         634 :                         ptr->config->chroma_bit_depth = 8 + gf_bs_read_int(bs, 3);
    2758             : 
    2759         634 :                         count = gf_bs_read_int(bs, 8);
    2760         634 :                         if (count*2 > ptr->size) {
    2761             :                                 //ffmpeg just ignores this part while allocating bytes (filled with garbage?)
    2762           0 :                                 GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("AVCC: invalid numOfSequenceParameterSetExt value. Skipping.\n"));
    2763             :                                 return GF_OK;
    2764             :                         }
    2765         634 :                         if (count) {
    2766           0 :                                 ptr->config->sequenceParameterSetExtensions = gf_list_new();
    2767           0 :                                 for (i=0; i<count; i++) {
    2768           0 :                                         ISOM_DECREASE_SIZE(ptr, 2)
    2769           0 :                                         GF_NALUFFParam *sl = (GF_NALUFFParam *)gf_malloc(sizeof(GF_NALUFFParam));
    2770           0 :                                         sl->size = gf_bs_read_u16(bs);
    2771           0 :                                         if ((gf_bs_available(bs) < sl->size) || (ptr->size<sl->size)) {
    2772           0 :                                                 gf_free(sl);
    2773           0 :                                                 GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("AVCC: Not enough bits to parse. Aborting.\n"));
    2774             :                                                 return GF_ISOM_INVALID_FILE;
    2775             :                                         }
    2776           0 :                                         sl->data = (char *)gf_malloc(sizeof(char) * sl->size);
    2777           0 :                                         gf_bs_read_data(bs, sl->data, sl->size);
    2778           0 :                                         gf_list_add(ptr->config->sequenceParameterSetExtensions, sl);
    2779           0 :                                         ptr->size -= sl->size;
    2780             :                                 }
    2781             :                         }
    2782             :                 }
    2783             :         }
    2784             :         return GF_OK;
    2785             : }
    2786             : 
    2787        1453 : GF_Box *avcc_box_new()
    2788             : {
    2789        1453 :         GF_AVCConfigurationBox *tmp = (GF_AVCConfigurationBox *) gf_malloc(sizeof(GF_AVCConfigurationBox));
    2790        1453 :         if (tmp == NULL) return NULL;
    2791             :         memset(tmp, 0, sizeof(GF_AVCConfigurationBox));
    2792        1453 :         tmp->type = GF_ISOM_BOX_TYPE_AVCC;
    2793        1453 :         return (GF_Box *)tmp;
    2794             : }
    2795             : 
    2796             : #ifndef GPAC_DISABLE_ISOM_WRITE
    2797        1051 : GF_Err avcc_box_write(GF_Box *s, GF_BitStream *bs)
    2798             : {
    2799             :         u32 i, count;
    2800             :         GF_Err e;
    2801             :         GF_AVCConfigurationBox *ptr = (GF_AVCConfigurationBox *) s;
    2802        1051 :         if (!s) return GF_BAD_PARAM;
    2803        1051 :         if (!ptr->config) return GF_OK;
    2804        1051 :         e = gf_isom_box_write_header(s, bs);
    2805        1051 :         if (e) return e;
    2806             : 
    2807        1051 :         gf_bs_write_u8(bs, ptr->config->configurationVersion);
    2808        1051 :         gf_bs_write_u8(bs, ptr->config->AVCProfileIndication);
    2809        1051 :         gf_bs_write_u8(bs, ptr->config->profile_compatibility);
    2810        1051 :         gf_bs_write_u8(bs, ptr->config->AVCLevelIndication);
    2811        1051 :         if (ptr->type==GF_ISOM_BOX_TYPE_AVCC) {
    2812        1033 :                 gf_bs_write_int(bs, 0x3F, 6);
    2813             :         } else {
    2814          18 :                 gf_bs_write_int(bs, ptr->config->complete_representation, 1);
    2815          18 :                 gf_bs_write_int(bs, 0x1F, 5);
    2816             :         }
    2817        1051 :         gf_bs_write_int(bs, ptr->config->nal_unit_size - 1, 2);
    2818        1051 :         gf_bs_write_int(bs, 0x7, 3);
    2819        1051 :         count = gf_list_count(ptr->config->sequenceParameterSets);
    2820        1051 :         gf_bs_write_int(bs, count, 5);
    2821        2132 :         for (i=0; i<count; i++) {
    2822        1081 :                 GF_NALUFFParam *sl = (GF_NALUFFParam *) gf_list_get(ptr->config->sequenceParameterSets, i);
    2823        1081 :                 gf_bs_write_u16(bs, sl->size);
    2824        1081 :                 gf_bs_write_data(bs, sl->data, sl->size);
    2825             :         }
    2826             : 
    2827        1051 :         count = gf_list_count(ptr->config->pictureParameterSets);
    2828        1051 :         gf_bs_write_u8(bs, count);
    2829        2132 :         for (i=0; i<count; i++) {
    2830        1081 :                 GF_NALUFFParam *sl = (GF_NALUFFParam *) gf_list_get(ptr->config->pictureParameterSets, i);
    2831        1081 :                 gf_bs_write_u16(bs, sl->size);
    2832        1081 :                 gf_bs_write_data(bs, sl->data, sl->size);
    2833             :         }
    2834             : 
    2835             : 
    2836        1051 :         if (ptr->type==GF_ISOM_BOX_TYPE_AVCC) {
    2837        1033 :                 if (gf_avc_is_rext_profile(ptr->config->AVCProfileIndication)) {
    2838         627 :                         gf_bs_write_int(bs, 0xFF, 6);
    2839         627 :                         gf_bs_write_int(bs, ptr->config->chroma_format, 2);
    2840         627 :                         gf_bs_write_int(bs, 0xFF, 5);
    2841         627 :                         gf_bs_write_int(bs, ptr->config->luma_bit_depth - 8, 3);
    2842         627 :                         gf_bs_write_int(bs, 0xFF, 5);
    2843         627 :                         gf_bs_write_int(bs, ptr->config->chroma_bit_depth - 8, 3);
    2844             : 
    2845         627 :                         count = ptr->config->sequenceParameterSetExtensions ? gf_list_count(ptr->config->sequenceParameterSetExtensions) : 0;
    2846         627 :                         gf_bs_write_u8(bs, count);
    2847         627 :                         for (i=0; i<count; i++) {
    2848           0 :                                 GF_NALUFFParam *sl = (GF_NALUFFParam *) gf_list_get(ptr->config->sequenceParameterSetExtensions, i);
    2849           0 :                                 gf_bs_write_u16(bs, sl->size);
    2850           0 :                                 gf_bs_write_data(bs, sl->data, sl->size);
    2851             :                         }
    2852             :                 }
    2853             :         }
    2854             :         return GF_OK;
    2855             : }
    2856        1771 : GF_Err avcc_box_size(GF_Box *s)
    2857             : {
    2858             :         u32 i, count;
    2859             :         GF_AVCConfigurationBox *ptr = (GF_AVCConfigurationBox *)s;
    2860             : 
    2861        1771 :         if (!ptr->config) {
    2862           3 :                 ptr->size = 0;
    2863           3 :                 return GF_OK;
    2864             :         }
    2865        1768 :         ptr->size += 7;
    2866        1768 :         count = gf_list_count(ptr->config->sequenceParameterSets);
    2867        3558 :         for (i=0; i<count; i++)
    2868        1790 :                 ptr->size += 2 + ((GF_NALUFFParam *)gf_list_get(ptr->config->sequenceParameterSets, i))->size;
    2869             : 
    2870        1768 :         count = gf_list_count(ptr->config->pictureParameterSets);
    2871        3558 :         for (i=0; i<count; i++)
    2872        1790 :                 ptr->size += 2 + ((GF_NALUFFParam *)gf_list_get(ptr->config->pictureParameterSets, i))->size;
    2873             : 
    2874        1768 :         if (ptr->type==GF_ISOM_BOX_TYPE_AVCC) {
    2875        1736 :                 if (gf_avc_is_rext_profile(ptr->config->AVCProfileIndication)) {
    2876        1168 :                         ptr->size += 4;
    2877        1168 :                         count = ptr->config->sequenceParameterSetExtensions ?gf_list_count(ptr->config->sequenceParameterSetExtensions) : 0;
    2878        1168 :                         for (i=0; i<count; i++)
    2879           0 :                                 ptr->size += 2 + ((GF_NALUFFParam *)gf_list_get(ptr->config->sequenceParameterSetExtensions, i))->size;
    2880             :                 }
    2881             :         }
    2882             :         return GF_OK;
    2883             : }
    2884             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
    2885             : 
    2886             : 
    2887             : 
    2888         755 : void hvcc_box_del(GF_Box *s)
    2889             : {
    2890             :         GF_HEVCConfigurationBox *ptr = (GF_HEVCConfigurationBox*)s;
    2891         755 :         if (ptr->config) gf_odf_hevc_cfg_del(ptr->config);
    2892         755 :         gf_free(ptr);
    2893         755 : }
    2894             : 
    2895         394 : GF_Err hvcc_box_read(GF_Box *s, GF_BitStream *bs)
    2896             : {
    2897             :         u64 consumed;
    2898             :         GF_HEVCConfigurationBox *ptr = (GF_HEVCConfigurationBox *)s;
    2899             : 
    2900         394 :         if (ptr->config) gf_odf_hevc_cfg_del(ptr->config);
    2901             : 
    2902         394 :         consumed = gf_bs_get_position(bs);
    2903         394 :         ptr->config = gf_odf_hevc_cfg_read_bs(bs, (s->type == GF_ISOM_BOX_TYPE_HVCC) ? GF_FALSE : GF_TRUE);
    2904         394 :         consumed = gf_bs_get_position(bs) - consumed ;
    2905         394 :         ISOM_DECREASE_SIZE(ptr, (u32)consumed)
    2906             : 
    2907         394 :         return ptr->config ? GF_OK : GF_ISOM_INVALID_FILE;
    2908             : }
    2909             : 
    2910         755 : GF_Box *hvcc_box_new()
    2911             : {
    2912         755 :         GF_HEVCConfigurationBox *tmp = (GF_HEVCConfigurationBox *) gf_malloc(sizeof(GF_HEVCConfigurationBox));
    2913         755 :         if (tmp == NULL) return NULL;
    2914             :         memset(tmp, 0, sizeof(GF_HEVCConfigurationBox));
    2915         755 :         tmp->type = GF_ISOM_BOX_TYPE_HVCC;
    2916         755 :         return (GF_Box *)tmp;
    2917             : }
    2918             : 
    2919             : #ifndef GPAC_DISABLE_ISOM_WRITE
    2920         523 : GF_Err hvcc_box_write(GF_Box *s, GF_BitStream *bs)
    2921             : {
    2922             :         GF_Err e;
    2923             :         GF_HEVCConfigurationBox *ptr = (GF_HEVCConfigurationBox *) s;
    2924         523 :         if (!s) return GF_BAD_PARAM;
    2925         523 :         if (!ptr->config) return GF_OK;
    2926         523 :         e = gf_isom_box_write_header(s, bs);
    2927         523 :         if (e) return e;
    2928             : 
    2929         523 :         return gf_odf_hevc_cfg_write_bs(ptr->config, bs);
    2930             : }
    2931             : 
    2932         976 : GF_Err hvcc_box_size(GF_Box *s)
    2933             : {
    2934             :         u32 i, count, j, subcount;
    2935             :         GF_HEVCConfigurationBox *ptr = (GF_HEVCConfigurationBox *)s;
    2936             : 
    2937         976 :         if (!ptr->config) {
    2938         191 :                 ptr->size = 0;
    2939         191 :                 return GF_OK;
    2940             :         }
    2941             : 
    2942         785 :         if (!ptr->config->is_lhvc)
    2943         756 :                 ptr->size += 23;
    2944             :         else
    2945          29 :                 ptr->size += 6;
    2946             : 
    2947         785 :         count = gf_list_count(ptr->config->param_array);
    2948        3033 :         for (i=0; i<count; i++) {
    2949        2248 :                 GF_NALUFFParamArray *ar = (GF_NALUFFParamArray*)gf_list_get(ptr->config->param_array, i);
    2950        2248 :                 ptr->size += 3;
    2951        2248 :                 subcount = gf_list_count(ar->nalus);
    2952        4496 :                 for (j=0; j<subcount; j++) {
    2953        2248 :                         ptr->size += 2 + ((GF_NALUFFParam *)gf_list_get(ar->nalus, j))->size;
    2954             :                 }
    2955             :         }
    2956             :         return GF_OK;
    2957             : }
    2958             : 
    2959             : 
    2960             : 
    2961           2 : void vvcc_box_del(GF_Box *s)
    2962             : {
    2963             :         GF_VVCConfigurationBox *ptr = (GF_VVCConfigurationBox*)s;
    2964           2 :         if (ptr->config) gf_odf_vvc_cfg_del(ptr->config);
    2965           2 :         gf_free(ptr);
    2966           2 : }
    2967             : 
    2968           0 : GF_Err vvcc_box_read(GF_Box *s, GF_BitStream *bs)
    2969             : {
    2970             :         u64 consumed;
    2971             :         GF_VVCConfigurationBox *ptr = (GF_VVCConfigurationBox *)s;
    2972             : 
    2973           0 :         if (ptr->config) gf_odf_vvc_cfg_del(ptr->config);
    2974             : 
    2975           0 :         consumed = gf_bs_get_position(bs);
    2976           0 :         ptr->config = gf_odf_vvc_cfg_read_bs(bs);
    2977           0 :         consumed = gf_bs_get_position(bs) - consumed ;
    2978           0 :         ISOM_DECREASE_SIZE(ptr, (u32)consumed)
    2979             : 
    2980           0 :         return ptr->config ? GF_OK : GF_ISOM_INVALID_FILE;
    2981             : }
    2982             : 
    2983           2 : GF_Box *vvcc_box_new()
    2984             : {
    2985           2 :         GF_VVCConfigurationBox *tmp = (GF_VVCConfigurationBox *) gf_malloc(sizeof(GF_VVCConfigurationBox));
    2986           2 :         if (tmp == NULL) return NULL;
    2987             :         memset(tmp, 0, sizeof(GF_VVCConfigurationBox));
    2988           2 :         tmp->type = GF_ISOM_BOX_TYPE_HVCC;
    2989           2 :         return (GF_Box *)tmp;
    2990             : }
    2991             : 
    2992             : #ifndef GPAC_DISABLE_ISOM_WRITE
    2993           0 : GF_Err vvcc_box_write(GF_Box *s, GF_BitStream *bs)
    2994             : {
    2995             :         GF_Err e;
    2996             :         GF_VVCConfigurationBox *ptr = (GF_VVCConfigurationBox *) s;
    2997           0 :         if (!s) return GF_BAD_PARAM;
    2998           0 :         if (!ptr->config) return GF_OK;
    2999           0 :         e = gf_isom_box_write_header(s, bs);
    3000           0 :         if (e) return e;
    3001             : 
    3002           0 :         return gf_odf_vvc_cfg_write_bs(ptr->config, bs);
    3003             : }
    3004             : 
    3005           1 : GF_Err vvcc_box_size(GF_Box *s)
    3006             : {
    3007             :         u32 i, count, j, subcount;
    3008             :         GF_VVCConfigurationBox *ptr = (GF_VVCConfigurationBox *)s;
    3009             : 
    3010           1 :         if (!ptr->config) {
    3011           1 :                 ptr->size = 0;
    3012           1 :                 return GF_OK;
    3013             :         }
    3014             : 
    3015           0 :         ptr->size += 6;
    3016           0 :         if (ptr->config->ptl_present) {
    3017           0 :                 if (!ptr->config->general_constraint_info)
    3018           0 :                         ptr->config->num_constraint_info = 0;
    3019           0 :                 if (!ptr->config->sub_profiles_idc)
    3020           0 :                         ptr->config->num_sub_profiles = 0;
    3021             : 
    3022           0 :                 ptr->size += 2 + 2 + ptr->config->num_constraint_info + 2 + ptr->config->num_sub_profiles*4;
    3023           0 :                 if (ptr->config->numTemporalLayers>1)
    3024           0 :                         ptr->size += 1;
    3025           0 :                 for (i=0; i<ptr->config->numTemporalLayers; i++) {
    3026           0 :                         if (ptr->config->ptl_sublayer_present_mask & (1<<i))
    3027           0 :                                 ptr->size+=1;
    3028             :                 }
    3029             :         }
    3030             : 
    3031           0 :         count = gf_list_count(ptr->config->param_array);
    3032           0 :         for (i=0; i<count; i++) {
    3033           0 :                 GF_NALUFFParamArray *ar = (GF_NALUFFParamArray*)gf_list_get(ptr->config->param_array, i);
    3034           0 :                 ptr->size += 3;
    3035           0 :                 subcount = gf_list_count(ar->nalus);
    3036           0 :                 for (j=0; j<subcount; j++) {
    3037           0 :                         ptr->size += 2 + ((GF_NALUFFParam *)gf_list_get(ar->nalus, j))->size;
    3038             :                 }
    3039             :         }
    3040             :         return GF_OK;
    3041             : }
    3042             : #endif
    3043             : 
    3044         560 : GF_Box *av1c_box_new() {
    3045         560 :         GF_AV1ConfigurationBox *tmp = (GF_AV1ConfigurationBox *)gf_malloc(sizeof(GF_AV1ConfigurationBox));
    3046         560 :         if (tmp == NULL) return NULL;
    3047             :         memset(tmp, 0, sizeof(GF_AV1ConfigurationBox));
    3048         560 :         tmp->type = GF_ISOM_BOX_TYPE_AV1C;
    3049         560 :         return (GF_Box *)tmp;
    3050             : }
    3051             : 
    3052         560 : void av1c_box_del(GF_Box *s) {
    3053             :         GF_AV1ConfigurationBox *ptr = (GF_AV1ConfigurationBox*)s;
    3054         560 :         if (ptr->config) gf_odf_av1_cfg_del(ptr->config);
    3055         560 :         gf_free(ptr);
    3056         560 : }
    3057             : 
    3058         352 : GF_Err av1c_box_read(GF_Box *s, GF_BitStream *bs)
    3059             : {
    3060             :         u64 pos, read;
    3061             :         GF_AV1ConfigurationBox *ptr = (GF_AV1ConfigurationBox*)s;
    3062             : 
    3063         352 :         if (ptr->config) gf_odf_av1_cfg_del(ptr->config);
    3064             : 
    3065         352 :         pos = gf_bs_get_position(bs);
    3066             : 
    3067         352 :         ptr->config = gf_odf_av1_cfg_read_bs_size(bs, (u32) ptr->size);
    3068             : 
    3069         352 :         read = gf_bs_get_position(bs) - pos;
    3070             : 
    3071         352 :         if (read < ptr->size)
    3072           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[ISOBMFF] AV1ConfigurationBox: read only "LLU" bytes (expected "LLU").\n", read, ptr->size));
    3073         352 :         if (read > ptr->size)
    3074           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[ISOBMFF] AV1ConfigurationBox overflow read "LLU" bytes, of box size "LLU".\n", read, ptr->size));
    3075             : 
    3076         352 :         return GF_OK;
    3077             : }
    3078             : 
    3079         309 : GF_Err av1c_box_write(GF_Box *s, GF_BitStream *bs) {
    3080             :         GF_Err e;
    3081             :         GF_AV1ConfigurationBox *ptr = (GF_AV1ConfigurationBox*)s;
    3082         309 :         if (!s) return GF_BAD_PARAM;
    3083         309 :         if (!ptr->config) return GF_BAD_PARAM;
    3084         309 :         e = gf_isom_box_write_header(s, bs);
    3085         309 :         if (e) return e;
    3086             : 
    3087         309 :         return gf_odf_av1_cfg_write_bs(ptr->config, bs);
    3088             : }
    3089             : 
    3090         508 : GF_Err av1c_box_size(GF_Box *s) {
    3091             :         u32 i;
    3092             :         GF_AV1ConfigurationBox *ptr = (GF_AV1ConfigurationBox *)s;
    3093             : 
    3094         508 :         if (!ptr->config) {
    3095           1 :                 ptr->size = 0;
    3096           1 :                 return GF_BAD_PARAM;
    3097             :         }
    3098             : 
    3099         507 :         ptr->size += 4;
    3100             : 
    3101        1014 :         for (i = 0; i < gf_list_count(ptr->config->obu_array); ++i) {
    3102         507 :                 GF_AV1_OBUArrayEntry *a = gf_list_get(ptr->config->obu_array, i);
    3103         507 :                 ptr->size += a->obu_length;
    3104             :         }
    3105             : 
    3106             :         return GF_OK;
    3107             : }
    3108             : 
    3109             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
    3110             : 
    3111             : 
    3112             : 
    3113             : 
    3114         207 : void vpcc_box_del(GF_Box *s)
    3115             : {
    3116             :         GF_VPConfigurationBox *ptr = (GF_VPConfigurationBox*)s;
    3117         207 :         if (ptr->config) gf_odf_vp_cfg_del(ptr->config);
    3118         207 :         ptr->config = NULL;
    3119         207 :         gf_free(ptr);
    3120         207 : }
    3121             : 
    3122         176 : GF_Err vpcc_box_read(GF_Box *s, GF_BitStream *bs)
    3123             : {
    3124             :         u64 pos;
    3125             :         GF_VPConfigurationBox *ptr = (GF_VPConfigurationBox *)s;
    3126             : 
    3127         176 :         if (ptr->config) gf_odf_vp_cfg_del(ptr->config);
    3128         176 :         ptr->config = NULL;
    3129             : 
    3130         176 :         pos = gf_bs_get_position(bs);
    3131         176 :         ptr->config = gf_odf_vp_cfg_read_bs(bs, ptr->version == 0);
    3132         176 :         pos = gf_bs_get_position(bs) - pos ;
    3133             : 
    3134         176 :         if (pos < ptr->size)
    3135           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[ISOBMFF] VPConfigurationBox: read only "LLU" bytes (expected "LLU").\n", pos, ptr->size));
    3136         176 :         if (pos > ptr->size)
    3137           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[ISOBMFF] VPConfigurationBox overflow read "LLU" bytes, of box size "LLU".\n", pos, ptr->size));
    3138             : 
    3139         176 :         return ptr->config ? GF_OK : GF_ISOM_INVALID_FILE;
    3140             : }
    3141             : 
    3142         207 : GF_Box *vpcc_box_new()
    3143             : {
    3144         207 :         GF_VPConfigurationBox *tmp = (GF_VPConfigurationBox *) gf_malloc(sizeof(GF_VPConfigurationBox));
    3145         207 :         if (tmp == NULL) return NULL;
    3146             :         memset(tmp, 0, sizeof(GF_VPConfigurationBox));
    3147         207 :         tmp->type = GF_ISOM_BOX_TYPE_VPCC;
    3148         207 :         tmp->version = 1;
    3149         207 :         return (GF_Box *)tmp;
    3150             : }
    3151             : 
    3152             : #ifndef GPAC_DISABLE_ISOM_WRITE
    3153          55 : GF_Err vpcc_box_write(GF_Box *s, GF_BitStream *bs)
    3154             : {
    3155             :         GF_Err e;
    3156             :         GF_VPConfigurationBox *ptr = (GF_VPConfigurationBox *) s;
    3157          55 :         if (!s) return GF_BAD_PARAM;
    3158          55 :         if (!ptr->config) return GF_OK;
    3159             : 
    3160          55 :         e = gf_isom_full_box_write(s, bs);
    3161          55 :         if (e) return e;
    3162             : 
    3163          55 :         return gf_odf_vp_cfg_write_bs(ptr->config, bs, ptr->version == 0);
    3164             : }
    3165             : #endif
    3166             : 
    3167          96 : GF_Err vpcc_box_size(GF_Box *s)
    3168             : {
    3169             :         GF_VPConfigurationBox *ptr = (GF_VPConfigurationBox *)s;
    3170             : 
    3171          96 :         if (!ptr->config) {
    3172           1 :                 ptr->size = 0;
    3173           1 :                 return GF_OK;
    3174             :         }
    3175             : 
    3176          95 :         if (ptr->version == 0) {
    3177           0 :                 ptr->size += 6;
    3178             :         } else {
    3179          95 :                 if (ptr->config->codec_initdata_size) {
    3180           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[ISOBMFF] VPConfigurationBox: codec_initdata_size MUST be 0, was %d\n", ptr->config->codec_initdata_size));
    3181             :                         return GF_ISOM_INVALID_FILE;
    3182             :                 }
    3183             : 
    3184          95 :                 ptr->size += 8;
    3185             :         }
    3186             : 
    3187             :         return GF_OK;
    3188             : }
    3189             : 
    3190             : 
    3191           4 : GF_Box *SmDm_box_new()
    3192             : {
    3193           8 :         ISOM_DECL_BOX_ALLOC(GF_SMPTE2086MasteringDisplayMetadataBox, GF_ISOM_BOX_TYPE_SMDM);
    3194           4 :         return (GF_Box *)tmp;
    3195             : }
    3196             : 
    3197           4 : void SmDm_box_del(GF_Box *a)
    3198             : {
    3199             :         GF_SMPTE2086MasteringDisplayMetadataBox *p = (GF_SMPTE2086MasteringDisplayMetadataBox *)a;
    3200           4 :         gf_free(p);
    3201           4 : }
    3202             : 
    3203           1 : GF_Err SmDm_box_read(GF_Box *s, GF_BitStream *bs)
    3204             : {
    3205             :         GF_SMPTE2086MasteringDisplayMetadataBox *p = (GF_SMPTE2086MasteringDisplayMetadataBox *)s;
    3206           1 :         ISOM_DECREASE_SIZE(p, 24)
    3207           1 :         p->primaryRChromaticity_x = gf_bs_read_u16(bs);
    3208           1 :         p->primaryRChromaticity_y = gf_bs_read_u16(bs);
    3209           1 :         p->primaryGChromaticity_x = gf_bs_read_u16(bs);
    3210           1 :         p->primaryGChromaticity_y = gf_bs_read_u16(bs);
    3211           1 :         p->primaryBChromaticity_x = gf_bs_read_u16(bs);
    3212           1 :         p->primaryBChromaticity_y = gf_bs_read_u16(bs);
    3213           1 :         p->whitePointChromaticity_x = gf_bs_read_u16(bs);
    3214           1 :         p->whitePointChromaticity_y = gf_bs_read_u16(bs);
    3215           1 :         p->luminanceMax = gf_bs_read_u32(bs);
    3216           1 :         p->luminanceMin = gf_bs_read_u32(bs);
    3217             : 
    3218           1 :         return GF_OK;
    3219             : }
    3220             : 
    3221             : #ifndef GPAC_DISABLE_ISOM_WRITE
    3222             : 
    3223           1 : GF_Err SmDm_box_write(GF_Box *s, GF_BitStream *bs)
    3224             : {
    3225             :         GF_Err e;
    3226             :         GF_SMPTE2086MasteringDisplayMetadataBox *p = (GF_SMPTE2086MasteringDisplayMetadataBox*)s;
    3227           1 :         e = gf_isom_full_box_write(s, bs);
    3228           1 :         if (e) return e;
    3229             : 
    3230           1 :         gf_bs_write_u16(bs, p->primaryRChromaticity_x);
    3231           1 :         gf_bs_write_u16(bs, p->primaryRChromaticity_y);
    3232           1 :         gf_bs_write_u16(bs, p->primaryGChromaticity_x);
    3233           1 :         gf_bs_write_u16(bs, p->primaryGChromaticity_y);
    3234           1 :         gf_bs_write_u16(bs, p->primaryBChromaticity_x);
    3235           1 :         gf_bs_write_u16(bs, p->primaryBChromaticity_y);
    3236           1 :         gf_bs_write_u16(bs, p->whitePointChromaticity_x);
    3237           1 :         gf_bs_write_u16(bs, p->whitePointChromaticity_y);
    3238           1 :         gf_bs_write_u32(bs, p->luminanceMax);
    3239           1 :         gf_bs_write_u32(bs, p->luminanceMin);
    3240             : 
    3241           1 :         return GF_OK;
    3242             : }
    3243             : 
    3244           1 : GF_Err SmDm_box_size(GF_Box *s)
    3245             : {
    3246             :         GF_SMPTE2086MasteringDisplayMetadataBox *p = (GF_SMPTE2086MasteringDisplayMetadataBox*)s;
    3247           1 :         p->size += 24;
    3248           1 :         return GF_OK;
    3249             : }
    3250             : 
    3251             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
    3252             : 
    3253             : 
    3254           4 : GF_Box *CoLL_box_new()
    3255             : {
    3256           8 :         ISOM_DECL_BOX_ALLOC(GF_VPContentLightLevelBox, GF_ISOM_BOX_TYPE_COLL);
    3257           4 :         return (GF_Box *)tmp;
    3258             : }
    3259             : 
    3260           4 : void CoLL_box_del(GF_Box *a)
    3261             : {
    3262             :         GF_VPContentLightLevelBox *p = (GF_VPContentLightLevelBox *)a;
    3263           4 :         gf_free(p);
    3264           4 : }
    3265             : 
    3266           1 : GF_Err CoLL_box_read(GF_Box *s, GF_BitStream *bs)
    3267             : {
    3268             :         GF_VPContentLightLevelBox *p = (GF_VPContentLightLevelBox *)s;
    3269           1 :         ISOM_DECREASE_SIZE(p, 4)
    3270           1 :         p->maxCLL = gf_bs_read_u16(bs);
    3271           1 :         p->maxFALL = gf_bs_read_u16(bs);
    3272             : 
    3273           1 :         return GF_OK;
    3274             : }
    3275             : 
    3276             : #ifndef GPAC_DISABLE_ISOM_WRITE
    3277             : 
    3278           1 : GF_Err CoLL_box_write(GF_Box *s, GF_BitStream *bs)
    3279             : {
    3280             :         GF_Err e;
    3281             :         GF_VPContentLightLevelBox *p = (GF_VPContentLightLevelBox*)s;
    3282           1 :         e = gf_isom_full_box_write(s, bs);
    3283           1 :         if (e) return e;
    3284             : 
    3285           1 :         gf_bs_write_u16(bs, p->maxCLL);
    3286           1 :         gf_bs_write_u16(bs, p->maxFALL);
    3287             : 
    3288           1 :         return GF_OK;
    3289             : }
    3290             : 
    3291           1 : GF_Err CoLL_box_size(GF_Box *s)
    3292             : {
    3293             :         GF_VPContentLightLevelBox *p = (GF_VPContentLightLevelBox*)s;
    3294           1 :         p->size += 4;
    3295           1 :         return GF_OK;
    3296             : }
    3297             : 
    3298             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
    3299             : 
    3300             : 
    3301             : 
    3302          57 : GF_OperatingPointsInformation *gf_isom_oinf_new_entry()
    3303             : {
    3304             :         GF_OperatingPointsInformation* ptr;
    3305          57 :         GF_SAFEALLOC(ptr, GF_OperatingPointsInformation);
    3306          57 :         if (ptr) {
    3307          57 :                 ptr->profile_tier_levels = gf_list_new();
    3308          57 :                 ptr->operating_points = gf_list_new();
    3309          57 :                 ptr->dependency_layers = gf_list_new();
    3310             :         }
    3311          57 :         return ptr;
    3312             : 
    3313             : }
    3314             : 
    3315          57 : void gf_isom_oinf_del_entry(void *entry)
    3316             : {
    3317             :         GF_OperatingPointsInformation* ptr = (GF_OperatingPointsInformation *)entry;
    3318          57 :         if (!ptr) return;
    3319          57 :         if (ptr->profile_tier_levels) {
    3320         219 :                 while (gf_list_count(ptr->profile_tier_levels)) {
    3321         162 :                         LHEVC_ProfileTierLevel *ptl = (LHEVC_ProfileTierLevel *)gf_list_get(ptr->profile_tier_levels, 0);
    3322         162 :                         gf_free(ptl);
    3323         162 :                         gf_list_rem(ptr->profile_tier_levels, 0);
    3324             :                 }
    3325          57 :                 gf_list_del(ptr->profile_tier_levels);
    3326             :         }
    3327          57 :         if (ptr->operating_points) {
    3328         165 :                 while (gf_list_count(ptr->operating_points)) {
    3329         108 :                         LHEVC_OperatingPoint *op = (LHEVC_OperatingPoint *)gf_list_get(ptr->operating_points, 0);
    3330         108 :                         gf_free(op);
    3331         108 :                         gf_list_rem(ptr->operating_points, 0);
    3332             :                 }
    3333          57 :                 gf_list_del(ptr->operating_points);
    3334             :         }
    3335          57 :         if (ptr->dependency_layers) {
    3336         165 :                 while (gf_list_count(ptr->dependency_layers)) {
    3337         108 :                         LHEVC_DependentLayer *dep = (LHEVC_DependentLayer *)gf_list_get(ptr->dependency_layers, 0);
    3338         108 :                         gf_free(dep);
    3339         108 :                         gf_list_rem(ptr->dependency_layers, 0);
    3340             :                 }
    3341          57 :                 gf_list_del(ptr->dependency_layers);
    3342             :         }
    3343          57 :         gf_free(ptr);
    3344          57 :         return;
    3345             : }
    3346             : 
    3347          19 : GF_Err gf_isom_oinf_read_entry(void *entry, GF_BitStream *bs)
    3348             : {
    3349             :         GF_OperatingPointsInformation* ptr = (GF_OperatingPointsInformation *)entry;
    3350             :         u32 i, j, count;
    3351             : 
    3352          19 :         if (!ptr) return GF_BAD_PARAM;
    3353          19 :         ptr->scalability_mask = gf_bs_read_u16(bs);
    3354          19 :         gf_bs_read_int(bs, 2);//reserved
    3355          19 :         count = gf_bs_read_int(bs, 6);
    3356          73 :         for (i = 0; i < count; i++) {
    3357             :                 LHEVC_ProfileTierLevel *ptl;
    3358          54 :                 GF_SAFEALLOC(ptl, LHEVC_ProfileTierLevel);
    3359          54 :                 if (!ptl) return GF_OUT_OF_MEM;
    3360          54 :                 ptl->general_profile_space = gf_bs_read_int(bs, 2);
    3361          54 :                 ptl->general_tier_flag= gf_bs_read_int(bs, 1);
    3362          54 :                 ptl->general_profile_idc = gf_bs_read_int(bs, 5);
    3363          54 :                 ptl->general_profile_compatibility_flags = gf_bs_read_u32(bs);
    3364          54 :                 ptl->general_constraint_indicator_flags = gf_bs_read_long_int(bs, 48);
    3365          54 :                 ptl->general_level_idc = gf_bs_read_u8(bs);
    3366          54 :                 gf_list_add(ptr->profile_tier_levels, ptl);
    3367             :         }
    3368          19 :         count = gf_bs_read_u16(bs);
    3369          55 :         for (i = 0; i < count; i++) {
    3370             :                 LHEVC_OperatingPoint *op;
    3371          36 :                 GF_SAFEALLOC(op, LHEVC_OperatingPoint);
    3372          36 :                 if (!op) return GF_OUT_OF_MEM;
    3373          36 :                 op->output_layer_set_idx = gf_bs_read_u16(bs);
    3374          36 :                 op->max_temporal_id = gf_bs_read_u8(bs);
    3375          36 :                 op->layer_count = gf_bs_read_u8(bs);
    3376          36 :                 if (op->layer_count > GF_ARRAY_LENGTH(op->layers_info))
    3377             :                         return GF_NON_COMPLIANT_BITSTREAM;
    3378          54 :                 for (j = 0; j < op->layer_count; j++) {
    3379          54 :                         op->layers_info[j].ptl_idx = gf_bs_read_u8(bs);
    3380          54 :                         op->layers_info[j].layer_id = gf_bs_read_int(bs, 6);
    3381          54 :                         op->layers_info[j].is_outputlayer = gf_bs_read_int(bs, 1) ? GF_TRUE : GF_FALSE;
    3382          54 :                         op->layers_info[j].is_alternate_outputlayer = gf_bs_read_int(bs, 1) ? GF_TRUE : GF_FALSE;
    3383             :                 }
    3384          36 :                 op->minPicWidth = gf_bs_read_u16(bs);
    3385          36 :                 op->minPicHeight = gf_bs_read_u16(bs);
    3386          36 :                 op->maxPicWidth = gf_bs_read_u16(bs);
    3387          36 :                 op->maxPicHeight = gf_bs_read_u16(bs);
    3388          36 :                 op->maxChromaFormat = gf_bs_read_int(bs, 2);
    3389          36 :                 op->maxBitDepth = gf_bs_read_int(bs, 3) + 8;
    3390          36 :                 gf_bs_read_int(bs, 1);//reserved
    3391          36 :                 op->frame_rate_info_flag = gf_bs_read_int(bs, 1) ? GF_TRUE : GF_FALSE;
    3392          36 :                 op->bit_rate_info_flag = gf_bs_read_int(bs, 1) ? GF_TRUE : GF_FALSE;
    3393          36 :                 if (op->frame_rate_info_flag) {
    3394           0 :                         op->avgFrameRate = gf_bs_read_u16(bs);
    3395           0 :                         gf_bs_read_int(bs, 6); //reserved
    3396           0 :                         op->constantFrameRate = gf_bs_read_int(bs, 2);
    3397             :                 }
    3398          36 :                 if (op->bit_rate_info_flag) {
    3399           0 :                         op->maxBitRate = gf_bs_read_u32(bs);
    3400           0 :                         op->avgBitRate = gf_bs_read_u32(bs);
    3401             :                 }
    3402          36 :                 gf_list_add(ptr->operating_points, op);
    3403             :         }
    3404          19 :         count = gf_bs_read_u8(bs);
    3405          55 :         for (i = 0; i < count; i++) {
    3406             :                 LHEVC_DependentLayer *dep;
    3407          36 :                 GF_SAFEALLOC(dep, LHEVC_DependentLayer);
    3408          36 :                 if (!dep) return GF_OUT_OF_MEM;
    3409          36 :                 dep->dependent_layerID = gf_bs_read_u8(bs);
    3410          36 :                 dep->num_layers_dependent_on = gf_bs_read_u8(bs);
    3411          36 :                 if (dep->num_layers_dependent_on > GF_ARRAY_LENGTH(dep->dependent_on_layerID)) {
    3412           0 :                         gf_free(dep);
    3413           0 :                         return GF_NON_COMPLIANT_BITSTREAM;
    3414             :                 }
    3415          18 :                 for (j = 0; j < dep->num_layers_dependent_on; j++)
    3416          18 :                         dep->dependent_on_layerID[j] = gf_bs_read_u8(bs);
    3417         576 :                 for (j = 0; j < 16; j++) {
    3418         576 :                         if (ptr->scalability_mask & (1 << j))
    3419          36 :                                 dep->dimension_identifier[j] = gf_bs_read_u8(bs);
    3420             :                 }
    3421          36 :                 gf_list_add(ptr->dependency_layers, dep);
    3422             :         }
    3423             : 
    3424             :         return GF_OK;
    3425             : }
    3426             : 
    3427          53 : GF_Err gf_isom_oinf_write_entry(void *entry, GF_BitStream *bs)
    3428             : {
    3429             :         GF_OperatingPointsInformation* ptr = (GF_OperatingPointsInformation *)entry;
    3430             :         u32 i, j, count;
    3431          53 :         if (!ptr) return GF_OK;
    3432             : 
    3433          53 :         gf_bs_write_u16(bs, ptr->scalability_mask);
    3434          53 :         gf_bs_write_int(bs, 0xFF, 2);//reserved
    3435          53 :         count=gf_list_count(ptr->profile_tier_levels);
    3436          53 :         gf_bs_write_int(bs, count, 6);
    3437         209 :         for (i = 0; i < count; i++) {
    3438         156 :                 LHEVC_ProfileTierLevel *ptl = (LHEVC_ProfileTierLevel *)gf_list_get(ptr->profile_tier_levels, i);
    3439         156 :                 gf_bs_write_int(bs, ptl->general_profile_space, 2);
    3440         156 :                 gf_bs_write_int(bs, ptl->general_tier_flag, 1);
    3441         156 :                 gf_bs_write_int(bs, ptl->general_profile_idc, 5);
    3442         156 :                 gf_bs_write_u32(bs, ptl->general_profile_compatibility_flags);
    3443         156 :                 gf_bs_write_long_int(bs, ptl->general_constraint_indicator_flags, 48);
    3444         156 :                 gf_bs_write_u8(bs, ptl->general_level_idc);
    3445             :         }
    3446          53 :         count=gf_list_count(ptr->operating_points);
    3447          53 :         gf_bs_write_u16(bs, count);
    3448         157 :         for (i = 0; i < count; i++) {
    3449         104 :                 LHEVC_OperatingPoint *op = (LHEVC_OperatingPoint *)gf_list_get(ptr->operating_points, i);
    3450         104 :                 gf_bs_write_u16(bs, op->output_layer_set_idx);
    3451         104 :                 gf_bs_write_u8(bs, op->max_temporal_id);
    3452         104 :                 gf_bs_write_u8(bs, op->layer_count);
    3453         260 :                 for (j = 0; j < op->layer_count; j++) {
    3454         156 :                         gf_bs_write_u8(bs, op->layers_info[j].ptl_idx);
    3455         156 :                         gf_bs_write_int(bs, op->layers_info[j].layer_id, 6);
    3456         156 :                         op->layers_info[j].is_outputlayer ? gf_bs_write_int(bs, 0x1, 1)  : gf_bs_write_int(bs, 0x0, 1);
    3457         156 :                         op->layers_info[j].is_alternate_outputlayer ? gf_bs_write_int(bs, 0x1, 1)  : gf_bs_write_int(bs, 0x0, 1);
    3458             :                 }
    3459         104 :                 gf_bs_write_u16(bs, op->minPicWidth);
    3460         104 :                 gf_bs_write_u16(bs, op->minPicHeight);
    3461         104 :                 gf_bs_write_u16(bs, op->maxPicWidth);
    3462         104 :                 gf_bs_write_u16(bs, op->maxPicHeight);
    3463         104 :                 gf_bs_write_int(bs, op->maxChromaFormat, 2);
    3464         104 :                 gf_bs_write_int(bs, op->maxBitDepth - 8, 3);
    3465         104 :                 gf_bs_write_int(bs, 0x1, 1);//resereved
    3466         104 :                 op->frame_rate_info_flag ? gf_bs_write_int(bs, 0x1, 1)  : gf_bs_write_int(bs, 0x0, 1);
    3467         104 :                 op->bit_rate_info_flag ? gf_bs_write_int(bs, 0x1, 1)  : gf_bs_write_int(bs, 0x0, 1);
    3468         104 :                 if (op->frame_rate_info_flag) {
    3469           0 :                         gf_bs_write_u16(bs, op->avgFrameRate);
    3470           0 :                         gf_bs_write_int(bs, 0xFF, 6); //reserved
    3471           0 :                         gf_bs_write_int(bs, op->constantFrameRate, 2);
    3472             :                 }
    3473         104 :                 if (op->bit_rate_info_flag) {
    3474           0 :                         gf_bs_write_u32(bs, op->maxBitRate);
    3475           0 :                         gf_bs_write_u32(bs, op->avgBitRate);
    3476             :                 }
    3477             :         }
    3478          53 :         count=gf_list_count(ptr->dependency_layers);
    3479          53 :         gf_bs_write_u8(bs, count);
    3480         157 :         for (i = 0; i < count; i++) {
    3481         104 :                 LHEVC_DependentLayer *dep = (LHEVC_DependentLayer *)gf_list_get(ptr->dependency_layers, i);
    3482         104 :                 gf_bs_write_u8(bs, dep->dependent_layerID);
    3483         104 :                 gf_bs_write_u8(bs, dep->num_layers_dependent_on);
    3484         156 :                 for (j = 0; j < dep->num_layers_dependent_on; j++)
    3485          52 :                         gf_bs_write_u8(bs, dep->dependent_on_layerID[j]);
    3486        1664 :                 for (j = 0; j < 16; j++) {
    3487        1664 :                         if (ptr->scalability_mask & (1 << j))
    3488         104 :                                 gf_bs_write_u8(bs, dep->dimension_identifier[j]);
    3489             :                 }
    3490             :         }
    3491             : 
    3492             :         return GF_OK;
    3493             : }
    3494             : 
    3495          31 : u32 gf_isom_oinf_size_entry(void *entry)
    3496             : {
    3497             :         GF_OperatingPointsInformation* ptr = (GF_OperatingPointsInformation *)entry;
    3498             :         u32 size = 0, i ,j, count;
    3499          31 :         if (!ptr) return 0;
    3500             : 
    3501             :         size += 3; //scalability_mask + reserved + num_profile_tier_level
    3502          31 :         count=gf_list_count(ptr->profile_tier_levels);
    3503          31 :         size += count * 12; //general_profile_space + general_tier_flag + general_profile_idc + general_profile_compatibility_flags + general_constraint_indicator_flags + general_level_idc
    3504          31 :         size += 2;//num_operating_points
    3505          31 :         count=gf_list_count(ptr->operating_points);
    3506          91 :         for (i = 0; i < count; i++) {
    3507          60 :                 LHEVC_OperatingPoint *op = (LHEVC_OperatingPoint *)gf_list_get(ptr->operating_points, i);
    3508          60 :                 size += 2/*output_layer_set_idx*/ + 1/*max_temporal_id*/ + 1/*layer_count*/;
    3509          60 :                 size += op->layer_count * 2;
    3510          60 :                 size += 9;
    3511          60 :                 if (op->frame_rate_info_flag) {
    3512           0 :                         size += 3;
    3513             :                 }
    3514          60 :                 if (op->bit_rate_info_flag) {
    3515           0 :                         size += 8;
    3516             :                 }
    3517             :         }
    3518          31 :         size += 1;//max_layer_count
    3519          31 :         count=gf_list_count(ptr->dependency_layers);
    3520          91 :         for (i = 0; i < count; i++) {
    3521          60 :                 LHEVC_DependentLayer *dep = (LHEVC_DependentLayer *)gf_list_get(ptr->dependency_layers, i);
    3522          60 :                 size += 1/*dependent_layerID*/ + 1/*num_layers_dependent_on*/;
    3523          60 :                 size += dep->num_layers_dependent_on * 1;//dependent_on_layerID
    3524        1020 :                 for (j = 0; j < 16; j++) {
    3525         960 :                         if (ptr->scalability_mask & (1 << j))
    3526          60 :                                 size += 1;//dimension_identifier
    3527             :                 }
    3528             :         }
    3529             :         return size;
    3530             : }
    3531             : 
    3532             : 
    3533          26 : GF_LHVCLayerInformation *gf_isom_linf_new_entry()
    3534             : {
    3535             :         GF_LHVCLayerInformation* ptr;
    3536          26 :         GF_SAFEALLOC(ptr, GF_LHVCLayerInformation);
    3537          26 :         if (ptr) ptr->num_layers_in_track = gf_list_new();
    3538             : 
    3539          26 :         return ptr;
    3540             : 
    3541             : }
    3542             : 
    3543          26 : void gf_isom_linf_del_entry(void *entry)
    3544             : {
    3545             :         GF_LHVCLayerInformation* ptr = (GF_LHVCLayerInformation *)entry;
    3546          26 :         if (!ptr) return;
    3547          70 :         while (gf_list_count(ptr->num_layers_in_track)) {
    3548          44 :                 LHVCLayerInfoItem *li = (LHVCLayerInfoItem *)gf_list_get(ptr->num_layers_in_track, 0);
    3549          44 :                 gf_free(li);
    3550          44 :                 gf_list_rem(ptr->num_layers_in_track, 0);
    3551             :         }
    3552          26 :         gf_list_del(ptr->num_layers_in_track);
    3553          26 :         gf_free(ptr);
    3554          26 :         return;
    3555             : }
    3556             : 
    3557          26 : GF_Err gf_isom_linf_read_entry(void *entry, GF_BitStream *bs)
    3558             : {
    3559             :         GF_LHVCLayerInformation* ptr = (GF_LHVCLayerInformation *)entry;
    3560             :         u32 i, count;
    3561             : 
    3562          26 :         if (!ptr) return GF_BAD_PARAM;
    3563          26 :         gf_bs_read_int(bs, 2);
    3564          26 :         count = gf_bs_read_int(bs, 6);
    3565          70 :         for (i = 0; i < count; i++) {
    3566             :                 LHVCLayerInfoItem *li;
    3567          44 :                 GF_SAFEALLOC(li, LHVCLayerInfoItem);
    3568          44 :                 if (!li) return GF_OUT_OF_MEM;
    3569          44 :                 gf_bs_read_int(bs, 4);
    3570          44 :                 li->layer_id = gf_bs_read_int(bs, 6);
    3571          44 :                 li->min_TemporalId = gf_bs_read_int(bs, 3);
    3572          44 :                 li->max_TemporalId = gf_bs_read_int(bs, 3);
    3573          44 :                 gf_bs_read_int(bs, 1);
    3574          44 :                 li->sub_layer_presence_flags = gf_bs_read_int(bs, 7);
    3575          44 :                 gf_list_add(ptr->num_layers_in_track, li);
    3576             :         }
    3577             :         return GF_OK;
    3578             : }
    3579             : 
    3580          22 : GF_Err gf_isom_linf_write_entry(void *entry, GF_BitStream *bs)
    3581             : {
    3582             :         GF_LHVCLayerInformation* ptr = (GF_LHVCLayerInformation *)entry;
    3583             :         u32 i, count;
    3584          22 :         if (!ptr) return GF_OK;
    3585             : 
    3586          22 :         gf_bs_write_int(bs, 0, 2);
    3587          22 :         count=gf_list_count(ptr->num_layers_in_track);
    3588          22 :         gf_bs_write_int(bs, count, 6);
    3589          59 :         for (i = 0; i < count; i++) {
    3590          37 :                 LHVCLayerInfoItem *li = (LHVCLayerInfoItem *)gf_list_get(ptr->num_layers_in_track, i);
    3591          37 :                 gf_bs_write_int(bs, 0, 4);
    3592          37 :                 gf_bs_write_int(bs, li->layer_id, 6);
    3593          37 :                 gf_bs_write_int(bs, li->min_TemporalId, 3);
    3594          37 :                 gf_bs_write_int(bs, li->max_TemporalId, 3);
    3595          37 :                 gf_bs_write_int(bs, 0, 1);
    3596          37 :                 gf_bs_write_int(bs, li->sub_layer_presence_flags, 7);
    3597             :         }
    3598             :         return GF_OK;
    3599             : }
    3600             : 
    3601          40 : u32 gf_isom_linf_size_entry(void *entry)
    3602             : {
    3603             :         GF_LHVCLayerInformation* ptr = (GF_LHVCLayerInformation *)entry;
    3604             :         u32 size = 0, count;
    3605          40 :         if (!ptr) return 0;
    3606             : 
    3607             :         size += 1;
    3608          40 :         count=gf_list_count(ptr->num_layers_in_track);
    3609          40 :         size += count * 3;
    3610          40 :         return size;
    3611             : }
    3612             : 
    3613             : 
    3614             : #endif /*GPAC_DISABLE_ISOM*/

Generated by: LCOV version 1.13