1 /*
2 Copyright (c) 2012, Broadcom Europe Ltd
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 notice, this list of conditions and the following disclaimer in the
11 documentation and/or other materials provided with the distribution.
12 * Neither the name of the copyright holder nor the
13 names of its contributors may be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30
31 #define CONTAINER_IS_BIG_ENDIAN
32 //#define ENABLE_CONTAINERS_LOG_FORMAT
33 //#define ENABLE_CONTAINERS_LOG_FORMAT_VERBOSE
34 #define CONTAINER_HELPER_LOG_INDENT(a) 0
35 #include "containers/core/containers_private.h"
36 #include "containers/core/containers_io_helpers.h"
37 #include "containers/core/containers_utils.h"
38 #include "containers/core/containers_uri.h"
39 #include "containers/core/containers_logging.h"
40 #include "containers/core/containers_bits.h"
41 #include "containers/core/containers_list.h"
42
43 #include "rtp_priv.h"
44 #include "rtp_mpeg4.h"
45 #include "rtp_h264.h"
46
47 #ifdef _DEBUG
48 /* Validates static sorted lists are correctly constructed */
49 #define RTP_DEBUG 1
50 #endif
51
52 /******************************************************************************
53 Configurable defines and constants.
54 ******************************************************************************/
55
56 /** Maximum size of an RTP packet */
57 #define MAXIMUM_PACKET_SIZE 2048
58
59 /** Maximum number of RTP packets that can be missed without restarting. */
60 #define MAX_DROPOUT 3000
61 /** Maximum number of out of sequence RTP packets that are accepted. */
62 #define MAX_MISORDER 0
63 /** Minimum number of sequential packets required for an acceptable connection
64 * when restarting. */
65 #define MIN_SEQUENTIAL 2
66
67 /******************************************************************************
68 Defines and constants.
69 ******************************************************************************/
70
71 #define RTP_SCHEME "rtp:"
72
73 /** The RTP PKT scheme is used with test pkt files */
74 #define RTP_PKT_SCHEME "rtppkt:"
75
76 /** \name RTP URI parameter names
77 * @{ */
78 #define PAYLOAD_TYPE_NAME "rtppt"
79 #define MIME_TYPE_NAME "mime-type"
80 #define CHANNELS_NAME "channels"
81 #define RATE_NAME "rate"
82 #define SSRC_NAME "ssrc"
83 #define SEQ_NAME "seq"
84 /* @} */
85
86 /** A sentinel codec that is not supported */
87 #define UNSUPPORTED_CODEC VC_FOURCC(0,0,0,0)
88
89 /** Evaluates to true if the given payload type is in the supported static audio range. */
90 #define IS_STATIC_AUDIO_TYPE(PT) ((PT) < countof(static_audio_payload_types))
91
92 /** Payload type number for the first static video type */
93 #define FIRST_STATIC_VIDEO_TYPE 24
94 /** Evaluates to true if the given payload type is in the supported static video range. */
95 #define IS_STATIC_VIDEO_TYPE(PT) ((PT) >= FIRST_STATIC_VIDEO_TYPE && \
96 (PT) < (FIRST_STATIC_VIDEO_TYPE + countof(static_video_payload_types)))
97
98 /** Evaluates to true if the given payload type is in the dynamic range. */
99 #define IS_DYNAMIC_TYPE(PT) ((PT) >= 96 && (PT) < 128)
100
101 /** All sequence numbers are modulo this value. */
102 #define RTP_SEQ_MOD (1 << 16)
103
104 /** All the static video payload types use a 90kHz timestamp clock */
105 #define STATIC_VIDEO_TIMESTAMP_CLOCK 90000
106
107 /** Number of microseconds in a second, used to convert RTP timestamps to microseconds */
108 #define MICROSECONDS_PER_SECOND 1000000
109
110 /******************************************************************************
111 Type definitions
112 ******************************************************************************/
113
114 /** \name MIME type parameter handlers
115 * Function prototypes for payload parameter handlers */
116 /* @{ */
117 static VC_CONTAINER_STATUS_T audio_parameter_handler(VC_CONTAINER_T *p_ctx, VC_CONTAINER_TRACK_T *track, const VC_CONTAINERS_LIST_T *params);
118 static VC_CONTAINER_STATUS_T l8_parameter_handler(VC_CONTAINER_T *p_ctx, VC_CONTAINER_TRACK_T *track, const VC_CONTAINERS_LIST_T *params);
119 static VC_CONTAINER_STATUS_T l16_parameter_handler(VC_CONTAINER_T *p_ctx, VC_CONTAINER_TRACK_T *track, const VC_CONTAINERS_LIST_T *params);
120 /* @} */
121
122 /** \name MIME type payload handlers */
123 /* @{ */
124 static VC_CONTAINER_STATUS_T l16_payload_handler(VC_CONTAINER_T *p_ctx, VC_CONTAINER_TRACK_T *track,
125 VC_CONTAINER_PACKET_T *p_packet, uint32_t flags);
126 /* @} */
127
128 /** Static audio payload type data */
129 typedef struct audio_payload_type_data_tag
130 {
131 VC_CONTAINER_FOURCC_T codec; /**< FourCC codec for this payload type */
132 uint32_t channels; /**< Number of audio channels */
133 uint32_t sample_rate; /**< Sample rate */
134 uint32_t bits_per_sample; /**< Bits per sample, or 1 if not applicable */
135 PARAMETER_HANDLER_T param_handler; /**< Optional parameter handler */
136 PAYLOAD_HANDLER_T payload_handler; /**< Optional payload handler */
137 } AUDIO_PAYLOAD_TYPE_DATA_T;
138
139 /** The details for the statically defined audio payload types from RFC3551 */
140 static AUDIO_PAYLOAD_TYPE_DATA_T static_audio_payload_types[] =
141 {
142 { VC_CONTAINER_CODEC_MULAW, 1, 8000, 8, audio_parameter_handler, NULL }, /* 0 - PCMU */
143 { UNSUPPORTED_CODEC }, /* 1 - reserved */
144 { UNSUPPORTED_CODEC }, /* 2 - reserved */
145 { UNSUPPORTED_CODEC, 1, 8000, 1, NULL, NULL }, /* 3 - GSM */
146 { UNSUPPORTED_CODEC, 1, 8000, 1, NULL, NULL }, /* 4 - G723 */
147 { UNSUPPORTED_CODEC, 1, 8000, 4, NULL, NULL }, /* 5 - DVI4 */
148 { UNSUPPORTED_CODEC, 1, 16000, 4, NULL, NULL }, /* 6 - DVI4 */
149 { UNSUPPORTED_CODEC, 1, 8000, 1, NULL, NULL }, /* 7 - LPC */
150 { VC_CONTAINER_CODEC_ALAW, 1, 8000, 8, audio_parameter_handler, NULL }, /* 8 - PCMA */
151 { UNSUPPORTED_CODEC, 1, 8000, 8, NULL, NULL }, /* 9 - G722 */
152 { VC_CONTAINER_CODEC_PCM_SIGNED, 2, 44100, 16, audio_parameter_handler, l16_payload_handler }, /* 10 - L16 */
153 { VC_CONTAINER_CODEC_PCM_SIGNED, 1, 44100, 16, audio_parameter_handler, l16_payload_handler }, /* 11 - L16 */
154 { VC_CONTAINER_CODEC_QCELP, 1, 8000, 16, NULL, NULL }, /* 12 - QCELP */
155 { UNSUPPORTED_CODEC, 1, 8000, 1, NULL, NULL }, /* 13 - CN */
156 { VC_CONTAINER_CODEC_MPGA, 1, 90000, 1, NULL, NULL }, /* 14 - MPA */
157 { UNSUPPORTED_CODEC, 1, 8000, 1, NULL, NULL }, /* 15 - G728 */
158 { UNSUPPORTED_CODEC, 1, 11025, 4, NULL, NULL }, /* 16 - DVI4 */
159 { UNSUPPORTED_CODEC, 1, 22050, 4, NULL, NULL }, /* 17 - DVI4 */
160 { UNSUPPORTED_CODEC, 1, 8000, 1, NULL, NULL }, /* 18 - G729 */
161 };
162
163 /** Static video payload type data */
164 typedef struct video_payload_type_data_tag
165 {
166 VC_CONTAINER_FOURCC_T codec; /**< FourCC codec for this payload type */
167 PARAMETER_HANDLER_T param_handler; /**< Optional parameter handler */
168 PAYLOAD_HANDLER_T payload_handler; /**< Optional payload handler */
169 } VIDEO_PAYLOAD_TYPE_DATA_T;
170
171 /** The details for the statically defined video payload types from RFC3551 */
172 static VIDEO_PAYLOAD_TYPE_DATA_T static_video_payload_types[] =
173 {
174 { UNSUPPORTED_CODEC }, /* 24 - unassigned */
175 { UNSUPPORTED_CODEC }, /* 25 - CelB */
176 { UNSUPPORTED_CODEC }, /* 26 - JPEG */
177 { UNSUPPORTED_CODEC }, /* 27 - unassigned */
178 { UNSUPPORTED_CODEC }, /* 28 - nv */
179 { UNSUPPORTED_CODEC }, /* 29 - unassigned */
180 { UNSUPPORTED_CODEC }, /* 30 - unassigned */
181 { UNSUPPORTED_CODEC }, /* 31 - H261 */
182 { VC_CONTAINER_CODEC_MP2V, NULL, NULL }, /* 32 - MPV */
183 { UNSUPPORTED_CODEC }, /* 33 - MP2T */
184 { VC_CONTAINER_CODEC_H263, NULL, NULL } /* 34 - H263 */
185 };
186
187 /** MIME type details */
188 typedef struct mime_type_data_tag
189 {
190 const char *name; /**< Name of MIME type */
191 VC_CONTAINER_ES_TYPE_T es_type; /**< Elementary stream type */
192 VC_CONTAINER_FOURCC_T codec; /**< Codec to be used */
193 PARAMETER_HANDLER_T param_handler; /**< Parameter handler for this MIME type */
194 } MIME_TYPE_DATA_T;
195
196 /** Comparator for MIME type details. */
197 static int mime_type_data_comparator(const MIME_TYPE_DATA_T *a, const MIME_TYPE_DATA_T *b);
198
199 /** Dynamic audio payload details
200 * Note: case-insensitive sort by name */
201 static MIME_TYPE_DATA_T dynamic_mime_details[] = {
202 { "audio/l16", VC_CONTAINER_ES_TYPE_AUDIO, VC_CONTAINER_CODEC_PCM_SIGNED, l16_parameter_handler },
203 { "audio/l8", VC_CONTAINER_ES_TYPE_AUDIO, VC_CONTAINER_CODEC_PCM_SIGNED, l8_parameter_handler },
204 { "audio/mpeg4-generic", VC_CONTAINER_ES_TYPE_AUDIO, VC_CONTAINER_CODEC_MP4A, mp4_parameter_handler },
205 { "video/h264", VC_CONTAINER_ES_TYPE_VIDEO, VC_CONTAINER_CODEC_H264, h264_parameter_handler },
206 { "video/mpeg4-generic", VC_CONTAINER_ES_TYPE_VIDEO, VC_CONTAINER_CODEC_MP4V, mp4_parameter_handler },
207 };
208
209 /** Sorted list of dynamic MIME type details */
210 VC_CONTAINERS_STATIC_LIST(dynamic_mime, dynamic_mime_details, mime_type_data_comparator);
211
212 /** RTP reader data. */
213 typedef struct VC_CONTAINER_MODULE_T
214 {
215 VC_CONTAINER_TRACK_T *track;
216 } VC_CONTAINER_MODULE_T;
217
218 /******************************************************************************
219 Function prototypes
220 ******************************************************************************/
221 VC_CONTAINER_STATUS_T rtp_reader_open( VC_CONTAINER_T * );
222
223 /******************************************************************************
224 Local Functions
225 ******************************************************************************/
226
227 /**************************************************************************//**
228 * Parameter comparison function.
229 * Compare two parameter structures and return whether the first is less than,
230 * equal to or greater than the second.
231 *
232 * @param first The first structure to be compared.
233 * @param second The second structure to be compared.
234 * @return Negative if first is less than second, positive if first is greater
235 * and zero if they are equal.
236 */
parameter_comparator(const PARAMETER_T * first,const PARAMETER_T * second)237 static int parameter_comparator(const PARAMETER_T *first, const PARAMETER_T *second)
238 {
239 return strcasecmp(first->name, second->name);
240 }
241
242 /**************************************************************************//**
243 * Creates and populates a parameter list from a URI structure.
244 * The list does not copy the parameter strings themselves, so the URI structure
245 * must be retained (and its parameters unmodified) while the list is in use.
246 *
247 * @param uri The URI containing the parameters.
248 * @return List created from the parameters of the URI, or NULL on error.
249 */
fill_parameter_list(VC_URI_PARTS_T * uri)250 static VC_CONTAINERS_LIST_T *fill_parameter_list(VC_URI_PARTS_T *uri)
251 {
252 uint32_t num_parameters = vc_uri_num_queries(uri);
253 VC_CONTAINERS_LIST_T *parameters;
254 uint32_t ii;
255
256 parameters = vc_containers_list_create(num_parameters, sizeof(PARAMETER_T), (VC_CONTAINERS_LIST_COMPARATOR_T)parameter_comparator);
257 if (!parameters)
258 return NULL;
259
260 for (ii = 0; ii < num_parameters; ii++)
261 {
262 PARAMETER_T param;
263
264 vc_uri_query(uri, ii, ¶m.name, ¶m.value);
265 if (!vc_containers_list_insert(parameters, ¶m, false))
266 {
267 vc_containers_list_destroy(parameters);
268 return NULL;
269 }
270 }
271
272 #ifdef RTP_DEBUG
273 vc_containers_list_validate(parameters);
274 #endif
275
276 return parameters;
277 }
278
279 /**************************************************************************//**
280 * Decodes a static audio payload type into track information.
281 * The static parameters may be overridden by URI parameters.
282 *
283 * @param p_ctx The reader context.
284 * @param track The track to be populated.
285 * @param param_list The URI parameter list.
286 * @param payload_type The static payload type.
287 * @return The resulting status of the function.
288 */
decode_static_audio_type(VC_CONTAINER_T * p_ctx,VC_CONTAINER_TRACK_T * track,const VC_CONTAINERS_LIST_T * param_list,uint32_t payload_type)289 static VC_CONTAINER_STATUS_T decode_static_audio_type(VC_CONTAINER_T *p_ctx,
290 VC_CONTAINER_TRACK_T *track,
291 const VC_CONTAINERS_LIST_T *param_list,
292 uint32_t payload_type)
293 {
294 VC_CONTAINER_ES_FORMAT_T *format = track->format;
295 AUDIO_PAYLOAD_TYPE_DATA_T *data = &static_audio_payload_types[payload_type];
296
297 VC_CONTAINER_PARAM_UNUSED(p_ctx);
298 VC_CONTAINER_PARAM_UNUSED(param_list);
299
300 vc_container_assert(payload_type < countof(static_audio_payload_types));
301
302 if (data->codec == UNSUPPORTED_CODEC)
303 return VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED;
304
305 format->es_type = VC_CONTAINER_ES_TYPE_AUDIO;
306 format->codec = data->codec;
307 format->type->audio.channels = data->channels;
308 format->type->audio.sample_rate = data->sample_rate;
309 format->type->audio.bits_per_sample = data->bits_per_sample;
310 format->type->audio.block_align = data->channels * BITS_TO_BYTES(data->bits_per_sample);
311 track->priv->module->timestamp_clock = format->type->audio.sample_rate;
312 track->priv->module->payload_handler = data->payload_handler;
313
314 if (data->param_handler)
315 data->param_handler(p_ctx, track, param_list);
316
317 return VC_CONTAINER_SUCCESS;
318 }
319
320 /**************************************************************************//**
321 * Decodes a static video payload type into track information.
322 * The static parameters may be overridden by URI parameters.
323 *
324 * @param p_ctx The reader context.
325 * @param track The track to be populated.
326 * @param param_list The URI parameter list.
327 * @param payload_type The static payload type.
328 * @return The resulting status of the function.
329 */
decode_static_video_type(VC_CONTAINER_T * p_ctx,VC_CONTAINER_TRACK_T * track,const VC_CONTAINERS_LIST_T * param_list,uint32_t payload_type)330 static VC_CONTAINER_STATUS_T decode_static_video_type(VC_CONTAINER_T *p_ctx,
331 VC_CONTAINER_TRACK_T *track,
332 const VC_CONTAINERS_LIST_T *param_list,
333 uint32_t payload_type)
334 {
335 VC_CONTAINER_ES_FORMAT_T *format = track->format;
336 VIDEO_PAYLOAD_TYPE_DATA_T *data = &static_video_payload_types[payload_type - FIRST_STATIC_VIDEO_TYPE];
337
338 VC_CONTAINER_PARAM_UNUSED(p_ctx);
339 VC_CONTAINER_PARAM_UNUSED(param_list);
340
341 vc_container_assert(payload_type >= FIRST_STATIC_VIDEO_TYPE);
342 vc_container_assert(payload_type < FIRST_STATIC_VIDEO_TYPE + countof(static_video_payload_types));
343
344 if (data->codec == UNSUPPORTED_CODEC)
345 return VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED;
346
347 format->es_type = VC_CONTAINER_ES_TYPE_VIDEO;
348 format->codec = data->codec;
349 track->priv->module->timestamp_clock = STATIC_VIDEO_TIMESTAMP_CLOCK;
350 track->priv->module->payload_handler = data->payload_handler;
351
352 if (data->param_handler)
353 data->param_handler(p_ctx, track, param_list);
354
355 return VC_CONTAINER_SUCCESS;
356 }
357
358 /**************************************************************************//**
359 * Compare two MIME type structures and return whether the first is less than,
360 * equal to or greater than the second.
361 *
362 * @param a The first parameter structure to be compared.
363 * @param b The second parameter structure to be compared.
364 * @return Negative if a is less than b, positive if a is greater and zero if
365 * they are equal.
366 */
mime_type_data_comparator(const MIME_TYPE_DATA_T * a,const MIME_TYPE_DATA_T * b)367 static int mime_type_data_comparator(const MIME_TYPE_DATA_T *a, const MIME_TYPE_DATA_T *b)
368 {
369 return strcasecmp(a->name, b->name);
370 }
371
372 /**************************************************************************//**
373 * Generic audio parameter handler.
374 * Updates the track information with generic audio parameters, such as "rate"
375 * and "channels".
376 *
377 * @param p_ctx The reader context.
378 * @param track The track to be updated.
379 * @param params The URI parameter list.
380 * @return The resulting status of the function.
381 */
audio_parameter_handler(VC_CONTAINER_T * p_ctx,VC_CONTAINER_TRACK_T * track,const VC_CONTAINERS_LIST_T * params)382 static VC_CONTAINER_STATUS_T audio_parameter_handler(VC_CONTAINER_T *p_ctx,
383 VC_CONTAINER_TRACK_T *track,
384 const VC_CONTAINERS_LIST_T *params)
385 {
386 VC_CONTAINER_AUDIO_FORMAT_T *audio = &track->format->type->audio;
387
388 VC_CONTAINER_PARAM_UNUSED(p_ctx);
389
390 /* See RFC3555. Generic audio parameters that can override static payload
391 * type defaults. */
392 if (rtp_get_parameter_u32(params, RATE_NAME, &audio->sample_rate))
393 track->priv->module->timestamp_clock = audio->sample_rate;
394 if (rtp_get_parameter_u32(params, CHANNELS_NAME, &audio->channels))
395 audio->block_align = audio->channels * BITS_TO_BYTES(audio->bits_per_sample);
396
397 return VC_CONTAINER_SUCCESS;
398 }
399
400 /**************************************************************************//**
401 * L8 specific audio parameter handler.
402 * Updates the track information with audio parameters needed by the audio/L8
403 * MIME type. For example, the "rate" parameter is mandatory.
404 *
405 * @param p_ctx The reader context.
406 * @param track The track to be updated.
407 * @param params The URI parameter list.
408 * @return The resulting status of the function.
409 */
l8_parameter_handler(VC_CONTAINER_T * p_ctx,VC_CONTAINER_TRACK_T * track,const VC_CONTAINERS_LIST_T * params)410 static VC_CONTAINER_STATUS_T l8_parameter_handler(VC_CONTAINER_T *p_ctx,
411 VC_CONTAINER_TRACK_T *track,
412 const VC_CONTAINERS_LIST_T *params)
413 {
414 VC_CONTAINER_AUDIO_FORMAT_T *audio = &track->format->type->audio;
415
416 VC_CONTAINER_PARAM_UNUSED(p_ctx);
417
418 /* See RFC3555, section 4.1.14, for parameter names and details. */
419 if (!rtp_get_parameter_u32(params, RATE_NAME, &audio->sample_rate))
420 return VC_CONTAINER_ERROR_FORMAT_INVALID;
421 if (!rtp_get_parameter_u32(params, CHANNELS_NAME, &audio->channels))
422 audio->channels = 1;
423 audio->bits_per_sample = 8;
424 audio->block_align = audio->channels;
425 track->priv->module->timestamp_clock = audio->sample_rate;
426
427 return VC_CONTAINER_SUCCESS;
428 }
429
430 /**************************************************************************//**
431 * L16 specific audio parameter handler.
432 * Updates the track information with audio parameters needed by the audio/L16
433 * MIME type. For example, the "rate" parameter is mandatory.
434 *
435 * @param p_ctx The reader context.
436 * @param track The track to be updated.
437 * @param params The URI parameter list.
438 * @return The resulting status of the function.
439 */
l16_parameter_handler(VC_CONTAINER_T * p_ctx,VC_CONTAINER_TRACK_T * track,const VC_CONTAINERS_LIST_T * params)440 static VC_CONTAINER_STATUS_T l16_parameter_handler(VC_CONTAINER_T *p_ctx,
441 VC_CONTAINER_TRACK_T *track,
442 const VC_CONTAINERS_LIST_T *params)
443 {
444 VC_CONTAINER_AUDIO_FORMAT_T *audio = &track->format->type->audio;
445
446 VC_CONTAINER_PARAM_UNUSED(p_ctx);
447
448 /* See RFC3555, section 4.1.15, for parameter names and details. */
449 if (!rtp_get_parameter_u32(params, RATE_NAME, &audio->sample_rate))
450 return VC_CONTAINER_ERROR_FORMAT_INVALID;
451 if (!rtp_get_parameter_u32(params, CHANNELS_NAME, &audio->channels))
452 audio->channels = 1;
453 audio->bits_per_sample = 16;
454 audio->block_align = audio->channels * 2;
455 track->priv->module->timestamp_clock = audio->sample_rate;
456 track->priv->module->payload_handler = l16_payload_handler;
457
458 /* TODO: add support for "channel-order" to set channel mapping */
459
460 return VC_CONTAINER_SUCCESS;
461 }
462
463 /**************************************************************************//**
464 * Decode a dynamic payload type from parameters.
465 * Populates the track information with data for supported dynamic media types.
466 *
467 * @param p_ctx The reader context.
468 * @param track The track to be updated.
469 * @param param_list The URI parameter list.
470 * @return The resulting status of the function.
471 */
decode_dynamic_type(VC_CONTAINER_T * p_ctx,VC_CONTAINER_TRACK_T * track,const VC_CONTAINERS_LIST_T * param_list)472 static VC_CONTAINER_STATUS_T decode_dynamic_type(VC_CONTAINER_T *p_ctx,
473 VC_CONTAINER_TRACK_T *track,
474 const VC_CONTAINERS_LIST_T *param_list)
475 {
476 VC_CONTAINER_ES_FORMAT_T *format = track->format;
477 VC_CONTAINER_STATUS_T status = VC_CONTAINER_SUCCESS;
478 PARAMETER_T mime_type;
479 MIME_TYPE_DATA_T mime_details;
480
481 /* Get MIME type parameter */
482 mime_type.name = MIME_TYPE_NAME;
483 if (!vc_containers_list_find_entry(param_list, &mime_type))
484 return VC_CONTAINER_ERROR_FORMAT_INVALID;
485
486 #ifdef RTP_DEBUG
487 vc_containers_list_validate(&dynamic_mime);
488 #endif
489
490 /* Look up MIME type to see if it can be handled */
491 mime_details.name = mime_type.value;
492 if (!vc_containers_list_find_entry(&dynamic_mime, &mime_details))
493 return VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED;
494
495 format->codec = mime_details.codec;
496 format->es_type = mime_details.es_type;
497
498 /* Default number of channels for audio is one */
499 if (mime_details.es_type == VC_CONTAINER_ES_TYPE_AUDIO)
500 format->type->audio.channels = 1;
501
502 /* Lete MIME type specific parameter handler deal with any other parameters */
503 status = mime_details.param_handler(p_ctx, track, param_list);
504
505 /* Ensure that the sample rate has been set for audio formats */
506 if (mime_details.es_type == VC_CONTAINER_ES_TYPE_AUDIO && !format->type->audio.sample_rate)
507 return VC_CONTAINER_ERROR_FORMAT_INVALID;
508
509 return status;
510 }
511
512 /**************************************************************************//**
513 * Decode the RTP payload type.
514 * Populates track information with data from static tables and the URI
515 * parameter list, according to the payload and MIME types.
516 *
517 * @param p_ctx The reader context.
518 * @param track The track to be updated.
519 * @param params The URI parameter list.
520 * @return The resulting status of the function.
521 */
decode_payload_type(VC_CONTAINER_T * p_ctx,VC_CONTAINER_TRACK_T * track,const VC_CONTAINERS_LIST_T * param_list,uint32_t payload_type)522 static VC_CONTAINER_STATUS_T decode_payload_type(VC_CONTAINER_T *p_ctx,
523 VC_CONTAINER_TRACK_T *track,
524 const VC_CONTAINERS_LIST_T *param_list,
525 uint32_t payload_type)
526 {
527 VC_CONTAINER_TRACK_MODULE_T *module = track->priv->module;
528 VC_CONTAINER_STATUS_T status;
529
530 if (IS_STATIC_AUDIO_TYPE(payload_type))
531 status = decode_static_audio_type(p_ctx, track, param_list, payload_type);
532 else if (IS_STATIC_VIDEO_TYPE(payload_type))
533 status = decode_static_video_type(p_ctx, track, param_list, payload_type);
534 else if (IS_DYNAMIC_TYPE(payload_type))
535 status = decode_dynamic_type(p_ctx, track, param_list);
536 else
537 status = VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED;
538
539 module->payload_type = (uint8_t)payload_type;
540
541 return status;
542 }
543
544 /**************************************************************************//**
545 * Initialises the RTP sequence number algorithm with a new sequence number.
546 *
547 * @param t_module The track module.
548 * @param seq The new sequence number.
549 */
init_sequence_number(VC_CONTAINER_TRACK_MODULE_T * t_module,uint16_t seq)550 static void init_sequence_number(VC_CONTAINER_TRACK_MODULE_T *t_module,
551 uint16_t seq)
552 {
553 t_module->base_seq = seq;
554 t_module->max_seq_num = seq;
555 t_module->bad_seq = RTP_SEQ_MOD + 1; /* so seq == bad_seq is false */
556 t_module->received = 0;
557 }
558
559 /**************************************************************************//**
560 * Checks whether the sequence number for a packet is acceptable or not.
561 * The packet will be unacceptable if it is out of sequence by some degree, or
562 * if the packet sequence is still being established.
563 *
564 * @param t_module The track module.
565 * @param seq The new sequence number.
566 * @return True if the sequence number indicates the packet is acceptable
567 */
update_sequence_number(VC_CONTAINER_TRACK_MODULE_T * t_module,uint16_t seq)568 static bool update_sequence_number(VC_CONTAINER_TRACK_MODULE_T *t_module,
569 uint16_t seq)
570 {
571 uint16_t udelta = seq - t_module->max_seq_num;
572
573 /* NOTE: This source is derived from the example code in RFC3550, section A.1 */
574
575 /* Source is not valid until MIN_SEQUENTIAL packets with
576 * sequential sequence numbers have been received. */
577 if (t_module->probation)
578 {
579 /* packet is in sequence */
580 if (seq == t_module->max_seq_num + 1)
581 {
582 t_module->probation--;
583 t_module->max_seq_num = seq;
584 LOG_INFO(0, "RTP: Probation, %u more packet(s) to go at 0x%4.4hx", t_module->probation, seq);
585
586 if (!t_module->probation)
587 {
588 init_sequence_number(t_module, seq);
589 t_module->received++;
590 return 1;
591 }
592 } else {
593 t_module->probation = MIN_SEQUENTIAL - 1;
594 t_module->max_seq_num = seq;
595 LOG_INFO(0, "RTP: Probation reset, wait for %u packet(s) at 0x%4.4hx", t_module->probation, seq);
596 }
597 return 0;
598 } else if (udelta < MAX_DROPOUT)
599 {
600 if (!udelta)
601 {
602 /* Duplicate packet, drop it */
603 LOG_INFO(0, "RTP: Drop duplicate packet at 0x%4.4hx", seq);
604 return 0;
605 }
606 if (udelta > 1)
607 {
608 LOG_INFO(0, "RTP: Jumped by %hu packets to 0x%4.4hx", udelta, seq);
609 }
610 /* in order, with permissible gap */
611 t_module->max_seq_num = seq;
612 } else
613 #if (MAX_MISORDER != 0)
614 /* When MAX_MISORDER is zero, always treat as out of order */
615 if (udelta <= RTP_SEQ_MOD - MAX_MISORDER)
616 #endif
617 {
618 /* the sequence number made a very large jump */
619 if (seq == t_module->bad_seq)
620 {
621 LOG_INFO(0, "RTP: Misorder restart at 0x%4.4hx", seq);
622 /* Two sequential packets -- assume that the other side
623 * restarted without telling us so just re-sync
624 * (i.e., pretend this was the first packet). */
625 init_sequence_number(t_module, seq);
626 } else {
627 LOG_INFO(0, "RTP: Misorder at 0x%4.4hx, expected 0x%4.4hx", seq, t_module->max_seq_num);
628 t_module->bad_seq = (seq + 1) & (RTP_SEQ_MOD-1);
629 return 0;
630 }
631 }
632 #if (MAX_MISORDER != 0)
633 else {
634 /* duplicate or reordered packet */
635
636 /* TODO: handle out of order packets */
637 }
638 #endif
639 t_module->received++;
640 return 1;
641 }
642
643 /**************************************************************************//**
644 * Extract the fields of an RTP packet and validate it.
645 *
646 * @param p_ctx The reader context.
647 * @param t_module The track module.
648 * @return True if successful, false if there were not enough bits in the
649 * packet or the packet was invalid.
650 */
decode_rtp_packet_header(VC_CONTAINER_T * p_ctx,VC_CONTAINER_TRACK_MODULE_T * t_module)651 static void decode_rtp_packet_header(VC_CONTAINER_T *p_ctx,
652 VC_CONTAINER_TRACK_MODULE_T *t_module)
653 {
654 VC_CONTAINER_BITS_T *payload = &t_module->payload;
655 uint32_t version, has_padding, has_extension, csrc_count, has_marker;
656 uint32_t payload_type, ssrc;
657 uint16_t seq_num;
658
659 /* Break down fixed header area into component parts */
660 version = BITS_READ_U32(p_ctx, payload, 2, "Version");
661 has_padding = BITS_READ_U32(p_ctx, payload, 1, "Has padding");
662 has_extension = BITS_READ_U32(p_ctx, payload, 1, "Has extension");
663 csrc_count = BITS_READ_U32(p_ctx, payload, 4, "CSRC count");
664 has_marker = BITS_READ_U32(p_ctx, payload, 1, "Has marker");
665 payload_type = BITS_READ_U32(p_ctx, payload, 7, "Payload type");
666 seq_num = BITS_READ_U16(p_ctx, payload, 16, "Sequence number");
667 t_module->timestamp = BITS_READ_U32(p_ctx, payload, 32, "Timestamp");
668 ssrc = BITS_READ_U32(p_ctx, payload, 32, "SSRC");
669
670 /* If there was only a partial header, abort immediately */
671 if (!BITS_VALID(p_ctx, payload))
672 return;
673
674 /* Validate version, payload type, sequence number and SSRC, if set */
675 if (version != 2 || payload_type != t_module->payload_type)
676 {
677 BITS_INVALIDATE(p_ctx, payload);
678 return;
679 }
680 if (BIT_IS_SET(t_module->flags, TRACK_SSRC_SET) && (ssrc != t_module->expected_ssrc))
681 {
682 LOG_DEBUG(p_ctx, "RTP: Unexpected SSRC (0x%8.8X)", ssrc);
683 BITS_INVALIDATE(p_ctx, payload);
684 return;
685 }
686
687 /* Check sequence number indicates packet is usable */
688 if (!update_sequence_number(t_module, seq_num))
689 {
690 BITS_INVALIDATE(p_ctx, payload);
691 return;
692 }
693
694 /* Adjust to account for padding, CSRCs and extension */
695 if (has_padding)
696 {
697 VC_CONTAINER_BITS_T bit_stream;
698 uint32_t available = BITS_BYTES_AVAILABLE(p_ctx, payload);
699 uint8_t padding;
700
701 BITS_COPY_STREAM(p_ctx, &bit_stream, payload);
702 /* The last byte of the payload is the number of padding bytes, including itself */
703 BITS_SKIP_BYTES(p_ctx, &bit_stream, available - 1, "Skip to padding length");
704 padding = BITS_READ_U8(p_ctx, &bit_stream, 8, "Padding length");
705
706 BITS_REDUCE_BYTES(p_ctx, payload, padding, "Remove padding");
707 }
708
709 /* Each CSRC is 32 bits, so shift count up to skip the right number of bits */
710 BITS_SKIP(p_ctx, payload, csrc_count << 5, "CSRC section");
711
712 if (has_extension)
713 {
714 uint32_t extension_bits;
715
716 /* Extension header is 16-bit ID (which isn't needed), then 16-bit length in 32-bit words */
717 BITS_SKIP(p_ctx, payload, 16, "Extension ID");
718 extension_bits = BITS_READ_U32(p_ctx, payload, 16, "Extension length") << 5;
719 BITS_SKIP(p_ctx, payload, extension_bits, "Extension data");
720 }
721
722 /* Record whether or not this RTP packet had the marker bit set */
723 if (has_marker)
724 SET_BIT(t_module->flags, TRACK_HAS_MARKER);
725 else
726 CLEAR_BIT(t_module->flags, TRACK_HAS_MARKER);
727
728 /* If it hasn't been set independently, use the first timestamp as a baseline */
729 if (!t_module->timestamp_base)
730 t_module->timestamp_base = t_module->timestamp;
731 t_module->timestamp -= t_module->timestamp_base;
732 }
733
734 /**************************************************************************//**
735 * Generic payload handler.
736 * Copies/skips data verbatim from the packet payload.
737 *
738 * @param p_ctx The reader context.
739 * @param track The track being read.
740 * @param p_packet The container packet information, or NULL.
741 * @param flags The container read flags.
742 * @return The resulting status of the function.
743 */
generic_payload_handler(VC_CONTAINER_T * p_ctx,VC_CONTAINER_TRACK_T * track,VC_CONTAINER_PACKET_T * p_packet,uint32_t flags)744 static VC_CONTAINER_STATUS_T generic_payload_handler(VC_CONTAINER_T *p_ctx,
745 VC_CONTAINER_TRACK_T *track,
746 VC_CONTAINER_PACKET_T *p_packet,
747 uint32_t flags)
748 {
749 VC_CONTAINER_TRACK_MODULE_T *t_module = track->priv->module;
750 VC_CONTAINER_BITS_T *payload = &t_module->payload;
751 uint32_t size;
752
753 VC_CONTAINER_PARAM_UNUSED(p_ctx);
754
755 if (!p_packet)
756 {
757 /* Skip the rest of this RTP packet */
758 BITS_INVALIDATE(p_ctx, payload);
759 return VC_CONTAINER_SUCCESS;
760 }
761
762 /* Copy as much as possible into the client packet buffer */
763 size = BITS_BYTES_AVAILABLE(p_ctx, payload);
764
765 if (flags & VC_CONTAINER_READ_FLAG_SKIP)
766 BITS_SKIP_BYTES(p_ctx, payload, size, "Packet data");
767 else {
768 if (!(flags & VC_CONTAINER_READ_FLAG_INFO))
769 {
770 if (size > p_packet->buffer_size)
771 size = p_packet->buffer_size;
772
773 BITS_COPY_BYTES(p_ctx, payload, size, p_packet->data, "Packet data");
774 }
775 p_packet->size = size;
776 }
777
778 return VC_CONTAINER_SUCCESS;
779 }
780
781 /**************************************************************************//**
782 * L16 payload handler.
783 * Copies/skips data from the packet payload. On copy, swaps consecutive bytes
784 * in the data in order to get expected byte order.
785 *
786 * @param p_ctx The reader context.
787 * @param track The track being read.
788 * @param p_packet The container packet information, or NULL.
789 * @param flags The container read flags.
790 * @return The resulting status of the function.
791 */
l16_payload_handler(VC_CONTAINER_T * p_ctx,VC_CONTAINER_TRACK_T * track,VC_CONTAINER_PACKET_T * p_packet,uint32_t flags)792 static VC_CONTAINER_STATUS_T l16_payload_handler(VC_CONTAINER_T *p_ctx,
793 VC_CONTAINER_TRACK_T *track,
794 VC_CONTAINER_PACKET_T *p_packet,
795 uint32_t flags)
796 {
797 VC_CONTAINER_STATUS_T status;
798
799 /* Most aspects are handled adequately by the generic handler */
800 status = generic_payload_handler(p_ctx, track, p_packet, flags);
801 if (status != VC_CONTAINER_SUCCESS)
802 return status;
803
804 if (p_packet && !(flags & (VC_CONTAINER_READ_FLAG_SKIP | VC_CONTAINER_READ_FLAG_INFO)))
805 {
806 uint8_t *ptr, *end_ptr;
807
808 /* Ensure packet size is even */
809 p_packet->size &= ~1;
810
811 /* Swap bytes of each sample, to get host order instead of network order */
812 for (ptr = p_packet->data, end_ptr = ptr + p_packet->size; ptr < end_ptr; ptr += 2)
813 {
814 uint8_t high_byte = ptr[0];
815 ptr[0] = ptr[1];
816 ptr[1] = high_byte;
817 }
818 }
819
820 return status;
821 }
822
823 /*****************************************************************************
824 Utility functions for use by RTP payload handlers
825 *****************************************************************************/
826
827 /**************************************************************************//**
828 * Gets the value of a parameter as an unsigned 32-bit decimal integer.
829 *
830 * @param param_list The URI parameter list.
831 * @param name The name of the parameter.
832 * @param value Pointer to the variable to receive the value.
833 * @return True if the parameter value was read and stored correctly, false
834 * otherwise.
835 */
rtp_get_parameter_u32(const VC_CONTAINERS_LIST_T * param_list,const char * name,uint32_t * value)836 bool rtp_get_parameter_u32(const VC_CONTAINERS_LIST_T *param_list,
837 const char *name,
838 uint32_t *value)
839 {
840 PARAMETER_T param;
841
842 param.name = name;
843 if (vc_containers_list_find_entry(param_list, ¶m) && param.value)
844 {
845 char *end;
846
847 *value = strtoul(param.value, &end, 10);
848 return (end != param.value) && (*end == '\0');
849 }
850
851 return false;
852 }
853
854 /**************************************************************************//**
855 * Gets the value of a parameter as an unsigned 32-bit hexadecimal integer.
856 *
857 * @param param_list The URI parameter list.
858 * @param name The name of the parameter.
859 * @param value Pointer to the variable to receive the value.
860 * @return True if the parameter value was read and stored correctly, false
861 * otherwise.
862 */
rtp_get_parameter_x32(const VC_CONTAINERS_LIST_T * param_list,const char * name,uint32_t * value)863 bool rtp_get_parameter_x32(const VC_CONTAINERS_LIST_T *param_list,
864 const char *name,
865 uint32_t *value)
866 {
867 PARAMETER_T param;
868
869 param.name = name;
870 if (vc_containers_list_find_entry(param_list, ¶m) && param.value)
871 {
872 char *end;
873
874 *value = strtoul(param.value, &end, 16);
875 return (end != param.value) && (*end == '\0');
876 }
877
878 return false;
879 }
880
881 /*****************************************************************************
882 Functions exported as part of the Container Module API
883 *****************************************************************************/
884
885 /**************************************************************************//**
886 * Read/skip data from the container.
887 * Can also be used to query information about the next block of data.
888 *
889 * @param p_ctx The reader context.
890 * @param p_packet The container packet information, or NULL.
891 * @param flags The container read flags.
892 * @return The resulting status of the function.
893 */
rtp_reader_read(VC_CONTAINER_T * p_ctx,VC_CONTAINER_PACKET_T * p_packet,uint32_t flags)894 static VC_CONTAINER_STATUS_T rtp_reader_read( VC_CONTAINER_T *p_ctx,
895 VC_CONTAINER_PACKET_T *p_packet,
896 uint32_t flags )
897 {
898 VC_CONTAINER_TRACK_T *track;
899 VC_CONTAINER_TRACK_MODULE_T *t_module;
900 VC_CONTAINER_STATUS_T status;
901
902 if((flags & VC_CONTAINER_READ_FLAG_FORCE_TRACK) && p_packet->track)
903 return VC_CONTAINER_ERROR_INVALID_ARGUMENT;
904
905 track = p_ctx->tracks[0];
906 t_module = track->priv->module;
907
908 CLEAR_BIT(t_module->flags, TRACK_NEW_PACKET);
909
910 while (!BITS_AVAILABLE(p_ctx, &t_module->payload))
911 {
912 uint32_t bytes_read;
913
914 /* No data left from last RTP packet, get another one */
915 bytes_read = READ_BYTES(p_ctx, t_module->buffer, MAXIMUM_PACKET_SIZE);
916 if (!bytes_read)
917 return STREAM_STATUS(p_ctx);
918
919 BITS_INIT(p_ctx, &t_module->payload, t_module->buffer, bytes_read);
920
921 decode_rtp_packet_header(p_ctx, t_module);
922 SET_BIT(t_module->flags, TRACK_NEW_PACKET);
923 }
924
925 if (p_packet)
926 {
927 uint32_t timestamp_top = t_module->timestamp >> 30;
928
929 /* Determine whether timestamp has wrapped forwards or backwards around zero */
930 if ((timestamp_top == 0) && (t_module->last_timestamp_top == 3))
931 t_module->timestamp_wraps++;
932 else if ((timestamp_top == 3) && (t_module->last_timestamp_top == 0))
933 t_module->timestamp_wraps--;
934 t_module->last_timestamp_top = timestamp_top;
935
936 p_packet->dts = p_packet->pts = ((int64_t)t_module->timestamp_wraps << 32) | t_module->timestamp;
937 p_packet->track = 0;
938 p_packet->flags = 0;
939 }
940
941 status = t_module->payload_handler(p_ctx, track, p_packet, flags);
942 if (p_packet && status == VC_CONTAINER_SUCCESS)
943 {
944 /* Adjust timestamps from RTP clock rate to microseconds */
945 p_packet->pts = p_packet->pts * MICROSECONDS_PER_SECOND / t_module->timestamp_clock;
946 p_packet->dts = p_packet->dts * MICROSECONDS_PER_SECOND / t_module->timestamp_clock;
947 }
948
949 STREAM_STATUS(p_ctx) = status;
950 return status;
951 }
952
953 /**************************************************************************//**
954 * Seek over data in the container.
955 *
956 * @param p_ctx The reader context.
957 * @param p_offset The seek offset.
958 * @param mode The seek mode.
959 * @param flags The seek flags.
960 * @return The resulting status of the function.
961 */
rtp_reader_seek(VC_CONTAINER_T * p_ctx,int64_t * p_offset,VC_CONTAINER_SEEK_MODE_T mode,VC_CONTAINER_SEEK_FLAGS_T flags)962 static VC_CONTAINER_STATUS_T rtp_reader_seek( VC_CONTAINER_T *p_ctx,
963 int64_t *p_offset,
964 VC_CONTAINER_SEEK_MODE_T mode,
965 VC_CONTAINER_SEEK_FLAGS_T flags)
966 {
967 VC_CONTAINER_PARAM_UNUSED(p_ctx);
968 VC_CONTAINER_PARAM_UNUSED(p_offset);
969 VC_CONTAINER_PARAM_UNUSED(mode);
970 VC_CONTAINER_PARAM_UNUSED(flags);
971
972 /* RTP is a non-seekable container */
973 return VC_CONTAINER_ERROR_UNSUPPORTED_OPERATION;
974 }
975
976 /**************************************************************************//**
977 * Apply a control operation to the container.
978 *
979 * @param p_ctx The reader context.
980 * @param operation The control operation.
981 * @param args Optional additional arguments for the operation.
982 * @return The resulting status of the function.
983 */
rtp_reader_control(VC_CONTAINER_T * p_ctx,VC_CONTAINER_CONTROL_T operation,va_list args)984 static VC_CONTAINER_STATUS_T rtp_reader_control( VC_CONTAINER_T *p_ctx,
985 VC_CONTAINER_CONTROL_T operation,
986 va_list args)
987 {
988 VC_CONTAINER_STATUS_T status;
989 VC_CONTAINER_TRACK_MODULE_T *t_module = p_ctx->tracks[0]->priv->module;
990
991 switch (operation)
992 {
993 case VC_CONTAINER_CONTROL_SET_TIMESTAMP_BASE:
994 {
995 t_module->timestamp_base = va_arg(args, uint32_t);
996 if (!t_module->timestamp_base)
997 t_module->timestamp_base = 1; /* Zero is used to mean "not set" */
998 status = VC_CONTAINER_SUCCESS;
999 }
1000 break;
1001 case VC_CONTAINER_CONTROL_SET_NEXT_SEQUENCE_NUMBER:
1002 {
1003 init_sequence_number(t_module, (uint16_t)va_arg(args, uint32_t));
1004 t_module->probation = 0;
1005 status = VC_CONTAINER_SUCCESS;
1006 }
1007 break;
1008 case VC_CONTAINER_CONTROL_SET_SOURCE_ID:
1009 {
1010 t_module->expected_ssrc = va_arg(args, uint32_t);
1011 SET_BIT(t_module->flags, TRACK_SSRC_SET);
1012 status = VC_CONTAINER_SUCCESS;
1013 }
1014 break;
1015 default:
1016 status = VC_CONTAINER_ERROR_UNSUPPORTED_OPERATION;
1017 }
1018
1019 return status;
1020 }
1021
1022 /**************************************************************************//**
1023 * Close the container.
1024 *
1025 * @param p_ctx The reader context.
1026 * @return The resulting status of the function.
1027 */
rtp_reader_close(VC_CONTAINER_T * p_ctx)1028 static VC_CONTAINER_STATUS_T rtp_reader_close( VC_CONTAINER_T *p_ctx )
1029 {
1030 VC_CONTAINER_MODULE_T *module = p_ctx->priv->module;
1031
1032 vc_container_assert(p_ctx->tracks_num < 2);
1033
1034 if (p_ctx->tracks_num)
1035 {
1036 void *payload_extra;
1037
1038 vc_container_assert(module);
1039 vc_container_assert(module->track);
1040 vc_container_assert(module->track->priv);
1041 vc_container_assert(module->track->priv->module);
1042
1043 payload_extra = module->track->priv->module->extra;
1044 if (payload_extra)
1045 free(payload_extra);
1046 vc_container_free_track(p_ctx, module->track);
1047 }
1048 p_ctx->tracks = NULL;
1049 p_ctx->tracks_num = 0;
1050 if (module) free(module);
1051 p_ctx->priv->module = 0;
1052 return VC_CONTAINER_SUCCESS;
1053 }
1054
1055 /**************************************************************************//**
1056 * Open the container.
1057 * Uses the I/O URI and/or data to configure the container.
1058 *
1059 * @param p_ctx The reader context.
1060 * @return The resulting status of the function.
1061 */
rtp_reader_open(VC_CONTAINER_T * p_ctx)1062 VC_CONTAINER_STATUS_T rtp_reader_open( VC_CONTAINER_T *p_ctx )
1063 {
1064 VC_CONTAINER_MODULE_T *module = 0;
1065 VC_CONTAINER_TRACK_T *track = 0;
1066 VC_CONTAINER_TRACK_MODULE_T *t_module = 0;
1067 VC_CONTAINER_STATUS_T status = VC_CONTAINER_SUCCESS;
1068 VC_CONTAINERS_LIST_T *parameters = NULL;
1069 uint32_t payload_type;
1070 uint32_t initial_seq_num;
1071
1072 /* Check the URI scheme looks valid */
1073 if (!vc_uri_scheme(p_ctx->priv->uri) ||
1074 (strcasecmp(vc_uri_scheme(p_ctx->priv->uri), RTP_SCHEME) &&
1075 strcasecmp(vc_uri_scheme(p_ctx->priv->uri), RTP_PKT_SCHEME)))
1076 return VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED;
1077
1078 /* Make the query/parameter list more easily searchable */
1079 parameters = fill_parameter_list(p_ctx->priv->uri);
1080 if (!parameters) { status = VC_CONTAINER_ERROR_OUT_OF_MEMORY; goto error; }
1081
1082 /* Payload type parameter is mandatory and must fit in 7 bits */
1083 if (!rtp_get_parameter_u32(parameters, PAYLOAD_TYPE_NAME, &payload_type) || payload_type > 127)
1084 {
1085 status = VC_CONTAINER_ERROR_FORMAT_INVALID;
1086 goto error;
1087 }
1088
1089 /* Allocate our context */
1090 module = (VC_CONTAINER_MODULE_T *)malloc(sizeof(VC_CONTAINER_MODULE_T));
1091 if (!module) { status = VC_CONTAINER_ERROR_OUT_OF_MEMORY; goto error; }
1092
1093 memset(module, 0, sizeof(*module));
1094 p_ctx->priv->module = module;
1095 p_ctx->tracks = &module->track;
1096
1097 /* Allocate the track, including space for reading an RTP packet on the end */
1098 track = vc_container_allocate_track(p_ctx, sizeof(VC_CONTAINER_TRACK_MODULE_T) + MAXIMUM_PACKET_SIZE);
1099 if (!track)
1100 {
1101 status = VC_CONTAINER_ERROR_OUT_OF_MEMORY;
1102 goto error;
1103 }
1104 module->track = track;
1105 p_ctx->tracks_num = 1;
1106 t_module = track->priv->module;
1107
1108 /* Initialise the track data */
1109 t_module->buffer = (uint8_t *)(t_module + 1);
1110 status = decode_payload_type(p_ctx, track, parameters, payload_type);
1111 if (status != VC_CONTAINER_SUCCESS)
1112 goto error;
1113
1114 vc_container_assert(t_module->timestamp_clock != 0);
1115
1116 /* Default to a generic, unstructured payload handler */
1117 if (!t_module->payload_handler)
1118 t_module->payload_handler = generic_payload_handler;
1119
1120 if (rtp_get_parameter_x32(parameters, SSRC_NAME, &t_module->expected_ssrc))
1121 SET_BIT(t_module->flags, TRACK_SSRC_SET);
1122
1123 t_module->probation = MIN_SEQUENTIAL;
1124 if (rtp_get_parameter_u32(parameters, SEQ_NAME, &initial_seq_num))
1125 {
1126 /* If an initial sequence number is provided, avoid probation period */
1127 t_module->max_seq_num = (uint16_t)initial_seq_num;
1128 t_module->probation = 0;
1129 }
1130
1131 track->is_enabled = true;
1132
1133 vc_containers_list_destroy(parameters);
1134
1135 p_ctx->priv->pf_close = rtp_reader_close;
1136 p_ctx->priv->pf_read = rtp_reader_read;
1137 p_ctx->priv->pf_seek = rtp_reader_seek;
1138 p_ctx->priv->pf_control = rtp_reader_control;
1139
1140 return VC_CONTAINER_SUCCESS;
1141
1142 error:
1143 if (parameters) vc_containers_list_destroy(parameters);
1144 if(status == VC_CONTAINER_SUCCESS || status == VC_CONTAINER_ERROR_EOS)
1145 status = VC_CONTAINER_ERROR_FORMAT_INVALID;
1146 LOG_DEBUG(p_ctx, "error opening RTP (%i)", status);
1147 rtp_reader_close(p_ctx);
1148 return status;
1149 }
1150
1151 /********************************************************************************
1152 Entrypoint function
1153 ********************************************************************************/
1154
1155 #if !defined(ENABLE_CONTAINERS_STANDALONE) && defined(__HIGHC__)
1156 # pragma weak reader_open rtp_reader_open
1157 #endif
1158