summaryrefslogtreecommitdiffstats
path: root/branches/1.0/tinyDAV/src/video
diff options
context:
space:
mode:
Diffstat (limited to 'branches/1.0/tinyDAV/src/video')
-rw-r--r--branches/1.0/tinyDAV/src/video/tdav_converter_video.c285
-rw-r--r--branches/1.0/tinyDAV/src/video/tdav_runnable_video.c95
-rw-r--r--branches/1.0/tinyDAV/src/video/tdav_session_video.c675
3 files changed, 0 insertions, 1055 deletions
diff --git a/branches/1.0/tinyDAV/src/video/tdav_converter_video.c b/branches/1.0/tinyDAV/src/video/tdav_converter_video.c
deleted file mode 100644
index 60bf44b..0000000
--- a/branches/1.0/tinyDAV/src/video/tdav_converter_video.c
+++ /dev/null
@@ -1,285 +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_converter_video.c
-* @brief Video converter.
-*
-* @author Mamadou Diop <diopmamadou(at)doubango.org>
-* @author Alex Vishnev (Added support for rotation)
-*
-* @date Created: Sat Nov 8 16:54:58 2009 mdiop
-*/
-#include "tinydav/video/tdav_converter_video.h"
-
-#include "tsk_memory.h"
-#include "tsk_debug.h"
-
-// use macro for performance reasons keep (called (15x3) times per seconds)
-#define rotate90(srcw, srch, srcdata, dstdata) \
-{ \
- register int i,j; \
- register int newx = 0; \
- for (i = 0; i < (int)srcw; i ++ ){ \
- for( j = srch-1; j >=0; j -- ){ \
- dstdata[newx++] = srcdata[j * srcw + i]; \
- } \
- } \
-}
-
-
-
-tdav_converter_video_t* tdav_converter_video_create(tsk_size_t srcWidth, tsk_size_t srcHeight, tsk_size_t dstWidth, tsk_size_t dstHeight, tmedia_chroma_t chroma, tsk_bool_t toYUV420)
-{
-#if HAVE_FFMPEG || HAVE_SWSSCALE
- tdav_converter_video_t* converter;
- enum PixelFormat pixfmt;
-
- TSK_DEBUG_INFO("Creating new Video Converter src=(%dx%d) dst=(%dx%d)", srcWidth, srcHeight, dstWidth, dstHeight);
-
- switch(chroma){
- case tmedia_rgb24:
- pixfmt = PIX_FMT_RGB24;
- break;
- case tmedia_bgr24:
- pixfmt = PIX_FMT_BGR24;
- break;
- case tmedia_rgb32:
- pixfmt = PIX_FMT_RGB32;
- break;
- case tmedia_rgb565le:
- pixfmt = PIX_FMT_RGB565LE;
- break;
- case tmedia_rgb565be:
- pixfmt = PIX_FMT_RGB565BE;
- break;
- case tmedia_nv21:
- pixfmt = PIX_FMT_NV21;
- break;
- case tmedia_nv12:
- pixfmt = PIX_FMT_NV12;
- break;
- case tmedia_yuv422p:
- pixfmt = PIX_FMT_YUV422P;
- break;
- case tmedia_uyvy422:
- pixfmt = PIX_FMT_UYVY422;
- break;
- case tmedia_yuv420p:
- pixfmt = PIX_FMT_YUV420P;
- break;
- default:
- TSK_DEBUG_ERROR("Invalid chroma");
- return tsk_null;
- }
-
- if(!(converter = tsk_object_new(tdav_converter_video_def_t))){
- TSK_DEBUG_ERROR("Failed to create Video Converter object");
- return tsk_null;
- }
-
- // Set values
- converter->toYUV420 = toYUV420;
- converter->pixfmt = pixfmt;
- converter->srcWidth = srcWidth ? srcWidth : dstWidth;
- converter->srcHeight = srcHeight ? srcHeight : dstHeight;
- converter->dstWidth = dstWidth ? dstWidth : srcWidth;
- converter->dstHeight = dstHeight ? dstHeight : srcHeight;
-
- return converter;
-#else
- return tsk_null;
-#endif
-}
-
-tsk_size_t tdav_converter_video_convert(tdav_converter_video_t* self, const void* buffer, void** output, tsk_size_t* output_max_size)
-{
-#if HAVE_FFMPEG || HAVE_SWSSCALE
- int ret, size;
- enum PixelFormat srcFormat, dstFormat;
-
- if(!self || !buffer || !output){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- /* Formats */
- srcFormat = self->toYUV420 ? self->pixfmt : PIX_FMT_YUV420P;
- dstFormat = self->toYUV420 ? PIX_FMT_YUV420P : self->pixfmt;
-
-
- /* Pictures */
- if(!self->srcFrame){
- if(!(self->srcFrame = avcodec_alloc_frame())){
- TSK_DEBUG_ERROR("Failed to create picture");
- return 0;
- }
- }
- if(!self->dstFrame){
- if(!(self->dstFrame = avcodec_alloc_frame())){
- TSK_DEBUG_ERROR("Failed to create picture");
- return 0;
- }
- }
-
- size = avpicture_get_size(dstFormat, self->dstWidth, self->dstHeight);
- if((int)*output_max_size <size){
- if(!(*output = tsk_realloc(*output, size))){
- *output_max_size = 0;
- TSK_DEBUG_ERROR("Failed to allocate buffer");
- return 0;
- }
- *output_max_size = size;
- }
-
- /* Wrap the source buffer */
- ret = avpicture_fill((AVPicture *)self->srcFrame, (uint8_t*)buffer, srcFormat, self->srcWidth, self->srcHeight);
- /* Wrap the destination buffer */
- ret = avpicture_fill((AVPicture *)self->dstFrame, (uint8_t*)*output, dstFormat, self->dstWidth, self->dstHeight);
-
- /* === performs conversion === */
- /* Context */
- if(!self->context){
- self->context = sws_getContext(
- self->srcWidth, self->srcHeight, srcFormat,
- self->dstWidth, self->dstHeight, dstFormat,
- SWS_FAST_BILINEAR, NULL, NULL, NULL);
-
- if(!self->context){
- TSK_DEBUG_ERROR("Failed to create context");
- return 0;
- }
- }
- // chroma conversion
- ret = sws_scale(self->context, (const uint8_t* const*)self->srcFrame->data, self->srcFrame->linesize, 0, self->srcHeight,
- self->dstFrame->data, self->dstFrame->linesize);
- if(ret < 0){
- TSK_FREE(*output);
- return 0;
- }
-
- // Rotation
- if(self->rotation && (PIX_FMT_YUV420P == dstFormat) && self->rotation==90/*FIXME: For now only 90° rotation is supported */){
- // because we rotated 90 width = original height, height = original width
- int w = self->dstHeight;
- int h = self->dstWidth;
-
- // allocation rotation frame if not already done
- if(!(self->rot.frame) && !(self->rot.frame = avcodec_alloc_frame())){
- TSK_DEBUG_ERROR("failed to allocate rotation frame");
- TSK_FREE(*output);
- return(0);
- }
-
- // allocate rotation temporary buffer
- if(!self->rot.buffer){
- int buff_size = avpicture_get_size(dstFormat, w, h);
- if (!(self->rot.buffer = (uint8_t *)av_malloc(buff_size))){
- TSK_DEBUG_ERROR("failed to allocate new buffer for the frame");
- TSK_FREE(*output);
- return(0);
- }
- }
-
- //wrap
- avpicture_fill((AVPicture *)self->rot.frame, self->rot.buffer, dstFormat, w, h);
- // rotate
- rotate90(self->dstWidth, self->dstHeight, self->dstFrame->data[0], self->rot.frame->data[0]);
- rotate90(self->dstWidth/2, self->dstHeight/2, self->dstFrame->data[1], self->rot.frame->data[1]);
- rotate90(self->dstWidth/2, self->dstHeight/2, self->dstFrame->data[2], self->rot.frame->data[2]);
-
- /* Context */
- if(!self->rot.context){
- if(!(self->rot.context = sws_getContext(w, h, dstFormat, h, w, dstFormat, SWS_FAST_BILINEAR, NULL, NULL, NULL))){
- TSK_DEBUG_ERROR("Failed to create context");
- TSK_FREE(*output);
- return 0;
- }
- }
-
- // Copy frame
- if((ret = sws_scale(self->rot.context, (const uint8_t* const*)self->rot.frame->data, self->rot.frame->linesize,
- 0, h, self->dstFrame->data, self->dstFrame->linesize)) <0)
- {
- TSK_DEBUG_ERROR("Failed to copy frame");
- TSK_FREE(*output);
- return 0;
- }
- }//end of rotation
-
- return size;
-#else
- return 0;
-#endif
-}
-
-
-
-//=================================================================================================
-// Video Converter object definition
-//
-static tsk_object_t* tdav_converter_video_ctor(tsk_object_t * self, va_list * app)
-{
- tdav_converter_video_t *converter = self;
- if(converter){
-
- }
- return self;
-}
-
-static tsk_object_t* tdav_converter_video_dtor(tsk_object_t * self)
-{
- tdav_converter_video_t *converter = self;
- if(converter){
-#if HAVE_FFMPEG || HAVE_SWSSCALE
- if(converter->context){
- sws_freeContext(converter->context);
- }
- if(converter->srcFrame){
- av_free(converter->srcFrame);
- }
- if(converter->dstFrame){
- av_free(converter->dstFrame);
- }
-
- // Rotation
- if(converter->rot.context){
- sws_freeContext(converter->rot.context);
- }
- if(converter->rot.frame){
- av_free(converter->rot.frame);
- }
- if(converter->rot.buffer){
- TSK_FREE(converter->rot.buffer);
- }
-#endif
- }
-
- return self;
-}
-
-static const tsk_object_def_t tdav_converter_video_def_s =
-{
- sizeof(tdav_converter_video_t),
- tdav_converter_video_ctor,
- tdav_converter_video_dtor,
- tsk_null,
-};
-const tsk_object_def_t *tdav_converter_video_def_t = &tdav_converter_video_def_s;
diff --git a/branches/1.0/tinyDAV/src/video/tdav_runnable_video.c b/branches/1.0/tinyDAV/src/video/tdav_runnable_video.c
deleted file mode 100644
index ebb6896..0000000
--- a/branches/1.0/tinyDAV/src/video/tdav_runnable_video.c
+++ /dev/null
@@ -1,95 +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_runnable_video.c
- * @brief Video runnable used by codecs.
- *
- * @author Mamadou Diop <diopmamadou(at)doubango.org>
- *
- * @date Created: Sat Nov 8 16:54:58 2009 mdiop
- */
-#include "tinydav/video/tdav_runnable_video.h"
-
-#include "tsk_buffer.h"
-#include "tsk_debug.h"
-
-tdav_runnable_video_t* tdav_runnable_video_create(tsk_runnable_func_run run_f, const void* userdata)
-{
- tdav_runnable_video_t* runnable;
-
- if((runnable = tsk_object_new(tdav_runnable_video_def_t))){
- TSK_RUNNABLE(runnable)->run = run_f;
- runnable->userdata = userdata;
- }
- return runnable;
-}
-
-int tdav_runnable_video_start(tdav_runnable_video_t* self)
-{
- if(!self){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- return tsk_runnable_start(TSK_RUNNABLE(self), tsk_buffer_def_t);
-}
-
-int tdav_runnable_video_stop(tdav_runnable_video_t* self)
-{
- if(!self){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- return tsk_runnable_stop(TSK_RUNNABLE(self));
-}
-
-
-//=================================================================================================
-// Video Runable object definition
-//
-static tsk_object_t* tdav_runnable_video_ctor(tsk_object_t * self, va_list * app)
-{
- tdav_runnable_video_t *runnable = self;
- if(runnable){
-
- }
- return self;
-}
-
-static tsk_object_t* tdav_runnable_video_dtor(tsk_object_t * self)
-{
- tdav_runnable_video_t *runnable = self;
- if(runnable){
- tsk_runnable_stop(TSK_RUNNABLE(runnable));
- }
-
- return self;
-}
-
-static const tsk_object_def_t tdav_runnable_video_def_s =
-{
- sizeof(tdav_runnable_video_t),
- tdav_runnable_video_ctor,
- tdav_runnable_video_dtor,
- tsk_null,
-};
-const tsk_object_def_t *tdav_runnable_video_def_t = &tdav_runnable_video_def_s;
diff --git a/branches/1.0/tinyDAV/src/video/tdav_session_video.c b/branches/1.0/tinyDAV/src/video/tdav_session_video.c
deleted file mode 100644
index c276fe8..0000000
--- a/branches/1.0/tinyDAV/src/video/tdav_session_video.c
+++ /dev/null
@@ -1,675 +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_session_video.c
- * @brief Video Session plugin.
- *
- * @author Mamadou Diop <diopmamadou(at)doubango.org>
- *
- * @date Created: Sat Nov 8 16:54:58 2009 mdiop
- */
-#include "tinydav/video/tdav_session_video.h"
-
-#include "tinydav/video/tdav_converter_video.h"
-
-#include "tinymedia/tmedia_consumer.h"
-#include "tinymedia/tmedia_producer.h"
-
-#include "tinyrtp/trtp_manager.h"
-#include "tinyrtp/rtp/trtp_rtp_packet.h"
-
-#include "tsk_memory.h"
-#include "tsk_debug.h"
-
-// RTP/RTCP callback (From the network to the consumer)
-static int tdav_session_video_rtp_cb(const void* callback_data, const struct trtp_rtp_packet_s* packet)
-{
- tdav_session_video_t* session = (tdav_session_video_t*)callback_data;
- int ret = 0;
-
- if(!session || !packet){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- if(session->consumer){
- tmedia_codec_t* codec;
- tsk_istr_t format;
- tsk_size_t out_size;
-
- // Find the codec to use to decode the RTP payload
- tsk_itoa(packet->header->payload_type, &format);
- if(!(codec = tmedia_codec_find_by_format(TMEDIA_SESSION(session)->neg_codecs, format)) || !codec->plugin || !codec->plugin->decode){
- TSK_DEBUG_ERROR("%s is not a valid payload for this session", format);
- ret = -2;
- goto bail;
- }
- // Open codec if not already done
- if(!TMEDIA_CODEC(codec)->opened){
- tsk_safeobj_lock(session);
- if((ret = tmedia_codec_open(codec))){
- tsk_safeobj_unlock(session);
- TSK_DEBUG_ERROR("Failed to open [%s] codec", codec->plugin->desc);
- goto bail;
- }
- tsk_safeobj_unlock(session);
- }
- // Decode data
- out_size = codec->plugin->decode(codec, packet->payload.data, packet->payload.size, &session->decoder.buffer, &session->decoder.buffer_size, packet->header);
- // check
- if(!out_size || !session->decoder.buffer){
- goto bail;
- }
-
- // Convert decoded data to the consumer chroma and size
-#define CONSUMER_INSIZE_CHANGED ((session->consumer->video.in.width * session->consumer->video.in.height * 3)/2 != out_size)// we have good reasons not to use 1.5f
-#define CONSUMER_DISPLAY_NEED_RESIZE (session->consumer->video.in.width != session->consumer->video.display.width || session->consumer->video.in.height != session->consumer->video.display.height)
-#define CONSUMER_DISPLAYSIZE_CHANGED (session->conv.consumerLastWidth != session->consumer->video.display.width || session->conv.consumerLastHeight != session->consumer->video.display.height)
-#define CONSUMER_DISPLAY_NEED_CHROMACHANGE (session->consumer->video.display.chroma != tmedia_yuv420p)
-
- if((CONSUMER_DISPLAY_NEED_CHROMACHANGE || CONSUMER_DISPLAYSIZE_CHANGED || CONSUMER_DISPLAY_NEED_RESIZE || CONSUMER_INSIZE_CHANGED)){
- tsk_size_t _output_size;
-
- // Create video converter if not already done
- if(!session->conv.fromYUV420 || CONSUMER_DISPLAYSIZE_CHANGED || CONSUMER_INSIZE_CHANGED){
- const tmedia_video_size_t* video_size = tmedia_get_video_size(tmedia_yuv420p, out_size);
- TSK_OBJECT_SAFE_FREE(session->conv.fromYUV420);
- // update in (set by the codec)
- session->consumer->video.in.width = video_size->width;
- session->consumer->video.in.height = video_size->height;
-
- // important: do not override the display size (used by the end-user) unless requested
- if(session->consumer->video.display.auto_resize){
- session->consumer->video.display.width = session->consumer->video.in.width;
- session->consumer->video.display.height = session->consumer->video.in.height;
- }
- // set xdisplay with latest valid sizes (set by the user)
- session->conv.consumerLastWidth = session->consumer->video.display.width;
- session->conv.consumerLastHeight = session->consumer->video.display.height;
- if(!(session->conv.fromYUV420 = tdav_converter_video_create(video_size->width, video_size->height, session->conv.consumerLastWidth, session->conv.consumerLastHeight,
- session->consumer->video.display.chroma, tsk_false))){
- TSK_DEBUG_ERROR("Failed to create video converter");
- ret = -3;
- goto bail;
- }
- }
- // convert data to the consumer's chroma
- _output_size = tdav_converter_video_convert(session->conv.fromYUV420, session->decoder.buffer, &session->decoder.conv_buffer, &session->decoder.conv_buffer_size);
- if(!_output_size || !session->decoder.conv_buffer){
- TSK_DEBUG_ERROR("Failed to convert YUV420 buffer to consumer's chroma");
- ret = -4;
- goto bail;
- }
-
- tmedia_consumer_consume(session->consumer, &session->decoder.conv_buffer, _output_size, packet->header);
- if(!session->decoder.conv_buffer){
- /* taken by the consumer */
- session->decoder.conv_buffer_size = 0;
- }
-
- }
- else{
- tmedia_consumer_consume(session->consumer, &session->decoder.buffer, out_size, packet->header);
- if(!session->decoder.buffer){
- /* taken by the consumer */
- session->decoder.buffer_size = 0;
- }
- }
-
-bail:
- TSK_OBJECT_SAFE_FREE(codec);
- }
- return ret;
-}
-
-// Codec callback (From codec/producer to the network) to send() data "as is"
-static int tdav_session_video_raw_cb(const void* callback_data, const void* buffer, tsk_size_t size, uint32_t duration, tsk_bool_t marker)
-{
- tdav_session_video_t* session = (tdav_session_video_t*)callback_data;
-
- if(session->rtp_manager && session->rtp_manager->started){
- return trtp_manager_send_rtp(session->rtp_manager, buffer, size, duration, marker, marker);
- }
-
- return 0;
-}
-
-// Producer callback (From the producer to the network) => encode data before send()
-static int tdav_session_video_producer_enc_cb(const void* callback_data, const void* buffer, tsk_size_t size)
-{
- tdav_session_video_t* session = (tdav_session_video_t*)callback_data;
- tsk_size_t yuv420p_size = 0;
- int ret = 0;
-
- if(session && session->rtp_manager){
- /* encode */
- tsk_size_t out_size = 0;
- tmedia_codec_t* codec = tsk_null;
-
- // Use first codec to encode data
- if((codec = tsk_object_ref(TSK_LIST_FIRST_DATA(TMEDIA_SESSION(session)->neg_codecs)))){
- if(!codec->plugin || !codec->plugin->encode){
- TSK_OBJECT_SAFE_FREE(codec);
- TSK_DEBUG_ERROR("Invalid codec");
- return -2;
- }
- // open the codec if not already done
- if(!TMEDIA_CODEC(codec)->opened){
- tsk_safeobj_lock(session);
- if((ret = tmedia_codec_open(codec))){
- tsk_safeobj_unlock(session);
- TSK_DEBUG_ERROR("Failed to open [%s] codec", codec->plugin->desc);
- TSK_OBJECT_SAFE_FREE(codec);
- return ret;
- }
- tsk_safeobj_unlock(session);
- }
- }
- else{
- TSK_DEBUG_ERROR("Failed to find a valid codec");
- return -4;
- }
-
-
-#define PRODUCER_SIZE_CHANGED (session->conv.producerWidth != session->producer->video.width) || (session->conv.producerHeight != session->producer->video.height) \
-|| (session->conv.xProducerSize != size)
- // Video codecs only accept YUV420P buffers ==> do conversion if needed or producer doesn't have the right size
- if((session->producer->video.chroma != tmedia_yuv420p) || PRODUCER_SIZE_CHANGED){
- // Create video converter if not already done or producer size has changed
- if(!session->conv.toYUV420 || PRODUCER_SIZE_CHANGED){
- TSK_OBJECT_SAFE_FREE(session->conv.toYUV420);
- session->conv.producerWidth = session->producer->video.width;
- session->conv.producerHeight = session->producer->video.height;
- session->conv.xProducerSize = size;
-
- if(!(session->conv.toYUV420 = tdav_converter_video_create(session->producer->video.width, session->producer->video.height, TMEDIA_CODEC_VIDEO(codec)->width, TMEDIA_CODEC_VIDEO(codec)->height,
- session->producer->video.chroma, tsk_true))){
- TSK_DEBUG_ERROR("Failed to create video converter");
- ret = -5;
- goto bail;
- }
- }
- // update one-shot parameters
- tdav_converter_video_init(session->conv.toYUV420, session->producer->video.rotation);
- // convert data to yuv420p
- yuv420p_size = tdav_converter_video_convert(session->conv.toYUV420, buffer, &session->encoder.conv_buffer, &session->encoder.conv_buffer_size);
- if(!yuv420p_size || !session->encoder.conv_buffer){
- TSK_DEBUG_ERROR("Failed to convert XXX buffer to YUV42P");
- ret = -6;
- goto bail;
- }
- }
-
- // Encode data
- if(session->encoder.conv_buffer && yuv420p_size){
- /* producer doesn't support yuv42p */
- out_size = codec->plugin->encode(codec, session->encoder.conv_buffer, yuv420p_size, &session->encoder.buffer, &session->encoder.buffer_size);
- }
- else{
- /* producer supports yuv42p */
- out_size = codec->plugin->encode(codec, buffer, size, &session->encoder.buffer, &session->encoder.buffer_size);
- }
-
- if(out_size){
- /* Never called, see tdav_session_video_raw_cb() */
- trtp_manager_send_rtp(session->rtp_manager, session->encoder.buffer, out_size, 6006, tsk_true, tsk_true);
- }
-bail:
- TSK_OBJECT_SAFE_FREE(codec);
- }
- else{
- TSK_DEBUG_ERROR("Invalid parameter");
- ret = -1;
- }
-
- return ret;
-}
-
-
-/* ============ Plugin interface ================= */
-
-int tmedia_session_video_set(tmedia_session_t* self, const tmedia_param_t* param)
-{
- int ret = 0;
- tdav_session_video_t* video;
-
- if(!self){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- video = (tdav_session_video_t*)self;
-
- if(param->plugin_type == tmedia_ppt_consumer){
- if(!video->consumer){
- TSK_DEBUG_ERROR("No consumer associated to this session");
- return -1;
- }
- ret = tmedia_consumer_set(video->consumer, param);
- }
- else if(param->plugin_type == tmedia_ppt_producer){
- if(!video->producer){
- TSK_DEBUG_ERROR("No producer associated to this session");
- return -1;
- }
- ret = tmedia_producer_set(video->producer, param);
- }
- else{
- if(param->value_type == tmedia_pvt_pchar){
- if(tsk_striequals(param->key, "remote-ip")){
- /* only if no ip associated to the "m=" line */
- if(param->value && !video->remote_ip){
- video->remote_ip = tsk_strdup(param->value);
- }
- }
- else if(tsk_striequals(param->key, "local-ip")){
- tsk_strupdate(&video->local_ip, param->value);
- }
- else if(tsk_striequals(param->key, "local-ipver")){
- video->useIPv6 = tsk_striequals(param->value, "ipv6");
- }
- }
- else if(param->value_type == tmedia_pvt_int32){
- if(tsk_striequals(param->key, "bandwidth-level")){
- tsk_list_item_t* item;
- self->bl = (tmedia_bandwidth_level_t) TSK_TO_UINT32((uint8_t*)param->value);
- self->codecs = tsk_object_ref(self->codecs);
- tsk_list_foreach(item, self->codecs){
- ((tmedia_codec_t*)item->data)->bl = self->bl;
- }
- tsk_object_unref(self->codecs);
- }
- }
- else if(param->value_type == tmedia_pvt_pobject){
- if(tsk_striequals(param->key, "natt-ctx")){
- TSK_OBJECT_SAFE_FREE(video->natt_ctx);
- video->natt_ctx = tsk_object_ref(param->value);
- }
- }
- }
-
- return ret;
-}
-
-int tdav_session_video_prepare(tmedia_session_t* self)
-{
- tdav_session_video_t* video;
- int ret = 0;
-
- video = (tdav_session_video_t*)self;
-
- /* set local port */
- if(!video->rtp_manager){
- if((video->rtp_manager = trtp_manager_create(video->rtcp_enabled, video->local_ip, video->useIPv6))){
-
- ret = trtp_manager_set_rtp_callback(video->rtp_manager, tdav_session_video_rtp_cb, video);
- ret = trtp_manager_prepare(video->rtp_manager);
- if(video->natt_ctx){
- ret = trtp_manager_set_natt_ctx(video->rtp_manager, video->natt_ctx);
- }
- }
- }
-
- /* Consumer will be prepared in tdav_session_video_start() */
- /* Producer will be prepared in tdav_session_video_start() */
-
- return ret;
-}
-
-int tdav_session_video_start(tmedia_session_t* self)
-{
- tdav_session_video_t* video;
-
- if(!self){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- video = (tdav_session_video_t*)self;
-
- if(TSK_LIST_IS_EMPTY(self->neg_codecs)){
- TSK_DEBUG_ERROR("No codec matched");
- return -2;
- }
-
- if(video->rtp_manager){
- int ret;
- const tmedia_codec_t* codec = (const tmedia_codec_t*)TSK_LIST_FIRST_DATA(self->neg_codecs);
- /* RTP/RTCP manager: use latest information. */
- ret = trtp_manager_set_rtp_remote(video->rtp_manager, video->remote_ip, video->remote_port);
- trtp_manager_set_payload_type(video->rtp_manager, codec->neg_format ? atoi(codec->neg_format) : atoi(codec->format));
- ret = trtp_manager_start(video->rtp_manager);
-
- /* Consumer */
- if(video->consumer){
- tmedia_consumer_prepare(video->consumer, codec);
- tmedia_consumer_start(video->consumer);
- }
- /* Producer */
- if(video->producer){
- tmedia_producer_prepare(video->producer, codec);
- tmedia_producer_start(video->producer);
- }
-
- /* for test */
- //trtp_manager_send_rtp(video->rtp_manager, "test", 4, tsk_true);
- return ret;
- }
- else{
- TSK_DEBUG_ERROR("Invalid RTP/RTCP manager or neg_codecs");
- return -3;
- }
-}
-
-int tdav_session_video_stop(tmedia_session_t* self)
-{
- tdav_session_video_t* video;
-
- if(!self){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- video = (tdav_session_video_t*)self;
-
- /* RTP/RTCP manager */
- if(video->rtp_manager){
- trtp_manager_stop(video->rtp_manager);
- }
-
- /* Consumer */
- if(video->consumer){
- tmedia_consumer_stop(video->consumer);
- }
- /* Producer */
- if(video->producer){
- tmedia_producer_stop(video->producer);
- }
-
- return 0;
-}
-
-int tdav_session_video_pause(tmedia_session_t* self)
-{
- tdav_session_video_t* video;
-
- video = (tdav_session_video_t*)self;
-
- if(!self){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- /* Consumer */
- if(video->consumer){
- tmedia_consumer_pause(video->consumer);
- }
- /* Producer */
- if(video->producer){
- tmedia_producer_pause(video->producer);
- }
-
- return 0;
-}
-
-const tsdp_header_M_t* tdav_session_video_get_lo(tmedia_session_t* self)
-{
- tdav_session_video_t* video;
- tsk_bool_t changed = tsk_false;
-
- if(!self || !self->plugin){
- TSK_DEBUG_ERROR("Invalid parameter");
- return tsk_null;
- }
-
- video = (tdav_session_video_t*)self;
-
- if(!video->rtp_manager || !video->rtp_manager->transport){
- TSK_DEBUG_ERROR("RTP/RTCP manager in invalid");
- return tsk_null;
- }
-
- if(self->ro_changed && self->M.lo){
- /* Codecs */
- tsdp_header_A_removeAll_by_field(self->M.lo->Attributes, "fmtp");
- tsdp_header_A_removeAll_by_field(self->M.lo->Attributes, "rtpmap");
- tsk_list_clear_items(self->M.lo->FMTs);
-
- /* QoS */
- tsdp_header_A_removeAll_by_field(self->M.lo->Attributes, "curr");
- tsdp_header_A_removeAll_by_field(self->M.lo->Attributes, "des");
- tsdp_header_A_removeAll_by_field(self->M.lo->Attributes, "conf");
- }
-
- changed = (self->ro_changed || !self->M.lo);
-
- if(!self->M.lo){
- if((self->M.lo = tsdp_header_M_create(self->plugin->media, video->rtp_manager->rtp.public_port, "RTP/AVP"))){
- /* If NATT is active, do not rely on the global IP address Connection line */
- if(video->natt_ctx){
- tsdp_header_M_add_headers(self->M.lo,
- TSDP_HEADER_C_VA_ARGS("IN", video->useIPv6 ? "IP6" : "IP4", video->rtp_manager->rtp.public_ip),
- tsk_null);
- }
- }
- else{
- TSK_DEBUG_ERROR("Failed to create lo");
- return tsk_null;
- }
- }
-
- /* from codecs to sdp */
- if(changed){
- tmedia_codecs_L_t* neg_codecs = tsk_null;
-
- if(self->M.ro){
- TSK_OBJECT_SAFE_FREE(self->neg_codecs);
- /* update negociated codecs */
- if((neg_codecs = tmedia_session_match_codec(self, self->M.ro))){
- self->neg_codecs = neg_codecs;
- // set video codec callback
- if(!TSK_LIST_IS_EMPTY(self->neg_codecs)){
- tmedia_codec_video_set_callback((tmedia_codec_video_t*)TSK_LIST_FIRST_DATA(self->neg_codecs), tdav_session_video_raw_cb, self);
- }
- }
- /* from codecs to sdp */
- if(self->neg_codecs){
- tmedia_codec_to_sdp(self->neg_codecs, self->M.lo);
- }
- else{
- self->M.lo->port = 0; /* Keep the RTP transport and reuse it when we receive a reINVITE or UPDATE request */
- goto DONE;
- }
- }
- else{
- /* from codecs to sdp */
- tmedia_codec_to_sdp(self->codecs, self->M.lo);
- }
-
- /* Hold/Resume */
- if(self->M.ro){
- if(tsdp_header_M_is_held(self->M.ro, tsk_false)){
- tsdp_header_M_hold(self->M.lo, tsk_false);
- }
- else{
- tsdp_header_M_resume(self->M.lo, tsk_false);
- }
- }
-
- /* QoS */
- if(self->qos){
- tmedia_qos_tline_t* ro_tline;
- if(self->M.ro && (ro_tline = tmedia_qos_tline_from_sdp(self->M.ro))){
- tmedia_qos_tline_set_ro(self->qos, ro_tline);
- TSK_OBJECT_SAFE_FREE(ro_tline);
- }
- tmedia_qos_tline_to_sdp(self->qos, self->M.lo);
- }
-DONE:;
- }
-
- return self->M.lo;
-}
-
-int tdav_session_video_set_ro(tmedia_session_t* self, const tsdp_header_M_t* m)
-{
- tdav_session_video_t* video;
- tmedia_codecs_L_t* neg_codecs;
-
- if(!self || !m){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- video = (tdav_session_video_t*)self;
-
- /* update remote offer */
- TSK_OBJECT_SAFE_FREE(self->M.ro);
- self->M.ro = tsk_object_ref((void*)m);
-
- if(self->M.lo){
- if((neg_codecs = tmedia_session_match_codec(self, m))){
- /* update negociated codecs */
- TSK_OBJECT_SAFE_FREE(self->neg_codecs);
- self->neg_codecs = neg_codecs;
- // set codec callback
- if(!TSK_LIST_IS_EMPTY(self->neg_codecs)){
- tmedia_codec_video_set_callback((tmedia_codec_video_t*)TSK_LIST_FIRST_DATA(self->neg_codecs), tdav_session_video_raw_cb, self);
- }
- }
- else{
- return -1;
- }
-
- /* QoS */
- if(self->qos){
- tmedia_qos_tline_t* ro_tline;
- if(self->M.ro && (ro_tline = tmedia_qos_tline_from_sdp(self->M.ro))){
- tmedia_qos_tline_set_ro(self->qos, ro_tline);
- TSK_OBJECT_SAFE_FREE(ro_tline);
- }
- }
- }
-
- /* get connection associated to this media line
- * If the connnection is global, then the manager will call tmedia_session_video_set() */
- if(m->C && m->C->addr){
- tsk_strupdate(&video->remote_ip, m->C->addr);
- video->useIPv6 = tsk_striequals(m->C->addrtype, "IP6");
- }
- /* set remote port */
- video->remote_port = m->port;
-
-
- return 0;
-}
-
-
-
-
-
-//=================================================================================================
-// Session Video Plugin object definition
-//
-/* constructor */
-static tsk_object_t* tdav_session_video_ctor(tsk_object_t * self, va_list * app)
-{
- tdav_session_video_t *session = self;
- if(session){
- /* init base: called by tmedia_session_create() */
- /* init self */
- tsk_safeobj_init(session);
- if(!(session->consumer = tmedia_consumer_create(tdav_session_video_plugin_def_t->type, TMEDIA_SESSION(session)->id))){
- TSK_DEBUG_ERROR("Failed to create Video consumer");
- }
- if((session->producer = tmedia_producer_create(tdav_session_video_plugin_def_t->type, TMEDIA_SESSION(session)->id))){
- tmedia_producer_set_enc_callback(session->producer, tdav_session_video_producer_enc_cb, self);
- tmedia_producer_set_raw_callback(session->producer, tdav_session_video_raw_cb, self);
- }
- else{
- TSK_DEBUG_ERROR("Failed to create Video producer");
- }
- }
- return self;
-}
-/* destructor */
-static tsk_object_t* tdav_session_video_dtor(tsk_object_t * self)
-{
- tdav_session_video_t *session = self;
- if(session){
-
- // Do it in this order (deinit self first)
-
- /* deinit self (rtp manager should be destroyed after the producer) */
- TSK_OBJECT_SAFE_FREE(session->consumer);
- TSK_OBJECT_SAFE_FREE(session->producer);
- TSK_OBJECT_SAFE_FREE(session->conv.toYUV420);
- TSK_OBJECT_SAFE_FREE(session->conv.fromYUV420);
- TSK_OBJECT_SAFE_FREE(session->rtp_manager);
- TSK_FREE(session->remote_ip);
- TSK_FREE(session->local_ip);
-
- TSK_FREE(session->encoder.buffer);
- TSK_FREE(session->encoder.conv_buffer);
- TSK_FREE(session->decoder.buffer);
- TSK_FREE(session->decoder.conv_buffer);
-
- /* NAT Traversal context */
- TSK_OBJECT_SAFE_FREE(session->natt_ctx);
-
- tsk_safeobj_deinit(session);
-
- /* deinit base */
- tmedia_session_deinit(self);
- }
-
- return self;
-}
-/* object definition */
-static const tsk_object_def_t tdav_session_video_def_s =
-{
- sizeof(tdav_session_video_t),
- tdav_session_video_ctor,
- tdav_session_video_dtor,
- tmedia_session_cmp,
-};
-/* plugin definition*/
-static const tmedia_session_plugin_def_t tdav_session_video_plugin_def_s =
-{
- &tdav_session_video_def_s,
-
- tmedia_video,
- "video",
-
- tmedia_session_video_set,
- tdav_session_video_prepare,
- tdav_session_video_start,
- tdav_session_video_pause,
- tdav_session_video_stop,
-
- /* Audio part */
- { tsk_null },
-
- tdav_session_video_get_lo,
- tdav_session_video_set_ro
-};
-const tmedia_session_plugin_def_t *tdav_session_video_plugin_def_t = &tdav_session_video_plugin_def_s;
OpenPOWER on IntegriCloud