diff options
Diffstat (limited to 'branches/1.0/tinyDAV/src/codecs/theora/tdav_codec_theora.c')
-rw-r--r-- | branches/1.0/tinyDAV/src/codecs/theora/tdav_codec_theora.c | 707 |
1 files changed, 0 insertions, 707 deletions
diff --git a/branches/1.0/tinyDAV/src/codecs/theora/tdav_codec_theora.c b/branches/1.0/tinyDAV/src/codecs/theora/tdav_codec_theora.c deleted file mode 100644 index 67fb3e6..0000000 --- a/branches/1.0/tinyDAV/src/codecs/theora/tdav_codec_theora.c +++ /dev/null @@ -1,707 +0,0 @@ -/* -* Copyright (C) 2009-2010 Mamadou Diop. -* -* Contact: Mamadou Diop <diopmamadou(at)doubango.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. -* -*/ - -/**@file tdav_codec_theora.c - * @brief Theora codec plugin - * RTP payloader/depayloader follows draft-barbato-avt-rtp-theora-01. - * For more information about Theora, http://www.theora.org/doc/Theora.pdf. - * @author Mamadou Diop <diopmamadou(at)doubango.org> - * - * @date Created: Sat Nov 8 16:54:58 2009 mdiop - */ -#include "tinydav/codecs/theora/tdav_codec_theora.h" - -#if HAVE_FFMPEG - -#include "tinydav/video/tdav_converter_video.h" - -#include "tinyrtp/rtp/trtp_rtp_packet.h" - -#include "tsk_time.h" -#include "tsk_params.h" -#include "tsk_memory.h" -#include "tsk_debug.h" - -#define THEORA_RTP_PAYLOAD_SIZE 900 -#define THEORA_PAYLOAD_HEADER_SIZE 4 /* 2.2. Payload Header */ -#define THEORA_PAYLOAD_LENGTH_SIZE 2 /* 2.2. Payload Header */ -#define THEORA_IDENT_HEADER_SIZE 42 /* 6.2 Identification Header Decode */ -#define THEORA_CONF_SEND_COUNT 10 /* at 250ms, 500ms, 1000ms, .... */ - -/* 2.2. Payload Header filed 'F'*/ -typedef enum theora_frag_type_e{ - Not_Fragmented = 0, - Start_Fragment = 1, - Continuation_Fragment = 2, - End_Fragment = 3, -} -theora_frag_type_t; - -/* 2.2. Payload Header field 'TDT'*/ -typedef enum theora_datatype_e{ - Raw_Theora_payload = 0, - Theora_Packed_Configuration_payload = 1, - Legacy_Theora_Comment_payload = 2, - Reserved = 3, -} -theora_datatype_t; - -static int tdav_codec_theora_send(tdav_codec_theora_t* self, const uint8_t* data, tsk_size_t size, theora_datatype_t tdt); -static void tdav_codec_theora_rtp_callback(tdav_codec_theora_t *self, const void *data, tsk_size_t size, tsk_bool_t marker); - -static void tdav_codec_theora_encap(tdav_codec_theora_t* theora, const uint8_t* pdata, tsk_size_t size); - -/* ============ Theora Plugin interface functions ================= */ - -#define tdav_codec_theora_fmtp_set tsk_null - -int tdav_codec_theora_open(tmedia_codec_t* self) -{ - int ret; - int size; - float bitRate = 64000.f; - - tdav_codec_theora_t* theora = (tdav_codec_theora_t*)self; - - if(!theora){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - /* the caller (base class) already checked that the codec is not opened */ - - // - // Encoder - // - if(!(theora->encoder.codec = avcodec_find_encoder(CODEC_ID_THEORA))){ - TSK_DEBUG_ERROR("Failed to find Theora encoder"); - return -2; - } - theora->encoder.context = avcodec_alloc_context(); - avcodec_get_context_defaults(theora->encoder.context); - - theora->encoder.context->pix_fmt = PIX_FMT_YUV420P; - theora->encoder.context->time_base.num = 1; - theora->encoder.context->time_base.den = TMEDIA_CODEC_VIDEO(theora)->fps; - theora->encoder.context->width = TMEDIA_CODEC_VIDEO(theora)->width; - theora->encoder.context->height = TMEDIA_CODEC_VIDEO(theora)->height; - - //theora->encoder.context->mb_qmin = theora->encoder.context->qmin = 4; - //theora->encoder.context->mb_qmax = theora->encoder.context->qmax = 4; - theora->encoder.context->mb_decision = FF_MB_DECISION_SIMPLE; - - switch(self->bl){ - case tmedia_bl_low: - default: - bitRate = 64000.f; - break; - case tmedia_bl_medium: - case tmedia_bl_hight: - bitRate = 128000.f; - break; - } - - theora->encoder.context->thread_count = 1; - theora->encoder.context->rtp_payload_size = THEORA_RTP_PAYLOAD_SIZE; - theora->encoder.context->opaque = tsk_null; - theora->encoder.context->bit_rate = (int) (bitRate * 0.80f); - theora->encoder.context->bit_rate_tolerance = (int) (bitRate * 0.20f); - theora->encoder.context->gop_size = TMEDIA_CODEC_VIDEO(theora)->fps*2; // each 2 seconds - - // Picture (YUV 420) - if(!(theora->encoder.picture = avcodec_alloc_frame())){ - TSK_DEBUG_ERROR("Failed to create encoder picture"); - return -2; - } - avcodec_get_frame_defaults(theora->encoder.picture); - - size = avpicture_get_size(PIX_FMT_YUV420P, theora->encoder.context->width, theora->encoder.context->height); - if(!(theora->encoder.buffer = tsk_calloc(size, sizeof(uint8_t)))){ - TSK_DEBUG_ERROR("Failed to allocate encoder buffer"); - return -2; - } - - // Open encoder - if((ret = avcodec_open(theora->encoder.context, theora->encoder.codec)) < 0){ - TSK_DEBUG_ERROR("Failed to open Theora encoder"); - return ret; - } - - // - // Decoder - // - if(!(theora->decoder.codec = avcodec_find_decoder(CODEC_ID_THEORA))){ - TSK_DEBUG_ERROR("Failed to find Theora decoder"); - return -2; - } - theora->decoder.context = avcodec_alloc_context(); - avcodec_get_context_defaults(theora->decoder.context); - - theora->decoder.context->pix_fmt = PIX_FMT_YUV420P; - theora->decoder.context->width = TMEDIA_CODEC_VIDEO(theora)->width; - theora->decoder.context->height = TMEDIA_CODEC_VIDEO(theora)->height; - - // Picture (YUV 420) - if(!(theora->decoder.picture = avcodec_alloc_frame())){ - TSK_DEBUG_ERROR("Failed to create decoder picture"); - return -2; - } - avcodec_get_frame_defaults(theora->decoder.picture); - - size = avpicture_get_size(PIX_FMT_YUV420P, theora->decoder.context->width, theora->decoder.context->height); - if(!(theora->decoder.accumulator = tsk_calloc((size + FF_INPUT_BUFFER_PADDING_SIZE), sizeof(uint8_t)))){ - TSK_DEBUG_ERROR("Failed to allocate decoder buffer"); - return -2; - } - - if(!(theora->decoder.accumulator = tsk_calloc((size + FF_INPUT_BUFFER_PADDING_SIZE), sizeof(uint8_t)))){ - TSK_DEBUG_ERROR("Failed to allocate decoder buffer"); - return -2; - } - - // Open decoder - //if((ret = avcodec_open(theora->decoder.context, theora->decoder.codec)) < 0){ - // TSK_DEBUG_ERROR("Failed to open Theora decoder"); - // return ret; - //} - - return 0; -} - -int tdav_codec_theora_close(tmedia_codec_t* self) -{ - tdav_codec_theora_t* theora = (tdav_codec_theora_t*)self; - - if(!theora){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - /* the caller (base class) already checked that the codec is opened */ - - // - // Encoder - // - if(theora->encoder.context){ - avcodec_close(theora->encoder.context); - av_free(theora->encoder.context); - theora->encoder.context = tsk_null; - } - if(theora->encoder.picture){ - av_free(theora->encoder.picture); - } - if(theora->encoder.buffer){ - TSK_FREE(theora->encoder.buffer); - } - - // - // Decoder - // - if(theora->decoder.context){ - avcodec_close(theora->decoder.context); - if(theora->decoder.context->extradata){ - TSK_FREE(theora->decoder.context->extradata); - theora->decoder.context->extradata_size = 0; - } - av_free(theora->decoder.context); - theora->decoder.context = tsk_null; - } - if(theora->decoder.picture){ - av_free(theora->decoder.picture); - theora->decoder.picture = tsk_null; - } - if(theora->decoder.accumulator){ - TSK_FREE(theora->decoder.accumulator); - } - - return 0; -} - -//#include "tsk_time.h" -tsk_size_t tdav_codec_theora_encode(tmedia_codec_t* self, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size) -{ - int ret; - int size; - - tdav_codec_theora_t* theora = (tdav_codec_theora_t*)self; - - if(!self || !in_data || !in_size || !out_data){ - TSK_DEBUG_ERROR("Invalid parameter"); - return 0; - } - - // wrap yuv420 buffer - size = avpicture_fill((AVPicture *)theora->encoder.picture, (uint8_t*)in_data, PIX_FMT_YUV420P, theora->encoder.context->width, theora->encoder.context->height); - if(size != in_size){ - /* guard */ - TSK_DEBUG_ERROR("Invalid size"); - return 0; - } - /* Flip */ -#if FLIP_ENCODED_PICT - tdav_converter_video_flip(theora->encoder.picture, theora->encoder.context->height); -#endif - - // Encode data - //theora->encoder.picture->pts = tsk_time_epoch(); - theora->encoder.picture->pts = AV_NOPTS_VALUE; - //theora->encoder.picture->pict_type = FF_I_TYPE; - ret = avcodec_encode_video(theora->encoder.context, theora->encoder.buffer, size, theora->encoder.picture); - if(ret > 0){ - tdav_codec_theora_encap(theora, theora->encoder.buffer, (tsk_size_t)ret); - } - - return 0; -} - -tsk_size_t tdav_codec_theora_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) -{ - const uint8_t* pdata = in_data; - int pkts; - const uint8_t* pay_ptr; - tsk_size_t pay_size; - //tsk_size_t hdr_size; - tsk_size_t xsize, retsize = 0; - int got_picture_ptr; - int ret; - - tdav_codec_theora_t* theora = (tdav_codec_theora_t*)self; - const trtp_rtp_header_t* rtp_hdr = proto_hdr; - - if(!self || !in_data || (in_size<(THEORA_PAYLOAD_HEADER_SIZE + THEORA_PAYLOAD_LENGTH_SIZE)) || !out_data || !theora->decoder.context){ - TSK_DEBUG_ERROR("Invalid parameter"); - return 0; - } - - /* Packet lost? */ - if(theora->decoder.last_seq != (rtp_hdr->seq_num - 1) && theora->decoder.last_seq){ - if(theora->decoder.last_seq == rtp_hdr->seq_num){ - // Could happen on some stupid emulators - //TSK_DEBUG_INFO("Packet duplicated, seq_num=%d", rtp_hdr->seq_num); - return 0; - } - TSK_DEBUG_INFO("Packet lost, seq_num=%d", rtp_hdr->seq_num); - } - theora->decoder.last_seq = rtp_hdr->seq_num; - - xsize = avpicture_get_size(theora->decoder.context->pix_fmt, theora->decoder.context->width, theora->decoder.context->height); - - /* 2.2. Payload Header - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Configuration Ident | F |TDT|# pkts.| - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - /* 2.3. Payload Data - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Payload Length | Theora Data .. - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - pkts = (pdata[3] & 0x0F); - pay_ptr = (pdata + THEORA_PAYLOAD_HEADER_SIZE); - - do{ /* pkts=0 for fragmented packets */ - - pay_size = pay_ptr[0], pay_size<<=8, pay_size |= pay_ptr[1]; /* Big Endian read */ - pay_ptr += THEORA_PAYLOAD_LENGTH_SIZE; - /* check size validity */ - if((pay_ptr + pay_size)>(pdata + in_size)){ - TSK_DEBUG_ERROR("Too short"); - break; - } - - switch((pdata[3]>>4) & 0x03){ - case Raw_Theora_payload: - { /* ====== Theora data (2.2. Payload Header, 2.3. Payload Data) ====== */ - /* append buffer */ - if((int)(theora->decoder.accumulator_pos + pay_size) <= xsize){ - memcpy(&((uint8_t*)theora->decoder.accumulator)[theora->decoder.accumulator_pos], pay_ptr, pay_size); - theora->decoder.accumulator_pos += pay_size; - } - else{ - TSK_DEBUG_WARN("Buffer overflow"); - theora->decoder.accumulator_pos = 0; - break; - } - /* only take care if last packet (What about the RTP marker?) */ - if(((pdata[3]>>6) == Not_Fragmented || (pdata[3]>>6) == End_Fragment /*|| rtp_hdr->marker*/) && theora->decoder.opened){ - AVPacket packet; - /* Perform decoding */ - av_init_packet(&packet); - packet.size = theora->decoder.accumulator_pos; - packet.data = theora->decoder.accumulator; - ret = avcodec_decode_video2(theora->decoder.context, theora->decoder.picture, &got_picture_ptr, &packet); - - if(ret <0 || !got_picture_ptr){ - TSK_DEBUG_WARN("Failed to decode the buffer"); - } - else{ - retsize = xsize; -#if FLIP_DECODED_PICT - tdav_converter_video_flip(theora->decoder.picture, theora->decoder.context->height); -#endif - /* allocate buffer */ - if(*out_max_size <xsize){ - if((*out_data = tsk_realloc(*out_data, xsize))){ - *out_max_size = xsize; - } - else{ - TSK_DEBUG_ERROR("Failed to allocate new buffer"); - *out_max_size = 0; - return 0; - } - } - /* copy picture into a linear buffer */ - avpicture_layout((AVPicture *)theora->decoder.picture, theora->decoder.context->pix_fmt, theora->decoder.context->width, theora->decoder.context->height, - *out_data, retsize); - } - /* in all cases: reset accumulator */ - theora->decoder.accumulator_pos = 0; - } - break; - } - case Theora_Packed_Configuration_payload: - {/* ====== Configuration packet (3.1.1. Packed Configuration) ====== */ - static uint8_t __theora_comment_hdr[] = {0x81, 0x74, 0x68, 0x65, 0x6F, 0x72, 0x61, - 0x00, 0x00, 0x00, 0x08, /* 4-byte length */ - 'd', 'o', 'u', 'b', 'a', 'n', 'g', 'o', /* UTF-8 encoded string */ - }; - - /* http://www.theora.org/doc/Theora.pdf - Chapter 6 - A Theora bitstream begins with three header packets. The header packets - are, in order, the identifcation header, the comment header, and the setup - header. All are required for decode compliance. An end-of-packet condition - encountered while decoding the identification or setup header packets renders - the stream undecodable. An end-of-packet condition encountered while decode - the comment header is a non-fatal error condition, and MAY be ignored by a - decoder. - - Decode continues according to HEADERTYPE. The identification header - is type 0x80, the comment header is type 0x81, and the setup header is type - 0x82. - */ - /*TSK_DEBUG_INFO("Theora_Packed_Configuration_payload");*/ - - if(!theora->decoder.opened /*|| (conf_ident changed)*/){ - if(!theora->decoder.conf_pkt){ - theora->decoder.conf_pkt = tsk_buffer_create(pay_ptr, pay_size); - } - else{ - tsk_buffer_append(theora->decoder.conf_pkt, pay_ptr, pay_size); - } - - if((pdata[3]>>6) == Not_Fragmented || (pdata[3]>>6) == End_Fragment || rtp_hdr->marker){ - if(theora->decoder.conf_pkt->size > THEORA_IDENT_HEADER_SIZE){ - const uint8_t* conf_ptr = theora->decoder.conf_pkt->data; - int setup_size = theora->decoder.conf_pkt->size - THEORA_IDENT_HEADER_SIZE; - int extradata_size = (2 + THEORA_IDENT_HEADER_SIZE) + (2 + setup_size) + (2 + sizeof(__theora_comment_hdr)); - if(conf_ptr[0] == 0x80 && conf_ptr[THEORA_IDENT_HEADER_SIZE] == 0x82){ /* Do not check for 't'h'e'o'r'a' */ - /* save configration identification */ - memcpy(theora->decoder.conf_ident, &pdata[0], sizeof(theora->decoder.conf_ident)); - if(theora->decoder.context->extradata){ - TSK_FREE(theora->decoder.context->extradata); - } - if((theora->decoder.context->extradata = tsk_calloc(extradata_size + FF_INPUT_BUFFER_PADDING_SIZE, 1))){ - int index = 0; - /* Because of endianess pb. do not use uint16_t or uint32_t */ - theora->decoder.context->extradata[index++] = 0x00; - theora->decoder.context->extradata[index++] = THEORA_IDENT_HEADER_SIZE; - memcpy(&theora->decoder.context->extradata[index], &conf_ptr[0], THEORA_IDENT_HEADER_SIZE); - index += THEORA_IDENT_HEADER_SIZE; - - theora->decoder.context->extradata[index++] = (setup_size >>8) & 0xFF; - theora->decoder.context->extradata[index++] = (setup_size & 0xFF); - memcpy(&theora->decoder.context->extradata[index], &conf_ptr[THEORA_IDENT_HEADER_SIZE], setup_size); - index+=setup_size; - - theora->decoder.context->extradata[index++] = 0x00; - theora->decoder.context->extradata[index++] = sizeof(__theora_comment_hdr);/* <0xFF */ - memcpy(&theora->decoder.context->extradata[index], __theora_comment_hdr, sizeof(__theora_comment_hdr)); - - theora->decoder.context->extradata_size = extradata_size; - - if((ret = avcodec_open(theora->decoder.context, theora->decoder.codec)) == 0){ - theora->decoder.opened = tsk_true; - } - else{ - TSK_DEBUG_ERROR("Failed to open theora decoder %d", ret); - TSK_FREE(theora->decoder.context->extradata); - theora->decoder.context->extradata_size = 0; - } - } - } - else{ - TSK_DEBUG_ERROR("Invalid configuration packet"); - } - } - else{ - TSK_DEBUG_ERROR("Too short"); - } - tsk_buffer_cleanup(theora->decoder.conf_pkt); - } - } - break; - } - case Legacy_Theora_Comment_payload: - /*TSK_DEBUG_INFO("Legacy_Theora_Comment_payload");*/ - break; - case Reserved: - /*TSK_DEBUG_INFO("Reserved");*/ - break; - } - } - while(--pkts>0); - - - - return retsize; -} - -tsk_bool_t tdav_codec_theora_fmtp_match(const tmedia_codec_t* codec, const char* fmtp) -{ - tsk_bool_t ret = tsk_true; // accept decoding any size - tsk_params_L_t* params = tsk_null; - tmedia_codec_video_t* theora = (tmedia_codec_video_t*)codec; - - if((params = tsk_params_fromstring(fmtp, ";", tsk_true))){ - int width = tsk_params_get_param_value_as_int(params, "width"); - int height = tsk_params_get_param_value_as_int(params, "height"); - - // Set Encoding size - switch(codec->bl){ - case tmedia_bl_low: - default: - if(width<=176 && height<=144){ - theora->width = width, theora->height = height; - } - else{ - theora->width = 176, theora->height = 144; - } - break; - - case tmedia_bl_medium: - case tmedia_bl_hight: - if(width<=352 && height<=288){ - theora->width = width, theora->height = height; - } - else{ - theora->width = 352, theora->height = 288; - } - break; - } - } - TSK_OBJECT_SAFE_FREE(params); - - return ret; -} - -char* tdav_codec_theora_fmtp_get(const tmedia_codec_t* self) -{ - switch(self->bl){ - case tmedia_bl_low: - default: - return tsk_strdup("sampling=YCbCr-4:2:0; width=176; height=144"); - break; - case tmedia_bl_medium: - case tmedia_bl_hight: - return tsk_strdup("sampling=YCbCr-4:2:0; width=352; height=288"); - break; - } -} - - - -/* constructor */ -static tsk_object_t* tdav_codec_theora_ctor(tsk_object_t * self, va_list * app) -{ - tdav_codec_theora_t *theora = self; - if(theora){ - /* init base: called by tmedia_codec_create() */ - /* init self */ - //TSK_OBJECT_SAFE_FREE(theora->conf_data); - } - return self; -} -/* destructor */ -static tsk_object_t* tdav_codec_theora_dtor(tsk_object_t * self) -{ - tdav_codec_theora_t *theora = self; - if(theora){ - /* deinit base */ - tmedia_codec_video_deinit(self); - /* deinit self */ - TSK_OBJECT_SAFE_FREE(theora->decoder.conf_pkt); - TSK_FREE(theora->rtp.ptr); - theora->rtp.size = 0; - } - - return self; -} -/* object definition */ -static const tsk_object_def_t tdav_codec_theora_def_s = -{ - sizeof(tdav_codec_theora_t), - tdav_codec_theora_ctor, - tdav_codec_theora_dtor, - tmedia_codec_cmp, -}; -/* plugin definition*/ -static const tmedia_codec_plugin_def_t tdav_codec_theora_plugin_def_s = -{ - &tdav_codec_theora_def_s, - - tmedia_video, - "theora", - "Theora Codec", - TMEDIA_CODEC_FORMAT_THEORA, - tsk_true, - 90000, // rate - - /* audio */ - { 0 }, - - /* video */ - {176, 144, 15}, - - tdav_codec_theora_open, - tdav_codec_theora_close, - tdav_codec_theora_encode, - tdav_codec_theora_decode, - tdav_codec_theora_fmtp_match, - tdav_codec_theora_fmtp_get, - tdav_codec_theora_fmtp_set -}; -const tmedia_codec_plugin_def_t *tdav_codec_theora_plugin_def_t = &tdav_codec_theora_plugin_def_s; - - - -static void tdav_codec_theora_encap(tdav_codec_theora_t* theora, const uint8_t* pdata, tsk_size_t size) -{ - if((theora->encoder.conf_count < THEORA_CONF_SEND_COUNT) && theora->encoder.context && theora->encoder.context->extradata){ - if((theora->encoder.conf_last + (250 *theora->encoder.conf_count)) < tsk_time_epoch()){ - int hdr_size, i, exd_size = theora->encoder.context->extradata_size, conf_pkt_size = 0; - uint8_t *conf_pkt_ptr = tsk_null, *exd_ptr = theora->encoder.context->extradata; - for(i=0; i<3 && exd_size; i++){ - hdr_size = exd_ptr[0], hdr_size<<=8, hdr_size |= exd_ptr[1]; - exd_ptr += 2; - exd_size -= 2; - if(hdr_size > exd_size){ - TSK_DEBUG_ERROR("Invalid extradata"); - TSK_FREE(conf_pkt_ptr); - conf_pkt_size = 0; - } - - if(exd_ptr[0] == 0x80 || exd_ptr[0] == 0x82){ /* Ignore 'comment' which is equal to '0x81' */ - if((conf_pkt_ptr = tsk_realloc(conf_pkt_ptr, (conf_pkt_size + hdr_size)))){ - memcpy((conf_pkt_ptr + conf_pkt_size), exd_ptr, hdr_size); - conf_pkt_size += hdr_size; - } - } - exd_size -= hdr_size; - exd_ptr += hdr_size; - } - - /* Send the conf pack */ - if(conf_pkt_ptr && conf_pkt_size){ - /*TSK_DEBUG_INFO("Sending Configuration Packet");*/ - tdav_codec_theora_send(theora, conf_pkt_ptr, conf_pkt_size, Theora_Packed_Configuration_payload); - TSK_FREE(conf_pkt_ptr); - } - - theora->encoder.conf_last = tsk_time_epoch(); - theora->encoder.conf_count++; - } - } - - /* Send Theora Raw data */ - tdav_codec_theora_send(theora, pdata, size, Raw_Theora_payload); -} - -int tdav_codec_theora_send(tdav_codec_theora_t* self, const uint8_t* data, tsk_size_t size, theora_datatype_t tdt) -{ - /* 2.2. Payload Header - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Configuration Ident | F |TDT|# pkts.| - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - uint8_t pay_hdr[THEORA_PAYLOAD_HEADER_SIZE/*4*/ + THEORA_PAYLOAD_LENGTH_SIZE/*2*/] = {0x01, 0x19, 0x83, 0x00, 0x00, 0x00}; - //uint8_t* pay_ptr = tsk_null; - tsk_size_t pay_size; - tsk_bool_t frag, first = tsk_true; - - pay_hdr[3] = (tdt & 0xFF) <<4; - - /* whether the packet will be fragmented or not */ - frag = (size > THEORA_RTP_PAYLOAD_SIZE); - - while(size){ - pay_size = TSK_MIN(THEORA_RTP_PAYLOAD_SIZE, size); - pay_hdr[4] = pay_size>>8, pay_hdr[5] = pay_size & 0xFF; - - if(frag){ - if(first){ - first = tsk_false; - pay_hdr[3] &= 0x3F, pay_hdr[3] |= (Start_Fragment <<6); - } - else{ /* could not be 'first' and 'last' */ - if(size<=THEORA_RTP_PAYLOAD_SIZE){ - /* Last frag */ - pay_hdr[3] &= 0x3F, pay_hdr[3] |= (End_Fragment <<6); - } - else{ - /* Continuation frag */ - pay_hdr[3] &= 0x3F, pay_hdr[3] |= (Continuation_Fragment <<6); - } - } - } - else{ - pay_hdr[3] |= 0x01; /* 'pkts' */ - pay_hdr[3] &= 0x3F, pay_hdr[3] |= (Not_Fragmented <<6); - } - - if(self->rtp.size < (pay_size + sizeof(pay_hdr))){ - if(!(self->rtp.ptr = tsk_realloc(self->rtp.ptr, (pay_size + sizeof(pay_hdr))))){ - TSK_DEBUG_ERROR("Failed to allocate new buffer"); - return -2; - } - self->rtp.size = (pay_size + sizeof(pay_hdr)); - } - - memcpy(self->rtp.ptr, pay_hdr, sizeof(pay_hdr)); - memcpy((self->rtp.ptr + sizeof(pay_hdr)), data, pay_size); - data += pay_size; - size -= pay_size; - - // Send data over the network - if(TMEDIA_CODEC_VIDEO(self)->callback){ - TMEDIA_CODEC_VIDEO(self)->callback(TMEDIA_CODEC_VIDEO(self)->callback_data, self->rtp.ptr, (pay_size + sizeof(pay_hdr)), (3003* (30/TMEDIA_CODEC_VIDEO(self)->fps)), (size == 0)); - } - } - - return 0; -} - -#endif /* HAVE_FFMPEG */
\ No newline at end of file |