Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Jean Le Feuvre
5 : * Copyright (c) Telecom ParisTech 2000-2012
6 : * All rights reserved
7 : *
8 : * This file is part of GPAC / MPEG-4 ObjectDescriptor 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/odf_dev.h>
27 :
28 :
29 : //
30 : // Constructor
31 : //
32 7551 : GF_Descriptor *gf_odf_new_slc(u8 predef)
33 : {
34 7551 : GF_SLConfig *newDesc = (GF_SLConfig *) gf_malloc(sizeof(GF_SLConfig));
35 7551 : if (!newDesc) return NULL;
36 : memset(newDesc, 0, sizeof(GF_SLConfig));
37 7551 : newDesc->tag = GF_ODF_SLC_TAG;
38 7551 : newDesc->predefined = predef;
39 7551 : if (predef) gf_odf_slc_set_pref(newDesc);
40 7551 : newDesc->useTimestampsFlag = 1;
41 :
42 7551 : return (GF_Descriptor *)newDesc;
43 : }
44 :
45 : //
46 : // Destructor
47 : //
48 7547 : GF_Err gf_odf_del_slc(GF_SLConfig *sl)
49 : {
50 7547 : if (!sl) return GF_BAD_PARAM;
51 7547 : gf_free(sl);
52 7547 : return GF_OK;
53 : }
54 :
55 : //
56 : // Set the SL to the ISO predefined value
57 : //
58 : GF_EXPORT
59 6842 : GF_Err gf_odf_slc_set_pref(GF_SLConfig *sl)
60 : {
61 6842 : if (! sl) return GF_BAD_PARAM;
62 :
63 6842 : switch (sl->predefined) {
64 :
65 6842 : case SLPredef_MP4:
66 6842 : sl->useAccessUnitStartFlag = 0;
67 6842 : sl->useAccessUnitEndFlag = 0;
68 : //each packet is an AU, and we need RAP signaling
69 6842 : sl->useRandomAccessPointFlag = 1;
70 6842 : sl->hasRandomAccessUnitsOnlyFlag = 0;
71 6842 : sl->usePaddingFlag = 0;
72 : //in MP4 file, we use TimeStamps
73 6842 : sl->useTimestampsFlag = 1;
74 6842 : sl->useIdleFlag = 0;
75 6842 : sl->durationFlag = 0;
76 6842 : sl->timestampLength = 0;
77 6842 : sl->OCRLength = 0;
78 6842 : sl->AULength = 0;
79 6842 : sl->instantBitrateLength = 0;
80 6842 : sl->degradationPriorityLength = 0;
81 6842 : sl->AUSeqNumLength = 0;
82 6842 : sl->packetSeqNumLength = 0;
83 6842 : break;
84 :
85 0 : case SLPredef_Null:
86 0 : sl->useAccessUnitStartFlag = 0;
87 0 : sl->useAccessUnitEndFlag = 0;
88 0 : sl->useRandomAccessPointFlag = 0;
89 0 : sl->hasRandomAccessUnitsOnlyFlag = 0;
90 0 : sl->usePaddingFlag = 0;
91 0 : sl->useTimestampsFlag = 0;
92 0 : sl->useIdleFlag = 0;
93 0 : sl->AULength = 0;
94 0 : sl->degradationPriorityLength = 0;
95 0 : sl->AUSeqNumLength = 0;
96 0 : sl->packetSeqNumLength = 0;
97 :
98 : //for MPEG4 IP
99 0 : sl->timestampResolution = 1000;
100 0 : sl->timestampLength = 32;
101 0 : break;
102 : /*handle all unknown predefined as predef-null*/
103 0 : default:
104 0 : sl->useAccessUnitStartFlag = 0;
105 0 : sl->useAccessUnitEndFlag = 0;
106 0 : sl->useRandomAccessPointFlag = 0;
107 0 : sl->hasRandomAccessUnitsOnlyFlag = 0;
108 0 : sl->usePaddingFlag = 0;
109 0 : sl->useTimestampsFlag = 1;
110 0 : sl->useIdleFlag = 0;
111 0 : sl->AULength = 0;
112 0 : sl->degradationPriorityLength = 0;
113 0 : sl->AUSeqNumLength = 0;
114 0 : sl->packetSeqNumLength = 0;
115 :
116 0 : sl->timestampResolution = 1000;
117 0 : sl->timestampLength = 32;
118 0 : break;
119 : }
120 :
121 : return GF_OK;
122 : }
123 :
124 :
125 : //this function gets the real amount of bytes needed to store the timeStamp
126 : static u32 GetTSbytesLen(GF_SLConfig *sl)
127 : {
128 : u32 TSlen, TSbytes;
129 : if (! sl) return 0;
130 :
131 16 : TSlen = sl->timestampLength * 2;
132 16 : TSbytes = TSlen / 8;
133 16 : TSlen = TSlen % 8;
134 16 : if (TSlen) TSbytes += 1;
135 : return TSbytes;
136 : }
137 :
138 : //
139 : // Reader
140 : //
141 3893 : GF_Err gf_odf_read_slc(GF_BitStream *bs, GF_SLConfig *sl, u32 DescSize)
142 : {
143 : GF_Err e;
144 : u32 nbBytes = 0;
145 :
146 3893 : if (!sl) return GF_BAD_PARAM;
147 :
148 : //APPLE fix
149 3893 : if (!DescSize) {
150 0 : sl->predefined = SLPredef_MP4;
151 0 : return gf_odf_slc_set_pref(sl);
152 : }
153 :
154 3893 : sl->predefined = gf_bs_read_int(bs, 8);
155 : nbBytes += 1;
156 :
157 : /*MPEG4 IP fix*/
158 3893 : if (!sl->predefined && nbBytes==DescSize) {
159 0 : sl->predefined = SLPredef_Null;
160 0 : gf_odf_slc_set_pref(sl);
161 0 : return GF_OK;
162 : }
163 :
164 3893 : if (sl->predefined) {
165 : //predefined configuration
166 3367 : e = gf_odf_slc_set_pref(sl);
167 3367 : if (e) return e;
168 : } else {
169 526 : sl->useAccessUnitStartFlag = gf_bs_read_int(bs, 1);
170 526 : sl->useAccessUnitEndFlag = gf_bs_read_int(bs, 1);
171 526 : sl->useRandomAccessPointFlag = gf_bs_read_int(bs, 1);
172 526 : sl->hasRandomAccessUnitsOnlyFlag = gf_bs_read_int(bs, 1);
173 526 : sl->usePaddingFlag = gf_bs_read_int(bs, 1);
174 526 : sl->useTimestampsFlag = gf_bs_read_int(bs, 1);
175 526 : sl->useIdleFlag = gf_bs_read_int(bs, 1);
176 526 : sl->durationFlag = gf_bs_read_int(bs, 1);
177 526 : sl->timestampResolution = gf_bs_read_int(bs, 32);
178 526 : sl->OCRResolution = gf_bs_read_int(bs, 32);
179 :
180 526 : sl->timestampLength = gf_bs_read_int(bs, 8);
181 526 : if (sl->timestampLength > 64) return GF_ODF_INVALID_DESCRIPTOR;
182 :
183 526 : sl->OCRLength = gf_bs_read_int(bs, 8);
184 526 : if (sl->OCRLength > 64) return GF_ODF_INVALID_DESCRIPTOR;
185 :
186 526 : sl->AULength = gf_bs_read_int(bs, 8);
187 526 : if (sl->AULength > 32) return GF_ODF_INVALID_DESCRIPTOR;
188 :
189 526 : sl->instantBitrateLength = gf_bs_read_int(bs, 8);
190 526 : sl->degradationPriorityLength = gf_bs_read_int(bs, 4);
191 526 : sl->AUSeqNumLength = gf_bs_read_int(bs, 5);
192 526 : if (sl->AUSeqNumLength > 16) return GF_ODF_INVALID_DESCRIPTOR;
193 526 : sl->packetSeqNumLength = gf_bs_read_int(bs, 5);
194 526 : if (sl->packetSeqNumLength > 16) return GF_ODF_INVALID_DESCRIPTOR;
195 :
196 526 : /*reserved = */gf_bs_read_int(bs, 2);
197 : nbBytes += 15;
198 : }
199 :
200 3893 : if (sl->durationFlag) {
201 0 : sl->timeScale = gf_bs_read_int(bs, 32);
202 0 : sl->AUDuration = gf_bs_read_int(bs, 16);
203 0 : sl->CUDuration = gf_bs_read_int(bs, 16);
204 0 : nbBytes += 8;
205 : }
206 3893 : if (! sl->useTimestampsFlag) {
207 8 : sl->startDTS = gf_bs_read_long_int(bs, sl->timestampLength);
208 8 : sl->startCTS = gf_bs_read_long_int(bs, sl->timestampLength);
209 8 : nbBytes += GetTSbytesLen(sl);
210 : }
211 :
212 3893 : if (DescSize != nbBytes) return GF_ODF_INVALID_DESCRIPTOR;
213 3893 : return GF_OK;
214 : }
215 :
216 :
217 : //
218 : // Size
219 : //
220 9894 : GF_Err gf_odf_size_slc(GF_SLConfig *sl, u32 *outSize)
221 : {
222 9894 : if (! sl) return GF_BAD_PARAM;
223 :
224 9894 : *outSize = 1;
225 9894 : if (! sl->predefined) *outSize += 15;
226 9894 : if (sl->durationFlag) *outSize += 8;
227 9902 : if (! sl->useTimestampsFlag) *outSize += GetTSbytesLen(sl);
228 : return GF_OK;
229 : }
230 :
231 : //
232 : // Writer
233 : //
234 3778 : GF_Err gf_odf_write_slc(GF_BitStream *bs, GF_SLConfig *sl)
235 : {
236 : GF_Err e;
237 : u32 size;
238 3778 : if (! sl) return GF_BAD_PARAM;
239 :
240 3778 : e = gf_odf_size_descriptor((GF_Descriptor *)sl, &size);
241 3778 : if (e) return e;
242 3778 : e = gf_odf_write_base_descriptor(bs, sl->tag, size);
243 3778 : if (e) return e;
244 :
245 3778 : gf_bs_write_int(bs, sl->predefined, 8);
246 3778 : if (! sl->predefined) {
247 548 : gf_bs_write_int(bs, sl->useAccessUnitStartFlag, 1);
248 548 : gf_bs_write_int(bs, sl->useAccessUnitEndFlag, 1);
249 548 : gf_bs_write_int(bs, sl->useRandomAccessPointFlag, 1);
250 548 : gf_bs_write_int(bs, sl->hasRandomAccessUnitsOnlyFlag, 1);
251 548 : gf_bs_write_int(bs, sl->usePaddingFlag, 1);
252 548 : gf_bs_write_int(bs, sl->useTimestampsFlag, 1);
253 548 : gf_bs_write_int(bs, sl->useIdleFlag, 1);
254 548 : gf_bs_write_int(bs, sl->durationFlag, 1);
255 548 : gf_bs_write_int(bs, sl->timestampResolution, 32);
256 548 : gf_bs_write_int(bs, sl->OCRResolution, 32);
257 548 : gf_bs_write_int(bs, sl->timestampLength, 8);
258 548 : gf_bs_write_int(bs, sl->OCRLength, 8);
259 548 : gf_bs_write_int(bs, sl->AULength, 8);
260 548 : gf_bs_write_int(bs, sl->instantBitrateLength, 8);
261 548 : gf_bs_write_int(bs, sl->degradationPriorityLength, 4);
262 548 : gf_bs_write_int(bs, sl->AUSeqNumLength, 5);
263 548 : gf_bs_write_int(bs, sl->packetSeqNumLength, 5);
264 548 : gf_bs_write_int(bs, 3, 2); //reserved: 0b11 == 3
265 : }
266 3778 : if (sl->durationFlag) {
267 0 : gf_bs_write_int(bs, sl->timeScale, 32);
268 0 : gf_bs_write_int(bs, sl->AUDuration, 16);
269 0 : gf_bs_write_int(bs, sl->CUDuration, 16);
270 : }
271 3778 : if (! sl->useTimestampsFlag) {
272 8 : gf_bs_write_long_int(bs, sl->startDTS, sl->timestampLength);
273 8 : gf_bs_write_long_int(bs, sl->startCTS, sl->timestampLength);
274 : }
275 :
276 : return GF_OK;
277 : }
278 :
279 :
280 : /*allocates and writes the SL-PDU (Header + PDU) given the SLConfig and the GF_SLHeader
281 : for this PDU. AUs must be split in PDUs by another process if needed (packetizer).*/
282 : GF_EXPORT
283 2 : void gf_sl_packetize(GF_SLConfig* slConfig,
284 : GF_SLHeader *Header,
285 : u8 *PDU,
286 : u32 size,
287 : u8 **outPacket,
288 : u32 *OutSize)
289 : {
290 2 : GF_BitStream *bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
291 2 : *OutSize = 0;
292 2 : if (!bs) return;
293 :
294 2 : if (slConfig->useAccessUnitStartFlag) gf_bs_write_int(bs, Header->accessUnitStartFlag, 1);
295 2 : if (slConfig->useAccessUnitEndFlag) gf_bs_write_int(bs, Header->accessUnitEndFlag, 1);
296 2 : if (slConfig->OCRLength > 0) gf_bs_write_int(bs, Header->OCRflag, 1);
297 2 : if (slConfig->useIdleFlag) gf_bs_write_int(bs, Header->idleFlag, 1);
298 2 : if (slConfig->usePaddingFlag) {
299 0 : gf_bs_write_int(bs, Header->paddingFlag, 1);
300 0 : if (Header->paddingFlag) gf_bs_write_int(bs, Header->paddingBits, 3);
301 : }
302 2 : if (! Header->idleFlag && (! Header->paddingFlag || Header->paddingBits != 0)) {
303 2 : if (slConfig->packetSeqNumLength > 0) gf_bs_write_int(bs, Header->packetSequenceNumber, slConfig->packetSeqNumLength);
304 2 : if (slConfig->degradationPriorityLength > 0) {
305 0 : gf_bs_write_int(bs, Header->degradationPriorityFlag, 1);
306 0 : if (Header->degradationPriorityFlag) gf_bs_write_int(bs, Header->degradationPriority, slConfig->degradationPriorityLength);
307 : }
308 2 : if (Header->OCRflag) gf_bs_write_long_int(bs, Header->objectClockReference, slConfig->OCRLength);
309 2 : if (Header->accessUnitStartFlag) {
310 2 : if (slConfig->useRandomAccessPointFlag) gf_bs_write_int(bs, Header->randomAccessPointFlag, 1);
311 2 : if (slConfig->AUSeqNumLength > 0) gf_bs_write_int(bs, Header->AU_sequenceNumber, slConfig->AUSeqNumLength);
312 2 : if (slConfig->useTimestampsFlag) {
313 2 : gf_bs_write_int(bs, Header->decodingTimeStampFlag, 1);
314 2 : gf_bs_write_int(bs, Header->compositionTimeStampFlag, 1);
315 : }
316 2 : if (slConfig->instantBitrateLength > 0) gf_bs_write_int(bs, Header->instantBitrateFlag, 1);
317 2 : if (Header->decodingTimeStampFlag) gf_bs_write_long_int(bs, Header->decodingTimeStamp, slConfig->timestampLength);
318 2 : if (Header->compositionTimeStampFlag) gf_bs_write_long_int(bs, Header->compositionTimeStamp, slConfig->timestampLength);
319 2 : if (slConfig->AULength > 0) gf_bs_write_int(bs, Header->accessUnitLength, slConfig->AULength);
320 2 : if (Header->instantBitrateFlag) gf_bs_write_int(bs, Header->instantBitrate, slConfig->instantBitrateLength);
321 : }
322 : }
323 : /*done with the Header, Alin*/
324 2 : gf_bs_align(bs);
325 :
326 : /*write the PDU - already byte aligned with stuffing (paddingBits in SL Header)*/
327 2 : if (PDU && size)
328 0 : gf_bs_write_data(bs, PDU, size);
329 :
330 2 : gf_bs_align(bs);
331 2 : gf_bs_get_content(bs, outPacket, OutSize);
332 2 : gf_bs_del(bs);
333 : }
334 :
335 : /*allocates and writes the SL-PDU (Header + PDU) given the SLConfig and the GF_SLHeader
336 : for this PDU. AUs must be split in PDUs by another process if needed (packetizer).*/
337 : GF_EXPORT
338 2 : u32 gf_sl_get_header_size(GF_SLConfig* slConfig, GF_SLHeader *Header)
339 : {
340 : u32 nb_bits = 0;
341 :
342 2 : if (slConfig->useAccessUnitStartFlag) nb_bits++;
343 2 : if (slConfig->useAccessUnitEndFlag) nb_bits++;
344 2 : if (slConfig->OCRLength > 0) nb_bits++;
345 2 : if (slConfig->useIdleFlag) nb_bits++;
346 2 : if (slConfig->usePaddingFlag) {
347 0 : nb_bits++;
348 0 : if (Header->paddingFlag) nb_bits+=3;
349 : }
350 2 : if (!Header->idleFlag && (! Header->paddingFlag || Header->paddingBits != 0)) {
351 2 : if (slConfig->packetSeqNumLength > 0) nb_bits += slConfig->packetSeqNumLength;
352 2 : if (slConfig->degradationPriorityLength > 0) {
353 0 : nb_bits++;
354 0 : if (Header->degradationPriorityFlag) nb_bits += slConfig->degradationPriorityLength;
355 : }
356 2 : if (Header->OCRflag) nb_bits += slConfig->OCRLength;
357 2 : if (Header->accessUnitStartFlag) {
358 2 : if (slConfig->useRandomAccessPointFlag) nb_bits++;
359 2 : if (slConfig->AUSeqNumLength > 0) nb_bits += slConfig->AUSeqNumLength;
360 2 : if (slConfig->useTimestampsFlag) {
361 : nb_bits++;
362 2 : nb_bits++;
363 : }
364 2 : if (slConfig->instantBitrateLength > 0) nb_bits++;
365 2 : if (Header->decodingTimeStampFlag) nb_bits += slConfig->timestampLength;
366 2 : if (Header->compositionTimeStampFlag) nb_bits += slConfig->timestampLength;
367 2 : if (slConfig->AULength > 0) nb_bits += slConfig->AULength;
368 2 : if (Header->instantBitrateFlag) nb_bits += slConfig->instantBitrateLength;
369 : }
370 : }
371 4 : while (nb_bits%8) nb_bits++;
372 2 : return nb_bits/8;
373 : }
374 :
375 :
376 : GF_EXPORT
377 2 : void gf_sl_depacketize (GF_SLConfig *slConfig, GF_SLHeader *Header, const u8 *PDU, u32 PDULength, u32 *HeaderLen)
378 : {
379 : GF_BitStream *bs;
380 2 : *HeaderLen = 0;
381 2 : if (!Header) return;
382 : //reset the input header
383 : memset(Header, 0, sizeof(GF_SLHeader));
384 :
385 2 : bs = gf_bs_new(PDU, PDULength, GF_BITSTREAM_READ);
386 2 : if (!bs) return;
387 :
388 2 : if (slConfig->useAccessUnitStartFlag) Header->accessUnitStartFlag = gf_bs_read_int(bs, 1);
389 2 : if (slConfig->useAccessUnitEndFlag) Header->accessUnitEndFlag = gf_bs_read_int(bs, 1);
390 2 : if ( !slConfig->useAccessUnitStartFlag && !slConfig->useAccessUnitEndFlag) {
391 0 : Header->accessUnitStartFlag = 1;
392 0 : Header->accessUnitEndFlag = 1;
393 : }
394 2 : if (slConfig->OCRLength > 0) Header->OCRflag = gf_bs_read_int(bs, 1);
395 2 : if (slConfig->useIdleFlag) Header->idleFlag = gf_bs_read_int(bs, 1);
396 2 : if (slConfig->usePaddingFlag) {
397 0 : Header->paddingFlag = gf_bs_read_int(bs, 1);
398 0 : if (Header->paddingFlag) Header->paddingBits = gf_bs_read_int(bs, 3);
399 : }
400 2 : if (!Header->paddingFlag || (Header->paddingBits != 0)) {
401 :
402 2 : if (slConfig->packetSeqNumLength > 0) Header->packetSequenceNumber = gf_bs_read_int(bs, slConfig->packetSeqNumLength);
403 2 : if (slConfig->degradationPriorityLength > 0) {
404 0 : Header->degradationPriorityFlag = gf_bs_read_int(bs, 1);
405 0 : if (Header->degradationPriorityFlag) Header->degradationPriority = gf_bs_read_int(bs, slConfig->degradationPriorityLength);
406 : }
407 2 : if (Header->OCRflag) Header->objectClockReference = gf_bs_read_long_int(bs, slConfig->OCRLength);
408 2 : if (Header->accessUnitStartFlag) {
409 2 : if (slConfig->useRandomAccessPointFlag) Header->randomAccessPointFlag = gf_bs_read_int(bs, 1);
410 2 : if (slConfig->AUSeqNumLength > 0) Header->AU_sequenceNumber = gf_bs_read_int(bs, slConfig->AUSeqNumLength);
411 2 : if (slConfig->useTimestampsFlag) {
412 2 : Header->decodingTimeStampFlag = gf_bs_read_int(bs, 1);
413 2 : Header->compositionTimeStampFlag = gf_bs_read_int(bs, 1);
414 : }
415 2 : if (slConfig->instantBitrateLength > 0) Header->instantBitrateFlag = gf_bs_read_int(bs, 1);
416 2 : if (Header->decodingTimeStampFlag) Header->decodingTimeStamp = gf_bs_read_long_int(bs, slConfig->timestampLength);
417 2 : if (Header->compositionTimeStampFlag) Header->compositionTimeStamp = gf_bs_read_long_int(bs, slConfig->timestampLength);
418 2 : if (slConfig->AULength > 0) Header->accessUnitLength = gf_bs_read_int(bs, slConfig->AULength);
419 2 : if (Header->instantBitrateFlag) Header->instantBitrate = gf_bs_read_int(bs, slConfig->instantBitrateLength);
420 : }
421 : }
422 2 : gf_bs_align(bs);
423 2 : *HeaderLen = (u32) gf_bs_get_position(bs);
424 2 : gf_bs_del(bs);
425 : }
|