207 lines
5.7 KiB
C
207 lines
5.7 KiB
C
/*
|
|
* Copyright (C) 2011 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.
|
|
*
|
|
*/
|
|
#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 <string.h>
|
|
|
|
|
|
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 */
|