1 /*
2 * GPAC - Multimedia Framework C SDK
3 *
4 * Authors: Jean Le Feuvre
5 * Copyright (c) Telecom ParisTech 2000-2012
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
29 #ifndef GPAC_DISABLE_AV_PARSERS
30 #include <gpac/internal/media_dev.h>
31 #endif
32
33 #ifndef GPAC_DISABLE_ISOM
34
35
gf_isom_is_nalu_based_entry(GF_MediaBox * mdia,GF_SampleEntryBox * _entry)36 Bool gf_isom_is_nalu_based_entry(GF_MediaBox *mdia, GF_SampleEntryBox *_entry)
37 {
38 GF_MPEGVisualSampleEntryBox *entry;
39 if (mdia->handler->handlerType != GF_ISOM_MEDIA_VISUAL) return GF_FALSE;
40 switch (_entry->type) {
41 case GF_4CC('a', 'v', 'c', '1'):
42 case GF_4CC('a', 'v', 'c', '2'):
43 case GF_4CC('a', 'v', 'c', '3'):
44 case GF_4CC('a', 'v', 'c', '4'):
45 case GF_4CC('s', 'v', 'c', '1'):
46 case GF_4CC('s', 'v', 'c', '2'):
47 case GF_4CC('m', 'v', 'c', '1'):
48 case GF_4CC('m', 'v', 'c', '2'):
49 case GF_4CC('h', 'v', 'c', '1'):
50 case GF_4CC('h', 'e', 'v', '1'):
51 case GF_4CC('h', 'v', 'c', '2'):
52 case GF_4CC('h', 'e', 'v', '2'):
53 case GF_4CC('l', 'h', 'v', '1'):
54 case GF_4CC('l', 'h', 'e', '1'):
55 case GF_4CC('m', 'h', 'v', '1'):
56 case GF_4CC('m', 'h', 'c', '1'):
57 case GF_4CC('h', 'v', 't', '1'):
58 case GF_4CC('l', 'h', 't', '1'):
59 return GF_TRUE;
60 default:
61 return GF_FALSE;
62 }
63 entry = (GF_MPEGVisualSampleEntryBox*)_entry;
64 if (!entry) return GF_FALSE;
65 if (entry->avc_config || entry->svc_config || entry->hevc_config || entry->lhvc_config) return GF_TRUE;
66 return GF_FALSE;
67 }
68
69
rewrite_nalus_list(GF_List * nalus,GF_BitStream * bs,Bool rewrite_start_codes,u32 nal_unit_size_field)70 static void rewrite_nalus_list(GF_List *nalus, GF_BitStream *bs, Bool rewrite_start_codes, u32 nal_unit_size_field)
71 {
72 u32 i, count = gf_list_count(nalus);
73 for (i = 0; i<count; i++) {
74 GF_AVCConfigSlot *sl = (GF_AVCConfigSlot*)gf_list_get(nalus, i);
75 if (rewrite_start_codes) gf_bs_write_u32(bs, 1);
76 else gf_bs_write_int(bs, sl->size, 8 * nal_unit_size_field);
77 gf_bs_write_data(bs, sl->data, sl->size);
78 }
79 }
80
81
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,GF_BitStream * src_bs,GF_BitStream * dst_bs,u32 extractor_mode)82 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, GF_BitStream *src_bs, GF_BitStream *dst_bs, u32 extractor_mode)
83 {
84 GF_Err e;
85 u32 di, ref_track_index, ref_track_num, data_offset, data_length, cur_extract_mode, ref_extract_mode, ref_nalu_size, nb_bytes_nalh;
86 GF_TrackReferenceTypeBox *dpnd;
87 GF_ISOSample *ref_samp;
88 GF_BitStream *ref_bs;
89 GF_TrackBox *ref_trak;
90 s8 sample_offset;
91 char*buffer = NULL;
92 u32 max_size = 0;
93 u32 last_byte, ref_sample_num, prev_ref_sample_num;
94
95 nb_bytes_nalh = is_hevc ? 2 : 1;
96
97 switch (extractor_mode) {
98 case 0:
99 last_byte = (u32)gf_bs_get_position(src_bs) + nal_size - (is_hevc ? 2 : 1);
100 if (!is_hevc) gf_bs_read_int(src_bs, 24); //1 byte for HEVC , 3 bytes for AVC of NALUHeader in extractor
101 while (gf_bs_get_position(src_bs) < last_byte) {
102 u32 xmode = 0;
103 //hevc extractors use constructors
104 if (is_hevc) xmode = gf_bs_read_u8(src_bs);
105 if (xmode) {
106 u8 len = gf_bs_read_u8(src_bs);
107 while (len) {
108 u8 c = gf_bs_read_u8(src_bs);
109 gf_bs_write_u8(dst_bs, c);
110 len--;
111 }
112 continue;
113 }
114
115 ref_track_index = gf_bs_read_u8(src_bs);
116 sample_offset = (s8)gf_bs_read_int(src_bs, 8);
117 data_offset = gf_bs_read_int(src_bs, nal_unit_size_field * 8);
118 data_length = gf_bs_read_int(src_bs, nal_unit_size_field * 8);
119
120 Track_FindRef(mdia->mediaTrack, GF_4CC('s', 'c', 'a', 'l'), &dpnd);
121 ref_track_num = 0;
122 if (dpnd && ref_track_index && (ref_track_index <= dpnd->trackIDCount))
123 ref_track_num = gf_isom_get_track_by_id(file, dpnd->trackIDs[ref_track_index - 1]);
124
125 if (!ref_track_num) {
126 GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("ISOBMF: Extractor target track is not present in file - skipping.\n"));
127 return GF_OK;
128 }
129
130 cur_extract_mode = gf_isom_get_nalu_extract_mode(file, ref_track_num);
131
132 //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)
133 //and this will corrupt extraction (wrong data offsets)
134 ref_extract_mode = GF_ISOM_NALU_EXTRACT_INSPECT;
135 gf_isom_set_nalu_extract_mode(file, ref_track_num, ref_extract_mode);
136
137 ref_trak = gf_isom_get_track_from_file(file, ref_track_num);
138 if (!ref_trak) return GF_ISOM_INVALID_FILE;
139
140 ref_samp = gf_isom_sample_new();
141 if (!ref_samp) return GF_IO_ERR;
142
143 e = stbl_findEntryForTime(ref_trak->Media->information->sampleTable, sampleDTS, 0, &ref_sample_num, &prev_ref_sample_num);
144 if (e) return e;
145 if (!ref_sample_num) ref_sample_num = prev_ref_sample_num;
146 if (!ref_sample_num) return GF_ISOM_INVALID_FILE;
147 if ((sample_offset<0) && (ref_sample_num >(u32) -sample_offset)) return GF_ISOM_INVALID_FILE;
148 ref_sample_num = (u32)((s32)ref_sample_num + sample_offset);
149
150 e = Media_GetSample(ref_trak->Media, ref_sample_num, &ref_samp, &di, GF_FALSE, NULL);
151 if (e) return e;
152
153 if (rewrite_start_codes) {
154 gf_bs_write_int(dst_bs, 1, 32);
155 if (is_hevc) {
156 gf_bs_write_int(dst_bs, 0, 1);
157 gf_bs_write_int(dst_bs, GF_HEVC_NALU_ACCESS_UNIT, 6);
158 gf_bs_write_int(dst_bs, 0, 9);
159 /*pic-type - by default we signal all slice types possible*/
160 gf_bs_write_int(dst_bs, 2, 3);
161 gf_bs_write_int(dst_bs, 0, 5);
162 }
163 else {
164 gf_bs_write_int(dst_bs, (ref_samp->data[0] & 0x60) | GF_AVC_NALU_ACCESS_UNIT, 8);
165 gf_bs_write_int(dst_bs, 0xF0, 8); /*7 "all supported NALUs" (=111) + rbsp trailing (10000)*/;
166 }
167 }
168 ref_bs = gf_bs_new(ref_samp->data + data_offset, ref_samp->dataLength - data_offset, GF_BITSTREAM_READ);
169 if (!data_length)
170 data_length = ref_samp->dataLength - data_offset;
171
172 if (ref_samp->dataLength - data_offset >= data_length) {
173
174 while (data_length && gf_bs_available(ref_bs)) {
175 ref_nalu_size = gf_bs_read_int(ref_bs, 8 * nal_unit_size_field);
176 assert(ref_nalu_size <= data_length);
177
178 if (ref_nalu_size > max_size) {
179 buffer = (char*)gf_realloc(buffer, sizeof(char) * ref_nalu_size);
180 max_size = ref_nalu_size;
181 }
182 gf_bs_read_data(ref_bs, buffer, ref_nalu_size);
183
184 if (rewrite_start_codes)
185 gf_bs_write_u32(dst_bs, 1);
186 else
187 gf_bs_write_int(dst_bs, ref_nalu_size, 8 * nal_unit_size_field);
188
189 gf_bs_write_data(dst_bs, buffer, ref_nalu_size);
190 data_length -= ref_nalu_size + nal_unit_size_field;
191 }
192 }
193 else {
194 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("ISOBMF: Extractor size is larger than refered sample size - skipping.\n"));
195 }
196 gf_isom_sample_del(&ref_samp);
197 ref_samp = NULL;
198 gf_bs_del(ref_bs);
199 ref_bs = NULL;
200 if (buffer) gf_free(buffer);
201 buffer = NULL;
202 gf_isom_set_nalu_extract_mode(file, ref_track_num, cur_extract_mode);
203
204 if (!is_hevc) break;
205 }
206 break;
207 case 1:
208 //skip to end of this NALU
209 gf_bs_skip_bytes(src_bs, nal_size - nb_bytes_nalh);
210 break;
211 case 2:
212 buffer = (char*)gf_malloc(sizeof(char) * (nal_size - nb_bytes_nalh));
213 gf_bs_read_data(src_bs, buffer, nal_size - nb_bytes_nalh);
214 if (rewrite_start_codes)
215 gf_bs_write_u32(dst_bs, 1);
216 else
217 gf_bs_write_int(dst_bs, nal_size, 8 * nal_unit_size_field);
218
219 gf_bs_write_u8(dst_bs, nal_hdr);
220 gf_bs_write_data(dst_bs, buffer, nal_size - nb_bytes_nalh);
221 gf_free(buffer);
222 break;
223 }
224 return GF_OK;
225 }
226
227 #ifndef GPAC_DISABLE_HEVC
228 /* returns the SAP type as defined in the 14496-12 specification */
sap_type_from_nal_type(u8 nal_type)229 static SAPType sap_type_from_nal_type(u8 nal_type) {
230 switch (nal_type) {
231 case GF_HEVC_NALU_SLICE_CRA:
232 return SAP_TYPE_3;
233 case GF_HEVC_NALU_SLICE_IDR_N_LP:
234 case GF_HEVC_NALU_SLICE_BLA_N_LP:
235 return SAP_TYPE_1;
236 case GF_HEVC_NALU_SLICE_IDR_W_DLP:
237 case GF_HEVC_NALU_SLICE_BLA_W_DLP:
238 case GF_HEVC_NALU_SLICE_BLA_W_LP:
239 return SAP_TYPE_2;
240 default:
241 return RAP_NO;
242 }
243 }
244 #endif
245
is_sample_idr(GF_ISOSample * sample,GF_MPEGVisualSampleEntryBox * entry)246 static SAPType is_sample_idr(GF_ISOSample *sample, GF_MPEGVisualSampleEntryBox *entry)
247 {
248 Bool is_hevc = GF_FALSE;
249 u32 nalu_size_field = 0;
250 GF_BitStream *bs;
251 if (entry->avc_config && entry->avc_config->config) nalu_size_field = entry->avc_config->config->nal_unit_size;
252 else if (entry->svc_config && entry->svc_config->config) nalu_size_field = entry->svc_config->config->nal_unit_size;
253 else if (entry->hevc_config && entry->hevc_config->config) {
254 nalu_size_field = entry->hevc_config->config->nal_unit_size;
255 is_hevc = GF_TRUE;
256 }
257 else if (entry->lhvc_config && entry->lhvc_config->config) {
258 nalu_size_field = entry->lhvc_config->config->nal_unit_size;
259 is_hevc = GF_TRUE;
260 }
261 if (!nalu_size_field) return RAP_NO;
262
263 bs = gf_bs_new(sample->data, sample->dataLength, GF_BITSTREAM_READ);
264 if (!bs) return RAP_NO;
265
266 while (gf_bs_available(bs)) {
267 u8 nal_type;
268 u32 size = gf_bs_read_int(bs, 8 * nalu_size_field);
269
270 if (is_hevc) {
271 #ifndef GPAC_DISABLE_HEVC
272 u16 nal_hdr = gf_bs_read_u16(bs);
273 nal_type = (nal_hdr & 0x7E00) >> 9;
274
275 switch (nal_type) {
276 case GF_HEVC_NALU_SLICE_CRA:
277 gf_bs_del(bs);
278 return SAP_TYPE_3;
279 case GF_HEVC_NALU_SLICE_IDR_N_LP:
280 case GF_HEVC_NALU_SLICE_BLA_N_LP:
281 gf_bs_del(bs);
282 return SAP_TYPE_1;
283 case GF_HEVC_NALU_SLICE_IDR_W_DLP:
284 case GF_HEVC_NALU_SLICE_BLA_W_DLP:
285 case GF_HEVC_NALU_SLICE_BLA_W_LP:
286 gf_bs_del(bs);
287 return SAP_TYPE_2;
288 case GF_HEVC_NALU_ACCESS_UNIT:
289 case GF_HEVC_NALU_FILLER_DATA:
290 case GF_HEVC_NALU_SEI_PREFIX:
291 case GF_HEVC_NALU_VID_PARAM:
292 case GF_HEVC_NALU_SEQ_PARAM:
293 case GF_HEVC_NALU_PIC_PARAM:
294 break;
295 default:
296 gf_bs_del(bs);
297 return RAP_NO;
298 }
299 gf_bs_skip_bytes(bs, size - 2);
300 #endif
301 }
302 else {
303 u8 nal_hdr = gf_bs_read_u8(bs);
304 nal_type = nal_hdr & 0x1F;
305
306 switch (nal_type) {
307 /* case GF_AVC_NALU_SEQ_PARAM:
308 case GF_AVC_NALU_PIC_PARAM:
309 case GF_AVC_NALU_SEQ_PARAM_EXT:
310 case GF_AVC_NALU_SVC_SUBSEQ_PARAM:
311 */ case GF_AVC_NALU_IDR_SLICE:
312 gf_bs_del(bs);
313 return SAP_TYPE_1;
314 case GF_AVC_NALU_ACCESS_UNIT:
315 case GF_AVC_NALU_FILLER_DATA:
316 case GF_AVC_NALU_SEI:
317 break;
318 default:
319 gf_bs_del(bs);
320 return RAP_NO;
321 }
322 gf_bs_skip_bytes(bs, size - 1);
323 }
324 }
325 gf_bs_del(bs);
326 return RAP_NO;
327 }
328
nalu_merge_ps(GF_BitStream * ps_bs,Bool rewrite_start_codes,u32 nal_unit_size_field,GF_MPEGVisualSampleEntryBox * entry,Bool is_hevc)329 static void nalu_merge_ps(GF_BitStream *ps_bs, Bool rewrite_start_codes, u32 nal_unit_size_field, GF_MPEGVisualSampleEntryBox *entry, Bool is_hevc)
330 {
331 u32 i, count;
332 if (is_hevc) {
333 if (entry->hevc_config) {
334 count = gf_list_count(entry->hevc_config->config->param_array);
335 for (i = 0; i<count; i++) {
336 GF_HEVCParamArray *ar = (GF_HEVCParamArray*)gf_list_get(entry->hevc_config->config->param_array, i);
337 rewrite_nalus_list(ar->nalus, ps_bs, rewrite_start_codes, nal_unit_size_field);
338 }
339 }
340 if (entry->lhvc_config) {
341 count = gf_list_count(entry->lhvc_config->config->param_array);
342 for (i = 0; i<count; i++) {
343 GF_HEVCParamArray *ar = (GF_HEVCParamArray*)gf_list_get(entry->lhvc_config->config->param_array, i);
344 rewrite_nalus_list(ar->nalus, ps_bs, rewrite_start_codes, nal_unit_size_field);
345 }
346 }
347 }
348 else {
349 if (entry->avc_config) {
350 rewrite_nalus_list(entry->avc_config->config->sequenceParameterSets, ps_bs, rewrite_start_codes, nal_unit_size_field);
351 rewrite_nalus_list(entry->avc_config->config->sequenceParameterSetExtensions, ps_bs, rewrite_start_codes, nal_unit_size_field);
352 rewrite_nalus_list(entry->avc_config->config->pictureParameterSets, ps_bs, rewrite_start_codes, nal_unit_size_field);
353 }
354
355 /*add svc config */
356 if (entry->svc_config) {
357 rewrite_nalus_list(entry->svc_config->config->sequenceParameterSets, ps_bs, rewrite_start_codes, nal_unit_size_field);
358 rewrite_nalus_list(entry->svc_config->config->pictureParameterSets, ps_bs, rewrite_start_codes, nal_unit_size_field);
359 }
360 }
361 }
362
363
gf_isom_nalu_sample_rewrite(GF_MediaBox * mdia,GF_ISOSample * sample,u32 sampleNumber,GF_MPEGVisualSampleEntryBox * entry)364 GF_Err gf_isom_nalu_sample_rewrite(GF_MediaBox *mdia, GF_ISOSample *sample, u32 sampleNumber, GF_MPEGVisualSampleEntryBox *entry)
365 {
366 Bool is_hevc = GF_FALSE;
367 //if only one sync given in the sample sync table, insert sps/pps/vps before cra/bla in hevc
368 // Bool check_cra_bla = (mdia->information->sampleTable->SyncSample && mdia->information->sampleTable->SyncSample->nb_entries>1) ? 0 : 1;
369 Bool check_cra_bla = GF_TRUE;
370 Bool insert_nalu_delim = GF_TRUE;
371 GF_Err e = GF_OK;
372 GF_ISOSample *ref_samp;
373 GF_BitStream *src_bs, *ref_bs, *dst_bs, *ps_bs;
374 u32 nal_size, max_size, nal_unit_size_field, extractor_mode;
375 Bool rewrite_ps, rewrite_start_codes, insert_vdrd_code;
376 s8 nal_type;
377 u32 nal_hdr, sabt_ref, i, track_num;
378 u32 temporal_id = 0;
379 char *buffer;
380 GF_ISOFile *file = mdia->mediaTrack->moov->mov;
381 GF_TrackReferenceTypeBox *scal = NULL;
382
383 src_bs = ref_bs = dst_bs = ps_bs = NULL;
384 ref_samp = NULL;
385 buffer = NULL;
386
387 Track_FindRef(mdia->mediaTrack, GF_4CC('s', 'c', 'a', 'l'), &scal);
388
389 rewrite_ps = (mdia->mediaTrack->extractor_mode & GF_ISOM_NALU_EXTRACT_INBAND_PS_FLAG) ? GF_TRUE : GF_FALSE;
390 rewrite_start_codes = (mdia->mediaTrack->extractor_mode & GF_ISOM_NALU_EXTRACT_ANNEXB_FLAG) ? GF_TRUE : GF_FALSE;
391 insert_vdrd_code = (mdia->mediaTrack->extractor_mode & GF_ISOM_NALU_EXTRACT_VDRD_FLAG) ? GF_TRUE : GF_FALSE;
392 if (!entry->svc_config && !entry->lhvc_config) insert_vdrd_code = GF_FALSE;
393 extractor_mode = mdia->mediaTrack->extractor_mode & 0x0000FFFF;
394
395 if (mdia->mediaTrack->extractor_mode & GF_ISOM_NALU_EXTRACT_TILE_ONLY) {
396 insert_nalu_delim = GF_FALSE;
397 }
398
399 track_num = 1 + gf_list_find(mdia->mediaTrack->moov->trackList, mdia->mediaTrack);
400
401 if ((extractor_mode != GF_ISOM_NALU_EXTRACT_INSPECT) && !(mdia->mediaTrack->extractor_mode & GF_ISOM_NALU_EXTRACT_TILE_ONLY)) {
402 u32 ref_track, di;
403 //aggregate all sabt samples with the same DTS
404
405 if (entry->lhvc_config && !entry->hevc_config) {
406 GF_ISOSample *base_samp;
407 if (gf_isom_get_reference_count(mdia->mediaTrack->moov->mov, track_num, GF_ISOM_REF_SCAL) <= 0) {
408 //FIXME - for now we only support two layers (base + enh) in implicit
409 if (gf_isom_get_reference_count(mdia->mediaTrack->moov->mov, track_num, GF_ISOM_REF_BASE) >= 1) {
410 gf_isom_get_reference(mdia->mediaTrack->moov->mov, track_num, GF_ISOM_REF_BASE, 1, &ref_track);
411 switch (gf_isom_get_media_subtype(mdia->mediaTrack->moov->mov, ref_track, 1)) {
412 case GF_ISOM_SUBTYPE_HVC1:
413 case GF_ISOM_SUBTYPE_HVC2:
414 case GF_ISOM_SUBTYPE_HEV1:
415 case GF_ISOM_SUBTYPE_HEV2:
416
417 base_samp = gf_isom_get_sample(mdia->mediaTrack->moov->mov, ref_track, sampleNumber + mdia->mediaTrack->sample_count_at_seg_start, &di);
418 if (base_samp && base_samp->data) {
419 sample->data = gf_realloc(sample->data, sample->dataLength + base_samp->dataLength);
420 memmove(sample->data + base_samp->dataLength, sample->data, sample->dataLength);
421 memcpy(sample->data, base_samp->data, base_samp->dataLength);
422 sample->dataLength += base_samp->dataLength;
423 }
424 if (base_samp) gf_isom_sample_del(&base_samp);
425 Track_FindRef(mdia->mediaTrack, GF_4CC('s', 'b', 'a', 's'), &scal);
426 break;
427 }
428 }
429 }
430 }
431
432 sabt_ref = gf_isom_get_reference_count(mdia->mediaTrack->moov->mov, track_num, GF_ISOM_REF_SABT);
433 if ((s32)sabt_ref >= 0) {
434 for (i = 0; i<sabt_ref; i++) {
435 GF_ISOSample *tile_samp;
436 gf_isom_get_reference(mdia->mediaTrack->moov->mov, track_num, GF_ISOM_REF_SABT, i + 1, &ref_track);
437 tile_samp = gf_isom_get_sample(mdia->mediaTrack->moov->mov, ref_track, sampleNumber + mdia->mediaTrack->sample_count_at_seg_start, &di);
438 if (tile_samp && tile_samp->data) {
439 sample->data = gf_realloc(sample->data, sample->dataLength + tile_samp->dataLength);
440 memcpy(sample->data + sample->dataLength, tile_samp->data, tile_samp->dataLength);
441 sample->dataLength += tile_samp->dataLength;
442 }
443 if (tile_samp) gf_isom_sample_del(&tile_samp);
444 }
445 }
446 }
447
448 if (gf_isom_get_reference_count(mdia->mediaTrack->moov->mov, track_num, GF_ISOM_REF_TBAS) >= 1) {
449 u32 ref_track;
450 u32 idx = gf_list_find(mdia->information->sampleTable->SampleDescription->other_boxes, entry);
451 GF_TrackBox *tbas;
452 gf_isom_get_reference(mdia->mediaTrack->moov->mov, track_num, GF_ISOM_REF_TBAS, 1, &ref_track);
453 tbas = (GF_TrackBox *)gf_list_get(mdia->mediaTrack->moov->trackList, ref_track - 1);
454 entry = gf_list_get(tbas->Media->information->sampleTable->SampleDescription->other_boxes, idx);
455 }
456
457
458 if (sample->IsRAP < SAP_TYPE_2) {
459 if (mdia->information->sampleTable->no_sync_found || (!sample->IsRAP && check_cra_bla)) {
460 sample->IsRAP = is_sample_idr(sample, entry);
461 }
462 }
463 if (!sample->IsRAP)
464 rewrite_ps = GF_FALSE;
465
466 if (extractor_mode != GF_ISOM_NALU_EXTRACT_LAYER_ONLY)
467 insert_vdrd_code = GF_FALSE;
468
469 //this is a compatible HEVC, don't insert VDRD, insert NALU delim
470 if (entry->lhvc_config && entry->hevc_config)
471 insert_vdrd_code = GF_FALSE;
472
473 if (extractor_mode == GF_ISOM_NALU_EXTRACT_INSPECT) {
474 if (!rewrite_ps && !rewrite_start_codes)
475 return GF_OK;
476 }
477
478 if (!entry) return GF_BAD_PARAM;
479 nal_unit_size_field = 0;
480 /*if svc rewrite*/
481 if (entry->svc_config && entry->svc_config->config) nal_unit_size_field = entry->svc_config->config->nal_unit_size;
482 /*if mvc rewrite*/
483
484 /*if lhvc rewrite*/
485 else if (entry->lhvc_config && entry->lhvc_config->config) {
486 is_hevc = GF_TRUE;
487 nal_unit_size_field = entry->lhvc_config->config->nal_unit_size;
488 }
489
490 /*otherwise do nothing*/
491 else if (!rewrite_ps && !rewrite_start_codes && !scal) {
492 return GF_OK;
493 }
494
495 if (!nal_unit_size_field) {
496 if (entry->avc_config) nal_unit_size_field = entry->avc_config->config->nal_unit_size;
497 else if (entry->hevc_config || entry->lhvc_config) {
498 nal_unit_size_field = entry->lhvc_config ? entry->lhvc_config->config->nal_unit_size : entry->hevc_config->config->nal_unit_size;
499 is_hevc = GF_TRUE;
500 }
501 }
502
503 if (!nal_unit_size_field) return GF_ISOM_INVALID_FILE;
504
505 dst_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
506 ps_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
507 src_bs = gf_bs_new(sample->data, sample->dataLength, GF_BITSTREAM_READ);
508 if (!src_bs && sample->data) return GF_ISOM_INVALID_FILE;
509 max_size = 4096;
510
511 /*rewrite start code with NALU delim*/
512 if (rewrite_start_codes) {
513
514 //we are SVC, don't write NALU delim, only insert VDRD NALU
515 if (insert_vdrd_code) {
516 if (is_hevc) {
517 //spec is not clear here, we insert a NALU AU delimiter before the layer starts
518 }
519 else {
520 gf_bs_write_int(dst_bs, 1, 32);
521 gf_bs_write_int(dst_bs, GF_AVC_NALU_VDRD, 8);
522 insert_nalu_delim = 0;
523 }
524 }
525
526 //AVC/HEVC base, insert NALU delim
527 if (insert_nalu_delim) {
528 gf_bs_write_int(dst_bs, 1, 32);
529 if (is_hevc) {
530 #ifndef GPAC_DISABLE_HEVC
531 gf_bs_write_int(dst_bs, 0, 1);
532 gf_bs_write_int(dst_bs, GF_HEVC_NALU_ACCESS_UNIT, 6);
533 gf_bs_write_int(dst_bs, insert_vdrd_code ? 1 : 0, 6); //we should pick the layerID of the following nalus ...
534 gf_bs_write_int(dst_bs, 1, 3); //nuh_temporal_id_plus1 - cannot be 0, we use 1 by default, and overwrite it if needed at the end
535
536 /*pic-type - by default we signal all slice types possible*/
537 gf_bs_write_int(dst_bs, 2, 3);
538 gf_bs_write_int(dst_bs, 0, 5);
539 #endif
540 }
541 else {
542 gf_bs_write_int(dst_bs, (sample->data[0] & 0x60) | GF_AVC_NALU_ACCESS_UNIT, 8);
543 gf_bs_write_int(dst_bs, 0xF0, 8); /*7 "all supported NALUs" (=111) + rbsp trailing (10000)*/;
544 }
545 }
546 }
547
548 if (rewrite_ps) {
549 //in inspect mode or single-layer mode just use the xPS from this layer
550 if (extractor_mode == GF_ISOM_NALU_EXTRACT_DEFAULT) {
551 u32 i;
552
553 if (scal) {
554 for (i = 0; i<scal->trackIDCount; i++) {
555 GF_TrackBox *a_track = GetTrackbyID(mdia->mediaTrack->moov, scal->trackIDs[i]);
556 GF_MPEGVisualSampleEntryBox *an_entry = NULL;
557 if (a_track && a_track->Media && a_track->Media->information && a_track->Media->information->sampleTable && a_track->Media->information->sampleTable->SampleDescription)
558 an_entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(a_track->Media->information->sampleTable->SampleDescription->other_boxes, 0);
559
560 if (an_entry)
561 nalu_merge_ps(ps_bs, rewrite_start_codes, nal_unit_size_field, an_entry, is_hevc);
562 }
563 }
564 }
565 nalu_merge_ps(ps_bs, rewrite_start_codes, nal_unit_size_field, entry, is_hevc);
566
567
568 if (is_hevc) {
569 /*little optimization if we are not asked to start codes: copy over the sample*/
570 if (!rewrite_start_codes && !entry->lhvc_config && !scal) {
571 if (ps_bs) {
572 u8 nal_type = (sample->data[nal_unit_size_field] & 0x7E) >> 1;
573 //temp fix - if we detect xPS in the beginning of the sample do NOT copy the ps bitstream
574 //this is not correct since we are not sure whether they are the same xPS or not, but it crashes openHEVC ...
575 switch (nal_type) {
576 #ifndef GPAC_DISABLE_HEVC
577 case GF_HEVC_NALU_VID_PARAM:
578 case GF_HEVC_NALU_SEQ_PARAM:
579 case GF_HEVC_NALU_PIC_PARAM:
580 break;
581 #endif
582 default:
583 gf_bs_transfer(dst_bs, ps_bs);
584 break;
585 }
586 gf_bs_del(ps_bs);
587 ps_bs = NULL;
588 }
589 gf_bs_write_data(dst_bs, sample->data, sample->dataLength);
590 gf_free(sample->data);
591 sample->data = NULL;
592 gf_bs_get_content(dst_bs, &sample->data, &sample->dataLength);
593 gf_bs_del(src_bs);
594 gf_bs_del(dst_bs);
595 return GF_OK;
596 }
597 }
598 }
599
600 /*little optimization if we are not asked to rewrite extractors or start codes: copy over the sample*/
601 if (!scal && !rewrite_start_codes && !rewrite_ps) {
602 if (ps_bs)
603 {
604 gf_bs_transfer(dst_bs, ps_bs);
605 gf_bs_del(ps_bs);
606 ps_bs = NULL;
607 }
608 gf_bs_write_data(dst_bs, sample->data, sample->dataLength);
609 gf_free(sample->data);
610 sample->data = NULL;
611 gf_bs_get_content(dst_bs, &sample->data, &sample->dataLength);
612 gf_bs_del(src_bs);
613 gf_bs_del(dst_bs);
614 return GF_OK;
615 }
616
617 buffer = (char *)gf_malloc(sizeof(char)*max_size);
618
619 while (gf_bs_available(src_bs)) {
620 nal_size = gf_bs_read_int(src_bs, 8 * nal_unit_size_field);
621 if (gf_bs_get_position(src_bs) + nal_size > sample->dataLength) {
622 GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("Sample %u (size %u) rewrite: corrupted NAL Unit (size %u)\n", sampleNumber, sample->dataLength, nal_size));
623 goto exit;
624 }
625 if (nal_size>max_size) {
626 buffer = (char*)gf_realloc(buffer, sizeof(char)*nal_size);
627 max_size = nal_size;
628 }
629 if (is_hevc) {
630 nal_hdr = gf_bs_read_u16(src_bs);
631 nal_type = (nal_hdr & 0x7E00) >> 9;
632 }
633 else {
634 nal_hdr = gf_bs_read_u8(src_bs);
635 nal_type = nal_hdr & 0x1F;
636 }
637
638 if (is_hevc) {
639 if (ps_bs) {
640 gf_bs_transfer(dst_bs, ps_bs);
641 gf_bs_del(ps_bs);
642 ps_bs = NULL;
643 }
644
645 #ifndef GPAC_DISABLE_HEVC
646 /*we already wrote this stuff*/
647 if (nal_type == GF_HEVC_NALU_ACCESS_UNIT) {
648 gf_bs_skip_bytes(src_bs, nal_size - 2);
649 continue;
650 }
651 switch (nal_type) {
652 //extractor
653 case 49:
654 e = process_extractor(file, mdia, sampleNumber, sample->DTS, nal_size, nal_hdr, nal_unit_size_field, GF_TRUE, rewrite_ps, rewrite_start_codes, src_bs, dst_bs, extractor_mode);
655 if (e) goto exit;
656 break;
657
658 case GF_HEVC_NALU_SLICE_TSA_N:
659 case GF_HEVC_NALU_SLICE_STSA_N:
660 case GF_HEVC_NALU_SLICE_TSA_R:
661 case GF_HEVC_NALU_SLICE_STSA_R:
662 if (temporal_id < (nal_hdr & 0x7))
663 temporal_id = (nal_hdr & 0x7);
664 /*rewrite nal*/
665 gf_bs_read_data(src_bs, buffer, nal_size - 2);
666 if (rewrite_start_codes)
667 gf_bs_write_u32(dst_bs, 1);
668 else
669 gf_bs_write_int(dst_bs, nal_size, 8 * nal_unit_size_field);
670
671 gf_bs_write_u16(dst_bs, nal_hdr);
672 gf_bs_write_data(dst_bs, buffer, nal_size - 2);
673 break;
674
675 case GF_HEVC_NALU_SLICE_BLA_W_LP:
676 case GF_HEVC_NALU_SLICE_BLA_W_DLP:
677 case GF_HEVC_NALU_SLICE_BLA_N_LP:
678 case GF_HEVC_NALU_SLICE_IDR_W_DLP:
679 case GF_HEVC_NALU_SLICE_IDR_N_LP:
680 case GF_HEVC_NALU_SLICE_CRA:
681 //insert xPS before CRA/BLA
682 if (check_cra_bla && !sample->IsRAP) {
683 if (ref_samp) gf_isom_sample_del(&ref_samp);
684 if (src_bs) gf_bs_del(src_bs);
685 if (ref_bs) gf_bs_del(ref_bs);
686 if (dst_bs) gf_bs_del(dst_bs);
687 if (buffer) gf_free(buffer);
688
689 sample->IsRAP = sap_type_from_nal_type(nal_type);
690 return gf_isom_nalu_sample_rewrite(mdia, sample, sampleNumber, entry);
691 }
692 default:
693 /*rewrite nal*/
694 gf_bs_read_data(src_bs, buffer, nal_size - 2);
695 if (rewrite_start_codes)
696 gf_bs_write_u32(dst_bs, 1);
697 else
698 gf_bs_write_int(dst_bs, nal_size, 8 * nal_unit_size_field);
699
700 gf_bs_write_u16(dst_bs, nal_hdr);
701 gf_bs_write_data(dst_bs, buffer, nal_size - 2);
702 }
703 #endif
704
705 //done with HEVC
706 continue;
707 }
708
709 switch (nal_type) {
710 case GF_AVC_NALU_ACCESS_UNIT:
711 /*we already wrote this stuff*/
712 gf_bs_skip_bytes(src_bs, nal_size - 1);
713 continue;
714 //extractor
715 case 31:
716 e = process_extractor(file, mdia, sampleNumber, sample->DTS, nal_size, nal_hdr, nal_unit_size_field, GF_FALSE, rewrite_ps, rewrite_start_codes, src_bs, dst_bs, extractor_mode);
717 if (e) goto exit;
718 break;
719 // case GF_AVC_NALU_SEI:
720 case GF_AVC_NALU_SEQ_PARAM:
721 case GF_AVC_NALU_PIC_PARAM:
722 case GF_AVC_NALU_SEQ_PARAM_EXT:
723 case GF_AVC_NALU_SVC_SUBSEQ_PARAM:
724 // we will rewrite the sps/pps if and only if there is no sps/pps in bistream
725 if (ps_bs) {
726 gf_bs_del(ps_bs);
727 ps_bs = NULL;
728 }
729 default:
730 if (ps_bs) {
731 gf_bs_transfer(dst_bs, ps_bs);
732 gf_bs_del(ps_bs);
733 ps_bs = NULL;
734 }
735 gf_bs_read_data(src_bs, buffer, nal_size - 1);
736 if (rewrite_start_codes)
737 gf_bs_write_u32(dst_bs, 1);
738 else
739 gf_bs_write_int(dst_bs, nal_size, 8 * nal_unit_size_field);
740
741 gf_bs_write_u8(dst_bs, nal_hdr);
742 gf_bs_write_data(dst_bs, buffer, nal_size - 1);
743 }
744 }
745
746 /*done*/
747 gf_free(sample->data);
748 sample->data = NULL;
749 gf_bs_get_content(dst_bs, &sample->data, &sample->dataLength);
750
751 /*rewrite temporal ID of AU Ddelim NALU (first one)*/
752 if (rewrite_start_codes && is_hevc && temporal_id) {
753 sample->data[6] = (sample->data[6] & 0xF8) | (temporal_id + 1);
754 }
755
756
757 exit:
758 if (ref_samp) gf_isom_sample_del(&ref_samp);
759 if (src_bs) gf_bs_del(src_bs);
760 if (ref_bs) gf_bs_del(ref_bs);
761 if (dst_bs) gf_bs_del(dst_bs);
762 if (buffer) gf_free(buffer);
763 return e;
764 }
765
HEVC_DuplicateConfig(GF_HEVCConfig * cfg)766 GF_HEVCConfig *HEVC_DuplicateConfig(GF_HEVCConfig *cfg)
767 {
768 char *data;
769 u32 data_size;
770 GF_HEVCConfig *new_cfg;
771 GF_BitStream *bs;
772
773 if (!cfg) return NULL;
774 bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
775 gf_odf_hevc_cfg_write_bs(cfg, bs);
776
777 gf_bs_get_content(bs, &data, &data_size);
778 gf_bs_del(bs);
779 bs = gf_bs_new(data, data_size, GF_BITSTREAM_READ);
780
781 new_cfg = gf_odf_hevc_cfg_read_bs(bs, cfg->is_lhvc);
782 new_cfg->is_lhvc = cfg->is_lhvc;
783 gf_bs_del(bs);
784 gf_free(data);
785 return new_cfg;
786 }
787
AVC_DuplicateConfig(GF_AVCConfig * cfg)788 static GF_AVCConfig *AVC_DuplicateConfig(GF_AVCConfig *cfg)
789 {
790 u32 i, count;
791 GF_AVCConfigSlot *p1, *p2;
792 GF_AVCConfig *cfg_new = gf_odf_avc_cfg_new();
793 cfg_new->AVCLevelIndication = cfg->AVCLevelIndication;
794 cfg_new->AVCProfileIndication = cfg->AVCProfileIndication;
795 cfg_new->configurationVersion = cfg->configurationVersion;
796 cfg_new->nal_unit_size = cfg->nal_unit_size;
797 cfg_new->profile_compatibility = cfg->profile_compatibility;
798 cfg_new->complete_representation = cfg->complete_representation;
799 cfg_new->chroma_bit_depth = cfg->chroma_bit_depth;
800 cfg_new->luma_bit_depth = cfg->luma_bit_depth;
801 cfg_new->chroma_format = cfg->chroma_format;
802
803 count = gf_list_count(cfg->sequenceParameterSets);
804 for (i = 0; i<count; i++) {
805 p1 = (GF_AVCConfigSlot*)gf_list_get(cfg->sequenceParameterSets, i);
806 p2 = (GF_AVCConfigSlot*)gf_malloc(sizeof(GF_AVCConfigSlot));
807 p2->size = p1->size;
808 p2->id = p1->id;
809 p2->data = (char *)gf_malloc(sizeof(char)*p1->size);
810 memcpy(p2->data, p1->data, sizeof(char)*p1->size);
811 gf_list_add(cfg_new->sequenceParameterSets, p2);
812 }
813
814 count = gf_list_count(cfg->pictureParameterSets);
815 for (i = 0; i<count; i++) {
816 p1 = (GF_AVCConfigSlot*)gf_list_get(cfg->pictureParameterSets, i);
817 p2 = (GF_AVCConfigSlot*)gf_malloc(sizeof(GF_AVCConfigSlot));
818 p2->size = p1->size;
819 p2->id = p1->id;
820 p2->data = (char*)gf_malloc(sizeof(char)*p1->size);
821 memcpy(p2->data, p1->data, sizeof(char)*p1->size);
822 gf_list_add(cfg_new->pictureParameterSets, p2);
823 }
824
825 if (cfg->sequenceParameterSetExtensions) {
826 cfg_new->sequenceParameterSetExtensions = gf_list_new();
827 count = gf_list_count(cfg->sequenceParameterSetExtensions);
828 for (i = 0; i<count; i++) {
829 p1 = (GF_AVCConfigSlot*)gf_list_get(cfg->sequenceParameterSetExtensions, i);
830 p2 = (GF_AVCConfigSlot*)gf_malloc(sizeof(GF_AVCConfigSlot));
831 p2->size = p1->size;
832 p2->id = p1->id;
833 p2->data = (char*)gf_malloc(sizeof(char)*p1->size);
834 memcpy(p2->data, p1->data, sizeof(char)*p1->size);
835 gf_list_add(cfg_new->sequenceParameterSetExtensions, p2);
836 }
837 }
838 return cfg_new;
839 }
840
merge_avc_config(GF_AVCConfig * dst_cfg,GF_AVCConfig * src_cfg)841 static void merge_avc_config(GF_AVCConfig *dst_cfg, GF_AVCConfig *src_cfg)
842 {
843 GF_AVCConfig *cfg = AVC_DuplicateConfig(src_cfg);
844 if (!cfg || !dst_cfg) return;
845
846 while (gf_list_count(cfg->sequenceParameterSets)) {
847 GF_AVCConfigSlot *p = (GF_AVCConfigSlot*)gf_list_get(cfg->sequenceParameterSets, 0);
848 gf_list_rem(cfg->sequenceParameterSets, 0);
849 gf_list_insert(dst_cfg->sequenceParameterSets, p, 0);
850 }
851 while (gf_list_count(cfg->pictureParameterSets)) {
852 GF_AVCConfigSlot *p = (GF_AVCConfigSlot*)gf_list_get(cfg->pictureParameterSets, 0);
853 gf_list_rem(cfg->pictureParameterSets, 0);
854 gf_list_insert(dst_cfg->pictureParameterSets, p, 0);
855 }
856 gf_odf_avc_cfg_del(cfg);
857 }
858
merge_hevc_config(GF_HEVCConfig * dst_cfg,GF_HEVCConfig * src_cfg,Bool force_insert)859 void merge_hevc_config(GF_HEVCConfig *dst_cfg, GF_HEVCConfig *src_cfg, Bool force_insert)
860 {
861 GF_HEVCConfig *cfg = HEVC_DuplicateConfig(src_cfg);
862 //merge all xPS
863 u32 i, j, count = cfg->param_array ? gf_list_count(cfg->param_array) : 0;
864 for (i = 0; i<count; i++) {
865 GF_HEVCParamArray *ar_h = NULL;
866 u32 count2 = dst_cfg->param_array ? gf_list_count(dst_cfg->param_array) : 0;
867 GF_HEVCParamArray *ar = (GF_HEVCParamArray*)gf_list_get(cfg->param_array, i);
868 for (j = 0; j<count2; j++) {
869 ar_h = (GF_HEVCParamArray*)gf_list_get(dst_cfg->param_array, j);
870 if (ar_h->type == ar->type) {
871 break;
872 }
873 ar_h = NULL;
874 }
875 if (!ar_h) {
876 gf_list_add(dst_cfg->param_array, ar);
877 gf_list_rem(cfg->param_array, i);
878 count--;
879 i--;
880 }
881 else {
882 while (gf_list_count(ar->nalus)) {
883 GF_AVCConfigSlot *p = (GF_AVCConfigSlot*)gf_list_get(ar->nalus, 0);
884 gf_list_rem(ar->nalus, 0);
885 if (force_insert)
886 gf_list_insert(ar_h->nalus, p, 0);
887 else
888 gf_list_add(ar_h->nalus, p);
889 }
890
891 }
892 }
893 gf_odf_hevc_cfg_del(cfg);
894
895 #define CHECK_CODE(__code) if (dst_cfg->__code < src_cfg->__code) dst_cfg->__code = src_cfg->__code;
896
897 CHECK_CODE(configurationVersion)
898 CHECK_CODE(profile_idc)
899 CHECK_CODE(profile_space)
900 CHECK_CODE(tier_flag)
901 CHECK_CODE(general_profile_compatibility_flags)
902 CHECK_CODE(progressive_source_flag)
903 CHECK_CODE(interlaced_source_flag)
904 CHECK_CODE(constraint_indicator_flags)
905 CHECK_CODE(level_idc)
906 CHECK_CODE(min_spatial_segmentation_idc)
907
908 }
909
merge_all_config(GF_AVCConfig * avc_cfg,GF_HEVCConfig * hevc_cfg,GF_MediaBox * mdia)910 void merge_all_config(GF_AVCConfig *avc_cfg, GF_HEVCConfig *hevc_cfg, GF_MediaBox *mdia)
911 {
912 u32 i;
913 GF_TrackReferenceTypeBox *scal = NULL;
914 Track_FindRef(mdia->mediaTrack, GF_4CC('s', 'c', 'a', 'l'), &scal);
915
916 if (!scal) return;
917
918 for (i = 0; i<scal->trackIDCount; i++) {
919 GF_TrackBox *a_track = GetTrackbyID(mdia->mediaTrack->moov, scal->trackIDs[i]);
920 GF_MPEGVisualSampleEntryBox *an_entry = NULL;
921 if (a_track && a_track->Media && a_track->Media->information && a_track->Media->information->sampleTable && a_track->Media->information->sampleTable->SampleDescription)
922 an_entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(a_track->Media->information->sampleTable->SampleDescription->other_boxes, 0);
923
924 if (!an_entry) continue;
925
926 if (avc_cfg && an_entry->svc_config && an_entry->svc_config->config)
927 merge_avc_config(avc_cfg, an_entry->svc_config->config);
928
929 if (avc_cfg && an_entry->avc_config && an_entry->avc_config->config)
930 merge_avc_config(avc_cfg, an_entry->avc_config->config);
931
932 if (hevc_cfg && an_entry->lhvc_config && an_entry->lhvc_config->config)
933 merge_hevc_config(hevc_cfg, an_entry->lhvc_config->config, GF_TRUE);
934
935 if (hevc_cfg && an_entry->hevc_config && an_entry->hevc_config->config)
936 merge_hevc_config(hevc_cfg, an_entry->hevc_config->config, GF_TRUE);
937 }
938
939 if (hevc_cfg) hevc_cfg->is_lhvc = GF_FALSE;
940 }
941
AVC_RewriteESDescriptorEx(GF_MPEGVisualSampleEntryBox * avc,GF_MediaBox * mdia)942 void AVC_RewriteESDescriptorEx(GF_MPEGVisualSampleEntryBox *avc, GF_MediaBox *mdia)
943 {
944 GF_AVCConfig *avcc, *svcc;
945 GF_BitRateBox *btrt = gf_isom_sample_entry_get_bitrate((GF_SampleEntryBox *)avc, GF_FALSE);
946
947 if (avc->emul_esd) gf_odf_desc_del((GF_Descriptor *)avc->emul_esd);
948 avc->emul_esd = gf_odf_desc_esd_new(2);
949 avc->emul_esd->decoderConfig->streamType = GF_STREAM_VISUAL;
950 /*AVC OTI is 0x21, AVC parameter set stream OTI (not supported in gpac) is 0x22, SVC OTI is 0x24*/
951 /*if we have only SVC stream, set objectTypeIndication to AVC OTI; else set it to AVC OTI*/
952 if (avc->svc_config && !avc->avc_config)
953 avc->emul_esd->decoderConfig->objectTypeIndication = GPAC_OTI_VIDEO_SVC;
954 else
955 avc->emul_esd->decoderConfig->objectTypeIndication = GPAC_OTI_VIDEO_AVC;
956
957 if (btrt) {
958 avc->emul_esd->decoderConfig->bufferSizeDB = btrt->bufferSizeDB;
959 avc->emul_esd->decoderConfig->avgBitrate = btrt->avgBitrate;
960 avc->emul_esd->decoderConfig->maxBitrate = btrt->maxBitrate;
961 }
962 if (avc->descr) {
963 u32 i = 0;
964 GF_Descriptor *desc, *clone;
965 i = 0;
966 while ((desc = (GF_Descriptor *)gf_list_enum(avc->descr->descriptors, &i))) {
967 clone = NULL;
968 gf_odf_desc_copy(desc, &clone);
969 if (gf_odf_desc_add_desc((GF_Descriptor *)avc->emul_esd, clone) != GF_OK)
970 gf_odf_desc_del(clone);
971 }
972 }
973 if (avc->avc_config) {
974 avcc = avc->avc_config->config ? AVC_DuplicateConfig(avc->avc_config->config) : NULL;
975 /*merge SVC config*/
976 if (avc->svc_config) {
977 merge_avc_config(avcc, avc->svc_config->config);
978 }
979 if (avcc) {
980 if (mdia) merge_all_config(avcc, NULL, mdia);
981
982 gf_odf_avc_cfg_write(avcc, &avc->emul_esd->decoderConfig->decoderSpecificInfo->data, &avc->emul_esd->decoderConfig->decoderSpecificInfo->dataLength);
983 gf_odf_avc_cfg_del(avcc);
984 }
985 }
986 else if (avc->svc_config) {
987 svcc = AVC_DuplicateConfig(avc->svc_config->config);
988
989 if (mdia) merge_all_config(svcc, NULL, mdia);
990
991 gf_odf_avc_cfg_write(svcc, &avc->emul_esd->decoderConfig->decoderSpecificInfo->data, &avc->emul_esd->decoderConfig->decoderSpecificInfo->dataLength);
992 gf_odf_avc_cfg_del(svcc);
993 }
994 }
995
AVC_RewriteESDescriptor(GF_MPEGVisualSampleEntryBox * avc)996 void AVC_RewriteESDescriptor(GF_MPEGVisualSampleEntryBox *avc)
997 {
998 AVC_RewriteESDescriptorEx(avc, NULL);
999 }
1000
HEVC_RewriteESDescriptorEx(GF_MPEGVisualSampleEntryBox * hevc,GF_MediaBox * mdia)1001 void HEVC_RewriteESDescriptorEx(GF_MPEGVisualSampleEntryBox *hevc, GF_MediaBox *mdia)
1002 {
1003 GF_BitRateBox *btrt = gf_isom_sample_entry_get_bitrate((GF_SampleEntryBox *)hevc, GF_FALSE);
1004
1005 if (hevc->emul_esd) gf_odf_desc_del((GF_Descriptor *)hevc->emul_esd);
1006 hevc->emul_esd = gf_odf_desc_esd_new(2);
1007 hevc->emul_esd->decoderConfig->streamType = GF_STREAM_VISUAL;
1008 hevc->emul_esd->decoderConfig->objectTypeIndication = GPAC_OTI_VIDEO_HEVC;
1009 if (hevc->lhvc_config && !hevc->hevc_config)
1010 hevc->emul_esd->decoderConfig->objectTypeIndication = GPAC_OTI_VIDEO_LHVC;
1011
1012 if (btrt) {
1013 hevc->emul_esd->decoderConfig->bufferSizeDB = btrt->bufferSizeDB;
1014 hevc->emul_esd->decoderConfig->avgBitrate = btrt->avgBitrate;
1015 hevc->emul_esd->decoderConfig->maxBitrate = btrt->maxBitrate;
1016 }
1017 if (hevc->descr) {
1018 u32 i = 0;
1019 GF_Descriptor *desc, *clone;
1020 i = 0;
1021 while ((desc = (GF_Descriptor *)gf_list_enum(hevc->descr->descriptors, &i))) {
1022 clone = NULL;
1023 gf_odf_desc_copy(desc, &clone);
1024 if (gf_odf_desc_add_desc((GF_Descriptor *)hevc->emul_esd, clone) != GF_OK)
1025 gf_odf_desc_del(clone);
1026 }
1027 }
1028
1029 if (hevc->hevc_config || hevc->lhvc_config) {
1030 GF_HEVCConfig *hcfg = HEVC_DuplicateConfig(hevc->hevc_config ? hevc->hevc_config->config : hevc->lhvc_config->config);
1031
1032 if (hevc->hevc_config && hevc->lhvc_config) {
1033 //merge LHVC config to HEVC conf, so we add entry rather than insert
1034 merge_hevc_config(hcfg, hevc->lhvc_config->config, GF_FALSE);
1035 }
1036
1037 if (mdia) merge_all_config(NULL, hcfg, mdia);
1038
1039 if (hcfg) {
1040 if (mdia && ((mdia->mediaTrack->extractor_mode & 0x0000FFFF) != GF_ISOM_NALU_EXTRACT_INSPECT)) {
1041 hcfg->is_lhvc = GF_FALSE;
1042 }
1043 gf_odf_hevc_cfg_write(hcfg, &hevc->emul_esd->decoderConfig->decoderSpecificInfo->data, &hevc->emul_esd->decoderConfig->decoderSpecificInfo->dataLength);
1044 gf_odf_hevc_cfg_del(hcfg);
1045 }
1046 }
1047 }
HEVC_RewriteESDescriptor(GF_MPEGVisualSampleEntryBox * hevc)1048 void HEVC_RewriteESDescriptor(GF_MPEGVisualSampleEntryBox *hevc)
1049 {
1050 HEVC_RewriteESDescriptorEx(hevc, NULL);
1051 }
1052
AVC_HEVC_UpdateESD(GF_MPEGVisualSampleEntryBox * avc,GF_ESD * esd)1053 GF_Err AVC_HEVC_UpdateESD(GF_MPEGVisualSampleEntryBox *avc, GF_ESD *esd)
1054 {
1055 GF_BitRateBox *btrt = gf_isom_sample_entry_get_bitrate((GF_SampleEntryBox *)avc, GF_TRUE);
1056
1057 if (avc->descr) gf_isom_box_del((GF_Box *)avc->descr);
1058 avc->descr = NULL;
1059 btrt->avgBitrate = esd->decoderConfig->avgBitrate;
1060 btrt->maxBitrate = esd->decoderConfig->maxBitrate;
1061 btrt->bufferSizeDB = esd->decoderConfig->bufferSizeDB;
1062
1063 if (gf_list_count(esd->IPIDataSet)
1064 || gf_list_count(esd->IPMPDescriptorPointers)
1065 || esd->langDesc
1066 || gf_list_count(esd->extensionDescriptors)
1067 || esd->ipiPtr || esd->qos || esd->RegDescriptor) {
1068
1069 avc->descr = (GF_MPEG4ExtensionDescriptorsBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_M4DS);
1070 if (esd->RegDescriptor) {
1071 gf_list_add(avc->descr->descriptors, esd->RegDescriptor);
1072 esd->RegDescriptor = NULL;
1073 }
1074 if (esd->qos) {
1075 gf_list_add(avc->descr->descriptors, esd->qos);
1076 esd->qos = NULL;
1077 }
1078 if (esd->ipiPtr) {
1079 gf_list_add(avc->descr->descriptors, esd->ipiPtr);
1080 esd->ipiPtr = NULL;
1081 }
1082
1083 while (gf_list_count(esd->IPIDataSet)) {
1084 GF_Descriptor *desc = (GF_Descriptor *)gf_list_get(esd->IPIDataSet, 0);
1085 gf_list_rem(esd->IPIDataSet, 0);
1086 gf_list_add(avc->descr->descriptors, desc);
1087 }
1088 while (gf_list_count(esd->IPMPDescriptorPointers)) {
1089 GF_Descriptor *desc = (GF_Descriptor *)gf_list_get(esd->IPMPDescriptorPointers, 0);
1090 gf_list_rem(esd->IPMPDescriptorPointers, 0);
1091 gf_list_add(avc->descr->descriptors, desc);
1092 }
1093 if (esd->langDesc) {
1094 gf_list_add(avc->descr->descriptors, esd->langDesc);
1095 esd->langDesc = NULL;
1096 }
1097 while (gf_list_count(esd->extensionDescriptors)) {
1098 GF_Descriptor *desc = (GF_Descriptor *)gf_list_get(esd->extensionDescriptors, 0);
1099 gf_list_rem(esd->extensionDescriptors, 0);
1100 gf_list_add(avc->descr->descriptors, desc);
1101 }
1102 }
1103
1104
1105 if (!avc->lhvc_config && (esd->decoderConfig->objectTypeIndication == GPAC_OTI_VIDEO_HEVC)) {
1106 if (!avc->hevc_config) avc->hevc_config = (GF_HEVCConfigurationBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_HVCC);
1107 if (esd->decoderConfig->decoderSpecificInfo && esd->decoderConfig->decoderSpecificInfo->data) {
1108 if (avc->hevc_config->config) gf_odf_hevc_cfg_del(avc->hevc_config->config);
1109 avc->hevc_config->config = gf_odf_hevc_cfg_read(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, GF_FALSE);
1110 }
1111 }
1112 else if (!avc->svc_config && (esd->decoderConfig->objectTypeIndication == GPAC_OTI_VIDEO_AVC)) {
1113 if (!avc->avc_config) avc->avc_config = (GF_AVCConfigurationBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_AVCC);
1114 if (esd->decoderConfig->decoderSpecificInfo && esd->decoderConfig->decoderSpecificInfo->data) {
1115 if (avc->avc_config->config) gf_odf_avc_cfg_del(avc->avc_config->config);
1116 avc->avc_config->config = gf_odf_avc_cfg_read(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength);
1117 }
1118 }
1119
1120 gf_odf_desc_del((GF_Descriptor *)esd);
1121 if (avc->hevc_config) {
1122 HEVC_RewriteESDescriptor(avc);
1123 }
1124 else {
1125 AVC_RewriteESDescriptor(avc);
1126 }
1127 return GF_OK;
1128 }
1129
1130
1131 #ifndef GPAC_DISABLE_ISOM_WRITE
1132 GF_EXPORT
gf_isom_avc_config_new(GF_ISOFile * the_file,u32 trackNumber,GF_AVCConfig * cfg,char * URLname,char * URNname,u32 * outDescriptionIndex)1133 GF_Err gf_isom_avc_config_new(GF_ISOFile *the_file, u32 trackNumber, GF_AVCConfig *cfg, char *URLname, char *URNname, u32 *outDescriptionIndex)
1134 {
1135 GF_TrackBox *trak;
1136 GF_Err e;
1137 u32 dataRefIndex;
1138 GF_MPEGVisualSampleEntryBox *entry;
1139
1140 e = CanAccessMovie(the_file, GF_ISOM_OPEN_WRITE);
1141 if (e) return e;
1142
1143 trak = gf_isom_get_track_from_file(the_file, trackNumber);
1144 if (!trak || !trak->Media || !cfg) return GF_BAD_PARAM;
1145
1146 //get or create the data ref
1147 e = Media_FindDataRef(trak->Media->information->dataInformation->dref, URLname, URNname, &dataRefIndex);
1148 if (e) return e;
1149 if (!dataRefIndex) {
1150 e = Media_CreateDataRef(trak->Media->information->dataInformation->dref, URLname, URNname, &dataRefIndex);
1151 if (e) return e;
1152 }
1153 if (!the_file->keep_utc)
1154 trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time();
1155
1156 //create a new entry
1157 entry = (GF_MPEGVisualSampleEntryBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_AVC1);
1158 if (!entry) return GF_OUT_OF_MEM;
1159 entry->avc_config = (GF_AVCConfigurationBox*)gf_isom_box_new(GF_ISOM_BOX_TYPE_AVCC);
1160 entry->avc_config->config = AVC_DuplicateConfig(cfg);
1161 entry->dataReferenceIndex = dataRefIndex;
1162 e = gf_list_add(trak->Media->information->sampleTable->SampleDescription->other_boxes, entry);
1163 *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->other_boxes);
1164 AVC_RewriteESDescriptor(entry);
1165 return e;
1166 }
1167
gf_isom_avc_config_update_ex(GF_ISOFile * the_file,u32 trackNumber,u32 DescriptionIndex,GF_AVCConfig * cfg,u32 op_type)1168 static GF_Err gf_isom_avc_config_update_ex(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex, GF_AVCConfig *cfg, u32 op_type)
1169 {
1170 GF_TrackBox *trak;
1171 GF_Err e;
1172 GF_MPEGVisualSampleEntryBox *entry;
1173
1174 e = CanAccessMovie(the_file, GF_ISOM_OPEN_WRITE);
1175 if (e) return e;
1176 trak = gf_isom_get_track_from_file(the_file, trackNumber);
1177 if (!trak || !trak->Media || !DescriptionIndex) return GF_BAD_PARAM;
1178 entry = (GF_MPEGVisualSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, DescriptionIndex - 1);
1179 if (!entry) return GF_BAD_PARAM;
1180 switch (entry->type) {
1181 case GF_ISOM_BOX_TYPE_AVC1:
1182 case GF_ISOM_BOX_TYPE_AVC2:
1183 case GF_ISOM_BOX_TYPE_AVC3:
1184 case GF_ISOM_BOX_TYPE_AVC4:
1185 case GF_ISOM_BOX_TYPE_SVC1:
1186 break;
1187 default:
1188 return GF_BAD_PARAM;
1189 }
1190
1191 switch (op_type) {
1192 /*AVCC replacement*/
1193 case 0:
1194 if (!cfg) return GF_BAD_PARAM;
1195 if (!entry->avc_config) entry->avc_config = (GF_AVCConfigurationBox*)gf_isom_box_new(GF_ISOM_BOX_TYPE_AVCC);
1196 if (entry->avc_config->config) gf_odf_avc_cfg_del(entry->avc_config->config);
1197 entry->avc_config->config = AVC_DuplicateConfig(cfg);
1198 entry->type = GF_ISOM_BOX_TYPE_AVC1;
1199 break;
1200 /*SVCC replacement*/
1201 case 1:
1202 if (!cfg) return GF_BAD_PARAM;
1203 if (!entry->svc_config) entry->svc_config = (GF_AVCConfigurationBox*)gf_isom_box_new(GF_ISOM_BOX_TYPE_SVCC);
1204 if (entry->svc_config->config) gf_odf_avc_cfg_del(entry->svc_config->config);
1205 entry->svc_config->config = AVC_DuplicateConfig(cfg);
1206 entry->type = GF_ISOM_BOX_TYPE_AVC1;
1207 break;
1208 /*SVCC replacement and AVC removal*/
1209 case 2:
1210 if (!cfg) return GF_BAD_PARAM;
1211 if (entry->avc_config) {
1212 gf_isom_box_del((GF_Box*)entry->avc_config);
1213 entry->avc_config = NULL;
1214 }
1215 if (!entry->svc_config) entry->svc_config = (GF_AVCConfigurationBox*)gf_isom_box_new(GF_ISOM_BOX_TYPE_SVCC);
1216 if (entry->svc_config->config) gf_odf_avc_cfg_del(entry->svc_config->config);
1217 entry->svc_config->config = AVC_DuplicateConfig(cfg);
1218 entry->type = GF_ISOM_BOX_TYPE_SVC1;
1219 break;
1220 /*AVCC removal and switch to avc3*/
1221 case 3:
1222 if (!entry->avc_config || !entry->avc_config->config)
1223 return GF_BAD_PARAM;
1224
1225 if (entry->svc_config) {
1226 gf_isom_box_del((GF_Box*)entry->svc_config);
1227 entry->svc_config = NULL;
1228 }
1229
1230 while (gf_list_count(entry->avc_config->config->sequenceParameterSets)) {
1231 GF_AVCConfigSlot *sl = (GF_AVCConfigSlot*)gf_list_get(entry->avc_config->config->sequenceParameterSets, 0);
1232 gf_list_rem(entry->avc_config->config->sequenceParameterSets, 0);
1233 if (sl->data) gf_free(sl->data);
1234 gf_free(sl);
1235 }
1236
1237 while (gf_list_count(entry->avc_config->config->pictureParameterSets)) {
1238 GF_AVCConfigSlot *sl = (GF_AVCConfigSlot*)gf_list_get(entry->avc_config->config->pictureParameterSets, 0);
1239 gf_list_rem(entry->avc_config->config->pictureParameterSets, 0);
1240 if (sl->data) gf_free(sl->data);
1241 gf_free(sl);
1242 }
1243
1244 if (entry->type == GF_ISOM_BOX_TYPE_AVC1)
1245 entry->type = GF_ISOM_BOX_TYPE_AVC3;
1246 else if (entry->type == GF_ISOM_BOX_TYPE_AVC2)
1247 entry->type = GF_ISOM_BOX_TYPE_AVC4;
1248 break;
1249 }
1250 AVC_RewriteESDescriptor(entry);
1251 return GF_OK;
1252 }
1253
1254 GF_EXPORT
gf_isom_avc_set_inband_config(GF_ISOFile * the_file,u32 trackNumber,u32 DescriptionIndex)1255 GF_Err gf_isom_avc_set_inband_config(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
1256 {
1257 return gf_isom_avc_config_update_ex(the_file, trackNumber, DescriptionIndex, NULL, 3);
1258 }
1259
1260 GF_EXPORT
gf_isom_avc_config_update(GF_ISOFile * the_file,u32 trackNumber,u32 DescriptionIndex,GF_AVCConfig * cfg)1261 GF_Err gf_isom_avc_config_update(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex, GF_AVCConfig *cfg)
1262 {
1263 return gf_isom_avc_config_update_ex(the_file, trackNumber, DescriptionIndex, cfg, 0);
1264 }
1265
gf_isom_svc_config_update(GF_ISOFile * the_file,u32 trackNumber,u32 DescriptionIndex,GF_AVCConfig * cfg,Bool is_add)1266 GF_Err gf_isom_svc_config_update(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex, GF_AVCConfig *cfg, Bool is_add)
1267 {
1268 return gf_isom_avc_config_update_ex(the_file, trackNumber, DescriptionIndex, cfg, is_add ? 1 : 2);
1269 }
1270
gf_isom_svc_config_del(GF_ISOFile * the_file,u32 trackNumber,u32 DescriptionIndex)1271 GF_Err gf_isom_svc_config_del(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
1272 {
1273 GF_TrackBox *trak;
1274 GF_Err e;
1275 GF_MPEGVisualSampleEntryBox *entry;
1276
1277 e = CanAccessMovie(the_file, GF_ISOM_OPEN_WRITE);
1278 if (e) return e;
1279 trak = gf_isom_get_track_from_file(the_file, trackNumber);
1280 if (!trak || !trak->Media || !DescriptionIndex) return GF_BAD_PARAM;
1281 entry = (GF_MPEGVisualSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, DescriptionIndex - 1);
1282 if (!entry) return GF_BAD_PARAM;
1283 switch (entry->type) {
1284 case GF_ISOM_BOX_TYPE_AVC1:
1285 case GF_ISOM_BOX_TYPE_AVC2:
1286 case GF_ISOM_BOX_TYPE_AVC3:
1287 case GF_ISOM_BOX_TYPE_AVC4:
1288 case GF_ISOM_BOX_TYPE_SVC1:
1289 break;
1290 default:
1291 return GF_BAD_PARAM;
1292 }
1293
1294 if (entry->svc_config) {
1295 gf_isom_box_del((GF_Box*)entry->svc_config);
1296 entry->svc_config = NULL;
1297 }
1298 AVC_RewriteESDescriptor(entry);
1299 return GF_OK;
1300 }
1301
1302 GF_EXPORT
gf_isom_set_ipod_compatible(GF_ISOFile * the_file,u32 trackNumber)1303 GF_Err gf_isom_set_ipod_compatible(GF_ISOFile *the_file, u32 trackNumber)
1304 {
1305 static const u8 ipod_ext[][16] = { { 0x6B, 0x68, 0x40, 0xF2, 0x5F, 0x24, 0x4F, 0xC5, 0xBA, 0x39, 0xA5, 0x1B, 0xCF, 0x03, 0x23, 0xF3 } };
1306 GF_TrackBox *trak;
1307 GF_Err e;
1308 GF_MPEGVisualSampleEntryBox *entry;
1309
1310 e = CanAccessMovie(the_file, GF_ISOM_OPEN_WRITE);
1311 if (e) return e;
1312 trak = gf_isom_get_track_from_file(the_file, trackNumber);
1313 if (!trak || !trak->Media) return GF_BAD_PARAM;
1314 entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, 0);
1315 if (!entry) return GF_OK;
1316 switch (entry->type) {
1317 case GF_ISOM_BOX_TYPE_AVC1:
1318 case GF_ISOM_BOX_TYPE_AVC2:
1319 case GF_ISOM_BOX_TYPE_AVC3:
1320 case GF_ISOM_BOX_TYPE_AVC4:
1321 case GF_ISOM_BOX_TYPE_SVC1:
1322 case GF_ISOM_BOX_TYPE_HVC1:
1323 case GF_ISOM_BOX_TYPE_HEV1:
1324 case GF_ISOM_BOX_TYPE_HVT1:
1325 break;
1326 default:
1327 return GF_OK;
1328 }
1329
1330 if (!entry->ipod_ext) entry->ipod_ext = (GF_UnknownUUIDBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_UUID);
1331 memcpy(entry->ipod_ext->uuid, ipod_ext, sizeof(u8) * 16);
1332 entry->ipod_ext->dataSize = 0;
1333 return GF_OK;
1334 }
1335
gf_isom_svc_config_new(GF_ISOFile * the_file,u32 trackNumber,GF_AVCConfig * cfg,char * URLname,char * URNname,u32 * outDescriptionIndex)1336 GF_Err gf_isom_svc_config_new(GF_ISOFile *the_file, u32 trackNumber, GF_AVCConfig *cfg, char *URLname, char *URNname, u32 *outDescriptionIndex)
1337 {
1338 GF_TrackBox *trak;
1339 GF_Err e;
1340 u32 dataRefIndex;
1341 GF_MPEGVisualSampleEntryBox *entry;
1342
1343 e = CanAccessMovie(the_file, GF_ISOM_OPEN_WRITE);
1344 if (e) return e;
1345
1346 trak = gf_isom_get_track_from_file(the_file, trackNumber);
1347 if (!trak || !trak->Media || !cfg) return GF_BAD_PARAM;
1348
1349 //get or create the data ref
1350 e = Media_FindDataRef(trak->Media->information->dataInformation->dref, URLname, URNname, &dataRefIndex);
1351 if (e) return e;
1352 if (!dataRefIndex) {
1353 e = Media_CreateDataRef(trak->Media->information->dataInformation->dref, URLname, URNname, &dataRefIndex);
1354 if (e) return e;
1355 }
1356 if (!the_file->keep_utc)
1357 trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time();
1358
1359 //create a new entry
1360 entry = (GF_MPEGVisualSampleEntryBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_SVC1);
1361 if (!entry) return GF_OUT_OF_MEM;
1362 entry->svc_config = (GF_AVCConfigurationBox*)gf_isom_box_new(GF_ISOM_BOX_TYPE_SVCC);
1363 entry->svc_config->config = AVC_DuplicateConfig(cfg);
1364 entry->dataReferenceIndex = dataRefIndex;
1365 e = gf_list_add(trak->Media->information->sampleTable->SampleDescription->other_boxes, entry);
1366 *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->other_boxes);
1367 AVC_RewriteESDescriptor(entry);
1368 return e;
1369 }
1370
1371 GF_EXPORT
gf_isom_hevc_config_new(GF_ISOFile * the_file,u32 trackNumber,GF_HEVCConfig * cfg,char * URLname,char * URNname,u32 * outDescriptionIndex)1372 GF_Err gf_isom_hevc_config_new(GF_ISOFile *the_file, u32 trackNumber, GF_HEVCConfig *cfg, char *URLname, char *URNname, u32 *outDescriptionIndex)
1373 {
1374 GF_TrackBox *trak;
1375 GF_Err e;
1376 u32 dataRefIndex;
1377 GF_MPEGVisualSampleEntryBox *entry;
1378
1379 e = CanAccessMovie(the_file, GF_ISOM_OPEN_WRITE);
1380 if (e) return e;
1381
1382 trak = gf_isom_get_track_from_file(the_file, trackNumber);
1383 if (!trak || !trak->Media || !cfg) return GF_BAD_PARAM;
1384
1385 //get or create the data ref
1386 e = Media_FindDataRef(trak->Media->information->dataInformation->dref, URLname, URNname, &dataRefIndex);
1387 if (e) return e;
1388 if (!dataRefIndex) {
1389 e = Media_CreateDataRef(trak->Media->information->dataInformation->dref, URLname, URNname, &dataRefIndex);
1390 if (e) return e;
1391 }
1392 if (!the_file->keep_utc)
1393 trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time();
1394
1395 //create a new entry
1396 entry = (GF_MPEGVisualSampleEntryBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_HVC1);
1397 if (!entry) return GF_OUT_OF_MEM;
1398 entry->hevc_config = (GF_HEVCConfigurationBox*)gf_isom_box_new(GF_ISOM_BOX_TYPE_HVCC);
1399 entry->hevc_config->config = HEVC_DuplicateConfig(cfg);
1400 entry->dataReferenceIndex = dataRefIndex;
1401 e = gf_list_add(trak->Media->information->sampleTable->SampleDescription->other_boxes, entry);
1402 *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->other_boxes);
1403 HEVC_RewriteESDescriptor(entry);
1404 return e;
1405 }
1406
1407 typedef enum
1408 {
1409 GF_ISOM_HVCC_UPDATE = 0,
1410 GF_ISOM_HVCC_SET_INBAND,
1411 GF_ISOM_HVCC_SET_TILE,
1412 GF_ISOM_HVCC_SET_TILE_BASE_TRACK,
1413 GF_ISOM_HVCC_SET_LHVC,
1414 GF_ISOM_HVCC_SET_LHVC_WITH_BASE,
1415 GF_ISOM_HVCC_SET_LHVC_WITH_BASE_BACKWARD,
1416 } HevcConfigUpdateType;
1417
hevc_cleanup_config(GF_HEVCConfig * cfg,HevcConfigUpdateType operand_type)1418 static Bool hevc_cleanup_config(GF_HEVCConfig *cfg, HevcConfigUpdateType operand_type)
1419 {
1420 u32 i;
1421 Bool array_incomplete = (operand_type == GF_ISOM_HVCC_SET_INBAND) ? 1 : 0;
1422 if (!cfg) return 0;
1423
1424 for (i = 0; i<gf_list_count(cfg->param_array); i++) {
1425 GF_HEVCParamArray *ar = (GF_HEVCParamArray*)gf_list_get(cfg->param_array, i);
1426
1427 /*we want to force hev1*/
1428 if (operand_type == GF_ISOM_HVCC_SET_INBAND)
1429 ar->array_completeness = 0;
1430
1431 if (!ar->array_completeness) {
1432 array_incomplete = 1;
1433
1434 while (gf_list_count(ar->nalus)) {
1435 GF_AVCConfigSlot *sl = (GF_AVCConfigSlot*)gf_list_get(ar->nalus, 0);
1436 gf_list_rem(ar->nalus, 0);
1437 if (sl->data) gf_free(sl->data);
1438 gf_free(sl);
1439 }
1440 gf_list_del(ar->nalus);
1441 gf_free(ar);
1442 gf_list_rem(cfg->param_array, i);
1443 i--;
1444
1445 }
1446 }
1447 return array_incomplete;
1448 }
1449
1450 static
gf_isom_hevc_config_update_ex(GF_ISOFile * the_file,u32 trackNumber,u32 DescriptionIndex,GF_HEVCConfig * cfg,u32 operand_type)1451 GF_Err gf_isom_hevc_config_update_ex(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex, GF_HEVCConfig *cfg, u32 operand_type)
1452 {
1453 u32 array_incomplete;
1454 GF_TrackBox *trak;
1455 GF_Err e;
1456 GF_MPEGVisualSampleEntryBox *entry;
1457
1458 e = CanAccessMovie(the_file, GF_ISOM_OPEN_WRITE);
1459 if (e) return e;
1460 trak = gf_isom_get_track_from_file(the_file, trackNumber);
1461 if (!trak || !trak->Media || !DescriptionIndex) return GF_BAD_PARAM;
1462 entry = (GF_MPEGVisualSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, DescriptionIndex - 1);
1463 if (!entry) return GF_BAD_PARAM;
1464 switch (entry->type) {
1465 case GF_ISOM_BOX_TYPE_HVC1:
1466 case GF_ISOM_BOX_TYPE_HEV1:
1467 case GF_ISOM_BOX_TYPE_HVC2:
1468 case GF_ISOM_BOX_TYPE_HEV2:
1469 case GF_ISOM_BOX_TYPE_LHV1:
1470 case GF_ISOM_BOX_TYPE_LHE1:
1471 case GF_ISOM_BOX_TYPE_HVT1:
1472 break;
1473 default:
1474 return GF_BAD_PARAM;
1475 }
1476
1477
1478 if (operand_type == GF_ISOM_HVCC_SET_TILE_BASE_TRACK) {
1479 if (entry->type == GF_ISOM_BOX_TYPE_HVC1)
1480 entry->type = GF_ISOM_BOX_TYPE_HVC2;
1481 else if (entry->type == GF_ISOM_BOX_TYPE_HEV1)
1482 entry->type = GF_ISOM_BOX_TYPE_HEV2;
1483 }
1484 else if (operand_type == GF_ISOM_HVCC_SET_TILE) {
1485 if (!entry->hevc_config) entry->hevc_config = (GF_HEVCConfigurationBox*)gf_isom_box_new(GF_ISOM_BOX_TYPE_HVCC);
1486 if (entry->hevc_config->config) gf_odf_hevc_cfg_del(entry->hevc_config->config);
1487 entry->hevc_config->config = NULL;
1488 entry->type = GF_ISOM_BOX_TYPE_HVT1;
1489 }
1490 else if (operand_type < GF_ISOM_HVCC_SET_LHVC) {
1491 if ((operand_type != GF_ISOM_HVCC_SET_INBAND) && !entry->hevc_config)
1492 entry->hevc_config = (GF_HEVCConfigurationBox*)gf_isom_box_new(GF_ISOM_BOX_TYPE_HVCC);
1493
1494 if (cfg) {
1495 if (entry->hevc_config->config) gf_odf_hevc_cfg_del(entry->hevc_config->config);
1496 entry->hevc_config->config = HEVC_DuplicateConfig(cfg);
1497 }
1498 else if (operand_type != GF_ISOM_HVCC_SET_TILE) {
1499 operand_type = GF_ISOM_HVCC_SET_INBAND;
1500 }
1501 array_incomplete = (operand_type == GF_ISOM_HVCC_SET_INBAND) ? 1 : 0;
1502 if (entry->hevc_config && hevc_cleanup_config(entry->hevc_config->config, operand_type))
1503 array_incomplete = 1;
1504
1505 if (entry->lhvc_config && hevc_cleanup_config(entry->lhvc_config->config, operand_type))
1506 array_incomplete = 1;
1507
1508 switch (entry->type) {
1509 case GF_ISOM_BOX_TYPE_HEV1:
1510 case GF_ISOM_BOX_TYPE_HVC1:
1511 entry->type = array_incomplete ? GF_ISOM_BOX_TYPE_HEV1 : GF_ISOM_BOX_TYPE_HVC1;
1512 break;
1513 case GF_ISOM_BOX_TYPE_HEV2:
1514 case GF_ISOM_BOX_TYPE_HVC2:
1515 entry->type = array_incomplete ? GF_ISOM_BOX_TYPE_HEV2 : GF_ISOM_BOX_TYPE_HVC2;
1516 break;
1517 case GF_ISOM_BOX_TYPE_LHE1:
1518 case GF_ISOM_BOX_TYPE_LHV1:
1519 entry->type = array_incomplete ? GF_ISOM_BOX_TYPE_LHE1 : GF_ISOM_BOX_TYPE_LHV1;
1520 break;
1521 }
1522 }
1523 else {
1524
1525 /*SVCC replacement/removal with HEVC base, backward compatible signaling*/
1526 if ((operand_type == GF_ISOM_HVCC_SET_LHVC_WITH_BASE_BACKWARD) || (operand_type == GF_ISOM_HVCC_SET_LHVC_WITH_BASE)) {
1527 if (!entry->hevc_config) return GF_BAD_PARAM;
1528 if (!cfg) {
1529 if (entry->lhvc_config) {
1530 gf_isom_box_del((GF_Box*)entry->lhvc_config);
1531 entry->lhvc_config = NULL;
1532 }
1533 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;
1534 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;
1535 else entry->type = (operand_type == GF_ISOM_HVCC_SET_LHVC_WITH_BASE) ? GF_ISOM_BOX_TYPE_HVC2 : GF_ISOM_BOX_TYPE_HVC1;
1536 }
1537 else {
1538 if (!entry->lhvc_config) entry->lhvc_config = (GF_HEVCConfigurationBox*)gf_isom_box_new(GF_ISOM_BOX_TYPE_LHVC);
1539 if (entry->lhvc_config->config) gf_odf_hevc_cfg_del(entry->lhvc_config->config);
1540 entry->lhvc_config->config = HEVC_DuplicateConfig(cfg);
1541
1542 if (operand_type == GF_ISOM_HVCC_SET_LHVC_WITH_BASE_BACKWARD) {
1543 if (entry->type == GF_ISOM_BOX_TYPE_HEV2) entry->type = GF_ISOM_BOX_TYPE_HEV1;
1544 else entry->type = GF_ISOM_BOX_TYPE_HVC1;
1545 }
1546 else {
1547 if (entry->type == GF_ISOM_BOX_TYPE_HEV1) entry->type = GF_ISOM_BOX_TYPE_HEV2;
1548 else entry->type = GF_ISOM_BOX_TYPE_HVC2;
1549 }
1550 }
1551 }
1552 /*LHEVC track without base*/
1553 else if (operand_type == GF_ISOM_HVCC_SET_LHVC) {
1554 if (entry->hevc_config) {
1555 gf_isom_box_del((GF_Box*)entry->hevc_config);
1556 entry->hevc_config = NULL;
1557 }
1558 if (!cfg) return GF_BAD_PARAM;
1559
1560 if (!entry->lhvc_config) entry->lhvc_config = (GF_HEVCConfigurationBox*)gf_isom_box_new(GF_ISOM_BOX_TYPE_LHVC);
1561 if (entry->lhvc_config->config) gf_odf_hevc_cfg_del(entry->lhvc_config->config);
1562 entry->lhvc_config->config = HEVC_DuplicateConfig(cfg);
1563
1564 if ((entry->type == GF_ISOM_BOX_TYPE_HEV1) || (entry->type == GF_ISOM_BOX_TYPE_HEV2)) entry->type = GF_ISOM_BOX_TYPE_LHE1;
1565 else entry->type = GF_ISOM_BOX_TYPE_LHV1;
1566 }
1567 }
1568
1569 HEVC_RewriteESDescriptor(entry);
1570 return GF_OK;
1571 }
1572
1573 GF_EXPORT
gf_isom_hevc_config_update(GF_ISOFile * the_file,u32 trackNumber,u32 DescriptionIndex,GF_HEVCConfig * cfg)1574 GF_Err gf_isom_hevc_config_update(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex, GF_HEVCConfig *cfg)
1575 {
1576 return gf_isom_hevc_config_update_ex(the_file, trackNumber, DescriptionIndex, cfg, GF_ISOM_HVCC_UPDATE);
1577 }
1578
1579 GF_EXPORT
gf_isom_hevc_set_inband_config(GF_ISOFile * the_file,u32 trackNumber,u32 DescriptionIndex)1580 GF_Err gf_isom_hevc_set_inband_config(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
1581 {
1582 return gf_isom_hevc_config_update_ex(the_file, trackNumber, DescriptionIndex, NULL, GF_ISOM_HVCC_SET_INBAND);
1583 }
1584
1585 GF_EXPORT
gf_isom_hevc_set_tile_config(GF_ISOFile * the_file,u32 trackNumber,u32 DescriptionIndex,GF_HEVCConfig * cfg,Bool is_base_track)1586 GF_Err gf_isom_hevc_set_tile_config(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex, GF_HEVCConfig *cfg, Bool is_base_track)
1587 {
1588 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);
1589 }
1590
gf_isom_lhvc_config_update(GF_ISOFile * the_file,u32 trackNumber,u32 DescriptionIndex,GF_HEVCConfig * cfg,GF_ISOMLHEVCTrackType track_type)1591 GF_Err gf_isom_lhvc_config_update(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex, GF_HEVCConfig *cfg, GF_ISOMLHEVCTrackType track_type)
1592 {
1593 if (cfg) cfg->is_lhvc = GF_TRUE;
1594 switch (track_type) {
1595 case GF_ISOM_LEHVC_ONLY:
1596 return gf_isom_hevc_config_update_ex(the_file, trackNumber, DescriptionIndex, cfg, GF_ISOM_HVCC_SET_LHVC);
1597 case GF_ISOM_LEHVC_WITH_BASE:
1598 return gf_isom_hevc_config_update_ex(the_file, trackNumber, DescriptionIndex, cfg, GF_ISOM_HVCC_SET_LHVC_WITH_BASE);
1599 case GF_ISOM_LEHVC_WITH_BASE_BACKWARD:
1600 return gf_isom_hevc_config_update_ex(the_file, trackNumber, DescriptionIndex, cfg, GF_ISOM_HVCC_SET_LHVC_WITH_BASE_BACKWARD);
1601 default:
1602 return GF_BAD_PARAM;
1603 }
1604 }
1605
1606 #endif /*GPAC_DISABLE_ISOM_WRITE*/
1607
1608 GF_EXPORT
gf_isom_clone_config_box(GF_Box * box)1609 GF_Box *gf_isom_clone_config_box(GF_Box *box)
1610 {
1611 GF_Box *clone;
1612 switch (box->type)
1613 {
1614 case GF_ISOM_BOX_TYPE_AVCC:
1615 case GF_ISOM_BOX_TYPE_SVCC:
1616 clone = gf_isom_box_new(box->type);
1617 ((GF_AVCConfigurationBox *)clone)->config = AVC_DuplicateConfig(((GF_AVCConfigurationBox *)box)->config);
1618 break;
1619 case GF_ISOM_BOX_TYPE_HVCC:
1620 clone = gf_isom_box_new(box->type);
1621 ((GF_HEVCConfigurationBox *)clone)->config = HEVC_DuplicateConfig(((GF_HEVCConfigurationBox *)box)->config);
1622 break;
1623 default:
1624 clone = NULL;
1625 GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("Cloning of config not supported for type %s\n", gf_4cc_to_str(box->type)));
1626 break;
1627 }
1628 return clone;
1629 }
1630
1631 GF_EXPORT
gf_isom_avc_config_get(GF_ISOFile * the_file,u32 trackNumber,u32 DescriptionIndex)1632 GF_AVCConfig *gf_isom_avc_config_get(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
1633 {
1634 GF_TrackBox *trak;
1635 GF_MPEGVisualSampleEntryBox *entry;
1636 trak = gf_isom_get_track_from_file(the_file, trackNumber);
1637 if (!trak || !trak->Media || !DescriptionIndex) return NULL;
1638 if (gf_isom_get_avc_svc_type(the_file, trackNumber, DescriptionIndex) == GF_ISOM_AVCTYPE_NONE)
1639 return NULL;
1640
1641 entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, DescriptionIndex - 1);
1642 if (!entry) return NULL;
1643
1644 if (!entry->avc_config) return NULL;
1645 return AVC_DuplicateConfig(entry->avc_config->config);
1646 }
1647
1648 GF_EXPORT
gf_isom_hevc_config_get(GF_ISOFile * the_file,u32 trackNumber,u32 DescriptionIndex)1649 GF_HEVCConfig *gf_isom_hevc_config_get(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
1650 {
1651 GF_TrackBox *trak;
1652 GF_MPEGVisualSampleEntryBox *entry;
1653 if (gf_isom_get_reference_count(the_file, trackNumber, GF_ISOM_REF_TBAS)) {
1654 u32 ref_track;
1655 GF_Err e = gf_isom_get_reference(the_file, trackNumber, GF_ISOM_REF_TBAS, 1, &ref_track);
1656 if (e == GF_OK) {
1657 trackNumber = ref_track;
1658 }
1659 }
1660 trak = gf_isom_get_track_from_file(the_file, trackNumber);
1661 if (!trak || !trak->Media || !DescriptionIndex) return NULL;
1662 if (gf_isom_get_hevc_lhvc_type(the_file, trackNumber, DescriptionIndex) == GF_ISOM_HEVCTYPE_NONE)
1663 return NULL;
1664 entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, DescriptionIndex - 1);
1665 if (!entry) return NULL;
1666 if (!entry->hevc_config) return NULL;
1667 return HEVC_DuplicateConfig(entry->hevc_config->config);
1668 }
1669
1670 GF_EXPORT
gf_isom_svc_config_get(GF_ISOFile * the_file,u32 trackNumber,u32 DescriptionIndex)1671 GF_AVCConfig *gf_isom_svc_config_get(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
1672 {
1673 GF_TrackBox *trak;
1674 GF_MPEGVisualSampleEntryBox *entry;
1675 trak = gf_isom_get_track_from_file(the_file, trackNumber);
1676 if (!trak || !trak->Media || !DescriptionIndex) return NULL;
1677 if (gf_isom_get_avc_svc_type(the_file, trackNumber, DescriptionIndex) == GF_ISOM_AVCTYPE_NONE)
1678 return NULL;
1679 entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, DescriptionIndex - 1);
1680 if (!entry) return NULL;
1681 if (!entry->svc_config) return NULL;
1682 return AVC_DuplicateConfig(entry->svc_config->config);
1683 }
1684
1685
1686 GF_EXPORT
gf_isom_get_avc_svc_type(GF_ISOFile * the_file,u32 trackNumber,u32 DescriptionIndex)1687 u32 gf_isom_get_avc_svc_type(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
1688 {
1689 u32 type;
1690 GF_TrackBox *trak;
1691 GF_MPEGVisualSampleEntryBox *entry;
1692 trak = gf_isom_get_track_from_file(the_file, trackNumber);
1693 if (!trak || !trak->Media || !DescriptionIndex) return GF_ISOM_AVCTYPE_NONE;
1694 if (trak->Media->handler->handlerType != GF_ISOM_MEDIA_VISUAL) return GF_ISOM_AVCTYPE_NONE;
1695 entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, DescriptionIndex - 1);
1696 type = entry->type;
1697
1698 if (type == GF_ISOM_BOX_TYPE_ENCV) {
1699 GF_ProtectionInfoBox *sinf = (GF_ProtectionInfoBox *)gf_list_get(entry->protections, 0);
1700 if (sinf && sinf->original_format) type = sinf->original_format->data_format;
1701 }
1702
1703 switch (type) {
1704 case GF_ISOM_BOX_TYPE_AVC1:
1705 case GF_ISOM_BOX_TYPE_AVC2:
1706 case GF_ISOM_BOX_TYPE_AVC3:
1707 case GF_ISOM_BOX_TYPE_AVC4:
1708 case GF_ISOM_BOX_TYPE_SVC1:
1709 break;
1710 default:
1711 return GF_ISOM_AVCTYPE_NONE;
1712 }
1713 if (entry->avc_config && !entry->svc_config) return GF_ISOM_AVCTYPE_AVC_ONLY;
1714 if (entry->avc_config && entry->svc_config) return GF_ISOM_AVCTYPE_AVC_SVC;
1715 if (!entry->avc_config && entry->svc_config) return GF_ISOM_AVCTYPE_SVC_ONLY;
1716 return GF_ISOM_AVCTYPE_NONE;
1717 }
1718
1719 GF_EXPORT
gf_isom_get_hevc_lhvc_type(GF_ISOFile * the_file,u32 trackNumber,u32 DescriptionIndex)1720 u32 gf_isom_get_hevc_lhvc_type(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
1721 {
1722 u32 type;
1723 GF_TrackBox *trak;
1724 GF_MPEGVisualSampleEntryBox *entry;
1725 trak = gf_isom_get_track_from_file(the_file, trackNumber);
1726 if (!trak || !trak->Media || !DescriptionIndex) return GF_ISOM_HEVCTYPE_NONE;
1727 if (trak->Media->handler->handlerType != GF_ISOM_MEDIA_VISUAL) return GF_ISOM_HEVCTYPE_NONE;
1728 entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, DescriptionIndex - 1);
1729 type = entry->type;
1730
1731 if (type == GF_ISOM_BOX_TYPE_ENCV) {
1732 GF_ProtectionInfoBox *sinf = (GF_ProtectionInfoBox *)gf_list_get(entry->protections, 0);
1733 if (sinf && sinf->original_format) type = sinf->original_format->data_format;
1734 }
1735
1736 switch (type) {
1737 case GF_ISOM_BOX_TYPE_HVC1:
1738 case GF_ISOM_BOX_TYPE_HEV1:
1739 case GF_ISOM_BOX_TYPE_HVC2:
1740 case GF_ISOM_BOX_TYPE_HEV2:
1741 case GF_ISOM_BOX_TYPE_LHV1:
1742 case GF_ISOM_BOX_TYPE_LHE1:
1743 case GF_ISOM_BOX_TYPE_HVT1:
1744 break;
1745 default:
1746 return GF_ISOM_HEVCTYPE_NONE;
1747 }
1748 if (entry->hevc_config && !entry->lhvc_config) return GF_ISOM_HEVCTYPE_HEVC_ONLY;
1749 if (entry->hevc_config && entry->lhvc_config) return GF_ISOM_HEVCTYPE_HEVC_LHVC;
1750 if (!entry->hevc_config && entry->lhvc_config) return GF_ISOM_HEVCTYPE_LHVC_ONLY;
1751 return GF_ISOM_HEVCTYPE_NONE;
1752 }
1753
1754 GF_EXPORT
gf_isom_lhvc_config_get(GF_ISOFile * the_file,u32 trackNumber,u32 DescriptionIndex)1755 GF_HEVCConfig *gf_isom_lhvc_config_get(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
1756 {
1757 GF_HEVCConfig *lhvc;
1758 GF_OperatingPointsInformation *oinf = NULL;
1759 GF_TrackBox *trak;
1760 GF_MPEGVisualSampleEntryBox *entry;
1761 trak = gf_isom_get_track_from_file(the_file, trackNumber);
1762 if (!trak || !trak->Media || !DescriptionIndex) return NULL;
1763 if (gf_isom_get_hevc_lhvc_type(the_file, trackNumber, DescriptionIndex) == GF_ISOM_HEVCTYPE_NONE)
1764 return NULL;
1765 entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, DescriptionIndex - 1);
1766 if (!entry) return NULL;
1767 if (!entry->lhvc_config) return NULL;
1768 lhvc = HEVC_DuplicateConfig(entry->lhvc_config->config);
1769 if (!lhvc) return NULL;
1770
1771 gf_isom_get_oinf_info(the_file, trackNumber, &oinf);
1772 if (oinf) {
1773 LHEVC_ProfileTierLevel *ptl = (LHEVC_ProfileTierLevel *)gf_list_last(oinf->profile_tier_levels);
1774 if (ptl) {
1775 lhvc->profile_space = ptl->general_profile_space;
1776 lhvc->tier_flag = ptl->general_tier_flag;
1777 lhvc->profile_idc = ptl->general_profile_idc;
1778 lhvc->general_profile_compatibility_flags = ptl->general_profile_compatibility_flags;
1779 lhvc->constraint_indicator_flags = ptl->general_constraint_indicator_flags;
1780 }
1781 }
1782 return lhvc;
1783 }
1784
1785
btrt_del(GF_Box * s)1786 void btrt_del(GF_Box *s)
1787 {
1788 GF_BitRateBox *ptr = (GF_BitRateBox *)s;
1789 if (ptr) gf_free(ptr);
1790 }
btrt_Read(GF_Box * s,GF_BitStream * bs)1791 GF_Err btrt_Read(GF_Box *s, GF_BitStream *bs)
1792 {
1793 GF_BitRateBox *ptr = (GF_BitRateBox *)s;
1794 ptr->bufferSizeDB = gf_bs_read_u32(bs);
1795 ptr->maxBitrate = gf_bs_read_u32(bs);
1796 ptr->avgBitrate = gf_bs_read_u32(bs);
1797 return GF_OK;
1798 }
btrt_New()1799 GF_Box *btrt_New()
1800 {
1801 GF_BitRateBox *tmp = (GF_BitRateBox *)gf_malloc(sizeof(GF_BitRateBox));
1802 if (tmp == NULL) return NULL;
1803 memset(tmp, 0, sizeof(GF_BitRateBox));
1804 tmp->type = GF_ISOM_BOX_TYPE_BTRT;
1805 return (GF_Box *)tmp;
1806 }
1807
1808 #ifndef GPAC_DISABLE_ISOM_WRITE
btrt_Write(GF_Box * s,GF_BitStream * bs)1809 GF_Err btrt_Write(GF_Box *s, GF_BitStream *bs)
1810 {
1811 GF_Err e;
1812 GF_BitRateBox *ptr = (GF_BitRateBox *)s;
1813 if (!s) return GF_BAD_PARAM;
1814 e = gf_isom_box_write_header(s, bs);
1815 if (e) return e;
1816 gf_bs_write_u32(bs, ptr->bufferSizeDB);
1817 gf_bs_write_u32(bs, ptr->maxBitrate);
1818 gf_bs_write_u32(bs, ptr->avgBitrate);
1819 return GF_OK;
1820 }
btrt_Size(GF_Box * s)1821 GF_Err btrt_Size(GF_Box *s)
1822 {
1823 GF_Err e;
1824 GF_BitRateBox *ptr = (GF_BitRateBox *)s;
1825 e = gf_isom_box_get_size(s);
1826 ptr->size += 12;
1827 return e;
1828 }
1829 #endif /*GPAC_DISABLE_ISOM_WRITE*/
1830
1831
1832
m4ds_del(GF_Box * s)1833 void m4ds_del(GF_Box *s)
1834 {
1835 GF_MPEG4ExtensionDescriptorsBox *ptr = (GF_MPEG4ExtensionDescriptorsBox *)s;
1836 gf_odf_desc_list_del(ptr->descriptors);
1837 gf_list_del(ptr->descriptors);
1838 gf_free(ptr);
1839 }
m4ds_Read(GF_Box * s,GF_BitStream * bs)1840 GF_Err m4ds_Read(GF_Box *s, GF_BitStream *bs)
1841 {
1842 GF_Err e;
1843 char *enc_od;
1844 GF_MPEG4ExtensionDescriptorsBox *ptr = (GF_MPEG4ExtensionDescriptorsBox *)s;
1845 u32 od_size = (u32)ptr->size;
1846 if (!od_size) return GF_OK;
1847 enc_od = (char *)gf_malloc(sizeof(char) * od_size);
1848 gf_bs_read_data(bs, enc_od, od_size);
1849 e = gf_odf_desc_list_read((char *)enc_od, od_size, ptr->descriptors);
1850 gf_free(enc_od);
1851 return e;
1852 }
m4ds_New()1853 GF_Box *m4ds_New()
1854 {
1855 GF_MPEG4ExtensionDescriptorsBox *tmp = (GF_MPEG4ExtensionDescriptorsBox *)gf_malloc(sizeof(GF_MPEG4ExtensionDescriptorsBox));
1856 if (tmp == NULL) return NULL;
1857 memset(tmp, 0, sizeof(GF_MPEG4ExtensionDescriptorsBox));
1858 tmp->type = GF_ISOM_BOX_TYPE_M4DS;
1859 tmp->descriptors = gf_list_new();
1860 return (GF_Box *)tmp;
1861 }
1862
1863 #ifndef GPAC_DISABLE_ISOM_WRITE
m4ds_Write(GF_Box * s,GF_BitStream * bs)1864 GF_Err m4ds_Write(GF_Box *s, GF_BitStream *bs)
1865 {
1866 GF_Err e;
1867 char *enc_ods;
1868 u32 enc_od_size;
1869 GF_MPEG4ExtensionDescriptorsBox *ptr = (GF_MPEG4ExtensionDescriptorsBox *)s;
1870 if (!s) return GF_BAD_PARAM;
1871 e = gf_isom_box_write_header(s, bs);
1872 if (e) return e;
1873 enc_ods = NULL;
1874 enc_od_size = 0;
1875 e = gf_odf_desc_list_write(ptr->descriptors, &enc_ods, &enc_od_size);
1876 if (e) return e;
1877 if (enc_od_size) {
1878 gf_bs_write_data(bs, enc_ods, enc_od_size);
1879 gf_free(enc_ods);
1880 }
1881 return GF_OK;
1882 }
m4ds_Size(GF_Box * s)1883 GF_Err m4ds_Size(GF_Box *s)
1884 {
1885 GF_Err e;
1886 u32 descSize = 0;
1887 GF_MPEG4ExtensionDescriptorsBox *ptr = (GF_MPEG4ExtensionDescriptorsBox *)s;
1888 e = gf_isom_box_get_size(s);
1889 if (e) return e;
1890 e = gf_odf_desc_list_size(ptr->descriptors, &descSize);
1891 ptr->size += descSize;
1892 return e;
1893 }
1894 #endif /*GPAC_DISABLE_ISOM_WRITE*/
1895
1896
1897
avcc_del(GF_Box * s)1898 void avcc_del(GF_Box *s)
1899 {
1900 GF_AVCConfigurationBox *ptr = (GF_AVCConfigurationBox *)s;
1901 if (ptr->config) gf_odf_avc_cfg_del(ptr->config);
1902 gf_free(ptr);
1903 }
1904
avcc_Read(GF_Box * s,GF_BitStream * bs)1905 GF_Err avcc_Read(GF_Box *s, GF_BitStream *bs)
1906 {
1907 u32 i, count;
1908 GF_AVCConfigurationBox *ptr = (GF_AVCConfigurationBox *)s;
1909
1910 if (ptr->config) gf_odf_avc_cfg_del(ptr->config);
1911 ptr->config = gf_odf_avc_cfg_new();
1912 ptr->config->configurationVersion = gf_bs_read_u8(bs);
1913 ptr->config->AVCProfileIndication = gf_bs_read_u8(bs);
1914 ptr->config->profile_compatibility = gf_bs_read_u8(bs);
1915 ptr->config->AVCLevelIndication = gf_bs_read_u8(bs);
1916 if (ptr->type == GF_ISOM_BOX_TYPE_AVCC) {
1917 gf_bs_read_int(bs, 6);
1918 }
1919 else {
1920 ptr->config->complete_representation = gf_bs_read_int(bs, 1);
1921 gf_bs_read_int(bs, 5);
1922 }
1923 ptr->config->nal_unit_size = 1 + gf_bs_read_int(bs, 2);
1924 gf_bs_read_int(bs, 3);
1925 count = gf_bs_read_int(bs, 5);
1926
1927 ptr->size -= 7; //including 2nd count
1928
1929 for (i = 0; i<count; i++) {
1930 GF_AVCConfigSlot *sl = (GF_AVCConfigSlot *)gf_malloc(sizeof(GF_AVCConfigSlot));
1931 sl->size = gf_bs_read_u16(bs);
1932 sl->data = (char *)gf_malloc(sizeof(char) * sl->size);
1933 gf_bs_read_data(bs, sl->data, sl->size);
1934 gf_list_add(ptr->config->sequenceParameterSets, sl);
1935 ptr->size -= 2 + sl->size;
1936 }
1937
1938 count = gf_bs_read_u8(bs);
1939 for (i = 0; i<count; i++) {
1940 GF_AVCConfigSlot *sl = (GF_AVCConfigSlot *)gf_malloc(sizeof(GF_AVCConfigSlot));
1941 sl->size = gf_bs_read_u16(bs);
1942 sl->data = (char *)gf_malloc(sizeof(char) * sl->size);
1943 gf_bs_read_data(bs, sl->data, sl->size);
1944 gf_list_add(ptr->config->pictureParameterSets, sl);
1945 ptr->size -= 2 + sl->size;
1946 }
1947
1948 if (ptr->type == GF_ISOM_BOX_TYPE_AVCC) {
1949 if (gf_avc_is_rext_profile(ptr->config->AVCProfileIndication)) {
1950 if (!ptr->size) {
1951 #ifndef GPAC_DISABLE_AV_PARSERS
1952 AVCState avc;
1953 s32 idx, vui_flag_pos;
1954 GF_AVCConfigSlot *sl = (GF_AVCConfigSlot*)gf_list_get(ptr->config->sequenceParameterSets, 0);
1955 idx = gf_media_avc_read_sps(sl->data + 1, sl->size - 1, &avc, 0, (u32 *)&vui_flag_pos);
1956 if (idx >= 0) {
1957 ptr->config->chroma_format = avc.sps[idx].chroma_format;
1958 ptr->config->luma_bit_depth = 8 + avc.sps[idx].luma_bit_depth_m8;
1959 ptr->config->chroma_bit_depth = 8 + avc.sps[idx].chroma_bit_depth_m8;
1960 }
1961 #else
1962 /*set default values ...*/
1963 ptr->config->chroma_format = 1;
1964 ptr->config->luma_bit_depth = 8;
1965 ptr->config->chroma_bit_depth = 8;
1966 #endif
1967 return GF_OK;
1968 }
1969 gf_bs_read_int(bs, 6);
1970 ptr->config->chroma_format = gf_bs_read_int(bs, 2);
1971 gf_bs_read_int(bs, 5);
1972 ptr->config->luma_bit_depth = 8 + gf_bs_read_int(bs, 3);
1973 gf_bs_read_int(bs, 5);
1974 ptr->config->chroma_bit_depth = 8 + gf_bs_read_int(bs, 3);
1975
1976 count = gf_bs_read_int(bs, 8);
1977 ptr->size -= 4;
1978 if (count * 2 > ptr->size) {
1979 //ffmpeg just ignores this part while allocating bytes (filled with garbage?)
1980 GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("AVCC: invalid numOfSequenceParameterSetExt value. Skipping.\n"));
1981 return GF_OK;
1982 }
1983 if (count) {
1984 ptr->config->sequenceParameterSetExtensions = gf_list_new();
1985 for (i = 0; i<count; i++) {
1986 GF_AVCConfigSlot *sl = (GF_AVCConfigSlot *)gf_malloc(sizeof(GF_AVCConfigSlot));
1987 sl->size = gf_bs_read_u16(bs);
1988 sl->data = (char *)gf_malloc(sizeof(char) * sl->size);
1989 gf_bs_read_data(bs, sl->data, sl->size);
1990 gf_list_add(ptr->config->sequenceParameterSetExtensions, sl);
1991 ptr->size -= sl->size + 2;
1992 }
1993 }
1994 }
1995 }
1996 return GF_OK;
1997 }
1998
avcc_New()1999 GF_Box *avcc_New()
2000 {
2001 GF_AVCConfigurationBox *tmp = (GF_AVCConfigurationBox *)gf_malloc(sizeof(GF_AVCConfigurationBox));
2002 if (tmp == NULL) return NULL;
2003 memset(tmp, 0, sizeof(GF_AVCConfigurationBox));
2004 tmp->type = GF_ISOM_BOX_TYPE_AVCC;
2005 return (GF_Box *)tmp;
2006 }
2007
2008 #ifndef GPAC_DISABLE_ISOM_WRITE
avcc_Write(GF_Box * s,GF_BitStream * bs)2009 GF_Err avcc_Write(GF_Box *s, GF_BitStream *bs)
2010 {
2011 u32 i, count;
2012 GF_Err e;
2013 GF_AVCConfigurationBox *ptr = (GF_AVCConfigurationBox *)s;
2014 if (!s) return GF_BAD_PARAM;
2015 if (!ptr->config) return GF_OK;
2016 e = gf_isom_box_write_header(s, bs);
2017 if (e) return e;
2018
2019 gf_bs_write_u8(bs, ptr->config->configurationVersion);
2020 gf_bs_write_u8(bs, ptr->config->AVCProfileIndication);
2021 gf_bs_write_u8(bs, ptr->config->profile_compatibility);
2022 gf_bs_write_u8(bs, ptr->config->AVCLevelIndication);
2023 if (ptr->type == GF_ISOM_BOX_TYPE_AVCC) {
2024 gf_bs_write_int(bs, 0x3F, 6);
2025 }
2026 else {
2027 gf_bs_write_int(bs, ptr->config->complete_representation, 1);
2028 gf_bs_write_int(bs, 0x1F, 5);
2029 }
2030 gf_bs_write_int(bs, ptr->config->nal_unit_size - 1, 2);
2031 gf_bs_write_int(bs, 0x7, 3);
2032 count = gf_list_count(ptr->config->sequenceParameterSets);
2033 gf_bs_write_int(bs, count, 5);
2034 for (i = 0; i<count; i++) {
2035 GF_AVCConfigSlot *sl = (GF_AVCConfigSlot *)gf_list_get(ptr->config->sequenceParameterSets, i);
2036 gf_bs_write_u16(bs, sl->size);
2037 gf_bs_write_data(bs, sl->data, sl->size);
2038 }
2039
2040 count = gf_list_count(ptr->config->pictureParameterSets);
2041 gf_bs_write_u8(bs, count);
2042 for (i = 0; i<count; i++) {
2043 GF_AVCConfigSlot *sl = (GF_AVCConfigSlot *)gf_list_get(ptr->config->pictureParameterSets, i);
2044 gf_bs_write_u16(bs, sl->size);
2045 gf_bs_write_data(bs, sl->data, sl->size);
2046 }
2047
2048
2049 if (ptr->type == GF_ISOM_BOX_TYPE_AVCC) {
2050 if (gf_avc_is_rext_profile(ptr->config->AVCProfileIndication)) {
2051 gf_bs_write_int(bs, 0xFF, 6);
2052 gf_bs_write_int(bs, ptr->config->chroma_format, 2);
2053 gf_bs_write_int(bs, 0xFF, 5);
2054 gf_bs_write_int(bs, ptr->config->luma_bit_depth - 8, 3);
2055 gf_bs_write_int(bs, 0xFF, 5);
2056 gf_bs_write_int(bs, ptr->config->chroma_bit_depth - 8, 3);
2057
2058 count = ptr->config->sequenceParameterSetExtensions ? gf_list_count(ptr->config->sequenceParameterSetExtensions) : 0;
2059 gf_bs_write_u8(bs, count);
2060 for (i = 0; i<count; i++) {
2061 GF_AVCConfigSlot *sl = (GF_AVCConfigSlot *)gf_list_get(ptr->config->sequenceParameterSetExtensions, i);
2062 gf_bs_write_u16(bs, sl->size);
2063 gf_bs_write_data(bs, sl->data, sl->size);
2064 }
2065 }
2066 }
2067 return GF_OK;
2068 }
avcc_Size(GF_Box * s)2069 GF_Err avcc_Size(GF_Box *s)
2070 {
2071 GF_Err e;
2072 u32 i, count;
2073 GF_AVCConfigurationBox *ptr = (GF_AVCConfigurationBox *)s;
2074 e = gf_isom_box_get_size(s);
2075 if (e) return e;
2076 if (!ptr->config) {
2077 ptr->size = 0;
2078 return e;
2079 }
2080 ptr->size += 7;
2081 count = gf_list_count(ptr->config->sequenceParameterSets);
2082 for (i = 0; i<count; i++)
2083 ptr->size += 2 + ((GF_AVCConfigSlot *)gf_list_get(ptr->config->sequenceParameterSets, i))->size;
2084
2085 count = gf_list_count(ptr->config->pictureParameterSets);
2086 for (i = 0; i<count; i++)
2087 ptr->size += 2 + ((GF_AVCConfigSlot *)gf_list_get(ptr->config->pictureParameterSets, i))->size;
2088
2089 if (ptr->type == GF_ISOM_BOX_TYPE_AVCC) {
2090 if (gf_avc_is_rext_profile(ptr->config->AVCProfileIndication)) {
2091 ptr->size += 4;
2092 count = ptr->config->sequenceParameterSetExtensions ? gf_list_count(ptr->config->sequenceParameterSetExtensions) : 0;
2093 for (i = 0; i<count; i++)
2094 ptr->size += 2 + ((GF_AVCConfigSlot *)gf_list_get(ptr->config->sequenceParameterSetExtensions, i))->size;
2095 }
2096 }
2097 return GF_OK;
2098 }
2099 #endif /*GPAC_DISABLE_ISOM_WRITE*/
2100
2101
2102
hvcc_del(GF_Box * s)2103 void hvcc_del(GF_Box *s)
2104 {
2105 GF_HEVCConfigurationBox *ptr = (GF_HEVCConfigurationBox*)s;
2106 if (ptr->config) gf_odf_hevc_cfg_del(ptr->config);
2107 gf_free(ptr);
2108 }
2109
hvcc_Read(GF_Box * s,GF_BitStream * bs)2110 GF_Err hvcc_Read(GF_Box *s, GF_BitStream *bs)
2111 {
2112 u64 pos;
2113 GF_HEVCConfigurationBox *ptr = (GF_HEVCConfigurationBox *)s;
2114
2115 if (ptr->config) gf_odf_hevc_cfg_del(ptr->config);
2116
2117 pos = gf_bs_get_position(bs);
2118 ptr->config = gf_odf_hevc_cfg_read_bs(bs, (s->type == GF_ISOM_BOX_TYPE_HVCC) ? GF_FALSE : GF_TRUE);
2119 pos = gf_bs_get_position(bs) - pos;
2120 if (pos < ptr->size)
2121 ptr->size -= (u32)pos;
2122
2123 return GF_OK;
2124 }
hvcc_New()2125 GF_Box *hvcc_New()
2126 {
2127 GF_HEVCConfigurationBox *tmp = (GF_HEVCConfigurationBox *)gf_malloc(sizeof(GF_HEVCConfigurationBox));
2128 if (tmp == NULL) return NULL;
2129 memset(tmp, 0, sizeof(GF_HEVCConfigurationBox));
2130 tmp->type = GF_ISOM_BOX_TYPE_HVCC;
2131 return (GF_Box *)tmp;
2132 }
2133
2134 #ifndef GPAC_DISABLE_ISOM_WRITE
hvcc_Write(GF_Box * s,GF_BitStream * bs)2135 GF_Err hvcc_Write(GF_Box *s, GF_BitStream *bs)
2136 {
2137 GF_Err e;
2138 GF_HEVCConfigurationBox *ptr = (GF_HEVCConfigurationBox *)s;
2139 if (!s) return GF_BAD_PARAM;
2140 if (!ptr->config) return GF_OK;
2141 e = gf_isom_box_write_header(s, bs);
2142 if (e) return e;
2143
2144 return gf_odf_hevc_cfg_write_bs(ptr->config, bs);
2145 }
hvcc_Size(GF_Box * s)2146 GF_Err hvcc_Size(GF_Box *s)
2147 {
2148 GF_Err e;
2149 u32 i, count, j, subcount;
2150 GF_HEVCConfigurationBox *ptr = (GF_HEVCConfigurationBox *)s;
2151 e = gf_isom_box_get_size(s);
2152 if (e) return e;
2153 if (!ptr->config) {
2154 ptr->size = 0;
2155 return e;
2156 }
2157
2158 if (!ptr->config->is_lhvc)
2159 ptr->size += 23;
2160 else
2161 ptr->size += 6;
2162
2163 count = gf_list_count(ptr->config->param_array);
2164 for (i = 0; i<count; i++) {
2165 GF_HEVCParamArray *ar = (GF_HEVCParamArray*)gf_list_get(ptr->config->param_array, i);
2166 ptr->size += 3;
2167 subcount = gf_list_count(ar->nalus);
2168 for (j = 0; j<subcount; j++) {
2169 ptr->size += 2 + ((GF_AVCConfigSlot *)gf_list_get(ar->nalus, j))->size;
2170 }
2171 }
2172 return GF_OK;
2173 }
2174 #endif /*GPAC_DISABLE_ISOM_WRITE*/
2175
gf_isom_oinf_new_entry()2176 GF_OperatingPointsInformation *gf_isom_oinf_new_entry()
2177 {
2178 GF_OperatingPointsInformation* ptr;
2179 GF_SAFEALLOC(ptr, GF_OperatingPointsInformation);
2180 if (ptr) {
2181 ptr->profile_tier_levels = gf_list_new();
2182 ptr->operating_points = gf_list_new();
2183 ptr->dependency_layers = gf_list_new();
2184 }
2185 return ptr;
2186
2187 }
2188
gf_isom_oinf_del_entry(void * entry)2189 void gf_isom_oinf_del_entry(void *entry)
2190 {
2191 GF_OperatingPointsInformation* ptr = (GF_OperatingPointsInformation *)entry;
2192 if (!ptr) return;
2193 if (ptr->profile_tier_levels) {
2194 while (gf_list_count(ptr->profile_tier_levels)) {
2195 LHEVC_ProfileTierLevel *ptl = (LHEVC_ProfileTierLevel *)gf_list_get(ptr->profile_tier_levels, 0);
2196 gf_free(ptl);
2197 gf_list_rem(ptr->profile_tier_levels, 0);
2198 }
2199 gf_list_del(ptr->profile_tier_levels);
2200 }
2201 if (ptr->operating_points) {
2202 while (gf_list_count(ptr->operating_points)) {
2203 LHEVC_OperatingPoint *op = (LHEVC_OperatingPoint *)gf_list_get(ptr->operating_points, 0);
2204 gf_free(op);
2205 gf_list_rem(ptr->operating_points, 0);
2206 }
2207 gf_list_del(ptr->operating_points);
2208 }
2209 if (ptr->dependency_layers) {
2210 while (gf_list_count(ptr->dependency_layers)) {
2211 LHEVC_DependentLayer *dep = (LHEVC_DependentLayer *)gf_list_get(ptr->dependency_layers, 0);
2212 gf_free(dep);
2213 gf_list_rem(ptr->dependency_layers, 0);
2214 }
2215 gf_list_del(ptr->dependency_layers);
2216 }
2217 gf_free(ptr);
2218 return;
2219 }
2220
gf_isom_oinf_read_entry(void * entry,GF_BitStream * bs)2221 GF_Err gf_isom_oinf_read_entry(void *entry, GF_BitStream *bs)
2222 {
2223 GF_OperatingPointsInformation* ptr = (GF_OperatingPointsInformation *)entry;
2224 u32 i, j, count;
2225
2226 if (!ptr) return GF_BAD_PARAM;
2227 ptr->scalability_mask = gf_bs_read_u16(bs);
2228 gf_bs_read_int(bs, 2);//reserved
2229 count = gf_bs_read_int(bs, 6);
2230 for (i = 0; i < count; i++) {
2231 LHEVC_ProfileTierLevel *ptl;
2232 GF_SAFEALLOC(ptl, LHEVC_ProfileTierLevel);
2233 if (!ptl) return GF_OUT_OF_MEM;
2234 ptl->general_profile_space = gf_bs_read_int(bs, 2);
2235 ptl->general_tier_flag = gf_bs_read_int(bs, 1);
2236 ptl->general_profile_idc = gf_bs_read_int(bs, 5);
2237 ptl->general_profile_compatibility_flags = gf_bs_read_u32(bs);
2238 ptl->general_constraint_indicator_flags = gf_bs_read_long_int(bs, 48);
2239 ptl->general_level_idc = gf_bs_read_u8(bs);
2240 gf_list_add(ptr->profile_tier_levels, ptl);
2241 }
2242 count = gf_bs_read_u16(bs);
2243 for (i = 0; i < count; i++) {
2244 LHEVC_OperatingPoint *op;
2245 GF_SAFEALLOC(op, LHEVC_OperatingPoint);
2246 if (!op) return GF_OUT_OF_MEM;
2247 op->output_layer_set_idx = gf_bs_read_u16(bs);
2248 op->max_temporal_id = gf_bs_read_u8(bs);
2249 op->layer_count = gf_bs_read_u8(bs);
2250 for (j = 0; j < op->layer_count; j++) {
2251 op->layers_info[j].ptl_idx = gf_bs_read_u8(bs);
2252 op->layers_info[j].layer_id = gf_bs_read_int(bs, 6);
2253 op->layers_info[j].is_outputlayer = gf_bs_read_int(bs, 1) ? GF_TRUE : GF_FALSE;
2254 op->layers_info[j].is_alternate_outputlayer = gf_bs_read_int(bs, 1) ? GF_TRUE : GF_FALSE;
2255 }
2256 op->minPicWidth = gf_bs_read_u16(bs);
2257 op->minPicHeight = gf_bs_read_u16(bs);
2258 op->maxPicWidth = gf_bs_read_u16(bs);
2259 op->maxPicHeight = gf_bs_read_u16(bs);
2260 op->maxChromaFormat = gf_bs_read_int(bs, 2);
2261 op->maxBitDepth = gf_bs_read_int(bs, 3) + 8;
2262 gf_bs_read_int(bs, 1);//reserved
2263 op->frame_rate_info_flag = gf_bs_read_int(bs, 1) ? GF_TRUE : GF_FALSE;
2264 op->bit_rate_info_flag = gf_bs_read_int(bs, 1) ? GF_TRUE : GF_FALSE;
2265 if (op->frame_rate_info_flag) {
2266 op->avgFrameRate = gf_bs_read_u16(bs);
2267 gf_bs_read_int(bs, 6); //reserved
2268 op->constantFrameRate = gf_bs_read_int(bs, 2);
2269 }
2270 if (op->bit_rate_info_flag) {
2271 op->maxBitRate = gf_bs_read_u32(bs);
2272 op->avgBitRate = gf_bs_read_u32(bs);
2273 }
2274 gf_list_add(ptr->operating_points, op);
2275 }
2276 count = gf_bs_read_u8(bs);
2277 for (i = 0; i < count; i++) {
2278 LHEVC_DependentLayer *dep;
2279 GF_SAFEALLOC(dep, LHEVC_DependentLayer);
2280 if (!dep) return GF_OUT_OF_MEM;
2281 dep->dependent_layerID = gf_bs_read_u8(bs);
2282 dep->num_layers_dependent_on = gf_bs_read_u8(bs);
2283 for (j = 0; j < dep->num_layers_dependent_on; j++)
2284 dep->dependent_on_layerID[j] = gf_bs_read_u8(bs);
2285 for (j = 0; j < 16; j++) {
2286 if (ptr->scalability_mask & (1 << j))
2287 dep->dimension_identifier[j] = gf_bs_read_u8(bs);
2288 }
2289 gf_list_add(ptr->dependency_layers, dep);
2290 }
2291
2292 return GF_OK;
2293 }
2294
gf_isom_oinf_write_entry(void * entry,GF_BitStream * bs)2295 GF_Err gf_isom_oinf_write_entry(void *entry, GF_BitStream *bs)
2296 {
2297 GF_OperatingPointsInformation* ptr = (GF_OperatingPointsInformation *)entry;
2298 u32 i, j, count;
2299 if (!ptr) return GF_OK;
2300
2301 gf_bs_write_u16(bs, ptr->scalability_mask);
2302 gf_bs_write_int(bs, 0xFF, 2);//reserved
2303 count = gf_list_count(ptr->profile_tier_levels);
2304 gf_bs_write_int(bs, count, 6);
2305 for (i = 0; i < count; i++) {
2306 LHEVC_ProfileTierLevel *ptl = (LHEVC_ProfileTierLevel *)gf_list_get(ptr->profile_tier_levels, i);
2307 gf_bs_write_int(bs, ptl->general_profile_space, 2);
2308 gf_bs_write_int(bs, ptl->general_tier_flag, 1);
2309 gf_bs_write_int(bs, ptl->general_profile_idc, 5);
2310 gf_bs_write_u32(bs, ptl->general_profile_compatibility_flags);
2311 gf_bs_write_long_int(bs, ptl->general_constraint_indicator_flags, 48);
2312 gf_bs_write_u8(bs, ptl->general_level_idc);
2313 }
2314 count = gf_list_count(ptr->operating_points);
2315 gf_bs_write_u16(bs, count);
2316 for (i = 0; i < count; i++) {
2317 LHEVC_OperatingPoint *op = (LHEVC_OperatingPoint *)gf_list_get(ptr->operating_points, i);;
2318 gf_bs_write_u16(bs, op->output_layer_set_idx);
2319 gf_bs_write_u8(bs, op->max_temporal_id);
2320 gf_bs_write_u8(bs, op->layer_count);
2321 for (j = 0; j < op->layer_count; j++) {
2322 gf_bs_write_u8(bs, op->layers_info[j].ptl_idx);
2323 gf_bs_write_int(bs, op->layers_info[j].layer_id, 6);
2324 op->layers_info[j].is_outputlayer ? gf_bs_write_int(bs, 0x1, 1) : gf_bs_write_int(bs, 0x0, 1);
2325 op->layers_info[j].is_alternate_outputlayer ? gf_bs_write_int(bs, 0x1, 1) : gf_bs_write_int(bs, 0x0, 1);
2326 }
2327 gf_bs_write_u16(bs, op->minPicWidth);
2328 gf_bs_write_u16(bs, op->minPicHeight);
2329 gf_bs_write_u16(bs, op->maxPicWidth);
2330 gf_bs_write_u16(bs, op->maxPicHeight);
2331 gf_bs_write_int(bs, op->maxChromaFormat, 2);
2332 gf_bs_write_int(bs, op->maxBitDepth - 8, 3);
2333 gf_bs_write_int(bs, 0x1, 1);//resereved
2334 op->frame_rate_info_flag ? gf_bs_write_int(bs, 0x1, 1) : gf_bs_write_int(bs, 0x0, 1);
2335 op->bit_rate_info_flag ? gf_bs_write_int(bs, 0x1, 1) : gf_bs_write_int(bs, 0x0, 1);
2336 if (op->frame_rate_info_flag) {
2337 gf_bs_write_u16(bs, op->avgFrameRate);
2338 gf_bs_write_int(bs, 0xFF, 6); //reserved
2339 gf_bs_write_int(bs, op->constantFrameRate, 2);
2340 }
2341 if (op->bit_rate_info_flag) {
2342 gf_bs_write_u32(bs, op->maxBitRate);
2343 gf_bs_write_u32(bs, op->avgBitRate);
2344 }
2345 }
2346 count = gf_list_count(ptr->dependency_layers);
2347 gf_bs_write_u8(bs, count);
2348 for (i = 0; i < count; i++) {
2349 LHEVC_DependentLayer *dep = (LHEVC_DependentLayer *)gf_list_get(ptr->dependency_layers, i);
2350 gf_bs_write_u8(bs, dep->dependent_layerID);
2351 gf_bs_write_u8(bs, dep->num_layers_dependent_on);
2352 for (j = 0; j < dep->num_layers_dependent_on; j++)
2353 gf_bs_write_u8(bs, dep->dependent_on_layerID[j]);
2354 for (j = 0; j < 16; j++) {
2355 if (ptr->scalability_mask & (1 << j))
2356 gf_bs_write_u8(bs, dep->dimension_identifier[j]);
2357 }
2358 }
2359
2360 return GF_OK;
2361 }
2362
gf_isom_oinf_size_entry(void * entry)2363 u32 gf_isom_oinf_size_entry(void *entry)
2364 {
2365 GF_OperatingPointsInformation* ptr = (GF_OperatingPointsInformation *)entry;
2366 u32 size = 0, i, j, count;
2367 if (!ptr) return 0;
2368
2369 size += 3; //scalability_mask + reserved + num_profile_tier_level
2370 count = gf_list_count(ptr->profile_tier_levels);
2371 size += count * 12; //general_profile_space + general_tier_flag + general_profile_idc + general_profile_compatibility_flags + general_constraint_indicator_flags + general_level_idc
2372 size += 2;//num_operating_points
2373 count = gf_list_count(ptr->operating_points);
2374 for (i = 0; i < count; i++) {
2375 LHEVC_OperatingPoint *op = (LHEVC_OperatingPoint *)gf_list_get(ptr->operating_points, i);;
2376 size += 2/*output_layer_set_idx*/ + 1/*max_temporal_id*/ + 1/*layer_count*/;
2377 size += op->layer_count * 2;
2378 size += 9;
2379 if (op->frame_rate_info_flag) {
2380 size += 3;
2381 }
2382 if (op->bit_rate_info_flag) {
2383 size += 8;
2384 }
2385 }
2386 size += 1;//max_layer_count
2387 count = gf_list_count(ptr->dependency_layers);
2388 for (i = 0; i < count; i++) {
2389 LHEVC_DependentLayer *dep = (LHEVC_DependentLayer *)gf_list_get(ptr->dependency_layers, i);
2390 size += 1/*dependent_layerID*/ + 1/*num_layers_dependent_on*/;
2391 size += dep->num_layers_dependent_on * 1;//dependent_on_layerID
2392 for (j = 0; j < 16; j++) {
2393 if (ptr->scalability_mask & (1 << j))
2394 size += 1;//dimension_identifier
2395 }
2396 }
2397 return size;
2398 }
2399
2400
gf_isom_linf_new_entry()2401 GF_LHVCLayerInformation *gf_isom_linf_new_entry()
2402 {
2403 GF_LHVCLayerInformation* ptr;
2404 GF_SAFEALLOC(ptr, GF_LHVCLayerInformation);
2405 if (ptr) ptr->num_layers_in_track = gf_list_new();
2406
2407 return ptr;
2408
2409 }
2410
gf_isom_linf_del_entry(void * entry)2411 void gf_isom_linf_del_entry(void *entry)
2412 {
2413 GF_LHVCLayerInformation* ptr = (GF_LHVCLayerInformation *)entry;
2414 if (!ptr) return;
2415 while (gf_list_count(ptr->num_layers_in_track)) {
2416 LHVCLayerInfoItem *li = (LHVCLayerInfoItem *)gf_list_get(ptr->num_layers_in_track, 0);
2417 gf_free(li);
2418 gf_list_rem(ptr->num_layers_in_track, 0);
2419 }
2420 gf_list_del(ptr->num_layers_in_track);
2421 gf_free(ptr);
2422 return;
2423 }
2424
gf_isom_linf_read_entry(void * entry,GF_BitStream * bs)2425 GF_Err gf_isom_linf_read_entry(void *entry, GF_BitStream *bs)
2426 {
2427 GF_LHVCLayerInformation* ptr = (GF_LHVCLayerInformation *)entry;
2428 u32 i, count;
2429
2430 if (!ptr) return GF_BAD_PARAM;
2431 gf_bs_read_int(bs, 2);
2432 count = gf_bs_read_int(bs, 6);
2433 for (i = 0; i < count; i++) {
2434 LHVCLayerInfoItem *li;
2435 GF_SAFEALLOC(li, LHVCLayerInfoItem);
2436 if (!li) return GF_OUT_OF_MEM;
2437 gf_bs_read_int(bs, 4);
2438 li->layer_id = gf_bs_read_int(bs, 6);
2439 li->min_TemporalId = gf_bs_read_int(bs, 3);
2440 li->max_TemporalId = gf_bs_read_int(bs, 3);
2441 gf_bs_read_int(bs, 1);
2442 li->sub_layer_presence_flags = gf_bs_read_int(bs, 7);
2443 gf_list_add(ptr->num_layers_in_track, li);
2444 }
2445 return GF_OK;
2446 }
2447
gf_isom_linf_write_entry(void * entry,GF_BitStream * bs)2448 GF_Err gf_isom_linf_write_entry(void *entry, GF_BitStream *bs)
2449 {
2450 GF_LHVCLayerInformation* ptr = (GF_LHVCLayerInformation *)entry;
2451 u32 i, count;
2452 if (!ptr) return GF_OK;
2453
2454 gf_bs_write_int(bs, 0, 2);
2455 count = gf_list_count(ptr->num_layers_in_track);
2456 gf_bs_write_int(bs, count, 6);
2457 for (i = 0; i < count; i++) {
2458 LHVCLayerInfoItem *li = (LHVCLayerInfoItem *)gf_list_get(ptr->num_layers_in_track, i);
2459 gf_bs_write_int(bs, 0, 4);
2460 gf_bs_write_int(bs, li->layer_id, 6);
2461 gf_bs_write_int(bs, li->min_TemporalId, 3);
2462 gf_bs_write_int(bs, li->max_TemporalId, 3);
2463 gf_bs_write_int(bs, 0, 1);
2464 gf_bs_write_int(bs, li->sub_layer_presence_flags, 7);
2465 }
2466 return GF_OK;
2467 }
2468
gf_isom_linf_size_entry(void * entry)2469 u32 gf_isom_linf_size_entry(void *entry)
2470 {
2471 GF_LHVCLayerInformation* ptr = (GF_LHVCLayerInformation *)entry;
2472 u32 size = 0, count;
2473 if (!ptr) return 0;
2474
2475 size += 1;
2476 count = gf_list_count(ptr->num_layers_in_track);
2477 size += count * 3;
2478 return size;
2479 }
2480
2481
2482 #endif /*GPAC_DISABLE_ISOM*/
2483