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