summaryrefslogtreecommitdiffstats
path: root/tinyDAV/src/codecs/fec/tdav_codec_red.c
diff options
context:
space:
mode:
Diffstat (limited to 'tinyDAV/src/codecs/fec/tdav_codec_red.c')
-rwxr-xr-xtinyDAV/src/codecs/fec/tdav_codec_red.c363
1 files changed, 182 insertions, 181 deletions
diff --git a/tinyDAV/src/codecs/fec/tdav_codec_red.c b/tinyDAV/src/codecs/fec/tdav_codec_red.c
index 2fb6f27..cf92173 100755
--- a/tinyDAV/src/codecs/fec/tdav_codec_red.c
+++ b/tinyDAV/src/codecs/fec/tdav_codec_red.c
@@ -2,19 +2,19 @@
* Copyright (C) 2012 Doubango Telecom <http://www.doubango.org>
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
-*
+*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
-*
+*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-*
+*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
@@ -31,171 +31,174 @@
#include "tsk_time.h"
#include "tsk_debug.h"
-typedef struct tdav_codec_red_s
-{
- TMEDIA_DECLARE_CODEC_VIDEO;
+typedef struct tdav_codec_red_s {
+ TMEDIA_DECLARE_CODEC_VIDEO;
- tdav_codec_red_rtppacket_cb_f callback;
- const void* callback_data;
+ tdav_codec_red_rtppacket_cb_f callback;
+ const void* callback_data;
}
tdav_codec_red_t;
int tdav_codec_red_set_callback(tdav_codec_red_t *self, tdav_codec_red_rtppacket_cb_f callback, const void* callback_data)
{
- if(!self){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
+ if(!self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
- self->callback = callback;
- self->callback_data = callback_data;
+ self->callback = callback;
+ self->callback_data = callback_data;
- return 0;
+ return 0;
}
static int tdav_codec_red_open(tmedia_codec_t* self)
{
- return 0;
+ return 0;
}
static int tdav_codec_red_close(tmedia_codec_t* self)
{
- return 0;
+ return 0;
}
static tsk_size_t tdav_codec_red_encode(tmedia_codec_t* self, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size)
{
- tdav_codec_red_t *red = (tdav_codec_red_t *)self;
- tsk_size_t xsize = (in_size + 1);
- static const uint8_t __first_octet = 0x00; // F=1, PT=0. Up to the caller to update this first octet with the right PT.
-
- if(!red || !in_data || !in_size || !out_data || !out_max_size){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- if(*out_max_size < xsize){
- if(!(*out_data = tsk_realloc(*out_data, xsize))){
- TSK_DEBUG_ERROR("Failed to realloc data");
- *out_max_size = 0;
- }
- *out_max_size = xsize;
- }
-
- ((uint8_t*)*out_data)[0] = __first_octet;
- memcpy(&((uint8_t*)*out_data)[1], in_data, in_size);
-
- return xsize;
+ tdav_codec_red_t *red = (tdav_codec_red_t *)self;
+ tsk_size_t xsize = (in_size + 1);
+ static const uint8_t __first_octet = 0x00; // F=1, PT=0. Up to the caller to update this first octet with the right PT.
+
+ if(!red || !in_data || !in_size || !out_data || !out_max_size) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ if(*out_max_size < xsize) {
+ if(!(*out_data = tsk_realloc(*out_data, xsize))) {
+ TSK_DEBUG_ERROR("Failed to realloc data");
+ *out_max_size = 0;
+ }
+ *out_max_size = xsize;
+ }
+
+ ((uint8_t*)*out_data)[0] = __first_octet;
+ memcpy(&((uint8_t*)*out_data)[1], in_data, in_size);
+
+ return xsize;
}
static tsk_size_t tdav_codec_red_decode(tmedia_codec_t* self, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size, const tsk_object_t* proto_hdr)
{
- tdav_codec_red_t* red = (tdav_codec_red_t*)self;
- const trtp_rtp_header_t* rtp_hdr = proto_hdr;
- trtp_rtp_packet_t* red_rtp_pkt = tsk_null;
- const uint8_t* pdata = in_data;
- const uint8_t* red_hdr = in_data;
- tsk_size_t red_hdrs_count, i;
- tsk_bool_t last;
- uint8_t F;
- uint16_t timestamp_offset, block_length;
-
- if(!red || !in_data || (in_size < TDAV_CODEC_RED_MIN_PKT_SIZE)|| !out_data){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- if(!red->callback){
- TSK_DEBUG_WARN("Not callback installed for RED data");
- return 0;
- }
-
- if((F = (pdata[0] & 0x80)) == 0){
- i = 1;
- red_hdrs_count = 1;
- }
- else{
- for(i = 0, red_hdrs_count = 0; i < in_size; i+= 4, ++red_hdrs_count){
- if((F = (pdata[i] & 0x80)) == 0){ ++i; ++red_hdrs_count; break; }
- }
- }
-
- if(i >= in_size){
- TSK_DEBUG_ERROR("Invalid data");
- return 0;
- }
-
- pdata += i;
- in_size -= i;
-
- for(i = 0; i < red_hdrs_count && in_size > 0; ++i){
- TSK_OBJECT_SAFE_FREE(red_rtp_pkt);
- if(!(red_rtp_pkt = trtp_rtp_packet_create_null())){
- TSK_DEBUG_ERROR("Failed to create RTP packet");
- continue;
- }
- if(!(red_rtp_pkt->header = trtp_rtp_header_create(rtp_hdr->ssrc, rtp_hdr->seq_num, rtp_hdr->timestamp, rtp_hdr->payload_type, rtp_hdr->marker))){
- TSK_DEBUG_ERROR("Failed to create RTP header");
- continue;
- }
-
- // Must create an RTP packet for each RED chunck as they will be saved in the JB
- last = (i == (red_hdrs_count - 1));
- F = (red_hdr[0] & 0x80);
- red_rtp_pkt->header->payload_type = (red_hdr[0] & 0x7F);
-
- if(last || !F){
- /*
- 0 1 2 3 4 5 6 7
+ tdav_codec_red_t* red = (tdav_codec_red_t*)self;
+ const trtp_rtp_header_t* rtp_hdr = proto_hdr;
+ trtp_rtp_packet_t* red_rtp_pkt = tsk_null;
+ const uint8_t* pdata = in_data;
+ const uint8_t* red_hdr = in_data;
+ tsk_size_t red_hdrs_count, i;
+ tsk_bool_t last;
+ uint8_t F;
+ uint16_t timestamp_offset, block_length;
+
+ if(!red || !in_data || (in_size < TDAV_CODEC_RED_MIN_PKT_SIZE)|| !out_data) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ if(!red->callback) {
+ TSK_DEBUG_WARN("Not callback installed for RED data");
+ return 0;
+ }
+
+ if((F = (pdata[0] & 0x80)) == 0) {
+ i = 1;
+ red_hdrs_count = 1;
+ }
+ else {
+ for(i = 0, red_hdrs_count = 0; i < in_size; i+= 4, ++red_hdrs_count) {
+ if((F = (pdata[i] & 0x80)) == 0) {
+ ++i;
+ ++red_hdrs_count;
+ break;
+ }
+ }
+ }
+
+ if(i >= in_size) {
+ TSK_DEBUG_ERROR("Invalid data");
+ return 0;
+ }
+
+ pdata += i;
+ in_size -= i;
+
+ for(i = 0; i < red_hdrs_count && in_size > 0; ++i) {
+ TSK_OBJECT_SAFE_FREE(red_rtp_pkt);
+ if(!(red_rtp_pkt = trtp_rtp_packet_create_null())) {
+ TSK_DEBUG_ERROR("Failed to create RTP packet");
+ continue;
+ }
+ if(!(red_rtp_pkt->header = trtp_rtp_header_create(rtp_hdr->ssrc, rtp_hdr->seq_num, rtp_hdr->timestamp, rtp_hdr->payload_type, rtp_hdr->marker))) {
+ TSK_DEBUG_ERROR("Failed to create RTP header");
+ continue;
+ }
+
+ // Must create an RTP packet for each RED chunck as they will be saved in the JB
+ last = (i == (red_hdrs_count - 1));
+ F = (red_hdr[0] & 0x80);
+ red_rtp_pkt->header->payload_type = (red_hdr[0] & 0x7F);
+
+ if(last || !F) {
+ /*
+ 0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+
|0| Block PT |
+-+-+-+-+-+-+-+-+
- */
- block_length = (uint16_t)in_size;
- }
- else{
- /*
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- |1| block PT=7 | timestamp offset | block length |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
- timestamp_offset = ((red_hdr[1] << 8) | red_hdr[2]) >> 2;
- block_length = ((red_hdr[2] & 0x03) << 8) | red_hdr[3];
- if(block_length > in_size){
- TSK_DEBUG_ERROR("Invalid 'block length'");
- break;
- }
- red_rtp_pkt->header->timestamp += timestamp_offset;
- red_hdr += 4;
- }
-
- // decode
- if(red->callback){
- // do not use "data_const" as payload will be saved in the jitter buffer and decoded later (async)
- if((red_rtp_pkt->payload.data = tsk_malloc(block_length))){
- memcpy(red_rtp_pkt->payload.data, pdata, block_length);
- red_rtp_pkt->payload.size = block_length;
- red->callback(red->callback_data, red_rtp_pkt);
- }
- }
-
- pdata += block_length;
- in_size -= block_length;
- }
-
- TSK_OBJECT_SAFE_FREE(red_rtp_pkt);
-
- return 0; // must be always zero
+ */
+ block_length = (uint16_t)in_size;
+ }
+ else {
+ /*
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |1| block PT=7 | timestamp offset | block length |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+ timestamp_offset = ((red_hdr[1] << 8) | red_hdr[2]) >> 2;
+ block_length = ((red_hdr[2] & 0x03) << 8) | red_hdr[3];
+ if(block_length > in_size) {
+ TSK_DEBUG_ERROR("Invalid 'block length'");
+ break;
+ }
+ red_rtp_pkt->header->timestamp += timestamp_offset;
+ red_hdr += 4;
+ }
+
+ // decode
+ if(red->callback) {
+ // do not use "data_const" as payload will be saved in the jitter buffer and decoded later (async)
+ if((red_rtp_pkt->payload.data = tsk_malloc(block_length))) {
+ memcpy(red_rtp_pkt->payload.data, pdata, block_length);
+ red_rtp_pkt->payload.size = block_length;
+ red->callback(red->callback_data, red_rtp_pkt);
+ }
+ }
+
+ pdata += block_length;
+ in_size -= block_length;
+ }
+
+ TSK_OBJECT_SAFE_FREE(red_rtp_pkt);
+
+ return 0; // must be always zero
}
static tsk_bool_t tdav_codec_red_sdp_att_match(const tmedia_codec_t* codec, const char* att_name, const char* att_value)
{
- return tsk_true;
+ return tsk_true;
}
static char* tdav_codec_red_sdp_att_get(const tmedia_codec_t* self, const char* att_name)
{
- return tsk_null;
+ return tsk_null;
}
@@ -204,60 +207,58 @@ static char* tdav_codec_red_sdp_att_get(const tmedia_codec_t* self, const char*
/* constructor */
static tsk_object_t* tdav_codec_red_ctor(tsk_object_t * self, va_list * app)
{
- tdav_codec_red_t *red = self;
- if(red){
- /* init base: called by tmedia_codec_create() */
- /* init self */
-
- }
- return self;
+ tdav_codec_red_t *red = self;
+ if(red) {
+ /* init base: called by tmedia_codec_create() */
+ /* init self */
+
+ }
+ return self;
}
/* destructor */
static tsk_object_t* tdav_codec_red_dtor(tsk_object_t * self)
-{
- tdav_codec_red_t *red = self;
- if(red){
- /* deinit base */
- tmedia_codec_video_deinit(red);
- /* deinit self */
-
- }
-
- return self;
+{
+ tdav_codec_red_t *red = self;
+ if(red) {
+ /* deinit base */
+ tmedia_codec_video_deinit(red);
+ /* deinit self */
+
+ }
+
+ return self;
}
/* object definition */
-static const tsk_object_def_t tdav_codec_red_def_s =
-{
- sizeof(tdav_codec_red_t),
- tdav_codec_red_ctor,
- tdav_codec_red_dtor,
- tmedia_codec_cmp,
+static const tsk_object_def_t tdav_codec_red_def_s = {
+ sizeof(tdav_codec_red_t),
+ tdav_codec_red_ctor,
+ tdav_codec_red_dtor,
+ tmedia_codec_cmp,
};
/* plugin definition*/
-static const tmedia_codec_plugin_def_t tdav_codec_red_plugin_def_s =
-{
- &tdav_codec_red_def_s,
-
- (/* tmedia_video | tmedia_audio | */tmedia_t140), // FIXME: for now is only supported with T.140
- tmedia_codec_id_red,
- "red",
- "red codec",
- TMEDIA_CODEC_FORMAT_RED,
- tsk_true,
- 1000, // rate: FIXME: for now it's only for T.140
-
- /* audio */
- { 0 },
-
- /* video (defaul width,height,fps) */
- {176, 144, 15},
-
- tsk_null, // set()
- tdav_codec_red_open,
- tdav_codec_red_close,
- tdav_codec_red_encode,
- tdav_codec_red_decode,
- tdav_codec_red_sdp_att_match,
- tdav_codec_red_sdp_att_get
+static const tmedia_codec_plugin_def_t tdav_codec_red_plugin_def_s = {
+ &tdav_codec_red_def_s,
+
+ (/* tmedia_video | tmedia_audio | */tmedia_t140), // FIXME: for now is only supported with T.140
+ tmedia_codec_id_red,
+ "red",
+ "red codec",
+ TMEDIA_CODEC_FORMAT_RED,
+ tsk_true,
+ 1000, // rate: FIXME: for now it's only for T.140
+
+ /* audio */
+ { 0 },
+
+ /* video (defaul width,height,fps) */
+ {176, 144, 15},
+
+ tsk_null, // set()
+ tdav_codec_red_open,
+ tdav_codec_red_close,
+ tdav_codec_red_encode,
+ tdav_codec_red_decode,
+ tdav_codec_red_sdp_att_match,
+ tdav_codec_red_sdp_att_get
};
const tmedia_codec_plugin_def_t *tdav_codec_red_plugin_def_t = &tdav_codec_red_plugin_def_s;
OpenPOWER on IntegriCloud