Coverage Report

Created: 2026-06-08 06:18

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