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