Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Jean Le Feuvre
5 : * Copyright (c) Telecom ParisTech 2000-2021
6 : * All rights reserved
7 : *
8 : * This file is part of GPAC / ISO Media File Format sub-project
9 : *
10 : * GPAC is free software; you can redistribute it and/or modify
11 : * it under the terms of the GNU Lesser General Public License as published by
12 : * the Free Software Foundation; either version 2, or (at your option)
13 : * any later version.
14 : *
15 : * GPAC is distributed in the hope that it will be useful,
16 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : * GNU Lesser General Public License for more details.
19 : *
20 : * You should have received a copy of the GNU Lesser General Public
21 : * License along with this library; see the file COPYING. If not, write to
22 : * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23 : *
24 : */
25 :
26 : #include <gpac/internal/isomedia_dev.h>
27 :
28 : #if !defined(GPAC_DISABLE_ISOM) && !defined(GPAC_DISABLE_ISOM_HINTING)
29 :
30 135 : GF_Box *ghnt_box_new()
31 : {
32 : GF_HintSampleEntryBox *tmp;
33 135 : GF_SAFEALLOC(tmp, GF_HintSampleEntryBox);
34 135 : if (!tmp) return NULL;
35 135 : gf_isom_sample_entry_init((GF_SampleEntryBox *)tmp);
36 :
37 : //this type is used internally for protocols that share the same base entry
38 : //currently only RTP uses this, but a flexMux could use this entry too...
39 135 : tmp->type = GF_ISOM_BOX_TYPE_GHNT;
40 135 : tmp->HintTrackVersion = 1;
41 135 : tmp->LastCompatibleVersion = 1;
42 135 : return (GF_Box *)tmp;
43 : }
44 :
45 135 : void ghnt_box_del(GF_Box *s)
46 : {
47 : GF_HintSampleEntryBox *ptr;
48 :
49 135 : gf_isom_sample_entry_predestroy((GF_SampleEntryBox *)s);
50 : ptr = (GF_HintSampleEntryBox *)s;
51 135 : if (ptr->hint_sample) gf_isom_hint_sample_del(ptr->hint_sample);
52 135 : gf_free(ptr);
53 135 : }
54 :
55 51 : GF_Err ghnt_box_read(GF_Box *s, GF_BitStream *bs)
56 : {
57 : GF_Err e;
58 : GF_HintSampleEntryBox *ptr = (GF_HintSampleEntryBox *)s;
59 51 : if (ptr == NULL) return GF_BAD_PARAM;
60 :
61 : //sample entry + 4 bytes in box
62 51 : ISOM_DECREASE_SIZE(ptr, 12)
63 :
64 51 : e = gf_isom_base_sample_entry_read((GF_SampleEntryBox *)ptr, bs);
65 51 : if (e) return e;
66 :
67 51 : ptr->HintTrackVersion = gf_bs_read_u16(bs);
68 51 : ptr->LastCompatibleVersion = gf_bs_read_u16(bs);
69 :
70 51 : if ((s->type == GF_ISOM_BOX_TYPE_RTP_STSD) || (s->type == GF_ISOM_BOX_TYPE_SRTP_STSD) || (s->type == GF_ISOM_BOX_TYPE_RRTP_STSD) || (s->type == GF_ISOM_BOX_TYPE_RTCP_STSD)) {
71 50 : ISOM_DECREASE_SIZE(ptr, 4)
72 50 : ptr->MaxPacketSize = gf_bs_read_u32(bs);
73 1 : } else if (s->type == GF_ISOM_BOX_TYPE_FDP_STSD) {
74 1 : ISOM_DECREASE_SIZE(ptr, 4)
75 1 : ptr->partition_entry_ID = gf_bs_read_u16(bs);
76 1 : ptr->FEC_overhead = gf_bs_read_u16(bs);
77 :
78 : }
79 51 : return gf_isom_box_array_read(s, bs);
80 : }
81 :
82 : #ifndef GPAC_DISABLE_ISOM_WRITE
83 :
84 79 : GF_Err ghnt_box_write(GF_Box *s, GF_BitStream *bs)
85 : {
86 : GF_Err e;
87 : GF_HintSampleEntryBox *ptr = (GF_HintSampleEntryBox *)s;
88 :
89 79 : e = gf_isom_box_write_header(s, bs);
90 79 : if (e) return e;
91 79 : gf_bs_write_data(bs, ptr->reserved, 6);
92 79 : gf_bs_write_u16(bs, ptr->dataReferenceIndex);
93 79 : gf_bs_write_u16(bs, ptr->HintTrackVersion);
94 79 : gf_bs_write_u16(bs, ptr->LastCompatibleVersion);
95 79 : gf_bs_write_u32(bs, ptr->MaxPacketSize);
96 79 : return GF_OK;
97 : }
98 :
99 225 : GF_Err ghnt_box_size(GF_Box *s)
100 : {
101 : GF_HintSampleEntryBox *ptr = (GF_HintSampleEntryBox *)s;
102 225 : ptr->size += 16;
103 225 : return GF_OK;
104 : }
105 :
106 :
107 : #endif /*GPAC_DISABLE_ISOM_WRITE*/
108 :
109 :
110 59555 : GF_HintSample *gf_isom_hint_sample_new(u32 ProtocolType)
111 : {
112 : GF_HintSample *tmp;
113 59555 : switch (ProtocolType) {
114 : case GF_ISOM_BOX_TYPE_RTP_STSD:
115 : case GF_ISOM_BOX_TYPE_SRTP_STSD:
116 : case GF_ISOM_BOX_TYPE_RRTP_STSD:
117 : case GF_ISOM_BOX_TYPE_RTCP_STSD:
118 : break;
119 0 : case GF_ISOM_BOX_TYPE_FDP_STSD:
120 0 : return (GF_HintSample *) gf_isom_box_new(GF_ISOM_BOX_TYPE_FDSA);
121 : break;
122 : default:
123 : return NULL;
124 : }
125 59555 : GF_SAFEALLOC(tmp, GF_HintSample);
126 59555 : if (!tmp) return NULL;
127 59555 : tmp->packetTable = gf_list_new();
128 59555 : tmp->hint_subtype = ProtocolType;
129 59555 : return tmp;
130 : }
131 :
132 59555 : void gf_isom_hint_sample_del(GF_HintSample *ptr)
133 : {
134 59555 : if (ptr->hint_subtype==GF_ISOM_BOX_TYPE_FDP_STSD) {
135 0 : gf_isom_box_del((GF_Box*)ptr);
136 0 : return;
137 : }
138 :
139 128077 : while (gf_list_count(ptr->packetTable)) {
140 68522 : GF_HintPacket *pck = (GF_HintPacket *)gf_list_get(ptr->packetTable, 0);
141 68522 : gf_isom_hint_pck_del(pck);
142 68522 : gf_list_rem(ptr->packetTable, 0);
143 : }
144 59555 : gf_list_del(ptr->packetTable);
145 59555 : if (ptr->AdditionalData) gf_free(ptr->AdditionalData);
146 :
147 59555 : if (ptr->sample_cache) {
148 0 : while (gf_list_count(ptr->sample_cache)) {
149 0 : GF_HintDataCache *hdc = (GF_HintDataCache *)gf_list_get(ptr->sample_cache, 0);
150 0 : gf_list_rem(ptr->sample_cache, 0);
151 0 : if (hdc->samp) gf_isom_sample_del(&hdc->samp);
152 0 : gf_free(hdc);
153 : }
154 0 : gf_list_del(ptr->sample_cache);
155 : }
156 59555 : if (ptr->extra_data)
157 0 : gf_isom_box_del((GF_Box*)ptr->extra_data);
158 59555 : if (ptr->child_boxes)
159 0 : gf_isom_box_array_del(ptr->child_boxes);
160 :
161 59555 : gf_free(ptr);
162 : }
163 :
164 385 : GF_Err gf_isom_hint_sample_read(GF_HintSample *ptr, GF_BitStream *bs, u32 sampleSize)
165 : {
166 : u16 i;
167 : u32 type;
168 : GF_Err e;
169 : #ifndef GPAC_DISABLE_LOG
170 385 : char *szName = (ptr->hint_subtype==GF_ISOM_BOX_TYPE_RTCP_STSD) ? "RTCP" : "RTP";
171 : #endif
172 : u64 sizeIn, sizeOut;
173 :
174 385 : sizeIn = gf_bs_available(bs);
175 :
176 385 : switch (ptr->hint_subtype) {
177 : case GF_ISOM_BOX_TYPE_RTP_STSD:
178 : case GF_ISOM_BOX_TYPE_SRTP_STSD:
179 : case GF_ISOM_BOX_TYPE_RRTP_STSD:
180 : case GF_ISOM_BOX_TYPE_RTCP_STSD:
181 : break;
182 0 : case GF_ISOM_BOX_TYPE_FDP_STSD:
183 0 : ptr->size = gf_bs_read_u32(bs);
184 0 : type = gf_bs_read_u32(bs);
185 0 : if (type != GF_ISOM_BOX_TYPE_FDSA) {
186 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso] invalid FDT sample, top box type %s not fdsa\n", gf_4cc_to_str(type) ));
187 : return GF_ISOM_INVALID_MEDIA;
188 : }
189 0 : return gf_isom_box_read((GF_Box*)ptr, bs);
190 : default:
191 : return GF_NOT_SUPPORTED;
192 : }
193 :
194 385 : ptr->packetCount = gf_bs_read_u16(bs);
195 385 : ptr->reserved = gf_bs_read_u16(bs);
196 385 : if (ptr->packetCount>=sampleSize) {
197 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso] broken %s sample: %d packet_count indicated but only %d bytes in samples\n", szName, ptr->packetCount, sampleSize));
198 : return GF_ISOM_INVALID_MEDIA;
199 : }
200 :
201 385 : for (i = 0; i < ptr->packetCount; i++) {
202 : GF_HintPacket *pck;
203 385 : if (! gf_bs_available(bs) ) {
204 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso] %s hint sample has no more data but still %d entries to read\n", szName, ptr->packetCount-i));
205 : return GF_ISOM_INVALID_MEDIA;
206 : }
207 385 : pck = gf_isom_hint_pck_new(ptr->hint_subtype);
208 385 : pck->trackID = ptr->trackID;
209 385 : pck->sampleNumber = ptr->sampleNumber;
210 385 : gf_list_add(ptr->packetTable, pck);
211 :
212 385 : e = gf_isom_hint_pck_read(pck, bs);
213 385 : if (e) return e;
214 : }
215 :
216 385 : if (ptr->hint_subtype==GF_ISOM_BOX_TYPE_RTCP_STSD) return GF_OK;
217 :
218 :
219 385 : sizeOut = gf_bs_available(bs) - sizeIn;
220 :
221 : //do we have some more data after the packets ??
222 385 : if ((u32)sizeOut < sampleSize) {
223 0 : ptr->dataLength = sampleSize - (u32)sizeOut;
224 0 : ptr->AdditionalData = (char*)gf_malloc(sizeof(char) * ptr->dataLength);
225 0 : if (!ptr->AdditionalData) return GF_OUT_OF_MEM;
226 0 : gf_bs_read_data(bs, ptr->AdditionalData, ptr->dataLength);
227 : }
228 : return GF_OK;
229 : }
230 :
231 :
232 : #ifndef GPAC_DISABLE_ISOM_WRITE
233 :
234 59170 : GF_Err gf_isom_hint_sample_write(GF_HintSample *ptr, GF_BitStream *bs)
235 : {
236 : u32 count, i;
237 : GF_Err e;
238 :
239 59170 : if (ptr->hint_subtype==GF_ISOM_BOX_TYPE_FDP_STSD) {
240 0 : e = gf_isom_box_size((GF_Box*)ptr);
241 0 : if (!e) e = gf_isom_box_write((GF_Box*)ptr, bs);
242 : return e;
243 : }
244 :
245 59170 : count = gf_list_count(ptr->packetTable);
246 59170 : gf_bs_write_u16(bs, count);
247 59170 : gf_bs_write_u16(bs, ptr->reserved);
248 : //write the packet table
249 127307 : for (i=0; i<count; i++) {
250 68137 : GF_HintPacket *pck = (GF_HintPacket *)gf_list_get(ptr->packetTable, i);
251 68137 : e = gf_isom_hint_pck_write(pck, bs);
252 68137 : if (e) return e;
253 : }
254 : //write additional data
255 59170 : if (ptr->AdditionalData) {
256 83 : gf_bs_write_data(bs, ptr->AdditionalData, ptr->dataLength);
257 : }
258 : return GF_OK;
259 : }
260 :
261 :
262 59170 : u32 gf_isom_hint_sample_size(GF_HintSample *ptr)
263 : {
264 : u32 size, count, i;
265 59170 : if (ptr->hint_subtype==GF_ISOM_BOX_TYPE_FDP_STSD) {
266 0 : gf_isom_box_size((GF_Box*)ptr);
267 0 : size = (u32) ptr->size;
268 : } else {
269 : size = 4;
270 59170 : count = gf_list_count(ptr->packetTable);
271 127307 : for (i=0; i<count; i++) {
272 68137 : GF_HintPacket *pck = (GF_HintPacket *)gf_list_get(ptr->packetTable, i);
273 68137 : size += gf_isom_hint_pck_size(pck);
274 : }
275 59170 : size += ptr->dataLength;
276 : }
277 59170 : return size;
278 : }
279 :
280 : #endif /*GPAC_DISABLE_ISOM_WRITE*/
281 :
282 :
283 : GF_EXPORT
284 68523 : GF_HintPacket *gf_isom_hint_pck_new(u32 HintType)
285 : {
286 : GF_HintPacket *pck;
287 68523 : switch (HintType) {
288 68522 : case GF_ISOM_BOX_TYPE_RTP_STSD:
289 : case GF_ISOM_BOX_TYPE_SRTP_STSD:
290 : case GF_ISOM_BOX_TYPE_RRTP_STSD:
291 68522 : pck = (GF_HintPacket *) gf_isom_hint_rtp_new();
292 68522 : if (pck) pck->hint_subtype = HintType;
293 : return pck;
294 1 : case GF_ISOM_BOX_TYPE_RTCP_STSD:
295 1 : pck = (GF_HintPacket *) gf_isom_hint_rtcp_new();
296 1 : if (pck) pck->hint_subtype = HintType;
297 : return pck;
298 : default:
299 : return NULL;
300 : }
301 : }
302 :
303 : GF_EXPORT
304 68523 : void gf_isom_hint_pck_del(GF_HintPacket *ptr)
305 : {
306 68523 : if (!ptr) return;
307 68523 : switch (ptr->hint_subtype) {
308 68522 : case GF_ISOM_BOX_TYPE_RTP_STSD:
309 : case GF_ISOM_BOX_TYPE_SRTP_STSD:
310 : case GF_ISOM_BOX_TYPE_RRTP_STSD:
311 68522 : gf_isom_hint_rtp_del((GF_RTPPacket *)ptr);
312 68522 : break;
313 1 : case GF_ISOM_BOX_TYPE_RTCP_STSD:
314 1 : gf_isom_hint_rtcp_del((GF_RTCPPacket *)ptr);
315 1 : break;
316 : default:
317 : break;
318 : }
319 : }
320 :
321 : GF_EXPORT
322 386 : GF_Err gf_isom_hint_pck_read(GF_HintPacket *ptr, GF_BitStream *bs)
323 : {
324 386 : if (!ptr) return GF_BAD_PARAM;
325 386 : switch (ptr->hint_subtype) {
326 385 : case GF_ISOM_BOX_TYPE_RTP_STSD:
327 : case GF_ISOM_BOX_TYPE_SRTP_STSD:
328 : case GF_ISOM_BOX_TYPE_RRTP_STSD:
329 385 : return gf_isom_hint_rtp_read((GF_RTPPacket *)ptr, bs);
330 1 : case GF_ISOM_BOX_TYPE_RTCP_STSD:
331 1 : return gf_isom_hint_rtcp_read((GF_RTCPPacket *)ptr, bs);
332 : default:
333 : return GF_NOT_SUPPORTED;
334 : }
335 : }
336 :
337 : #ifndef GPAC_DISABLE_ISOM_WRITE
338 :
339 : GF_EXPORT
340 68138 : GF_Err gf_isom_hint_pck_write(GF_HintPacket *ptr, GF_BitStream *bs)
341 : {
342 68138 : if (!ptr) return GF_BAD_PARAM;
343 68138 : switch (ptr->hint_subtype) {
344 68137 : case GF_ISOM_BOX_TYPE_RTP_STSD:
345 : case GF_ISOM_BOX_TYPE_SRTP_STSD:
346 : case GF_ISOM_BOX_TYPE_RRTP_STSD:
347 68137 : return gf_isom_hint_rtp_write((GF_RTPPacket *)ptr, bs);
348 1 : case GF_ISOM_BOX_TYPE_RTCP_STSD:
349 1 : return gf_isom_hint_rtcp_write((GF_RTCPPacket *)ptr, bs);
350 : default:
351 : return GF_NOT_SUPPORTED;
352 : }
353 : }
354 :
355 : GF_EXPORT
356 68138 : u32 gf_isom_hint_pck_size(GF_HintPacket *ptr)
357 : {
358 68138 : if (!ptr) return GF_BAD_PARAM;
359 68138 : switch (ptr->hint_subtype) {
360 68137 : case GF_ISOM_BOX_TYPE_RTP_STSD:
361 : case GF_ISOM_BOX_TYPE_SRTP_STSD:
362 : case GF_ISOM_BOX_TYPE_RRTP_STSD:
363 68137 : return gf_isom_hint_rtp_size((GF_RTPPacket *)ptr);
364 : case GF_ISOM_BOX_TYPE_RTCP_STSD:
365 1 : return gf_isom_hint_rtcp_size((GF_RTCPPacket *)ptr);
366 : default:
367 : return 0;
368 : }
369 : }
370 :
371 159 : GF_Err gf_isom_hint_pck_offset(GF_HintPacket *ptr, u32 offset, u32 HintSampleNumber)
372 : {
373 159 : if (!ptr) return GF_BAD_PARAM;
374 159 : switch (ptr->hint_subtype) {
375 159 : case GF_ISOM_BOX_TYPE_RTP_STSD:
376 : case GF_ISOM_BOX_TYPE_SRTP_STSD:
377 : case GF_ISOM_BOX_TYPE_RRTP_STSD:
378 159 : return gf_isom_hint_rtp_offset((GF_RTPPacket *)ptr, offset, HintSampleNumber);
379 : case GF_ISOM_BOX_TYPE_RTCP_STSD:
380 : return GF_BAD_PARAM;
381 0 : default:
382 0 : return GF_NOT_SUPPORTED;
383 : }
384 : }
385 :
386 124334 : GF_Err gf_isom_hint_pck_add_dte(GF_HintPacket *ptr, GF_GenericDTE *dte, u8 AtBegin)
387 : {
388 124334 : if (!ptr) return GF_BAD_PARAM;
389 124334 : switch (ptr->hint_subtype) {
390 124334 : case GF_ISOM_BOX_TYPE_RTP_STSD:
391 : case GF_ISOM_BOX_TYPE_SRTP_STSD:
392 : case GF_ISOM_BOX_TYPE_RRTP_STSD:
393 124334 : if (AtBegin)
394 34278 : return gf_list_insert( ((GF_RTPPacket *)ptr)->DataTable, dte, 0);
395 : else
396 90056 : return gf_list_add( ((GF_RTPPacket *)ptr)->DataTable, dte);
397 :
398 : case GF_ISOM_BOX_TYPE_RTCP_STSD:
399 : return GF_BAD_PARAM;
400 0 : default:
401 0 : return GF_NOT_SUPPORTED;
402 : }
403 : }
404 :
405 : GF_EXPORT
406 68138 : u32 gf_isom_hint_pck_length(GF_HintPacket *ptr)
407 : {
408 68138 : if (!ptr) return 0;
409 68138 : switch (ptr->hint_subtype) {
410 68137 : case GF_ISOM_BOX_TYPE_RTP_STSD:
411 : case GF_ISOM_BOX_TYPE_SRTP_STSD:
412 : case GF_ISOM_BOX_TYPE_RRTP_STSD:
413 68137 : return gf_isom_hint_rtp_length((GF_RTPPacket *)ptr);
414 : case GF_ISOM_BOX_TYPE_RTCP_STSD:
415 1 : return gf_isom_hint_rtcp_length((GF_RTCPPacket *)ptr);
416 : default:
417 : return 0;
418 : }
419 : }
420 :
421 :
422 : #endif /*GPAC_DISABLE_ISOM_WRITE*/
423 :
424 :
425 :
426 : /********************************************************************
427 : Creation of DataTable entries in the RTP sample
428 : ********************************************************************/
429 :
430 : //creation of DTEs
431 125104 : GF_GenericDTE *NewDTE(u8 type)
432 : {
433 125104 : switch (type) {
434 0 : case 0:
435 : {
436 : GF_EmptyDTE *dte;
437 0 : GF_SAFEALLOC(dte, GF_EmptyDTE);
438 : return (GF_GenericDTE *)dte;
439 : }
440 49407 : case 1:
441 : {
442 : GF_ImmediateDTE *dte;
443 49407 : GF_SAFEALLOC(dte, GF_ImmediateDTE);
444 49407 : if (dte) dte->source = 1;
445 : return (GF_GenericDTE *)dte;
446 : }
447 75697 : case 2:
448 : {
449 : GF_SampleDTE *dte;
450 75697 : GF_SAFEALLOC(dte, GF_SampleDTE);
451 75697 : if (!dte) return NULL;
452 75697 : dte->source = 2;
453 : //can be -1 in QT , so init at -2
454 75697 : dte->trackRefIndex = (s8) -2;
455 75697 : dte->samplesPerComp = 1;
456 75697 : dte->bytesPerComp = 1;
457 75697 : return (GF_GenericDTE *)dte;
458 : }
459 0 : case 3:
460 : {
461 : GF_StreamDescDTE *dte;
462 0 : GF_SAFEALLOC(dte, GF_StreamDescDTE);
463 0 : if (!dte) return NULL;
464 0 : dte->source = 3;
465 : //can be -1 in QT , so init at -2
466 0 : dte->trackRefIndex = (s8) -2;
467 0 : return (GF_GenericDTE *)dte;
468 : }
469 : default:
470 : return NULL;
471 : }
472 : }
473 :
474 : /********************************************************************
475 : Deletion of DataTable entries in the RTP sample
476 : ********************************************************************/
477 :
478 : //deletion of DTEs
479 0 : void DelDTE(GF_GenericDTE *dte)
480 : {
481 125104 : switch (dte->source) {
482 125104 : case 0:
483 : case 1:
484 : case 2:
485 : case 3:
486 125104 : gf_free(dte);
487 0 : break;
488 : default:
489 : return;
490 : }
491 : }
492 :
493 :
494 :
495 : /********************************************************************
496 : Reading of DataTable entries in the RTP sample
497 : ********************************************************************/
498 :
499 770 : GF_Err ReadDTE(GF_GenericDTE *_dte, GF_BitStream *bs)
500 : {
501 770 : switch (_dte->source) {
502 0 : case 0:
503 : //empty but always 15 bytes !!!
504 0 : gf_bs_skip_bytes(bs, 15);
505 0 : return GF_OK;
506 385 : case 1:
507 : {
508 : GF_ImmediateDTE *dte = (GF_ImmediateDTE *)_dte;
509 385 : dte->dataLength = gf_bs_read_u8(bs);
510 385 : if (dte->dataLength > 14) return GF_ISOM_INVALID_FILE;
511 385 : gf_bs_read_data(bs, dte->data, dte->dataLength);
512 385 : if (dte->dataLength < 14) gf_bs_skip_bytes(bs, 14 - dte->dataLength);
513 : return GF_OK;
514 : }
515 385 : case 2:
516 : {
517 : GF_SampleDTE *dte = (GF_SampleDTE *)_dte;
518 385 : dte->trackRefIndex = (s8) gf_bs_read_u8(bs);
519 385 : dte->dataLength = gf_bs_read_u16(bs);
520 385 : dte->sampleNumber = gf_bs_read_u32(bs);
521 385 : dte->byteOffset = gf_bs_read_u32(bs);
522 385 : dte->bytesPerComp = gf_bs_read_u16(bs);
523 385 : dte->samplesPerComp = gf_bs_read_u16(bs);
524 385 : if (dte->bytesPerComp != 1) {
525 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso] hint packet constructor with bytesperblock %d, not 1\n", dte->bytesPerComp));
526 : }
527 385 : if (dte->samplesPerComp != 1) {
528 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso] hint packet constructor with samplesperblock %d, not 1\n", dte->bytesPerComp));
529 : }
530 : return GF_OK;
531 : }
532 0 : case 3:
533 : {
534 : GF_StreamDescDTE *dte = (GF_StreamDescDTE *)_dte;
535 0 : dte->trackRefIndex = gf_bs_read_u8(bs);
536 0 : dte->dataLength = gf_bs_read_u16(bs);
537 0 : dte->streamDescIndex = gf_bs_read_u32(bs);
538 0 : dte->byteOffset = gf_bs_read_u32(bs);
539 0 : dte->reserved = gf_bs_read_u32(bs);
540 0 : return GF_OK;
541 : }
542 : default:
543 : return GF_ISOM_INVALID_FILE;
544 : }
545 : }
546 :
547 : /********************************************************************
548 : Writing of DataTable entries in the RTP sample
549 : ********************************************************************/
550 :
551 :
552 124334 : GF_Err WriteDTE(GF_GenericDTE *_dte, GF_BitStream *bs)
553 : {
554 124334 : switch (_dte->source) {
555 0 : case 0:
556 : {
557 : GF_EmptyDTE *dte = (GF_EmptyDTE *)_dte;
558 0 : gf_bs_write_u8(bs, dte->source);
559 : //empty but always 15 bytes !!!
560 0 : gf_bs_write_data(bs, "empty hint DTE", 15);
561 0 : return GF_OK;
562 : }
563 49022 : case 1:
564 : {
565 : GF_ImmediateDTE *dte = (GF_ImmediateDTE *)_dte;
566 49022 : gf_bs_write_u8(bs, dte->source);
567 49022 : gf_bs_write_u8(bs, dte->dataLength);
568 49022 : gf_bs_write_data(bs, dte->data, dte->dataLength);
569 49022 : if (dte->dataLength < 14) {
570 : char data[14];
571 : memset(data, 0, 14);
572 48965 : gf_bs_write_data(bs, data, 14 - dte->dataLength);
573 : }
574 : return GF_OK;
575 : }
576 75312 : case 2:
577 : {
578 : GF_SampleDTE *dte = (GF_SampleDTE *)_dte;
579 75312 : gf_bs_write_u8(bs, dte->source);
580 75312 : gf_bs_write_u8(bs, dte->trackRefIndex);
581 75312 : gf_bs_write_u16(bs, dte->dataLength);
582 75312 : gf_bs_write_u32(bs, dte->sampleNumber);
583 75312 : gf_bs_write_u32(bs, dte->byteOffset);
584 75312 : gf_bs_write_u16(bs, dte->bytesPerComp);
585 75312 : gf_bs_write_u16(bs, dte->samplesPerComp);
586 75312 : return GF_OK;
587 : }
588 0 : case 3:
589 : {
590 : GF_StreamDescDTE *dte = (GF_StreamDescDTE *)_dte;
591 0 : gf_bs_write_u8(bs, dte->source);
592 :
593 0 : gf_bs_write_u8(bs, dte->trackRefIndex);
594 0 : gf_bs_write_u16(bs, dte->dataLength);
595 0 : gf_bs_write_u32(bs, dte->streamDescIndex);
596 0 : gf_bs_write_u32(bs, dte->byteOffset);
597 0 : gf_bs_write_u32(bs, dte->reserved);
598 0 : return GF_OK;
599 : }
600 : default:
601 : return GF_ISOM_INVALID_FILE;
602 : }
603 : }
604 :
605 0 : GF_Err OffsetDTE(GF_GenericDTE *dte, u32 offset, u32 HintSampleNumber)
606 : {
607 : GF_SampleDTE *sDTE;
608 : //offset shifting is only true for intra sample reference
609 911 : switch (dte->source) {
610 : case 2:
611 : break;
612 : default:
613 : return GF_OK;
614 : }
615 :
616 : sDTE = (GF_SampleDTE *)dte;
617 : //we only adjust for intra HintTrack reference
618 911 : if (sDTE->trackRefIndex != (s8) -1) return GF_OK;
619 : //and in the same sample
620 83 : if (sDTE->sampleNumber != HintSampleNumber) return GF_OK;
621 83 : sDTE->byteOffset += offset;
622 0 : return GF_OK;
623 : }
624 :
625 68522 : GF_RTPPacket *gf_isom_hint_rtp_new()
626 : {
627 : GF_RTPPacket *tmp;
628 68522 : GF_SAFEALLOC(tmp, GF_RTPPacket);
629 68522 : if (!tmp) return NULL;
630 68522 : tmp->TLV = gf_list_new();
631 68522 : tmp->DataTable = gf_list_new();
632 68522 : return tmp;
633 : }
634 :
635 68522 : void gf_isom_hint_rtp_del(GF_RTPPacket *ptr)
636 : {
637 : //the DTE
638 262148 : while (gf_list_count(ptr->DataTable)) {
639 125104 : GF_GenericDTE *p = (GF_GenericDTE *)gf_list_get(ptr->DataTable, 0);
640 : DelDTE(p);
641 125104 : gf_list_rem(ptr->DataTable, 0);
642 : }
643 68522 : gf_list_del(ptr->DataTable);
644 : //the TLV
645 68522 : gf_isom_box_array_del(ptr->TLV);
646 68522 : gf_free(ptr);
647 68522 : }
648 :
649 385 : GF_Err gf_isom_hint_rtp_read(GF_RTPPacket *ptr, GF_BitStream *bs)
650 : {
651 : GF_Err e;
652 : u8 hasTLV, type;
653 : u16 i, count;
654 : u32 TLVsize, tempSize;
655 : GF_Box *a;
656 :
657 385 : ptr->relativeTransTime = gf_bs_read_u32(bs);
658 : //RTP Header
659 : //1- reserved fields
660 385 : gf_bs_read_int(bs, 2);
661 385 : ptr->P_bit = gf_bs_read_int(bs, 1);
662 385 : ptr->X_bit = gf_bs_read_int(bs, 1);
663 385 : gf_bs_read_int(bs, 4);
664 385 : ptr->M_bit = gf_bs_read_int(bs, 1);
665 385 : ptr->payloadType = gf_bs_read_int(bs, 7);
666 :
667 385 : ptr->SequenceNumber = gf_bs_read_u16(bs);
668 385 : gf_bs_read_int(bs, 13);
669 385 : hasTLV = gf_bs_read_int(bs, 1);
670 385 : ptr->B_bit = gf_bs_read_int(bs, 1);
671 385 : ptr->R_bit = gf_bs_read_int(bs, 1);
672 385 : count = gf_bs_read_u16(bs);
673 :
674 : //read the TLV
675 385 : if (hasTLV) {
676 : tempSize = 4; //TLVsize includes its field length
677 0 : TLVsize = gf_bs_read_u32(bs);
678 0 : while (tempSize < TLVsize) {
679 0 : e = gf_isom_box_parse(&a, bs);
680 0 : if (e) return e;
681 0 : gf_list_add(ptr->TLV, a);
682 0 : tempSize += (u32) a->size;
683 : }
684 0 : if (tempSize != TLVsize) return GF_ISOM_INVALID_FILE;
685 : }
686 :
687 : //read the DTEs
688 770 : for (i=0; i<count; i++) {
689 : GF_GenericDTE *dte;
690 : Bool add_it = 0;
691 770 : type = gf_bs_read_u8(bs);
692 770 : dte = NewDTE(type);
693 770 : if (!dte) {
694 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso] invalid DTE code %d in hint sample %d of trackID %d\n", type, ptr->sampleNumber, ptr->trackID));
695 : return GF_ISOM_INVALID_FILE;
696 : }
697 770 : e = ReadDTE(dte, bs);
698 770 : if (e) return e;
699 : /*little opt, remove empty dte*/
700 770 : switch (type) {
701 385 : case 1:
702 385 : if ( ((GF_ImmediateDTE *)dte)->dataLength) add_it = 1;
703 : break;
704 385 : case 2:
705 385 : if ( ((GF_SampleDTE *)dte)->dataLength) add_it = 1;
706 : break;
707 0 : case 3:
708 0 : if ( ((GF_StreamDescDTE *)dte)->dataLength) add_it = 1;
709 : break;
710 : }
711 : if (add_it)
712 770 : gf_list_add(ptr->DataTable, dte);
713 : else
714 : DelDTE(dte);
715 : }
716 : return GF_OK;
717 : }
718 :
719 159 : GF_Err gf_isom_hint_rtp_offset(GF_RTPPacket *ptr, u32 offset, u32 HintSampleNumber)
720 : {
721 : u32 count, i;
722 : GF_Err e;
723 :
724 159 : count = gf_list_count(ptr->DataTable);
725 1070 : for (i=0; i<count; i++) {
726 911 : GF_GenericDTE *dte = (GF_GenericDTE *)gf_list_get(ptr->DataTable, i);
727 : e = OffsetDTE(dte, offset, HintSampleNumber);
728 : if (e) return e;
729 : }
730 : return GF_OK;
731 : }
732 :
733 : //Gets the REAL size of the packet once rebuild, but without CSRC fields in the
734 : //header
735 68522 : u32 gf_isom_hint_rtp_length(GF_RTPPacket *ptr)
736 : {
737 : u32 size, count, i;
738 :
739 : //64 bit header
740 : size = 8;
741 : //32 bit SSRC
742 : size += 4;
743 68522 : count = gf_list_count(ptr->DataTable);
744 193626 : for (i=0; i<count; i++) {
745 125104 : GF_GenericDTE *dte = (GF_GenericDTE *)gf_list_get(ptr->DataTable, i);
746 125104 : switch (dte->source) {
747 : case 0:
748 : break;
749 49407 : case 1:
750 49407 : size += ((GF_ImmediateDTE *)dte)->dataLength;
751 49407 : break;
752 75697 : case 2:
753 75697 : size += ((GF_SampleDTE *)dte)->dataLength;
754 75697 : break;
755 0 : case 3:
756 0 : size += ((GF_StreamDescDTE *)dte)->dataLength;
757 0 : break;
758 : }
759 : }
760 68522 : return size;
761 : }
762 :
763 :
764 : #ifndef GPAC_DISABLE_ISOM_WRITE
765 :
766 68137 : u32 gf_isom_hint_rtp_size(GF_RTPPacket *ptr)
767 : {
768 : GF_Box none;
769 : u32 size, count;
770 : //the RTP Header size and co
771 : size = 12;
772 : //the extra table size
773 68137 : count = gf_list_count(ptr->TLV);
774 68137 : if (count) {
775 9737 : none.size = 4; //WE INCLUDE THE SIZE FIELD LENGTH
776 9737 : none.type = 0;
777 : //REMEMBER THAT TLV ENTRIES ARE 4-BYTES ALIGNED !!!
778 9737 : gf_isom_box_array_size(&none, ptr->TLV);
779 9737 : size += (u32) none.size;
780 : }
781 : //the DTE (each entry is 16 bytes)
782 68137 : count = gf_list_count(ptr->DataTable);
783 68137 : size += count * 16;
784 68137 : return size;
785 : }
786 :
787 68137 : GF_Err gf_isom_hint_rtp_write(GF_RTPPacket *ptr, GF_BitStream *bs)
788 : {
789 : GF_Err e;
790 : u32 TLVcount, DTEcount, i;
791 : GF_Box none;
792 :
793 68137 : gf_bs_write_u32(bs, ptr->relativeTransTime);
794 : //RTP Header
795 : // gf_bs_write_int(bs, 2, 2);
796 : //version is 2
797 68137 : gf_bs_write_int(bs, 2, 2);
798 68137 : gf_bs_write_int(bs, ptr->P_bit, 1);
799 68137 : gf_bs_write_int(bs, ptr->X_bit, 1);
800 68137 : gf_bs_write_int(bs, 0, 4);
801 68137 : gf_bs_write_int(bs, ptr->M_bit, 1);
802 68137 : gf_bs_write_int(bs, ptr->payloadType, 7);
803 :
804 68137 : gf_bs_write_u16(bs, ptr->SequenceNumber);
805 68137 : gf_bs_write_int(bs, 0, 13);
806 68137 : TLVcount = gf_list_count(ptr->TLV);
807 68137 : DTEcount = gf_list_count(ptr->DataTable);
808 68137 : gf_bs_write_int(bs, TLVcount ? 1 : 0, 1);
809 68137 : gf_bs_write_int(bs, ptr->B_bit, 1);
810 68137 : gf_bs_write_int(bs, ptr->R_bit, 1);
811 :
812 68137 : gf_bs_write_u16(bs, DTEcount);
813 :
814 68137 : if (TLVcount) {
815 : //first write the size of the table ...
816 9737 : none.size = 4; //WE INCLUDE THE SIZE FIELD LENGTH
817 9737 : none.type = 0;
818 9737 : gf_isom_box_array_size(&none, ptr->TLV);
819 9737 : gf_bs_write_u32(bs, (u32) none.size);
820 9737 : e = gf_isom_box_array_write(&none, ptr->TLV, bs);
821 9737 : if (e) return e;
822 : }
823 : //write the DTE...
824 124334 : for (i = 0; i < DTEcount; i++) {
825 124334 : GF_GenericDTE *dte = (GF_GenericDTE *)gf_list_get(ptr->DataTable, i);
826 124334 : e = WriteDTE(dte, bs);
827 124334 : if (e) return e;
828 : }
829 : return GF_OK;
830 : }
831 :
832 : #endif /*GPAC_DISABLE_ISOM_WRITE*/
833 :
834 :
835 :
836 1 : GF_RTCPPacket *gf_isom_hint_rtcp_new()
837 : {
838 : GF_RTCPPacket *tmp;
839 1 : GF_SAFEALLOC(tmp, GF_RTCPPacket);
840 1 : return tmp;
841 : }
842 :
843 1 : void gf_isom_hint_rtcp_del(GF_RTCPPacket *ptr)
844 : {
845 1 : if(ptr->data) gf_free(ptr->data);
846 1 : gf_free(ptr);
847 1 : }
848 :
849 1 : GF_Err gf_isom_hint_rtcp_read(GF_RTCPPacket *ptr, GF_BitStream *bs)
850 : {
851 : //RTCP Header
852 :
853 1 : ptr->Version = gf_bs_read_int(bs, 2);
854 1 : ptr->Padding = gf_bs_read_int(bs, 1);
855 1 : ptr->Count = gf_bs_read_int(bs, 5);
856 1 : ptr->PayloadType = gf_bs_read_u8(bs);
857 1 : ptr->length = 4 * gf_bs_read_u16(bs);
858 1 : if (ptr->length<4) return GF_ISOM_INVALID_MEDIA;
859 :
860 : //remove header size
861 0 : if (gf_bs_available(bs) < ptr->length) {
862 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso] RTCP hint packet has more data (%d) than available\n", ptr->length ));
863 : return GF_ISOM_INVALID_MEDIA;
864 : }
865 0 : ptr->data = gf_malloc(sizeof(char) * ptr->length);
866 0 : if (!ptr->data) return GF_OUT_OF_MEM;
867 0 : gf_bs_read_data(bs, ptr->data, ptr->length);
868 0 : return GF_OK;
869 : }
870 :
871 :
872 : //Gets the REAL size of the packet once rebuild, but without CSRC fields in the
873 : //header
874 0 : u32 gf_isom_hint_rtcp_length(GF_RTCPPacket *ptr)
875 : {
876 1 : return 4 * (ptr->length + 1);
877 : }
878 :
879 :
880 : #ifndef GPAC_DISABLE_ISOM_WRITE
881 :
882 0 : u32 gf_isom_hint_rtcp_size(GF_RTCPPacket *ptr)
883 : {
884 1 : return 4 * (ptr->length + 1);
885 : }
886 :
887 1 : GF_Err gf_isom_hint_rtcp_write(GF_RTCPPacket *ptr, GF_BitStream *bs)
888 : {
889 : //RTP Header
890 1 : gf_bs_write_int(bs, ptr->Version, 2);
891 1 : gf_bs_write_int(bs, ptr->Padding, 1);
892 1 : gf_bs_write_int(bs, ptr->Count, 5);
893 1 : gf_bs_write_u8(bs, ptr->PayloadType);
894 1 : gf_bs_write_u16(bs, 4*ptr->length);
895 1 : gf_bs_write_data(bs, ptr->data, ptr->length);
896 1 : return GF_OK;
897 : }
898 :
899 : #endif /*GPAC_DISABLE_ISOM_WRITE*/
900 :
901 :
902 :
903 : #if 0 //unused
904 :
905 : /*small hint reader - performs data caching*/
906 :
907 : /*resets hint reading parameters, returns an error if the hint type is not supported for reading
908 : packet sequence number is always reseted to 0
909 : @sample_start: indicates from where the packets should be read (regular 1-based sample number)
910 : @ts_offset: constant offset for timestamps, must be expressed in media timescale (which is the hint timescale).
911 : usually 0 (no offset)
912 : @sn_offset: offset for packet sequence number (first packet will have a SN of 1 + sn_offset)
913 : usually 0
914 : @ssrc: sync source identifier for RTP
915 : */
916 :
917 : GF_Err gf_isom_reset_hint_reader(GF_ISOFile *the_file, u32 trackNumber, u32 sample_start, u32 ts_offset, u32 sn_offset, u32 ssrc)
918 : {
919 : GF_Err e;
920 : GF_TrackBox *trak;
921 : GF_HintSampleEntryBox *entry;
922 :
923 : trak = gf_isom_get_track_from_file(the_file, trackNumber);
924 : if (!trak) return GF_BAD_PARAM;
925 :
926 : if (!sample_start) return GF_BAD_PARAM;
927 : if (sample_start>=trak->Media->information->sampleTable->SampleSize->sampleCount) return GF_BAD_PARAM;
928 :
929 : e = Media_GetSampleDesc(trak->Media, 1, (GF_SampleEntryBox **) &entry, NULL);
930 : if (e) return e;
931 : switch (entry->type) {
932 : case GF_ISOM_BOX_TYPE_RTP_STSD:
933 : case GF_ISOM_BOX_TYPE_SRTP_STSD:
934 : case GF_ISOM_BOX_TYPE_RRTP_STSD:
935 : break;
936 : default:
937 : return GF_NOT_SUPPORTED;
938 : }
939 :
940 : entry->hint_ref = NULL;
941 : e = Track_FindRef(trak, GF_ISOM_REF_HINT, &entry->hint_ref);
942 : if (e) return e;
943 :
944 : entry->cur_sample = sample_start;
945 : entry->pck_sn = 1 + sn_offset;
946 : entry->ssrc = ssrc;
947 : entry->ts_offset = ts_offset;
948 : if (entry->hint_sample) gf_isom_hint_sample_del(entry->hint_sample);
949 : entry->hint_sample = NULL;
950 : return GF_OK;
951 : }
952 :
953 : static GF_Err gf_isom_load_next_hint_sample(GF_ISOFile *the_file, u32 trackNumber, GF_TrackBox *trak, GF_HintSampleEntryBox *entry)
954 : {
955 : GF_BitStream *bs;
956 : u32 descIdx;
957 : GF_ISOSample *samp;
958 :
959 : if (!entry->cur_sample) return GF_BAD_PARAM;
960 : if (entry->cur_sample>trak->Media->information->sampleTable->SampleSize->sampleCount) return GF_EOS;
961 :
962 : samp = gf_isom_get_sample(the_file, trackNumber, entry->cur_sample, &descIdx);
963 : if (!samp) return GF_IO_ERR;
964 : entry->cur_sample++;
965 :
966 : if (entry->hint_sample) gf_isom_hint_sample_del(entry->hint_sample);
967 :
968 : bs = gf_bs_new(samp->data, samp->dataLength, GF_BITSTREAM_READ);
969 : entry->hint_sample = gf_isom_hint_sample_new(entry->type);
970 : gf_isom_hint_sample_read(entry->hint_sample, bs, samp->dataLength);
971 : gf_bs_del(bs);
972 : entry->hint_sample->TransmissionTime = samp->DTS;
973 : gf_isom_sample_del(&samp);
974 : entry->hint_sample->sample_cache = gf_list_new();
975 : return GF_OK;
976 : }
977 :
978 : static GF_ISOSample *gf_isom_get_data_sample(GF_HintSample *hsamp, GF_TrackBox *trak, u32 sample_num)
979 : {
980 : GF_ISOSample *samp;
981 : GF_HintDataCache *hdc;
982 : u32 i, count;
983 : count = gf_list_count(hsamp->sample_cache);
984 : for (i=0; i<count; i++) {
985 : hdc = (GF_HintDataCache *)gf_list_get(hsamp->sample_cache, i);
986 : if ((hdc->sample_num==sample_num) && (hdc->trak==trak)) return hdc->samp;
987 : }
988 :
989 : samp = gf_isom_sample_new();
990 : Media_GetSample(trak->Media, sample_num, &samp, &i, 0, NULL);
991 : if (!samp) return NULL;
992 : GF_SAFEALLOC(hdc, GF_HintDataCache);
993 : if (!hdc) return NULL;
994 : hdc->samp = samp;
995 : hdc->sample_num = sample_num;
996 : hdc->trak = trak;
997 : /*we insert all new samples, since they're more likely to be fetched next (except for audio
998 : interleaving and other multiplex)*/
999 : gf_list_insert(hsamp->sample_cache, hdc, 0);
1000 : return samp;
1001 : }
1002 :
1003 : /*reads next hint packet. ALl packets are read in transmission (decoding) order
1004 : returns an error if not supported, or GF_EOS when no more packets are available
1005 : currently only RTP reader is supported
1006 : @pck_data, @pck_size: output packet data (must be freed by caller) - contains all info to be sent
1007 : on the wire, eg for RTP contains the RTP header and the data
1008 : @disposable (optional): indicates that the packet can be dropped when late (B-frames & co)
1009 : @repeated (optional): indicates this is a repeated packet (same one has already been sent)
1010 : @trans_ts (optional): indicates the transmission time of the packet, expressed in hint timescale, taking into account
1011 : the ts_offset specified in gf_isom_reset_hint_reader. Depending on packets this may not be the same
1012 : as the hint sample timestamp + ts_offset, some packets may need to be sent earlier (B-frames)
1013 : @sample_num (optional): indicates hint sample number the packet belongs to
1014 : */
1015 : GF_Err gf_isom_next_hint_packet(GF_ISOFile *the_file, u32 trackNumber, char **pck_data, u32 *pck_size, Bool *disposable, Bool *repeated, u32 *trans_ts, u32 *sample_num)
1016 : {
1017 : GF_RTPPacket *pck;
1018 : GF_Err e;
1019 : GF_BitStream *bs;
1020 : GF_TrackBox *trak, *ref_trak;
1021 : GF_HintSampleEntryBox *entry;
1022 : u32 i, count, ts;
1023 : s32 cts_off;
1024 :
1025 : *pck_data = NULL;
1026 : *pck_size = 0;
1027 : if (trans_ts) *trans_ts = 0;
1028 : if (disposable) *disposable = 0;
1029 : if (repeated) *repeated = 0;
1030 : if (sample_num) *sample_num = 0;
1031 :
1032 : trak = gf_isom_get_track_from_file(the_file, trackNumber);
1033 : if (!trak) return GF_BAD_PARAM;
1034 : e = Media_GetSampleDesc(trak->Media, 1, (GF_SampleEntryBox **) &entry, NULL);
1035 : if (e) return e;
1036 : switch (entry->type) {
1037 : case GF_ISOM_BOX_TYPE_RTP_STSD:
1038 : case GF_ISOM_BOX_TYPE_SRTP_STSD:
1039 : case GF_ISOM_BOX_TYPE_RRTP_STSD:
1040 : break;
1041 : default:
1042 : return GF_NOT_SUPPORTED;
1043 : }
1044 :
1045 : if (!entry->hint_sample) {
1046 : e = gf_isom_load_next_hint_sample(the_file, trackNumber, trak, entry);
1047 : if (e) return e;
1048 : }
1049 : pck = (GF_RTPPacket *)gf_list_get(entry->hint_sample->packetTable, 0);
1050 : gf_list_rem(entry->hint_sample->packetTable, 0);
1051 : if (!pck) return GF_BAD_PARAM;
1052 :
1053 : bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
1054 : /*write RTP header*/
1055 : gf_bs_write_int(bs, 2, 2); /*version*/
1056 : gf_bs_write_int(bs, pck->P_bit, 1); /*P bit*/
1057 : gf_bs_write_int(bs, pck->X_bit, 1); /*X bit*/
1058 : gf_bs_write_int(bs, 0, 4); /*CSRC count*/
1059 : gf_bs_write_int(bs, pck->M_bit, 1); /*M bit*/
1060 : gf_bs_write_int(bs, pck->payloadType, 7); /*payt*/
1061 : gf_bs_write_u16(bs, entry->pck_sn); /*seq num*/
1062 : entry->pck_sn++;
1063 :
1064 : /*look for CTS offset in TLV*/
1065 : cts_off = 0;
1066 : count = gf_list_count(pck->TLV);
1067 : for (i=0; i<count; i++) {
1068 : GF_RTPOBox *rtpo = (GF_RTPOBox *)gf_list_get(pck->TLV, i);
1069 : if (rtpo->type == GF_ISOM_BOX_TYPE_RTPO) {
1070 : cts_off = rtpo->timeOffset;
1071 : break;
1072 : }
1073 : }
1074 : /*TS - TODO check TS wrapping*/
1075 : ts = (u32) (entry->hint_sample->TransmissionTime + pck->relativeTransTime + entry->ts_offset + cts_off);
1076 : gf_bs_write_u32(bs, ts );
1077 : gf_bs_write_u32(bs, entry->ssrc); /*SSRC*/
1078 :
1079 : /*then build all data*/
1080 : count = gf_list_count(pck->DataTable);
1081 : for (i=0; i<count; i++) {
1082 : GF_GenericDTE *dte = (GF_GenericDTE *)gf_list_get(pck->DataTable, i);
1083 : switch (dte->source) {
1084 : /*empty*/
1085 : case 0:
1086 : break;
1087 : /*immediate data*/
1088 : case 1:
1089 : gf_bs_write_data(bs, ((GF_ImmediateDTE *)dte)->data, ((GF_ImmediateDTE *)dte)->dataLength);
1090 : break;
1091 : /*sample data*/
1092 : case 2:
1093 : {
1094 : GF_ISOSample *samp;
1095 : GF_SampleDTE *sdte = (GF_SampleDTE *)dte;
1096 : /*get track if not this one*/
1097 : if (sdte->trackRefIndex != (s8) -1) {
1098 : if (!entry->hint_ref || !entry->hint_ref->trackIDs) {
1099 : gf_isom_hint_rtp_del(pck);
1100 : gf_bs_del(bs);
1101 : return GF_ISOM_INVALID_FILE;
1102 : }
1103 : ref_trak = gf_isom_get_track_from_id(trak->moov, entry->hint_ref->trackIDs[(u32)sdte->trackRefIndex]);
1104 : } else {
1105 : ref_trak = trak;
1106 : }
1107 : samp = gf_isom_get_data_sample(entry->hint_sample, ref_trak, sdte->sampleNumber);
1108 : if (!samp) {
1109 : gf_isom_hint_rtp_del(pck);
1110 : gf_bs_del(bs);
1111 : return GF_IO_ERR;
1112 : }
1113 : gf_bs_write_data(bs, samp->data + sdte->byteOffset, sdte->dataLength);
1114 : }
1115 : break;
1116 : /*sample desc data - currently NOT SUPPORTED !!!*/
1117 : case 3:
1118 : break;
1119 : }
1120 : }
1121 : if (trans_ts) *trans_ts = ts;
1122 : if (disposable) *disposable = pck->B_bit;
1123 : if (repeated) *repeated = pck->R_bit;
1124 : if (sample_num) *sample_num = entry->cur_sample-1;
1125 :
1126 : gf_bs_get_content(bs, pck_data, pck_size);
1127 : gf_bs_del(bs);
1128 : gf_isom_hint_rtp_del(pck);
1129 : if (!gf_list_count(entry->hint_sample->packetTable)) {
1130 : gf_isom_hint_sample_del(entry->hint_sample);
1131 : entry->hint_sample = NULL;
1132 : }
1133 : return GF_OK;
1134 : }
1135 :
1136 : #endif
1137 :
1138 :
1139 : #endif /* !defined(GPAC_DISABLE_ISOM) && !defined(GPAC_DISABLE_ISOM_HINTING)*/
|