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