Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Jean Le Feuvre
5 : * Copyright (c) Telecom ParisTech 2000-2012
6 : * All rights reserved
7 : *
8 : * This file is part of GPAC / IETF RTP/RTSP/SDP 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/ietf_dev.h>
27 :
28 : #ifndef GPAC_DISABLE_STREAMING
29 :
30 : #include <gpac/constants.h>
31 : #include <gpac/maths.h>
32 :
33 : void InitSL_RTP(GF_SLConfig *slc);
34 :
35 :
36 :
37 :
38 : GF_EXPORT
39 110 : GP_RTPPacketizer *gf_rtp_builder_new(u32 rtp_payt, GF_SLConfig *slc, u32 flags,
40 : void *cbk_obj,
41 : void (*OnNewPacket)(void *cbk, GF_RTPHeader *header),
42 : void (*OnPacketDone)(void *cbk, GF_RTPHeader *header),
43 : void (*OnDataReference)(void *cbk, u32 payload_size, u32 offset_from_orig),
44 : void (*OnData)(void *cbk, u8 *data, u32 data_size, Bool is_head)
45 : )
46 : {
47 : GP_RTPPacketizer *tmp;
48 110 : if (!rtp_payt || !cbk_obj || !OnPacketDone) return NULL;
49 :
50 110 : GF_SAFEALLOC(tmp, GP_RTPPacketizer);
51 110 : if (!tmp) return NULL;
52 :
53 110 : if (slc) {
54 110 : memcpy(&tmp->sl_config, slc, sizeof(GF_SLConfig));
55 : } else {
56 0 : memset(&tmp->sl_config, 0, sizeof(GF_SLConfig));
57 0 : tmp->sl_config.useTimestampsFlag = 1;
58 0 : tmp->sl_config.timestampLength = 32;
59 : }
60 110 : tmp->OnNewPacket = OnNewPacket;
61 110 : tmp->OnDataReference = OnDataReference;
62 110 : tmp->OnData = OnData;
63 110 : tmp->cbk_obj = cbk_obj;
64 110 : tmp->OnPacketDone = OnPacketDone;
65 110 : tmp->rtp_payt = rtp_payt;
66 110 : tmp->flags = flags;
67 : //default init
68 110 : tmp->sl_header.AU_sequenceNumber = 1;
69 110 : tmp->sl_header.packetSequenceNumber = 1;
70 :
71 : //we assume we start on a new AU
72 110 : tmp->sl_header.accessUnitStartFlag = 1;
73 110 : return tmp;
74 : }
75 :
76 : GF_EXPORT
77 110 : void gf_rtp_builder_del(GP_RTPPacketizer *builder)
78 : {
79 110 : if (!builder) return;
80 :
81 110 : if (builder->payload) gf_bs_del(builder->payload);
82 110 : if (builder->pck_hdr) gf_bs_del(builder->pck_hdr);
83 110 : gf_free(builder);
84 : }
85 :
86 : GF_EXPORT
87 70383 : GF_Err gf_rtp_builder_process(GP_RTPPacketizer *builder, u8 *data, u32 data_size, u8 IsAUEnd, u32 FullAUSize, u32 duration, u8 descIndex)
88 : {
89 70383 : if (!builder) return GF_BAD_PARAM;
90 :
91 70383 : switch (builder->rtp_payt) {
92 18214 : case GF_RTP_PAYT_MPEG4:
93 18214 : return gp_rtp_builder_do_mpeg4(builder, data, data_size, IsAUEnd, FullAUSize);
94 : #ifndef GPAC_DISABLE_AV_PARSERS
95 2065 : case GF_RTP_PAYT_MPEG12_VIDEO:
96 2065 : return gp_rtp_builder_do_mpeg12_video(builder, data, data_size, IsAUEnd, FullAUSize);
97 : #endif
98 3876 : case GF_RTP_PAYT_MPEG12_AUDIO:
99 3876 : return gp_rtp_builder_do_mpeg12_audio(builder, data, data_size, IsAUEnd, FullAUSize);
100 463 : case GF_RTP_PAYT_H263:
101 463 : return gp_rtp_builder_do_h263(builder, data, data_size, IsAUEnd, FullAUSize);
102 21421 : case GF_RTP_PAYT_AMR:
103 : case GF_RTP_PAYT_AMR_WB:
104 21421 : return gp_rtp_builder_do_amr(builder, data, data_size, IsAUEnd, FullAUSize);
105 1932 : case GF_RTP_PAYT_3GPP_TEXT:
106 1932 : return gp_rtp_builder_do_tx3g(builder, data, data_size, IsAUEnd, FullAUSize, duration, descIndex);
107 3721 : case GF_RTP_PAYT_H264_AVC:
108 : case GF_RTP_PAYT_H264_SVC:
109 3721 : return gp_rtp_builder_do_avc(builder, data, data_size, IsAUEnd, FullAUSize);
110 555 : case GF_RTP_PAYT_QCELP:
111 555 : return gp_rtp_builder_do_qcelp(builder, data, data_size, IsAUEnd, FullAUSize);
112 15185 : case GF_RTP_PAYT_EVRC_SMV:
113 15185 : return gp_rtp_builder_do_smv(builder, data, data_size, IsAUEnd, FullAUSize);
114 49 : case GF_RTP_PAYT_LATM:
115 49 : return gp_rtp_builder_do_latm(builder, data, data_size, IsAUEnd, FullAUSize, duration);
116 : #if GPAC_ENABLE_3GPP_DIMS_RTP
117 : case GF_RTP_PAYT_3GPP_DIMS:
118 : return gp_rtp_builder_do_dims(builder, data, data_size, IsAUEnd, FullAUSize, duration);
119 : #endif
120 61 : case GF_RTP_PAYT_AC3:
121 61 : return gp_rtp_builder_do_ac3(builder, data, data_size, IsAUEnd, FullAUSize);
122 2786 : case GF_RTP_PAYT_HEVC:
123 : case GF_RTP_PAYT_LHVC:
124 2786 : return gp_rtp_builder_do_hevc(builder, data, data_size, IsAUEnd, FullAUSize);
125 55 : case GF_RTP_PAYT_MP2T:
126 55 : return gp_rtp_builder_do_mp2t(builder, data, data_size, IsAUEnd, FullAUSize);
127 : default:
128 : return GF_NOT_SUPPORTED;
129 : }
130 : }
131 :
132 :
133 : //Compute the #params of the slMap
134 : GF_EXPORT
135 110 : void gf_rtp_builder_init(GP_RTPPacketizer *builder, u8 PayloadType, u32 PathMTU, u32 max_ptime,
136 : u32 StreamType, u32 codecid, u32 PL_ID,
137 : u32 avgSize, u32 maxSize,
138 : u32 avgTS, u32 maxDTS,
139 : u32 IV_length, u32 KI_length,
140 : char *pref_mode)
141 : {
142 : u32 k, ismacrypt_flags;
143 :
144 110 : memset(&builder->slMap, 0, sizeof(GP_RTPSLMap));
145 110 : builder->Path_MTU = PathMTU;
146 110 : builder->PayloadType = PayloadType;
147 110 : builder->slMap.StreamType = StreamType;
148 110 : builder->slMap.CodecID = codecid;
149 110 : builder->slMap.PL_ID = PL_ID;
150 110 : builder->max_ptime = max_ptime;
151 110 : if (pref_mode) strcpy(builder->slMap.mode, pref_mode);
152 :
153 :
154 : //some cst vars
155 110 : builder->rtp_header.Version = 2;
156 110 : builder->rtp_header.PayloadType = builder->PayloadType;
157 :
158 : /*our max config is with 1 packet only (SingleSL)*/
159 110 : builder->first_sl_in_rtp = GF_TRUE;
160 : /*no AUX data*/
161 110 : builder->slMap.AuxiliaryDataSizeLength = 0;
162 :
163 :
164 : /*just compute max aggregation size*/
165 110 : switch (builder->rtp_payt) {
166 8 : case GF_RTP_PAYT_QCELP:
167 : case GF_RTP_PAYT_EVRC_SMV:
168 : case GF_RTP_PAYT_AMR:
169 : case GF_RTP_PAYT_AMR_WB:
170 : {
171 : u32 nb_pck = 1;
172 : u32 block_size = 160;
173 : /*compute max frames per packet - if no avg size, use max size per codec*/
174 8 : if (builder->flags & GP_RTP_PCK_USE_MULTI) {
175 0 : if (builder->rtp_payt == GF_RTP_PAYT_QCELP) {
176 0 : if (!avgSize) avgSize = 35;
177 0 : nb_pck = (PathMTU-1) / avgSize; /*one-byte header*/
178 0 : if (nb_pck>10) nb_pck=10; /*cf RFC2658*/
179 0 : } else if (builder->rtp_payt == GF_RTP_PAYT_EVRC_SMV) {
180 0 : if (!avgSize) avgSize = 23;
181 0 : nb_pck = (PathMTU) / avgSize;
182 0 : if (nb_pck>32) nb_pck=32; /*cf RFC3558*/
183 0 : } else if (builder->rtp_payt == GF_RTP_PAYT_AMR_WB) {
184 0 : if (!avgSize) avgSize = 61;
185 0 : nb_pck = (PathMTU-1) / avgSize;
186 : block_size = 320;
187 : } else {
188 0 : if (!avgSize) avgSize = 32;
189 0 : nb_pck = (PathMTU-1) / avgSize;
190 : }
191 0 : if (max_ptime) {
192 0 : u32 max_pck = max_ptime / block_size;
193 0 : if (nb_pck > max_pck) nb_pck = max_pck;
194 : }
195 : }
196 0 : if (nb_pck<=1) {
197 8 : builder->flags &= ~(GP_RTP_PCK_USE_MULTI|GP_RTP_PCK_USE_INTERLEAVING);
198 8 : builder->auh_size = 1;
199 : } else {
200 0 : builder->auh_size = nb_pck;
201 : }
202 : /*remove all MPEG-4 and ISMA flags */
203 8 : builder->flags &= 0x07;
204 : }
205 8 : return;
206 : case GF_RTP_PAYT_LATM:
207 : case GF_RTP_PAYT_MPEG4:
208 : break;
209 49 : default:
210 : /*remove all MPEG-4 and ISMA flags */
211 49 : builder->flags &= 0x07;
212 : /*disable aggregation for visual streams, except for AVC where STAP/MTAP can be used*/
213 49 : if (StreamType==GF_STREAM_VISUAL) {
214 27 : if ((codecid != GF_CODECID_AVC) && (codecid != GF_CODECID_SVC) && (codecid != GF_CODECID_MVC) && (codecid != GF_CODECID_HEVC) && (codecid != GF_CODECID_LHVC)) {
215 7 : builder->flags &= ~GP_RTP_PCK_USE_MULTI;
216 : }
217 : }
218 22 : else if (avgSize && (PathMTU <= avgSize) ) {
219 0 : builder->flags &= ~GP_RTP_PCK_USE_MULTI;
220 : }
221 : return;
222 : }
223 :
224 53 : builder->slMap.IV_length = IV_length;
225 53 : builder->slMap.KI_length = KI_length;
226 :
227 : ismacrypt_flags = 0;
228 53 : if (builder->flags & GP_RTP_PCK_SELECTIVE_ENCRYPTION) ismacrypt_flags |= GP_RTP_PCK_SELECTIVE_ENCRYPTION;
229 53 : if (builder->flags & GP_RTP_PCK_KEY_IDX_PER_AU) ismacrypt_flags |= GP_RTP_PCK_KEY_IDX_PER_AU;
230 :
231 : /*mode setup*/
232 53 : if (!strnicmp(builder->slMap.mode, "AAC", 3)) {
233 25 : builder->flags = GP_RTP_PCK_USE_MULTI | GP_RTP_PCK_SIGNAL_SIZE | GP_RTP_PCK_SIGNAL_AU_IDX | ismacrypt_flags;
234 : /*if (builder->flags & GP_RTP_PCK_USE_INTERLEAVING) */
235 25 : builder->slMap.ConstantDuration = avgTS;
236 :
237 : /*AAC LBR*/
238 25 : if (maxSize < 63) {
239 : strcpy(builder->slMap.mode, "AAC-lbr");
240 0 : builder->slMap.IndexLength = builder->slMap.IndexDeltaLength = 2;
241 0 : builder->slMap.SizeLength = 6;
242 : }
243 : /*AAC HBR*/
244 : else {
245 : strcpy(builder->slMap.mode, "AAC-hbr");
246 25 : builder->slMap.IndexLength = builder->slMap.IndexDeltaLength = 3;
247 25 : builder->slMap.SizeLength = 13;
248 : }
249 : goto check_header;
250 : }
251 28 : if (!strnicmp(builder->slMap.mode, "CELP", 4)) {
252 : /*CELP-cbr*/
253 0 : if (maxSize == avgSize) {
254 : /*reset flags (interleaving forbidden)*/
255 0 : builder->flags = GP_RTP_PCK_USE_MULTI | ismacrypt_flags;
256 : strcpy(builder->slMap.mode, "CELP-cbr");
257 0 : builder->slMap.ConstantSize = avgSize;
258 0 : builder->slMap.ConstantDuration = avgTS;
259 : }
260 : /*CELP VBR*/
261 : else {
262 : strcpy(builder->slMap.mode, "CELP-vbr");
263 0 : builder->slMap.IndexLength = builder->slMap.IndexDeltaLength = 2;
264 0 : builder->slMap.SizeLength = 6;
265 0 : /*if (builder->flags & GP_RTP_PCK_USE_INTERLEAVING) */builder->slMap.ConstantDuration = avgTS;
266 0 : builder->flags = GP_RTP_PCK_USE_MULTI | GP_RTP_PCK_SIGNAL_SIZE | GP_RTP_PCK_SIGNAL_AU_IDX | ismacrypt_flags;
267 : }
268 : goto check_header;
269 : }
270 :
271 : /*generic setup by flags*/
272 :
273 : /*size*/
274 28 : if (builder->flags & GP_RTP_PCK_SIGNAL_SIZE) {
275 0 : if (avgSize==maxSize) {
276 0 : builder->slMap.SizeLength = 0;
277 0 : builder->slMap.ConstantSize = maxSize;
278 : } else {
279 0 : builder->slMap.SizeLength = gf_get_bit_size(maxSize ? maxSize : PathMTU);
280 0 : builder->slMap.ConstantSize = 0;
281 : }
282 : } else {
283 28 : builder->slMap.SizeLength = 0;
284 28 : if (builder->flags & GP_RTP_PCK_USE_MULTI)
285 0 : builder->slMap.ConstantSize = (avgSize==maxSize) ? maxSize : 0;
286 : else
287 28 : builder->slMap.ConstantSize = 0;
288 : }
289 :
290 : /*single SL per RTP*/
291 28 : if (!(builder->flags & GP_RTP_PCK_USE_MULTI)) {
292 28 : if ( builder->sl_config.AUSeqNumLength && (builder->flags & GP_RTP_PCK_SIGNAL_AU_IDX)) {
293 0 : builder->slMap.IndexLength = builder->sl_config.AUSeqNumLength;
294 : } else {
295 28 : builder->slMap.IndexLength = 0;
296 : }
297 : /*one packet per RTP so no delta*/
298 28 : builder->slMap.IndexDeltaLength = 0;
299 28 : builder->slMap.IV_delta_length = 0;
300 :
301 : /*CTS Delta is always 0 since we have one SL packet per RTP*/
302 28 : builder->slMap.CTSDeltaLength = 0;
303 :
304 : /*DTS Delta depends on the video type*/
305 28 : if ((builder->flags & GP_RTP_PCK_SIGNAL_TS) && maxDTS )
306 6 : builder->slMap.DTSDeltaLength = gf_get_bit_size(maxDTS);
307 : else
308 22 : builder->slMap.DTSDeltaLength = 0;
309 :
310 : /*RAP*/
311 28 : if (builder->sl_config.useRandomAccessPointFlag && (builder->flags & GP_RTP_PCK_SIGNAL_RAP)) {
312 5 : builder->slMap.RandomAccessIndication = GF_TRUE;
313 : } else {
314 23 : builder->slMap.RandomAccessIndication = GF_FALSE;
315 : }
316 :
317 : /*stream state*/
318 28 : if (builder->flags & GP_RTP_PCK_SYSTEMS_CAROUSEL) {
319 1 : if (!builder->sl_config.AUSeqNumLength) builder->sl_config.AUSeqNumLength = 4;
320 1 : builder->slMap.StreamStateIndication = builder->sl_config.AUSeqNumLength;
321 : }
322 : goto check_header;
323 : }
324 :
325 : /*this is the avg samples we can store per RTP packet*/
326 0 : k = PathMTU / avgSize;
327 0 : if (k<=1) {
328 0 : builder->flags &= ~GP_RTP_PCK_USE_MULTI;
329 : /*keep TS signaling for B-frames (eg never default to M4V-ES when B-frames are present)*/
330 : //builder->flags &= ~GP_RTP_PCK_SIGNAL_TS;
331 0 : builder->flags &= ~GP_RTP_PCK_SIGNAL_SIZE;
332 0 : builder->flags &= ~GP_RTP_PCK_SIGNAL_AU_IDX;
333 0 : builder->flags &= ~GP_RTP_PCK_USE_INTERLEAVING;
334 0 : builder->flags &= ~GP_RTP_PCK_KEY_IDX_PER_AU;
335 0 : gf_rtp_builder_init(builder, PayloadType, PathMTU, max_ptime, StreamType, codecid, PL_ID, avgSize, maxSize, avgTS, maxDTS, IV_length, KI_length, pref_mode);
336 0 : return;
337 : }
338 :
339 : /*multiple SL per RTP - check if we have to send TS*/
340 0 : builder->slMap.ConstantDuration = builder->sl_config.CUDuration;
341 0 : if (!builder->slMap.ConstantDuration) {
342 0 : builder->flags |= GP_RTP_PCK_SIGNAL_TS;
343 : }
344 : /*if we have a constant duration and are not writting TSs, make sure we write AU IDX when interleaving*/
345 0 : else if (! (builder->flags & GP_RTP_PCK_SIGNAL_TS) && (builder->flags & GP_RTP_PCK_USE_INTERLEAVING)) {
346 0 : builder->flags |= GP_RTP_PCK_SIGNAL_AU_IDX;
347 : }
348 :
349 0 : if (builder->flags & GP_RTP_PCK_SIGNAL_TS) {
350 : /*compute CTS delta*/
351 0 : builder->slMap.CTSDeltaLength = gf_get_bit_size(k*avgTS);
352 :
353 : /*compute DTS delta. Delta is ALWAYS from the CTS of the same sample*/
354 0 : if (maxDTS)
355 0 : builder->slMap.DTSDeltaLength = gf_get_bit_size(maxDTS);
356 : else
357 0 : builder->slMap.DTSDeltaLength = 0;
358 : }
359 :
360 0 : if ((builder->flags & GP_RTP_PCK_SIGNAL_AU_IDX) && builder->sl_config.AUSeqNumLength) {
361 0 : builder->slMap.IndexLength = builder->sl_config.AUSeqNumLength;
362 : /*and k-1 AUs in Delta*/
363 0 : builder->slMap.IndexDeltaLength = (builder->flags & GP_RTP_PCK_USE_INTERLEAVING) ? gf_get_bit_size(k-1) : 0;
364 : }
365 0 : else if (builder->flags & GP_RTP_PCK_SYSTEMS_CAROUSEL) {
366 0 : if (!builder->sl_config.AUSeqNumLength) builder->sl_config.AUSeqNumLength = 4;
367 0 : builder->slMap.StreamStateIndication = builder->sl_config.AUSeqNumLength;
368 : }
369 :
370 : /*RAP*/
371 0 : if (builder->sl_config.useRandomAccessPointFlag && (builder->flags & GP_RTP_PCK_SIGNAL_RAP)) {
372 0 : builder->slMap.RandomAccessIndication = GF_TRUE;
373 : } else {
374 0 : builder->slMap.RandomAccessIndication = GF_FALSE;
375 : }
376 :
377 53 : check_header:
378 :
379 : /*IV delta only if interleaving (otherwise reconstruction from IV is trivial)*/
380 53 : if (IV_length && (builder->flags & GP_RTP_PCK_USE_INTERLEAVING)) {
381 0 : builder->slMap.IV_delta_length = gf_get_bit_size(maxSize);
382 : }
383 : /*ISMACryp video mode*/
384 53 : if ((builder->slMap.StreamType==GF_STREAM_VISUAL) && (builder->slMap.CodecID==GF_CODECID_MPEG4_PART2)
385 7 : && (builder->flags & GP_RTP_PCK_SIGNAL_RAP) && builder->slMap.IV_length
386 : && !(builder->flags & GP_RTP_PCK_SIGNAL_AU_IDX) && !(builder->flags & GP_RTP_PCK_SIGNAL_SIZE)
387 : /*shall have SignalTS*/
388 0 : && (builder->flags & GP_RTP_PCK_SIGNAL_TS) && !(builder->flags & GP_RTP_PCK_USE_MULTI)
389 : ) {
390 : strcpy(builder->slMap.mode, "mpeg4-video");
391 : }
392 : /*ISMACryp AVC video mode*/
393 53 : else if ((builder->slMap.StreamType==GF_STREAM_VISUAL) && (builder->slMap.CodecID==GF_CODECID_AVC)
394 1 : && (builder->flags & GP_RTP_PCK_SIGNAL_RAP) && builder->slMap.IV_length
395 : && !(builder->flags & GP_RTP_PCK_SIGNAL_AU_IDX) && !(builder->flags & GP_RTP_PCK_SIGNAL_SIZE)
396 : /*shall have SignalTS*/
397 1 : && (builder->flags & GP_RTP_PCK_SIGNAL_TS) && !(builder->flags & GP_RTP_PCK_USE_MULTI)
398 : ) {
399 : strcpy(builder->slMap.mode, "avc-video");
400 : }
401 :
402 : /*check if we use AU header or not*/
403 53 : if (!builder->slMap.SizeLength
404 53 : && !builder->slMap.IndexLength
405 : && !builder->slMap.IndexDeltaLength
406 28 : && !builder->slMap.DTSDeltaLength
407 : && !builder->slMap.CTSDeltaLength
408 22 : && !builder->slMap.RandomAccessIndication
409 : && !builder->slMap.IV_length
410 18 : && !builder->slMap.KI_length
411 : ) {
412 18 : builder->has_AU_header = GF_FALSE;
413 : } else {
414 35 : builder->has_AU_header = GF_TRUE;
415 : }
416 : }
417 :
418 932 : void gf_rtp_builder_set_cryp_info(GP_RTPPacketizer *builder, u64 IV, char *key_indicator, Bool is_encrypted)
419 : {
420 932 : if (!builder) return;
421 932 : if (!key_indicator) {
422 932 : if (builder->key_indicator) {
423 : /*force flush if no provision for keyIndicator per AU*/
424 0 : builder->force_flush = (builder->flags & GP_RTP_PCK_KEY_IDX_PER_AU) ? GF_FALSE : GF_TRUE;
425 0 : gf_free(builder->key_indicator);
426 0 : builder->key_indicator = NULL;
427 : }
428 0 : } else if (!builder->key_indicator
429 0 : ||
430 0 : memcmp(builder->key_indicator, key_indicator, sizeof(char)*builder->slMap.KI_length)
431 : ) {
432 : /*force flush if no provision for keyIndicator per AU*/
433 0 : builder->force_flush = (builder->flags & GP_RTP_PCK_KEY_IDX_PER_AU) ? GF_FALSE : GF_TRUE;
434 :
435 0 : if (!builder->key_indicator) builder->key_indicator = (char *) gf_malloc(sizeof(char)*builder->slMap.KI_length);
436 0 : memcpy(builder->key_indicator, key_indicator, sizeof(char)*builder->slMap.KI_length);
437 : }
438 932 : if (builder->IV != IV) {
439 0 : builder->IV = IV;
440 0 : if (builder->slMap.IV_delta_length && (builder->slMap.IV_delta_length < gf_get_bit_size((u32) (IV - builder->first_AU_IV) ))) {
441 0 : builder->first_AU_IV = IV;
442 0 : builder->force_flush = GF_TRUE;
443 : }
444 : }
445 932 : builder->is_encrypted = is_encrypted;
446 : }
447 :
448 : GF_EXPORT
449 182 : Bool gf_rtp_builder_get_payload_name(GP_RTPPacketizer *rtpb, char szPayloadName[20], char szMediaName[20])
450 : {
451 182 : u32 flags = rtpb->flags;
452 :
453 182 : switch (rtpb->rtp_payt) {
454 90 : case GF_RTP_PAYT_MPEG4:
455 90 : if ((rtpb->slMap.StreamType==GF_STREAM_VISUAL) && (rtpb->slMap.CodecID==GF_CODECID_MPEG4_PART2)) {
456 : strcpy(szMediaName, "video");
457 : /*ISMACryp video*/
458 12 : if ( (flags & GP_RTP_PCK_SIGNAL_RAP) && rtpb->slMap.IV_length
459 : && !(flags & GP_RTP_PCK_SIGNAL_AU_IDX) && !(flags & GP_RTP_PCK_SIGNAL_SIZE)
460 0 : && (flags & GP_RTP_PCK_SIGNAL_TS) && !(flags & GP_RTP_PCK_USE_MULTI)
461 : )
462 : {
463 : strcpy(szPayloadName, "enc-mpeg4-generic");
464 0 : return GF_TRUE;
465 : }
466 : /*mpeg4-generic*/
467 12 : if ( (flags & GP_RTP_PCK_SIGNAL_RAP) || (flags & GP_RTP_PCK_SIGNAL_AU_IDX) || (flags & GP_RTP_PCK_SIGNAL_SIZE)
468 12 : || (flags & GP_RTP_PCK_SIGNAL_TS) || (flags & GP_RTP_PCK_USE_MULTI) ) {
469 : strcpy(szPayloadName, "mpeg4-generic");
470 10 : return GF_TRUE;
471 : } else {
472 : strcpy(szPayloadName, "MP4V-ES");
473 2 : return GF_TRUE;
474 : }
475 : }
476 : /*for all other types*/
477 78 : if (rtpb->slMap.StreamType==GF_STREAM_AUDIO) strcpy(szMediaName, "audio");
478 37 : else if (rtpb->slMap.StreamType==GF_STREAM_MPEGJ) strcpy(szMediaName, "application");
479 : else strcpy(szMediaName, "video");
480 78 : strcpy(szPayloadName, rtpb->slMap.IV_length ? "enc-mpeg4-generic" : "mpeg4-generic");
481 78 : return GF_TRUE;
482 : case GF_RTP_PAYT_MPEG12_VIDEO:
483 : strcpy(szMediaName, "video");
484 : strcpy(szPayloadName, "MPV");
485 6 : return GF_TRUE;
486 : case GF_RTP_PAYT_MPEG12_AUDIO:
487 : strcpy(szMediaName, "audio");
488 : strcpy(szPayloadName, "MPA");
489 16 : return GF_TRUE;
490 : case GF_RTP_PAYT_H263:
491 : strcpy(szMediaName, "video");
492 : strcpy(szPayloadName, "H263-1998");
493 4 : return GF_TRUE;
494 : case GF_RTP_PAYT_AMR:
495 : strcpy(szMediaName, "audio");
496 : strcpy(szPayloadName, "AMR");
497 4 : return GF_TRUE;
498 : case GF_RTP_PAYT_AMR_WB:
499 : strcpy(szMediaName, "audio");
500 : strcpy(szPayloadName, "AMR-WB");
501 2 : return GF_TRUE;
502 : case GF_RTP_PAYT_3GPP_TEXT:
503 : strcpy(szMediaName, "text");
504 : strcpy(szPayloadName, "3gpp-tt");
505 16 : return GF_TRUE;
506 : case GF_RTP_PAYT_H264_AVC:
507 : strcpy(szMediaName, "video");
508 : strcpy(szPayloadName, "H264");
509 28 : return GF_TRUE;
510 : case GF_RTP_PAYT_QCELP:
511 : strcpy(szMediaName, "audio");
512 : strcpy(szPayloadName, "QCELP");
513 4 : return GF_TRUE;
514 : case GF_RTP_PAYT_EVRC_SMV:
515 : strcpy(szMediaName, "audio");
516 2 : if ((rtpb->slMap.CodecID==0xA0) || (rtpb->slMap.CodecID==GF_CODECID_EVRC))
517 : strcpy(szPayloadName, "EVRC");
518 : else
519 : strcpy(szPayloadName, "SMV");
520 :
521 : /*header-free version*/
522 2 : if (rtpb->auh_size<=1) strcat(szPayloadName, "0");
523 : return GF_TRUE;
524 : case GF_RTP_PAYT_LATM:
525 : strcpy(szMediaName, "audio");
526 : strcpy(szPayloadName, "MP4A-LATM");
527 2 : return GF_TRUE;
528 : #if GPAC_ENABLE_3GPP_DIMS_RTP
529 : case GF_RTP_PAYT_3GPP_DIMS:
530 : strcpy(szMediaName, "video");
531 : strcpy(szPayloadName, "richmedia+xml");
532 : return GF_TRUE;
533 : #endif
534 : case GF_RTP_PAYT_AC3:
535 : strcpy(szMediaName, "audio");
536 : strcpy(szPayloadName, "ac3");
537 4 : return GF_TRUE;
538 : case GF_RTP_PAYT_H264_SVC:
539 : strcpy(szMediaName, "video");
540 : strcpy(szPayloadName, "H264-SVC");
541 0 : return GF_TRUE;
542 : case GF_RTP_PAYT_HEVC:
543 : strcpy(szMediaName, "video");
544 : strcpy(szPayloadName, "H265");
545 4 : return GF_TRUE;
546 : case GF_RTP_PAYT_LHVC:
547 : strcpy(szMediaName, "video");
548 : strcpy(szPayloadName, "H265-SHVC");
549 0 : return GF_TRUE;
550 : default:
551 : strcpy(szMediaName, "");
552 : strcpy(szPayloadName, "");
553 0 : return GF_FALSE;
554 : }
555 : return GF_FALSE;
556 : }
557 :
558 :
559 : GF_EXPORT
560 53 : GF_Err gf_rtp_builder_format_sdp(GP_RTPPacketizer *builder, char *payload_name, char *sdpLine, char *dsi, u32 dsi_size)
561 : {
562 : char buffer[20100], dsiString[20000];
563 : u32 i, k;
564 : Bool is_first = GF_TRUE;
565 :
566 53 : if ((builder->rtp_payt!=GF_RTP_PAYT_MPEG4) && (builder->rtp_payt!=GF_RTP_PAYT_LATM) ) return GF_BAD_PARAM;
567 :
568 : #define SDP_ADD_INT(_name, _val) { if (!is_first) strcat(sdpLine, "; "); sprintf(buffer, "%s=%d", _name, _val); strcat(sdpLine, buffer); is_first = 0;}
569 : #define SDP_ADD_STR(_name, _val) { if (!is_first) strcat(sdpLine, "; "); sprintf(buffer, "%s=%s", _name, _val); strcat(sdpLine, buffer); is_first = 0;}
570 :
571 53 : sprintf(sdpLine, "a=fmtp:%d ", builder->PayloadType);
572 :
573 : /*mandatory fields*/
574 53 : if (builder->slMap.PL_ID) SDP_ADD_INT("profile-level-id", builder->slMap.PL_ID);
575 :
576 53 : if (builder->rtp_payt == GF_RTP_PAYT_LATM) SDP_ADD_INT("cpresent", 0);
577 :
578 53 : if (dsi && dsi_size) {
579 : k = 0;
580 7060 : for (i=0; i<dsi_size; i++) {
581 7060 : sprintf(&dsiString[k], "%02x", (unsigned char) dsi[i]);
582 7060 : k+=2;
583 : }
584 46 : dsiString[k] = 0;
585 46 : SDP_ADD_STR("config", dsiString);
586 : }
587 53 : if (!strcmp(payload_name, "MP4V-ES") || (builder->rtp_payt == GF_RTP_PAYT_LATM) ) return GF_OK;
588 :
589 98 : SDP_ADD_INT("streamType", builder->slMap.StreamType);
590 49 : if (strcmp(builder->slMap.mode, "") && strcmp(builder->slMap.mode, "default")) {
591 24 : SDP_ADD_STR("mode", builder->slMap.mode);
592 : } else {
593 : SDP_ADD_STR("mode", "generic");
594 : }
595 :
596 : /*optional fields*/
597 98 : if (builder->slMap.CodecID) SDP_ADD_INT("objectType", builder->slMap.CodecID);
598 49 : if (builder->slMap.ConstantSize) SDP_ADD_INT("constantSize", builder->slMap.ConstantSize);
599 72 : if (builder->slMap.ConstantDuration) SDP_ADD_INT("constantDuration", builder->slMap.ConstantDuration);
600 49 : if (builder->slMap.maxDisplacement) SDP_ADD_INT("maxDisplacement", builder->slMap.maxDisplacement);
601 49 : if (builder->slMap.deinterleaveBufferSize) SDP_ADD_INT("de-interleaveBufferSize", builder->slMap.deinterleaveBufferSize);
602 72 : if (builder->slMap.SizeLength) SDP_ADD_INT("sizeLength", builder->slMap.SizeLength);
603 72 : if (builder->slMap.IndexLength) SDP_ADD_INT("indexLength", builder->slMap.IndexLength);
604 72 : if (builder->slMap.IndexDeltaLength) SDP_ADD_INT("indexDeltaLength", builder->slMap.IndexDeltaLength);
605 49 : if (builder->slMap.CTSDeltaLength) SDP_ADD_INT("CTSDeltaLength", builder->slMap.CTSDeltaLength);
606 55 : if (builder->slMap.DTSDeltaLength) SDP_ADD_INT("DTSDeltaLength", builder->slMap.DTSDeltaLength);
607 54 : if (builder->slMap.RandomAccessIndication) SDP_ADD_INT("randomAccessIndication", builder->slMap.RandomAccessIndication);
608 50 : if (builder->slMap.StreamStateIndication) SDP_ADD_INT("streamStateIndication", builder->slMap.StreamStateIndication);
609 49 : if (builder->slMap.AuxiliaryDataSizeLength) SDP_ADD_INT("auxiliaryDataSizeLength", builder->slMap.AuxiliaryDataSizeLength);
610 :
611 : /*ISMACryp config*/
612 49 : if (builder->slMap.IV_length) {
613 : /*don't write default*/
614 : /*SDP_ADD_STR("ISMACrypCryptoSuite", "AES_CTR_128");*/
615 5 : if (builder->flags & GP_RTP_PCK_SELECTIVE_ENCRYPTION) SDP_ADD_INT("ISMACrypSelectiveEncryption", 1);
616 5 : SDP_ADD_INT("ISMACrypIVLength", builder->slMap.IV_length);
617 5 : if (builder->slMap.IV_delta_length) SDP_ADD_INT("ISMACrypDeltaIVLength", builder->slMap.IV_delta_length);
618 5 : if (builder->slMap.KI_length) SDP_ADD_INT("ISMACrypKeyIndicatorLength", builder->slMap.KI_length);
619 5 : if (builder->flags & GP_RTP_PCK_KEY_IDX_PER_AU) SDP_ADD_INT("ISMACrypKeyIndicatorPerAU", 1);
620 : }
621 : return GF_OK;
622 : }
623 :
624 : #endif /*GPAC_DISABLE_STREAMING*/
|