diff options
Diffstat (limited to 'branches/1.0/tinyDAV/src/codecs/h264/tdav_codec_h264_rtp.c')
-rw-r--r-- | branches/1.0/tinyDAV/src/codecs/h264/tdav_codec_h264_rtp.c | 356 |
1 files changed, 0 insertions, 356 deletions
diff --git a/branches/1.0/tinyDAV/src/codecs/h264/tdav_codec_h264_rtp.c b/branches/1.0/tinyDAV/src/codecs/h264/tdav_codec_h264_rtp.c deleted file mode 100644 index a750ccf..0000000 --- a/branches/1.0/tinyDAV/src/codecs/h264/tdav_codec_h264_rtp.c +++ /dev/null @@ -1,356 +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_h264_rtp.c - * @brief H.264 payloader/depayloder as per RFC 3984 - * - * @author Mamadou Diop <diopmamadou(at)doubango.org> - * - * @date Created: Sat Nov 8 16:54:58 2009 mdiop - */ -#include "tinydav/codecs/h264/tdav_codec_h264_rtp.h" - -#include "tinydav/codecs/h264/tdav_codec_h264.h" - -#if HAVE_FFMPEG && (!defined(HAVE_H264) || HAVE_H264) - -#include "tinymedia/tmedia_codec.h" - -#include "tsk_string.h" -#include "tsk_debug.h" - -#include "tsk_memory.h" -#include <string.h> /* strlen() */ -#include <stdlib.h> /* strtol() */ - -/* -* ITU H.264 - http://www.itu.int/rec/T-REC-H.264-200903-S/en -*/ - -uint8_t H264_START_CODE_PREFIX[4] = { 0x00, 0x00, 0x00, 0x01 }; - -#define H264_NAL_UNIT_TYPE_HEADER_SIZE 1 -#define H264_F_UNIT_TYPE_HEADER_SIZE 1 -#define H264_FUA_HEADER_SIZE 2 -#define H264_FUB_HEADER_SIZE 4 -#define H264_NAL_AGG_MAX_SIZE 65535 - -int tdav_codec_h264_get_fua_pay(const uint8_t* in_data, tsk_size_t in_size, const void** out_data, tsk_size_t *out_size, tsk_bool_t* append_scp); -int tdav_codec_h264_get_nalunit_pay(const uint8_t* in_data, tsk_size_t in_size, const void** out_data, tsk_size_t *out_size); - -// profile_level_id MUST be a "null-terminated" string -int tdav_codec_h264_parse_profile(const char* profile_level_id, profile_idc_t *p_idc, profile_iop_t *p_iop, level_idc_t *l_idc) -{ - uint32_t value; - - if(tsk_strlen(profile_level_id) != 6){ - TSK_DEBUG_ERROR("I say [%s] is an invalid profile-level-id", profile_level_id); - return -1; - } - - value = strtol(profile_level_id, tsk_null, 16); - - /* profile-idc */ - if(p_idc){ - switch((value >> 16)){ - case profile_idc_baseline: - *p_idc = profile_idc_baseline; - break; - case profile_idc_extended: - *p_idc = profile_idc_extended; - break; - case profile_idc_main: - *p_idc = profile_idc_main; - break; - case profile_idc_high: - *p_idc = profile_idc_high; - break; - default: - *p_idc = profile_idc_none; - break; - } - } - - /* profile-iop */ - if(p_iop){ - p_iop->constraint_set0_flag = ((value >> 8) & 0x80)>>7; - p_iop->constraint_set1_flag = ((value >> 8) & 0x40)>>6; - p_iop->constraint_set2_flag = ((value >> 8) & 0x20)>>5; - p_iop->reserved_zero_5bits = ((value >> 8) & 0x1F); - } - - /* level-idc */ - if(l_idc){ - switch((value & 0xFF)){ - case level_idc_1_0: - *l_idc = level_idc_1_0; - break; - case level_idc_1_b: - *l_idc = level_idc_1_b; - break; - case level_idc_1_1: - *l_idc = level_idc_1_1; - break; - case level_idc_1_2: - *l_idc = level_idc_1_2; - break; - case level_idc_1_3: - *l_idc = level_idc_1_3; - break; - case level_idc_2_0: - *l_idc = level_idc_2_0; - break; - case level_idc_2_1: - *l_idc = level_idc_2_1; - break; - case level_idc_2_2: - *l_idc = level_idc_2_2; - break; - case level_idc_3_0: - *l_idc = level_idc_3_0; - break; - default: - *l_idc = level_idc_none; - break; - } - } - - return 0; -} - -int tdav_codec_h264_get_pay(const void* in_data, tsk_size_t in_size, const void** out_data, tsk_size_t *out_size, tsk_bool_t* append_scp) -{ - const uint8_t* pdata = in_data; - if(!in_data || !in_size || !out_data || !out_size){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - *out_data = tsk_null; - *out_size = 0; - *append_scp = tsk_true; - - /* 5.3. NAL Unit Octet Usage - +---------------+ - |0|1|2|3|4|5|6|7| - +-+-+-+-+-+-+-+-+ - |F|NRI| Type | - +---------------+ - */ - switch((pdata[0] & 0x1F)){ - case undefined_0: - case undefined_30: - case undefined_31: - case stap_a: - case stap_b: - case mtap16: - case mtap24: - break; - case fu_a: - return tdav_codec_h264_get_fua_pay(pdata, in_size, out_data, out_size, append_scp); - case fu_b: - return -1; - default: /* NAL unit (1-23) */ - return tdav_codec_h264_get_nalunit_pay(pdata, in_size, out_data, out_size); - } - - TSK_DEBUG_WARN("%d not supported as valid NAL Unit type", (*pdata & 0x1F)); - return -1; -} - - -int tdav_codec_h264_get_fua_pay(const uint8_t* in_data, tsk_size_t in_size, const void** out_data, tsk_size_t *out_size, tsk_bool_t* append_scp) -{ - if(in_size <=2){ - TSK_DEBUG_ERROR("Too short"); - return -1; - } - /* RFC 3984 - 5.8. Fragmentation Units (FUs) - - 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 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | FU indicator | FU header | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | - | | - | FU payload | - | | - | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | :...OPTIONAL RTP padding | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - The FU indicator octet has the following format: - - +---------------+ - |0|1|2|3|4|5|6|7| - +-+-+-+-+-+-+-+-+ - |F|NRI| Type | - +---------------+ - - The FU header has the following format: - - +---------------+ - |0|1|2|3|4|5|6|7| - +-+-+-+-+-+-+-+-+ - |S|E|R| Type | - +---------------+ - */ - - if((in_data[1] & 0x80) == 0x80 /*S*/){ - /* discard "FU indicator" - S: 1 bit - When set to one, the Start bit indicates the start of a fragmented - NAL unit. When the following FU payload is not the start of a - fragmented NAL unit payload, the Start bit is set to zero. - */ - if(in_size> H264_NAL_UNIT_TYPE_HEADER_SIZE){ - uint8_t hdr; - *out_data = (in_data + H264_NAL_UNIT_TYPE_HEADER_SIZE); - *out_size = (in_size - H264_NAL_UNIT_TYPE_HEADER_SIZE); - - // F, NRI and Type - hdr = (in_data[0] & 0xe0) /* F,NRI from "FU indicator"*/ | (in_data[1] & 0x1f) /* type from "FU header" */; - *((uint8_t*)*out_data) = hdr; - // Need to append Start Code Prefix - *append_scp = tsk_true; - } - else{ - TSK_DEBUG_ERROR("Too short"); - return -1; - } - } - else{ - /* "FU indicator" and "FU header" */ - if(in_size> H264_FUA_HEADER_SIZE){ - *out_data = (in_data + H264_FUA_HEADER_SIZE); - *out_size = (in_size - H264_FUA_HEADER_SIZE); - *append_scp = tsk_false; - } - else{ - TSK_DEBUG_ERROR("Too short"); - return -1; - } - } - - return 0; -} - -int tdav_codec_h264_get_nalunit_pay(const uint8_t* in_data, tsk_size_t in_size, const void** out_data, tsk_size_t *out_size) -{ - -/* 5.6. Single NAL Unit Packet - - 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 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - |F|NRI| type | | - +-+-+-+-+-+-+-+-+ | - | | - | Bytes 2..n of a Single NAL unit | - | | - | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | :...OPTIONAL RTP padding | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -*/ - - *out_data = in_data; - *out_size = in_size; - - return 0; -} - -#if TDAV_UNDER_WINDOWS -# include "tsk_thread.h" -#endif -void tdav_codec_h264_rtp_callback(struct tdav_codec_h264_s *self, const void *data, tsk_size_t size, tsk_bool_t marker) -{ - uint8_t* pdata = (uint8_t*)data; - - if(size>4 && pdata[0] == H264_START_CODE_PREFIX[0] && pdata[1] == H264_START_CODE_PREFIX[1]){ - if(pdata[2] == H264_START_CODE_PREFIX[3]){ - pdata += 3, size -= 3; - } - else if(pdata[2] == H264_START_CODE_PREFIX[2] && pdata[3] == H264_START_CODE_PREFIX[3]){ - pdata += 4, size -= 4; - } - } - - //TSK_DEBUG_INFO("==> SCP %2x %2x %2x %2x", pdata[0], pdata[1], pdata[2], pdata[3]); - - if(size < H264_RTP_PAYLOAD_SIZE){ - /* Can be packet in a Single Nal Unit */ - // Send data over the network - if(TMEDIA_CODEC_VIDEO(self)->callback){ - TMEDIA_CODEC_VIDEO(self)->callback(TMEDIA_CODEC_VIDEO(self)->callback_data, pdata, size, (3003* (30/TMEDIA_CODEC_VIDEO(self)->fps)), marker); - } - } - else if(size > H264_NAL_UNIT_TYPE_HEADER_SIZE){ -#if TDAV_UNDER_WINDOWS - tsk_bool_t burst = ((size/H264_RTP_PAYLOAD_SIZE) > 5); - int count = 0; -#endif - /* Should be Fragmented as FUA */ - uint8_t fua_hdr[H264_FUA_HEADER_SIZE]; /* "FU indicator" and "FU header" - 2bytes */ - fua_hdr[0] = pdata[0] & 0x60/* F=0 */, fua_hdr[0] |= fu_a; - fua_hdr[1] = 0x80/* S=1,E=0,R=0 */, fua_hdr[1] |= pdata[0] & 0x1f; /* type */ - // discard header - pdata += H264_NAL_UNIT_TYPE_HEADER_SIZE; - size -= H264_NAL_UNIT_TYPE_HEADER_SIZE; - - while(size){ - tsk_size_t packet_size = TSK_MIN(H264_RTP_PAYLOAD_SIZE, size); - - if(self->rtp.size < (packet_size + H264_FUA_HEADER_SIZE)){ - if(!(self->rtp.ptr = tsk_realloc(self->rtp.ptr, (packet_size + H264_FUA_HEADER_SIZE)))){ - TSK_DEBUG_ERROR("Failed to allocate new buffer"); - return; - } - self->rtp.size = (packet_size + H264_FUA_HEADER_SIZE); - } - // set E bit - if((size - packet_size) == 0){ - // Last packet - fua_hdr[1] |= 0x40; - } - // copy FUA header - memcpy(self->rtp.ptr, fua_hdr, H264_FUA_HEADER_SIZE); - // reset "S" bit - fua_hdr[1] &= 0x7F; - // copy data - memcpy((self->rtp.ptr + H264_FUA_HEADER_SIZE), pdata, packet_size); - pdata += packet_size; - size -= packet_size; - - // send data - if(TMEDIA_CODEC_VIDEO(self)->callback){ - TMEDIA_CODEC_VIDEO(self)->callback(TMEDIA_CODEC_VIDEO(self)->callback_data, self->rtp.ptr, (packet_size + H264_FUA_HEADER_SIZE), (3003* (30/TMEDIA_CODEC_VIDEO(self)->fps)), (size == 0)); -#if TDAV_UNDER_WINDOWS// FIXME: WinSock problem: Why do we get packet lost (burst case only)? - if(burst && (++count % 2 == 0)){ - tsk_thread_sleep(1); // 1 millisecond - } -#endif - } - } - } -} - -#endif /* HAVE_FFMPEG */
\ No newline at end of file |