Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Jean Le Feuvre
5 : * Copyright (c) Telecom ParisTech 2000-2020
6 : * All rights reserved
7 : *
8 : * This file is part of GPAC / RTP input module
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/ietf_dev.h>
27 :
28 : #ifndef GPAC_DISABLE_STREAMING
29 :
30 : #include <gpac/base_coding.h>
31 : #include <gpac/constants.h>
32 : #include <gpac/isomedia.h>
33 : #include <gpac/mpeg4_odf.h>
34 : #include <gpac/avparse.h>
35 :
36 23 : static void gf_rtp_parse_pass_through(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, u8 *payload, u32 size)
37 : {
38 23 : if (!rtp) return;
39 :
40 23 : rtp->sl_hdr.accessUnitStartFlag = 1;
41 23 : if (rtp->sl_hdr.compositionTimeStamp != hdr->TimeStamp)
42 : rtp->sl_hdr.accessUnitStartFlag = 1;
43 :
44 23 : rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp;
45 23 : rtp->sl_hdr.decodingTimeStamp = hdr->TimeStamp;
46 23 : rtp->sl_hdr.accessUnitEndFlag = hdr->Marker;
47 23 : rtp->sl_hdr.randomAccessPointFlag = 1;
48 23 : rtp->on_sl_packet(rtp->udta, payload, size, &rtp->sl_hdr, GF_OK);
49 : }
50 :
51 104 : static void gf_rtp_parse_mpeg4(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, u8 *payload, u32 size)
52 : {
53 : u32 aux_size, first_idx, au_hdr_size, num_au;
54 : u64 pay_start, au_size;
55 : s32 au_idx;
56 : GF_BitStream *hdr_bs, *aux_bs;
57 :
58 104 : hdr_bs = gf_bs_new(payload, size, GF_BITSTREAM_READ);
59 104 : aux_bs = gf_bs_new(payload, size, GF_BITSTREAM_READ);
60 :
61 : /*global AU header len*/
62 : au_hdr_size = 0;
63 104 : if (rtp->sl_map.auh_first_min_len) {
64 75 : au_hdr_size = gf_bs_read_u16(hdr_bs);
65 75 : gf_bs_read_u16(aux_bs);
66 : }
67 :
68 : /*jump to aux section, skip it and get payload start*/
69 104 : gf_bs_read_int(aux_bs, au_hdr_size);
70 104 : gf_bs_align(aux_bs);
71 104 : if (rtp->sl_map.AuxiliaryDataSizeLength) {
72 0 : aux_size = gf_bs_read_int(aux_bs, rtp->sl_map.AuxiliaryDataSizeLength);
73 0 : gf_bs_read_int(aux_bs, aux_size);
74 0 : gf_bs_align(aux_bs);
75 : }
76 104 : pay_start = gf_bs_get_position(aux_bs);
77 104 : gf_bs_del(aux_bs);
78 :
79 : first_idx = 0;
80 : au_idx = 0;
81 :
82 104 : rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp;
83 104 : rtp->sl_hdr.decodingTimeStamp = hdr->TimeStamp;
84 :
85 : num_au = 0;
86 :
87 104 : rtp->sl_hdr.accessUnitEndFlag = hdr->Marker;
88 : /*override some defaults for RFC 3016*/
89 104 : if (rtp->flags & GF_RTP_NEW_AU) {
90 102 : rtp->sl_hdr.accessUnitStartFlag = 1;
91 : } else {
92 2 : rtp->sl_hdr.accessUnitStartFlag = 0;
93 : }
94 104 : rtp->sl_hdr.randomAccessPointFlag = 0;
95 :
96 : while (1) {
97 : /*get default AU size*/
98 744 : au_size = rtp->sl_map.ConstantSize;
99 : /*not signaled, assume max one AU per packet*/
100 424 : if (!au_size) au_size = size - pay_start;
101 :
102 424 : if ((!num_au && rtp->sl_map.auh_first_min_len) || (num_au && rtp->sl_map.auh_min_len)) {
103 : /*ISMACryp*/
104 395 : if (rtp->flags & GF_RTP_HAS_ISMACRYP) {
105 : u32 nbbits;
106 0 : rtp->sl_hdr.isma_encrypted = 1;
107 0 : if (rtp->flags & GF_RTP_ISMA_SEL_ENC) {
108 0 : rtp->sl_hdr.isma_encrypted = gf_bs_read_int(hdr_bs, 1);
109 0 : gf_bs_read_int(hdr_bs, 7);
110 0 : au_hdr_size -= 8;
111 : }
112 : /*Note: ISMACryp ALWAYS indicates IV (BSO) and KEYIDX, even when sample is not encrypted.
113 : This is quite a waste when using selective encryption....*/
114 0 : if (!num_au) {
115 0 : nbbits = 8*rtp->sl_map.IV_length;
116 0 : if (nbbits) {
117 0 : rtp->sl_hdr.isma_BSO = gf_bs_read_int(hdr_bs, nbbits);
118 0 : au_hdr_size -= nbbits;
119 : }
120 : }
121 : /*NOT SUPPORTED YET*/
122 0 : else if (rtp->sl_map.IV_delta_length) {
123 0 : nbbits = 8*rtp->sl_map.IV_delta_length;
124 : if (nbbits) {
125 0 : rtp->sl_hdr.isma_BSO += gf_bs_read_int(hdr_bs, nbbits);
126 0 : au_hdr_size -= nbbits;
127 : }
128 : }
129 0 : if (rtp->sl_map.KI_length) {
130 : /*NOT SUPPORTED YET*/
131 0 : if (!num_au || !(rtp->flags & GF_RTP_ISMA_HAS_KEY_IDX) ) {
132 0 : nbbits = 8*rtp->sl_map.KI_length;
133 : if (nbbits) {
134 0 : gf_bs_read_int(hdr_bs, nbbits);
135 0 : au_hdr_size -= nbbits;
136 : }
137 : }
138 : }
139 : }
140 :
141 : /*AU size*/
142 395 : if (rtp->sl_map.SizeLength) {
143 395 : au_size = gf_bs_read_int(hdr_bs, rtp->sl_map.SizeLength);
144 395 : if (au_size > size - pay_start) au_size = size - pay_start;
145 395 : au_hdr_size -= rtp->sl_map.SizeLength;
146 : }
147 : /*AU index*/
148 395 : if (! num_au) {
149 75 : au_idx = first_idx = gf_bs_read_int(hdr_bs, rtp->sl_map.IndexLength);
150 75 : au_hdr_size -= rtp->sl_map.IndexLength;
151 : } else {
152 320 : au_idx += 1 + (u32) gf_bs_read_int(hdr_bs, rtp->sl_map.IndexDeltaLength);
153 320 : au_hdr_size -= rtp->sl_map.IndexDeltaLength;
154 : }
155 : /*CTS flag*/
156 395 : if (rtp->sl_map.CTSDeltaLength) {
157 0 : rtp->sl_hdr.compositionTimeStampFlag = gf_bs_read_int(hdr_bs, 1);
158 0 : au_hdr_size -= 1;
159 : } else {
160 : /*get CTS from IDX*/
161 395 : if (rtp->sl_map.ConstantDuration) {
162 395 : rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp + (au_idx - first_idx) * rtp->sl_map.ConstantDuration;
163 : } else {
164 0 : rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp + (au_idx - first_idx) * rtp->sl_hdr.au_duration;
165 : }
166 : }
167 :
168 : /*CTS in-band*/
169 395 : if (rtp->sl_hdr.compositionTimeStampFlag) {
170 0 : rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp + (u32) gf_bs_read_int(hdr_bs, rtp->sl_map.CTSDeltaLength);
171 0 : au_hdr_size -= rtp->sl_map.CTSDeltaLength;
172 : }
173 : /*DTS flag is always present (needed for reconstruction of TSs in case of packet loss)*/
174 395 : if (rtp->sl_map.DTSDeltaLength) {
175 0 : rtp->sl_hdr.decodingTimeStampFlag = gf_bs_read_int(hdr_bs, 1);
176 0 : au_hdr_size -= 1;
177 : } else {
178 : /*NO DTS otherwise*/
179 395 : rtp->sl_hdr.decodingTimeStampFlag = 0;
180 : }
181 395 : if (rtp->sl_hdr.decodingTimeStampFlag) {
182 0 : u32 ts_off = gf_bs_read_int(hdr_bs, rtp->sl_map.DTSDeltaLength);
183 : /*TODO FIXME may not be true in case of TS wrapping*/
184 0 : if (hdr->TimeStamp > ts_off) rtp->sl_hdr.decodingTimeStamp = hdr->TimeStamp - ts_off;
185 0 : au_hdr_size -= rtp->sl_map.DTSDeltaLength;
186 : }
187 : /*RAP flag*/
188 395 : if (rtp->sl_map.RandomAccessIndication) {
189 0 : rtp->sl_hdr.randomAccessPointFlag = gf_bs_read_int(hdr_bs, 1);
190 0 : au_hdr_size -= 1;
191 0 : if (rtp->sl_hdr.randomAccessPointFlag)
192 0 : rtp->sl_hdr.randomAccessPointFlag=1;
193 : } else {
194 395 : rtp->sl_hdr.randomAccessPointFlag=1;
195 : }
196 : /*stream state - map directly to seqNum*/
197 395 : if (rtp->sl_map.StreamStateIndication) {
198 0 : rtp->sl_hdr.AU_sequenceNumber = gf_bs_read_int(hdr_bs, rtp->sl_map.StreamStateIndication);
199 0 : au_hdr_size -= rtp->sl_map.StreamStateIndication;
200 : }
201 : }
202 : /*no header present, update CTS/DTS - note we're sure there's no interleaving*/
203 : else {
204 29 : if (num_au) {
205 0 : rtp->sl_hdr.compositionTimeStamp += rtp->sl_map.ConstantDuration;
206 0 : rtp->sl_hdr.decodingTimeStamp += rtp->sl_map.ConstantDuration;
207 : }
208 : }
209 : /*we cannot map RTP SN to SL SN since an RTP packet may carry several SL ones - only inc by 1 seq nums*/
210 424 : rtp->sl_hdr.packetSequenceNumber += 1;
211 :
212 : /*force indication of CTS whenever we have a new AU*/
213 :
214 424 : rtp->sl_hdr.compositionTimeStampFlag = (rtp->flags & GF_RTP_NEW_AU) ? 1 : 0;
215 :
216 : /*locate VOP start code*/
217 424 : if (rtp->sl_hdr.accessUnitStartFlag && (rtp->flags & GF_RTP_M4V_CHECK_RAP)) {
218 : u32 i;
219 : Bool is_rap = GF_FALSE;
220 27 : unsigned char *pay = (unsigned char *) payload + pay_start;
221 : i=0;
222 54 : while (i<au_size-4) {
223 27 : if (!pay[i] && !pay[i+1] && (pay[i+2]==1) && (pay[i+3]==0xB6)) {
224 27 : is_rap = ((pay[i+4] & 0xC0)==0) ? GF_TRUE : GF_FALSE;
225 27 : break;
226 : }
227 0 : i++;
228 : }
229 27 : rtp->sl_hdr.randomAccessPointFlag = is_rap ? 1 : 0;
230 : }
231 :
232 424 : rtp->on_sl_packet(rtp->udta, payload + pay_start, (u32) au_size, &rtp->sl_hdr, GF_OK);
233 :
234 424 : rtp->sl_hdr.compositionTimeStampFlag = 0;
235 :
236 424 : if (rtp->flags & GF_RTP_HAS_ISMACRYP) rtp->sl_hdr.isma_BSO += au_size;
237 :
238 424 : if (au_hdr_size < rtp->sl_map.auh_min_len) break;
239 349 : pay_start += au_size;
240 349 : if (pay_start >= size) break;
241 320 : num_au ++;
242 : }
243 : // assert(!au_hdr_size);
244 :
245 104 : if (hdr->Marker)
246 102 : rtp->flags |= GF_RTP_NEW_AU;
247 : else
248 2 : rtp->flags &= ~GF_RTP_NEW_AU;
249 :
250 104 : gf_bs_del(hdr_bs);
251 104 : }
252 :
253 : #ifndef GPAC_DISABLE_AV_PARSERS
254 :
255 39 : static void gf_rtp_parse_mpeg12_audio(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, u8 *payload, u32 size)
256 : {
257 : u16 offset;
258 : u32 mp3hdr, ts;
259 : GF_BitStream *bs;
260 :
261 39 : rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp;
262 39 : rtp->sl_hdr.decodingTimeStamp = hdr->TimeStamp;
263 :
264 39 : rtp->sl_hdr.accessUnitStartFlag = rtp->sl_hdr.accessUnitEndFlag ? 1 : 0;
265 39 : if (rtp->flags & GF_RTP_NEW_AU) rtp->sl_hdr.accessUnitStartFlag = 1;
266 :
267 : /*get frag header*/
268 39 : bs = gf_bs_new(payload, size, GF_BITSTREAM_READ);
269 39 : gf_bs_read_u16(bs);
270 39 : offset = gf_bs_read_u16(bs);
271 39 : gf_bs_del(bs);
272 39 : payload += 4;
273 39 : size -= 4;
274 : mp3hdr = 0;
275 : while (1) {
276 :
277 : /*frame start if no offset*/
278 39 : rtp->sl_hdr.accessUnitStartFlag = offset ? 0 : 1;
279 39 : rtp->sl_hdr.randomAccessPointFlag = 1;
280 :
281 : /*new frame, store size*/
282 39 : rtp->sl_hdr.compositionTimeStampFlag = 0;
283 39 : if (rtp->sl_hdr.accessUnitStartFlag) {
284 39 : mp3hdr = GF_4CC((u32) payload[0], (u8) payload[1], (u8) payload[2], (u8) payload[3]);
285 39 : rtp->sl_hdr.accessUnitLength = gf_mp3_frame_size(mp3hdr);
286 39 : rtp->sl_hdr.channels = gf_mp3_num_channels(mp3hdr);
287 39 : rtp->sl_hdr.samplerate = gf_mp3_sampling_rate(mp3hdr);
288 39 : if (rtp->sl_hdr.samplerate) {
289 39 : rtp->sl_hdr.au_duration = gf_mp3_window_size(mp3hdr);
290 39 : rtp->sl_hdr.au_duration *= rtp->clock_rate;
291 39 : rtp->sl_hdr.au_duration /= rtp->sl_hdr.samplerate;
292 : }
293 39 : rtp->sl_hdr.compositionTimeStampFlag = 1;
294 : }
295 39 : if (!rtp->sl_hdr.accessUnitLength) break;
296 : /*fragmented frame*/
297 39 : if (rtp->sl_hdr.accessUnitLength>size) {
298 0 : rtp->on_sl_packet(rtp->udta, payload, rtp->sl_hdr.accessUnitLength, &rtp->sl_hdr, GF_OK);
299 0 : rtp->sl_hdr.accessUnitLength -= size;
300 0 : rtp->sl_hdr.accessUnitStartFlag = rtp->sl_hdr.accessUnitEndFlag = 0;
301 0 : return;
302 : }
303 : /*complete frame*/
304 39 : rtp->sl_hdr.accessUnitEndFlag = 1;
305 39 : rtp->on_sl_packet(rtp->udta, payload, rtp->sl_hdr.accessUnitLength, &rtp->sl_hdr, GF_OK);
306 39 : payload += rtp->sl_hdr.accessUnitLength;
307 39 : size -= rtp->sl_hdr.accessUnitLength;
308 39 : rtp->sl_hdr.accessUnitLength = 0;
309 :
310 : /*if fragmented there shall not be other frames in the packet*/
311 39 : if (!rtp->sl_hdr.accessUnitStartFlag) return;
312 39 : if (!size) break;
313 : offset = 0;
314 : /*get ts*/
315 0 : ts = gf_mp3_window_size(mp3hdr);
316 0 : rtp->sl_hdr.compositionTimeStamp += ts;
317 0 : rtp->sl_hdr.decodingTimeStamp += ts;
318 : }
319 39 : rtp->flags |= GF_RTP_NEW_AU;
320 : }
321 :
322 : #endif
323 :
324 73 : static void gf_rtp_parse_mpeg12_video(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, u8 *payload, u32 size)
325 : {
326 : u8 pic_type;
327 :
328 73 : rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp;
329 73 : rtp->sl_hdr.decodingTimeStamp = hdr->TimeStamp;
330 :
331 :
332 73 : pic_type = payload[2] & 0x7;
333 73 : payload += 4;
334 73 : size -= 4;
335 :
336 : /*missed something*/
337 73 : if (rtp->sl_hdr.compositionTimeStamp != hdr->TimeStamp) rtp->flags |= GF_RTP_NEW_AU;
338 :
339 73 : rtp->sl_hdr.accessUnitStartFlag = (rtp->flags & GF_RTP_NEW_AU) ? 1 : 0;
340 73 : rtp->sl_hdr.accessUnitEndFlag = hdr->Marker ? 1 : 0;
341 73 : rtp->sl_hdr.randomAccessPointFlag = (pic_type==1) ? 1 : 0;
342 :
343 73 : if (rtp->sl_hdr.accessUnitStartFlag) {
344 27 : rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp;
345 27 : rtp->sl_hdr.compositionTimeStampFlag = 1;
346 : } else {
347 46 : rtp->sl_hdr.compositionTimeStampFlag = 0;
348 : }
349 73 : rtp->on_sl_packet(rtp->udta, payload, size, &rtp->sl_hdr, GF_OK);
350 73 : if (hdr->Marker) {
351 27 : rtp->flags |= GF_RTP_NEW_AU;
352 : } else {
353 46 : rtp->flags &= ~GF_RTP_NEW_AU;
354 : }
355 73 : }
356 :
357 51 : static void gf_rtp_parse_amr(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, u8 *payload, u32 size)
358 : {
359 : unsigned char c;
360 : char *data;
361 : /*we support max 30 frames in one RTP packet...*/
362 : u32 nbFrame, i, frame_size;
363 : /*not supported yet*/
364 51 : if (!(rtp->flags & GF_RTP_AMR_ALIGN) ) return;
365 :
366 : /*process toc and locate start of payload data*/
367 : nbFrame = 0;
368 : while (1) {
369 51 : c = payload[nbFrame + 1];
370 : nbFrame++;
371 51 : if (!(c & 0x80)) break;
372 : }
373 51 : data = payload + nbFrame + 1;
374 51 : rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp;
375 : /*then each frame*/
376 153 : for (i=0; i<nbFrame; i++) {
377 : u8 type;
378 51 : c = payload[i + 1];
379 51 : type = ((c & 0x78) >> 3);
380 51 : if (rtp->payt==GF_RTP_PAYT_AMR) {
381 51 : frame_size = (u32)GF_AMR_FRAME_SIZE[type];
382 : } else {
383 0 : frame_size = (u32)GF_AMR_WB_FRAME_SIZE[type];
384 : }
385 :
386 51 : rtp->sl_hdr.compositionTimeStampFlag = 1;
387 51 : rtp->sl_hdr.accessUnitStartFlag = 1;
388 51 : rtp->sl_hdr.accessUnitEndFlag = 0;
389 51 : rtp->sl_hdr.randomAccessPointFlag = 1;
390 : /*send TOC*/
391 51 : rtp->on_sl_packet(rtp->udta, &payload[i+1], 1, &rtp->sl_hdr, GF_OK);
392 51 : rtp->sl_hdr.packetSequenceNumber ++;
393 51 : rtp->sl_hdr.compositionTimeStampFlag = 0;
394 51 : rtp->sl_hdr.accessUnitStartFlag = 0;
395 51 : rtp->sl_hdr.accessUnitEndFlag = 1;
396 : /*send payload*/
397 51 : rtp->on_sl_packet(rtp->udta, data, frame_size, &rtp->sl_hdr, GF_OK);
398 51 : data += frame_size;
399 51 : rtp->sl_hdr.compositionTimeStamp += 160;
400 : }
401 : }
402 :
403 :
404 17 : static void gf_rtp_parse_h263(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, u8 *payload, u32 size)
405 : {
406 : GF_BitStream *bs;
407 : Bool P_bit, V_bit;
408 : u32 plen;
409 : u64 offset;
410 : char blank[2];
411 :
412 17 : bs = gf_bs_new(payload, size, GF_BITSTREAM_READ);
413 : /*reserved*/
414 17 : gf_bs_read_int(bs, 5);
415 17 : P_bit = (Bool)gf_bs_read_int(bs, 1);
416 17 : V_bit = (Bool)gf_bs_read_int(bs, 1);
417 17 : plen = gf_bs_read_int(bs, 6);
418 17 : /*plen_bits = */gf_bs_read_int(bs, 3);
419 :
420 : /*VRC not supported yet*/
421 17 : if (V_bit) {
422 0 : gf_bs_read_u8(bs);
423 : }
424 : /*extra picture header not supported yet*/
425 17 : if (plen) {
426 0 : gf_bs_skip_bytes(bs, plen);
427 : }
428 17 : offset = gf_bs_get_position(bs);
429 17 : gf_bs_del(bs);
430 :
431 17 : blank[0] = blank[1] = 0;
432 : /*start*/
433 17 : if (P_bit) {
434 17 : rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp;
435 17 : rtp->sl_hdr.compositionTimeStampFlag = 1;
436 17 : rtp->sl_hdr.accessUnitStartFlag = 1;
437 17 : rtp->sl_hdr.accessUnitEndFlag = 0;
438 :
439 : /*the first 16 bytes are NOT sent on the wire*/
440 17 : rtp->sl_hdr.randomAccessPointFlag = (payload[offset+2]&0x02) ? 0 : 1;
441 :
442 : /*send missing start code*/
443 17 : rtp->on_sl_packet(rtp->udta, (char *) blank, 2, &rtp->sl_hdr, GF_OK);
444 : /*send payload*/
445 17 : rtp->sl_hdr.compositionTimeStampFlag = 0;
446 17 : rtp->sl_hdr.accessUnitStartFlag = 0;
447 17 : rtp->sl_hdr.randomAccessPointFlag = 0;
448 :
449 : /*if M bit set, end of frame*/
450 17 : rtp->sl_hdr.accessUnitEndFlag = hdr->Marker;
451 17 : rtp->on_sl_packet(rtp->udta, payload + offset, (u32) (size - offset), &rtp->sl_hdr, GF_OK);
452 : } else {
453 : /*middle/end of frames - if M bit set, end of frame*/
454 0 : rtp->sl_hdr.accessUnitEndFlag = hdr->Marker;
455 0 : rtp->on_sl_packet(rtp->udta, payload + offset, (u32) (size - offset), &rtp->sl_hdr, GF_OK);
456 : }
457 17 : }
458 :
459 2 : static void gf_rtp_ttxt_flush(GF_RTPDepacketizer *rtp, u32 ts)
460 : {
461 : GF_BitStream *bs;
462 : u8 *data;
463 : u32 data_size;
464 4 : if (!rtp->inter_bs) return;
465 :
466 0 : rtp->sl_hdr.compositionTimeStamp = ts;
467 0 : rtp->sl_hdr.compositionTimeStampFlag = 1;
468 0 : rtp->sl_hdr.accessUnitStartFlag = 1;
469 0 : rtp->sl_hdr.accessUnitEndFlag = 0;
470 0 : rtp->sl_hdr.randomAccessPointFlag = 1;
471 :
472 0 : bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
473 0 : gf_bs_write_int(bs, rtp->sl_hdr.idleFlag, 1);
474 0 : rtp->sl_hdr.idleFlag = 0;
475 0 : gf_bs_write_int(bs, 0, 4);
476 0 : gf_bs_write_int(bs, 1, 3);
477 0 : gf_bs_write_u16(bs, 8 + (u16) gf_bs_get_position(rtp->inter_bs));
478 0 : gf_bs_write_u8(bs, rtp->sidx);
479 0 : gf_bs_write_u24(bs, rtp->sl_hdr.au_duration);
480 0 : gf_bs_write_u16(bs, rtp->txt_len);
481 0 : gf_bs_get_content(bs, &data, &data_size);
482 0 : gf_bs_del(bs);
483 :
484 0 : rtp->on_sl_packet(rtp->udta, data, data_size, &rtp->sl_hdr, GF_OK);
485 0 : gf_free(data);
486 0 : rtp->sl_hdr.accessUnitStartFlag = 0;
487 0 : rtp->sl_hdr.accessUnitEndFlag = 1;
488 0 : gf_bs_get_content(rtp->inter_bs, &data, &data_size);
489 0 : rtp->on_sl_packet(rtp->udta, data, data_size, &rtp->sl_hdr, GF_OK);
490 0 : gf_free(data);
491 :
492 0 : gf_bs_del(rtp->inter_bs);
493 0 : rtp->inter_bs = NULL;
494 0 : rtp->nb_txt_frag = rtp->cur_txt_frag = rtp->sidx = rtp->txt_len = rtp->nb_mod_frag = 0;
495 : }
496 :
497 2 : static void gf_rtp_parse_ttxt(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, u8 *payload, u32 size)
498 : {
499 : Bool is_utf_16;
500 : u32 type, ttu_len, duration, ts, sidx, txt_size;
501 : u32 nb_frag, cur_frag;
502 : u64 pay_start;
503 : GF_BitStream *bs;
504 :
505 2 : ts = hdr->TimeStamp;
506 :
507 2 : bs = gf_bs_new(payload, size, GF_BITSTREAM_READ);
508 6 : while (gf_bs_available(bs)) {
509 2 : pay_start = gf_bs_get_position(bs);
510 2 : is_utf_16 = (Bool)gf_bs_read_int(bs, 1);
511 2 : gf_bs_read_int(bs, 4);
512 2 : type = gf_bs_read_int(bs, 3);
513 2 : ttu_len = gf_bs_read_u16(bs);
514 2 : if (ttu_len<2) break;
515 :
516 2 : if (type==1) {
517 : /*flush any existing packet*/
518 2 : gf_rtp_ttxt_flush(rtp, (u32) rtp->sl_hdr.compositionTimeStamp);
519 :
520 : /*bad ttu(1)*/
521 2 : if (ttu_len<8) break;
522 2 : rtp->sl_hdr.compositionTimeStamp = ts;
523 2 : rtp->sl_hdr.compositionTimeStampFlag = 1;
524 2 : rtp->sl_hdr.accessUnitStartFlag = 1;
525 2 : rtp->sl_hdr.accessUnitEndFlag = 1;
526 2 : rtp->sl_hdr.randomAccessPointFlag = 1;
527 2 : gf_bs_read_u8(bs);
528 2 : rtp->sl_hdr.au_duration = gf_bs_read_u24(bs);
529 2 : rtp->on_sl_packet(rtp->udta, payload + pay_start, ttu_len + 1, &rtp->sl_hdr, GF_OK);
530 2 : gf_bs_skip_bytes(bs, ttu_len - 6);
531 2 : ts += rtp->sl_hdr.au_duration;
532 : }
533 : /*text segment*/
534 0 : else if (type==2) {
535 : /*TS changed, flush packet*/
536 0 : if (rtp->sl_hdr.compositionTimeStamp < ts) {
537 0 : gf_rtp_ttxt_flush(rtp, (u32) rtp->sl_hdr.compositionTimeStamp);
538 : }
539 0 : if (ttu_len<9) break;
540 0 : rtp->sl_hdr.compositionTimeStamp = ts;
541 0 : rtp->sl_hdr.idleFlag = is_utf_16;
542 0 : nb_frag = gf_bs_read_int(bs, 4);
543 0 : cur_frag = gf_bs_read_int(bs, 4);
544 0 : duration = gf_bs_read_u24(bs);
545 0 : sidx = gf_bs_read_u8(bs);
546 0 : gf_bs_read_u16(bs);/*complete text sample size, ignored*/
547 0 : txt_size = size - 10;
548 :
549 : /*init - 3GPP/MPEG-4 splitting is IMHO stupid:
550 : - nb frag & cur frags are not needed: rtp reordering insures packet are in order, and
551 : !!!we assume fragments are sent in order!!!
552 : - any other TTU suffices to indicate end of text string (modifiers or != RTP TS)
553 : - replacing these 8bits field with a 16 bit absolute character offset would add error recovery
554 : */
555 0 : if (!rtp->nb_txt_frag) {
556 0 : rtp->nb_txt_frag = nb_frag;
557 0 : rtp->cur_txt_frag = 0;
558 0 : rtp->sidx = sidx;
559 : }
560 : /*flush prev if any mismatch*/
561 0 : if ((nb_frag != rtp->nb_txt_frag) || (rtp->cur_txt_frag > cur_frag)) {
562 0 : gf_rtp_ttxt_flush(rtp, (u32) rtp->sl_hdr.compositionTimeStamp);
563 0 : rtp->nb_txt_frag = nb_frag;
564 0 : rtp->sidx = sidx;
565 : }
566 0 : if (!rtp->inter_bs) rtp->inter_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
567 :
568 : /*we don't reorder - RTP reordering is done at lower level, if this is out of order too bad*/
569 0 : rtp->cur_txt_frag = cur_frag;
570 0 : gf_bs_write_data(rtp->inter_bs, payload+10, txt_size);
571 0 : gf_bs_skip_bytes(bs, txt_size);
572 :
573 0 : rtp->sl_hdr.au_duration = duration;
574 : /*done*/
575 0 : if (hdr->Marker) {
576 : assert(gf_bs_get_position(rtp->inter_bs) < 1<<7);
577 0 : rtp->txt_len = (u8) gf_bs_get_position(rtp->inter_bs);
578 0 : gf_rtp_ttxt_flush(rtp, ts);
579 : }
580 0 : } else if ((type==3) || (type==4)) {
581 0 : if (!rtp->inter_bs) rtp->inter_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
582 : /*first modifier, store effective written text*/
583 0 : if (type==3) {
584 : assert(gf_bs_get_position(rtp->inter_bs) < 1<<7);
585 0 : rtp->txt_len = (u8) gf_bs_get_position(rtp->inter_bs);
586 : }
587 0 : if (ttu_len<6) break;
588 :
589 0 : nb_frag = gf_bs_read_int(bs, 4);
590 0 : if (!rtp->nb_mod_frag) rtp->nb_mod_frag = nb_frag;
591 0 : else if (rtp->nb_mod_frag != nb_frag) {
592 0 : gf_rtp_ttxt_flush(rtp, (u32) rtp->sl_hdr.compositionTimeStamp);
593 0 : rtp->nb_mod_frag = nb_frag;
594 : }
595 0 : gf_bs_read_int(bs, 4); /*cur_frag, ignore*/
596 0 : rtp->sl_hdr.au_duration = gf_bs_read_u24(bs);
597 0 : gf_bs_write_data(rtp->inter_bs, payload+7, ttu_len-6);
598 0 : gf_bs_skip_bytes(bs, ttu_len-6);
599 :
600 : /*done*/
601 0 : if (hdr->Marker) gf_rtp_ttxt_flush(rtp, ts);
602 : }
603 : }
604 2 : gf_bs_del(bs);
605 2 : }
606 :
607 18 : static void gf_rtp_h264_flush(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, Bool missed_end)
608 : {
609 : u8 *data;
610 : u32 data_size, nal_s;
611 27 : if (!rtp->inter_bs) return;
612 :
613 9 : data = NULL;
614 9 : data_size = 0;
615 9 : gf_bs_get_content(rtp->inter_bs, &data, &data_size);
616 9 : gf_bs_del(rtp->inter_bs);
617 9 : rtp->inter_bs = NULL;
618 9 : nal_s = data_size-4;
619 :
620 9 : if (rtp->flags & GF_RTP_AVC_USE_ANNEX_B) {
621 0 : data[0] = data[1] = data[2] = 0;
622 0 : data[3] = 1;
623 : } else {
624 9 : data[0] = nal_s>>24;
625 9 : data[1] = nal_s>>16;
626 9 : data[2] = nal_s>>8;
627 9 : data[3] = nal_s&0xFF;
628 : }
629 : /*set F-bit since nal is corrupted*/
630 : // if (missed_end) data[4] |= 0x80;
631 :
632 9 : rtp->sl_hdr.accessUnitEndFlag = hdr->Marker;
633 9 : rtp->sl_hdr.compositionTimeStampFlag = 1;
634 9 : rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp;
635 9 : rtp->sl_hdr.decodingTimeStampFlag = 0;
636 :
637 9 : rtp->on_sl_packet(rtp->udta, data, data_size, &rtp->sl_hdr, GF_OK);
638 9 : rtp->sl_hdr.accessUnitStartFlag = 0;
639 9 : rtp->sl_hdr.randomAccessPointFlag = 0;
640 9 : gf_free(data);
641 : }
642 :
643 127 : void gf_rtp_parse_h264(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, u8 *payload, u32 size)
644 : {
645 : char nalhdr[4];
646 : u32 nal_type;
647 127 : if (rtp->h264_pck_mode==2) return;
648 :
649 127 : nal_type = payload[0] & 0x1F;
650 :
651 : /*set start*/
652 127 : if (rtp->sl_hdr.compositionTimeStamp != hdr->TimeStamp) {
653 80 : rtp->sl_hdr.accessUnitEndFlag = 0;
654 80 : rtp->sl_hdr.accessUnitStartFlag = 1;
655 80 : rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp;
656 80 : rtp->sl_hdr.compositionTimeStampFlag = 1;
657 80 : rtp->sl_hdr.decodingTimeStampFlag = 0;
658 80 : rtp->sl_hdr.randomAccessPointFlag = 0;
659 : }
660 :
661 : /*single NALU*/
662 127 : if (nal_type<23) {
663 71 : if (nal_type==GF_AVC_NALU_IDR_SLICE) {
664 2 : rtp->sl_hdr.randomAccessPointFlag = 1;
665 2 : rtp->flags &= ~GF_RTP_AVC_WAIT_RAP;
666 : }
667 69 : else if (rtp->flags & GF_RTP_AVC_WAIT_RAP)
668 : return;
669 :
670 71 : rtp->sl_hdr.accessUnitEndFlag = 0;
671 :
672 71 : if (rtp->flags & GF_RTP_AVC_USE_ANNEX_B) {
673 0 : nalhdr[0] = 0;
674 0 : nalhdr[1] = 0;
675 0 : nalhdr[2] = 0;
676 0 : nalhdr[3] = 1;
677 : } else {
678 : /*signal NALU size on 4 bytes*/
679 71 : nalhdr[0] = size>>24;
680 71 : nalhdr[1] = size>>16;
681 71 : nalhdr[2] = size>>8;
682 71 : nalhdr[3] = size&0xFF;
683 : }
684 71 : rtp->on_sl_packet(rtp->udta, nalhdr, 4, &rtp->sl_hdr, GF_OK);
685 :
686 71 : rtp->sl_hdr.accessUnitStartFlag = 0;
687 71 : rtp->sl_hdr.compositionTimeStampFlag = 1;
688 71 : rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp;
689 71 : rtp->sl_hdr.accessUnitEndFlag = hdr->Marker;
690 :
691 : /*send NAL payload*/
692 71 : rtp->on_sl_packet(rtp->udta, payload, size, &rtp->sl_hdr, GF_OK);
693 : }
694 : /*STAP-A NALU*/
695 56 : else if (nal_type==24) {
696 : u32 offset = 1;
697 8 : while (offset<size) {
698 : Bool send = GF_TRUE;
699 4 : u32 nal_size = (u8) payload[offset];
700 4 : nal_size<<=8;
701 4 : nal_size |= (u8) payload[offset+1];
702 4 : offset += 2;
703 4 : if ((payload[offset] & 0x1F) == GF_AVC_NALU_IDR_SLICE) {
704 0 : rtp->sl_hdr.randomAccessPointFlag = 1;
705 0 : rtp->flags &= ~GF_RTP_AVC_WAIT_RAP;
706 : }
707 4 : if (rtp->flags & GF_RTP_AVC_WAIT_RAP) send = GF_FALSE;
708 :
709 : if (send) {
710 : /*signal NALU size on 4 bytes*/
711 3 : if (rtp->flags & GF_RTP_AVC_USE_ANNEX_B) {
712 0 : nalhdr[0] = 0;
713 0 : nalhdr[1] = 0;
714 0 : nalhdr[2] = 0;
715 0 : nalhdr[3] = 1;
716 : } else {
717 3 : nalhdr[0] = nal_size>>24;
718 3 : nalhdr[1] = nal_size>>16;
719 3 : nalhdr[2] = nal_size>>8;
720 3 : nalhdr[3] = nal_size&0xFF;
721 : }
722 3 : rtp->on_sl_packet(rtp->udta, nalhdr, 4, &rtp->sl_hdr, GF_OK);
723 3 : rtp->sl_hdr.accessUnitStartFlag = 0;
724 3 : rtp->sl_hdr.compositionTimeStampFlag = 0;
725 : }
726 4 : rtp->sl_hdr.accessUnitEndFlag = (hdr->Marker && (offset+nal_size==size)) ? 1 : 0;
727 4 : if (send) rtp->on_sl_packet(rtp->udta, payload+offset, nal_size, &rtp->sl_hdr, GF_OK);
728 4 : offset += nal_size;
729 : }
730 : }
731 : /*FU-A NALU*/
732 52 : else if (nal_type==28) {
733 52 : Bool is_start = payload[1] & 0x80;
734 : Bool is_end = payload[1] & 0x40;
735 : /*flush*/
736 52 : if (is_start) gf_rtp_h264_flush(rtp, hdr, GF_TRUE);
737 :
738 52 : if ((payload[1] & 0x1F) == GF_AVC_NALU_IDR_SLICE) {
739 13 : rtp->flags &= ~GF_RTP_AVC_WAIT_RAP;
740 13 : rtp->sl_hdr.randomAccessPointFlag = 1;
741 39 : } else if (rtp->flags & GF_RTP_AVC_WAIT_RAP)
742 : return;
743 :
744 : /*setup*/
745 52 : if (!rtp->inter_bs) {
746 : u8 nal_hdr;
747 9 : rtp->inter_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
748 : /*copy F and NRI*/
749 9 : nal_hdr = payload[0] & 0xE0;
750 : /*start bit not set, signal corrupted data (we missed start packet)*/
751 : // if (!is_start) nal_hdr |= 0x80;
752 : /*copy NALU type*/
753 9 : nal_hdr |= (payload[1] & 0x1F);
754 : /*dummy size field*/
755 9 : gf_bs_write_u32(rtp->inter_bs, 0);
756 9 : gf_bs_write_u8(rtp->inter_bs, nal_hdr);
757 : }
758 52 : gf_bs_write_data(rtp->inter_bs, payload+2, size-2);
759 52 : if (is_end || hdr->Marker) gf_rtp_h264_flush(rtp, hdr, GF_FALSE);
760 : }
761 : }
762 :
763 : #if !defined(GPAC_DISABLE_HEVC) && !defined(GPAC_DISABLE_AV_PARSERS)
764 :
765 8 : static void gf_rtp_hevc_flush(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, Bool missed_end)
766 : {
767 : u8 *data;
768 : u32 data_size, nal_s;
769 12 : if (!rtp->inter_bs) return;
770 :
771 4 : data = NULL;
772 4 : data_size = 0;
773 4 : gf_bs_get_content(rtp->inter_bs, &data, &data_size);
774 4 : gf_bs_del(rtp->inter_bs);
775 4 : rtp->inter_bs = NULL;
776 4 : nal_s = data_size-4;
777 :
778 4 : data[0] = nal_s>>24;
779 4 : data[1] = nal_s>>16;
780 4 : data[2] = nal_s>>8;
781 4 : data[3] = nal_s&0xFF;
782 : /*set F-bit since nal is corrupted*/
783 4 : if (missed_end) data[4] |= 0x80;
784 :
785 4 : rtp->sl_hdr.accessUnitEndFlag = hdr->Marker;
786 4 : rtp->sl_hdr.compositionTimeStampFlag = 1;
787 4 : rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp;
788 4 : rtp->sl_hdr.decodingTimeStampFlag = 0;
789 4 : rtp->on_sl_packet(rtp->udta, data, data_size, &rtp->sl_hdr, GF_OK);
790 4 : rtp->sl_hdr.accessUnitStartFlag = 0;
791 4 : rtp->sl_hdr.randomAccessPointFlag = 0;
792 4 : gf_free(data);
793 : }
794 :
795 281 : static void gf_rtp_parse_hevc(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, u8 *payload, u32 size)
796 : {
797 : u32 nal_type;
798 : char nalu_size[4];
799 :
800 281 : nal_type = (payload[0] & 0x7E) >> 1;
801 :
802 : /*set start*/
803 281 : if (rtp->sl_hdr.compositionTimeStamp != hdr->TimeStamp) {
804 27 : rtp->sl_hdr.accessUnitEndFlag = 0;
805 27 : rtp->sl_hdr.accessUnitStartFlag = 1;
806 27 : rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp;
807 27 : rtp->sl_hdr.compositionTimeStampFlag = 1;
808 27 : rtp->sl_hdr.decodingTimeStampFlag = 0;
809 27 : rtp->sl_hdr.randomAccessPointFlag = 0;
810 : }
811 :
812 : /*Single NALU*/
813 281 : if (nal_type <= 40) {
814 : /*FIXME: strict condition for randomAccessPointFlag because of decoder's issue*/
815 267 : if ((nal_type==GF_HEVC_NALU_SLICE_IDR_W_DLP) || (nal_type==GF_HEVC_NALU_SLICE_IDR_N_LP)) {
816 : //if ((nal_type>=GF_HEVC_NALU_SLICE_BLA_W_LP) && (nal_type<=GF_HEVC_NALU_SLICE_CRA)) {
817 15 : rtp->sl_hdr.randomAccessPointFlag = 1;
818 : }
819 :
820 267 : rtp->sl_hdr.accessUnitEndFlag = 0;
821 :
822 : /*signal NALU size on 4 bytes*/
823 267 : nalu_size[0] = size>>24;
824 267 : nalu_size[1] = size>>16;
825 267 : nalu_size[2] = size>>8;
826 267 : nalu_size[3] = size&0xFF;
827 267 : rtp->on_sl_packet(rtp->udta, nalu_size, 4, &rtp->sl_hdr, GF_OK);
828 :
829 267 : rtp->sl_hdr.accessUnitStartFlag = 0;
830 267 : rtp->sl_hdr.compositionTimeStampFlag = 1;
831 267 : rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp;
832 267 : rtp->sl_hdr.accessUnitEndFlag = hdr->Marker;
833 :
834 : /*send NAL payload*/
835 267 : rtp->on_sl_packet(rtp->udta, payload, size, &rtp->sl_hdr, GF_OK);
836 : }
837 : /*AP NALU*/
838 14 : else if (nal_type == 48) {
839 : u32 offset = 2;
840 0 : while (offset<size) {
841 0 : u32 nal_size = (u8) payload[offset];
842 0 : nal_size<<=8;
843 0 : nal_size |= (u8) payload[offset+1];
844 0 : offset += 2;
845 0 : nal_type = (payload[offset] & 0x7E) >> 1;
846 : /*FIXME: strict condition for randomAccessPointFlag because of decoder's issue*/
847 0 : if ((nal_type==GF_HEVC_NALU_SLICE_IDR_W_DLP) || (nal_type==GF_HEVC_NALU_SLICE_IDR_N_LP)) {
848 : //if ((nal_type>=GF_HEVC_NALU_SLICE_BLA_W_LP) && (nal_type<=GF_HEVC_NALU_SLICE_CRA)) {
849 0 : rtp->sl_hdr.randomAccessPointFlag = 1;
850 : }
851 :
852 : /*signal NALU size on 4 bytes*/
853 0 : nalu_size[0] = nal_size>>24;
854 0 : nalu_size[1] = nal_size>>16;
855 0 : nalu_size[2] = nal_size>>8;
856 0 : nalu_size[3] = nal_size&0xFF;
857 0 : rtp->on_sl_packet(rtp->udta, nalu_size, 4, &rtp->sl_hdr, GF_OK);
858 :
859 0 : rtp->sl_hdr.accessUnitStartFlag = 0;
860 0 : rtp->sl_hdr.compositionTimeStampFlag = 0;
861 0 : rtp->sl_hdr.accessUnitEndFlag = (hdr->Marker && (offset+nal_size==size)) ? 1 : 0;
862 0 : rtp->on_sl_packet(rtp->udta, payload+offset, nal_size, &rtp->sl_hdr, GF_OK);
863 0 : offset += nal_size;
864 : }
865 : }
866 : /*FU NALU*/
867 14 : else if (nal_type == 49) {
868 14 : Bool is_start = payload[2] & 0x80;
869 : Bool is_end = payload[2] & 0x40;
870 : /*flush*/
871 14 : if (is_start) gf_rtp_hevc_flush(rtp, hdr, GF_TRUE);
872 :
873 14 : nal_type = payload[2] & 0x3F;
874 : /*FIXME: strict condition for randomAccessPointFlag because of decoder's issue*/
875 14 : if ((nal_type==GF_HEVC_NALU_SLICE_IDR_W_DLP) || (nal_type==GF_HEVC_NALU_SLICE_IDR_N_LP)) {
876 : //if ((nal_type>=GF_HEVC_NALU_SLICE_BLA_W_LP) && (nal_type<=GF_HEVC_NALU_SLICE_CRA)) {
877 12 : rtp->sl_hdr.randomAccessPointFlag = 1;
878 : }
879 :
880 : /*setup*/
881 14 : if (!rtp->inter_bs) {
882 : char nal_hdr[2];
883 4 : rtp->inter_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
884 : /*coypy F bit highest bit of LayerId*/
885 4 : nal_hdr[0] = payload[0] & 0x81;
886 : /*assign NAL type*/
887 4 : nal_hdr[0] |= (payload[2] & 0x3F) << 1;
888 : /*copy LayerId and TID*/
889 4 : nal_hdr[1] = payload[1];
890 : /*dummy size field*/
891 4 : gf_bs_write_u32(rtp->inter_bs, 0);
892 4 : gf_bs_write_data(rtp->inter_bs, nal_hdr, 2);
893 : }
894 14 : gf_bs_write_data(rtp->inter_bs, payload+3, size-3);
895 14 : if (is_end || hdr->Marker) gf_rtp_hevc_flush(rtp, hdr, GF_FALSE);
896 : }
897 281 : }
898 : #endif
899 :
900 : #ifndef GPAC_DISABLE_AV_PARSERS
901 :
902 9 : static void gf_rtp_parse_latm(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, u8 *payload, u32 size)
903 : {
904 : u32 remain, latm_hdr_size, latm_size;
905 :
906 9 : rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp;
907 9 : rtp->sl_hdr.compositionTimeStampFlag = 1;
908 9 : rtp->sl_hdr.accessUnitStartFlag = rtp->sl_hdr.accessUnitEndFlag = 1;
909 9 : rtp->sl_hdr.randomAccessPointFlag = 1;
910 :
911 : remain = size;
912 65 : while (remain) {
913 : latm_hdr_size = latm_size = 0;
914 : while (1) {
915 70 : u8 c = *payload;
916 70 : latm_hdr_size += 1;
917 70 : latm_size += c;
918 70 : payload ++;
919 70 : if (c < 0xFF) break;
920 : }
921 :
922 47 : rtp->on_sl_packet(rtp->udta, (char *) payload, latm_size, &rtp->sl_hdr, GF_OK);
923 47 : payload += latm_size;
924 47 : remain -= (latm_size+latm_hdr_size);
925 47 : if (rtp->sl_hdr.au_duration)
926 47 : rtp->sl_hdr.compositionTimeStamp += rtp->sl_hdr.au_duration;
927 : else
928 0 : rtp->sl_hdr.compositionTimeStamp += 1024;
929 : }
930 9 : }
931 : #endif
932 :
933 : #if GPAC_ENABLE_3GPP_DIMS_RTP
934 : static void gf_rtp_parse_3gpp_dims(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, char *payload, u32 size)
935 : {
936 : u32 du_size, offset, dsize, hdr_size;
937 : char *data, dhdr[6];
938 :
939 : u32 frag_state = ((payload[0]>>3) & 0x7);
940 :
941 : rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp;
942 : rtp->sl_hdr.compositionTimeStampFlag = 1;
943 :
944 : if (rtp->flags & GF_RTP_NEW_AU) {
945 : rtp->flags &= ~GF_RTP_NEW_AU;
946 : rtp->sl_hdr.accessUnitStartFlag = 1;
947 : }
948 : rtp->sl_hdr.accessUnitEndFlag = 0;
949 : if (hdr->Marker) rtp->flags |= GF_RTP_NEW_AU;
950 :
951 : rtp->sl_hdr.randomAccessPointFlag = (payload[0] & 0x40);
952 : rtp->sl_hdr.AU_sequenceNumber = (payload[0] & 0x7);
953 :
954 : offset = 1;
955 : while (offset < size) {
956 : switch (frag_state) {
957 : case 0:
958 : {
959 : GF_BitStream *bs;
960 : bs = gf_bs_new(payload+offset, 2, GF_BITSTREAM_READ);
961 : du_size = 2 + gf_bs_read_u16(bs);
962 : gf_bs_del(bs);
963 : if (hdr->Marker && offset+du_size>=size) {
964 : rtp->sl_hdr.accessUnitEndFlag = 1;
965 : }
966 : rtp->on_sl_packet(rtp->udta, payload + offset, du_size, &rtp->sl_hdr, GF_OK);
967 : rtp->sl_hdr.accessUnitStartFlag = 0;
968 : offset += du_size;
969 : }
970 : break;
971 : case 1:
972 : if (rtp->inter_bs) gf_bs_del(rtp->inter_bs);
973 :
974 : rtp->inter_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
975 : gf_bs_write_data(rtp->inter_bs, payload+offset, size-offset);
976 : return;
977 : case 2:
978 : if (!rtp->inter_bs) return;
979 : gf_bs_write_data(rtp->inter_bs, payload+offset, size-offset);
980 : return;
981 : case 3:
982 : if (!rtp->inter_bs) return;
983 : gf_bs_write_data(rtp->inter_bs, payload+offset, size-offset);
984 : gf_bs_get_content(rtp->inter_bs, &data, &dsize);
985 : gf_bs_del(rtp->inter_bs);
986 :
987 : /*send unit header - if dims size is >0xFFFF, use our internal hack for large units*/
988 : rtp->inter_bs = gf_bs_new(dhdr, 6, GF_BITSTREAM_WRITE);
989 : if (dsize<=0xFFFF) {
990 : gf_bs_write_u16(rtp->inter_bs, dsize);
991 : hdr_size = 2;
992 : } else {
993 : gf_bs_write_u16(rtp->inter_bs, 0);
994 : gf_bs_write_u32(rtp->inter_bs, dsize);
995 : hdr_size = 6;
996 : }
997 : gf_bs_del(rtp->inter_bs);
998 : rtp->inter_bs = NULL;
999 :
1000 : rtp->on_sl_packet(rtp->udta, dhdr, hdr_size, &rtp->sl_hdr, GF_OK);
1001 : rtp->sl_hdr.accessUnitStartFlag = 0;
1002 :
1003 : rtp->sl_hdr.accessUnitEndFlag = hdr->Marker;
1004 : rtp->on_sl_packet(rtp->udta, data, dsize, &rtp->sl_hdr, GF_OK);
1005 : gf_free(data);
1006 : return;
1007 : }
1008 : }
1009 :
1010 : }
1011 : #endif
1012 :
1013 :
1014 : #ifndef GPAC_DISABLE_AV_PARSERS
1015 :
1016 29 : static void gf_rtp_parse_ac3(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, u8 *payload, u32 size)
1017 : {
1018 : u8 ft;
1019 :
1020 29 : rtp->sl_hdr.compositionTimeStampFlag = 1;
1021 29 : rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp;
1022 29 : rtp->sl_hdr.randomAccessPointFlag = 1;
1023 29 : ft = payload[0];
1024 : /*nb_pck = payload[1];*/
1025 29 : payload += 2;
1026 29 : size -= 2;
1027 :
1028 29 : if (!ft) {
1029 : GF_AC3Config ac3hdr;
1030 : memset(&ac3hdr, 0, sizeof(GF_AC3Config));
1031 29 : rtp->sl_hdr.accessUnitStartFlag = rtp->sl_hdr.accessUnitEndFlag = 1;
1032 87 : while (size) {
1033 : u32 offset;
1034 29 : if (!gf_ac3_parser((u8*)payload, size, &offset, &ac3hdr, GF_FALSE)) {
1035 0 : return;
1036 : }
1037 29 : if (offset) {
1038 0 : if (offset>size) return;
1039 0 : payload+=offset;
1040 0 : size-=offset;
1041 : }
1042 29 : rtp->on_sl_packet(rtp->udta, payload, ac3hdr.framesize, &rtp->sl_hdr, GF_OK);
1043 29 : if (size < ac3hdr.framesize) return;
1044 29 : size -= ac3hdr.framesize;
1045 29 : payload += ac3hdr.framesize;
1046 29 : rtp->sl_hdr.compositionTimeStamp += 1536;
1047 : }
1048 29 : rtp->flags |= GF_RTP_NEW_AU;
1049 0 : } else if (ft==3) {
1050 0 : rtp->sl_hdr.accessUnitStartFlag = 0;
1051 0 : rtp->sl_hdr.accessUnitEndFlag = hdr->Marker ? 1 : 0;
1052 0 : rtp->on_sl_packet(rtp->udta, payload, size, &rtp->sl_hdr, GF_OK);
1053 : } else {
1054 0 : rtp->sl_hdr.accessUnitStartFlag = 1;
1055 0 : rtp->sl_hdr.accessUnitEndFlag = 0;
1056 0 : rtp->on_sl_packet(rtp->udta, payload, size, &rtp->sl_hdr, GF_OK);
1057 : }
1058 : }
1059 : #endif /*GPAC_DISABLE_AV_PARSERS*/
1060 :
1061 20 : static u32 gf_rtp_get_payload_type(GF_RTPMap *map, GF_SDPMedia *media)
1062 : {
1063 : u32 i, j;
1064 :
1065 20 : if (!stricmp(map->payload_name, "MP4V-ES") ) return GF_RTP_PAYT_MPEG4;
1066 19 : else if (!stricmp(map->payload_name, "mpeg4-generic")) return GF_RTP_PAYT_MPEG4;
1067 12 : else if (!stricmp(map->payload_name, "enc-mpeg4-generic")) return GF_RTP_PAYT_MPEG4;
1068 : /*optibase mm400 card hack*/
1069 12 : else if (!stricmp(map->payload_name, "enc-generic-mp4") ) {
1070 0 : gf_free(map->payload_name);
1071 0 : map->payload_name = gf_strdup("enc-mpeg4-generic");
1072 : return GF_RTP_PAYT_MPEG4;
1073 : }
1074 :
1075 : /*LATM: only without multiplexing (not tested but should be straight AUs)*/
1076 12 : else if (!stricmp(map->payload_name, "MP4A-LATM")) {
1077 : GF_SDP_FMTP *fmtp;
1078 1 : i=0;
1079 2 : while ((fmtp = (GF_SDP_FMTP *) gf_list_enum(media->FMTP, &i))) {
1080 : GF_X_Attribute *att;
1081 1 : if (fmtp->PayloadType != map->PayloadType) continue;
1082 : //this is our payload. check cpresent is 0
1083 1 : j=0;
1084 4 : while ((att = (GF_X_Attribute *)gf_list_enum(fmtp->Attributes, &j))) {
1085 4 : if (!stricmp(att->Name, "cpresent") && atoi(att->Value)) return 0;
1086 : }
1087 : }
1088 : return GF_RTP_PAYT_LATM;
1089 : }
1090 11 : else if (!stricmp(map->payload_name, "MPA")) return GF_RTP_PAYT_MPEG12_AUDIO;
1091 10 : else if (!stricmp(map->payload_name, "MPV")) return GF_RTP_PAYT_MPEG12_VIDEO;
1092 9 : else if (!stricmp(map->payload_name, "H263-1998") || !stricmp(map->payload_name, "H263-2000")) return GF_RTP_PAYT_H263;
1093 8 : else if (!stricmp(map->payload_name, "AMR")) return GF_RTP_PAYT_AMR;
1094 7 : else if (!stricmp(map->payload_name, "AMR-WB")) return GF_RTP_PAYT_AMR_WB;
1095 7 : else if (!stricmp(map->payload_name, "3gpp-tt")) return GF_RTP_PAYT_3GPP_TEXT;
1096 6 : else if (!stricmp(map->payload_name, "H264")) return GF_RTP_PAYT_H264_AVC;
1097 : #if GPAC_ENABLE_3GPP_DIMS_RTP
1098 : else if (!stricmp(map->payload_name, "richmedia+xml")) return GF_RTP_PAYT_3GPP_DIMS;
1099 : #endif
1100 3 : else if (!stricmp(map->payload_name, "ac3")) return GF_RTP_PAYT_AC3;
1101 2 : else if (!stricmp(map->payload_name, "H264-SVC")) return GF_RTP_PAYT_H264_SVC;
1102 2 : else if (!stricmp(map->payload_name, "H265")) return GF_RTP_PAYT_HEVC;
1103 1 : else if (!stricmp(map->payload_name, "H265-SHVC")) return GF_RTP_PAYT_LHVC;
1104 : else return 0;
1105 : }
1106 :
1107 :
1108 90 : static GF_Err payt_set_param(GF_RTPDepacketizer *rtp, char *param_name, char *param_val)
1109 : {
1110 : u32 i, val;
1111 : char valS[3];
1112 : GF_BitStream *bs;
1113 :
1114 90 : if (!rtp || !param_name) return GF_BAD_PARAM;
1115 :
1116 : /*1 - mpeg4-generic / RFC 3016 payload type items*/
1117 :
1118 : /*PL (not needed when IOD is here)*/
1119 90 : if (!stricmp(param_name, "Profile-level-id")) {
1120 12 : if (rtp->payt == GF_RTP_PAYT_H264_AVC || rtp->payt == GF_RTP_PAYT_H264_SVC) {
1121 3 : sscanf(param_val, "%x", &rtp->sl_map.PL_ID);
1122 : } else {
1123 9 : rtp->sl_map.PL_ID = atoi(param_val);
1124 : }
1125 : }
1126 : /*decoder specific info (not needed when IOD is here)*/
1127 78 : else if (!stricmp(param_name, "config")) {
1128 9 : u32 len = (u32) strlen(param_val);
1129 : //decode the buffer - the string buffer is MSB hexadecimal
1130 9 : bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
1131 9 : valS[2] = 0;
1132 86 : for (i=0; i<len; i+=2) {
1133 77 : valS[0] = param_val[i];
1134 77 : valS[1] = param_val[i+1];
1135 77 : sscanf(valS, "%x", &val);
1136 77 : gf_bs_write_u8(bs, val);
1137 : }
1138 9 : if (rtp->sl_map.config) gf_free(rtp->sl_map.config);
1139 9 : rtp->sl_map.config = NULL;
1140 9 : gf_bs_get_content(bs, &rtp->sl_map.config, &rtp->sl_map.configSize);
1141 9 : gf_bs_del(bs);
1142 : }
1143 : /*mpeg4-generic payload type items required*/
1144 :
1145 : /*constant size (size of all AUs) */
1146 69 : else if (!stricmp(param_name, "ConstantSize")) {
1147 0 : rtp->sl_map.ConstantSize = atoi(param_val);
1148 : }
1149 : /*constant size (size of all AUs) */
1150 69 : else if (!stricmp(param_name, "ConstantDuration")) {
1151 7 : rtp->sl_map.ConstantDuration = atoi(param_val);
1152 : }
1153 : /*object type indication (not needed when IOD is here)*/
1154 62 : else if (!stricmp(param_name, "ObjectType")) {
1155 7 : rtp->sl_map.CodecID = atoi(param_val);
1156 : }
1157 55 : else if (!stricmp(param_name, "StreamType"))
1158 7 : rtp->sl_map.StreamType = atoi(param_val);
1159 48 : else if (!stricmp(param_name, "mode")) {
1160 7 : strcpy(rtp->sl_map.mode, param_val);
1161 : /*in case no IOD and no streamType/OTI in the file*/
1162 7 : if (!stricmp(param_val, "AAC-hbr") || !stricmp(param_val, "AAC-lbr") || !stricmp(param_val, "CELP-vbr") || !stricmp(param_val, "CELP-cbr")) {
1163 7 : rtp->sl_map.StreamType = GF_STREAM_AUDIO;
1164 7 : rtp->sl_map.CodecID = GF_CODECID_AAC_MPEG4;
1165 : }
1166 : /*in case no IOD and no streamType/OTI in the file*/
1167 0 : else if (!stricmp(param_val, "avc-video") ) {
1168 0 : rtp->sl_map.StreamType = GF_STREAM_VISUAL;
1169 0 : rtp->sl_map.CodecID = GF_CODECID_AVC;
1170 : }
1171 : }
1172 :
1173 41 : else if (!stricmp(param_name, "DTSDeltaLength")) rtp->sl_map.DTSDeltaLength = atoi(param_val);
1174 41 : else if (!stricmp(param_name, "CTSDeltaLength")) rtp->sl_map.CTSDeltaLength = atoi(param_val);
1175 48 : else if (!stricmp(param_name, "SizeLength")) rtp->sl_map.SizeLength = atoi(param_val);
1176 41 : else if (!stricmp(param_name, "IndexLength")) rtp->sl_map.IndexLength = atoi(param_val);
1177 34 : else if (!stricmp(param_name, "IndexDeltaLength")) rtp->sl_map.IndexDeltaLength = atoi(param_val);
1178 20 : else if (!stricmp(param_name, "RandomAccessIndication")) rtp->sl_map.RandomAccessIndication = atoi(param_val);
1179 20 : else if (!stricmp(param_name, "StreamStateIndication")) rtp->sl_map.StreamStateIndication = atoi(param_val);
1180 20 : else if (!stricmp(param_name, "AuxiliaryDataSizeLength")) rtp->sl_map.AuxiliaryDataSizeLength = atoi(param_val);
1181 :
1182 : /*H264/AVC config - we only handle mode 0 and 1*/
1183 20 : else if (!stricmp(param_name, "packetization-mode"))
1184 3 : rtp->h264_pck_mode = 1;
1185 : /*AMR config*/
1186 17 : else if (!stricmp(param_name, "octet-align")) {
1187 1 : if (!stricmp(param_val, "1"))
1188 1 : rtp->flags |= GF_RTP_AMR_ALIGN;
1189 : } /*ISMACryp config*/
1190 16 : else if (!stricmp(param_name, "ISMACrypCryptoSuite")) {
1191 0 : if (!stricmp(param_val, "AES_CTR_128"))
1192 0 : rtp->isma_scheme = GF_ISOM_ISMACRYP_SCHEME;
1193 : else
1194 0 : rtp->isma_scheme = 0;
1195 : }
1196 16 : else if (!stricmp(param_name, "ISMACrypSelectiveEncryption")) {
1197 0 : if (!stricmp(param_val, "1") || !stricmp(param_val, "true"))
1198 0 : rtp->flags |= GF_RTP_ISMA_SEL_ENC;
1199 : else
1200 0 : rtp->flags &= ~GF_RTP_ISMA_SEL_ENC;
1201 : }
1202 16 : else if (!stricmp(param_name, "ISMACrypIVLength"))
1203 0 : rtp->sl_map.IV_length = atoi(param_val);
1204 16 : else if (!stricmp(param_name, "ISMACrypDeltaIVLength"))
1205 0 : rtp->sl_map.IV_delta_length = atoi(param_val);
1206 16 : else if (!stricmp(param_name, "ISMACrypKeyIndicatorLength"))
1207 0 : rtp->sl_map.KI_length = atoi(param_val);
1208 16 : else if (!stricmp(param_name, "ISMACrypKeyIndicatorPerAU")) {
1209 0 : if (!stricmp(param_val, "1") || !stricmp(param_val, "true"))
1210 0 : rtp->flags |= GF_RTP_ISMA_HAS_KEY_IDX;
1211 : else
1212 0 : rtp->flags &= ~GF_RTP_ISMA_HAS_KEY_IDX;
1213 16 : } else if (!stricmp(param_name, "ISMACrypKey")) {
1214 0 : rtp->key = gf_strdup(param_val);
1215 : }
1216 : return GF_OK;
1217 : }
1218 :
1219 20 : static GF_Err gf_rtp_payt_setup(GF_RTPDepacketizer *rtp, GF_RTPMap *map, GF_SDPMedia *media)
1220 : {
1221 : u32 i, j;
1222 : GF_SDP_FMTP *fmtp;
1223 :
1224 : /*reset sl map*/
1225 20 : memset(&rtp->sl_map, 0, sizeof(GP_RTPSLMap));
1226 :
1227 20 : if (map && !stricmp(map->payload_name, "enc-mpeg4-generic")) rtp->flags |= GF_RTP_HAS_ISMACRYP;
1228 :
1229 :
1230 : /*then process all FMTPs*/
1231 20 : if (media) {
1232 19 : i=0;
1233 53 : while ((fmtp = (GF_SDP_FMTP*)gf_list_enum(media->FMTP, &i))) {
1234 : GF_X_Attribute *att;
1235 : //we work with only one PayloadType for now
1236 15 : if (map && (fmtp->PayloadType != map->PayloadType)) continue;
1237 15 : j=0;
1238 120 : while ((att = (GF_X_Attribute *)gf_list_enum(fmtp->Attributes, &j))) {
1239 90 : payt_set_param(rtp, att->Name, att->Value);
1240 : }
1241 : }
1242 : }
1243 :
1244 20 : switch (rtp->payt) {
1245 : #ifndef GPAC_DISABLE_AV_PARSERS
1246 1 : case GF_RTP_PAYT_LATM:
1247 : {
1248 : u32 AudioMuxVersion, AllStreamsSameTime, numSubFrames, numPrograms, numLayers, ch_cfg;
1249 : GF_M4ADecSpecInfo cfg;
1250 1 : char *latm_dsi = rtp->sl_map.config;
1251 1 : GF_BitStream *bs = gf_bs_new(latm_dsi, rtp->sl_map.configSize, GF_BITSTREAM_READ);
1252 1 : AudioMuxVersion = gf_bs_read_int(bs, 1);
1253 1 : AllStreamsSameTime = gf_bs_read_int(bs, 1);
1254 1 : numSubFrames = gf_bs_read_int(bs, 6);
1255 1 : numPrograms = gf_bs_read_int(bs, 4);
1256 1 : numLayers = gf_bs_read_int(bs, 3);
1257 :
1258 1 : if (AudioMuxVersion || !AllStreamsSameTime || numSubFrames || numPrograms || numLayers) {
1259 0 : gf_bs_del(bs);
1260 0 : return GF_NOT_SUPPORTED;
1261 : }
1262 : memset(&cfg, 0, sizeof(cfg));
1263 1 : cfg.base_object_type = gf_bs_read_int(bs, 5);
1264 1 : cfg.base_sr_index = gf_bs_read_int(bs, 4);
1265 1 : if (cfg.base_sr_index == 0x0F) {
1266 0 : cfg.base_sr = gf_bs_read_int(bs, 24);
1267 : } else {
1268 1 : cfg.base_sr = GF_M4ASampleRates[cfg.base_sr_index];
1269 : }
1270 1 : ch_cfg = gf_bs_read_int(bs, 4);
1271 1 : if (cfg.base_object_type==5 || cfg.base_object_type==29) {
1272 0 : if (cfg.base_object_type==29) {
1273 0 : cfg.has_ps = 1;
1274 0 : cfg.nb_chan = 1;
1275 : }
1276 0 : cfg.has_sbr = 1;
1277 0 : cfg.sbr_sr_index = gf_bs_read_int(bs, 4);
1278 0 : if (cfg.sbr_sr_index == 0x0F) {
1279 0 : cfg.sbr_sr = gf_bs_read_int(bs, 24);
1280 : } else {
1281 0 : cfg.sbr_sr = GF_M4ASampleRates[cfg.sbr_sr_index];
1282 : }
1283 0 : cfg.sbr_object_type = gf_bs_read_int(bs, 5);
1284 : }
1285 1 : gf_bs_del(bs);
1286 1 : gf_free(rtp->sl_map.config);
1287 1 : bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
1288 : /*write as regular AAC*/
1289 1 : gf_bs_write_int(bs, cfg.base_object_type, 5);
1290 1 : gf_bs_write_int(bs, cfg.base_sr_index, 4);
1291 :
1292 1 : gf_bs_write_int(bs, ch_cfg, 4);
1293 1 : gf_bs_align(bs);
1294 1 : gf_bs_get_content(bs, &rtp->sl_map.config, &rtp->sl_map.configSize);
1295 1 : gf_bs_del(bs);
1296 1 : rtp->sl_map.StreamType = GF_STREAM_AUDIO;
1297 1 : rtp->sl_map.CodecID = GF_CODECID_AAC_MPEG4;
1298 1 : rtp->sl_hdr.au_duration = 1024;
1299 1 : if (cfg.base_sr && map && (cfg.base_sr!=map->ClockRate)) {
1300 0 : rtp->sl_hdr.au_duration *= map->ClockRate;
1301 0 : rtp->sl_hdr.au_duration /= cfg.base_sr;
1302 : }
1303 :
1304 : /*assign depacketizer*/
1305 1 : rtp->depacketize = gf_rtp_parse_latm;
1306 : }
1307 1 : break;
1308 : #endif
1309 8 : case GF_RTP_PAYT_MPEG4:
1310 : /*mark if AU header is present*/
1311 8 : rtp->sl_map.auh_first_min_len = 0;
1312 8 : if (rtp->flags & GF_RTP_HAS_ISMACRYP) {
1313 0 : if (!rtp->isma_scheme) rtp->isma_scheme = GF_ISOM_ISMACRYP_SCHEME;
1314 0 : if (!rtp->sl_map.IV_length) rtp->sl_map.IV_length = 4;
1315 :
1316 0 : if (rtp->flags & GF_RTP_ISMA_SEL_ENC) rtp->sl_map.auh_first_min_len += 8;
1317 0 : else rtp->sl_map.auh_first_min_len += 8*(rtp->sl_map.IV_length + rtp->sl_map.KI_length);
1318 : }
1319 8 : rtp->sl_map.auh_first_min_len += rtp->sl_map.CTSDeltaLength;
1320 8 : rtp->sl_map.auh_first_min_len += rtp->sl_map.DTSDeltaLength;
1321 8 : rtp->sl_map.auh_first_min_len += rtp->sl_map.SizeLength;
1322 8 : rtp->sl_map.auh_first_min_len += rtp->sl_map.RandomAccessIndication;
1323 8 : rtp->sl_map.auh_first_min_len += rtp->sl_map.StreamStateIndication;
1324 : rtp->sl_map.auh_min_len = rtp->sl_map.auh_first_min_len;
1325 8 : rtp->sl_map.auh_first_min_len += rtp->sl_map.IndexLength;
1326 8 : rtp->sl_map.auh_min_len += rtp->sl_map.IndexDeltaLength;
1327 8 : if (!map) {
1328 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_RTP, ("[RTP] Missing required payload map\n"));
1329 : return GF_NON_COMPLIANT_BITSTREAM;
1330 : }
1331 : /*RFC3016 flags*/
1332 8 : if (!stricmp(map->payload_name, "MP4V-ES")) {
1333 1 : rtp->sl_map.StreamType = GF_STREAM_VISUAL;
1334 1 : rtp->sl_map.CodecID = GF_CODECID_MPEG4_PART2;
1335 : }
1336 7 : else if (!strnicmp(map->payload_name, "AAC", 3)) {
1337 0 : rtp->sl_map.StreamType = GF_STREAM_AUDIO;
1338 0 : rtp->sl_map.CodecID = GF_CODECID_AAC_MPEG4;
1339 : }
1340 7 : else if (!stricmp(map->payload_name, "MP4A-LATM")) {
1341 0 : rtp->sl_map.StreamType = GF_STREAM_AUDIO;
1342 0 : rtp->sl_map.CodecID = GF_CODECID_AAC_MPEG4;
1343 : }
1344 : /*MPEG-4 video, check RAPs if not indicated*/
1345 8 : if ((rtp->sl_map.StreamType == GF_STREAM_VISUAL) && (rtp->sl_map.CodecID == GF_CODECID_MPEG4_PART2) && !rtp->sl_map.RandomAccessIndication) {
1346 1 : rtp->flags |= GF_RTP_M4V_CHECK_RAP;
1347 : }
1348 : #ifndef GPAC_DISABLE_AV_PARSERS
1349 8 : if ((rtp->sl_map.CodecID == GF_CODECID_AAC_MPEG4) && !rtp->sl_map.config && media) {
1350 : GF_M4ADecSpecInfo cfg;
1351 0 : GF_RTPMap *a_map = (GF_RTPMap*)gf_list_get(media->RTPMaps, 0);
1352 :
1353 : memset(&cfg, 0, sizeof(GF_M4ADecSpecInfo));
1354 0 : cfg.audioPL = rtp->sl_map.PL_ID;
1355 0 : cfg.nb_chan = a_map->AudioChannels ? a_map->AudioChannels : 1;
1356 0 : cfg.base_sr = a_map->ClockRate/2;
1357 0 : cfg.sbr_sr = a_map->ClockRate;
1358 0 : cfg.base_object_type = GF_M4A_AAC_SBR;
1359 0 : cfg.sbr_object_type = GF_M4A_AAC_MAIN;
1360 0 : gf_m4a_write_config(&cfg, &rtp->sl_map.config, &rtp->sl_map.configSize);
1361 : }
1362 : #endif
1363 : /*assign depacketizer*/
1364 8 : rtp->depacketize = gf_rtp_parse_mpeg4;
1365 8 : break;
1366 : #ifndef GPAC_DISABLE_AV_PARSERS
1367 1 : case GF_RTP_PAYT_MPEG12_AUDIO:
1368 1 : rtp->sl_map.StreamType = GF_STREAM_AUDIO;
1369 1 : rtp->sl_map.CodecID = GF_CODECID_MPEG2_PART3;
1370 : /*assign depacketizer*/
1371 1 : rtp->depacketize = gf_rtp_parse_mpeg12_audio;
1372 1 : break;
1373 : #endif /*GPAC_DISABLE_AV_PARSERS*/
1374 :
1375 1 : case GF_RTP_PAYT_MPEG12_VIDEO:
1376 : /*we signal RAPs*/
1377 1 : rtp->sl_map.RandomAccessIndication = GF_TRUE;
1378 1 : rtp->sl_map.StreamType = GF_STREAM_VISUAL;
1379 : /*FIXME: how to differentiate MPEG1 from MPEG2 video before any frame is received??*/
1380 1 : rtp->sl_map.CodecID = GF_CODECID_MPEG1;
1381 : /*assign depacketizer*/
1382 1 : rtp->depacketize = gf_rtp_parse_mpeg12_video;
1383 1 : break;
1384 1 : case GF_RTP_PAYT_AMR:
1385 : case GF_RTP_PAYT_AMR_WB:
1386 1 : rtp->sl_map.StreamType = GF_STREAM_AUDIO;
1387 1 : rtp->sl_map.CodecID = (rtp->payt == GF_RTP_PAYT_AMR) ? GF_CODECID_AMR : GF_CODECID_AMR_WB;
1388 : /*assign depacketizer*/
1389 1 : rtp->depacketize = gf_rtp_parse_amr;
1390 1 : break;
1391 1 : case GF_RTP_PAYT_H263:
1392 1 : if (media) {
1393 : GF_X_Attribute *att;
1394 1 : j=0;
1395 5 : while ((att = (GF_X_Attribute *)gf_list_enum(media->Attributes, &j))) {
1396 3 : if (stricmp(att->Name, "cliprect")) continue;
1397 : /*only get the display area*/
1398 1 : sscanf(att->Value, "%u,%u,%u,%u", &rtp->y, &rtp->x, &rtp->h, &rtp->w);
1399 : }
1400 : }
1401 1 : rtp->sl_map.StreamType = GF_STREAM_VISUAL;
1402 1 : rtp->sl_map.CodecID = GF_CODECID_H263;
1403 :
1404 : /*we signal RAPs*/
1405 1 : rtp->sl_map.RandomAccessIndication = GF_TRUE;
1406 :
1407 : /*assign depacketizer*/
1408 1 : rtp->depacketize = gf_rtp_parse_h263;
1409 1 : break;
1410 :
1411 : case GF_RTP_PAYT_3GPP_TEXT:
1412 : {
1413 : char *tx3g, *a_tx3g;
1414 : GF_BitStream *bs;
1415 : u32 nb_desc;
1416 : GF_TextConfig tcfg;
1417 : memset(&tcfg, 0, sizeof(GF_TextConfig));
1418 1 : tcfg.tag = GF_ODF_TEXT_CFG_TAG;
1419 1 : tcfg.Base3GPPFormat = 0x10;
1420 1 : tcfg.MPEGExtendedFormat = 0x10;
1421 1 : tcfg.profileLevel = 0x10;
1422 1 : if (!map || !media) {
1423 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_RTP, ("[RTP] Missing required payload map\n"));
1424 0 : return GF_NON_COMPLIANT_BITSTREAM;
1425 : }
1426 1 : tcfg.timescale = map->ClockRate;
1427 1 : tcfg.sampleDescriptionFlags = 1;
1428 : tx3g = NULL;
1429 :
1430 1 : i=0;
1431 3 : while ((fmtp = (GF_SDP_FMTP*)gf_list_enum(media->FMTP, &i))) {
1432 : GF_X_Attribute *att;
1433 1 : if (fmtp->PayloadType != map->PayloadType) continue;
1434 1 : j=0;
1435 11 : while ((att = (GF_X_Attribute *)gf_list_enum(fmtp->Attributes, &j))) {
1436 :
1437 10 : if (!stricmp(att->Name, "width")) tcfg.text_width = atoi(att->Value);
1438 9 : else if (!stricmp(att->Name, "height")) tcfg.text_height = atoi(att->Value);
1439 8 : else if (!stricmp(att->Name, "tx")) tcfg.horiz_offset = atoi(att->Value);
1440 7 : else if (!stricmp(att->Name, "ty")) tcfg.vert_offset = atoi(att->Value);
1441 6 : else if (!stricmp(att->Name, "layer")) tcfg.layer = atoi(att->Value);
1442 5 : else if (!stricmp(att->Name, "max-w")) tcfg.video_width = atoi(att->Value);
1443 4 : else if (!stricmp(att->Name, "max-h")) tcfg.video_height = atoi(att->Value);
1444 2 : else if (!stricmp(att->Name, "tx3g")) tx3g = att->Value;
1445 : }
1446 : }
1447 1 : if (!tx3g) return GF_NON_COMPLIANT_BITSTREAM;
1448 :
1449 1 : bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
1450 1 : gf_bs_write_u8(bs, tcfg.Base3GPPFormat);
1451 1 : gf_bs_write_u8(bs, tcfg.MPEGExtendedFormat); /*MPEGExtendedFormat*/
1452 1 : gf_bs_write_u8(bs, tcfg.profileLevel); /*profileLevel*/
1453 1 : gf_bs_write_u24(bs, tcfg.timescale);
1454 1 : gf_bs_write_int(bs, 0, 1); /*no alt formats*/
1455 1 : gf_bs_write_int(bs, tcfg.sampleDescriptionFlags, 2);
1456 1 : gf_bs_write_int(bs, 1, 1); /*we will write sample desc*/
1457 1 : gf_bs_write_int(bs, 1, 1); /*video info*/
1458 1 : gf_bs_write_int(bs, 0, 3); /*reserved, spec doesn't say the values*/
1459 1 : gf_bs_write_u8(bs, tcfg.layer);
1460 1 : gf_bs_write_u16(bs, tcfg.text_width);
1461 1 : gf_bs_write_u16(bs, tcfg.text_height);
1462 : /*get all tx3g (comma separated)*/
1463 : nb_desc = 1;
1464 : a_tx3g = tx3g;
1465 2 : while ((a_tx3g = strchr(a_tx3g, ',')) ) {
1466 0 : a_tx3g ++;
1467 0 : nb_desc ++;
1468 : }
1469 : a_tx3g = tx3g;
1470 1 : gf_bs_write_u8(bs, nb_desc);
1471 : nb_desc = 1;
1472 0 : while (1) {
1473 : char *next_tx3g, szOut[1000];
1474 : u32 len, s_len;
1475 1 : next_tx3g = strchr(a_tx3g, ',');
1476 1 : if (next_tx3g) s_len = (u32) (next_tx3g - a_tx3g - 1);
1477 1 : else s_len = (u32) strlen(a_tx3g);
1478 :
1479 1 : len = gf_base64_decode(a_tx3g, s_len, szOut, 1000);
1480 : nb_desc++;
1481 1 : gf_bs_write_data(bs, szOut, len);
1482 1 : if (!next_tx3g) break;
1483 0 : a_tx3g = strchr(a_tx3g, ',');
1484 0 : if (!a_tx3g) break;
1485 0 : a_tx3g += 1;
1486 0 : while (a_tx3g[0] == ' ') a_tx3g += 1;
1487 : }
1488 :
1489 : /*write video cfg*/
1490 1 : gf_bs_write_u16(bs, tcfg.video_width);
1491 1 : gf_bs_write_u16(bs, tcfg.video_height);
1492 1 : gf_bs_write_u16(bs, tcfg.horiz_offset);
1493 1 : gf_bs_write_u16(bs, tcfg.vert_offset);
1494 1 : gf_bs_get_content(bs, &rtp->sl_map.config, &rtp->sl_map.configSize);
1495 1 : rtp->sl_map.StreamType = GF_STREAM_TEXT;
1496 1 : rtp->sl_map.CodecID = GF_CODECID_TEXT_MPEG4;
1497 1 : gf_bs_del(bs);
1498 : /*assign depacketizer*/
1499 1 : rtp->depacketize = gf_rtp_parse_ttxt;
1500 : }
1501 : break;
1502 : #ifndef GPAC_DISABLE_AV_PARSERS
1503 3 : case GF_RTP_PAYT_H264_AVC:
1504 : case GF_RTP_PAYT_H264_SVC:
1505 : {
1506 : GF_AVCConfig *avcc;
1507 3 : if (!map || !media) {
1508 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_RTP, ("[RTP] Missing required payload map\n"));
1509 : return GF_NON_COMPLIANT_BITSTREAM;
1510 : }
1511 :
1512 3 : avcc = gf_odf_avc_cfg_new();
1513 3 : avcc->AVCProfileIndication = (rtp->sl_map.PL_ID>>16) & 0xFF;
1514 3 : avcc->profile_compatibility = (rtp->sl_map.PL_ID>>8) & 0xFF;
1515 3 : avcc->AVCLevelIndication = rtp->sl_map.PL_ID & 0xFF;
1516 3 : avcc->configurationVersion = 1;
1517 3 : avcc->nal_unit_size = 4;
1518 3 : rtp->sl_map.StreamType = 4;
1519 3 : rtp->sl_map.CodecID = GF_CODECID_AVC;
1520 : /*we will signal RAPs*/
1521 3 : rtp->sl_map.RandomAccessIndication = GF_TRUE;
1522 : /*rewrite sps and pps*/
1523 3 : i=0;
1524 9 : while ((fmtp = (GF_SDP_FMTP*)gf_list_enum(media->FMTP, &i))) {
1525 : GF_X_Attribute *att;
1526 3 : if (fmtp->PayloadType != map->PayloadType) continue;
1527 3 : j=0;
1528 15 : while ((att = (GF_X_Attribute *)gf_list_enum(fmtp->Attributes, &j))) {
1529 : char *nal_ptr, *sep;
1530 9 : if (stricmp(att->Name, "sprop-parameter-sets")) continue;
1531 :
1532 3 : nal_ptr = att->Value;
1533 9 : while (nal_ptr) {
1534 : u32 nalt, b64size, ret;
1535 : char *b64_d;
1536 :
1537 6 : sep = strchr(nal_ptr, ',');
1538 6 : if (sep) sep[0] = 0;
1539 :
1540 6 : b64size = (u32) strlen(nal_ptr);
1541 6 : b64_d = (char*)gf_malloc(sizeof(char)*b64size);
1542 6 : ret = gf_base64_decode(nal_ptr, b64size, b64_d, b64size);
1543 6 : b64_d[ret] = 0;
1544 :
1545 6 : nalt = b64_d[0] & 0x1F;
1546 6 : if (/*SPS*/(nalt==0x07) || /*PPS*/(nalt==0x08) || /*SSPS*/(nalt==0x0F)) {
1547 6 : GF_NALUFFParam *sl = (GF_NALUFFParam *)gf_malloc(sizeof(GF_NALUFFParam));
1548 6 : sl->size = ret;
1549 6 : sl->data = (char*)gf_malloc(sizeof(char)*sl->size);
1550 6 : memcpy(sl->data, b64_d, sizeof(char)*sl->size);
1551 6 : if (nalt==0x07 || nalt==0x0F) {
1552 3 : gf_list_add(avcc->sequenceParameterSets, sl);
1553 : } else {
1554 3 : gf_list_add(avcc->pictureParameterSets, sl);
1555 : }
1556 : }
1557 6 : gf_free(b64_d);
1558 :
1559 6 : if (sep) {
1560 3 : sep[0] = ',';
1561 3 : nal_ptr = sep+1;
1562 : } else {
1563 : break;
1564 : }
1565 : }
1566 : }
1567 : }
1568 3 : if (gf_list_count(avcc->sequenceParameterSets) && gf_list_count(avcc->pictureParameterSets)) {
1569 3 : gf_odf_avc_cfg_write(avcc, &rtp->sl_map.config, &rtp->sl_map.configSize);
1570 : } else {
1571 0 : rtp->flags |= GF_RTP_AVC_USE_ANNEX_B;
1572 : }
1573 3 : gf_odf_avc_cfg_del(avcc);
1574 : }
1575 : /*assign depacketizer*/
1576 3 : rtp->depacketize = gf_rtp_parse_h264;
1577 3 : break;
1578 1 : case GF_RTP_PAYT_HEVC:
1579 : case GF_RTP_PAYT_LHVC:
1580 : #ifndef GPAC_DISABLE_HEVC
1581 : {
1582 : GF_HEVCConfig *hevcc;
1583 1 : if (!map || !media) {
1584 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_RTP, ("[RTP] Missing required payload map\n"));
1585 : return GF_NON_COMPLIANT_BITSTREAM;
1586 : }
1587 1 : hevcc = gf_odf_hevc_cfg_new();
1588 1 : hevcc->configurationVersion = 1;
1589 1 : hevcc->nal_unit_size = 4;
1590 1 : rtp->sl_map.StreamType = 4;
1591 1 : rtp->sl_map.CodecID = GF_CODECID_HEVC;
1592 : /*we will signal RAPs*/
1593 1 : rtp->sl_map.RandomAccessIndication = GF_TRUE;
1594 1 : i=0;
1595 3 : while ((fmtp = (GF_SDP_FMTP*)gf_list_enum(media->FMTP, &i))) {
1596 : GF_X_Attribute *att;
1597 1 : if (fmtp->PayloadType != map->PayloadType) continue;
1598 1 : j=0;
1599 5 : while ((att = (GF_X_Attribute *)gf_list_enum(fmtp->Attributes, &j))) {
1600 : char *nal_ptr, *sep;
1601 : GF_NALUFFParamArray *ar;
1602 3 : if (!stricmp(att->Name, "sprop-vps")) {
1603 1 : GF_SAFEALLOC(ar, GF_NALUFFParamArray);
1604 1 : if (!ar) return GF_OUT_OF_MEM;
1605 1 : ar->nalus = gf_list_new();
1606 1 : ar->type = GF_HEVC_NALU_VID_PARAM;
1607 : }
1608 2 : else if (!stricmp(att->Name, "sprop-sps")) {
1609 1 : GF_SAFEALLOC(ar, GF_NALUFFParamArray);
1610 1 : if (!ar) return GF_OUT_OF_MEM;
1611 1 : ar->nalus = gf_list_new();
1612 1 : ar->type = GF_HEVC_NALU_SEQ_PARAM;
1613 : }
1614 1 : else if (!stricmp(att->Name, "sprop-pps")) {
1615 1 : GF_SAFEALLOC(ar, GF_NALUFFParamArray);
1616 1 : if (!ar) return GF_OUT_OF_MEM;
1617 1 : ar->nalus = gf_list_new();
1618 1 : ar->type = GF_HEVC_NALU_PIC_PARAM;
1619 : }
1620 : else
1621 0 : continue;
1622 3 : nal_ptr = att->Value;
1623 6 : while (nal_ptr) {
1624 : u32 b64size, ret;
1625 : char *b64_d;
1626 : GF_NALUFFParam *sl;
1627 :
1628 3 : sep = strchr(nal_ptr, ',');
1629 3 : if (sep) sep[0] = 0;
1630 :
1631 3 : b64size = (u32) strlen(nal_ptr);
1632 3 : b64_d = (char*)gf_malloc(sizeof(char)*b64size);
1633 3 : ret = gf_base64_decode(nal_ptr, b64size, b64_d, b64size);
1634 3 : b64_d[ret] = 0;
1635 :
1636 3 : sl = (GF_NALUFFParam *)gf_malloc(sizeof(GF_NALUFFParam));
1637 3 : sl->size = ret;
1638 3 : sl->data = (char*)gf_malloc(sizeof(char)*sl->size);
1639 3 : memcpy(sl->data, b64_d, sizeof(char)*sl->size);
1640 3 : gf_list_add(ar->nalus, sl);
1641 :
1642 3 : gf_free(b64_d);
1643 :
1644 3 : if (sep) {
1645 0 : sep[0] = ',';
1646 0 : nal_ptr = sep+1;
1647 : } else {
1648 : break;
1649 : }
1650 : }
1651 3 : if (!hevcc->param_array) hevcc->param_array = gf_list_new();
1652 3 : gf_list_add(hevcc->param_array, ar);
1653 : }
1654 : }
1655 1 : gf_odf_hevc_cfg_write(hevcc, &rtp->sl_map.config, &rtp->sl_map.configSize);
1656 1 : gf_odf_hevc_cfg_del(hevcc);
1657 : }
1658 1 : rtp->depacketize = gf_rtp_parse_hevc;
1659 : #else
1660 : return GF_NOT_SUPPORTED;
1661 : #endif
1662 1 : break;
1663 : #endif /*GPAC_DISABLE_AV_PARSERS*/
1664 :
1665 : #if GPAC_ENABLE_3GPP_DIMS_RTP
1666 : /*todo - rewrite DIMS config*/
1667 : case GF_RTP_PAYT_3GPP_DIMS:
1668 : rtp->sl_map.StreamType = GF_STREAM_SCENE;
1669 : rtp->sl_map.CodecID = GF_CODECID_DIMS;
1670 : /*we will signal RAPs*/
1671 : rtp->sl_map.RandomAccessIndication = GF_TRUE;
1672 : /*we map DIMS CTR to AU seq num, hence 3 bits*/
1673 : rtp->sl_map.StreamStateIndication = 3;
1674 : rtp->sl_map.IndexLength = 3;
1675 : /*assign depacketizer*/
1676 : rtp->depacketize = gf_rtp_parse_3gpp_dims;
1677 : break;
1678 : #endif
1679 :
1680 : #ifndef GPAC_DISABLE_AV_PARSERS
1681 1 : case GF_RTP_PAYT_AC3:
1682 1 : rtp->sl_map.StreamType = GF_STREAM_AUDIO;
1683 1 : rtp->sl_map.CodecID = GF_CODECID_AC3;
1684 1 : rtp->sl_map.RandomAccessIndication = GF_TRUE;
1685 : /*assign depacketizer*/
1686 1 : rtp->depacketize = gf_rtp_parse_ac3;
1687 1 : break;
1688 : #endif /*GPAC_DISABLE_AV_PARSERS*/
1689 1 : default:
1690 1 : if (rtp->payt >= GF_RTP_PAYT_LAST_STATIC_DEFINED)
1691 : return GF_NOT_SUPPORTED;
1692 1 : rtp->depacketize = gf_rtp_parse_pass_through;
1693 1 : return GF_OK;
1694 : }
1695 : return GF_OK;
1696 : }
1697 :
1698 : const GF_RTPStaticMap static_payloads [] =
1699 : {
1700 : { GF_RTP_PAYT_PCMU, 8000, GF_STREAM_AUDIO},
1701 : { GF_RTP_PAYT_GSM, 8000, GF_STREAM_AUDIO},
1702 : { GF_RTP_PAYT_G723, 8000, GF_STREAM_AUDIO},
1703 : { GF_RTP_PAYT_DVI4_8K, 8000, GF_STREAM_AUDIO},
1704 : { GF_RTP_PAYT_DVI4_16K, 16000, GF_STREAM_AUDIO},
1705 : { GF_RTP_PAYT_LPC, 8000, GF_STREAM_AUDIO},
1706 : { GF_RTP_PAYT_PCMA, 8000, GF_STREAM_AUDIO},
1707 : { GF_RTP_PAYT_G722, 8000, GF_STREAM_AUDIO},
1708 : { GF_RTP_PAYT_L16_STEREO, 44100, GF_STREAM_AUDIO},
1709 : { GF_RTP_PAYT_L16_MONO, 44100, GF_STREAM_AUDIO},
1710 : { GF_RTP_PAYT_QCELP_BASIC, 8000, GF_STREAM_AUDIO},
1711 : { GF_RTP_PAYT_CN, 8000, GF_STREAM_AUDIO},
1712 : { GF_RTP_PAYT_MPEG12_AUDIO, 90000, GF_STREAM_AUDIO},
1713 : { GF_RTP_PAYT_G728, 8000, GF_STREAM_AUDIO},
1714 : { GF_RTP_PAYT_DVI4_11K, 11025, GF_STREAM_AUDIO},
1715 : { GF_RTP_PAYT_DVI4_22K, 22050, GF_STREAM_AUDIO},
1716 : { GF_RTP_PAYT_G729, 8000, GF_STREAM_AUDIO},
1717 : { GF_RTP_PAYT_CelB, 90000, GF_STREAM_VISUAL},
1718 : { GF_RTP_PAYT_JPEG, 90000, GF_STREAM_VISUAL},
1719 : { GF_RTP_PAYT_nv, 90000, GF_STREAM_VISUAL},
1720 : { GF_RTP_PAYT_H261, 90000, GF_STREAM_VISUAL},
1721 : { GF_RTP_PAYT_MPEG12_VIDEO, 90000, GF_STREAM_VISUAL},
1722 : { GF_RTP_PAYT_MP2T, 90000, GF_STREAM_FILE, 0, "video/mp2t"},
1723 : { GF_RTP_PAYT_H263, 90000, GF_STREAM_VISUAL}
1724 : };
1725 :
1726 : static const GF_RTPStaticMap *gf_rtp_is_valid_static_payt(u32 payt)
1727 : {
1728 : u32 i, count = sizeof(static_payloads) / sizeof(struct rtp_static_payt);
1729 1 : if (payt>= GF_RTP_PAYT_LAST_STATIC_DEFINED) return NULL;
1730 22 : for (i=0; i<count; i++) {
1731 23 : if (static_payloads[i].fmt == payt) {
1732 1 : return &static_payloads[i];
1733 : }
1734 : }
1735 : return NULL;
1736 : }
1737 :
1738 :
1739 : GF_EXPORT
1740 21 : GF_RTPDepacketizer *gf_rtp_depacketizer_new(GF_SDPMedia *media, u32 hdr_payt, gf_rtp_packet_cbk sl_packet_cbk, void *udta)
1741 : {
1742 : GF_Err e;
1743 : GF_RTPMap *map = NULL;
1744 : u32 payt;
1745 : GF_RTPDepacketizer *tmp;
1746 : u32 clock_rate;
1747 : const GF_RTPStaticMap *static_map = NULL;
1748 :
1749 : /*check RTP map. For now we only support 1 RTPMap*/
1750 21 : if (!sl_packet_cbk || (!media && !hdr_payt)) return NULL;
1751 21 : if (media && (gf_list_count(media->RTPMaps) > 1)) return NULL;
1752 :
1753 : #ifdef GPAC_ENABEL_COVERAGE
1754 : if (gf_sys_is_cov_mode())
1755 : gf_rtp_is_valid_static_payt(22);
1756 : #endif
1757 :
1758 21 : if (!media) {
1759 : static_map = gf_rtp_is_valid_static_payt(hdr_payt);
1760 1 : if (!static_map) {
1761 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_RTP, ("RTP: Invalid/unsupported static payload type %d\n", hdr_payt));
1762 : return NULL;
1763 : }
1764 1 : clock_rate = static_map->clock_rate;
1765 : payt = hdr_payt;
1766 : } else {
1767 : /*check payload type*/
1768 20 : map = (GF_RTPMap *)gf_list_get(media->RTPMaps, 0);
1769 20 : if (!map) {
1770 : //we deal with at most one format
1771 0 : if (!media->fmt_list || strchr(media->fmt_list, ' ')) return NULL;
1772 :
1773 0 : payt = atoi(media->fmt_list);
1774 : static_map = gf_rtp_is_valid_static_payt(payt);
1775 0 : if (!static_map) {
1776 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_RTP, ("RTP: Invalid static payload type %d\n", payt));
1777 : return NULL;
1778 : }
1779 0 : clock_rate = static_map->clock_rate;
1780 : } else {
1781 20 : payt = gf_rtp_get_payload_type(map, media);
1782 20 : if (!payt) return NULL;
1783 19 : clock_rate = map->ClockRate;
1784 : }
1785 : }
1786 :
1787 20 : GF_SAFEALLOC(tmp, GF_RTPDepacketizer);
1788 20 : if (!tmp) return NULL;
1789 20 : tmp->payt = payt;
1790 20 : tmp->static_map = static_map;
1791 :
1792 20 : e = gf_rtp_payt_setup(tmp, map, media);
1793 20 : if (e) {
1794 0 : gf_free(tmp);
1795 0 : return NULL;
1796 : }
1797 :
1798 : assert(tmp->depacketize);
1799 20 : tmp->clock_rate = clock_rate;
1800 20 : tmp->on_sl_packet = sl_packet_cbk;
1801 20 : tmp->udta = udta;
1802 20 : return tmp;
1803 : }
1804 :
1805 : GF_EXPORT
1806 52 : void gf_rtp_depacketizer_reset(GF_RTPDepacketizer *rtp, Bool full_reset)
1807 : {
1808 52 : if (rtp) {
1809 51 : if (rtp->inter_bs) gf_bs_del(rtp->inter_bs);
1810 51 : rtp->inter_bs = NULL;
1811 51 : rtp->flags |= GF_RTP_NEW_AU;
1812 51 : if (full_reset) {
1813 19 : u32 dur = rtp->sl_hdr.au_duration;
1814 19 : memset(&rtp->sl_hdr, 0, sizeof(GF_SLHeader));
1815 19 : rtp->sl_hdr.au_duration = dur;
1816 : }
1817 : }
1818 52 : }
1819 :
1820 : GF_EXPORT
1821 20 : void gf_rtp_depacketizer_del(GF_RTPDepacketizer *rtp)
1822 : {
1823 20 : if (rtp) {
1824 20 : gf_rtp_depacketizer_reset(rtp, GF_FALSE);
1825 20 : if (rtp->sl_map.config) gf_free(rtp->sl_map.config);
1826 20 : if (rtp->key) gf_free(rtp->key);
1827 20 : gf_free(rtp);
1828 : }
1829 20 : }
1830 :
1831 : GF_EXPORT
1832 755 : void gf_rtp_depacketizer_process(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, u8 *payload, u32 size)
1833 : {
1834 : assert(rtp && rtp->depacketize);
1835 755 : rtp->sl_hdr.sender_ntp = hdr->recomputed_ntp_ts;
1836 755 : rtp->depacketize(rtp, hdr, payload, size);
1837 755 : }
1838 :
1839 :
1840 : #if 0 //unused
1841 : void gf_rtp_depacketizer_get_slconfig(GF_RTPDepacketizer *rtp, GF_SLConfig *slc)
1842 : {
1843 : memset(slc, 0, sizeof(GF_SLConfig));
1844 : slc->tag = GF_ODF_SLC_TAG;
1845 :
1846 : slc->AULength = rtp->sl_map.ConstantSize;
1847 : if (rtp->sl_map.ConstantDuration) {
1848 : slc->CUDuration = slc->AUDuration = rtp->sl_map.ConstantDuration;
1849 : } else {
1850 : slc->CUDuration = slc->AUDuration = rtp->sl_hdr.au_duration;
1851 : }
1852 : /*AUSeqNum is only signaled if streamState is used (eg for carrouselling); otherwise we ignore it*/
1853 : slc->AUSeqNumLength = rtp->sl_map.StreamStateIndication;
1854 : slc->no_dts_signaling = rtp->sl_map.DTSDeltaLength ? GF_FALSE : GF_TRUE;
1855 :
1856 :
1857 : /*RTP SN is on 16 bits*/
1858 : slc->packetSeqNumLength = 0;
1859 : /*RTP TS is on 32 bits*/
1860 : slc->timestampLength = 32;
1861 : slc->timeScale = slc->timestampResolution = rtp->clock_rate;
1862 : slc->useTimestampsFlag = 1;
1863 :
1864 : /*we override these flags because we emulate the flags through the marker bit */
1865 : slc->useAccessUnitEndFlag = slc->useAccessUnitStartFlag = 1;
1866 : slc->useRandomAccessPointFlag = rtp->sl_map.RandomAccessIndication;
1867 : /*checking RAP for video*/
1868 : if (rtp->flags & GF_RTP_M4V_CHECK_RAP) {
1869 : slc->useRandomAccessPointFlag = 1;
1870 : slc->hasRandomAccessUnitsOnlyFlag = 0;
1871 : }
1872 :
1873 : /*try to signal caroussel if not set in StreamState*/
1874 : if (!slc->AUSeqNumLength && rtp->sl_map.RandomAccessIndication) {
1875 : switch (rtp->sl_map.StreamType) {
1876 : case GF_STREAM_OD:
1877 : case GF_STREAM_SCENE:
1878 : slc->AUSeqNumLength = rtp->sl_map.IndexLength;
1879 : break;
1880 : }
1881 : }
1882 : }
1883 : #endif
1884 :
1885 :
1886 : #endif /*GPAC_DISABLE_STREAMING*/
|