/* * Copyright (C) 2011 Doubango Telecom . * * Contact: Mamadou Diop * * 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. * */ #ifndef TINYDAV_CODEC_H264_COMMON_H #define TINYDAV_CODEC_H264_COMMON_H #include "tinydav_config.h" #include "tinydav/codecs/h264/tdav_codec_h264_rtp.h" #include "tinymedia/tmedia_codec.h" #include "tinymedia/tmedia_defaults.h" #include "tsk_memory.h" #include "tsk_string.h" #include "tsk_params.h" #include "tsk_debug.h" #include TDAV_BEGIN_DECLS #if !defined(H264_MAX_BR) # define H264_MAX_BR 452 #endif #if !defined(H264_MAX_MBPS) # define H264_MAX_MBPS 11880 #endif #if !defined(H264_PACKETIZATION_MODE) # define H264_PACKETIZATION_MODE Non_Interleaved_Mode #endif // Because of FD, declare it here typedef enum packetization_mode_e{ Single_NAL_Unit_Mode = 0, /* Single NAL mode (Only nals from 1-23 are allowed) */ Non_Interleaved_Mode = 1, /* Non-interleaved Mode: 1-23, 24 (STAP-A), 28 (FU-A) are allowed */ Interleaved_Mode = 2 /* 25 (STAP-B), 26 (MTAP16), 27 (MTAP24), 28 (FU-A), and 29 (FU-B) are allowed.*/ } packetization_mode_t; typedef struct tdav_codec_h264_common_s { TMEDIA_DECLARE_CODEC_VIDEO; profile_idc_t profile; level_idc_t level; packetization_mode_t pack_mode; struct{ uint8_t* ptr; tsk_size_t size; } rtp; } tdav_codec_h264_common_t; #define TDAV_CODEC_H264_COMMON(self) ((tdav_codec_h264_common_t*)(self)) #define TDAV_DECLARE_CODEC_H264_COMMON tdav_codec_h264_common_t __video__ typedef struct tdav_codec_h264_common_level_size_xs { level_idc_t level; unsigned width; unsigned height; } tdav_codec_h264_common_level_size_xt; static const tdav_codec_h264_common_level_size_xt tdav_codec_h264_common_level_sizes [] = { {level_idc_1_0, 128, 96}, {level_idc_1_b, 128, 96}, {level_idc_1_1, 176, 144}, {level_idc_1_2, 320, 240}, {level_idc_1_3, 352, 288}, {level_idc_2_0, 352, 288}, {level_idc_2_1, 352, 480}, {level_idc_2_2, 352, 480}, {level_idc_3_0, 720, 480}, {level_idc_3_1, 1280, 720}, {level_idc_3_2, 1280, 720}, {level_idc_4_0, 2048, 1024}, {level_idc_4_1, 2048, 1024}, {level_idc_4_2, 2048, 1080}, {level_idc_5_0, 2560, 1920}, {level_idc_5_1, 3840, 2160}, {level_idc_5_2, 4096, 2048} }; static int tdav_codec_h264_common_size_from_level(level_idc_t level, unsigned *width, unsigned *height) { tsk_size_t i; for(i = 0; i < sizeof(tdav_codec_h264_common_level_sizes)/sizeof(tdav_codec_h264_common_level_sizes[0]); ++i){ if(tdav_codec_h264_common_level_sizes[i].level == level){ *width = tdav_codec_h264_common_level_sizes[i].width; *height = tdav_codec_h264_common_level_sizes[i].height; return 0; } } return -1; } static int tdav_codec_h264_common_level_from_size(unsigned width, unsigned height, level_idc_t *level) { tsk_size_t i; for(i = 0; i < sizeof(tdav_codec_h264_common_level_sizes)/sizeof(tdav_codec_h264_common_level_sizes[0]); ++i){ if(tdav_codec_h264_common_level_sizes[i].width >= width && tdav_codec_h264_common_level_sizes[i].height >= height){ *level = tdav_codec_h264_common_level_sizes[i].level; return 0; } } return -1; } static int tdav_codec_h264_common_init(tdav_codec_h264_common_t * h264) { if(h264){ // because at this step 'tmedia_codec_init()' is not called yet and we need default size to compute the H.264 level if(TMEDIA_CODEC_VIDEO(h264)->out.width == 0 || TMEDIA_CODEC_VIDEO(h264)->in.width == 0){ unsigned width, height; tmedia_pref_video_size_t pref_size = tmedia_defaults_get_pref_video_size(); if(tmedia_video_get_size(pref_size, &width, &height) == 0){ TMEDIA_CODEC_VIDEO(h264)->out.width = TMEDIA_CODEC_VIDEO(h264)->in.width = width; TMEDIA_CODEC_VIDEO(h264)->out.height = TMEDIA_CODEC_VIDEO(h264)->in.height = height; } } } return 0; } static int tdav_codec_h264_common_deinit(tdav_codec_h264_common_t * h264) { TSK_DEBUG_INFO("tdav_codec_h264_common_deinit"); if(h264){ tmedia_codec_video_deinit(TMEDIA_CODEC_VIDEO(h264)); TSK_FREE(h264->rtp.ptr); h264->rtp.size = 0; } return 0; } static int tdav_codec_h264_get_profile_and_level(const char* fmtp, profile_idc_t *profile, level_idc_t *level) { tsk_size_t size = tsk_strlen(fmtp); int start, end; int ret = -1; *profile = profile_idc_none; *level = level_idc_none; if((start = tsk_strindexOf(fmtp, size, "profile-level-id")) !=-1){ tsk_param_t* param; if((end = tsk_strindexOf((fmtp+start), (size-start), ";")) == -1){ end = size; } if((param = tsk_params_parse_param((fmtp+start), (end-start)))){ profile_idc_t p_idc; level_idc_t l_idc; if(param->value){ tsk_strtrim_both(¶m->value); } tdav_codec_h264_parse_profile(param->value, &p_idc, tsk_null, &l_idc); switch(p_idc){ case profile_idc_baseline: case profile_idc_main: *profile = p_idc; *level = l_idc; ret = 0; break; case profile_idc_extended: case profile_idc_high: default: /* Not supported */ break; } TSK_OBJECT_SAFE_FREE(param); } } return ret; } TDAV_END_DECLS #endif /* TINYDAV_CODEC_H264_COMMON_H */