summaryrefslogtreecommitdiffstats
path: root/tinyDAV/src/codecs
diff options
context:
space:
mode:
Diffstat (limited to 'tinyDAV/src/codecs')
-rwxr-xr-xtinyDAV/src/codecs/amr/tdav_codec_amr.c1202
-rwxr-xr-xtinyDAV/src/codecs/bfcp/tdav_codec_bfcp.c93
-rwxr-xr-xtinyDAV/src/codecs/bv/tdav_codec_bv16.c299
-rwxr-xr-xtinyDAV/src/codecs/dtmf/tdav_codec_dtmf.c117
-rwxr-xr-xtinyDAV/src/codecs/fec/tdav_codec_red.c363
-rwxr-xr-xtinyDAV/src/codecs/fec/tdav_codec_ulpfec.c588
-rwxr-xr-xtinyDAV/src/codecs/g711/g711.c269
-rwxr-xr-xtinyDAV/src/codecs/g711/tdav_codec_g711.c428
-rwxr-xr-xtinyDAV/src/codecs/g722/g722_decode.c203
-rwxr-xr-xtinyDAV/src/codecs/g722/g722_encode.c171
-rwxr-xr-xtinyDAV/src/codecs/g722/tdav_codec_g722.c271
-rwxr-xr-xtinyDAV/src/codecs/g729/tdav_codec_g729.c568
-rwxr-xr-xtinyDAV/src/codecs/gsm/tdav_codec_gsm.c261
-rwxr-xr-xtinyDAV/src/codecs/h261/tdav_codec_h261.c720
-rwxr-xr-xtinyDAV/src/codecs/h263/tdav_codec_h263.c2083
-rwxr-xr-xtinyDAV/src/codecs/h264/tdav_codec_h264.c1328
-rwxr-xr-xtinyDAV/src/codecs/h264/tdav_codec_h264_cisco.cxx1387
-rwxr-xr-xtinyDAV/src/codecs/h264/tdav_codec_h264_cuda.cxx1767
-rwxr-xr-xtinyDAV/src/codecs/h264/tdav_codec_h264_intel.cxx3383
-rwxr-xr-xtinyDAV/src/codecs/h264/tdav_codec_h264_rtp.c556
-rwxr-xr-xtinyDAV/src/codecs/ilbc/tdav_codec_ilbc.c354
-rwxr-xr-xtinyDAV/src/codecs/mp4ves/tdav_codec_mp4ves.c1295
-rwxr-xr-xtinyDAV/src/codecs/msrp/tdav_codec_msrp.c93
-rwxr-xr-xtinyDAV/src/codecs/opus/tdav_codec_opus.c501
-rwxr-xr-xtinyDAV/src/codecs/speex/tdav_codec_speex.c282
-rwxr-xr-xtinyDAV/src/codecs/t140/tdav_codec_t140.c198
-rwxr-xr-xtinyDAV/src/codecs/theora/tdav_codec_theora.c1394
-rwxr-xr-xtinyDAV/src/codecs/vpx/tdav_codec_vp8.c1643
28 files changed, 10840 insertions, 10977 deletions
diff --git a/tinyDAV/src/codecs/amr/tdav_codec_amr.c b/tinyDAV/src/codecs/amr/tdav_codec_amr.c
index 9304f85..727772c 100755
--- a/tinyDAV/src/codecs/amr/tdav_codec_amr.c
+++ b/tinyDAV/src/codecs/amr/tdav_codec_amr.c
@@ -2,19 +2,19 @@
* Copyright (C) 2010-2011 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.
*
@@ -62,7 +62,7 @@ static tsk_size_t tdav_codec_amr_be_encode(tdav_codec_amr_t* amr, const void* in
static tsk_size_t tdav_codec_amr_oa_encode(tdav_codec_amr_t* amr, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size);
static uint8_t tdav_codec_amr_bitbuffer_read(const void* bits, tsk_size_t size, tsk_size_t start, tsk_size_t count);
-/* ============ AMR-NB Plugin interface =================
+/* ============ AMR-NB Plugin interface =================
The AMR codec was originally developed and standardized by the
European Telecommunications Standards Institute (ETSI) for GSM
cellular systems. It is now chosen by the Third Generation
@@ -83,107 +83,107 @@ static uint8_t tdav_codec_amr_bitbuffer_read(const void* bits, tsk_size_t size,
int tdav_codec_amrnb_open(tmedia_codec_t* self)
{
- tdav_codec_amr_t* amrnb = (tdav_codec_amr_t*)self;
-
- if(!TDAV_CODEC_AMR(amrnb)->encoder){
- if(!(TDAV_CODEC_AMR(amrnb)->encoder = Encoder_Interface_init(0))){
- TSK_DEBUG_ERROR("Failed to initialize AMR-NB encoder");
- return -2;
- }
- }
-
- if(!TDAV_CODEC_AMR(amrnb)->decoder){
- if(!(TDAV_CODEC_AMR(amrnb)->decoder = Decoder_Interface_init())){
- TSK_DEBUG_ERROR("Failed to initialize AMR-NB encoder");
- return -2;
- }
- }
-
- return 0;
+ tdav_codec_amr_t* amrnb = (tdav_codec_amr_t*)self;
+
+ if(!TDAV_CODEC_AMR(amrnb)->encoder) {
+ if(!(TDAV_CODEC_AMR(amrnb)->encoder = Encoder_Interface_init(0))) {
+ TSK_DEBUG_ERROR("Failed to initialize AMR-NB encoder");
+ return -2;
+ }
+ }
+
+ if(!TDAV_CODEC_AMR(amrnb)->decoder) {
+ if(!(TDAV_CODEC_AMR(amrnb)->decoder = Decoder_Interface_init())) {
+ TSK_DEBUG_ERROR("Failed to initialize AMR-NB encoder");
+ return -2;
+ }
+ }
+
+ return 0;
}
int tdav_codec_amrnb_close(tmedia_codec_t* self)
{
- tdav_codec_amr_t* amrnb = (tdav_codec_amr_t*)self;
+ tdav_codec_amr_t* amrnb = (tdav_codec_amr_t*)self;
- if(TDAV_CODEC_AMR(amrnb)->encoder){
- Encoder_Interface_exit(TDAV_CODEC_AMR(amrnb)->encoder);
- TDAV_CODEC_AMR(amrnb)->encoder = tsk_null;
- }
+ if(TDAV_CODEC_AMR(amrnb)->encoder) {
+ Encoder_Interface_exit(TDAV_CODEC_AMR(amrnb)->encoder);
+ TDAV_CODEC_AMR(amrnb)->encoder = tsk_null;
+ }
- if(TDAV_CODEC_AMR(amrnb)->decoder){
- Decoder_Interface_exit(TDAV_CODEC_AMR(amrnb)->decoder);
- TDAV_CODEC_AMR(amrnb)->decoder = tsk_null;
- }
+ if(TDAV_CODEC_AMR(amrnb)->decoder) {
+ Decoder_Interface_exit(TDAV_CODEC_AMR(amrnb)->decoder);
+ TDAV_CODEC_AMR(amrnb)->decoder = tsk_null;
+ }
- return 0;
+ return 0;
}
tsk_size_t tdav_codec_amrnb_encode(tmedia_codec_t* self, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size)
-{
- tdav_codec_amr_t* amr = (tdav_codec_amr_t*)self;
-
- switch(amr->mode){
- case tdav_codec_amr_mode_be:
- return tdav_codec_amr_be_encode(amr, in_data, in_size, out_data, out_max_size);
- default:
- return tdav_codec_amr_oa_encode(amr, in_data, in_size, out_data, out_max_size);
- }
-
- return 0;
+{
+ tdav_codec_amr_t* amr = (tdav_codec_amr_t*)self;
+
+ switch(amr->mode) {
+ case tdav_codec_amr_mode_be:
+ return tdav_codec_amr_be_encode(amr, in_data, in_size, out_data, out_max_size);
+ default:
+ return tdav_codec_amr_oa_encode(amr, in_data, in_size, out_data, out_max_size);
+ }
+
+ return 0;
}
tsk_size_t tdav_codec_amrnb_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)
{
- tdav_codec_amr_t* amr = (tdav_codec_amr_t*)self;
-
- switch(amr->mode){
- case tdav_codec_amr_mode_be:
- return tdav_codec_amr_be_decode(amr, in_data, in_size, out_data, out_max_size, proto_hdr);
- default:
- return tdav_codec_amr_oa_decode(amr, in_data, in_size, out_data, out_max_size, proto_hdr);
- }
+ tdav_codec_amr_t* amr = (tdav_codec_amr_t*)self;
+
+ switch(amr->mode) {
+ case tdav_codec_amr_mode_be:
+ return tdav_codec_amr_be_decode(amr, in_data, in_size, out_data, out_max_size, proto_hdr);
+ default:
+ return tdav_codec_amr_oa_decode(amr, in_data, in_size, out_data, out_max_size, proto_hdr);
+ }
}
char* tdav_codec_amrnb_sdp_att_get(const tmedia_codec_t* codec, const char* att_name)
{
- const tdav_codec_amr_t* amr = (const tdav_codec_amr_t*)codec;
-
- /* We support all modes, all ... */
- if(amr){
- switch(amr->mode){
- case tdav_codec_amr_mode_be:
- return tsk_strdup("octet-align=0");
- default:
- return tsk_strdup("octet-align=1");
- }
- }
- return tsk_null;
+ const tdav_codec_amr_t* amr = (const tdav_codec_amr_t*)codec;
+
+ /* We support all modes, all ... */
+ if(amr) {
+ switch(amr->mode) {
+ case tdav_codec_amr_mode_be:
+ return tsk_strdup("octet-align=0");
+ default:
+ return tsk_strdup("octet-align=1");
+ }
+ }
+ return tsk_null;
}
tsk_bool_t tdav_codec_amrnb_sdp_att_match(const tmedia_codec_t* codec, const char* att_name, const char* att_value)
-{
- tdav_codec_amr_t* amr;
- if(!(amr = (tdav_codec_amr_t*)codec) || !att_name){
- TSK_DEBUG_ERROR("Invalid parameter");
- return tsk_false;
- }
-
- if(amr && tsk_striequals(att_name, "fmtp")){
- /* Match mode */
- if(tdav_codec_amr_get_mode(att_value) != amr->mode){
- TSK_DEBUG_INFO("Failed to match [%s]", att_value);
- return tsk_false;
- }
- /* check parameters validity */
- if(tdav_codec_amr_parse_fmtp(amr, att_value)){
- TSK_DEBUG_INFO("Failed to match [%s]", att_value);
- return tsk_false;
- }
-
- return tsk_true;
- }
- return tsk_false;
+{
+ tdav_codec_amr_t* amr;
+ if(!(amr = (tdav_codec_amr_t*)codec) || !att_name) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return tsk_false;
+ }
+
+ if(amr && tsk_striequals(att_name, "fmtp")) {
+ /* Match mode */
+ if(tdav_codec_amr_get_mode(att_value) != amr->mode) {
+ TSK_DEBUG_INFO("Failed to match [%s]", att_value);
+ return tsk_false;
+ }
+ /* check parameters validity */
+ if(tdav_codec_amr_parse_fmtp(amr, att_value)) {
+ TSK_DEBUG_INFO("Failed to match [%s]", att_value);
+ return tsk_false;
+ }
+
+ return tsk_true;
+ }
+ return tsk_false;
}
@@ -194,63 +194,61 @@ tsk_bool_t tdav_codec_amrnb_sdp_att_match(const tmedia_codec_t* codec, const cha
/* constructor */
static tsk_object_t* tdav_codec_amrnb_oa_ctor(tsk_object_t * self, va_list * app)
{
- tdav_codec_amr_t *amrnb_oa = self;
- if(amrnb_oa){
- /* init base: called by tmedia_codec_create() */
- /* init self */
- tdav_codec_amr_init(TDAV_CODEC_AMR(amrnb_oa), tdav_codec_amr_type_nb, tdav_codec_amr_mode_oa);
- }
- return self;
+ tdav_codec_amr_t *amrnb_oa = self;
+ if(amrnb_oa) {
+ /* init base: called by tmedia_codec_create() */
+ /* init self */
+ tdav_codec_amr_init(TDAV_CODEC_AMR(amrnb_oa), tdav_codec_amr_type_nb, tdav_codec_amr_mode_oa);
+ }
+ return self;
}
/* destructor */
static tsk_object_t* tdav_codec_amrnb_oa_dtor(tsk_object_t * self)
-{
- tdav_codec_amr_t *amrnb_oa = self;
- if(amrnb_oa){
- /* deinit base */
- tmedia_codec_audio_deinit(amrnb_oa);
- /* deinit self */
- tdav_codec_amr_deinit(TDAV_CODEC_AMR(amrnb_oa));
- }
-
- return self;
+{
+ tdav_codec_amr_t *amrnb_oa = self;
+ if(amrnb_oa) {
+ /* deinit base */
+ tmedia_codec_audio_deinit(amrnb_oa);
+ /* deinit self */
+ tdav_codec_amr_deinit(TDAV_CODEC_AMR(amrnb_oa));
+ }
+
+ return self;
}
/* object definition */
-static const tsk_object_def_t tdav_codec_amrnb_oa_def_s =
-{
- sizeof(tdav_codec_amr_t),
- tdav_codec_amrnb_oa_ctor,
- tdav_codec_amrnb_oa_dtor,
- tmedia_codec_cmp,
+static const tsk_object_def_t tdav_codec_amrnb_oa_def_s = {
+ sizeof(tdav_codec_amr_t),
+ tdav_codec_amrnb_oa_ctor,
+ tdav_codec_amrnb_oa_dtor,
+ tmedia_codec_cmp,
};
/* plugin definition*/
-static const tmedia_codec_plugin_def_t tdav_codec_amrnb_oa_plugin_def_s =
-{
- &tdav_codec_amrnb_oa_def_s,
-
- tmedia_audio,
- tmedia_codec_id_amr_nb_oa,
- "AMR",
- "AMR Narrow Band - Octet Aligned (libopencore-amr)",
- TMEDIA_CODEC_FORMAT_AMR_NB_OA,
- tsk_true,
- 8000, // rate
-
- { /* audio */
- 1, // channels
- 20 // ptime
- },
-
- /* video */
- {0},
-
- tsk_null, // set()
- tdav_codec_amrnb_open,
- tdav_codec_amrnb_close,
- tdav_codec_amrnb_encode,
- tdav_codec_amrnb_decode,
- tdav_codec_amrnb_sdp_att_match,
- tdav_codec_amrnb_sdp_att_get
+static const tmedia_codec_plugin_def_t tdav_codec_amrnb_oa_plugin_def_s = {
+ &tdav_codec_amrnb_oa_def_s,
+
+ tmedia_audio,
+ tmedia_codec_id_amr_nb_oa,
+ "AMR",
+ "AMR Narrow Band - Octet Aligned (libopencore-amr)",
+ TMEDIA_CODEC_FORMAT_AMR_NB_OA,
+ tsk_true,
+ 8000, // rate
+
+ { /* audio */
+ 1, // channels
+ 20 // ptime
+ },
+
+ /* video */
+ {0},
+
+ tsk_null, // set()
+ tdav_codec_amrnb_open,
+ tdav_codec_amrnb_close,
+ tdav_codec_amrnb_encode,
+ tdav_codec_amrnb_decode,
+ tdav_codec_amrnb_sdp_att_match,
+ tdav_codec_amrnb_sdp_att_get
};
const tmedia_codec_plugin_def_t *tdav_codec_amrnb_oa_plugin_def_t = &tdav_codec_amrnb_oa_plugin_def_s;
@@ -261,63 +259,61 @@ const tmedia_codec_plugin_def_t *tdav_codec_amrnb_oa_plugin_def_t = &tdav_codec_
/* constructor */
static tsk_object_t* tdav_codec_amrnb_be_ctor(tsk_object_t * self, va_list * app)
{
- tdav_codec_amr_t *amrnb_be = self;
- if(amrnb_be){
- /* init base: called by tmedia_codec_create() */
- /* init self */
- tdav_codec_amr_init(TDAV_CODEC_AMR(amrnb_be), tdav_codec_amr_type_nb, tdav_codec_amr_mode_be);
- }
- return self;
+ tdav_codec_amr_t *amrnb_be = self;
+ if(amrnb_be) {
+ /* init base: called by tmedia_codec_create() */
+ /* init self */
+ tdav_codec_amr_init(TDAV_CODEC_AMR(amrnb_be), tdav_codec_amr_type_nb, tdav_codec_amr_mode_be);
+ }
+ return self;
}
/* destructor */
static tsk_object_t* tdav_codec_amrnb_be_dtor(tsk_object_t * self)
-{
- tdav_codec_amr_t *amrnb_be = self;
- if(amrnb_be){
- /* deinit base */
- tmedia_codec_audio_deinit(amrnb_be);
- /* deinit self */
- tdav_codec_amr_deinit(TDAV_CODEC_AMR(amrnb_be));
- }
-
- return self;
+{
+ tdav_codec_amr_t *amrnb_be = self;
+ if(amrnb_be) {
+ /* deinit base */
+ tmedia_codec_audio_deinit(amrnb_be);
+ /* deinit self */
+ tdav_codec_amr_deinit(TDAV_CODEC_AMR(amrnb_be));
+ }
+
+ return self;
}
/* object definition */
-static const tsk_object_def_t tdav_codec_amrnb_be_def_s =
-{
- sizeof(tdav_codec_amr_t),
- tdav_codec_amrnb_be_ctor,
- tdav_codec_amrnb_be_dtor,
- tmedia_codec_cmp,
+static const tsk_object_def_t tdav_codec_amrnb_be_def_s = {
+ sizeof(tdav_codec_amr_t),
+ tdav_codec_amrnb_be_ctor,
+ tdav_codec_amrnb_be_dtor,
+ tmedia_codec_cmp,
};
/* plugin definition*/
-static const tmedia_codec_plugin_def_t tdav_codec_amrnb_be_plugin_def_s =
-{
- &tdav_codec_amrnb_be_def_s,
-
- tmedia_audio,
- tmedia_codec_id_amr_nb_be,
- "AMR",
- "AMR Narrow Band - Bandwidth-Efficient (libopencore-amr)",
- TMEDIA_CODEC_FORMAT_AMR_NB_BE,
- tsk_true,
- 8000, // rate
-
- { /* audio */
- 1, // channels
- 0 // ptime @deprecated
- },
-
- /* video */
- {0},
-
- tsk_null, // set()
- tdav_codec_amrnb_open,
- tdav_codec_amrnb_close,
- tdav_codec_amrnb_encode,
- tdav_codec_amrnb_decode,
- tdav_codec_amrnb_sdp_att_match,
- tdav_codec_amrnb_sdp_att_get
+static const tmedia_codec_plugin_def_t tdav_codec_amrnb_be_plugin_def_s = {
+ &tdav_codec_amrnb_be_def_s,
+
+ tmedia_audio,
+ tmedia_codec_id_amr_nb_be,
+ "AMR",
+ "AMR Narrow Band - Bandwidth-Efficient (libopencore-amr)",
+ TMEDIA_CODEC_FORMAT_AMR_NB_BE,
+ tsk_true,
+ 8000, // rate
+
+ { /* audio */
+ 1, // channels
+ 0 // ptime @deprecated
+ },
+
+ /* video */
+ {0},
+
+ tsk_null, // set()
+ tdav_codec_amrnb_open,
+ tdav_codec_amrnb_close,
+ tdav_codec_amrnb_encode,
+ tdav_codec_amrnb_decode,
+ tdav_codec_amrnb_sdp_att_match,
+ tdav_codec_amrnb_sdp_att_get
};
const tmedia_codec_plugin_def_t *tdav_codec_amrnb_be_plugin_def_t = &tdav_codec_amrnb_be_plugin_def_s;
@@ -335,137 +331,141 @@ const tmedia_codec_plugin_def_t *tdav_codec_amrnb_be_plugin_def_t = &tdav_codec_
static int tdav_codec_amr_init(tdav_codec_amr_t* self, tdav_codec_amr_type_t type, tdav_codec_amr_mode_t mode)
{
- if(self){
- self->type = type;
- self->mode = mode;
- self->encoder_mode = DEFAULT_ENC_MODE;
-
- return 0;
- }
- else{
- TSK_DEBUG_ERROR("Invalid Parameter");
- return -1;
- }
+ if(self) {
+ self->type = type;
+ self->mode = mode;
+ self->encoder_mode = DEFAULT_ENC_MODE;
+
+ return 0;
+ }
+ else {
+ TSK_DEBUG_ERROR("Invalid Parameter");
+ return -1;
+ }
}
static int tdav_codec_amr_deinit(tdav_codec_amr_t* self)
{
- if(self){
- switch(self->type){
- case tdav_codec_amr_type_nb:
- { /* AMR-NB */
- if(self->encoder){
- Encoder_Interface_exit(self->encoder);
- self->encoder = tsk_null;
- }
- if(self->decoder){
- Decoder_Interface_exit(self->decoder);
- self->decoder = tsk_null;
- }
- break;
- }
- case tdav_codec_amr_type_wb:
- { /* AMR-WB */
- break;
- }
- }
-
- return 0;
- }
- else{
- TSK_DEBUG_ERROR("Invalid Parameter");
- return -1;
- }
+ if(self) {
+ switch(self->type) {
+ case tdav_codec_amr_type_nb: {
+ /* AMR-NB */
+ if(self->encoder) {
+ Encoder_Interface_exit(self->encoder);
+ self->encoder = tsk_null;
+ }
+ if(self->decoder) {
+ Decoder_Interface_exit(self->decoder);
+ self->decoder = tsk_null;
+ }
+ break;
+ }
+ case tdav_codec_amr_type_wb: {
+ /* AMR-WB */
+ break;
+ }
+ }
+
+ return 0;
+ }
+ else {
+ TSK_DEBUG_ERROR("Invalid Parameter");
+ return -1;
+ }
}
static tdav_codec_amr_mode_t tdav_codec_amr_get_mode(const char* fmtp)
{
- /* RFC 4867 - 8.1. AMR Media Type Registration
- octet-align: Permissible values are 0 and 1. If 1, octet-aligned
- operation SHALL be used. If 0 or if not present, bandwidth-efficient operation is employed.
- */
- tdav_codec_amr_mode_t mode = tdav_codec_amr_mode_be;
- tsk_size_t size = tsk_strlen(fmtp);
- int start, end;
-
- if((start = tsk_strindexOf(fmtp, size, "octet-align")) !=-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)))){
- if(param->value && tsk_strequals(param->value, "1")){
- mode = tdav_codec_amr_mode_oa;
- }
- TSK_OBJECT_SAFE_FREE(param);
- }
- }
- return mode;
+ /* RFC 4867 - 8.1. AMR Media Type Registration
+ octet-align: Permissible values are 0 and 1. If 1, octet-aligned
+ operation SHALL be used. If 0 or if not present, bandwidth-efficient operation is employed.
+ */
+ tdav_codec_amr_mode_t mode = tdav_codec_amr_mode_be;
+ tsk_size_t size = tsk_strlen(fmtp);
+ int start, end;
+
+ if((start = tsk_strindexOf(fmtp, size, "octet-align")) !=-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)))) {
+ if(param->value && tsk_strequals(param->value, "1")) {
+ mode = tdav_codec_amr_mode_oa;
+ }
+ TSK_OBJECT_SAFE_FREE(param);
+ }
+ }
+ return mode;
}
int tdav_codec_amr_parse_fmtp(tdav_codec_amr_t* self, const char* fmtp)
{
- int ret = 0;
- int val_int;
- const char* val_str;
- //--tdav_codec_amr_mode_t mode = self->mode;
- tsk_params_L_t* params = tsk_null;
-
- if((params = tsk_params_fromstring(fmtp, ";", tsk_true))){
- /* Do not check "octet-align" => already done by the caller of this function */
-
- /* === mode-set ===*/
- if((val_str = tsk_params_get_param_value(params, "mode-set"))){
- char* modes = tsk_strdup(val_str);
- char *pch, *saveptr;
- int mode_int;
- pch = tsk_strtok_r(modes, ", ", &saveptr);
- while(pch){
- mode_int = atoi(pch);
- self->modes |= 0x0001 << mode_int;
- pch = tsk_strtok_r(tsk_null, ", ", &saveptr);
- }
-
- TSK_FREE(modes);
- }
- else{
- self->modes = 0xFFFF;
- }
-
- /* === interleaving ===*/
- if((val_int = tsk_params_get_param_value_as_int(params, "interleaving")) != -1){
- TSK_DEBUG_WARN("interleaving not supported");
- ret = -1; goto bail;
- }
- /* === mode-change-period ===*/
- if((val_int = tsk_params_get_param_value_as_int(params, "mode-change-period")) != -1){
- if(val_int != 1 && val_int != 2){
- TSK_DEBUG_ERROR("Invalid [mode-change-period]");
- ret = -1; goto bail;
- }
- self->mcp = (unsigned)val_int;
- }
- /* === mode-change-capability ===*/
- if((val_int = tsk_params_get_param_value_as_int(params, "mode-change-capability")) != -1){
- if(val_int != 1 && val_int != 2){
- TSK_DEBUG_ERROR("Invalid [mode-change-capability]");
- ret = -1; goto bail;
- }
- self->mcc = (unsigned)val_int;
- }
- /* === mode-change-neighbor ===*/
- if((val_int = tsk_params_get_param_value_as_int(params, "mode-change-neighbor")) != -1){
- if(val_int != 0 && val_int != 1){
- TSK_DEBUG_ERROR("Invalid [mode-change-neighbor]");
- ret = -1; goto bail;
- }
- self->mcn = (unsigned)val_int;
- }
- }
+ int ret = 0;
+ int val_int;
+ const char* val_str;
+ //--tdav_codec_amr_mode_t mode = self->mode;
+ tsk_params_L_t* params = tsk_null;
+
+ if((params = tsk_params_fromstring(fmtp, ";", tsk_true))) {
+ /* Do not check "octet-align" => already done by the caller of this function */
+
+ /* === mode-set ===*/
+ if((val_str = tsk_params_get_param_value(params, "mode-set"))) {
+ char* modes = tsk_strdup(val_str);
+ char *pch, *saveptr;
+ int mode_int;
+ pch = tsk_strtok_r(modes, ", ", &saveptr);
+ while(pch) {
+ mode_int = atoi(pch);
+ self->modes |= 0x0001 << mode_int;
+ pch = tsk_strtok_r(tsk_null, ", ", &saveptr);
+ }
+
+ TSK_FREE(modes);
+ }
+ else {
+ self->modes = 0xFFFF;
+ }
+
+ /* === interleaving ===*/
+ if((val_int = tsk_params_get_param_value_as_int(params, "interleaving")) != -1) {
+ TSK_DEBUG_WARN("interleaving not supported");
+ ret = -1;
+ goto bail;
+ }
+ /* === mode-change-period ===*/
+ if((val_int = tsk_params_get_param_value_as_int(params, "mode-change-period")) != -1) {
+ if(val_int != 1 && val_int != 2) {
+ TSK_DEBUG_ERROR("Invalid [mode-change-period]");
+ ret = -1;
+ goto bail;
+ }
+ self->mcp = (unsigned)val_int;
+ }
+ /* === mode-change-capability ===*/
+ if((val_int = tsk_params_get_param_value_as_int(params, "mode-change-capability")) != -1) {
+ if(val_int != 1 && val_int != 2) {
+ TSK_DEBUG_ERROR("Invalid [mode-change-capability]");
+ ret = -1;
+ goto bail;
+ }
+ self->mcc = (unsigned)val_int;
+ }
+ /* === mode-change-neighbor ===*/
+ if((val_int = tsk_params_get_param_value_as_int(params, "mode-change-neighbor")) != -1) {
+ if(val_int != 0 && val_int != 1) {
+ TSK_DEBUG_ERROR("Invalid [mode-change-neighbor]");
+ ret = -1;
+ goto bail;
+ }
+ self->mcn = (unsigned)val_int;
+ }
+ }
bail:
- TSK_OBJECT_SAFE_FREE(params);
- return ret;
+ TSK_OBJECT_SAFE_FREE(params);
+ return ret;
}
@@ -487,330 +487,330 @@ bail:
static tsk_size_t tdav_codec_amr_be_encode(tdav_codec_amr_t* amr, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size)
-{
- tsk_size_t out_size = 0, i;
- int ret_size;
- uint8_t ToC;
- static uint8_t CMR = NO_DATA /* No interleaving */;
-
- uint8_t outbuf[60 + 1]; /* enought for both NB and WB at ptime=20ms */
- if(!amr || !in_data || !in_size || !out_data || (amr->mode != tdav_codec_amr_mode_be)){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- /* Encode */
- if((ret_size = Encoder_Interface_Encode(amr->encoder, amr->encoder_mode, in_data, outbuf, 0)) <= 0){
- TSK_DEBUG_ERROR("Encoder_Interface_Encode() failed");
- goto bail;
- }
-
-
- /* allocate output buffer */
- if((int)*out_max_size <ret_size){
- if(!(*out_data = tsk_realloc(*out_data, ret_size))){
- *out_max_size = 0;
- TSK_DEBUG_ERROR("Failed to allocate new buffer");
- goto bail;
- }
- *out_max_size = ret_size;
- }
-
- out_size = ret_size;
-
- /* CMR (4bits) */
- ((uint8_t*)*out_data)[0] = (CMR<<4);
- /* ToC (Always ONE Frame, don't need to test for [F]) (6bits)*/
- ToC = outbuf[0]>>2/*2*[P]*/;
- ((uint8_t*)*out_data)[0] |= (ToC >> 2/*[Q],[1-FT]*/) & 0xF; /* 4bits */
- ((uint8_t*)*out_data)[1] = (ToC & 0x3/*[1-FT],[Q]*/)<<6; /* 2bits */
-
- /* === THERE ARE 2 EXTRA BITS === */
-
- for(i=1; i<out_size-1; i++){
- ((uint8_t*)*out_data)[i] |= outbuf[i]>>2;/* 6bits */
- ((uint8_t*)*out_data)[i+1] = outbuf[i]<<6;/* 2bits */
- }
+{
+ tsk_size_t out_size = 0, i;
+ int ret_size;
+ uint8_t ToC;
+ static uint8_t CMR = NO_DATA /* No interleaving */;
+
+ uint8_t outbuf[60 + 1]; /* enought for both NB and WB at ptime=20ms */
+ if(!amr || !in_data || !in_size || !out_data || (amr->mode != tdav_codec_amr_mode_be)) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ /* Encode */
+ if((ret_size = Encoder_Interface_Encode(amr->encoder, amr->encoder_mode, in_data, outbuf, 0)) <= 0) {
+ TSK_DEBUG_ERROR("Encoder_Interface_Encode() failed");
+ goto bail;
+ }
+
+
+ /* allocate output buffer */
+ if((int)*out_max_size <ret_size) {
+ if(!(*out_data = tsk_realloc(*out_data, ret_size))) {
+ *out_max_size = 0;
+ TSK_DEBUG_ERROR("Failed to allocate new buffer");
+ goto bail;
+ }
+ *out_max_size = ret_size;
+ }
+
+ out_size = ret_size;
+
+ /* CMR (4bits) */
+ ((uint8_t*)*out_data)[0] = (CMR<<4);
+ /* ToC (Always ONE Frame, don't need to test for [F]) (6bits)*/
+ ToC = outbuf[0]>>2/*2*[P]*/;
+ ((uint8_t*)*out_data)[0] |= (ToC >> 2/*[Q],[1-FT]*/) & 0xF; /* 4bits */
+ ((uint8_t*)*out_data)[1] = (ToC & 0x3/*[1-FT],[Q]*/)<<6; /* 2bits */
+
+ /* === THERE ARE 2 EXTRA BITS === */
+
+ for(i=1; i<out_size-1; i++) {
+ ((uint8_t*)*out_data)[i] |= outbuf[i]>>2;/* 6bits */
+ ((uint8_t*)*out_data)[i+1] = outbuf[i]<<6;/* 2bits */
+ }
bail:
- return out_size;
+ return out_size;
}
tsk_size_t tdav_codec_amr_be_decode(tdav_codec_amr_t* amr, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size, const tsk_object_t* proto_hdr)
{
- tsk_size_t out_size = 0, pcm_frame_size = 0, index = 0;
- const uint8_t* pdata = (const uint8_t*)in_data;
- //--const uint8_t* pend = (pdata + in_size);
- uint8_t CMR;
- int toc_entries = 0, i, k; // ToC entries count
-
- if(!amr || !in_data || !in_size || !out_data || (amr->mode != tdav_codec_amr_mode_be)){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- /* compute PCM frame size */
- switch(TDAV_CODEC_AMR(amr)->type){
- case tdav_codec_amr_type_nb:
- pcm_frame_size = 160 * sizeof(short);
- break;
- case tdav_codec_amr_type_wb:
- pcm_frame_size = 320 * sizeof(short);
- break;
- default:
- TSK_DEBUG_ERROR("Invalid AMR type");
- return 0;
- }
-
- /* CMR (4bits) */
- CMR = tdav_codec_amr_bitbuffer_read(in_data, (in_size*8), index, 4);
- index += 4;
- if(CMR != NO_DATA){
- amr->encoder_mode = (enum Mode)CMR;
- }
-
- /* F(1bit), FT(4bits), Q(1bit) */
- /* count ToC entries */
- do{ /* At least ONE ToC */
- ++toc_entries;
- ++pdata;
- index += 6;
- }
- while((index < (in_size*8)) && (tdav_codec_amr_bitbuffer_read(in_data, (in_size*8), (index-6), 1)/* F */));
-
- for(i = 0; (i<toc_entries && (in_size < (in_size*8))) ; i++){
- int size = -1;
- uint8_t* speech_data = tsk_null;
- //--int speech_data_size = 0;
- uint8_t ToC = tdav_codec_amr_bitbuffer_read(in_data, (in_size*8), 4/*CMR*/ + (i*6), 6);
-
- switch(TDAV_CODEC_AMR(amr)->type){
- case tdav_codec_amr_type_nb:
- size = tdav_codec_amr_nb_sizes[(ToC>>1)&0x0F/* FT */];
- break;
- case tdav_codec_amr_type_wb:
- size = tdav_codec_amr_wb_sizes[(ToC>>1)&0x0F/* FT */];
- break;
- }
-
- if((speech_data = tsk_calloc((size + 2/* ToC + '\0' */), sizeof(uint8_t)))){
- /* copy ToC */
- speech_data[0] = (ToC & 0x1F)<<2/* 2*[P] */; /* ToC as OA layout */
- /* copy speech data */
- for(k=0; k<size; k++){
- speech_data[1 + k] = tdav_codec_amr_bitbuffer_read(in_data, (in_size*8), index, 8);
- index+=8;
- if((k==size-1) && (index%8)){
- speech_data[1 + k] <<= (8-(index%8)); //clean
- }
- }
-
- /* allocate/reallocate speech data */
- if(*out_max_size <(out_size + pcm_frame_size)){
- if(!(*out_data = tsk_realloc(*out_data, (out_size + pcm_frame_size)))){
- TSK_DEBUG_ERROR("Failed to allocate new buffer");
- *out_max_size = 0;
- TSK_FREE(speech_data);
- goto bail;
- }
- *out_max_size = out_size + pcm_frame_size;
- }
-
- /* decode speech data */
- Decoder_Interface_Decode(amr->decoder, speech_data, &((short*)*out_data)[out_size/sizeof(short)], 0);
- out_size += pcm_frame_size, pdata+= size;
-
- TSK_FREE(speech_data);
- }
- }
+ tsk_size_t out_size = 0, pcm_frame_size = 0, index = 0;
+ const uint8_t* pdata = (const uint8_t*)in_data;
+ //--const uint8_t* pend = (pdata + in_size);
+ uint8_t CMR;
+ int toc_entries = 0, i, k; // ToC entries count
+
+ if(!amr || !in_data || !in_size || !out_data || (amr->mode != tdav_codec_amr_mode_be)) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ /* compute PCM frame size */
+ switch(TDAV_CODEC_AMR(amr)->type) {
+ case tdav_codec_amr_type_nb:
+ pcm_frame_size = 160 * sizeof(short);
+ break;
+ case tdav_codec_amr_type_wb:
+ pcm_frame_size = 320 * sizeof(short);
+ break;
+ default:
+ TSK_DEBUG_ERROR("Invalid AMR type");
+ return 0;
+ }
+
+ /* CMR (4bits) */
+ CMR = tdav_codec_amr_bitbuffer_read(in_data, (in_size*8), index, 4);
+ index += 4;
+ if(CMR != NO_DATA) {
+ amr->encoder_mode = (enum Mode)CMR;
+ }
+
+ /* F(1bit), FT(4bits), Q(1bit) */
+ /* count ToC entries */
+ do { /* At least ONE ToC */
+ ++toc_entries;
+ ++pdata;
+ index += 6;
+ }
+ while((index < (in_size*8)) && (tdav_codec_amr_bitbuffer_read(in_data, (in_size*8), (index-6), 1)/* F */));
+
+ for(i = 0; (i<toc_entries && (in_size < (in_size*8))) ; i++) {
+ int size = -1;
+ uint8_t* speech_data = tsk_null;
+ //--int speech_data_size = 0;
+ uint8_t ToC = tdav_codec_amr_bitbuffer_read(in_data, (in_size*8), 4/*CMR*/ + (i*6), 6);
+
+ switch(TDAV_CODEC_AMR(amr)->type) {
+ case tdav_codec_amr_type_nb:
+ size = tdav_codec_amr_nb_sizes[(ToC>>1)&0x0F/* FT */];
+ break;
+ case tdav_codec_amr_type_wb:
+ size = tdav_codec_amr_wb_sizes[(ToC>>1)&0x0F/* FT */];
+ break;
+ }
+
+ if((speech_data = tsk_calloc((size + 2/* ToC + '\0' */), sizeof(uint8_t)))) {
+ /* copy ToC */
+ speech_data[0] = (ToC & 0x1F)<<2/* 2*[P] */; /* ToC as OA layout */
+ /* copy speech data */
+ for(k=0; k<size; k++) {
+ speech_data[1 + k] = tdav_codec_amr_bitbuffer_read(in_data, (in_size*8), index, 8);
+ index+=8;
+ if((k==size-1) && (index%8)) {
+ speech_data[1 + k] <<= (8-(index%8)); //clean
+ }
+ }
+
+ /* allocate/reallocate speech data */
+ if(*out_max_size <(out_size + pcm_frame_size)) {
+ if(!(*out_data = tsk_realloc(*out_data, (out_size + pcm_frame_size)))) {
+ TSK_DEBUG_ERROR("Failed to allocate new buffer");
+ *out_max_size = 0;
+ TSK_FREE(speech_data);
+ goto bail;
+ }
+ *out_max_size = out_size + pcm_frame_size;
+ }
+
+ /* decode speech data */
+ Decoder_Interface_Decode(amr->decoder, speech_data, &((short*)*out_data)[out_size/sizeof(short)], 0);
+ out_size += pcm_frame_size, pdata+= size;
+
+ TSK_FREE(speech_data);
+ }
+ }
bail:
- return out_size;
+ return out_size;
}
static tsk_size_t tdav_codec_amr_oa_encode(tdav_codec_amr_t* amr, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size)
-{
- tsk_size_t out_size = 0;
- int ret_size;
- static uint8_t CMR = NO_DATA /* No interleaving */;
-
- uint8_t outbuf[60 + 1]; /* enought for both NB and WB at ptime=20ms */
- if(!amr || !in_data || !in_size || !out_data || (amr->mode != tdav_codec_amr_mode_oa)){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- /* Encode */
- if((ret_size = Encoder_Interface_Encode(amr->encoder, amr->encoder_mode, in_data, outbuf, 0)) <= 0){
- TSK_DEBUG_ERROR("Encoder_Interface_Encode() failed");
- goto bail;
- }
-
- out_size = ret_size + 1 /* CMR without interleaving */;
- /* allocate output buffer */
- if(*out_max_size <out_size){
- if(!(*out_data = tsk_realloc(*out_data, out_size))){
- TSK_DEBUG_ERROR("Failed to allocate new buffer");
- *out_max_size = out_size = 0;
- goto bail;
- }
- *out_max_size = out_size;
- }
-
- /* CMR */
- ((uint8_t*)*out_data)[0] = (CMR << 4);
- /* Only ONE ToC --> believe me */
- memcpy(&((uint8_t*)*out_data)[1], outbuf, ret_size);
+{
+ tsk_size_t out_size = 0;
+ int ret_size;
+ static uint8_t CMR = NO_DATA /* No interleaving */;
+
+ uint8_t outbuf[60 + 1]; /* enought for both NB and WB at ptime=20ms */
+ if(!amr || !in_data || !in_size || !out_data || (amr->mode != tdav_codec_amr_mode_oa)) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ /* Encode */
+ if((ret_size = Encoder_Interface_Encode(amr->encoder, amr->encoder_mode, in_data, outbuf, 0)) <= 0) {
+ TSK_DEBUG_ERROR("Encoder_Interface_Encode() failed");
+ goto bail;
+ }
+
+ out_size = ret_size + 1 /* CMR without interleaving */;
+ /* allocate output buffer */
+ if(*out_max_size <out_size) {
+ if(!(*out_data = tsk_realloc(*out_data, out_size))) {
+ TSK_DEBUG_ERROR("Failed to allocate new buffer");
+ *out_max_size = out_size = 0;
+ goto bail;
+ }
+ *out_max_size = out_size;
+ }
+
+ /* CMR */
+ ((uint8_t*)*out_data)[0] = (CMR << 4);
+ /* Only ONE ToC --> believe me */
+ memcpy(&((uint8_t*)*out_data)[1], outbuf, ret_size);
bail:
- return out_size;
+ return out_size;
}
static tsk_size_t tdav_codec_amr_oa_decode(tdav_codec_amr_t* amr, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size, const tsk_object_t* proto_hdr)
{
- tsk_size_t out_size = 0, pcm_frame_size = 0;
- const uint8_t* pdata = (const uint8_t*)in_data;
- const uint8_t* pend = (pdata + in_size);
- uint8_t CMR;
- int toc_entries = 0, i; // ToC entries count
-
- if(!amr || !in_data || !in_size || !out_data || (amr->mode != tdav_codec_amr_mode_oa)){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- /* compute PCM frame size */
- switch(TDAV_CODEC_AMR(amr)->type){
- case tdav_codec_amr_type_nb:
- pcm_frame_size = 160 * sizeof(short);
- break;
- case tdav_codec_amr_type_wb:
- pcm_frame_size = 320 * sizeof(short);
- break;
- default:
- TSK_DEBUG_ERROR("Invalid AMR type");
- return 0;
- }
-
- /* RFC 4867 - 4.4. Octet-Aligned Mode
- In octet-aligned mode, the payload header consists of a 4-bit CMR, 4
- reserved bits, and optionally, an 8-bit interleaving header, as shown
- below:
-
- 0 1
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
- +-+-+-+-+-+-+-+-+- - - - - - - -
- | CMR |R|R|R|R| ILL | ILP |
- +-+-+-+-+-+-+-+-+- - - - - - - -
-
- CMR (4 bits): same as defined in Section 4.3.1.
-
- "interleaving" not supported ==> could ignore ILL and ILP (wich are optional)
- */
-
- CMR = (*pdata++ >> 4);
- if(CMR != NO_DATA){
- /* The codec mode request received in the CMR field is valid until the
- next codec mode request is received, i.e., a newly received CMR value
- corresponding to a speech mode, or NO_DATA overrides the previously
- received CMR value corresponding to a speech mode or NO_DATA. */
- amr->encoder_mode = (enum Mode)CMR; // As we support all modes, do not check for validity
- }
-
- /*
- A ToC entry takes the following format in octet-aligned mode:
- 0 1 2 3 4 5 6 7
- +-+-+-+-+-+-+-+-+
- |F| FT |Q|P|P|
- +-+-+-+-+-+-+-+-+
-
- F (1 bit): see definition in Section 4.3.2.
- FT (4 bits, unsigned integer): see definition in Section 4.3.2.
- Q (1 bit): see definition in Section 4.3.2.
- P bits: padding bits, MUST be set to zero, and MUST be ignored on reception.
- */
-
- /* count ToC entries */
- do{ /* At least ONE ToC */
- ++toc_entries;
- ++pdata;
- }
- while(pdata && (pdata < pend) && (pdata[-1] >> 7/* F */));
-
- for(i = 0; (i<toc_entries && (pdata < pend)) ; i++){
- int size = -1;
- uint8_t* speech_data = tsk_null;
- //--int speech_data_size = 0;
- uint8_t ToC = ((const uint8_t*)in_data)[1/*CMR...*/ + i];
- switch(TDAV_CODEC_AMR(amr)->type){
- case tdav_codec_amr_type_nb:
- size = tdav_codec_amr_nb_sizes[(ToC>>3) & 0x0F/* FT */];
- break;
- case tdav_codec_amr_type_wb:
- size = tdav_codec_amr_wb_sizes[(ToC>>3) & 0x0F/* FT */];
- break;
- }
-
- /* check size */
- if(size <0 || ((pdata + size) > pend)){
- TSK_DEBUG_ERROR("Invalid size");
- break;
- }
-
- if((speech_data = tsk_calloc((size + 2/* ToC + '\0' */), sizeof(uint8_t)))){
- /* copy ToC */
- *speech_data = ToC & 0x7F/* with 'F'=0 */;
- /* copy speech data */
- memcpy((speech_data + 1), pdata, size);
- /* allocate/reallocate speech data */
- if(*out_max_size <(out_size + pcm_frame_size)){
- if(!(*out_data = tsk_realloc(*out_data, (out_size + pcm_frame_size)))){
- TSK_DEBUG_ERROR("Failed to allocate new buffer");
- *out_max_size = 0;
- TSK_FREE(speech_data);
- goto bail;
- }
- *out_max_size = (out_size + pcm_frame_size);
- }
- /* decode speech data */
- Decoder_Interface_Decode(amr->decoder, speech_data, &((short*)*out_data)[out_size/sizeof(short)], 0);
- out_size += pcm_frame_size, pdata+= size;
-
- TSK_FREE(speech_data);
- }
- }
+ tsk_size_t out_size = 0, pcm_frame_size = 0;
+ const uint8_t* pdata = (const uint8_t*)in_data;
+ const uint8_t* pend = (pdata + in_size);
+ uint8_t CMR;
+ int toc_entries = 0, i; // ToC entries count
+
+ if(!amr || !in_data || !in_size || !out_data || (amr->mode != tdav_codec_amr_mode_oa)) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ /* compute PCM frame size */
+ switch(TDAV_CODEC_AMR(amr)->type) {
+ case tdav_codec_amr_type_nb:
+ pcm_frame_size = 160 * sizeof(short);
+ break;
+ case tdav_codec_amr_type_wb:
+ pcm_frame_size = 320 * sizeof(short);
+ break;
+ default:
+ TSK_DEBUG_ERROR("Invalid AMR type");
+ return 0;
+ }
+
+ /* RFC 4867 - 4.4. Octet-Aligned Mode
+ In octet-aligned mode, the payload header consists of a 4-bit CMR, 4
+ reserved bits, and optionally, an 8-bit interleaving header, as shown
+ below:
+
+ 0 1
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ +-+-+-+-+-+-+-+-+- - - - - - - -
+ | CMR |R|R|R|R| ILL | ILP |
+ +-+-+-+-+-+-+-+-+- - - - - - - -
+
+ CMR (4 bits): same as defined in Section 4.3.1.
+
+ "interleaving" not supported ==> could ignore ILL and ILP (wich are optional)
+ */
+
+ CMR = (*pdata++ >> 4);
+ if(CMR != NO_DATA) {
+ /* The codec mode request received in the CMR field is valid until the
+ next codec mode request is received, i.e., a newly received CMR value
+ corresponding to a speech mode, or NO_DATA overrides the previously
+ received CMR value corresponding to a speech mode or NO_DATA. */
+ amr->encoder_mode = (enum Mode)CMR; // As we support all modes, do not check for validity
+ }
+
+ /*
+ A ToC entry takes the following format in octet-aligned mode:
+ 0 1 2 3 4 5 6 7
+ +-+-+-+-+-+-+-+-+
+ |F| FT |Q|P|P|
+ +-+-+-+-+-+-+-+-+
+
+ F (1 bit): see definition in Section 4.3.2.
+ FT (4 bits, unsigned integer): see definition in Section 4.3.2.
+ Q (1 bit): see definition in Section 4.3.2.
+ P bits: padding bits, MUST be set to zero, and MUST be ignored on reception.
+ */
+
+ /* count ToC entries */
+ do { /* At least ONE ToC */
+ ++toc_entries;
+ ++pdata;
+ }
+ while(pdata && (pdata < pend) && (pdata[-1] >> 7/* F */));
+
+ for(i = 0; (i<toc_entries && (pdata < pend)) ; i++) {
+ int size = -1;
+ uint8_t* speech_data = tsk_null;
+ //--int speech_data_size = 0;
+ uint8_t ToC = ((const uint8_t*)in_data)[1/*CMR...*/ + i];
+ switch(TDAV_CODEC_AMR(amr)->type) {
+ case tdav_codec_amr_type_nb:
+ size = tdav_codec_amr_nb_sizes[(ToC>>3) & 0x0F/* FT */];
+ break;
+ case tdav_codec_amr_type_wb:
+ size = tdav_codec_amr_wb_sizes[(ToC>>3) & 0x0F/* FT */];
+ break;
+ }
+
+ /* check size */
+ if(size <0 || ((pdata + size) > pend)) {
+ TSK_DEBUG_ERROR("Invalid size");
+ break;
+ }
+
+ if((speech_data = tsk_calloc((size + 2/* ToC + '\0' */), sizeof(uint8_t)))) {
+ /* copy ToC */
+ *speech_data = ToC & 0x7F/* with 'F'=0 */;
+ /* copy speech data */
+ memcpy((speech_data + 1), pdata, size);
+ /* allocate/reallocate speech data */
+ if(*out_max_size <(out_size + pcm_frame_size)) {
+ if(!(*out_data = tsk_realloc(*out_data, (out_size + pcm_frame_size)))) {
+ TSK_DEBUG_ERROR("Failed to allocate new buffer");
+ *out_max_size = 0;
+ TSK_FREE(speech_data);
+ goto bail;
+ }
+ *out_max_size = (out_size + pcm_frame_size);
+ }
+ /* decode speech data */
+ Decoder_Interface_Decode(amr->decoder, speech_data, &((short*)*out_data)[out_size/sizeof(short)], 0);
+ out_size += pcm_frame_size, pdata+= size;
+
+ TSK_FREE(speech_data);
+ }
+ }
bail:
- return out_size;
+ return out_size;
}
static uint8_t tdav_codec_amr_bitbuffer_read(const void* bits, tsk_size_t size, tsk_size_t start, tsk_size_t count)
{
- uint8_t byte, left, right, pad;
-
- if(!bits || !size || count>8){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- if((start + count) > size){
- count = (size - start);
- }
-
- pad = start ? (8 - (start % 8)) : count;
- left = ((uint8_t*)bits)[start/8] << (8-pad);
- right = ((uint8_t*)bits)[((start+count)<size ? (start+count) : start)/8] >> pad;
-
- if((start && (start % 8) != ((start+count)%8)) || (!start && count>8)){
- /* overlap */
- byte = (left | right) >> (8-count);
- }
- else{
- byte = (left | right) & (0xFF >> (8-count));
- }
-
- return byte;
+ uint8_t byte, left, right, pad;
+
+ if(!bits || !size || count>8) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ if((start + count) > size) {
+ count = (size - start);
+ }
+
+ pad = start ? (8 - (start % 8)) : count;
+ left = ((uint8_t*)bits)[start/8] << (8-pad);
+ right = ((uint8_t*)bits)[((start+count)<size ? (start+count) : start)/8] >> pad;
+
+ if((start && (start % 8) != ((start+count)%8)) || (!start && count>8)) {
+ /* overlap */
+ byte = (left | right) >> (8-count);
+ }
+ else {
+ byte = (left | right) & (0xFF >> (8-count));
+ }
+
+ return byte;
}
#endif /* HAVE_OPENCORE_AMR */
diff --git a/tinyDAV/src/codecs/bfcp/tdav_codec_bfcp.c b/tinyDAV/src/codecs/bfcp/tdav_codec_bfcp.c
index 3495295..5588410 100755
--- a/tinyDAV/src/codecs/bfcp/tdav_codec_bfcp.c
+++ b/tinyDAV/src/codecs/bfcp/tdav_codec_bfcp.c
@@ -1,18 +1,18 @@
/*
* Copyright (C) 2014 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.
*
@@ -35,8 +35,9 @@
#define tdav_codec_bfcp_decode tsk_null
static tsk_bool_t tdav_codec_bfcp_sdp_att_match(const tmedia_codec_t* codec, const char* att_name, const char* att_value)
-{ /* always match */
- return tsk_true;
+{
+ /* always match */
+ return tsk_true;
}
@@ -47,58 +48,56 @@ static tsk_bool_t tdav_codec_bfcp_sdp_att_match(const tmedia_codec_t* codec, con
/* constructor */
static tsk_object_t* tdav_codec_bfcp_ctor(tsk_object_t * self, va_list * app)
{
- tdav_codec_bfcp_t *bfcp = self;
- if (bfcp) {
- /* init base: called by tmedia_codec_create() */
- /* init self */
- }
- return self;
+ tdav_codec_bfcp_t *bfcp = self;
+ if (bfcp) {
+ /* init base: called by tmedia_codec_create() */
+ /* init self */
+ }
+ return self;
}
/* destructor */
static tsk_object_t* tdav_codec_bfcp_dtor(tsk_object_t * self)
-{
- tdav_codec_bfcp_t *bfcp = self;
- if (bfcp) {
- /* deinit base */
- tmedia_codec_bfcp_deinit(bfcp);
- /* deinit self */
- }
+{
+ tdav_codec_bfcp_t *bfcp = self;
+ if (bfcp) {
+ /* deinit base */
+ tmedia_codec_bfcp_deinit(bfcp);
+ /* deinit self */
+ }
- return self;
+ return self;
}
/* object definition */
-static const tsk_object_def_t tdav_codec_bfcp_def_s =
-{
- sizeof(tdav_codec_bfcp_t),
- tdav_codec_bfcp_ctor,
- tdav_codec_bfcp_dtor,
- tmedia_codec_cmp,
+static const tsk_object_def_t tdav_codec_bfcp_def_s = {
+ sizeof(tdav_codec_bfcp_t),
+ tdav_codec_bfcp_ctor,
+ tdav_codec_bfcp_dtor,
+ tmedia_codec_cmp,
};
/* plugin definition*/
-static const tmedia_codec_plugin_def_t tdav_codec_bfcp_plugin_def_s =
-{
- &tdav_codec_bfcp_def_s,
+static const tmedia_codec_plugin_def_t tdav_codec_bfcp_plugin_def_s = {
+ &tdav_codec_bfcp_def_s,
+
+ tmedia_bfcp,
+ tmedia_codec_id_none, // fake codec without real id
+ "application",
+ "BFCP fake codec",
+ TMEDIA_CODEC_FORMAT_BFCP,
+ tsk_false,
+ 0, // rate
- tmedia_bfcp,
- tmedia_codec_id_none, // fake codec without real id
- "application",
- "BFCP fake codec",
- TMEDIA_CODEC_FORMAT_BFCP,
- tsk_false,
- 0, // rate
-
- /* audio */
- {0},
+ /* audio */
+ {0},
- /* video */
- {0},
+ /* video */
+ {0},
- tsk_null, // set()
- tdav_codec_bfcp_open,
- tdav_codec_bfcp_close,
- tdav_codec_bfcp_encode,
- tdav_codec_bfcp_decode,
- tdav_codec_bfcp_sdp_att_match,
- tdav_codec_bfcp_sdp_att_get
+ tsk_null, // set()
+ tdav_codec_bfcp_open,
+ tdav_codec_bfcp_close,
+ tdav_codec_bfcp_encode,
+ tdav_codec_bfcp_decode,
+ tdav_codec_bfcp_sdp_att_match,
+ tdav_codec_bfcp_sdp_att_get
};
const tmedia_codec_plugin_def_t *tdav_codec_bfcp_plugin_def_t = &tdav_codec_bfcp_plugin_def_s;
diff --git a/tinyDAV/src/codecs/bv/tdav_codec_bv16.c b/tinyDAV/src/codecs/bv/tdav_codec_bv16.c
index 21850fb..26e27e6 100755
--- a/tinyDAV/src/codecs/bv/tdav_codec_bv16.c
+++ b/tinyDAV/src/codecs/bv/tdav_codec_bv16.c
@@ -2,19 +2,19 @@
* Copyright (C) 2010-2011 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.
*
@@ -49,11 +49,11 @@
#else
#include "bitpack.h"
#endif
-#include "memutil.h"
+#include "memutil.h"
/* RFC 4298 - 3.1. BroadVoice16 Bit Stream Definition */
#define TDAV_BV16_FRAME_SIZE 10
-#define FRSZ_IN_U8 (FRSZ*2)
+#define FRSZ_IN_U8 (FRSZ*2)
/* ============ BV16 Plugin interface ================= */
@@ -65,118 +65,119 @@ static int sizebitstream = sizeof(struct BV16_Bit_Stream);
int tdav_codec_bv16_open(tmedia_codec_t* self)
{
- tdav_codec_bv16_t* bv16 = (tdav_codec_bv16_t*)self;
-
- if(!bv16->encoder.state){
- bv16->encoder.state = allocWord16(0, sizestate/2-1);
- Reset_BV16_Encoder((struct BV16_Encoder_State*)bv16->encoder.state);
- }
- if(!bv16->encoder.bs){
- bv16->encoder.bs = allocWord16(0, sizebitstream/2-1);
- }
- if(!bv16->encoder.x){
- bv16->encoder.x = allocWord16(0, FRSZ-1);
- }
-
- if(!bv16->decoder.state){
- bv16->decoder.state = allocWord16(0, sizestate/2-1);
- Reset_BV16_Decoder((struct BV16_Decoder_State*)bv16->decoder.state);
- }
- if(!bv16->decoder.bs){
- bv16->decoder.bs = allocWord16(0, sizebitstream/2-1);
- }
- if(!bv16->decoder.x){
- bv16->decoder.x = allocWord16(0, FRSZ-1);
- }
-
- return 0;
+ tdav_codec_bv16_t* bv16 = (tdav_codec_bv16_t*)self;
+
+ if(!bv16->encoder.state) {
+ bv16->encoder.state = allocWord16(0, sizestate/2-1);
+ Reset_BV16_Encoder((struct BV16_Encoder_State*)bv16->encoder.state);
+ }
+ if(!bv16->encoder.bs) {
+ bv16->encoder.bs = allocWord16(0, sizebitstream/2-1);
+ }
+ if(!bv16->encoder.x) {
+ bv16->encoder.x = allocWord16(0, FRSZ-1);
+ }
+
+ if(!bv16->decoder.state) {
+ bv16->decoder.state = allocWord16(0, sizestate/2-1);
+ Reset_BV16_Decoder((struct BV16_Decoder_State*)bv16->decoder.state);
+ }
+ if(!bv16->decoder.bs) {
+ bv16->decoder.bs = allocWord16(0, sizebitstream/2-1);
+ }
+ if(!bv16->decoder.x) {
+ bv16->decoder.x = allocWord16(0, FRSZ-1);
+ }
+
+ return 0;
}
int tdav_codec_bv16_close(tmedia_codec_t* self)
{
- tdav_codec_bv16_t* bv16 = (tdav_codec_bv16_t*)self;
-
- if(bv16->encoder.state){
- deallocWord16(bv16->encoder.state, 0, sizestate/2-1);
- bv16->encoder.state = tsk_null;
- }
- if(bv16->encoder.bs){
- deallocWord16(bv16->encoder.bs, 0, sizebitstream/2-1);
- bv16->encoder.bs = tsk_null;
- }
- if(bv16->encoder.x){
- deallocWord16(bv16->encoder.x, 0, FRSZ-1);
- bv16->encoder.x = tsk_null;
- }
-
- if(bv16->decoder.state){
- deallocWord16(bv16->decoder.state, 0, sizestate/2-1);
- bv16->decoder.state = tsk_null;
- }
- if(bv16->encoder.bs){
- deallocWord16(bv16->decoder.bs, 0, sizebitstream/2-1);
- bv16->decoder.bs = tsk_null;
- }
- if(bv16->decoder.x){
- deallocWord16(bv16->decoder.x, 0, FRSZ-1);
- bv16->decoder.x = tsk_null;
- }
-
-
-
- return 0;
+ tdav_codec_bv16_t* bv16 = (tdav_codec_bv16_t*)self;
+
+ if(bv16->encoder.state) {
+ deallocWord16(bv16->encoder.state, 0, sizestate/2-1);
+ bv16->encoder.state = tsk_null;
+ }
+ if(bv16->encoder.bs) {
+ deallocWord16(bv16->encoder.bs, 0, sizebitstream/2-1);
+ bv16->encoder.bs = tsk_null;
+ }
+ if(bv16->encoder.x) {
+ deallocWord16(bv16->encoder.x, 0, FRSZ-1);
+ bv16->encoder.x = tsk_null;
+ }
+
+ if(bv16->decoder.state) {
+ deallocWord16(bv16->decoder.state, 0, sizestate/2-1);
+ bv16->decoder.state = tsk_null;
+ }
+ if(bv16->encoder.bs) {
+ deallocWord16(bv16->decoder.bs, 0, sizebitstream/2-1);
+ bv16->decoder.bs = tsk_null;
+ }
+ if(bv16->decoder.x) {
+ deallocWord16(bv16->decoder.x, 0, FRSZ-1);
+ bv16->decoder.x = tsk_null;
+ }
+
+
+
+ return 0;
}
tsk_size_t tdav_codec_bv16_encode(tmedia_codec_t* self, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size)
-{
- //tsk_size_t out_size = 0;
- tdav_codec_bv16_t* bv16 = (tdav_codec_bv16_t*)self;
+{
+ //tsk_size_t out_size = 0;
+ tdav_codec_bv16_t* bv16 = (tdav_codec_bv16_t*)self;
- if(!self || !in_data || !in_size || !out_data){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
+ if(!self || !in_data || !in_size || !out_data) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
- return 0;
+ return 0;
}
tsk_size_t tdav_codec_bv16_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)
{
- tsk_size_t out_size = 0;
- int i;
- tdav_codec_bv16_t* bv16 = (tdav_codec_bv16_t*)self;
- uint8_t mama[600];
-
- if(!self || !in_data || !in_size || !out_data || (in_size % TDAV_BV16_FRAME_SIZE)){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- for(i=0; i<(int)in_size; i+=TDAV_BV16_FRAME_SIZE){
- BV16_BitUnPack(mama, (struct BV16_Bit_Stream*)bv16->decoder.bs);
- //BV16_BitUnPack(&((UWord8 *)in_data)[i], (struct BV16_Bit_Stream*)bv16->decoder.bs);
- BV16_Decode((struct BV16_Bit_Stream*)bv16->decoder.bs, (struct BV16_Decoder_State*)bv16->decoder.state, bv16->decoder.x);
-
-
- if(*out_max_size<(out_size + FRSZ_IN_U8)){
- if(!(*out_data = tsk_realloc(*out_data, (out_size + FRSZ_IN_U8)))){
- TSK_DEBUG_ERROR("Failed to allocate new buffer");
- *out_max_size = 0;
- return 0;
- }
- *out_max_size = (out_size + FRSZ_IN_U8);
- }
- memcpy(&((uint8_t*)* out_data)[out_size], bv16->decoder.x, FRSZ_IN_U8);
- out_size += FRSZ_IN_U8;
- }
-
-
- return out_size;
+ tsk_size_t out_size = 0;
+ int i;
+ tdav_codec_bv16_t* bv16 = (tdav_codec_bv16_t*)self;
+ uint8_t mama[600];
+
+ if(!self || !in_data || !in_size || !out_data || (in_size % TDAV_BV16_FRAME_SIZE)) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ for(i=0; i<(int)in_size; i+=TDAV_BV16_FRAME_SIZE) {
+ BV16_BitUnPack(mama, (struct BV16_Bit_Stream*)bv16->decoder.bs);
+ //BV16_BitUnPack(&((UWord8 *)in_data)[i], (struct BV16_Bit_Stream*)bv16->decoder.bs);
+ BV16_Decode((struct BV16_Bit_Stream*)bv16->decoder.bs, (struct BV16_Decoder_State*)bv16->decoder.state, bv16->decoder.x);
+
+
+ if(*out_max_size<(out_size + FRSZ_IN_U8)) {
+ if(!(*out_data = tsk_realloc(*out_data, (out_size + FRSZ_IN_U8)))) {
+ TSK_DEBUG_ERROR("Failed to allocate new buffer");
+ *out_max_size = 0;
+ return 0;
+ }
+ *out_max_size = (out_size + FRSZ_IN_U8);
+ }
+ memcpy(&((uint8_t*)* out_data)[out_size], bv16->decoder.x, FRSZ_IN_U8);
+ out_size += FRSZ_IN_U8;
+ }
+
+
+ return out_size;
}
tsk_bool_t tdav_codec_bv16_sdp_att_match(const tmedia_codec_t* codec, const char* att_name, const char* att_value)
-{ /* always match */
- return tsk_true;
+{
+ /* always match */
+ return tsk_true;
}
@@ -187,62 +188,60 @@ tsk_bool_t tdav_codec_bv16_sdp_att_match(const tmedia_codec_t* codec, const char
/* constructor */
static tsk_object_t* tdav_codec_bv16_ctor(tsk_object_t * self, va_list * app)
{
- tdav_codec_bv16_t *bv16 = self;
- if(bv16){
- /* init base: called by tmedia_codec_create() */
- /* init self */
- }
- return self;
+ tdav_codec_bv16_t *bv16 = self;
+ if(bv16) {
+ /* init base: called by tmedia_codec_create() */
+ /* init self */
+ }
+ return self;
}
/* destructor */
static tsk_object_t* tdav_codec_bv16_dtor(tsk_object_t * self)
-{
- tdav_codec_bv16_t *bv16 = self;
- if(bv16){
- /* deinit base */
- tmedia_codec_audio_deinit(bv16);
- /* deinit self */
-
- }
-
- return self;
+{
+ tdav_codec_bv16_t *bv16 = self;
+ if(bv16) {
+ /* deinit base */
+ tmedia_codec_audio_deinit(bv16);
+ /* deinit self */
+
+ }
+
+ return self;
}
/* object definition */
-static const tsk_object_def_t tdav_codec_bv16_def_s =
-{
- sizeof(tdav_codec_bv16_t),
- tdav_codec_bv16_ctor,
- tdav_codec_bv16_dtor,
- tmedia_codec_cmp,
+static const tsk_object_def_t tdav_codec_bv16_def_s = {
+ sizeof(tdav_codec_bv16_t),
+ tdav_codec_bv16_ctor,
+ tdav_codec_bv16_dtor,
+ tmedia_codec_cmp,
};
/* plugin definition*/
-static const tmedia_codec_plugin_def_t tdav_codec_bv16_plugin_def_s =
-{
- &tdav_codec_bv16_def_s,
-
- tmedia_audio,
- tmedia_codec_id_bv16,
- "BV16",
- "BroadVoice16 Rate",
- TMEDIA_CODEC_FORMAT_BV16,
- tsk_true,
- 8000, // rate
-
- { /* audio */
- 1, // channels
- 0 // ptime @deprecated
- },
-
- /* video */
- {0},
-
- tdav_codec_bv16_open,
- tdav_codec_bv16_close,
- tdav_codec_bv16_encode,
- tdav_codec_bv16_decode,
- tdav_codec_bv16_sdp_att_match,
- tdav_codec_bv16_sdp_att_get,
- tdav_codec_bv16_fmtp_set
+static const tmedia_codec_plugin_def_t tdav_codec_bv16_plugin_def_s = {
+ &tdav_codec_bv16_def_s,
+
+ tmedia_audio,
+ tmedia_codec_id_bv16,
+ "BV16",
+ "BroadVoice16 Rate",
+ TMEDIA_CODEC_FORMAT_BV16,
+ tsk_true,
+ 8000, // rate
+
+ { /* audio */
+ 1, // channels
+ 0 // ptime @deprecated
+ },
+
+ /* video */
+ {0},
+
+ tdav_codec_bv16_open,
+ tdav_codec_bv16_close,
+ tdav_codec_bv16_encode,
+ tdav_codec_bv16_decode,
+ tdav_codec_bv16_sdp_att_match,
+ tdav_codec_bv16_sdp_att_get,
+ tdav_codec_bv16_fmtp_set
};
const tmedia_codec_plugin_def_t *tdav_codec_bv16_plugin_def_t = &tdav_codec_bv16_plugin_def_s;
diff --git a/tinyDAV/src/codecs/dtmf/tdav_codec_dtmf.c b/tinyDAV/src/codecs/dtmf/tdav_codec_dtmf.c
index 103ac8d..6fec2d4 100755
--- a/tinyDAV/src/codecs/dtmf/tdav_codec_dtmf.c
+++ b/tinyDAV/src/codecs/dtmf/tdav_codec_dtmf.c
@@ -2,19 +2,19 @@
* Copyright (C) 2010-2011 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.
*
@@ -38,25 +38,26 @@
tsk_size_t tdav_codec_dtmf_fmtp_encode(tmedia_codec_t* self, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size)
{
- return 0;
+ return 0;
}
tsk_size_t tdav_codec_dtmf_fmtp_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)
{
- return 0;
+ return 0;
}
char* tdav_codec_dtmf_sdp_att_get(const tmedia_codec_t* self, const char* att_name)
{
- if(tsk_striequals(att_name, "fmtp")){
- return tsk_strdup("0-16");
- }
- return tsk_null;
+ if(tsk_striequals(att_name, "fmtp")) {
+ return tsk_strdup("0-16");
+ }
+ return tsk_null;
}
tsk_bool_t tdav_codec_dtmf_sdp_att_match(const tmedia_codec_t* codec, const char* att_name, const char* att_value)
-{ /* always match */
- return tsk_true;
+{
+ /* always match */
+ return tsk_true;
}
@@ -67,60 +68,58 @@ tsk_bool_t tdav_codec_dtmf_sdp_att_match(const tmedia_codec_t* codec, const char
/* constructor */
static tsk_object_t* tdav_codec_dtmf_ctor(tsk_object_t * self, va_list * app)
{
- tdav_codec_dtmf_t *dtmf = self;
- if(dtmf){
- /* init base: called by tmedia_codec_create() */
- /* init self */
- }
- return self;
+ tdav_codec_dtmf_t *dtmf = self;
+ if(dtmf) {
+ /* init base: called by tmedia_codec_create() */
+ /* init self */
+ }
+ return self;
}
/* destructor */
static tsk_object_t* tdav_codec_dtmf_dtor(tsk_object_t * self)
-{
- tdav_codec_dtmf_t *dtmf = self;
- if(dtmf){
- /* deinit base */
- tmedia_codec_audio_deinit(dtmf);
- /* deinit self */
- }
-
- return self;
+{
+ tdav_codec_dtmf_t *dtmf = self;
+ if(dtmf) {
+ /* deinit base */
+ tmedia_codec_audio_deinit(dtmf);
+ /* deinit self */
+ }
+
+ return self;
}
/* object definition */
-static const tsk_object_def_t tdav_codec_dtmf_def_s =
-{
- sizeof(tdav_codec_dtmf_t),
- tdav_codec_dtmf_ctor,
- tdav_codec_dtmf_dtor,
- tmedia_codec_cmp,
+static const tsk_object_def_t tdav_codec_dtmf_def_s = {
+ sizeof(tdav_codec_dtmf_t),
+ tdav_codec_dtmf_ctor,
+ tdav_codec_dtmf_dtor,
+ tmedia_codec_cmp,
};
/* plugin definition*/
-static const tmedia_codec_plugin_def_t tdav_codec_dtmf_plugin_def_s =
-{
- &tdav_codec_dtmf_def_s,
-
- tmedia_audio,
- tmedia_codec_id_none, // fake codec without real identifier
- "telephone-event",
- "DTMF Codec (RFC 4733)",
- TMEDIA_CODEC_FORMAT_DTMF,
- tsk_true,
- 8000, // rate
-
- { /* audio */
- 1, // channels
- 20 // ptime
- },
-
- /* video */
- {0},
-
- tsk_null, // set()
- tsk_null, // open
- tsk_null, // close
- tdav_codec_dtmf_fmtp_encode,
- tdav_codec_dtmf_fmtp_decode,
- tdav_codec_dtmf_sdp_att_match,
- tdav_codec_dtmf_sdp_att_get
+static const tmedia_codec_plugin_def_t tdav_codec_dtmf_plugin_def_s = {
+ &tdav_codec_dtmf_def_s,
+
+ tmedia_audio,
+ tmedia_codec_id_none, // fake codec without real identifier
+ "telephone-event",
+ "DTMF Codec (RFC 4733)",
+ TMEDIA_CODEC_FORMAT_DTMF,
+ tsk_true,
+ 8000, // rate
+
+ { /* audio */
+ 1, // channels
+ 20 // ptime
+ },
+
+ /* video */
+ {0},
+
+ tsk_null, // set()
+ tsk_null, // open
+ tsk_null, // close
+ tdav_codec_dtmf_fmtp_encode,
+ tdav_codec_dtmf_fmtp_decode,
+ tdav_codec_dtmf_sdp_att_match,
+ tdav_codec_dtmf_sdp_att_get
};
const tmedia_codec_plugin_def_t *tdav_codec_dtmf_plugin_def_t = &tdav_codec_dtmf_plugin_def_s;
diff --git a/tinyDAV/src/codecs/fec/tdav_codec_red.c b/tinyDAV/src/codecs/fec/tdav_codec_red.c
index 2fb6f27..cf92173 100755
--- a/tinyDAV/src/codecs/fec/tdav_codec_red.c
+++ b/tinyDAV/src/codecs/fec/tdav_codec_red.c
@@ -2,19 +2,19 @@
* Copyright (C) 2012 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.
*
@@ -31,171 +31,174 @@
#include "tsk_time.h"
#include "tsk_debug.h"
-typedef struct tdav_codec_red_s
-{
- TMEDIA_DECLARE_CODEC_VIDEO;
+typedef struct tdav_codec_red_s {
+ TMEDIA_DECLARE_CODEC_VIDEO;
- tdav_codec_red_rtppacket_cb_f callback;
- const void* callback_data;
+ tdav_codec_red_rtppacket_cb_f callback;
+ const void* callback_data;
}
tdav_codec_red_t;
int tdav_codec_red_set_callback(tdav_codec_red_t *self, tdav_codec_red_rtppacket_cb_f callback, const void* callback_data)
{
- if(!self){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
+ if(!self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
- self->callback = callback;
- self->callback_data = callback_data;
+ self->callback = callback;
+ self->callback_data = callback_data;
- return 0;
+ return 0;
}
static int tdav_codec_red_open(tmedia_codec_t* self)
{
- return 0;
+ return 0;
}
static int tdav_codec_red_close(tmedia_codec_t* self)
{
- return 0;
+ return 0;
}
static tsk_size_t tdav_codec_red_encode(tmedia_codec_t* self, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size)
{
- tdav_codec_red_t *red = (tdav_codec_red_t *)self;
- tsk_size_t xsize = (in_size + 1);
- static const uint8_t __first_octet = 0x00; // F=1, PT=0. Up to the caller to update this first octet with the right PT.
-
- if(!red || !in_data || !in_size || !out_data || !out_max_size){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- if(*out_max_size < xsize){
- if(!(*out_data = tsk_realloc(*out_data, xsize))){
- TSK_DEBUG_ERROR("Failed to realloc data");
- *out_max_size = 0;
- }
- *out_max_size = xsize;
- }
-
- ((uint8_t*)*out_data)[0] = __first_octet;
- memcpy(&((uint8_t*)*out_data)[1], in_data, in_size);
-
- return xsize;
+ tdav_codec_red_t *red = (tdav_codec_red_t *)self;
+ tsk_size_t xsize = (in_size + 1);
+ static const uint8_t __first_octet = 0x00; // F=1, PT=0. Up to the caller to update this first octet with the right PT.
+
+ if(!red || !in_data || !in_size || !out_data || !out_max_size) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ if(*out_max_size < xsize) {
+ if(!(*out_data = tsk_realloc(*out_data, xsize))) {
+ TSK_DEBUG_ERROR("Failed to realloc data");
+ *out_max_size = 0;
+ }
+ *out_max_size = xsize;
+ }
+
+ ((uint8_t*)*out_data)[0] = __first_octet;
+ memcpy(&((uint8_t*)*out_data)[1], in_data, in_size);
+
+ return xsize;
}
static tsk_size_t tdav_codec_red_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)
{
- tdav_codec_red_t* red = (tdav_codec_red_t*)self;
- const trtp_rtp_header_t* rtp_hdr = proto_hdr;
- trtp_rtp_packet_t* red_rtp_pkt = tsk_null;
- const uint8_t* pdata = in_data;
- const uint8_t* red_hdr = in_data;
- tsk_size_t red_hdrs_count, i;
- tsk_bool_t last;
- uint8_t F;
- uint16_t timestamp_offset, block_length;
-
- if(!red || !in_data || (in_size < TDAV_CODEC_RED_MIN_PKT_SIZE)|| !out_data){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- if(!red->callback){
- TSK_DEBUG_WARN("Not callback installed for RED data");
- return 0;
- }
-
- if((F = (pdata[0] & 0x80)) == 0){
- i = 1;
- red_hdrs_count = 1;
- }
- else{
- for(i = 0, red_hdrs_count = 0; i < in_size; i+= 4, ++red_hdrs_count){
- if((F = (pdata[i] & 0x80)) == 0){ ++i; ++red_hdrs_count; break; }
- }
- }
-
- if(i >= in_size){
- TSK_DEBUG_ERROR("Invalid data");
- return 0;
- }
-
- pdata += i;
- in_size -= i;
-
- for(i = 0; i < red_hdrs_count && in_size > 0; ++i){
- TSK_OBJECT_SAFE_FREE(red_rtp_pkt);
- if(!(red_rtp_pkt = trtp_rtp_packet_create_null())){
- TSK_DEBUG_ERROR("Failed to create RTP packet");
- continue;
- }
- if(!(red_rtp_pkt->header = trtp_rtp_header_create(rtp_hdr->ssrc, rtp_hdr->seq_num, rtp_hdr->timestamp, rtp_hdr->payload_type, rtp_hdr->marker))){
- TSK_DEBUG_ERROR("Failed to create RTP header");
- continue;
- }
-
- // Must create an RTP packet for each RED chunck as they will be saved in the JB
- last = (i == (red_hdrs_count - 1));
- F = (red_hdr[0] & 0x80);
- red_rtp_pkt->header->payload_type = (red_hdr[0] & 0x7F);
-
- if(last || !F){
- /*
- 0 1 2 3 4 5 6 7
+ tdav_codec_red_t* red = (tdav_codec_red_t*)self;
+ const trtp_rtp_header_t* rtp_hdr = proto_hdr;
+ trtp_rtp_packet_t* red_rtp_pkt = tsk_null;
+ const uint8_t* pdata = in_data;
+ const uint8_t* red_hdr = in_data;
+ tsk_size_t red_hdrs_count, i;
+ tsk_bool_t last;
+ uint8_t F;
+ uint16_t timestamp_offset, block_length;
+
+ if(!red || !in_data || (in_size < TDAV_CODEC_RED_MIN_PKT_SIZE)|| !out_data) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ if(!red->callback) {
+ TSK_DEBUG_WARN("Not callback installed for RED data");
+ return 0;
+ }
+
+ if((F = (pdata[0] & 0x80)) == 0) {
+ i = 1;
+ red_hdrs_count = 1;
+ }
+ else {
+ for(i = 0, red_hdrs_count = 0; i < in_size; i+= 4, ++red_hdrs_count) {
+ if((F = (pdata[i] & 0x80)) == 0) {
+ ++i;
+ ++red_hdrs_count;
+ break;
+ }
+ }
+ }
+
+ if(i >= in_size) {
+ TSK_DEBUG_ERROR("Invalid data");
+ return 0;
+ }
+
+ pdata += i;
+ in_size -= i;
+
+ for(i = 0; i < red_hdrs_count && in_size > 0; ++i) {
+ TSK_OBJECT_SAFE_FREE(red_rtp_pkt);
+ if(!(red_rtp_pkt = trtp_rtp_packet_create_null())) {
+ TSK_DEBUG_ERROR("Failed to create RTP packet");
+ continue;
+ }
+ if(!(red_rtp_pkt->header = trtp_rtp_header_create(rtp_hdr->ssrc, rtp_hdr->seq_num, rtp_hdr->timestamp, rtp_hdr->payload_type, rtp_hdr->marker))) {
+ TSK_DEBUG_ERROR("Failed to create RTP header");
+ continue;
+ }
+
+ // Must create an RTP packet for each RED chunck as they will be saved in the JB
+ last = (i == (red_hdrs_count - 1));
+ F = (red_hdr[0] & 0x80);
+ red_rtp_pkt->header->payload_type = (red_hdr[0] & 0x7F);
+
+ if(last || !F) {
+ /*
+ 0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+
|0| Block PT |
+-+-+-+-+-+-+-+-+
- */
- block_length = (uint16_t)in_size;
- }
- else{
- /*
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- |1| block PT=7 | timestamp offset | block length |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
- timestamp_offset = ((red_hdr[1] << 8) | red_hdr[2]) >> 2;
- block_length = ((red_hdr[2] & 0x03) << 8) | red_hdr[3];
- if(block_length > in_size){
- TSK_DEBUG_ERROR("Invalid 'block length'");
- break;
- }
- red_rtp_pkt->header->timestamp += timestamp_offset;
- red_hdr += 4;
- }
-
- // decode
- if(red->callback){
- // do not use "data_const" as payload will be saved in the jitter buffer and decoded later (async)
- if((red_rtp_pkt->payload.data = tsk_malloc(block_length))){
- memcpy(red_rtp_pkt->payload.data, pdata, block_length);
- red_rtp_pkt->payload.size = block_length;
- red->callback(red->callback_data, red_rtp_pkt);
- }
- }
-
- pdata += block_length;
- in_size -= block_length;
- }
-
- TSK_OBJECT_SAFE_FREE(red_rtp_pkt);
-
- return 0; // must be always zero
+ */
+ block_length = (uint16_t)in_size;
+ }
+ else {
+ /*
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |1| block PT=7 | timestamp offset | block length |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+ timestamp_offset = ((red_hdr[1] << 8) | red_hdr[2]) >> 2;
+ block_length = ((red_hdr[2] & 0x03) << 8) | red_hdr[3];
+ if(block_length > in_size) {
+ TSK_DEBUG_ERROR("Invalid 'block length'");
+ break;
+ }
+ red_rtp_pkt->header->timestamp += timestamp_offset;
+ red_hdr += 4;
+ }
+
+ // decode
+ if(red->callback) {
+ // do not use "data_const" as payload will be saved in the jitter buffer and decoded later (async)
+ if((red_rtp_pkt->payload.data = tsk_malloc(block_length))) {
+ memcpy(red_rtp_pkt->payload.data, pdata, block_length);
+ red_rtp_pkt->payload.size = block_length;
+ red->callback(red->callback_data, red_rtp_pkt);
+ }
+ }
+
+ pdata += block_length;
+ in_size -= block_length;
+ }
+
+ TSK_OBJECT_SAFE_FREE(red_rtp_pkt);
+
+ return 0; // must be always zero
}
static tsk_bool_t tdav_codec_red_sdp_att_match(const tmedia_codec_t* codec, const char* att_name, const char* att_value)
{
- return tsk_true;
+ return tsk_true;
}
static char* tdav_codec_red_sdp_att_get(const tmedia_codec_t* self, const char* att_name)
{
- return tsk_null;
+ return tsk_null;
}
@@ -204,60 +207,58 @@ static char* tdav_codec_red_sdp_att_get(const tmedia_codec_t* self, const char*
/* constructor */
static tsk_object_t* tdav_codec_red_ctor(tsk_object_t * self, va_list * app)
{
- tdav_codec_red_t *red = self;
- if(red){
- /* init base: called by tmedia_codec_create() */
- /* init self */
-
- }
- return self;
+ tdav_codec_red_t *red = self;
+ if(red) {
+ /* init base: called by tmedia_codec_create() */
+ /* init self */
+
+ }
+ return self;
}
/* destructor */
static tsk_object_t* tdav_codec_red_dtor(tsk_object_t * self)
-{
- tdav_codec_red_t *red = self;
- if(red){
- /* deinit base */
- tmedia_codec_video_deinit(red);
- /* deinit self */
-
- }
-
- return self;
+{
+ tdav_codec_red_t *red = self;
+ if(red) {
+ /* deinit base */
+ tmedia_codec_video_deinit(red);
+ /* deinit self */
+
+ }
+
+ return self;
}
/* object definition */
-static const tsk_object_def_t tdav_codec_red_def_s =
-{
- sizeof(tdav_codec_red_t),
- tdav_codec_red_ctor,
- tdav_codec_red_dtor,
- tmedia_codec_cmp,
+static const tsk_object_def_t tdav_codec_red_def_s = {
+ sizeof(tdav_codec_red_t),
+ tdav_codec_red_ctor,
+ tdav_codec_red_dtor,
+ tmedia_codec_cmp,
};
/* plugin definition*/
-static const tmedia_codec_plugin_def_t tdav_codec_red_plugin_def_s =
-{
- &tdav_codec_red_def_s,
-
- (/* tmedia_video | tmedia_audio | */tmedia_t140), // FIXME: for now is only supported with T.140
- tmedia_codec_id_red,
- "red",
- "red codec",
- TMEDIA_CODEC_FORMAT_RED,
- tsk_true,
- 1000, // rate: FIXME: for now it's only for T.140
-
- /* audio */
- { 0 },
-
- /* video (defaul width,height,fps) */
- {176, 144, 15},
-
- tsk_null, // set()
- tdav_codec_red_open,
- tdav_codec_red_close,
- tdav_codec_red_encode,
- tdav_codec_red_decode,
- tdav_codec_red_sdp_att_match,
- tdav_codec_red_sdp_att_get
+static const tmedia_codec_plugin_def_t tdav_codec_red_plugin_def_s = {
+ &tdav_codec_red_def_s,
+
+ (/* tmedia_video | tmedia_audio | */tmedia_t140), // FIXME: for now is only supported with T.140
+ tmedia_codec_id_red,
+ "red",
+ "red codec",
+ TMEDIA_CODEC_FORMAT_RED,
+ tsk_true,
+ 1000, // rate: FIXME: for now it's only for T.140
+
+ /* audio */
+ { 0 },
+
+ /* video (defaul width,height,fps) */
+ {176, 144, 15},
+
+ tsk_null, // set()
+ tdav_codec_red_open,
+ tdav_codec_red_close,
+ tdav_codec_red_encode,
+ tdav_codec_red_decode,
+ tdav_codec_red_sdp_att_match,
+ tdav_codec_red_sdp_att_get
};
const tmedia_codec_plugin_def_t *tdav_codec_red_plugin_def_t = &tdav_codec_red_plugin_def_s;
diff --git a/tinyDAV/src/codecs/fec/tdav_codec_ulpfec.c b/tinyDAV/src/codecs/fec/tdav_codec_ulpfec.c
index f492a52..0e78b6a 100755
--- a/tinyDAV/src/codecs/fec/tdav_codec_ulpfec.c
+++ b/tinyDAV/src/codecs/fec/tdav_codec_ulpfec.c
@@ -31,57 +31,54 @@
#define TDAV_FEC_PKT_HDR_SIZE 10
-typedef struct tdav_codec_ulpfec_s
-{
- TMEDIA_DECLARE_CODEC_VIDEO;
+typedef struct tdav_codec_ulpfec_s {
+ TMEDIA_DECLARE_CODEC_VIDEO;
- struct{
- struct tdav_fec_pkt_s* pkt;
- } encoder;
+ struct {
+ struct tdav_fec_pkt_s* pkt;
+ } encoder;
}
tdav_codec_ulpfec_t;
//
// FEC LEVEL
//
-typedef struct tdav_fec_level_s
-{
- TSK_DECLARE_OBJECT;
-
- struct{ // 7.4. FEC Level Header for FEC Packets
- uint16_t length;
- uint64_t mask;
- tsk_size_t mask_size; // in bits
- } hdr;
- struct{
- uint8_t* ptr;
- tsk_size_t size;
- }payload;
-}tdav_fec_level_t;
+typedef struct tdav_fec_level_s {
+ TSK_DECLARE_OBJECT;
+
+ struct { // 7.4. FEC Level Header for FEC Packets
+ uint16_t length;
+ uint64_t mask;
+ tsk_size_t mask_size; // in bits
+ } hdr;
+ struct {
+ uint8_t* ptr;
+ tsk_size_t size;
+ } payload;
+} tdav_fec_level_t;
typedef tsk_list_t tdav_fec_levels_L_t;
static tsk_object_t* tdav_fec_level_ctor(tsk_object_t * self, va_list * app)
{
- tdav_fec_level_t *level = self;
- if (level){
- level->hdr.mask_size = 16; // L=0
- }
- return self;
+ tdav_fec_level_t *level = self;
+ if (level) {
+ level->hdr.mask_size = 16; // L=0
+ }
+ return self;
}
static tsk_object_t* tdav_fec_level_dtor(tsk_object_t * self)
{
- tdav_fec_level_t *level = self;
- if (level){
- TSK_FREE(level->payload.ptr);
- }
+ tdav_fec_level_t *level = self;
+ if (level) {
+ TSK_FREE(level->payload.ptr);
+ }
- return self;
+ return self;
}
-static const tsk_object_def_t tdav_fec_level_def_s =
-{
- sizeof(tdav_fec_level_t),
- tdav_fec_level_ctor,
- tdav_fec_level_dtor,
- tsk_null,
+static const tsk_object_def_t tdav_fec_level_def_s = {
+ sizeof(tdav_fec_level_t),
+ tdav_fec_level_ctor,
+ tdav_fec_level_dtor,
+ tsk_null,
};
const tsk_object_def_t *tdav_fec_level_def_t = &tdav_fec_level_def_s;
@@ -89,271 +86,274 @@ const tsk_object_def_t *tdav_fec_level_def_t = &tdav_fec_level_def_s;
//
// FEC PACKET
//
-typedef struct tdav_fec_pkt_s
-{
- TSK_DECLARE_OBJECT;
-
- struct{ // RFC 5109 - 7.3. FEC Header for FEC Packets
- unsigned E : 1;
- unsigned L : 1;
- unsigned P : 1;
- unsigned X : 1;
- unsigned CC : 4;
- unsigned M : 1;
- unsigned PT : 7;
- struct{
- uint16_t value;
- unsigned set : 1;
- }SN_base;
- uint32_t TS;
- uint16_t length;
- }hdr;
-
- tdav_fec_levels_L_t* levels;
+typedef struct tdav_fec_pkt_s {
+ TSK_DECLARE_OBJECT;
+
+ struct { // RFC 5109 - 7.3. FEC Header for FEC Packets
+ unsigned E : 1;
+ unsigned L : 1;
+ unsigned P : 1;
+ unsigned X : 1;
+ unsigned CC : 4;
+ unsigned M : 1;
+ unsigned PT : 7;
+ struct {
+ uint16_t value;
+ unsigned set : 1;
+ } SN_base;
+ uint32_t TS;
+ uint16_t length;
+ } hdr;
+
+ tdav_fec_levels_L_t* levels;
}
tdav_fec_pkt_t;
static tsk_object_t* tdav_fec_pkt_ctor(tsk_object_t * self, va_list * app)
{
- tdav_fec_pkt_t *pkt = self;
- if (pkt){
- if (!(pkt->levels = tsk_list_create())){
- TSK_DEBUG_ERROR("Failed to create levels");
- return tsk_null;
- }
- }
- return self;
+ tdav_fec_pkt_t *pkt = self;
+ if (pkt) {
+ if (!(pkt->levels = tsk_list_create())) {
+ TSK_DEBUG_ERROR("Failed to create levels");
+ return tsk_null;
+ }
+ }
+ return self;
}
static tsk_object_t* tdav_fec_pkt_dtor(tsk_object_t * self)
{
- tdav_fec_pkt_t *pkt = self;
- if (pkt){
- TSK_OBJECT_SAFE_FREE(pkt->levels);
- }
+ tdav_fec_pkt_t *pkt = self;
+ if (pkt) {
+ TSK_OBJECT_SAFE_FREE(pkt->levels);
+ }
- return self;
+ return self;
}
static int tdav_fec_pkt_cmp(const tsk_object_t *_p1, const tsk_object_t *_p2)
{
- const tdav_fec_pkt_t *p1 = _p1;
- const tdav_fec_pkt_t *p2 = _p2;
-
- if (p1 && p2){
- return (int)(p1->hdr.SN_base.value - p2->hdr.SN_base.value);
- }
- else if (!p1 && !p2) return 0;
- else return -1;
+ const tdav_fec_pkt_t *p1 = _p1;
+ const tdav_fec_pkt_t *p2 = _p2;
+
+ if (p1 && p2) {
+ return (int)(p1->hdr.SN_base.value - p2->hdr.SN_base.value);
+ }
+ else if (!p1 && !p2) {
+ return 0;
+ }
+ else {
+ return -1;
+ }
}
-static const tsk_object_def_t tdav_fec_pkt_def_s =
-{
- sizeof(tdav_fec_pkt_t),
- tdav_fec_pkt_ctor,
- tdav_fec_pkt_dtor,
- tdav_fec_pkt_cmp,
+static const tsk_object_def_t tdav_fec_pkt_def_s = {
+ sizeof(tdav_fec_pkt_t),
+ tdav_fec_pkt_ctor,
+ tdav_fec_pkt_dtor,
+ tdav_fec_pkt_cmp,
};
const tsk_object_def_t *tdav_fec_pkt_def_t = &tdav_fec_pkt_def_s;
tsk_size_t tdav_codec_ulpfec_guess_serialbuff_size(const tdav_codec_ulpfec_t* self)
{
- tsk_size_t size = TDAV_FEC_PKT_HDR_SIZE;
- tsk_list_item_t *item;
- tdav_fec_level_t* level;
-
- if (!self){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- tsk_list_foreach(item, self->encoder.pkt->levels){
- if (!(level = item->data)){
- continue;
- }
- size += 2 /* Protection length */ + (level->hdr.mask_size >> 3) + level->hdr.length;
- }
-
- return size;
+ tsk_size_t size = TDAV_FEC_PKT_HDR_SIZE;
+ tsk_list_item_t *item;
+ tdav_fec_level_t* level;
+
+ if (!self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ tsk_list_foreach(item, self->encoder.pkt->levels) {
+ if (!(level = item->data)) {
+ continue;
+ }
+ size += 2 /* Protection length */ + (level->hdr.mask_size >> 3) + level->hdr.length;
+ }
+
+ return size;
}
int tdav_codec_ulpfec_enc_reset(tdav_codec_ulpfec_t* self)
{
- tsk_list_item_t *item;
- tdav_fec_level_t* level;
-
- if (!self || !self->encoder.pkt){
- TSK_DEBUG_ERROR("invalid parameter");
- return -1;
- }
-
- // reset packet
- memset(&self->encoder.pkt->hdr, 0, sizeof(self->encoder.pkt->hdr));
-
- // reset levels
- tsk_list_foreach(item, self->encoder.pkt->levels){
- if ((level = item->data)){
- memset(&level->hdr, 0, sizeof(level->hdr));
- if (level->payload.ptr){
- memset(level->payload.ptr, 0, level->payload.size);
- }
- }
- }
- return 0;
+ tsk_list_item_t *item;
+ tdav_fec_level_t* level;
+
+ if (!self || !self->encoder.pkt) {
+ TSK_DEBUG_ERROR("invalid parameter");
+ return -1;
+ }
+
+ // reset packet
+ memset(&self->encoder.pkt->hdr, 0, sizeof(self->encoder.pkt->hdr));
+
+ // reset levels
+ tsk_list_foreach(item, self->encoder.pkt->levels) {
+ if ((level = item->data)) {
+ memset(&level->hdr, 0, sizeof(level->hdr));
+ if (level->payload.ptr) {
+ memset(level->payload.ptr, 0, level->payload.size);
+ }
+ }
+ }
+ return 0;
}
int tdav_codec_ulpfec_enc_protect(tdav_codec_ulpfec_t* self, const trtp_rtp_packet_t* rtp_packet)
{
- if (!self || !self->encoder.pkt || !rtp_packet || !rtp_packet->header){
- TSK_DEBUG_ERROR("invalid parameter");
- return -1;
- }
-
- // Packet
- self->encoder.pkt->hdr.P ^= rtp_packet->header->padding;
- self->encoder.pkt->hdr.X ^= rtp_packet->header->extension;
- self->encoder.pkt->hdr.CC ^= rtp_packet->header->csrc_count;
- self->encoder.pkt->hdr.M ^= rtp_packet->header->marker;
- self->encoder.pkt->hdr.PT ^= rtp_packet->header->payload_type;
- if (!self->encoder.pkt->hdr.SN_base.set){
- self->encoder.pkt->hdr.SN_base.value = rtp_packet->header->seq_num;
- self->encoder.pkt->hdr.SN_base.set = 1;
- }
- else{
- self->encoder.pkt->hdr.SN_base.value = TSK_MIN(self->encoder.pkt->hdr.SN_base.value, rtp_packet->header->seq_num);
- }
- self->encoder.pkt->hdr.TS ^= rtp_packet->header->timestamp;
- self->encoder.pkt->hdr.length ^= (trtp_rtp_packet_guess_serialbuff_size(rtp_packet) - TRTP_RTP_HEADER_MIN_SIZE);
-
- // Level
- // For now, always single-level protection
- {
- tdav_fec_level_t* level0 = TSK_LIST_FIRST_DATA(self->encoder.pkt->levels);
- const uint8_t* rtp_payload = (const uint8_t*)(rtp_packet->payload.data_const ? rtp_packet->payload.data_const : rtp_packet->payload.data);
- tsk_size_t i;
- if (!level0){
- tdav_fec_level_t* _level0;
- if (!(_level0 = tsk_object_new(tdav_fec_level_def_t))){
- TSK_DEBUG_ERROR("Failed to create level");
- return -2;
- }
- level0 = _level0;
- tsk_list_push_back_data(self->encoder.pkt->levels, (void**)&_level0);
- }
- if (level0->payload.size < rtp_packet->payload.size){
- if (!(level0->payload.ptr = tsk_realloc(level0->payload.ptr, rtp_packet->payload.size))){
- TSK_DEBUG_ERROR("Failed to realloc size %d", rtp_packet->payload.size);
- level0->payload.size = 0;
- return -3;
- }
- level0->payload.size = rtp_packet->payload.size;
- }
- for (i = 0; i < rtp_packet->payload.size; ++i){
- level0->payload.ptr[i] ^= rtp_payload[i];
- }
- level0->hdr.mask_size = self->encoder.pkt->hdr.L ? 48 : 16;
- level0->hdr.mask |= (uint64_t)((uint64_t)1 << (level0->hdr.mask_size - (rtp_packet->header->seq_num - self->encoder.pkt->hdr.SN_base.value)));
- level0->hdr.length = (uint16_t)(TSK_MAX(level0->hdr.length, rtp_packet->payload.size));
- }
-
- return 0;
+ if (!self || !self->encoder.pkt || !rtp_packet || !rtp_packet->header) {
+ TSK_DEBUG_ERROR("invalid parameter");
+ return -1;
+ }
+
+ // Packet
+ self->encoder.pkt->hdr.P ^= rtp_packet->header->padding;
+ self->encoder.pkt->hdr.X ^= rtp_packet->header->extension;
+ self->encoder.pkt->hdr.CC ^= rtp_packet->header->csrc_count;
+ self->encoder.pkt->hdr.M ^= rtp_packet->header->marker;
+ self->encoder.pkt->hdr.PT ^= rtp_packet->header->payload_type;
+ if (!self->encoder.pkt->hdr.SN_base.set) {
+ self->encoder.pkt->hdr.SN_base.value = rtp_packet->header->seq_num;
+ self->encoder.pkt->hdr.SN_base.set = 1;
+ }
+ else {
+ self->encoder.pkt->hdr.SN_base.value = TSK_MIN(self->encoder.pkt->hdr.SN_base.value, rtp_packet->header->seq_num);
+ }
+ self->encoder.pkt->hdr.TS ^= rtp_packet->header->timestamp;
+ self->encoder.pkt->hdr.length ^= (trtp_rtp_packet_guess_serialbuff_size(rtp_packet) - TRTP_RTP_HEADER_MIN_SIZE);
+
+ // Level
+ // For now, always single-level protection
+ {
+ tdav_fec_level_t* level0 = TSK_LIST_FIRST_DATA(self->encoder.pkt->levels);
+ const uint8_t* rtp_payload = (const uint8_t*)(rtp_packet->payload.data_const ? rtp_packet->payload.data_const : rtp_packet->payload.data);
+ tsk_size_t i;
+ if (!level0) {
+ tdav_fec_level_t* _level0;
+ if (!(_level0 = tsk_object_new(tdav_fec_level_def_t))) {
+ TSK_DEBUG_ERROR("Failed to create level");
+ return -2;
+ }
+ level0 = _level0;
+ tsk_list_push_back_data(self->encoder.pkt->levels, (void**)&_level0);
+ }
+ if (level0->payload.size < rtp_packet->payload.size) {
+ if (!(level0->payload.ptr = tsk_realloc(level0->payload.ptr, rtp_packet->payload.size))) {
+ TSK_DEBUG_ERROR("Failed to realloc size %d", rtp_packet->payload.size);
+ level0->payload.size = 0;
+ return -3;
+ }
+ level0->payload.size = rtp_packet->payload.size;
+ }
+ for (i = 0; i < rtp_packet->payload.size; ++i) {
+ level0->payload.ptr[i] ^= rtp_payload[i];
+ }
+ level0->hdr.mask_size = self->encoder.pkt->hdr.L ? 48 : 16;
+ level0->hdr.mask |= (uint64_t)((uint64_t)1 << (level0->hdr.mask_size - (rtp_packet->header->seq_num - self->encoder.pkt->hdr.SN_base.value)));
+ level0->hdr.length = (uint16_t)(TSK_MAX(level0->hdr.length, rtp_packet->payload.size));
+ }
+
+ return 0;
}
tsk_size_t tdav_codec_ulpfec_enc_serialize(const tdav_codec_ulpfec_t* self, void** out_data, tsk_size_t* out_max_size)
{
- uint8_t* pdata;
- tsk_size_t xsize;
- int32_t i;
- tsk_list_item_t* item;
- tdav_fec_level_t* level;
-
- if (!self || !self->encoder.pkt || !out_data){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
- xsize = tdav_codec_ulpfec_guess_serialbuff_size(self);
-
- if (*out_max_size < xsize){
- if (!(*out_data = tsk_realloc(*out_data, xsize))){
- TSK_DEBUG_ERROR("Failed to reallocate buffer with size =%d", xsize);
- *out_max_size = 0;
- return 0;
- }
- *out_max_size = xsize;
- }
- pdata = (uint8_t*)*out_data;
-
- // E(1), L(1), P(1), X(1), CC(4)
- pdata[0] =
- (self->encoder.pkt->hdr.E << 7) |
- (self->encoder.pkt->hdr.L << 6) |
- (self->encoder.pkt->hdr.P << 5) |
- (self->encoder.pkt->hdr.X << 4) |
- (self->encoder.pkt->hdr.CC & 0x0F);
- // M(1), PT(7)
- pdata[1] = (self->encoder.pkt->hdr.M << 7) | (self->encoder.pkt->hdr.PT & 0x7F);
- // SN base (16)
- pdata[2] = (self->encoder.pkt->hdr.SN_base.value >> 8);
- pdata[3] = (self->encoder.pkt->hdr.SN_base.value & 0xFF);
- // TS (32)
- pdata[4] = self->encoder.pkt->hdr.TS >> 24;
- pdata[5] = (self->encoder.pkt->hdr.TS >> 16) & 0xFF;
- pdata[6] = (self->encoder.pkt->hdr.TS >> 8) & 0xFF;
- pdata[7] = (self->encoder.pkt->hdr.TS & 0xFF);
- // Length (16)
- pdata[8] = (self->encoder.pkt->hdr.length >> 8);
- pdata[9] = (self->encoder.pkt->hdr.length & 0xFF);
-
- pdata += 10;
-
- tsk_list_foreach(item, self->encoder.pkt->levels){
- if (!(level = item->data)){
- continue;
- }
- // Protection length (16)
- pdata[0] = (level->hdr.length >> 8);
- pdata[1] = (level->hdr.length & 0xFF);
- pdata += 2;
- // mask (16 or 48)
- for (i = (int32_t)(level->hdr.mask_size - 8); i >= 0; i -= 8){
- *pdata = ((level->hdr.mask >> i) & 0xFF); ++pdata;
- }
- // payload
- memcpy(pdata, level->payload.ptr, level->hdr.length);
- }
-
- return xsize;
+ uint8_t* pdata;
+ tsk_size_t xsize;
+ int32_t i;
+ tsk_list_item_t* item;
+ tdav_fec_level_t* level;
+
+ if (!self || !self->encoder.pkt || !out_data) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+ xsize = tdav_codec_ulpfec_guess_serialbuff_size(self);
+
+ if (*out_max_size < xsize) {
+ if (!(*out_data = tsk_realloc(*out_data, xsize))) {
+ TSK_DEBUG_ERROR("Failed to reallocate buffer with size =%d", xsize);
+ *out_max_size = 0;
+ return 0;
+ }
+ *out_max_size = xsize;
+ }
+ pdata = (uint8_t*)*out_data;
+
+ // E(1), L(1), P(1), X(1), CC(4)
+ pdata[0] =
+ (self->encoder.pkt->hdr.E << 7) |
+ (self->encoder.pkt->hdr.L << 6) |
+ (self->encoder.pkt->hdr.P << 5) |
+ (self->encoder.pkt->hdr.X << 4) |
+ (self->encoder.pkt->hdr.CC & 0x0F);
+ // M(1), PT(7)
+ pdata[1] = (self->encoder.pkt->hdr.M << 7) | (self->encoder.pkt->hdr.PT & 0x7F);
+ // SN base (16)
+ pdata[2] = (self->encoder.pkt->hdr.SN_base.value >> 8);
+ pdata[3] = (self->encoder.pkt->hdr.SN_base.value & 0xFF);
+ // TS (32)
+ pdata[4] = self->encoder.pkt->hdr.TS >> 24;
+ pdata[5] = (self->encoder.pkt->hdr.TS >> 16) & 0xFF;
+ pdata[6] = (self->encoder.pkt->hdr.TS >> 8) & 0xFF;
+ pdata[7] = (self->encoder.pkt->hdr.TS & 0xFF);
+ // Length (16)
+ pdata[8] = (self->encoder.pkt->hdr.length >> 8);
+ pdata[9] = (self->encoder.pkt->hdr.length & 0xFF);
+
+ pdata += 10;
+
+ tsk_list_foreach(item, self->encoder.pkt->levels) {
+ if (!(level = item->data)) {
+ continue;
+ }
+ // Protection length (16)
+ pdata[0] = (level->hdr.length >> 8);
+ pdata[1] = (level->hdr.length & 0xFF);
+ pdata += 2;
+ // mask (16 or 48)
+ for (i = (int32_t)(level->hdr.mask_size - 8); i >= 0; i -= 8) {
+ *pdata = ((level->hdr.mask >> i) & 0xFF);
+ ++pdata;
+ }
+ // payload
+ memcpy(pdata, level->payload.ptr, level->hdr.length);
+ }
+
+ return xsize;
}
static int tdav_codec_ulpfec_open(tmedia_codec_t* self)
{
- return 0;
+ return 0;
}
static int tdav_codec_ulpfec_close(tmedia_codec_t* self)
{
- return 0;
+ return 0;
}
static tsk_size_t tdav_codec_ulpfec_encode(tmedia_codec_t* self, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size)
{
- TSK_DEBUG_ERROR("Not expected to be called");
- return 0;
+ TSK_DEBUG_ERROR("Not expected to be called");
+ return 0;
}
static tsk_size_t tdav_codec_ulpfec_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)
{
- TSK_DEBUG_ERROR("Not expected to be called");
- return 0;
+ TSK_DEBUG_ERROR("Not expected to be called");
+ return 0;
}
static tsk_bool_t tdav_codec_ulpfec_sdp_att_match(const tmedia_codec_t* codec, const char* att_name, const char* att_value)
{
- return tsk_true;
+ return tsk_true;
}
static char* tdav_codec_ulpfec_sdp_att_get(const tmedia_codec_t* self, const char* att_name)
{
- return tsk_null;
+ return tsk_null;
}
@@ -362,63 +362,61 @@ static char* tdav_codec_ulpfec_sdp_att_get(const tmedia_codec_t* self, const cha
/* constructor */
static tsk_object_t* tdav_codec_ulpfec_ctor(tsk_object_t * self, va_list * app)
{
- tdav_codec_ulpfec_t *ulpfec = self;
- if (ulpfec){
- /* init base: called by tmedia_codec_create() */
- /* init self */
- if (!(ulpfec->encoder.pkt = tsk_object_new(tdav_fec_pkt_def_t))){
- TSK_DEBUG_ERROR("Failed to create FEC packet");
- return tsk_null;
- }
- }
- return self;
+ tdav_codec_ulpfec_t *ulpfec = self;
+ if (ulpfec) {
+ /* init base: called by tmedia_codec_create() */
+ /* init self */
+ if (!(ulpfec->encoder.pkt = tsk_object_new(tdav_fec_pkt_def_t))) {
+ TSK_DEBUG_ERROR("Failed to create FEC packet");
+ return tsk_null;
+ }
+ }
+ return self;
}
/* destructor */
static tsk_object_t* tdav_codec_ulpfec_dtor(tsk_object_t * self)
{
- tdav_codec_ulpfec_t *ulpfec = self;
- if (ulpfec){
- /* deinit base */
- tmedia_codec_video_deinit(ulpfec);
- /* deinit self */
- TSK_OBJECT_SAFE_FREE(ulpfec->encoder.pkt);
- }
-
- return self;
+ tdav_codec_ulpfec_t *ulpfec = self;
+ if (ulpfec) {
+ /* deinit base */
+ tmedia_codec_video_deinit(ulpfec);
+ /* deinit self */
+ TSK_OBJECT_SAFE_FREE(ulpfec->encoder.pkt);
+ }
+
+ return self;
}
/* object definition */
-static const tsk_object_def_t tdav_codec_ulpfec_def_s =
-{
- sizeof(tdav_codec_ulpfec_t),
- tdav_codec_ulpfec_ctor,
- tdav_codec_ulpfec_dtor,
- tmedia_codec_cmp,
+static const tsk_object_def_t tdav_codec_ulpfec_def_s = {
+ sizeof(tdav_codec_ulpfec_t),
+ tdav_codec_ulpfec_ctor,
+ tdav_codec_ulpfec_dtor,
+ tmedia_codec_cmp,
};
/* plugin definition*/
-static const tmedia_codec_plugin_def_t tdav_codec_ulpfec_plugin_def_s =
-{
- &tdav_codec_ulpfec_def_s,
-
- tmedia_video,
- tmedia_codec_id_none, // fake codec
- "ulpfec",
- "ulpfec codec",
- TMEDIA_CODEC_FORMAT_ULPFEC,
- tsk_true,
- 90000, // rate
-
- /* audio */
- { 0 },
-
- /* video (defaul width,height,fps) */
- { 176, 144, 15 },
-
- tsk_null, // set()
- tdav_codec_ulpfec_open,
- tdav_codec_ulpfec_close,
- tdav_codec_ulpfec_encode,
- tdav_codec_ulpfec_decode,
- tdav_codec_ulpfec_sdp_att_match,
- tdav_codec_ulpfec_sdp_att_get
+static const tmedia_codec_plugin_def_t tdav_codec_ulpfec_plugin_def_s = {
+ &tdav_codec_ulpfec_def_s,
+
+ tmedia_video,
+ tmedia_codec_id_none, // fake codec
+ "ulpfec",
+ "ulpfec codec",
+ TMEDIA_CODEC_FORMAT_ULPFEC,
+ tsk_true,
+ 90000, // rate
+
+ /* audio */
+ { 0 },
+
+ /* video (defaul width,height,fps) */
+ { 176, 144, 15 },
+
+ tsk_null, // set()
+ tdav_codec_ulpfec_open,
+ tdav_codec_ulpfec_close,
+ tdav_codec_ulpfec_encode,
+ tdav_codec_ulpfec_decode,
+ tdav_codec_ulpfec_sdp_att_match,
+ tdav_codec_ulpfec_sdp_att_get
};
const tmedia_codec_plugin_def_t *tdav_codec_ulpfec_plugin_def_t = &tdav_codec_ulpfec_plugin_def_s; \ No newline at end of file
diff --git a/tinyDAV/src/codecs/g711/g711.c b/tinyDAV/src/codecs/g711/g711.c
index fa7c8be..cd599dc 100755
--- a/tinyDAV/src/codecs/g711/g711.c
+++ b/tinyDAV/src/codecs/g711/g711.c
@@ -40,7 +40,7 @@
* bli@cpk.auc.dk
*
*/
-
+
#include "tinydav/codecs/g711/g711.h"
#define SIGN_BIT (0x80) /* Sign bit for a A-law byte. */
@@ -50,63 +50,68 @@
#define SEG_MASK (0x70) /* Segment field mask. */
static short seg_aend[8] = {0x1F, 0x3F, 0x7F, 0xFF,
- 0x1FF, 0x3FF, 0x7FF, 0xFFF};
+ 0x1FF, 0x3FF, 0x7FF, 0xFFF
+ };
static short seg_uend[8] = {0x3F, 0x7F, 0xFF, 0x1FF,
- 0x3FF, 0x7FF, 0xFFF, 0x1FFF};
+ 0x3FF, 0x7FF, 0xFFF, 0x1FFF
+ };
/* copy from CCITT G.711 specifications */
unsigned char _u2a[128] = { /* u- to A-law conversions */
- 1, 1, 2, 2, 3, 3, 4, 4,
- 5, 5, 6, 6, 7, 7, 8, 8,
- 9, 10, 11, 12, 13, 14, 15, 16,
- 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 27, 29, 31, 33, 34, 35, 36,
- 37, 38, 39, 40, 41, 42, 43, 44,
- 46, 48, 49, 50, 51, 52, 53, 54,
- 55, 56, 57, 58, 59, 60, 61, 62,
- 64, 65, 66, 67, 68, 69, 70, 71,
- 72, 73, 74, 75, 76, 77, 78, 79,
-/* corrected:
- 81, 82, 83, 84, 85, 86, 87, 88,
- should be: */
- 80, 82, 83, 84, 85, 86, 87, 88,
- 89, 90, 91, 92, 93, 94, 95, 96,
- 97, 98, 99, 100, 101, 102, 103, 104,
- 105, 106, 107, 108, 109, 110, 111, 112,
- 113, 114, 115, 116, 117, 118, 119, 120,
- 121, 122, 123, 124, 125, 126, 127, 128};
+ 1, 1, 2, 2, 3, 3, 4, 4,
+ 5, 5, 6, 6, 7, 7, 8, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 27, 29, 31, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, 42, 43, 44,
+ 46, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, 62,
+ 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, 79,
+ /* corrected:
+ 81, 82, 83, 84, 85, 86, 87, 88,
+ should be: */
+ 80, 82, 83, 84, 85, 86, 87, 88,
+ 89, 90, 91, 92, 93, 94, 95, 96,
+ 97, 98, 99, 100, 101, 102, 103, 104,
+ 105, 106, 107, 108, 109, 110, 111, 112,
+ 113, 114, 115, 116, 117, 118, 119, 120,
+ 121, 122, 123, 124, 125, 126, 127, 128
+};
unsigned char _a2u[128] = { /* A- to u-law conversions */
- 1, 3, 5, 7, 9, 11, 13, 15,
- 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 32, 33, 33, 34, 34, 35, 35,
- 36, 37, 38, 39, 40, 41, 42, 43,
- 44, 45, 46, 47, 48, 48, 49, 49,
- 50, 51, 52, 53, 54, 55, 56, 57,
- 58, 59, 60, 61, 62, 63, 64, 64,
- 65, 66, 67, 68, 69, 70, 71, 72,
-/* corrected:
- 73, 74, 75, 76, 77, 78, 79, 79,
- should be: */
- 73, 74, 75, 76, 77, 78, 79, 80,
+ 1, 3, 5, 7, 9, 11, 13, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 32, 33, 33, 34, 34, 35, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 48, 49, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 64,
+ 65, 66, 67, 68, 69, 70, 71, 72,
+ /* corrected:
+ 73, 74, 75, 76, 77, 78, 79, 79,
+ should be: */
+ 73, 74, 75, 76, 77, 78, 79, 80,
- 80, 81, 82, 83, 84, 85, 86, 87,
- 88, 89, 90, 91, 92, 93, 94, 95,
- 96, 97, 98, 99, 100, 101, 102, 103,
- 104, 105, 106, 107, 108, 109, 110, 111,
- 112, 113, 114, 115, 116, 117, 118, 119,
- 120, 121, 122, 123, 124, 125, 126, 127};
+ 80, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103,
+ 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127
+};
static short search(short val, short *table, short size)
{
- short i;
+ short i;
- for (i = 0; i < size; i++) {
- if (val <= *table++)
- return (i);
- }
- return (size);
+ for (i = 0; i < size; i++) {
+ if (val <= *table++) {
+ return (i);
+ }
+ }
+ return (size);
}
/*
@@ -130,34 +135,38 @@ static short search(short val, short *table, short size)
*/
unsigned char linear2alaw(short pcm_val) /* 2's complement (16-bit range) */
{
- short mask;
- short seg;
- unsigned char aval;
+ short mask;
+ short seg;
+ unsigned char aval;
- pcm_val = pcm_val >> 3;
+ pcm_val = pcm_val >> 3;
- if (pcm_val >= 0) {
- mask = 0xD5; /* sign (7th) bit = 1 */
- } else {
- mask = 0x55; /* sign bit = 0 */
- pcm_val = -pcm_val - 1;
- }
+ if (pcm_val >= 0) {
+ mask = 0xD5; /* sign (7th) bit = 1 */
+ }
+ else {
+ mask = 0x55; /* sign bit = 0 */
+ pcm_val = -pcm_val - 1;
+ }
- /* Convert the scaled magnitude to segment number. */
- seg = search(pcm_val, seg_aend, 8);
+ /* Convert the scaled magnitude to segment number. */
+ seg = search(pcm_val, seg_aend, 8);
- /* Combine the sign, segment, and quantization bits. */
+ /* Combine the sign, segment, and quantization bits. */
- if (seg >= 8) /* out of range, return maximum value. */
- return (unsigned char) (0x7F ^ mask);
- else {
- aval = (unsigned char) seg << SEG_SHIFT;
- if (seg < 2)
- aval |= (pcm_val >> 1) & QUANT_MASK;
- else
- aval |= (pcm_val >> seg) & QUANT_MASK;
- return (aval ^ mask);
- }
+ if (seg >= 8) { /* out of range, return maximum value. */
+ return (unsigned char) (0x7F ^ mask);
+ }
+ else {
+ aval = (unsigned char) seg << SEG_SHIFT;
+ if (seg < 2) {
+ aval |= (pcm_val >> 1) & QUANT_MASK;
+ }
+ else {
+ aval |= (pcm_val >> seg) & QUANT_MASK;
+ }
+ return (aval ^ mask);
+ }
}
/*
@@ -166,25 +175,25 @@ unsigned char linear2alaw(short pcm_val) /* 2's complement (16-bit range) */
*/
short alaw2linear(unsigned char a_val)
{
- short t;
- short seg;
+ short t;
+ short seg;
- a_val ^= 0x55;
+ a_val ^= 0x55;
- t = (a_val & QUANT_MASK) << 4;
- seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT;
- switch (seg) {
- case 0:
- t += 8;
- break;
- case 1:
- t += 0x108;
- break;
- default:
- t += 0x108;
- t <<= seg - 1;
- }
- return ((a_val & SIGN_BIT) ? t : -t);
+ t = (a_val & QUANT_MASK) << 4;
+ seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT;
+ switch (seg) {
+ case 0:
+ t += 8;
+ break;
+ case 1:
+ t += 0x108;
+ break;
+ default:
+ t += 0x108;
+ t <<= seg - 1;
+ }
+ return ((a_val & SIGN_BIT) ? t : -t);
}
#define BIAS (0x84) /* Bias for linear code. */
@@ -221,34 +230,38 @@ short alaw2linear(unsigned char a_val)
*/
unsigned char linear2ulaw(short pcm_val) /* 2's complement (16-bit range) */
{
- short mask;
- short seg;
- unsigned char uval;
+ short mask;
+ short seg;
+ unsigned char uval;
- /* Get the sign and the magnitude of the value. */
- pcm_val = pcm_val >> 2;
- if (pcm_val < 0) {
- pcm_val = -pcm_val;
- mask = 0x7F;
- } else {
- mask = 0xFF;
- }
- if ( pcm_val > CLIP ) pcm_val = CLIP; /* clip the magnitude */
- pcm_val += (BIAS >> 2);
+ /* Get the sign and the magnitude of the value. */
+ pcm_val = pcm_val >> 2;
+ if (pcm_val < 0) {
+ pcm_val = -pcm_val;
+ mask = 0x7F;
+ }
+ else {
+ mask = 0xFF;
+ }
+ if ( pcm_val > CLIP ) {
+ pcm_val = CLIP; /* clip the magnitude */
+ }
+ pcm_val += (BIAS >> 2);
- /* Convert the scaled magnitude to segment number. */
- seg = search(pcm_val, seg_uend, 8);
+ /* Convert the scaled magnitude to segment number. */
+ seg = search(pcm_val, seg_uend, 8);
- /*
- * Combine the sign, segment, quantization bits;
- * and complement the code word.
- */
- if (seg >= 8) /* out of range, return maximum value. */
- return (unsigned char) (0x7F ^ mask);
- else {
- uval = (unsigned char) (seg << 4) | ((pcm_val >> (seg + 1)) & 0xF);
- return (uval ^ mask);
- }
+ /*
+ * Combine the sign, segment, quantization bits;
+ * and complement the code word.
+ */
+ if (seg >= 8) { /* out of range, return maximum value. */
+ return (unsigned char) (0x7F ^ mask);
+ }
+ else {
+ uval = (unsigned char) (seg << 4) | ((pcm_val >> (seg + 1)) & 0xF);
+ return (uval ^ mask);
+ }
}
@@ -263,33 +276,33 @@ unsigned char linear2ulaw(short pcm_val) /* 2's complement (16-bit range) */
*/
short ulaw2linear(unsigned char u_val)
{
- short t;
+ short t;
- /* Complement to obtain normal u-law value. */
- u_val = ~u_val;
+ /* Complement to obtain normal u-law value. */
+ u_val = ~u_val;
- /*
- * Extract and bias the quantization bits. Then
- * shift up by the segment number and subtract out the bias.
- */
- t = ((u_val & QUANT_MASK) << 3) + BIAS;
- t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT;
+ /*
+ * Extract and bias the quantization bits. Then
+ * shift up by the segment number and subtract out the bias.
+ */
+ t = ((u_val & QUANT_MASK) << 3) + BIAS;
+ t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT;
- return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS));
+ return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS));
}
/* A-law to u-law conversion */
unsigned char alaw2ulaw(unsigned char aval)
{
- aval &= 0xff;
- return (unsigned char) ((aval & 0x80) ? (0xFF ^ _a2u[aval ^ 0xD5]) :
- (0x7F ^ _a2u[aval ^ 0x55]));
+ aval &= 0xff;
+ return (unsigned char) ((aval & 0x80) ? (0xFF ^ _a2u[aval ^ 0xD5]) :
+ (0x7F ^ _a2u[aval ^ 0x55]));
}
/* u-law to A-law conversion */
unsigned char ulaw2alaw(unsigned char uval)
{
- uval &= 0xff;
- return (unsigned char) ((uval & 0x80) ? (0xD5 ^ (_u2a[0xFF ^ uval] - 1)) :
- (unsigned char) (0x55 ^ (_u2a[0x7F ^ uval] - 1)));
+ uval &= 0xff;
+ return (unsigned char) ((uval & 0x80) ? (0xD5 ^ (_u2a[0xFF ^ uval] - 1)) :
+ (unsigned char) (0x55 ^ (_u2a[0x7F ^ uval] - 1)));
}
diff --git a/tinyDAV/src/codecs/g711/tdav_codec_g711.c b/tinyDAV/src/codecs/g711/tdav_codec_g711.c
index fa970e1..288d70f 100755
--- a/tinyDAV/src/codecs/g711/tdav_codec_g711.c
+++ b/tinyDAV/src/codecs/g711/tdav_codec_g711.c
@@ -2,19 +2,19 @@
* Copyright (C) 2010-2011 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.
*
@@ -42,68 +42,69 @@
static tsk_size_t tdav_codec_g711u_encode(tmedia_codec_t* self, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size)
{
- register tsk_size_t i;
- register uint8_t* pout_data;
- register int16_t* pin_data;
- tsk_size_t out_size;
-
- if(!self || !in_data || !in_size || !out_data){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- out_size = (in_size >> 1);
-
- if(*out_max_size <out_size){
- if(!(*out_data = tsk_realloc(*out_data, out_size))){
- TSK_DEBUG_ERROR("Failed to allocate new buffer");
- *out_max_size = 0;
- return 0;
- }
- *out_max_size = out_size;
- }
-
- pout_data = *out_data;
- pin_data = (int16_t*)in_data;
- for(i = 0; i<out_size; i++){
- pout_data[i] = linear2ulaw(pin_data[i]);
- }
-
- return out_size;
+ register tsk_size_t i;
+ register uint8_t* pout_data;
+ register int16_t* pin_data;
+ tsk_size_t out_size;
+
+ if(!self || !in_data || !in_size || !out_data) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ out_size = (in_size >> 1);
+
+ if(*out_max_size <out_size) {
+ if(!(*out_data = tsk_realloc(*out_data, out_size))) {
+ TSK_DEBUG_ERROR("Failed to allocate new buffer");
+ *out_max_size = 0;
+ return 0;
+ }
+ *out_max_size = out_size;
+ }
+
+ pout_data = *out_data;
+ pin_data = (int16_t*)in_data;
+ for(i = 0; i<out_size; i++) {
+ pout_data[i] = linear2ulaw(pin_data[i]);
+ }
+
+ return out_size;
}
static tsk_size_t tdav_codec_g711u_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)
{
- tsk_size_t i;
- tsk_size_t out_size;
-
- if(!self || !in_data || !in_size || !out_data){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- out_size = (in_size << 1);
-
- /* allocate new buffer */
- if(*out_max_size<out_size){
- if(!(*out_data = tsk_realloc(*out_data, out_size))){
- TSK_DEBUG_ERROR("Failed to allocate new buffer");
- *out_max_size = 0;
- return 0;
- }
- *out_max_size = out_size;
- }
-
- for(i = 0; i<in_size; i++){
- ((short*)*out_data)[i] = ulaw2linear(((uint8_t*)in_data)[i]);
- }
-
- return out_size;
+ tsk_size_t i;
+ tsk_size_t out_size;
+
+ if(!self || !in_data || !in_size || !out_data) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ out_size = (in_size << 1);
+
+ /* allocate new buffer */
+ if(*out_max_size<out_size) {
+ if(!(*out_data = tsk_realloc(*out_data, out_size))) {
+ TSK_DEBUG_ERROR("Failed to allocate new buffer");
+ *out_max_size = 0;
+ return 0;
+ }
+ *out_max_size = out_size;
+ }
+
+ for(i = 0; i<in_size; i++) {
+ ((short*)*out_data)[i] = ulaw2linear(((uint8_t*)in_data)[i]);
+ }
+
+ return out_size;
}
static tsk_bool_t tdav_codec_g711u_sdp_att_match(const tmedia_codec_t* codec, const char* att_name, const char* att_value)
-{ /* always match */
- return tsk_true;
+{
+ /* always match */
+ return tsk_true;
}
@@ -114,61 +115,59 @@ static tsk_bool_t tdav_codec_g711u_sdp_att_match(const tmedia_codec_t* codec, co
/* constructor */
static tsk_object_t* tdav_codec_g711u_ctor(tsk_object_t * self, va_list * app)
{
- tdav_codec_g711u_t *g711u = self;
- if(g711u){
- /* init base: called by tmedia_codec_create() */
- /* init self */
- }
- return self;
+ tdav_codec_g711u_t *g711u = self;
+ if(g711u) {
+ /* init base: called by tmedia_codec_create() */
+ /* init self */
+ }
+ return self;
}
/* destructor */
static tsk_object_t* tdav_codec_g711u_dtor(tsk_object_t * self)
-{
- tdav_codec_g711u_t *g711u = self;
- if(g711u){
- /* deinit base */
- tmedia_codec_audio_deinit(g711u);
- /* deinit self */
- }
-
- return self;
+{
+ tdav_codec_g711u_t *g711u = self;
+ if(g711u) {
+ /* deinit base */
+ tmedia_codec_audio_deinit(g711u);
+ /* deinit self */
+ }
+
+ return self;
}
/* object definition */
-static const tsk_object_def_t tdav_codec_g711u_def_s =
-{
- sizeof(tdav_codec_g711u_t),
- tdav_codec_g711u_ctor,
- tdav_codec_g711u_dtor,
- tmedia_codec_cmp,
+static const tsk_object_def_t tdav_codec_g711u_def_s = {
+ sizeof(tdav_codec_g711u_t),
+ tdav_codec_g711u_ctor,
+ tdav_codec_g711u_dtor,
+ tmedia_codec_cmp,
};
/* plugin definition*/
-static const tmedia_codec_plugin_def_t tdav_codec_g711u_plugin_def_s =
-{
- &tdav_codec_g711u_def_s,
-
- tmedia_audio,
- tmedia_codec_id_pcmu,
- "PCMU",
- "G.711u codec (native)",
- TMEDIA_CODEC_FORMAT_G711u,
- tsk_false,
- 8000, // rate
-
- { /* audio */
- 1, // channels
- 0 // ptime @deprecated
- },
-
- /* video */
- {0},
-
- tsk_null, // set()
- tdav_codec_g711u_open,
- tdav_codec_g711u_close,
- tdav_codec_g711u_encode,
- tdav_codec_g711u_decode,
- tdav_codec_g711u_sdp_att_match,
- tdav_codec_g711u_sdp_att_get
+static const tmedia_codec_plugin_def_t tdav_codec_g711u_plugin_def_s = {
+ &tdav_codec_g711u_def_s,
+
+ tmedia_audio,
+ tmedia_codec_id_pcmu,
+ "PCMU",
+ "G.711u codec (native)",
+ TMEDIA_CODEC_FORMAT_G711u,
+ tsk_false,
+ 8000, // rate
+
+ { /* audio */
+ 1, // channels
+ 0 // ptime @deprecated
+ },
+
+ /* video */
+ {0},
+
+ tsk_null, // set()
+ tdav_codec_g711u_open,
+ tdav_codec_g711u_close,
+ tdav_codec_g711u_encode,
+ tdav_codec_g711u_decode,
+ tdav_codec_g711u_sdp_att_match,
+ tdav_codec_g711u_sdp_att_get
};
const tmedia_codec_plugin_def_t *tdav_codec_g711u_plugin_def_t = &tdav_codec_g711u_plugin_def_s;
@@ -181,34 +180,34 @@ const tmedia_codec_plugin_def_t *tdav_codec_g711u_plugin_def_t = &tdav_codec_g71
static tsk_size_t tdav_codec_g711a_encode(tmedia_codec_t* self, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size)
{
- register tsk_size_t i;
- register uint8_t* pout_data;
- register int16_t* pin_data;
- tsk_size_t out_size;
-
- if(!self || !in_data || !in_size || !out_data){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- out_size = (in_size >> 1);
-
- if(*out_max_size < out_size){
- if(!(*out_data = tsk_realloc(*out_data, out_size))){
- TSK_DEBUG_ERROR("Failed to allocate new buffer");
- *out_max_size = 0;
- return 0;
- }
- *out_max_size = out_size;
- }
-
- pout_data = *out_data;
- pin_data = (int16_t*)in_data;
- for(i = 0; i<out_size; i++){
- pout_data[i] = linear2alaw(pin_data[i]);
- }
-
- return out_size;
+ register tsk_size_t i;
+ register uint8_t* pout_data;
+ register int16_t* pin_data;
+ tsk_size_t out_size;
+
+ if(!self || !in_data || !in_size || !out_data) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ out_size = (in_size >> 1);
+
+ if(*out_max_size < out_size) {
+ if(!(*out_data = tsk_realloc(*out_data, out_size))) {
+ TSK_DEBUG_ERROR("Failed to allocate new buffer");
+ *out_max_size = 0;
+ return 0;
+ }
+ *out_max_size = out_size;
+ }
+
+ pout_data = *out_data;
+ pin_data = (int16_t*)in_data;
+ for(i = 0; i<out_size; i++) {
+ pout_data[i] = linear2alaw(pin_data[i]);
+ }
+
+ return out_size;
}
#if 0
@@ -217,46 +216,47 @@ int count = 0;
#endif
static tsk_size_t tdav_codec_g711a_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)
{
- tsk_size_t i, out_size;
-
- if(!self || !in_data || !in_size || !out_data){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
- out_size = (in_size << 1);
+ tsk_size_t i, out_size;
+
+ if(!self || !in_data || !in_size || !out_data) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+ out_size = (in_size << 1);
#if 0
- if(!file && count<=1000){
- file = fopen("./g711a.pcm", "wb");
- }
+ if(!file && count<=1000) {
+ file = fopen("./g711a.pcm", "wb");
+ }
#endif
- /* allocate new buffer */
- if(*out_max_size < out_size){
- if(!(*out_data = tsk_realloc(*out_data, out_size))){
- TSK_DEBUG_ERROR("Failed to allocate new buffer");
- *out_max_size = 0;
- return 0;
- }
- *out_max_size = out_size;
- }
-
- for(i = 0; i<in_size; i++){
- ((short*)*out_data)[i] = alaw2linear(((uint8_t*)in_data)[i]);
- }
+ /* allocate new buffer */
+ if(*out_max_size < out_size) {
+ if(!(*out_data = tsk_realloc(*out_data, out_size))) {
+ TSK_DEBUG_ERROR("Failed to allocate new buffer");
+ *out_max_size = 0;
+ return 0;
+ }
+ *out_max_size = out_size;
+ }
+
+ for(i = 0; i<in_size; i++) {
+ ((short*)*out_data)[i] = alaw2linear(((uint8_t*)in_data)[i]);
+ }
#if 0
- if(++count<=1000){
- fwrite(*out_data, sizeof(short), in_size, file);
- }
- else if(file){
- fclose(file);
- file = tsk_null;
- }
+ if(++count<=1000) {
+ fwrite(*out_data, sizeof(short), in_size, file);
+ }
+ else if(file) {
+ fclose(file);
+ file = tsk_null;
+ }
#endif
- return out_size;
+ return out_size;
}
static tsk_bool_t tdav_codec_g711a_sdp_att_match(const tmedia_codec_t* codec, const char* att_name, const char* att_value)
-{ /* always match */
- return tsk_true;
+{
+ /* always match */
+ return tsk_true;
}
@@ -267,60 +267,58 @@ static tsk_bool_t tdav_codec_g711a_sdp_att_match(const tmedia_codec_t* codec, co
/* constructor */
static tsk_object_t* tdav_codec_g711a_ctor(tsk_object_t * self, va_list * app)
{
- tdav_codec_g711a_t *g711a = self;
- if(g711a){
- /* init base: called by tmedia_codec_create() */
- /* init self */
- }
- return self;
+ tdav_codec_g711a_t *g711a = self;
+ if(g711a) {
+ /* init base: called by tmedia_codec_create() */
+ /* init self */
+ }
+ return self;
}
/* destructor */
static tsk_object_t* tdav_codec_g711a_dtor(tsk_object_t * self)
-{
- tdav_codec_g711a_t *g711a = self;
- if(g711a){
- /* deinit base */
- tmedia_codec_audio_deinit(g711a);
- /* deinit self */
- }
-
- return self;
+{
+ tdav_codec_g711a_t *g711a = self;
+ if(g711a) {
+ /* deinit base */
+ tmedia_codec_audio_deinit(g711a);
+ /* deinit self */
+ }
+
+ return self;
}
/* object definition */
-static const tsk_object_def_t tdav_codec_g711a_def_s =
-{
- sizeof(tdav_codec_g711a_t),
- tdav_codec_g711a_ctor,
- tdav_codec_g711a_dtor,
- tmedia_codec_cmp,
+static const tsk_object_def_t tdav_codec_g711a_def_s = {
+ sizeof(tdav_codec_g711a_t),
+ tdav_codec_g711a_ctor,
+ tdav_codec_g711a_dtor,
+ tmedia_codec_cmp,
};
/* plugin definition*/
-static const tmedia_codec_plugin_def_t tdav_codec_g711a_plugin_def_s =
-{
- &tdav_codec_g711a_def_s,
-
- tmedia_audio,
- tmedia_codec_id_pcma,
- "PCMA",
- "G.711a codec (native)",
- TMEDIA_CODEC_FORMAT_G711a,
- tsk_false,
- 8000, // rate
-
- { /* audio */
- 1, // channels
- 0 // ptime @deprecated
- },
-
- /* video */
- {0},
-
- tsk_null, // set()
- tdav_codec_g711a_open,
- tdav_codec_g711a_close,
- tdav_codec_g711a_encode,
- tdav_codec_g711a_decode,
- tdav_codec_g711a_sdp_att_match,
- tdav_codec_g711a_sdp_att_get
+static const tmedia_codec_plugin_def_t tdav_codec_g711a_plugin_def_s = {
+ &tdav_codec_g711a_def_s,
+
+ tmedia_audio,
+ tmedia_codec_id_pcma,
+ "PCMA",
+ "G.711a codec (native)",
+ TMEDIA_CODEC_FORMAT_G711a,
+ tsk_false,
+ 8000, // rate
+
+ { /* audio */
+ 1, // channels
+ 0 // ptime @deprecated
+ },
+
+ /* video */
+ {0},
+
+ tsk_null, // set()
+ tdav_codec_g711a_open,
+ tdav_codec_g711a_close,
+ tdav_codec_g711a_encode,
+ tdav_codec_g711a_decode,
+ tdav_codec_g711a_sdp_att_match,
+ tdav_codec_g711a_sdp_att_get
};
const tmedia_codec_plugin_def_t *tdav_codec_g711a_plugin_def_t = &tdav_codec_g711a_plugin_def_s;
diff --git a/tinyDAV/src/codecs/g722/g722_decode.c b/tinyDAV/src/codecs/g722/g722_decode.c
index b6b7830..c9c26af 100755
--- a/tinyDAV/src/codecs/g722/g722_decode.c
+++ b/tinyDAV/src/codecs/g722/g722_decode.c
@@ -7,7 +7,7 @@
*
* Copyright (C) 2005 Steve Underwood
*
- * Despite my general liking of the GPL, I place my own contributions
+ * Despite my general liking of the GPL, I place my own contributions
* to this code in the public domain for the benefit of all mankind -
* even the slimy ones who might try to proprietize my work and use it
* to my detriment.
@@ -48,10 +48,12 @@ static __inline int16_t saturate(int32_t amp)
/* Hopefully this is optimised for the common case - not clipping */
amp16 = (int16_t) amp;
- if (amp == amp16)
+ if (amp == amp16) {
return amp16;
- if (amp > TDAV_INT16_MAX)
+ }
+ if (amp > TDAV_INT16_MAX) {
return TDAV_INT16_MAX;
+ }
return TDAV_INT16_MIN;
}
/*- End of function --------------------------------------------------------*/
@@ -73,20 +75,24 @@ static void block4(g722_decode_state_t *s, int band, int d)
s->band[band].p[0] = saturate(s->band[band].sz + d);
/* Block 4, UPPOL2 */
- for (i = 0; i < 3; i++)
+ for (i = 0; i < 3; i++) {
s->band[band].sg[i] = s->band[band].p[i] >> 15;
+ }
wd1 = saturate(s->band[band].a[1] << 2);
wd2 = (s->band[band].sg[0] == s->band[band].sg[1]) ? -wd1 : wd1;
- if (wd2 > 32767)
+ if (wd2 > 32767) {
wd2 = 32767;
+ }
wd3 = (s->band[band].sg[0] == s->band[band].sg[2]) ? 128 : -128;
wd3 += (wd2 >> 7);
wd3 += (s->band[band].a[2]*32512) >> 15;
- if (wd3 > 12288)
+ if (wd3 > 12288) {
wd3 = 12288;
- else if (wd3 < -12288)
+ }
+ else if (wd3 < -12288) {
wd3 = -12288;
+ }
s->band[band].ap[2] = wd3;
/* Block 4, UPPOL1 */
@@ -97,16 +103,17 @@ static void block4(g722_decode_state_t *s, int band, int d)
s->band[band].ap[1] = saturate(wd1 + wd2);
wd3 = saturate(15360 - s->band[band].ap[2]);
- if (s->band[band].ap[1] > wd3)
+ if (s->band[band].ap[1] > wd3) {
s->band[band].ap[1] = wd3;
- else if (s->band[band].ap[1] < -wd3)
+ }
+ else if (s->band[band].ap[1] < -wd3) {
s->band[band].ap[1] = -wd3;
+ }
/* Block 4, UPZERO */
wd1 = (d == 0) ? 0 : 128;
s->band[band].sg[0] = d >> 15;
- for (i = 1; i < 7; i++)
- {
+ for (i = 1; i < 7; i++) {
s->band[band].sg[i] = s->band[band].d[i] >> 15;
wd2 = (s->band[band].sg[i] == s->band[band].sg[0]) ? wd1 : -wd1;
wd3 = (s->band[band].b[i]*32640) >> 15;
@@ -114,14 +121,12 @@ static void block4(g722_decode_state_t *s, int band, int d)
}
/* Block 4, DELAYA */
- for (i = 6; i > 0; i--)
- {
+ for (i = 6; i > 0; i--) {
s->band[band].d[i] = s->band[band].d[i - 1];
s->band[band].b[i] = s->band[band].bp[i];
}
-
- for (i = 2; i > 0; i--)
- {
+
+ for (i = 2; i > 0; i--) {
s->band[band].r[i] = s->band[band].r[i - 1];
s->band[band].p[i] = s->band[band].p[i - 1];
s->band[band].a[i] = s->band[band].ap[i];
@@ -136,8 +141,7 @@ static void block4(g722_decode_state_t *s, int band, int d)
/* Block 4, FILTEZ */
s->band[band].sz = 0;
- for (i = 6; i > 0; i--)
- {
+ for (i = 6; i > 0; i--) {
wd1 = saturate(s->band[band].d[i] + s->band[band].d[i]);
s->band[band].sz += (s->band[band].b[i]*wd1) >> 15;
}
@@ -150,24 +154,30 @@ static void block4(g722_decode_state_t *s, int band, int d)
g722_decode_state_t *g722_decode_init(g722_decode_state_t *s, int rate, int options)
{
- if (s == NULL)
- {
- if ((s = (g722_decode_state_t *) malloc(sizeof(*s))) == NULL)
+ if (s == NULL) {
+ if ((s = (g722_decode_state_t *) malloc(sizeof(*s))) == NULL) {
return NULL;
+ }
}
memset(s, 0, sizeof(*s));
- if (rate == 48000)
+ if (rate == 48000) {
s->bits_per_sample = 6;
- else if (rate == 56000)
+ }
+ else if (rate == 56000) {
s->bits_per_sample = 7;
- else
+ }
+ else {
s->bits_per_sample = 8;
- if ((options & G722_SAMPLE_RATE_8000))
+ }
+ if ((options & G722_SAMPLE_RATE_8000)) {
s->eight_k = TRUE;
- if ((options & G722_PACKED) && s->bits_per_sample != 8)
+ }
+ if ((options & G722_PACKED) && s->bits_per_sample != 8) {
s->packed = TRUE;
- else
+ }
+ else {
s->packed = FALSE;
+ }
s->band[0].det = 32;
s->band[1].det = 8;
return s;
@@ -186,8 +196,7 @@ int g722_decode(g722_decode_state_t *s, int16_t amp[],
{
static const int wl[8] = {-60, -30, 58, 172, 334, 538, 1198, 3042 };
static const int rl42[16] = {0, 7, 6, 5, 4, 3, 2, 1, 7, 6, 5, 4, 3, 2, 1, 0 };
- static const int ilb[32] =
- {
+ static const int ilb[32] = {
2048, 2093, 2139, 2186, 2233, 2282, 2332,
2383, 2435, 2489, 2543, 2599, 2656, 2714,
2774, 2834, 2896, 2960, 3025, 3091, 3158,
@@ -197,46 +206,42 @@ int g722_decode(g722_decode_state_t *s, int16_t amp[],
static const int wh[3] = {0, -214, 798};
static const int rh2[4] = {2, 1, 2, 1};
static const int qm2[4] = {-7408, -1616, 7408, 1616};
- static const int qm4[16] =
- {
- 0, -20456, -12896, -8968,
- -6288, -4240, -2584, -1200,
- 20456, 12896, 8968, 6288,
- 4240, 2584, 1200, 0
+ static const int qm4[16] = {
+ 0, -20456, -12896, -8968,
+ -6288, -4240, -2584, -1200,
+ 20456, 12896, 8968, 6288,
+ 4240, 2584, 1200, 0
};
- static const int qm5[32] =
- {
- -280, -280, -23352, -17560,
- -14120, -11664, -9752, -8184,
- -6864, -5712, -4696, -3784,
- -2960, -2208, -1520, -880,
- 23352, 17560, 14120, 11664,
- 9752, 8184, 6864, 5712,
- 4696, 3784, 2960, 2208,
- 1520, 880, 280, -280
+ static const int qm5[32] = {
+ -280, -280, -23352, -17560,
+ -14120, -11664, -9752, -8184,
+ -6864, -5712, -4696, -3784,
+ -2960, -2208, -1520, -880,
+ 23352, 17560, 14120, 11664,
+ 9752, 8184, 6864, 5712,
+ 4696, 3784, 2960, 2208,
+ 1520, 880, 280, -280
};
- static const int qm6[64] =
- {
- -136, -136, -136, -136,
- -24808, -21904, -19008, -16704,
- -14984, -13512, -12280, -11192,
- -10232, -9360, -8576, -7856,
- -7192, -6576, -6000, -5456,
- -4944, -4464, -4008, -3576,
- -3168, -2776, -2400, -2032,
- -1688, -1360, -1040, -728,
- 24808, 21904, 19008, 16704,
- 14984, 13512, 12280, 11192,
- 10232, 9360, 8576, 7856,
- 7192, 6576, 6000, 5456,
- 4944, 4464, 4008, 3576,
- 3168, 2776, 2400, 2032,
- 1688, 1360, 1040, 728,
- 432, 136, -432, -136
+ static const int qm6[64] = {
+ -136, -136, -136, -136,
+ -24808, -21904, -19008, -16704,
+ -14984, -13512, -12280, -11192,
+ -10232, -9360, -8576, -7856,
+ -7192, -6576, -6000, -5456,
+ -4944, -4464, -4008, -3576,
+ -3168, -2776, -2400, -2032,
+ -1688, -1360, -1040, -728,
+ 24808, 21904, 19008, 16704,
+ 14984, 13512, 12280, 11192,
+ 10232, 9360, 8576, 7856,
+ 7192, 6576, 6000, 5456,
+ 4944, 4464, 4008, 3576,
+ 3168, 2776, 2400, 2032,
+ 1688, 1360, 1040, 728,
+ 432, 136, -432, -136
};
- static const int qmf_coeffs[12] =
- {
- 3, -11, 12, 32, -210, 951, 3876, -805, 362, -156, 53, -11,
+ static const int qmf_coeffs[12] = {
+ 3, -11, 12, 32, -210, 951, 3876, -805, 362, -156, 53, -11,
};
int dlowt;
@@ -256,13 +261,10 @@ int g722_decode(g722_decode_state_t *s, int16_t amp[],
outlen = 0;
rhigh = 0;
- for (j = 0; j < len; )
- {
- if (s->packed)
- {
+ for (j = 0; j < len; ) {
+ if (s->packed) {
/* Unpack the code bits */
- if (s->in_bits < s->bits_per_sample)
- {
+ if (s->in_bits < s->bits_per_sample) {
s->in_buffer |= (g722_data[j++] << s->in_bits);
s->in_bits += 8;
}
@@ -270,13 +272,11 @@ int g722_decode(g722_decode_state_t *s, int16_t amp[],
s->in_buffer >>= s->bits_per_sample;
s->in_bits -= s->bits_per_sample;
}
- else
- {
+ else {
code = g722_data[j++];
}
- switch (s->bits_per_sample)
- {
+ switch (s->bits_per_sample) {
default:
case 8:
wd1 = code & 0x3F;
@@ -301,10 +301,12 @@ int g722_decode(g722_decode_state_t *s, int16_t amp[],
/* Block 5L, RECONS */
rlow = s->band[0].s + wd2;
/* Block 6L, LIMIT */
- if (rlow > 16383)
+ if (rlow > 16383) {
rlow = 16383;
- else if (rlow < -16384)
+ }
+ else if (rlow < -16384) {
rlow = -16384;
+ }
/* Block 2L, INVQAL */
wd2 = qm4[wd1];
@@ -314,12 +316,14 @@ int g722_decode(g722_decode_state_t *s, int16_t amp[],
wd2 = rl42[wd1];
wd1 = (s->band[0].nb*127) >> 7;
wd1 += wl[wd2];
- if (wd1 < 0)
+ if (wd1 < 0) {
wd1 = 0;
- else if (wd1 > 18432)
+ }
+ else if (wd1 > 18432) {
wd1 = 18432;
+ }
s->band[0].nb = wd1;
-
+
/* Block 3L, SCALEL */
wd1 = (s->band[0].nb >> 6) & 31;
wd2 = 8 - (s->band[0].nb >> 11);
@@ -327,30 +331,33 @@ int g722_decode(g722_decode_state_t *s, int16_t amp[],
s->band[0].det = wd3 << 2;
block4(s, 0, dlowt);
-
- if (!s->eight_k)
- {
+
+ if (!s->eight_k) {
/* Block 2H, INVQAH */
wd2 = qm2[ihigh];
dhigh = (s->band[1].det*wd2) >> 15;
/* Block 5H, RECONS */
rhigh = dhigh + s->band[1].s;
/* Block 6H, LIMIT */
- if (rhigh > 16383)
+ if (rhigh > 16383) {
rhigh = 16383;
- else if (rhigh < -16384)
+ }
+ else if (rhigh < -16384) {
rhigh = -16384;
+ }
/* Block 2H, INVQAH */
wd2 = rh2[ihigh];
wd1 = (s->band[1].nb*127) >> 7;
wd1 += wh[wd2];
- if (wd1 < 0)
+ if (wd1 < 0) {
wd1 = 0;
- else if (wd1 > 22528)
+ }
+ else if (wd1 > 22528) {
wd1 = 22528;
+ }
s->band[1].nb = wd1;
-
+
/* Block 3H, SCALEH */
wd1 = (s->band[1].nb >> 6) & 31;
wd2 = 10 - (s->band[1].nb >> 11);
@@ -360,29 +367,25 @@ int g722_decode(g722_decode_state_t *s, int16_t amp[],
block4(s, 1, dhigh);
}
- if (s->itu_test_mode)
- {
+ if (s->itu_test_mode) {
amp[outlen++] = (int16_t) (rlow << 1);
amp[outlen++] = (int16_t) (rhigh << 1);
}
- else
- {
- if (s->eight_k)
- {
+ else {
+ if (s->eight_k) {
amp[outlen++] = (int16_t) (rlow << 1);
}
- else
- {
+ else {
/* Apply the receive QMF */
- for (i = 0; i < 22; i++)
+ for (i = 0; i < 22; i++) {
s->x[i] = s->x[i + 2];
+ }
s->x[22] = rlow + rhigh;
s->x[23] = rlow - rhigh;
xout1 = 0;
xout2 = 0;
- for (i = 0; i < 12; i++)
- {
+ for (i = 0; i < 12; i++) {
xout2 += s->x[2*i]*qmf_coeffs[i];
xout1 += s->x[2*i + 1]*qmf_coeffs[11 - i];
}
diff --git a/tinyDAV/src/codecs/g722/g722_encode.c b/tinyDAV/src/codecs/g722/g722_encode.c
index 68758eb..a0bf821 100755
--- a/tinyDAV/src/codecs/g722/g722_encode.c
+++ b/tinyDAV/src/codecs/g722/g722_encode.c
@@ -9,7 +9,7 @@
*
* All rights reserved.
*
- * Despite my general liking of the GPL, I place my own contributions
+ * Despite my general liking of the GPL, I place my own contributions
* to this code in the public domain for the benefit of all mankind -
* even the slimy ones who might try to proprietize my work and use it
* to my detriment.
@@ -47,10 +47,12 @@ static __inline int16_t saturate(int32_t amp)
/* Hopefully this is optimised for the common case - not clipping */
amp16 = (int16_t) amp;
- if (amp == amp16)
+ if (amp == amp16) {
return amp16;
- if (amp > TDAV_INT16_MAX)
+ }
+ if (amp > TDAV_INT16_MAX) {
return TDAV_INT16_MAX;
+ }
return TDAV_INT16_MIN;
}
/*- End of function --------------------------------------------------------*/
@@ -70,19 +72,23 @@ static void block4(g722_encode_state_t *s, int band, int d)
s->band[band].p[0] = saturate(s->band[band].sz + d);
/* Block 4, UPPOL2 */
- for (i = 0; i < 3; i++)
+ for (i = 0; i < 3; i++) {
s->band[band].sg[i] = s->band[band].p[i] >> 15;
+ }
wd1 = saturate(s->band[band].a[1] << 2);
wd2 = (s->band[band].sg[0] == s->band[band].sg[1]) ? -wd1 : wd1;
- if (wd2 > 32767)
+ if (wd2 > 32767) {
wd2 = 32767;
+ }
wd3 = (wd2 >> 7) + ((s->band[band].sg[0] == s->band[band].sg[2]) ? 128 : -128);
wd3 += (s->band[band].a[2]*32512) >> 15;
- if (wd3 > 12288)
+ if (wd3 > 12288) {
wd3 = 12288;
- else if (wd3 < -12288)
+ }
+ else if (wd3 < -12288) {
wd3 = -12288;
+ }
s->band[band].ap[2] = wd3;
/* Block 4, UPPOL1 */
@@ -93,16 +99,17 @@ static void block4(g722_encode_state_t *s, int band, int d)
s->band[band].ap[1] = saturate(wd1 + wd2);
wd3 = saturate(15360 - s->band[band].ap[2]);
- if (s->band[band].ap[1] > wd3)
+ if (s->band[band].ap[1] > wd3) {
s->band[band].ap[1] = wd3;
- else if (s->band[band].ap[1] < -wd3)
+ }
+ else if (s->band[band].ap[1] < -wd3) {
s->band[band].ap[1] = -wd3;
+ }
/* Block 4, UPZERO */
wd1 = (d == 0) ? 0 : 128;
s->band[band].sg[0] = d >> 15;
- for (i = 1; i < 7; i++)
- {
+ for (i = 1; i < 7; i++) {
s->band[band].sg[i] = s->band[band].d[i] >> 15;
wd2 = (s->band[band].sg[i] == s->band[band].sg[0]) ? wd1 : -wd1;
wd3 = (s->band[band].b[i]*32640) >> 15;
@@ -110,14 +117,12 @@ static void block4(g722_encode_state_t *s, int band, int d)
}
/* Block 4, DELAYA */
- for (i = 6; i > 0; i--)
- {
+ for (i = 6; i > 0; i--) {
s->band[band].d[i] = s->band[band].d[i - 1];
s->band[band].b[i] = s->band[band].bp[i];
}
-
- for (i = 2; i > 0; i--)
- {
+
+ for (i = 2; i > 0; i--) {
s->band[band].r[i] = s->band[band].r[i - 1];
s->band[band].p[i] = s->band[band].p[i - 1];
s->band[band].a[i] = s->band[band].ap[i];
@@ -132,8 +137,7 @@ static void block4(g722_encode_state_t *s, int band, int d)
/* Block 4, FILTEZ */
s->band[band].sz = 0;
- for (i = 6; i > 0; i--)
- {
+ for (i = 6; i > 0; i--) {
wd1 = saturate(s->band[band].d[i] + s->band[band].d[i]);
s->band[band].sz += (s->band[band].b[i]*wd1) >> 15;
}
@@ -146,24 +150,30 @@ static void block4(g722_encode_state_t *s, int band, int d)
g722_encode_state_t *g722_encode_init(g722_encode_state_t *s, int rate, int options)
{
- if (s == NULL)
- {
- if ((s = (g722_encode_state_t *) malloc(sizeof(*s))) == NULL)
+ if (s == NULL) {
+ if ((s = (g722_encode_state_t *) malloc(sizeof(*s))) == NULL) {
return NULL;
+ }
}
memset(s, 0, sizeof(*s));
- if (rate == 48000)
+ if (rate == 48000) {
s->bits_per_sample = 6;
- else if (rate == 56000)
+ }
+ else if (rate == 56000) {
s->bits_per_sample = 7;
- else
+ }
+ else {
s->bits_per_sample = 8;
- if ((options & G722_SAMPLE_RATE_8000))
+ }
+ if ((options & G722_SAMPLE_RATE_8000)) {
s->eight_k = TRUE;
- if ((options & G722_PACKED) && s->bits_per_sample != 8)
+ }
+ if ((options & G722_PACKED) && s->bits_per_sample != 8) {
s->packed = TRUE;
- else
+ }
+ else {
s->packed = FALSE;
+ }
s->band[0].det = 32;
s->band[1].det = 8;
return s;
@@ -197,57 +207,48 @@ int16_t limitValues (int16_t rl)
int g722_encode(g722_encode_state_t *s, uint8_t g722_data[],
const int16_t amp[], int len)
{
- static const int q6[32] =
- {
- 0, 35, 72, 110, 150, 190, 233, 276,
- 323, 370, 422, 473, 530, 587, 650, 714,
- 786, 858, 940, 1023, 1121, 1219, 1339, 1458,
+ static const int q6[32] = {
+ 0, 35, 72, 110, 150, 190, 233, 276,
+ 323, 370, 422, 473, 530, 587, 650, 714,
+ 786, 858, 940, 1023, 1121, 1219, 1339, 1458,
1612, 1765, 1980, 2195, 2557, 2919, 0, 0
};
- static const int iln[32] =
- {
- 0, 63, 62, 31, 30, 29, 28, 27,
+ static const int iln[32] = {
+ 0, 63, 62, 31, 30, 29, 28, 27,
26, 25, 24, 23, 22, 21, 20, 19,
18, 17, 16, 15, 14, 13, 12, 11,
10, 9, 8, 7, 6, 5, 4, 0
};
- static const int ilp[32] =
- {
- 0, 61, 60, 59, 58, 57, 56, 55,
+ static const int ilp[32] = {
+ 0, 61, 60, 59, 58, 57, 56, 55,
54, 53, 52, 51, 50, 49, 48, 47,
46, 45, 44, 43, 42, 41, 40, 39,
38, 37, 36, 35, 34, 33, 32, 0
};
- static const int wl[8] =
- {
+ static const int wl[8] = {
-60, -30, 58, 172, 334, 538, 1198, 3042
};
- static const int rl42[16] =
- {
+ static const int rl42[16] = {
0, 7, 6, 5, 4, 3, 2, 1, 7, 6, 5, 4, 3, 2, 1, 0
};
- static const int ilb[32] =
- {
+ static const int ilb[32] = {
2048, 2093, 2139, 2186, 2233, 2282, 2332,
2383, 2435, 2489, 2543, 2599, 2656, 2714,
2774, 2834, 2896, 2960, 3025, 3091, 3158,
3228, 3298, 3371, 3444, 3520, 3597, 3676,
3756, 3838, 3922, 4008
};
- static const int qm4[16] =
- {
- 0, -20456, -12896, -8968,
- -6288, -4240, -2584, -1200,
- 20456, 12896, 8968, 6288,
- 4240, 2584, 1200, 0
+ static const int qm4[16] = {
+ 0, -20456, -12896, -8968,
+ -6288, -4240, -2584, -1200,
+ 20456, 12896, 8968, 6288,
+ 4240, 2584, 1200, 0
};
- static const int qm2[4] =
- {
+ static const int qm2[4] = {
-7408, -1616, 7408, 1616
};
- static const int qmf_coeffs[12] =
- {
- 3, -11, 12, 32, -210, 951, 3876, -805, 362, -156, 53, -11,
+ static const int qmf_coeffs[12] = {
+ 3, -11, 12, 32, -210, 951, 3876, -805, 362, -156, 53, -11,
};
static const int ihn[3] = {0, 1, 0};
static const int ihp[3] = {0, 3, 2};
@@ -281,34 +282,29 @@ int g722_encode(g722_encode_state_t *s, uint8_t g722_data[],
g722_bytes = 0;
xhigh = 0;
- for (j = 0; j < len; )
- {
- if (s->itu_test_mode)
- {
+ for (j = 0; j < len; ) {
+ if (s->itu_test_mode) {
xlow =
- xhigh = amp[j++] >> 1;
+ xhigh = amp[j++] >> 1;
}
- else
- {
- if (s->eight_k)
- {
+ else {
+ if (s->eight_k) {
/* We shift by 1 to allow for the 15 bit input to the G.722 algorithm. */
xlow = amp[j++] >> 1;
}
- else
- {
+ else {
/* Apply the transmit QMF */
/* Shuffle the buffer down */
- for (i = 0; i < 22; i++)
+ for (i = 0; i < 22; i++) {
s->x[i] = s->x[i + 2];
+ }
s->x[22] = amp[j++];
s->x[23] = amp[j++];
-
+
/* Discard every other QMF output */
sumeven = 0;
sumodd = 0;
- for (i = 0; i < 12; i++)
- {
+ for (i = 0; i < 12; i++) {
sumodd += s->x[2*i]*qmf_coeffs[i];
sumeven += s->x[2*i + 1]*qmf_coeffs[11 - i];
}
@@ -334,11 +330,11 @@ int g722_encode(g722_encode_state_t *s, uint8_t g722_data[],
/* Block 1L, QUANTL */
wd = (el >= 0) ? el : -(el + 1);
- for (i = 1; i < 30; i++)
- {
+ for (i = 1; i < 30; i++) {
wd1 = (q6[i]*s->band[0].det) >> 12;
- if (wd < wd1)
+ if (wd < wd1) {
break;
+ }
}
ilow = (el < 0) ? iln[i] : ilp[i];
@@ -351,10 +347,12 @@ int g722_encode(g722_encode_state_t *s, uint8_t g722_data[],
il4 = rl42[ril];
wd = (s->band[0].nb*127) >> 7;
s->band[0].nb = wd + wl[il4];
- if (s->band[0].nb < 0)
+ if (s->band[0].nb < 0) {
s->band[0].nb = 0;
- else if (s->band[0].nb > 18432)
+ }
+ else if (s->band[0].nb > 18432) {
s->band[0].nb = 18432;
+ }
/* Block 3L, SCALEL */
wd1 = (s->band[0].nb >> 6) & 31;
@@ -363,14 +361,12 @@ int g722_encode(g722_encode_state_t *s, uint8_t g722_data[],
s->band[0].det = wd3 << 2;
block4(s, 0, dlow);
-
- if (s->eight_k)
- {
+
+ if (s->eight_k) {
/* Just leave the high bits as zero */
code = (0xC0 | ilow) >> (8 - s->bits_per_sample);
}
- else
- {
+ else {
/* Block 1H, SUBTRA */
eh = saturate(xhigh - s->band[1].s);
@@ -388,10 +384,12 @@ int g722_encode(g722_encode_state_t *s, uint8_t g722_data[],
ih2 = rh2[ihigh];
wd = (s->band[1].nb*127) >> 7;
s->band[1].nb = wd + wh[ih2];
- if (s->band[1].nb < 0)
+ if (s->band[1].nb < 0) {
s->band[1].nb = 0;
- else if (s->band[1].nb > 22528)
+ }
+ else if (s->band[1].nb > 22528) {
s->band[1].nb = 22528;
+ }
/* Block 3H, SCALEH */
wd1 = (s->band[1].nb >> 6) & 31;
@@ -403,20 +401,17 @@ int g722_encode(g722_encode_state_t *s, uint8_t g722_data[],
code = ((ihigh << 6) | ilow) >> (8 - s->bits_per_sample);
}
- if (s->packed)
- {
+ if (s->packed) {
/* Pack the code bits */
s->out_buffer |= (code << s->out_bits);
s->out_bits += s->bits_per_sample;
- if (s->out_bits >= 8)
- {
+ if (s->out_bits >= 8) {
g722_data[g722_bytes++] = (uint8_t) (s->out_buffer & 0xFF);
s->out_bits -= 8;
s->out_buffer >>= 8;
}
}
- else
- {
+ else {
g722_data[g722_bytes++] = (uint8_t) code;
}
}
diff --git a/tinyDAV/src/codecs/g722/tdav_codec_g722.c b/tinyDAV/src/codecs/g722/tdav_codec_g722.c
index 749fa04..f543bdf 100755
--- a/tinyDAV/src/codecs/g722/tdav_codec_g722.c
+++ b/tinyDAV/src/codecs/g722/tdav_codec_g722.c
@@ -26,124 +26,123 @@
#include "tsk_memory.h"
#include "tsk_debug.h"
-typedef struct tdav_codec_g722_s
-{
- TMEDIA_DECLARE_CODEC_AUDIO;
+typedef struct tdav_codec_g722_s {
+ TMEDIA_DECLARE_CODEC_AUDIO;
- g722_encode_state_t *enc_state;
- g722_decode_state_t *dec_state;
+ g722_encode_state_t *enc_state;
+ g722_decode_state_t *dec_state;
}
tdav_codec_g722_t;
static int tdav_codec_g722_open(tmedia_codec_t* self)
{
- tdav_codec_g722_t* g722 = (tdav_codec_g722_t*)self;
-
- if (!g722){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- // Initialize the decoder
- if (!g722->dec_state){
- if (!(g722->dec_state = tsk_calloc(1, sizeof(g722_decode_state_t)))){
- TSK_DEBUG_ERROR("Failed to create G.722 decoder state");
- return -2;
- }
- // Create and/or reset the G.722 decoder
- // Bitrate 64 kbps and wideband mode (2)
- if (!(g722->dec_state = g722_decode_init(g722->dec_state, 64000, 2))){
- TSK_DEBUG_ERROR("g722_decode_init failed");
- return -3;
- }
- }
-
- // Initialize the encoder
- if (!g722->enc_state){
- if (!(g722->enc_state = tsk_calloc(1, sizeof(g722_encode_state_t)))){
- TSK_DEBUG_ERROR("Failed to create G.722 encoder state");
- return -4;
- }
- // Create and/or reset the G.722 encoder
- // Bitrate 64 kbps and wideband mode (2)
- if (!(g722->enc_state = g722_encode_init(g722->enc_state, 64000, 2))){
- TSK_DEBUG_ERROR("g722_encode_init failed");
- return -5;
- }
- }
-
- return 0;
+ tdav_codec_g722_t* g722 = (tdav_codec_g722_t*)self;
+
+ if (!g722) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ // Initialize the decoder
+ if (!g722->dec_state) {
+ if (!(g722->dec_state = tsk_calloc(1, sizeof(g722_decode_state_t)))) {
+ TSK_DEBUG_ERROR("Failed to create G.722 decoder state");
+ return -2;
+ }
+ // Create and/or reset the G.722 decoder
+ // Bitrate 64 kbps and wideband mode (2)
+ if (!(g722->dec_state = g722_decode_init(g722->dec_state, 64000, 2))) {
+ TSK_DEBUG_ERROR("g722_decode_init failed");
+ return -3;
+ }
+ }
+
+ // Initialize the encoder
+ if (!g722->enc_state) {
+ if (!(g722->enc_state = tsk_calloc(1, sizeof(g722_encode_state_t)))) {
+ TSK_DEBUG_ERROR("Failed to create G.722 encoder state");
+ return -4;
+ }
+ // Create and/or reset the G.722 encoder
+ // Bitrate 64 kbps and wideband mode (2)
+ if (!(g722->enc_state = g722_encode_init(g722->enc_state, 64000, 2))) {
+ TSK_DEBUG_ERROR("g722_encode_init failed");
+ return -5;
+ }
+ }
+
+ return 0;
}
static int tdav_codec_g722_close(tmedia_codec_t* self)
{
- tdav_codec_g722_t* g722 = (tdav_codec_g722_t*)self;
+ tdav_codec_g722_t* g722 = (tdav_codec_g722_t*)self;
- (void)(g722);
+ (void)(g722);
- /* resources will be freed by the dctor() */
+ /* resources will be freed by the dctor() */
- return 0;
+ return 0;
}
static tsk_size_t tdav_codec_g722_encode(tmedia_codec_t* self, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size)
{
- tsk_size_t out_g722_size;
- tdav_codec_g722_t* g722 = (tdav_codec_g722_t*)self;
+ tsk_size_t out_g722_size;
+ tdav_codec_g722_t* g722 = (tdav_codec_g722_t*)self;
- if (!self || !in_data || !in_size || !out_data){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
+ if (!self || !in_data || !in_size || !out_data) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
- out_g722_size = in_size >> 2;
+ out_g722_size = in_size >> 2;
- if (*out_max_size < out_g722_size){
- if (!(*out_data = tsk_realloc(*out_data, out_g722_size))){
- TSK_DEBUG_ERROR("Failed to allocate new buffer");
- *out_max_size = 0;
- return 0;
- }
- *out_max_size = out_g722_size;
- }
+ if (*out_max_size < out_g722_size) {
+ if (!(*out_data = tsk_realloc(*out_data, out_g722_size))) {
+ TSK_DEBUG_ERROR("Failed to allocate new buffer");
+ *out_max_size = 0;
+ return 0;
+ }
+ *out_max_size = out_g722_size;
+ }
- g722_encode(g722->enc_state, (uint8_t*)*out_data, (int16_t*)in_data, (int)in_size / sizeof(int16_t));
+ g722_encode(g722->enc_state, (uint8_t*)*out_data, (int16_t*)in_data, (int)in_size / sizeof(int16_t));
- return out_g722_size;
+ return out_g722_size;
}
static tsk_size_t tdav_codec_g722_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)
{
- tdav_codec_g722_t* g722 = (tdav_codec_g722_t*)self;
-
- if (!self || !in_data || !in_size || !out_data){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- /* allocate new buffer */
- if (*out_max_size < (in_size << 2)){
- if (!(*out_data = tsk_realloc(*out_data, in_size << 2))){
- TSK_DEBUG_ERROR("Failed to allocate new buffer");
- *out_max_size = 0;
- return 0;
- }
- *out_max_size = in_size << 2;
- }
-
- g722_decode(g722->dec_state, (int16_t*)*out_data, (uint8_t*)in_data, (int)in_size);
-
- return (in_size << 2);
+ tdav_codec_g722_t* g722 = (tdav_codec_g722_t*)self;
+
+ if (!self || !in_data || !in_size || !out_data) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ /* allocate new buffer */
+ if (*out_max_size < (in_size << 2)) {
+ if (!(*out_data = tsk_realloc(*out_data, in_size << 2))) {
+ TSK_DEBUG_ERROR("Failed to allocate new buffer");
+ *out_max_size = 0;
+ return 0;
+ }
+ *out_max_size = in_size << 2;
+ }
+
+ g722_decode(g722->dec_state, (int16_t*)*out_data, (uint8_t*)in_data, (int)in_size);
+
+ return (in_size << 2);
}
static tsk_bool_t tdav_codec_g722_sdp_att_match(const tmedia_codec_t* codec, const char* att_name, const char* att_value)
{
- return tsk_true;
+ return tsk_true;
}
static char* tdav_codec_g722_sdp_att_get(const tmedia_codec_t* codec, const char* att_name)
{
- return tsk_null;
+ return tsk_null;
}
//
@@ -153,67 +152,65 @@ static char* tdav_codec_g722_sdp_att_get(const tmedia_codec_t* codec, const char
/* constructor */
static tsk_object_t* tdav_codec_g722_ctor(tsk_object_t * self, va_list * app)
{
- tdav_codec_g722_t *g722 = self;
- if (g722){
- /* init base: called by tmedia_codec_create() */
- /* init self */
+ tdav_codec_g722_t *g722 = self;
+ if (g722) {
+ /* init base: called by tmedia_codec_create() */
+ /* init self */
- }
- return self;
+ }
+ return self;
}
/* destructor */
static tsk_object_t* tdav_codec_g722_dtor(tsk_object_t * self)
{
- tdav_codec_g722_t *g722 = self;
- if (g722){
- /* deinit base */
- tmedia_codec_audio_deinit(g722);
- /* deinit self */
- if (g722->enc_state){
- g722_encode_release(g722->enc_state), g722->enc_state = tsk_null;
- }
- if (g722->dec_state){
- g722_decode_release(g722->dec_state), g722->dec_state = tsk_null;
- }
- }
-
- return self;
+ tdav_codec_g722_t *g722 = self;
+ if (g722) {
+ /* deinit base */
+ tmedia_codec_audio_deinit(g722);
+ /* deinit self */
+ if (g722->enc_state) {
+ g722_encode_release(g722->enc_state), g722->enc_state = tsk_null;
+ }
+ if (g722->dec_state) {
+ g722_decode_release(g722->dec_state), g722->dec_state = tsk_null;
+ }
+ }
+
+ return self;
}
/* object definition */
-static const tsk_object_def_t tdav_codec_g722_def_s =
-{
- sizeof(tdav_codec_g722_t),
- tdav_codec_g722_ctor,
- tdav_codec_g722_dtor,
- tmedia_codec_cmp,
+static const tsk_object_def_t tdav_codec_g722_def_s = {
+ sizeof(tdav_codec_g722_t),
+ tdav_codec_g722_ctor,
+ tdav_codec_g722_dtor,
+ tmedia_codec_cmp,
};
/* plugin definition*/
-static const tmedia_codec_plugin_def_t tdav_codec_g722_plugin_def_s =
-{
- &tdav_codec_g722_def_s,
-
- tmedia_audio,
- tmedia_codec_id_g722,
- "G722",
- "g722 Codec (native)",
- TMEDIA_CODEC_FORMAT_G722,
- tsk_false,
- 16000,
-
- { /* audio */
- 1, // channels
- 0 // ptime @deprecated
- },
-
- /* video */
- { 0 },
-
- tsk_null, // set()
- tdav_codec_g722_open,
- tdav_codec_g722_close,
- tdav_codec_g722_encode,
- tdav_codec_g722_decode,
- tdav_codec_g722_sdp_att_match,
- tdav_codec_g722_sdp_att_get
+static const tmedia_codec_plugin_def_t tdav_codec_g722_plugin_def_s = {
+ &tdav_codec_g722_def_s,
+
+ tmedia_audio,
+ tmedia_codec_id_g722,
+ "G722",
+ "g722 Codec (native)",
+ TMEDIA_CODEC_FORMAT_G722,
+ tsk_false,
+ 16000,
+
+ { /* audio */
+ 1, // channels
+ 0 // ptime @deprecated
+ },
+
+ /* video */
+ { 0 },
+
+ tsk_null, // set()
+ tdav_codec_g722_open,
+ tdav_codec_g722_close,
+ tdav_codec_g722_encode,
+ tdav_codec_g722_decode,
+ tdav_codec_g722_sdp_att_match,
+ tdav_codec_g722_sdp_att_get
};
const tmedia_codec_plugin_def_t *tdav_codec_g722_plugin_def_t = &tdav_codec_g722_plugin_def_s;
diff --git a/tinyDAV/src/codecs/g729/tdav_codec_g729.c b/tinyDAV/src/codecs/g729/tdav_codec_g729.c
index 8981687..43b3425 100755
--- a/tinyDAV/src/codecs/g729/tdav_codec_g729.c
+++ b/tinyDAV/src/codecs/g729/tdav_codec_g729.c
@@ -2,19 +2,19 @@
* Copyright (C) 2010-2011 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.
*
@@ -65,210 +65,210 @@ static void pack_SID(const int16_t ituBits[], uint8_t bitstream[]);
static int tdav_codec_g729ab_open(tmedia_codec_t* self)
{
- tdav_codec_g729ab_t* g729a = (tdav_codec_g729ab_t*)self;
-
- // Initialize the decoder
- bad_lsf = 0;
- g729a->decoder.synth = (g729a->decoder.synth_buf + M);
-
- Init_Decod_ld8a();
- Init_Post_Filter();
- Init_Post_Process();
- /* for G.729B */
- Init_Dec_cng();
-
- // Initialize the encoder
- Init_Pre_Process();
- Init_Coder_ld8a();
- Set_zero(g729a->encoder.prm, PRM_SIZE + 1);
- /* for G.729B */
- Init_Cod_cng();
-
-
- return 0;
+ tdav_codec_g729ab_t* g729a = (tdav_codec_g729ab_t*)self;
+
+ // Initialize the decoder
+ bad_lsf = 0;
+ g729a->decoder.synth = (g729a->decoder.synth_buf + M);
+
+ Init_Decod_ld8a();
+ Init_Post_Filter();
+ Init_Post_Process();
+ /* for G.729B */
+ Init_Dec_cng();
+
+ // Initialize the encoder
+ Init_Pre_Process();
+ Init_Coder_ld8a();
+ Set_zero(g729a->encoder.prm, PRM_SIZE + 1);
+ /* for G.729B */
+ Init_Cod_cng();
+
+
+ return 0;
}
static int tdav_codec_g729ab_close(tmedia_codec_t* self)
{
- tdav_codec_g729ab_t* g729a = (tdav_codec_g729ab_t*)self;
+ tdav_codec_g729ab_t* g729a = (tdav_codec_g729ab_t*)self;
+
+ (void)(g729a);
+
+ /* resources will be freed by the dctor() */
- (void)(g729a);
-
- /* resources will be freed by the dctor() */
-
- return 0;
+ return 0;
}
static tsk_size_t tdav_codec_g729ab_encode(tmedia_codec_t* self, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size)
-{
- tsk_size_t ex_size, out_size = 0;
- tdav_codec_g729ab_t* g729a = (tdav_codec_g729ab_t*)self;
- int i, frame_count = (in_size / 160);
-
-
- if(!self || !in_data || !in_size || !out_data || (in_size % 160)){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- ex_size = (frame_count * 10);
-
- // allocate new buffer if needed
- if(*out_max_size <ex_size){
- if(!(*out_data = tsk_realloc(*out_data, ex_size))){
- TSK_DEBUG_ERROR("Failed to allocate new buffer");
- *out_max_size = 0;
- return 0;
- }
- *out_max_size = ex_size;
- }
-
- for(i=0; i<frame_count; i++){
- extern int16_t *new_speech;
-
- if(g729a->encoder.frame == 32767){
- g729a->encoder.frame = 256;
- }
- else{
- g729a->encoder.frame++;
- }
-
- memcpy(new_speech, &((uint8_t*)in_data)[i*L_FRAME*sizeof(int16_t)], sizeof(int16_t)*L_FRAME);
-
- Pre_Process(new_speech, L_FRAME);
- Coder_ld8a(g729a->encoder.prm, g729a->encoder.frame, g729a->encoder.vad_enable);
- prm2bits_ld8k(g729a->encoder.prm, g729a->encoder.serial);
-
- if(g729a->encoder.serial[1] == RATE_8000){
- pack_G729(&g729a->encoder.serial[2], &((uint8_t*)(*out_data))[out_size]);
- out_size += 10;
- }
- else if(g729a->encoder.serial[1] == RATE_SID_OCTET){
- pack_SID(&g729a->encoder.serial[2], &((uint8_t*)(*out_data))[out_size]);
- out_size += 2;
- }
- else{ // RATE_0
- //TSK_DEBUG_INFO("G729_RATE_0 - Not transmitted");
+{
+ tsk_size_t ex_size, out_size = 0;
+ tdav_codec_g729ab_t* g729a = (tdav_codec_g729ab_t*)self;
+ int i, frame_count = (in_size / 160);
+
+
+ if(!self || !in_data || !in_size || !out_data || (in_size % 160)) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ ex_size = (frame_count * 10);
+
+ // allocate new buffer if needed
+ if(*out_max_size <ex_size) {
+ if(!(*out_data = tsk_realloc(*out_data, ex_size))) {
+ TSK_DEBUG_ERROR("Failed to allocate new buffer");
+ *out_max_size = 0;
+ return 0;
+ }
+ *out_max_size = ex_size;
+ }
+
+ for(i=0; i<frame_count; i++) {
+ extern int16_t *new_speech;
+
+ if(g729a->encoder.frame == 32767) {
+ g729a->encoder.frame = 256;
+ }
+ else {
+ g729a->encoder.frame++;
+ }
+
+ memcpy(new_speech, &((uint8_t*)in_data)[i*L_FRAME*sizeof(int16_t)], sizeof(int16_t)*L_FRAME);
+
+ Pre_Process(new_speech, L_FRAME);
+ Coder_ld8a(g729a->encoder.prm, g729a->encoder.frame, g729a->encoder.vad_enable);
+ prm2bits_ld8k(g729a->encoder.prm, g729a->encoder.serial);
+
+ if(g729a->encoder.serial[1] == RATE_8000) {
+ pack_G729(&g729a->encoder.serial[2], &((uint8_t*)(*out_data))[out_size]);
+ out_size += 10;
+ }
+ else if(g729a->encoder.serial[1] == RATE_SID_OCTET) {
+ pack_SID(&g729a->encoder.serial[2], &((uint8_t*)(*out_data))[out_size]);
+ out_size += 2;
+ }
+ else { // RATE_0
+ //TSK_DEBUG_INFO("G729_RATE_0 - Not transmitted");
if (!g729a->encoder.vad_enable) {
// silence
memset(&((uint8_t*)(*out_data))[out_size], 0, 10);
out_size += 10;
}
- }
- }
+ }
+ }
- return out_size;
+ return out_size;
}
static tsk_size_t tdav_codec_g729ab_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)
{
- tsk_size_t out_size = 0;
- int i, frame_count;
- const uint8_t* data_start = (const uint8_t*)in_data;
- const uint8_t* data_end;
- tdav_codec_g729ab_t* g729a = (tdav_codec_g729ab_t*)self;
-
- if(!self || !in_data || !in_size || !out_data || ((in_size % 10) && (in_size % 10 != 2))){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- data_end = (data_start + in_size);
-
- frame_count = (in_size/10) + ((in_size % 10) ? 1 : 0);
-
- out_size = 160*frame_count;
-
- /* allocate new buffer if needed */
- if(*out_max_size <out_size){
- if(!(*out_data = tsk_realloc(*out_data, out_size))){
- TSK_DEBUG_ERROR("Failed to allocate new buffer");
- *out_max_size = 0;
- return 0;
- }
- *out_max_size = out_size;
- }
-
- for(i=0; i<frame_count; i++){
- memset(g729a->decoder.synth_buf, 0, M);
- g729a->decoder.synth = g729a->decoder.synth_buf + M;
-
- if((data_end - data_start) == 2){
- unpack_SID(data_start, g729a->decoder.serial);
- data_start += 2;
- }
- else{
- unpack_G729(data_start, g729a->decoder.serial, 10);
- data_start += 10;
- }
-
- bits2prm_ld8k(&g729a->decoder.serial[1], g729a->decoder.parm);
-
- /* This part was modified for version V1.3 */
- /* for speech and SID frames, the hardware detects frame erasures
- by checking if all bits are set to zero */
- /* for untransmitted frames, the hardware detects frame erasures
- by testing serial[0] */
-
- g729a->decoder.parm[0] = 0; /* No frame erasure */
- if(g729a->decoder.serial[1] != 0) {
- int j;
- for (j=0; j < g729a->decoder.serial[1]; j++){
- if (g729a->decoder.serial[j+2] == 0){
- g729a->decoder.parm[0] = 1; /* frame erased */
- break;
- }
- }
- }
- else if(g729a->decoder.serial[0] != SYNC_WORD){
- g729a->decoder.parm[0] = 1;
- }
- if(g729a->decoder.parm[1] == 1) {
- /* check parity and put 1 in parm[5] if parity error */
- g729a->decoder.parm[5] = Check_Parity_Pitch(g729a->decoder.parm[4], g729a->decoder.parm[5]);
- }
-
- Decod_ld8a(g729a->decoder.parm, g729a->decoder.synth, g729a->decoder.Az_dec, g729a->decoder.T2, &g729a->decoder.Vad);
- Post_Filter(g729a->decoder.synth, g729a->decoder.Az_dec, g729a->decoder.T2, g729a->decoder.Vad); /* Post-filter */
- Post_Process(g729a->decoder.synth, L_FRAME);
-
- memcpy(&((uint8_t*)*out_data)[160*i], g729a->decoder.synth, 160);
- }
-
-
- return out_size;
+ tsk_size_t out_size = 0;
+ int i, frame_count;
+ const uint8_t* data_start = (const uint8_t*)in_data;
+ const uint8_t* data_end;
+ tdav_codec_g729ab_t* g729a = (tdav_codec_g729ab_t*)self;
+
+ if(!self || !in_data || !in_size || !out_data || ((in_size % 10) && (in_size % 10 != 2))) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ data_end = (data_start + in_size);
+
+ frame_count = (in_size/10) + ((in_size % 10) ? 1 : 0);
+
+ out_size = 160*frame_count;
+
+ /* allocate new buffer if needed */
+ if(*out_max_size <out_size) {
+ if(!(*out_data = tsk_realloc(*out_data, out_size))) {
+ TSK_DEBUG_ERROR("Failed to allocate new buffer");
+ *out_max_size = 0;
+ return 0;
+ }
+ *out_max_size = out_size;
+ }
+
+ for(i=0; i<frame_count; i++) {
+ memset(g729a->decoder.synth_buf, 0, M);
+ g729a->decoder.synth = g729a->decoder.synth_buf + M;
+
+ if((data_end - data_start) == 2) {
+ unpack_SID(data_start, g729a->decoder.serial);
+ data_start += 2;
+ }
+ else {
+ unpack_G729(data_start, g729a->decoder.serial, 10);
+ data_start += 10;
+ }
+
+ bits2prm_ld8k(&g729a->decoder.serial[1], g729a->decoder.parm);
+
+ /* This part was modified for version V1.3 */
+ /* for speech and SID frames, the hardware detects frame erasures
+ by checking if all bits are set to zero */
+ /* for untransmitted frames, the hardware detects frame erasures
+ by testing serial[0] */
+
+ g729a->decoder.parm[0] = 0; /* No frame erasure */
+ if(g729a->decoder.serial[1] != 0) {
+ int j;
+ for (j=0; j < g729a->decoder.serial[1]; j++) {
+ if (g729a->decoder.serial[j+2] == 0) {
+ g729a->decoder.parm[0] = 1; /* frame erased */
+ break;
+ }
+ }
+ }
+ else if(g729a->decoder.serial[0] != SYNC_WORD) {
+ g729a->decoder.parm[0] = 1;
+ }
+ if(g729a->decoder.parm[1] == 1) {
+ /* check parity and put 1 in parm[5] if parity error */
+ g729a->decoder.parm[5] = Check_Parity_Pitch(g729a->decoder.parm[4], g729a->decoder.parm[5]);
+ }
+
+ Decod_ld8a(g729a->decoder.parm, g729a->decoder.synth, g729a->decoder.Az_dec, g729a->decoder.T2, &g729a->decoder.Vad);
+ Post_Filter(g729a->decoder.synth, g729a->decoder.Az_dec, g729a->decoder.T2, g729a->decoder.Vad); /* Post-filter */
+ Post_Process(g729a->decoder.synth, L_FRAME);
+
+ memcpy(&((uint8_t*)*out_data)[160*i], g729a->decoder.synth, 160);
+ }
+
+
+ return out_size;
}
static tsk_bool_t tdav_codec_g729ab_sdp_att_match(const tmedia_codec_t* codec, const char* att_name, const char* att_value)
-{
- tdav_codec_g729ab_t* g729a = (tdav_codec_g729ab_t*)codec;
-
- if(tsk_striequals(att_name, "fmtp")){
- tsk_params_L_t* params = tsk_null;
- const char* val_str;
- if((params = tsk_params_fromstring(att_value, ";", tsk_true))){
- if((val_str = tsk_params_get_param_value(params, "annexb"))){
+{
+ tdav_codec_g729ab_t* g729a = (tdav_codec_g729ab_t*)codec;
+
+ if(tsk_striequals(att_name, "fmtp")) {
+ tsk_params_L_t* params = tsk_null;
+ const char* val_str;
+ if((params = tsk_params_fromstring(att_value, ";", tsk_true))) {
+ if((val_str = tsk_params_get_param_value(params, "annexb"))) {
g729a->encoder.vad_enable &= tsk_strequals(val_str, "yes") ? 1 : 0;
- }
- TSK_OBJECT_SAFE_FREE(params);
- }
- }
- return tsk_true;
+ }
+ TSK_OBJECT_SAFE_FREE(params);
+ }
+ }
+ return tsk_true;
}
static char* tdav_codec_g729ab_sdp_att_get(const tmedia_codec_t* codec, const char* att_name)
{
- tdav_codec_g729ab_t* g729a = (tdav_codec_g729ab_t*)codec;
-
- if(tsk_striequals(att_name, "fmtp")){
- if(g729a->encoder.vad_enable){
- return tsk_strdup("annexb=yes");
- }
- else{
- return tsk_strdup("annexb=no");
- }
- }
- return tsk_null;
+ tdav_codec_g729ab_t* g729a = (tdav_codec_g729ab_t*)codec;
+
+ if(tsk_striequals(att_name, "fmtp")) {
+ if(g729a->encoder.vad_enable) {
+ return tsk_strdup("annexb=yes");
+ }
+ else {
+ return tsk_strdup("annexb=no");
+ }
+ }
+ return tsk_null;
}
@@ -287,18 +287,18 @@ static char* tdav_codec_g729ab_sdp_att_get(const tmedia_codec_t* codec, const ch
*/
static int16_t bin2int(int16_t no_of_bits, const int16_t *bitstream)
{
- int16_t value, i;
- int16_t bit;
-
- value = 0;
- for(i = 0; i < no_of_bits; i++){
- value <<= 1;
- bit = *bitstream++;
- if (bit == BIT_1){
- value += 1;
- }
- }
- return(value);
+ int16_t value, i;
+ int16_t bit;
+
+ value = 0;
+ for(i = 0; i < no_of_bits; i++) {
+ value <<= 1;
+ bit = *bitstream++;
+ if (bit == BIT_1) {
+ value += 1;
+ }
+ }
+ return(value);
}
/*----------------------------------------------------------------------------
@@ -314,21 +314,21 @@ static int16_t bin2int(int16_t no_of_bits, const int16_t *bitstream)
*/
static void int2bin(int16_t value, int16_t no_of_bits, int16_t *bitstream)
{
- int16_t *pt_bitstream;
- int16_t i, bit;
-
- pt_bitstream = bitstream + no_of_bits;
-
- for (i = 0; i < no_of_bits; i++){
- bit = value & (int16_t)0x0001; /* get lsb */
- if (bit == 0){
- *--pt_bitstream = BIT_0;
- }
- else{
- *--pt_bitstream = BIT_1;
- }
- value >>= 1;
- }
+ int16_t *pt_bitstream;
+ int16_t i, bit;
+
+ pt_bitstream = bitstream + no_of_bits;
+
+ for (i = 0; i < no_of_bits; i++) {
+ bit = value & (int16_t)0x0001; /* get lsb */
+ if (bit == 0) {
+ *--pt_bitstream = BIT_0;
+ }
+ else {
+ *--pt_bitstream = BIT_1;
+ }
+ value >>= 1;
+ }
}
/**
@@ -337,24 +337,24 @@ static void int2bin(int16_t value, int16_t no_of_bits, int16_t *bitstream)
* @param bits ITU bitstream used as destination (0 - BIT_0, 1 - BIT_1)
* @param len length of the RTP bitstream
*/
-static void unpack_G729(const uint8_t bitstream[], int16_t bits[], int len)
-{
- int16_t i;
- *bits++ = SYNC_WORD; /* bit[0], at receiver this bits indicates BFI */
- switch(len){
- case 10:
- *bits++ = SIZE_WORD;
- break;
- case 8: // RATE_6400
- case 15: //RATE_11800
- default:
- TSK_DEBUG_ERROR("%d is an invalid lenght value", len);
- return;
- }
-
- for(i=0; i<len; i++){
- int2bin(bitstream[i], 8, &bits[i*8]);
- }
+static void unpack_G729(const uint8_t bitstream[], int16_t bits[], int len)
+{
+ int16_t i;
+ *bits++ = SYNC_WORD; /* bit[0], at receiver this bits indicates BFI */
+ switch(len) {
+ case 10:
+ *bits++ = SIZE_WORD;
+ break;
+ case 8: // RATE_6400
+ case 15: //RATE_11800
+ default:
+ TSK_DEBUG_ERROR("%d is an invalid lenght value", len);
+ return;
+ }
+
+ for(i=0; i<len; i++) {
+ int2bin(bitstream[i], 8, &bits[i*8]);
+ }
}
/**
@@ -363,11 +363,11 @@ static void unpack_G729(const uint8_t bitstream[], int16_t bits[], int len)
* @param bits ITU bitstream used as destination (0 - BIT_0, 1 - BIT_1)
*/
static void unpack_SID(const uint8_t bitstream[], int16_t bits[])
-{
- *bits++ = SYNC_WORD;
- *bits++ = RATE_SID_OCTET;
- int2bin((int16_t)bitstream[0], 8, &bits[0]);
- int2bin((int16_t)bitstream[1], 8, &bits[8]);
+{
+ *bits++ = SYNC_WORD;
+ *bits++ = RATE_SID_OCTET;
+ int2bin((int16_t)bitstream[0], 8, &bits[0]);
+ int2bin((int16_t)bitstream[1], 8, &bits[8]);
}
/**
@@ -376,9 +376,9 @@ static void unpack_SID(const uint8_t bitstream[], int16_t bits[])
* @param bitstream RTP bitstream (80 bits, 5 shorts, 10 bytes)
*/
static void pack_G729(const int16_t ituBits[], uint8_t bitstream[])
-{
+{
int16_t word16, i;
- for(i=0; i<5; i++){
+ for(i=0; i<5; i++) {
word16 = bin2int(16, (int16_t*)&ituBits[i*16]);
bitstream[i*2] = word16>>8, bitstream[(i*2)+1] = (word16 & 0xFF);
}
@@ -390,10 +390,10 @@ static void pack_G729(const int16_t ituBits[], uint8_t bitstream[])
* @param bitstream RTP bitstream (15 bits, 1 short, 2 bytes)
*/
static void pack_SID(const int16_t ituBits[], uint8_t bitstream[])
-{
+{
int16_t word16 = bin2int(16, ituBits);
bitstream[0] = word16>>8, bitstream[1] = (word16 & 0xFF);
-}
+}
//
@@ -403,63 +403,61 @@ static void pack_SID(const int16_t ituBits[], uint8_t bitstream[])
/* constructor */
static tsk_object_t* tdav_codec_g729ab_ctor(tsk_object_t * self, va_list * app)
{
- tdav_codec_g729ab_t *g729a = self;
- if(g729a){
- /* init base: called by tmedia_codec_create() */
- /* init self */
- g729a->encoder.vad_enable = G729_ENABLE_VAD; // AnnexB
- }
- return self;
+ tdav_codec_g729ab_t *g729a = self;
+ if(g729a) {
+ /* init base: called by tmedia_codec_create() */
+ /* init self */
+ g729a->encoder.vad_enable = G729_ENABLE_VAD; // AnnexB
+ }
+ return self;
}
/* destructor */
static tsk_object_t* tdav_codec_g729ab_dtor(tsk_object_t * self)
-{
- tdav_codec_g729ab_t *g729a = self;
- if(g729a){
- /* deinit base */
- tmedia_codec_audio_deinit(g729a);
- /* deinit self */
-
- }
-
- return self;
+{
+ tdav_codec_g729ab_t *g729a = self;
+ if(g729a) {
+ /* deinit base */
+ tmedia_codec_audio_deinit(g729a);
+ /* deinit self */
+
+ }
+
+ return self;
}
/* object definition */
-static const tsk_object_def_t tdav_codec_g729ab_def_s =
-{
- sizeof(tdav_codec_g729ab_t),
- tdav_codec_g729ab_ctor,
- tdav_codec_g729ab_dtor,
- tmedia_codec_cmp,
+static const tsk_object_def_t tdav_codec_g729ab_def_s = {
+ sizeof(tdav_codec_g729ab_t),
+ tdav_codec_g729ab_ctor,
+ tdav_codec_g729ab_dtor,
+ tmedia_codec_cmp,
};
/* plugin definition*/
-static const tmedia_codec_plugin_def_t tdav_codec_g729ab_plugin_def_s =
-{
- &tdav_codec_g729ab_def_s,
-
- tmedia_audio,
- tmedia_codec_id_g729ab,
- "g729",
- "g729ab Codec (libg729)",
- TMEDIA_CODEC_FORMAT_G729,
- tsk_false,
- 8000, // rate
-
- { /* audio */
- 1, // channels
- 0 // ptime @deprecated
- },
-
- /* video */
- {0},
-
- tdav_codec_g729ab_set,
- tdav_codec_g729ab_open,
- tdav_codec_g729ab_close,
- tdav_codec_g729ab_encode,
- tdav_codec_g729ab_decode,
- tdav_codec_g729ab_sdp_att_match,
- tdav_codec_g729ab_sdp_att_get
+static const tmedia_codec_plugin_def_t tdav_codec_g729ab_plugin_def_s = {
+ &tdav_codec_g729ab_def_s,
+
+ tmedia_audio,
+ tmedia_codec_id_g729ab,
+ "g729",
+ "g729ab Codec (libg729)",
+ TMEDIA_CODEC_FORMAT_G729,
+ tsk_false,
+ 8000, // rate
+
+ { /* audio */
+ 1, // channels
+ 0 // ptime @deprecated
+ },
+
+ /* video */
+ {0},
+
+ tdav_codec_g729ab_set,
+ tdav_codec_g729ab_open,
+ tdav_codec_g729ab_close,
+ tdav_codec_g729ab_encode,
+ tdav_codec_g729ab_decode,
+ tdav_codec_g729ab_sdp_att_match,
+ tdav_codec_g729ab_sdp_att_get
};
const tmedia_codec_plugin_def_t *tdav_codec_g729ab_plugin_def_t = &tdav_codec_g729ab_plugin_def_s;
diff --git a/tinyDAV/src/codecs/gsm/tdav_codec_gsm.c b/tinyDAV/src/codecs/gsm/tdav_codec_gsm.c
index 8b5f1bc..31e5139 100755
--- a/tinyDAV/src/codecs/gsm/tdav_codec_gsm.c
+++ b/tinyDAV/src/codecs/gsm/tdav_codec_gsm.c
@@ -2,19 +2,19 @@
* Copyright (C) 2010-2011 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.
*
@@ -43,94 +43,95 @@
int tdav_codec_gsm_open(tmedia_codec_t* self)
{
- tdav_codec_gsm_t* gsm = (tdav_codec_gsm_t*)self;
-
- if(!gsm->encoder && !(gsm->encoder = gsm_create())){
- TSK_DEBUG_ERROR("Failed to create GSM encoder");
- return -2;
- }
- if(!gsm->decoder && !(gsm->decoder = gsm_create())){
- TSK_DEBUG_ERROR("Failed to create GSM decoder");
- return -3;
- }
-
- return 0;
+ tdav_codec_gsm_t* gsm = (tdav_codec_gsm_t*)self;
+
+ if(!gsm->encoder && !(gsm->encoder = gsm_create())) {
+ TSK_DEBUG_ERROR("Failed to create GSM encoder");
+ return -2;
+ }
+ if(!gsm->decoder && !(gsm->decoder = gsm_create())) {
+ TSK_DEBUG_ERROR("Failed to create GSM decoder");
+ return -3;
+ }
+
+ return 0;
}
int tdav_codec_gsm_close(tmedia_codec_t* self)
{
- tdav_codec_gsm_t* gsm = (tdav_codec_gsm_t*)self;
-
- if(gsm->encoder){
- gsm_destroy(gsm->encoder);
- gsm->encoder = tsk_null;
- }
- if(gsm->decoder){
- gsm_destroy(gsm->decoder);
- gsm->decoder = tsk_null;
- }
-
- return 0;
+ tdav_codec_gsm_t* gsm = (tdav_codec_gsm_t*)self;
+
+ if(gsm->encoder) {
+ gsm_destroy(gsm->encoder);
+ gsm->encoder = tsk_null;
+ }
+ if(gsm->decoder) {
+ gsm_destroy(gsm->decoder);
+ gsm->decoder = tsk_null;
+ }
+
+ return 0;
}
tsk_size_t tdav_codec_gsm_encode(tmedia_codec_t* self, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size)
-{
- tsk_size_t out_size;
- tdav_codec_gsm_t* gsm = (tdav_codec_gsm_t*)self;
-
- if(!self || !in_data || !in_size || !out_data){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- out_size = ((in_size / (TMEDIA_CODEC_PCM_FRAME_SIZE_AUDIO_ENCODING(self) * sizeof(short))) * TDAV_GSM_FRAME_SIZE);
-
- /* allocate new buffer if needed */
- if(*out_max_size <out_size){
- if(!(*out_data = tsk_realloc(*out_data, out_size))){
- TSK_DEBUG_ERROR("Failed to allocate new buffer");
- *out_max_size = 0;
- return 0;
- }
- *out_max_size = out_size;
- }
-
- gsm_encode(gsm->encoder, (gsm_signal*)in_data, (gsm_byte*)*out_data);
-
- return out_size;
+{
+ tsk_size_t out_size;
+ tdav_codec_gsm_t* gsm = (tdav_codec_gsm_t*)self;
+
+ if(!self || !in_data || !in_size || !out_data) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ out_size = ((in_size / (TMEDIA_CODEC_PCM_FRAME_SIZE_AUDIO_ENCODING(self) * sizeof(short))) * TDAV_GSM_FRAME_SIZE);
+
+ /* allocate new buffer if needed */
+ if(*out_max_size <out_size) {
+ if(!(*out_data = tsk_realloc(*out_data, out_size))) {
+ TSK_DEBUG_ERROR("Failed to allocate new buffer");
+ *out_max_size = 0;
+ return 0;
+ }
+ *out_max_size = out_size;
+ }
+
+ gsm_encode(gsm->encoder, (gsm_signal*)in_data, (gsm_byte*)*out_data);
+
+ return out_size;
}
tsk_size_t tdav_codec_gsm_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)
{
- tsk_size_t out_size;
- int ret;
- tdav_codec_gsm_t* gsm = (tdav_codec_gsm_t*)self;
-
- if(!self || !in_data || !in_size || !out_data || (in_size % TDAV_GSM_FRAME_SIZE)){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- out_size = (in_size / TDAV_GSM_FRAME_SIZE) * (TMEDIA_CODEC_PCM_FRAME_SIZE_AUDIO_DECODING(self) * sizeof(short));
-
- /* allocate new buffer if needed */
- if(*out_max_size <out_size){
- if(!(*out_data = tsk_realloc(*out_data, out_size))){
- TSK_DEBUG_ERROR("Failed to allocate new buffer");
- *out_max_size = 0;
- return 0;
- }
- *out_max_size = out_size;
- }
-
- ret = gsm_decode(gsm->decoder, (gsm_byte*)in_data, (gsm_signal*)*out_data);
-
- return out_size;
+ tsk_size_t out_size;
+ int ret;
+ tdav_codec_gsm_t* gsm = (tdav_codec_gsm_t*)self;
+
+ if(!self || !in_data || !in_size || !out_data || (in_size % TDAV_GSM_FRAME_SIZE)) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ out_size = (in_size / TDAV_GSM_FRAME_SIZE) * (TMEDIA_CODEC_PCM_FRAME_SIZE_AUDIO_DECODING(self) * sizeof(short));
+
+ /* allocate new buffer if needed */
+ if(*out_max_size <out_size) {
+ if(!(*out_data = tsk_realloc(*out_data, out_size))) {
+ TSK_DEBUG_ERROR("Failed to allocate new buffer");
+ *out_max_size = 0;
+ return 0;
+ }
+ *out_max_size = out_size;
+ }
+
+ ret = gsm_decode(gsm->decoder, (gsm_byte*)in_data, (gsm_signal*)*out_data);
+
+ return out_size;
}
tsk_bool_t tdav_codec_gsm_sdp_att_match(const tmedia_codec_t* codec, const char* att_name, const char* att_value)
-{ /* always match */
- return tsk_true;
+{
+ /* always match */
+ return tsk_true;
}
@@ -141,67 +142,65 @@ tsk_bool_t tdav_codec_gsm_sdp_att_match(const tmedia_codec_t* codec, const char*
/* constructor */
static tsk_object_t* tdav_codec_gsm_ctor(tsk_object_t * self, va_list * app)
{
- tdav_codec_gsm_t *gsm = self;
- if(gsm){
- /* init base: called by tmedia_codec_create() */
- /* init self */
- }
- return self;
+ tdav_codec_gsm_t *gsm = self;
+ if(gsm) {
+ /* init base: called by tmedia_codec_create() */
+ /* init self */
+ }
+ return self;
}
/* destructor */
static tsk_object_t* tdav_codec_gsm_dtor(tsk_object_t * self)
-{
- tdav_codec_gsm_t *gsm = self;
- if(gsm){
- /* deinit base */
- tmedia_codec_audio_deinit(gsm);
- /* deinit self */
- if(gsm->encoder){
- gsm_destroy(gsm->encoder);
- }
- if(gsm->decoder){
- gsm_destroy(gsm->decoder);
- }
- }
-
- return self;
+{
+ tdav_codec_gsm_t *gsm = self;
+ if(gsm) {
+ /* deinit base */
+ tmedia_codec_audio_deinit(gsm);
+ /* deinit self */
+ if(gsm->encoder) {
+ gsm_destroy(gsm->encoder);
+ }
+ if(gsm->decoder) {
+ gsm_destroy(gsm->decoder);
+ }
+ }
+
+ return self;
}
/* object definition */
-static const tsk_object_def_t tdav_codec_gsm_def_s =
-{
- sizeof(tdav_codec_gsm_t),
- tdav_codec_gsm_ctor,
- tdav_codec_gsm_dtor,
- tmedia_codec_cmp,
+static const tsk_object_def_t tdav_codec_gsm_def_s = {
+ sizeof(tdav_codec_gsm_t),
+ tdav_codec_gsm_ctor,
+ tdav_codec_gsm_dtor,
+ tmedia_codec_cmp,
};
/* plugin definition*/
-static const tmedia_codec_plugin_def_t tdav_codec_gsm_plugin_def_s =
-{
- &tdav_codec_gsm_def_s,
-
- tmedia_audio,
- tmedia_codec_id_gsm,
- "GSM",
- "GSM Full Rate (libgsm)",
- TMEDIA_CODEC_FORMAT_GSM,
- tsk_false,
- 8000, // rate
-
- { /* audio */
- 1, // channels
- 0 // ptime @deprecated
- },
-
- /* video */
- {0},
-
- tsk_null, // set()
- tdav_codec_gsm_open,
- tdav_codec_gsm_close,
- tdav_codec_gsm_encode,
- tdav_codec_gsm_decode,
- tdav_codec_gsm_sdp_att_match,
- tdav_codec_gsm_sdp_att_get
+static const tmedia_codec_plugin_def_t tdav_codec_gsm_plugin_def_s = {
+ &tdav_codec_gsm_def_s,
+
+ tmedia_audio,
+ tmedia_codec_id_gsm,
+ "GSM",
+ "GSM Full Rate (libgsm)",
+ TMEDIA_CODEC_FORMAT_GSM,
+ tsk_false,
+ 8000, // rate
+
+ { /* audio */
+ 1, // channels
+ 0 // ptime @deprecated
+ },
+
+ /* video */
+ {0},
+
+ tsk_null, // set()
+ tdav_codec_gsm_open,
+ tdav_codec_gsm_close,
+ tdav_codec_gsm_encode,
+ tdav_codec_gsm_decode,
+ tdav_codec_gsm_sdp_att_match,
+ tdav_codec_gsm_sdp_att_get
};
const tmedia_codec_plugin_def_t *tdav_codec_gsm_plugin_def_t = &tdav_codec_gsm_plugin_def_s;
diff --git a/tinyDAV/src/codecs/h261/tdav_codec_h261.c b/tinyDAV/src/codecs/h261/tdav_codec_h261.c
index 27aaab7..687bc68 100755
--- a/tinyDAV/src/codecs/h261/tdav_codec_h261.c
+++ b/tinyDAV/src/codecs/h261/tdav_codec_h261.c
@@ -2,19 +2,19 @@
* Copyright (C) 2010-2011 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.
*
@@ -57,375 +57,373 @@ static void tdav_codec_h261_encap(const tdav_codec_h261_t* h261, const uint8_t*
//
int tdav_codec_h261_open(tmedia_codec_t* self)
{
- int ret;
- int size;
-
- tdav_codec_h261_t* h261 = (tdav_codec_h261_t*)self;
-
- if(!h261){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- /* the caller (base class) already checked that the codec is not opened */
-
- //
- // Encoder
- //
- if(!(h261->encoder.codec = avcodec_find_encoder(CODEC_ID_H261))){
- TSK_DEBUG_ERROR("Failed to find H.261 encoder");
- return -2;
- }
- h261->encoder.context = avcodec_alloc_context();
- avcodec_get_context_defaults(h261->encoder.context);
-
- h261->encoder.context->pix_fmt = PIX_FMT_YUV420P;
- h261->encoder.context->time_base.num = 1;
- h261->encoder.context->time_base.den = TMEDIA_CODEC_VIDEO(h261)->out.fps;
- h261->encoder.context->width = TMEDIA_CODEC_VIDEO(h261)->out.width;
- h261->encoder.context->height = TMEDIA_CODEC_VIDEO(h261)->out.height;
-
- /*h261->encoder.context->mb_qmin =*/ h261->encoder.context->qmin = 4;
- /*h261->encoder.context->mb_qmax =*/ h261->encoder.context->qmax = 31;
- h261->encoder.context->mb_decision = FF_MB_DECISION_SIMPLE;
-
- h261->encoder.context->thread_count = 1;
- h261->encoder.context->rtp_payload_size = RTP_PAYLOAD_SIZE;
- h261->encoder.context->opaque = tsk_null;
- h261->encoder.context->bit_rate = (float) (500000) * 0.80f;
- h261->encoder.context->bit_rate_tolerance = (int) (500000 * 0.20f);
- h261->encoder.context->gop_size = TMEDIA_CODEC_VIDEO(h261)->out.fps*4; /* each 4 seconds */
-
- // Picture (YUV 420)
- if(!(h261->encoder.picture = avcodec_alloc_frame())){
- TSK_DEBUG_ERROR("Failed to create encoder picture");
- return -2;
- }
- avcodec_get_frame_defaults(h261->encoder.picture);
- //if((ret = avpicture_alloc((AVPicture*)h261->encoder.picture, PIX_FMT_YUV420P, h261->encoder.context->width, h261->encoder.context->height))){
- // TSK_DEBUG_ERROR("Failed to allocate encoder picture");
- // return ret;
- //}
-
- size = avpicture_get_size(PIX_FMT_YUV420P, h261->encoder.context->width, h261->encoder.context->height);
- if(!(h261->encoder.buffer = tsk_calloc(size, sizeof(uint8_t)))){
- TSK_DEBUG_ERROR("Failed to allocate encoder buffer");
- return -2;
- }
-
- // Open encoder
- if((ret = avcodec_open(h261->encoder.context, h261->encoder.codec)) < 0){
- TSK_DEBUG_ERROR("Failed to open H.261 encoder");
- return ret;
- }
-
- //
- // Decoder
- //
- if(!(h261->decoder.codec = avcodec_find_decoder(CODEC_ID_H261))){
- TSK_DEBUG_ERROR("Failed to find H.261 decoder");
- }
- h261->decoder.context = avcodec_alloc_context();
- avcodec_get_context_defaults(h261->decoder.context);
-
- h261->decoder.context->pix_fmt = PIX_FMT_YUV420P;
- h261->decoder.context->width = TMEDIA_CODEC_VIDEO(h261)->in.width;
- h261->decoder.context->height = TMEDIA_CODEC_VIDEO(h261)->in.height;
-
- // Picture (YUV 420)
- if(!(h261->decoder.picture = avcodec_alloc_frame())){
- TSK_DEBUG_ERROR("Failed to create decoder picture");
- return -2;
- }
- avcodec_get_frame_defaults(h261->decoder.picture);
-
- size = avpicture_get_size(PIX_FMT_YUV420P, h261->decoder.context->width, h261->decoder.context->height);
- if(!(h261->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(h261->decoder.context, h261->decoder.codec)) < 0){
- TSK_DEBUG_ERROR("Failed to open H.261 decoder");
- return ret;
- }
-
- return 0;
+ int ret;
+ int size;
+
+ tdav_codec_h261_t* h261 = (tdav_codec_h261_t*)self;
+
+ if(!h261) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ /* the caller (base class) already checked that the codec is not opened */
+
+ //
+ // Encoder
+ //
+ if(!(h261->encoder.codec = avcodec_find_encoder(CODEC_ID_H261))) {
+ TSK_DEBUG_ERROR("Failed to find H.261 encoder");
+ return -2;
+ }
+ h261->encoder.context = avcodec_alloc_context();
+ avcodec_get_context_defaults(h261->encoder.context);
+
+ h261->encoder.context->pix_fmt = PIX_FMT_YUV420P;
+ h261->encoder.context->time_base.num = 1;
+ h261->encoder.context->time_base.den = TMEDIA_CODEC_VIDEO(h261)->out.fps;
+ h261->encoder.context->width = TMEDIA_CODEC_VIDEO(h261)->out.width;
+ h261->encoder.context->height = TMEDIA_CODEC_VIDEO(h261)->out.height;
+
+ /*h261->encoder.context->mb_qmin =*/ h261->encoder.context->qmin = 4;
+ /*h261->encoder.context->mb_qmax =*/ h261->encoder.context->qmax = 31;
+ h261->encoder.context->mb_decision = FF_MB_DECISION_SIMPLE;
+
+ h261->encoder.context->thread_count = 1;
+ h261->encoder.context->rtp_payload_size = RTP_PAYLOAD_SIZE;
+ h261->encoder.context->opaque = tsk_null;
+ h261->encoder.context->bit_rate = (float) (500000) * 0.80f;
+ h261->encoder.context->bit_rate_tolerance = (int) (500000 * 0.20f);
+ h261->encoder.context->gop_size = TMEDIA_CODEC_VIDEO(h261)->out.fps*4; /* each 4 seconds */
+
+ // Picture (YUV 420)
+ if(!(h261->encoder.picture = avcodec_alloc_frame())) {
+ TSK_DEBUG_ERROR("Failed to create encoder picture");
+ return -2;
+ }
+ avcodec_get_frame_defaults(h261->encoder.picture);
+ //if((ret = avpicture_alloc((AVPicture*)h261->encoder.picture, PIX_FMT_YUV420P, h261->encoder.context->width, h261->encoder.context->height))){
+ // TSK_DEBUG_ERROR("Failed to allocate encoder picture");
+ // return ret;
+ //}
+
+ size = avpicture_get_size(PIX_FMT_YUV420P, h261->encoder.context->width, h261->encoder.context->height);
+ if(!(h261->encoder.buffer = tsk_calloc(size, sizeof(uint8_t)))) {
+ TSK_DEBUG_ERROR("Failed to allocate encoder buffer");
+ return -2;
+ }
+
+ // Open encoder
+ if((ret = avcodec_open(h261->encoder.context, h261->encoder.codec)) < 0) {
+ TSK_DEBUG_ERROR("Failed to open H.261 encoder");
+ return ret;
+ }
+
+ //
+ // Decoder
+ //
+ if(!(h261->decoder.codec = avcodec_find_decoder(CODEC_ID_H261))) {
+ TSK_DEBUG_ERROR("Failed to find H.261 decoder");
+ }
+ h261->decoder.context = avcodec_alloc_context();
+ avcodec_get_context_defaults(h261->decoder.context);
+
+ h261->decoder.context->pix_fmt = PIX_FMT_YUV420P;
+ h261->decoder.context->width = TMEDIA_CODEC_VIDEO(h261)->in.width;
+ h261->decoder.context->height = TMEDIA_CODEC_VIDEO(h261)->in.height;
+
+ // Picture (YUV 420)
+ if(!(h261->decoder.picture = avcodec_alloc_frame())) {
+ TSK_DEBUG_ERROR("Failed to create decoder picture");
+ return -2;
+ }
+ avcodec_get_frame_defaults(h261->decoder.picture);
+
+ size = avpicture_get_size(PIX_FMT_YUV420P, h261->decoder.context->width, h261->decoder.context->height);
+ if(!(h261->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(h261->decoder.context, h261->decoder.codec)) < 0) {
+ TSK_DEBUG_ERROR("Failed to open H.261 decoder");
+ return ret;
+ }
+
+ return 0;
}
int tdav_codec_h261_close(tmedia_codec_t* self)
{
- tdav_codec_h261_t* h261 = (tdav_codec_h261_t*)self;
-
- if(!h261){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- /* the caller (base class) already checked that the codec is opened */
-
- //
- // Encoder
- //
- if(h261->encoder.context){
- avcodec_close(h261->encoder.context);
- av_free(h261->encoder.context);
- h261->encoder.context = tsk_null;
- }
- if(h261->encoder.picture){
- av_free(h261->encoder.picture);
- }
- if(h261->encoder.buffer){
- TSK_FREE(h261->encoder.buffer);
- }
-
- //
- // Decoder
- //
- if(h261->decoder.context){
- avcodec_close(h261->decoder.context);
- av_free(h261->decoder.context);
- h261->decoder.context = tsk_null;
- }
- if(h261->decoder.picture){
- av_free(h261->decoder.picture);
- h261->decoder.picture = tsk_null;
- }
- if(h261->decoder.accumulator){
- TSK_FREE(h261->decoder.accumulator);
- h261->decoder.accumulator_pos = 0;
- }
-
- return 0;
+ tdav_codec_h261_t* h261 = (tdav_codec_h261_t*)self;
+
+ if(!h261) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ /* the caller (base class) already checked that the codec is opened */
+
+ //
+ // Encoder
+ //
+ if(h261->encoder.context) {
+ avcodec_close(h261->encoder.context);
+ av_free(h261->encoder.context);
+ h261->encoder.context = tsk_null;
+ }
+ if(h261->encoder.picture) {
+ av_free(h261->encoder.picture);
+ }
+ if(h261->encoder.buffer) {
+ TSK_FREE(h261->encoder.buffer);
+ }
+
+ //
+ // Decoder
+ //
+ if(h261->decoder.context) {
+ avcodec_close(h261->decoder.context);
+ av_free(h261->decoder.context);
+ h261->decoder.context = tsk_null;
+ }
+ if(h261->decoder.picture) {
+ av_free(h261->decoder.picture);
+ h261->decoder.picture = tsk_null;
+ }
+ if(h261->decoder.accumulator) {
+ TSK_FREE(h261->decoder.accumulator);
+ h261->decoder.accumulator_pos = 0;
+ }
+
+ return 0;
}
tsk_size_t tdav_codec_h261_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_h261_t* h261 = (tdav_codec_h261_t*)self;
-
- if(!self || !in_data || !in_size || !out_data){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- // delete old buffer
- if(*out_data){
- TSK_FREE(*out_data);
- }
-
- // wrap yuv420 buffer
- size = avpicture_fill((AVPicture *)h261->encoder.picture, (uint8_t*)in_data, PIX_FMT_YUV420P, h261->encoder.context->width, h261->encoder.context->height);
- if(size != in_size){
- /* guard */
- TSK_DEBUG_ERROR("Invalid size");
- return 0;
- }
-
- // Encode data
- h261->encoder.picture->pts = AV_NOPTS_VALUE;
- //h261->encoder.picture->pict_type = FF_I_TYPE;
- ret = avcodec_encode_video(h261->encoder.context, h261->encoder.buffer, size, h261->encoder.picture);
- if(ret > 0){
- tdav_codec_h261_encap(h261, h261->encoder.buffer, (tsk_size_t)ret);
- }
-
- return 0;
+ int ret;
+ int size;
+
+ tdav_codec_h261_t* h261 = (tdav_codec_h261_t*)self;
+
+ if(!self || !in_data || !in_size || !out_data) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ // delete old buffer
+ if(*out_data) {
+ TSK_FREE(*out_data);
+ }
+
+ // wrap yuv420 buffer
+ size = avpicture_fill((AVPicture *)h261->encoder.picture, (uint8_t*)in_data, PIX_FMT_YUV420P, h261->encoder.context->width, h261->encoder.context->height);
+ if(size != in_size) {
+ /* guard */
+ TSK_DEBUG_ERROR("Invalid size");
+ return 0;
+ }
+
+ // Encode data
+ h261->encoder.picture->pts = AV_NOPTS_VALUE;
+ //h261->encoder.picture->pict_type = FF_I_TYPE;
+ ret = avcodec_encode_video(h261->encoder.context, h261->encoder.buffer, size, h261->encoder.picture);
+ if(ret > 0) {
+ tdav_codec_h261_encap(h261, h261->encoder.buffer, (tsk_size_t)ret);
+ }
+
+ return 0;
}
tsk_size_t tdav_codec_h261_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)
{
- uint8_t sbit, ebit;
- const uint8_t* pdata = in_data;
- const uint8_t* pay_ptr;
- tsk_size_t pay_size;
- tsk_size_t xsize, retsize = 0;
- int got_picture_ptr;
- int ret;
-
- tdav_codec_h261_t* h261 = (tdav_codec_h261_t*)self;
- const trtp_rtp_header_t* rtp_hdr = proto_hdr;
-
- if(!self || !in_data || !in_size || !out_data || !h261->decoder.context){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- /* RFC 4587
- 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
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- |SBIT |EBIT |I|V| GOBN | MBAP | QUANT | HMVD | VMVD |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
- sbit = *pdata >> 5;
- ebit = (*pdata >> 2) & 0x07;
-
- /* Check size */
- if(in_size < H261_HEADER_SIZE){
- TSK_DEBUG_ERROR("Too short");
- return 0;
- }
-
- pay_ptr = (pdata + H261_HEADER_SIZE);
- pay_size = (in_size - H261_HEADER_SIZE);
- xsize = avpicture_get_size(h261->decoder.context->pix_fmt, h261->decoder.context->width, h261->decoder.context->height);
-
- /* Packet lost? */
- if(h261->decoder.last_seq != (rtp_hdr->seq_num - 1) && h261->decoder.last_seq){
- TSK_DEBUG_INFO("Packet lost");
- }
- h261->decoder.last_seq = rtp_hdr->seq_num;
-
- if((int)(h261->decoder.accumulator_pos + pay_size) <= xsize){
-
- if((h261->decoder.ebit + sbit) == 8){ /* Perfect one Byte to clean up */
- if(h261->decoder.accumulator_pos){
- ((uint8_t*)h261->decoder.accumulator)[h261->decoder.accumulator_pos-1] =
- (((uint8_t*)h261->decoder.accumulator)[h261->decoder.accumulator_pos-1] & (0xFF << h261->decoder.ebit)) |
- (*pay_ptr << sbit);
- }
- pay_ptr++, pay_size--;
- }
- h261->decoder.ebit = ebit;
-
- memcpy(&((uint8_t*)h261->decoder.accumulator)[h261->decoder.accumulator_pos], pay_ptr, pay_size);
- h261->decoder.accumulator_pos += pay_size;
- }
- else{
- TSK_DEBUG_WARN("Buffer overflow");
- h261->decoder.accumulator_pos = 0;
- return 0;
- }
-
- if(rtp_hdr->marker){
- AVPacket packet;
- /* allocate destination buffer */
- if(*out_max_size <xsize){
- if(!(*out_data = tsk_realloc(*out_data, xsize))){
- TSK_DEBUG_ERROR("Failed to allocate new buffer");
- *out_max_size = 0;
- h261->decoder.accumulator_pos = 0;
- return 0;
- }
- *out_max_size = xsize;
- }
-
- /* decode the picture */
- av_init_packet(&packet);
- packet.size = (int)h261->decoder.accumulator_pos;
- packet.data = h261->decoder.accumulator;
- ret = avcodec_decode_video2(h261->decoder.context, h261->decoder.picture, &got_picture_ptr, &packet);
-
- if(ret <0 || !got_picture_ptr){
- TSK_DEBUG_WARN("Failed to decode the buffer");
- }
- else{
- retsize = xsize;
- TMEDIA_CODEC_VIDEO(h261)->in.width = h261->decoder.context->width;
- TMEDIA_CODEC_VIDEO(h261)->in.height = h261->decoder.context->height;
- /* copy picture into a linear buffer */
- avpicture_layout((AVPicture *)h261->decoder.picture, h261->decoder.context->pix_fmt, (int)h261->decoder.context->width, (int)h261->decoder.context->height,
- *out_data, (int)retsize);
- }
- /* in all cases: reset accumulator */
- h261->decoder.accumulator_pos = 0;
- }
-
- return retsize;
+ uint8_t sbit, ebit;
+ const uint8_t* pdata = in_data;
+ const uint8_t* pay_ptr;
+ tsk_size_t pay_size;
+ tsk_size_t xsize, retsize = 0;
+ int got_picture_ptr;
+ int ret;
+
+ tdav_codec_h261_t* h261 = (tdav_codec_h261_t*)self;
+ const trtp_rtp_header_t* rtp_hdr = proto_hdr;
+
+ if(!self || !in_data || !in_size || !out_data || !h261->decoder.context) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ /* RFC 4587
+ 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
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |SBIT |EBIT |I|V| GOBN | MBAP | QUANT | HMVD | VMVD |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+ sbit = *pdata >> 5;
+ ebit = (*pdata >> 2) & 0x07;
+
+ /* Check size */
+ if(in_size < H261_HEADER_SIZE) {
+ TSK_DEBUG_ERROR("Too short");
+ return 0;
+ }
+
+ pay_ptr = (pdata + H261_HEADER_SIZE);
+ pay_size = (in_size - H261_HEADER_SIZE);
+ xsize = avpicture_get_size(h261->decoder.context->pix_fmt, h261->decoder.context->width, h261->decoder.context->height);
+
+ /* Packet lost? */
+ if(h261->decoder.last_seq != (rtp_hdr->seq_num - 1) && h261->decoder.last_seq) {
+ TSK_DEBUG_INFO("Packet lost");
+ }
+ h261->decoder.last_seq = rtp_hdr->seq_num;
+
+ if((int)(h261->decoder.accumulator_pos + pay_size) <= xsize) {
+
+ if((h261->decoder.ebit + sbit) == 8) { /* Perfect one Byte to clean up */
+ if(h261->decoder.accumulator_pos) {
+ ((uint8_t*)h261->decoder.accumulator)[h261->decoder.accumulator_pos-1] =
+ (((uint8_t*)h261->decoder.accumulator)[h261->decoder.accumulator_pos-1] & (0xFF << h261->decoder.ebit)) |
+ (*pay_ptr << sbit);
+ }
+ pay_ptr++, pay_size--;
+ }
+ h261->decoder.ebit = ebit;
+
+ memcpy(&((uint8_t*)h261->decoder.accumulator)[h261->decoder.accumulator_pos], pay_ptr, pay_size);
+ h261->decoder.accumulator_pos += pay_size;
+ }
+ else {
+ TSK_DEBUG_WARN("Buffer overflow");
+ h261->decoder.accumulator_pos = 0;
+ return 0;
+ }
+
+ if(rtp_hdr->marker) {
+ AVPacket packet;
+ /* allocate destination buffer */
+ if(*out_max_size <xsize) {
+ if(!(*out_data = tsk_realloc(*out_data, xsize))) {
+ TSK_DEBUG_ERROR("Failed to allocate new buffer");
+ *out_max_size = 0;
+ h261->decoder.accumulator_pos = 0;
+ return 0;
+ }
+ *out_max_size = xsize;
+ }
+
+ /* decode the picture */
+ av_init_packet(&packet);
+ packet.size = (int)h261->decoder.accumulator_pos;
+ packet.data = h261->decoder.accumulator;
+ ret = avcodec_decode_video2(h261->decoder.context, h261->decoder.picture, &got_picture_ptr, &packet);
+
+ if(ret <0 || !got_picture_ptr) {
+ TSK_DEBUG_WARN("Failed to decode the buffer");
+ }
+ else {
+ retsize = xsize;
+ TMEDIA_CODEC_VIDEO(h261)->in.width = h261->decoder.context->width;
+ TMEDIA_CODEC_VIDEO(h261)->in.height = h261->decoder.context->height;
+ /* copy picture into a linear buffer */
+ avpicture_layout((AVPicture *)h261->decoder.picture, h261->decoder.context->pix_fmt, (int)h261->decoder.context->width, (int)h261->decoder.context->height,
+ *out_data, (int)retsize);
+ }
+ /* in all cases: reset accumulator */
+ h261->decoder.accumulator_pos = 0;
+ }
+
+ return retsize;
}
tsk_bool_t tdav_codec_h261_sdp_att_match(const tmedia_codec_t* codec, const char* att_name, const char* att_value)
-{
- int ret;
- unsigned maxbr, fps, width, height;
- tmedia_codec_video_t* h261 = (tmedia_codec_video_t*)codec;
-
- if(tsk_striequals(att_value, "fmtp")){
- if(!(ret = tmedia_codec_parse_fmtp(att_value, &maxbr, &fps, &width, &height))){
- h261->in.max_br = h261->out.max_br = maxbr * 1000;
- h261->in.fps = h261->out.fps = fps;
- h261->in.width = h261->out.width = width;
- h261->in.height = h261->out.height = height;
- return tsk_true;
- }
- else{
- TSK_DEBUG_WARN("Failed to match fmtp [%s]", att_value);
- }
- }
- return tsk_false;
+{
+ int ret;
+ unsigned maxbr, fps, width, height;
+ tmedia_codec_video_t* h261 = (tmedia_codec_video_t*)codec;
+
+ if(tsk_striequals(att_value, "fmtp")) {
+ if(!(ret = tmedia_codec_parse_fmtp(att_value, &maxbr, &fps, &width, &height))) {
+ h261->in.max_br = h261->out.max_br = maxbr * 1000;
+ h261->in.fps = h261->out.fps = fps;
+ h261->in.width = h261->out.width = width;
+ h261->in.height = h261->out.height = height;
+ return tsk_true;
+ }
+ else {
+ TSK_DEBUG_WARN("Failed to match fmtp [%s]", att_value);
+ }
+ }
+ return tsk_false;
}
char* tdav_codec_h261_sdp_att_get(const tmedia_codec_t* self, const char* att_name)
{
#if 0
- return tsk_strdup("CIF=2/MaxBR=3840;QCIF=2/MaxBR=1920");
+ return tsk_strdup("CIF=2/MaxBR=3840;QCIF=2/MaxBR=1920");
#else
- return tsk_strdup("QCIF=2");
+ return tsk_strdup("QCIF=2");
#endif
}
/* constructor */
static tsk_object_t* tdav_codec_h261_ctor(tsk_object_t * self, va_list * app)
{
- tdav_codec_h261_t *h261 = self;
- if(h261){
- /* init base: called by tmedia_codec_create() */
- /* init self */
- }
- return self;
+ tdav_codec_h261_t *h261 = self;
+ if(h261) {
+ /* init base: called by tmedia_codec_create() */
+ /* init self */
+ }
+ return self;
}
/* destructor */
static tsk_object_t* tdav_codec_h261_dtor(tsk_object_t * self)
-{
- tdav_codec_h261_t *h261 = self;
- if(h261){
- /* deinit base */
- tmedia_codec_video_deinit(h261); // will call close()
- /* deinit self */
- TSK_FREE(h261->rtp.ptr);
- h261->rtp.size = 0;
- }
-
- return self;
+{
+ tdav_codec_h261_t *h261 = self;
+ if(h261) {
+ /* deinit base */
+ tmedia_codec_video_deinit(h261); // will call close()
+ /* deinit self */
+ TSK_FREE(h261->rtp.ptr);
+ h261->rtp.size = 0;
+ }
+
+ return self;
}
/* object definition */
-static const tsk_object_def_t tdav_codec_h261_def_s =
-{
- sizeof(tdav_codec_h261_t),
- tdav_codec_h261_ctor,
- tdav_codec_h261_dtor,
- tmedia_codec_cmp,
+static const tsk_object_def_t tdav_codec_h261_def_s = {
+ sizeof(tdav_codec_h261_t),
+ tdav_codec_h261_ctor,
+ tdav_codec_h261_dtor,
+ tmedia_codec_cmp,
};
/* plugin definition*/
-static const tmedia_codec_plugin_def_t tdav_codec_h261_plugin_def_s =
-{
- &tdav_codec_h261_def_s,
-
- tmedia_video,
- tmedia_codec_id_h261,
- "H261",
- "H261 codec (FFmpeg)",
- TMEDIA_CODEC_FORMAT_H261,
- tsk_false,
- 90000, // rate
-
- /* audio */
- { 0 },
-
- /* video */
- {176, 144, 15},
-
- tsk_null, // set()
- tdav_codec_h261_open,
- tdav_codec_h261_close,
- tdav_codec_h261_encode,
- tdav_codec_h261_decode,
- tdav_codec_h261_sdp_att_match,
- tdav_codec_h261_sdp_att_get
+static const tmedia_codec_plugin_def_t tdav_codec_h261_plugin_def_s = {
+ &tdav_codec_h261_def_s,
+
+ tmedia_video,
+ tmedia_codec_id_h261,
+ "H261",
+ "H261 codec (FFmpeg)",
+ TMEDIA_CODEC_FORMAT_H261,
+ tsk_false,
+ 90000, // rate
+
+ /* audio */
+ { 0 },
+
+ /* video */
+ {176, 144, 15},
+
+ tsk_null, // set()
+ tdav_codec_h261_open,
+ tdav_codec_h261_close,
+ tdav_codec_h261_encode,
+ tdav_codec_h261_decode,
+ tdav_codec_h261_sdp_att_match,
+ tdav_codec_h261_sdp_att_get
};
const tmedia_codec_plugin_def_t *tdav_codec_h261_plugin_def_t = &tdav_codec_h261_plugin_def_s;
@@ -451,26 +449,26 @@ const tmedia_codec_plugin_def_t *tdav_codec_h261_plugin_def_t = &tdav_codec_h261
static void tdav_codec_h261_encap(const tdav_codec_h261_t* h261, const uint8_t* pdata, tsk_size_t size)
{
- uint32_t i, last_index = 0;
-
- if(size < RTP_PAYLOAD_SIZE){
- goto last;
- }
-
- for(i = 4; i<(size - 4); i++){
- if(pdata[i] == 0x00 && pdata[i+1] == 0x00 && pdata[i+2]>=0x80){ /* PSC or (GBSC) found */
- if((i - last_index) >= RTP_PAYLOAD_SIZE){
- tdav_codec_h261_rtp_callback((tdav_codec_h261_t*)h261, pdata+last_index,
- (i - last_index), (last_index == size));
- }
- last_index = i;
- }
- }
+ uint32_t i, last_index = 0;
+
+ if(size < RTP_PAYLOAD_SIZE) {
+ goto last;
+ }
+
+ for(i = 4; i<(size - 4); i++) {
+ if(pdata[i] == 0x00 && pdata[i+1] == 0x00 && pdata[i+2]>=0x80) { /* PSC or (GBSC) found */
+ if((i - last_index) >= RTP_PAYLOAD_SIZE) {
+ tdav_codec_h261_rtp_callback((tdav_codec_h261_t*)h261, pdata+last_index,
+ (i - last_index), (last_index == size));
+ }
+ last_index = i;
+ }
+ }
last:
- if(last_index < size - 3/*PSC/GBSC size*/){
- tdav_codec_h261_rtp_callback((tdav_codec_h261_t*)h261, pdata + last_index,
- (size - last_index), tsk_true);
- }
+ if(last_index < size - 3/*PSC/GBSC size*/) {
+ tdav_codec_h261_rtp_callback((tdav_codec_h261_t*)h261, pdata + last_index,
+ (size - last_index), tsk_true);
+ }
}
//static void *run(void* self)
@@ -501,7 +499,7 @@ last:
// if(pdata[i] == 0x00 && pdata[i+1] == 0x00 && pdata[i+2]>=0x80){ /* PSC or (GBSC) found */
// if((i - last_index) >= RTP_PAYLOAD_SIZE){
// tdav_codec_h261_rtp_callback((tdav_codec_h261_t*)h261, pdata+last_index,
-// (i - last_index), (last_index == size));
+// (i - last_index), (last_index == size));
// }
// last_index = i;
// }
@@ -514,7 +512,7 @@ last:
//
// tsk_object_unref(curr);
// }
-//
+//
// TSK_RUNNABLE_RUN_END(self);
//
// TSK_DEBUG_INFO("H261 thread === STOP");
@@ -524,12 +522,12 @@ last:
static void tdav_codec_h261_rtp_callback(tdav_codec_h261_t *self, const void *data, tsk_size_t size, tsk_bool_t marker)
{
-
+
}
tsk_bool_t tdav_codec_ffmpeg_h261_is_supported()
{
- return /*(avcodec_find_encoder(CODEC_ID_H261) && avcodec_find_decoder(CODEC_ID_H261))*/tsk_false /* @deprecated */;
+ return /*(avcodec_find_encoder(CODEC_ID_H261) && avcodec_find_decoder(CODEC_ID_H261))*/tsk_false /* @deprecated */;
}
diff --git a/tinyDAV/src/codecs/h263/tdav_codec_h263.c b/tinyDAV/src/codecs/h263/tdav_codec_h263.c
index ed5d77f..bc20b36 100755
--- a/tinyDAV/src/codecs/h263/tdav_codec_h263.c
+++ b/tinyDAV/src/codecs/h263/tdav_codec_h263.c
@@ -2,19 +2,19 @@
* Copyright (C) 2010-2011 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.
*
@@ -73,48 +73,46 @@
#define TDAV_CODEC_H263(self) ((tdav_codec_h263_t*)(self))
-typedef enum tdav_codec_h263_type_e
-{
- tdav_codec_h263_1996,
- tdav_codec_h263_1998,
- tdav_codec_h263_2000,
+typedef enum tdav_codec_h263_type_e {
+ tdav_codec_h263_1996,
+ tdav_codec_h263_1998,
+ tdav_codec_h263_2000,
}
tdav_codec_h263_type_t;
/** H.263-1996 codec */
-typedef struct tdav_codec_h263_s
-{
- TMEDIA_DECLARE_CODEC_VIDEO;
-
- tdav_codec_h263_type_t type;
-
- struct{
- uint8_t* ptr;
- tsk_size_t size;
- } rtp;
-
- // Encoder
- struct{
- AVCodec* codec;
- AVCodecContext* context;
- AVFrame* picture;
- void* buffer;
- tsk_bool_t force_idr;
- int32_t quality; // [1-31]
- int32_t max_bw_kpbs;
- } encoder;
-
- // decoder
- struct{
- AVCodec* codec;
- AVCodecContext* context;
- AVFrame* picture;
-
- void* accumulator;
- uint8_t ebit;
- tsk_size_t accumulator_pos;
- uint16_t last_seq;
- } decoder;
+typedef struct tdav_codec_h263_s {
+ TMEDIA_DECLARE_CODEC_VIDEO;
+
+ tdav_codec_h263_type_t type;
+
+ struct {
+ uint8_t* ptr;
+ tsk_size_t size;
+ } rtp;
+
+ // Encoder
+ struct {
+ AVCodec* codec;
+ AVCodecContext* context;
+ AVFrame* picture;
+ void* buffer;
+ tsk_bool_t force_idr;
+ int32_t quality; // [1-31]
+ int32_t max_bw_kpbs;
+ } encoder;
+
+ // decoder
+ struct {
+ AVCodec* codec;
+ AVCodecContext* context;
+ AVFrame* picture;
+
+ void* accumulator;
+ uint8_t ebit;
+ tsk_size_t accumulator_pos;
+ uint16_t last_seq;
+ } decoder;
}
tdav_codec_h263_t;
@@ -128,16 +126,14 @@ static int tdav_codec_h263_close_encoder(tdav_codec_h263_t* self);
static int tdav_codec_h263_close_decoder(tdav_codec_h263_t* self);
/** H.263-1998 codec */
-typedef struct tdav_codec_h263p_s
-{
- TDAV_DECLARE_CODEC_H263;
+typedef struct tdav_codec_h263p_s {
+ TDAV_DECLARE_CODEC_H263;
}
tdav_codec_h263p_t;
/** H.263-2000 codec */
-typedef struct tdav_codec_h263pp_s
-{
- TDAV_DECLARE_CODEC_H263;
+typedef struct tdav_codec_h263pp_s {
+ TDAV_DECLARE_CODEC_H263;
}
tdav_codec_h263pp_t;
@@ -152,85 +148,82 @@ static void tdav_codec_h263_encap(const tdav_codec_h263_t* h263, const uint8_t*
static int tdav_codec_h263_set(tmedia_codec_t* self, const tmedia_param_t* param)
{
- tdav_codec_h263_t* h263 = (tdav_codec_h263_t*)self;
- if(!self->opened){
- TSK_DEBUG_ERROR("Codec not opened");
- return -1;
- }
- if(param->value_type == tmedia_pvt_int32){
- if(tsk_striequals(param->key, "action")){
- tmedia_codec_action_t action = (tmedia_codec_action_t)TSK_TO_INT32((uint8_t*)param->value);
- switch(action){
- case tmedia_codec_action_encode_idr:
- {
- h263->encoder.force_idr = tsk_true;
- break;
- }
- case tmedia_codec_action_bw_down:
- {
- h263->encoder.quality = TSK_CLAMP(1, (h263->encoder.quality + 1), 31);
- h263->encoder.context->global_quality = FF_QP2LAMBDA * h263->encoder.quality;
- break;
- }
- case tmedia_codec_action_bw_up:
- {
- h263->encoder.quality = TSK_CLAMP(1, (h263->encoder.quality - 1), 31);
- h263->encoder.context->global_quality = FF_QP2LAMBDA * h263->encoder.quality;
- break;
- }
- }
- return 0;
- }
- }
- return -1;
+ tdav_codec_h263_t* h263 = (tdav_codec_h263_t*)self;
+ if(!self->opened) {
+ TSK_DEBUG_ERROR("Codec not opened");
+ return -1;
+ }
+ if(param->value_type == tmedia_pvt_int32) {
+ if(tsk_striequals(param->key, "action")) {
+ tmedia_codec_action_t action = (tmedia_codec_action_t)TSK_TO_INT32((uint8_t*)param->value);
+ switch(action) {
+ case tmedia_codec_action_encode_idr: {
+ h263->encoder.force_idr = tsk_true;
+ break;
+ }
+ case tmedia_codec_action_bw_down: {
+ h263->encoder.quality = TSK_CLAMP(1, (h263->encoder.quality + 1), 31);
+ h263->encoder.context->global_quality = FF_QP2LAMBDA * h263->encoder.quality;
+ break;
+ }
+ case tmedia_codec_action_bw_up: {
+ h263->encoder.quality = TSK_CLAMP(1, (h263->encoder.quality - 1), 31);
+ h263->encoder.context->global_quality = FF_QP2LAMBDA * h263->encoder.quality;
+ break;
+ }
+ }
+ return 0;
+ }
+ }
+ return -1;
}
int tdav_codec_h263_init(tdav_codec_h263_t* self, tdav_codec_h263_type_t type, enum CodecID encoder, enum CodecID decoder)
{
- int ret = 0;
-
- if(!self){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- self->type = type;
- self->encoder.quality = 1;
-
- if(!(self->encoder.codec = avcodec_find_encoder(encoder))){
- TSK_DEBUG_ERROR("Failed to find [%d]encoder", encoder);
- ret = -2;
- }
-
- if(!(self->decoder.codec = avcodec_find_decoder(decoder))){
- TSK_DEBUG_ERROR("Failed to find [%d] decoder", decoder);
- ret = -3;
- }
-
- self->encoder.max_bw_kpbs = tmedia_defaults_get_bandwidth_video_upload_max();
-
- /* allocations MUST be done by open() */
- return ret;
+ int ret = 0;
+
+ if(!self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ self->type = type;
+ self->encoder.quality = 1;
+
+ if(!(self->encoder.codec = avcodec_find_encoder(encoder))) {
+ TSK_DEBUG_ERROR("Failed to find [%d]encoder", encoder);
+ ret = -2;
+ }
+
+ if(!(self->decoder.codec = avcodec_find_decoder(decoder))) {
+ TSK_DEBUG_ERROR("Failed to find [%d] decoder", decoder);
+ ret = -3;
+ }
+
+ self->encoder.max_bw_kpbs = tmedia_defaults_get_bandwidth_video_upload_max();
+
+ /* allocations MUST be done by open() */
+ return ret;
}
int tdav_codec_h263_deinit(tdav_codec_h263_t* self)
{
- if(!self){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- self->encoder.codec = tsk_null;
- self->decoder.codec = tsk_null;
-
- // FFMpeg resources are destroyed by close()
-
-
-
- TSK_FREE(self->rtp.ptr);
- self->rtp.size = 0;
-
- return 0;
+ if(!self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ self->encoder.codec = tsk_null;
+ self->decoder.codec = tsk_null;
+
+ // FFMpeg resources are destroyed by close()
+
+
+
+ TSK_FREE(self->rtp.ptr);
+ self->rtp.size = 0;
+
+ return 0;
}
@@ -242,360 +235,358 @@ int tdav_codec_h263_deinit(tdav_codec_h263_t* self)
//
static int tdav_codec_h263_open(tmedia_codec_t* self)
{
- int ret;
+ int ret;
- tdav_codec_h263_t* h263 = (tdav_codec_h263_t*)self;
+ tdav_codec_h263_t* h263 = (tdav_codec_h263_t*)self;
- if(!h263){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
+ if(!h263) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
- /* the caller (base class) already checked that the codec is not opened */
+ /* the caller (base class) already checked that the codec is not opened */
- // Encoder
- if((ret = tdav_codec_h263_open_encoder(h263))){
- return ret;
- }
+ // Encoder
+ if((ret = tdav_codec_h263_open_encoder(h263))) {
+ return ret;
+ }
- // Decoder
- if((ret = tdav_codec_h263_open_decoder(h263))){
- return ret;
- }
+ // Decoder
+ if((ret = tdav_codec_h263_open_decoder(h263))) {
+ return ret;
+ }
- return ret;
+ return ret;
}
static int tdav_codec_h263_close(tmedia_codec_t* self)
{
- tdav_codec_h263_t* h263 = (tdav_codec_h263_t*)self;
- int ret;
-
- if(!h263){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- /* the caller (base class) already checked that the codec is opened */
-
- // Encoder
- ret = tdav_codec_h263_close_encoder(h263);
- // Decoder
- ret = tdav_codec_h263_close_decoder(h263);
-
- return ret;
+ tdav_codec_h263_t* h263 = (tdav_codec_h263_t*)self;
+ int ret;
+
+ if(!h263) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ /* the caller (base class) already checked that the codec is opened */
+
+ // Encoder
+ ret = tdav_codec_h263_close_encoder(h263);
+ // Decoder
+ ret = tdav_codec_h263_close_decoder(h263);
+
+ return ret;
}
static tsk_size_t tdav_codec_h263_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_h263_t* h263 = (tdav_codec_h263_t*)self;
-
- if(!self || !in_data || !in_size || !out_data){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- // wrap yuv420 buffer
- size = avpicture_fill((AVPicture *)h263->encoder.picture, (uint8_t*)in_data, PIX_FMT_YUV420P, h263->encoder.context->width, h263->encoder.context->height);
- if(size != in_size){
- /* guard */
- TSK_DEBUG_ERROR("Invalid size");
- return 0;
- }
+ int ret;
+ int size;
+
+ tdav_codec_h263_t* h263 = (tdav_codec_h263_t*)self;
+
+ if(!self || !in_data || !in_size || !out_data) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ // wrap yuv420 buffer
+ size = avpicture_fill((AVPicture *)h263->encoder.picture, (uint8_t*)in_data, PIX_FMT_YUV420P, h263->encoder.context->width, h263->encoder.context->height);
+ if(size != in_size) {
+ /* guard */
+ TSK_DEBUG_ERROR("Invalid size");
+ return 0;
+ }
#if LIBAVCODEC_VERSION_MAJOR <= 53
- h263->encoder.picture->pict_type = h263->encoder.force_idr ? FF_I_TYPE : 0;
+ h263->encoder.picture->pict_type = h263->encoder.force_idr ? FF_I_TYPE : 0;
#else
h263->encoder.picture->pict_type = h263->encoder.force_idr ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_NONE;
#endif
- h263->encoder.picture->pts = AV_NOPTS_VALUE;
- h263->encoder.picture->quality = h263->encoder.context->global_quality;
- ret = avcodec_encode_video(h263->encoder.context, h263->encoder.buffer, size, h263->encoder.picture);
- if(ret > 0){
- tdav_codec_h263_encap(h263, h263->encoder.buffer, (tsk_size_t)ret);
- }
- h263->encoder.force_idr = tsk_false;
-
- return 0;
+ h263->encoder.picture->pts = AV_NOPTS_VALUE;
+ h263->encoder.picture->quality = h263->encoder.context->global_quality;
+ ret = avcodec_encode_video(h263->encoder.context, h263->encoder.buffer, size, h263->encoder.picture);
+ if(ret > 0) {
+ tdav_codec_h263_encap(h263, h263->encoder.buffer, (tsk_size_t)ret);
+ }
+ h263->encoder.force_idr = tsk_false;
+
+ return 0;
}
static tsk_size_t tdav_codec_h263_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)
{
- uint8_t F, P, sbit, ebit;
- const uint8_t* pdata = in_data;
- 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_h263_t* h263 = (tdav_codec_h263_t*)self;
- const trtp_rtp_header_t* rtp_hdr = proto_hdr;
- tsk_bool_t is_idr = tsk_false;
-
- if(!self || !in_data || !in_size || !out_data || !h263->decoder.context){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- /* RFC 2190
- get F and P bits, used to determine the header Mode (A, B or C)
- F: 1 bit
- The flag bit indicates the mode of the payload header. F=0, mode A;
- F=1, mode B or mode C depending on P bit defined below.
- P: 1 bit
- Optional PB-frames mode as defined by the H.263 [4]. "0" implies
- normal I or P frame, "1" PB-frames. When F=1, P also indicates modes:
- mode B if P=0, mode C if P=1.
-
- I: 1 bit.
- Picture coding type, bit 9 in PTYPE defined by H.263[4], "0" is
- intra-coded, "1" is inter-coded.
- */
- F = *pdata >> 7;
- P = (*pdata >> 6) & 0x01;
-
- /* SBIT and EBIT */
- sbit = (*pdata >> 3) & 0x0F;
- ebit = (*pdata & 0x07);
-
- if(F == 0){
- /* MODE A
- 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|P|SBIT |EBIT | SRC |I|U|S|A|R |DBQ| TRB | TR |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
- hdr_size = H263_HEADER_MODE_A_SIZE;
- is_idr = (in_size >= 2) && !(pdata[1] & 0x10) /* I==1 */;
- }
- else if(P == 0){ // F=1 and P=0
- /* MODE B
- 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|P|SBIT |EBIT | SRC | QUANT | GOBN | MBA |R |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- |I|U|S|A| HMV1 | VMV1 | HMV2 | VMV2 |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
- hdr_size = H263_HEADER_MODE_B_SIZE;
- is_idr = (in_size >= 5) && !(pdata[4] & 0x80) /* I==1 */;
- }
- else{ // F=1 and P=1
- /* MODE C
- 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|P|SBIT |EBIT | SRC | QUANT | GOBN | MBA |R |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- |I|U|S|A| HMV1 | VMV1 | HMV2 | VMV2 |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | RR |DBQ| TRB | TR |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
- hdr_size = H263_HEADER_MODE_C_SIZE;
- is_idr = (in_size >= 5) && !(pdata[4] & 0x80) /* I==1 */;
- }
-
- /* Check size */
- if(in_size < hdr_size){
- TSK_DEBUG_ERROR("Too short");
- return 0;
- }
-
- pay_ptr = (pdata + hdr_size);
- pay_size = (in_size - hdr_size);
- xsize = avpicture_get_size(h263->decoder.context->pix_fmt, h263->decoder.context->width, h263->decoder.context->height);
-
- /* Packet lost? */
- if(h263->decoder.last_seq != (rtp_hdr->seq_num - 1) && h263->decoder.last_seq){
- if(h263->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("[H.263] Packet loss, seq_num=%d", rtp_hdr->seq_num);
- }
- h263->decoder.last_seq = rtp_hdr->seq_num;
-
- if((int)(h263->decoder.accumulator_pos + pay_size) <= xsize){
- if((h263->decoder.ebit + sbit) == 8){ /* Perfect one Byte to clean up */
- if(h263->decoder.accumulator_pos){
- ((uint8_t*)h263->decoder.accumulator)[h263->decoder.accumulator_pos-1] = (((uint8_t*)h263->decoder.accumulator)[h263->decoder.accumulator_pos-1] & (0xFF << h263->decoder.ebit)) |
- (*pay_ptr & (0xFF >> sbit));
- }
- pay_ptr++, pay_size--;
- }
- h263->decoder.ebit = ebit;
-
- memcpy(&((uint8_t*)h263->decoder.accumulator)[h263->decoder.accumulator_pos], pay_ptr, pay_size);
- h263->decoder.accumulator_pos += pay_size;
- }
- else{
- TSK_DEBUG_WARN("Buffer overflow");
- h263->decoder.accumulator_pos = 0;
- return 0;
- }
-
- if(rtp_hdr->marker){
- AVPacket packet;
- /* allocate destination buffer */
- if(*out_max_size <xsize){
- if(!(*out_data = tsk_realloc(*out_data, xsize))){
- TSK_DEBUG_ERROR("Failed to allocate new buffer");
- h263->decoder.accumulator_pos = 0;
- *out_max_size = 0;
- return 0;
- }
- *out_max_size = xsize;
- }
-
- av_init_packet(&packet);
- packet.size = (int)h263->decoder.accumulator_pos;
- packet.data = h263->decoder.accumulator;
- ret = avcodec_decode_video2(h263->decoder.context, h263->decoder.picture, &got_picture_ptr, &packet);
-
- if(ret < 0){
- TSK_DEBUG_WARN("Failed to decode the buffer with error code = %d", ret);
- if(TMEDIA_CODEC_VIDEO(self)->in.callback){
- TMEDIA_CODEC_VIDEO(self)->in.result.type = tmedia_video_decode_result_type_error;
- TMEDIA_CODEC_VIDEO(self)->in.result.proto_hdr = proto_hdr;
- TMEDIA_CODEC_VIDEO(self)->in.callback(&TMEDIA_CODEC_VIDEO(self)->in.result);
- }
- }
- else if(got_picture_ptr){
- retsize = xsize;
- // Is it IDR frame?
- if(is_idr && TMEDIA_CODEC_VIDEO(self)->in.callback){
- TSK_DEBUG_INFO("Decoded H.263 IDR");
- TMEDIA_CODEC_VIDEO(self)->in.result.type = tmedia_video_decode_result_type_idr;
- TMEDIA_CODEC_VIDEO(self)->in.result.proto_hdr = proto_hdr;
- TMEDIA_CODEC_VIDEO(self)->in.callback(&TMEDIA_CODEC_VIDEO(self)->in.result);
- }
- TMEDIA_CODEC_VIDEO(h263)->in.width = h263->decoder.context->width;
- TMEDIA_CODEC_VIDEO(h263)->in.height = h263->decoder.context->height;
- /* copy picture into a linear buffer */
- avpicture_layout((AVPicture *)h263->decoder.picture, h263->decoder.context->pix_fmt, (int)h263->decoder.context->width, (int)h263->decoder.context->height,
- *out_data, (int)retsize);
- }
- /* in all cases: reset accumulator */
- h263->decoder.accumulator_pos = 0;
- }
-
- return retsize;
+ uint8_t F, P, sbit, ebit;
+ const uint8_t* pdata = in_data;
+ 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_h263_t* h263 = (tdav_codec_h263_t*)self;
+ const trtp_rtp_header_t* rtp_hdr = proto_hdr;
+ tsk_bool_t is_idr = tsk_false;
+
+ if(!self || !in_data || !in_size || !out_data || !h263->decoder.context) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ /* RFC 2190
+ get F and P bits, used to determine the header Mode (A, B or C)
+ F: 1 bit
+ The flag bit indicates the mode of the payload header. F=0, mode A;
+ F=1, mode B or mode C depending on P bit defined below.
+ P: 1 bit
+ Optional PB-frames mode as defined by the H.263 [4]. "0" implies
+ normal I or P frame, "1" PB-frames. When F=1, P also indicates modes:
+ mode B if P=0, mode C if P=1.
+
+ I: 1 bit.
+ Picture coding type, bit 9 in PTYPE defined by H.263[4], "0" is
+ intra-coded, "1" is inter-coded.
+ */
+ F = *pdata >> 7;
+ P = (*pdata >> 6) & 0x01;
+
+ /* SBIT and EBIT */
+ sbit = (*pdata >> 3) & 0x0F;
+ ebit = (*pdata & 0x07);
+
+ if(F == 0) {
+ /* MODE A
+ 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|P|SBIT |EBIT | SRC |I|U|S|A|R |DBQ| TRB | TR |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+ hdr_size = H263_HEADER_MODE_A_SIZE;
+ is_idr = (in_size >= 2) && !(pdata[1] & 0x10) /* I==1 */;
+ }
+ else if(P == 0) { // F=1 and P=0
+ /* MODE B
+ 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|P|SBIT |EBIT | SRC | QUANT | GOBN | MBA |R |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |I|U|S|A| HMV1 | VMV1 | HMV2 | VMV2 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+ hdr_size = H263_HEADER_MODE_B_SIZE;
+ is_idr = (in_size >= 5) && !(pdata[4] & 0x80) /* I==1 */;
+ }
+ else { // F=1 and P=1
+ /* MODE C
+ 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|P|SBIT |EBIT | SRC | QUANT | GOBN | MBA |R |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |I|U|S|A| HMV1 | VMV1 | HMV2 | VMV2 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | RR |DBQ| TRB | TR |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+ hdr_size = H263_HEADER_MODE_C_SIZE;
+ is_idr = (in_size >= 5) && !(pdata[4] & 0x80) /* I==1 */;
+ }
+
+ /* Check size */
+ if(in_size < hdr_size) {
+ TSK_DEBUG_ERROR("Too short");
+ return 0;
+ }
+
+ pay_ptr = (pdata + hdr_size);
+ pay_size = (in_size - hdr_size);
+ xsize = avpicture_get_size(h263->decoder.context->pix_fmt, h263->decoder.context->width, h263->decoder.context->height);
+
+ /* Packet lost? */
+ if(h263->decoder.last_seq != (rtp_hdr->seq_num - 1) && h263->decoder.last_seq) {
+ if(h263->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("[H.263] Packet loss, seq_num=%d", rtp_hdr->seq_num);
+ }
+ h263->decoder.last_seq = rtp_hdr->seq_num;
+
+ if((int)(h263->decoder.accumulator_pos + pay_size) <= xsize) {
+ if((h263->decoder.ebit + sbit) == 8) { /* Perfect one Byte to clean up */
+ if(h263->decoder.accumulator_pos) {
+ ((uint8_t*)h263->decoder.accumulator)[h263->decoder.accumulator_pos-1] = (((uint8_t*)h263->decoder.accumulator)[h263->decoder.accumulator_pos-1] & (0xFF << h263->decoder.ebit)) |
+ (*pay_ptr & (0xFF >> sbit));
+ }
+ pay_ptr++, pay_size--;
+ }
+ h263->decoder.ebit = ebit;
+
+ memcpy(&((uint8_t*)h263->decoder.accumulator)[h263->decoder.accumulator_pos], pay_ptr, pay_size);
+ h263->decoder.accumulator_pos += pay_size;
+ }
+ else {
+ TSK_DEBUG_WARN("Buffer overflow");
+ h263->decoder.accumulator_pos = 0;
+ return 0;
+ }
+
+ if(rtp_hdr->marker) {
+ AVPacket packet;
+ /* allocate destination buffer */
+ if(*out_max_size <xsize) {
+ if(!(*out_data = tsk_realloc(*out_data, xsize))) {
+ TSK_DEBUG_ERROR("Failed to allocate new buffer");
+ h263->decoder.accumulator_pos = 0;
+ *out_max_size = 0;
+ return 0;
+ }
+ *out_max_size = xsize;
+ }
+
+ av_init_packet(&packet);
+ packet.size = (int)h263->decoder.accumulator_pos;
+ packet.data = h263->decoder.accumulator;
+ ret = avcodec_decode_video2(h263->decoder.context, h263->decoder.picture, &got_picture_ptr, &packet);
+
+ if(ret < 0) {
+ TSK_DEBUG_WARN("Failed to decode the buffer with error code = %d", ret);
+ if(TMEDIA_CODEC_VIDEO(self)->in.callback) {
+ TMEDIA_CODEC_VIDEO(self)->in.result.type = tmedia_video_decode_result_type_error;
+ TMEDIA_CODEC_VIDEO(self)->in.result.proto_hdr = proto_hdr;
+ TMEDIA_CODEC_VIDEO(self)->in.callback(&TMEDIA_CODEC_VIDEO(self)->in.result);
+ }
+ }
+ else if(got_picture_ptr) {
+ retsize = xsize;
+ // Is it IDR frame?
+ if(is_idr && TMEDIA_CODEC_VIDEO(self)->in.callback) {
+ TSK_DEBUG_INFO("Decoded H.263 IDR");
+ TMEDIA_CODEC_VIDEO(self)->in.result.type = tmedia_video_decode_result_type_idr;
+ TMEDIA_CODEC_VIDEO(self)->in.result.proto_hdr = proto_hdr;
+ TMEDIA_CODEC_VIDEO(self)->in.callback(&TMEDIA_CODEC_VIDEO(self)->in.result);
+ }
+ TMEDIA_CODEC_VIDEO(h263)->in.width = h263->decoder.context->width;
+ TMEDIA_CODEC_VIDEO(h263)->in.height = h263->decoder.context->height;
+ /* copy picture into a linear buffer */
+ avpicture_layout((AVPicture *)h263->decoder.picture, h263->decoder.context->pix_fmt, (int)h263->decoder.context->width, (int)h263->decoder.context->height,
+ *out_data, (int)retsize);
+ }
+ /* in all cases: reset accumulator */
+ h263->decoder.accumulator_pos = 0;
+ }
+
+ return retsize;
}
static tsk_bool_t tdav_codec_h263_sdp_att_match(const tmedia_codec_t* codec, const char* att_name, const char* att_value)
-{
- if(tsk_striequals(att_name, "fmtp")){
- unsigned width, height, fps;
- if(tmedia_parse_video_fmtp(att_value, TMEDIA_CODEC_VIDEO(codec)->pref_size, &width, &height, &fps)){
- TSK_DEBUG_ERROR("Failed to match fmtp=%s", att_value);
- return tsk_false;
- }
- TMEDIA_CODEC_VIDEO(codec)->in.width = TMEDIA_CODEC_VIDEO(codec)->out.width = width;
- TMEDIA_CODEC_VIDEO(codec)->in.height = TMEDIA_CODEC_VIDEO(codec)->out.height = height;
- TMEDIA_CODEC_VIDEO(codec)->in.fps = TMEDIA_CODEC_VIDEO(codec)->out.fps = fps;
- }
+{
+ if(tsk_striequals(att_name, "fmtp")) {
+ unsigned width, height, fps;
+ if(tmedia_parse_video_fmtp(att_value, TMEDIA_CODEC_VIDEO(codec)->pref_size, &width, &height, &fps)) {
+ TSK_DEBUG_ERROR("Failed to match fmtp=%s", att_value);
+ return tsk_false;
+ }
+ TMEDIA_CODEC_VIDEO(codec)->in.width = TMEDIA_CODEC_VIDEO(codec)->out.width = width;
+ TMEDIA_CODEC_VIDEO(codec)->in.height = TMEDIA_CODEC_VIDEO(codec)->out.height = height;
+ TMEDIA_CODEC_VIDEO(codec)->in.fps = TMEDIA_CODEC_VIDEO(codec)->out.fps = fps;
+ }
#if 0
- else if(tsk_striequals(att_name, "imageattr")){
- unsigned in_width, in_height, out_width, out_height;
- if(tmedia_parse_video_imageattr(att_value, TMEDIA_CODEC_VIDEO(codec)->pref_size, &in_width, &in_height, &out_width, &out_height) != 0){
- return tsk_false;
- }
- TMEDIA_CODEC_VIDEO(codec)->in.width = in_width;
- TMEDIA_CODEC_VIDEO(codec)->in.height = in_height;
- TMEDIA_CODEC_VIDEO(codec)->out.width = out_width;
- TMEDIA_CODEC_VIDEO(codec)->out.height = out_height;
- }
+ else if(tsk_striequals(att_name, "imageattr")) {
+ unsigned in_width, in_height, out_width, out_height;
+ if(tmedia_parse_video_imageattr(att_value, TMEDIA_CODEC_VIDEO(codec)->pref_size, &in_width, &in_height, &out_width, &out_height) != 0) {
+ return tsk_false;
+ }
+ TMEDIA_CODEC_VIDEO(codec)->in.width = in_width;
+ TMEDIA_CODEC_VIDEO(codec)->in.height = in_height;
+ TMEDIA_CODEC_VIDEO(codec)->out.width = out_width;
+ TMEDIA_CODEC_VIDEO(codec)->out.height = out_height;
+ }
#endif
-
- return tsk_true;
+
+ return tsk_true;
}
static char* tdav_codec_h263_sdp_att_get(const tmedia_codec_t* codec, const char* att_name)
{
- if(tsk_striequals(att_name, "fmtp")){
- tmedia_pref_video_size_t cif_vs;
- if(tmedia_video_get_closest_cif_size(TMEDIA_CODEC_VIDEO(codec)->pref_size, &cif_vs)){
- TSK_DEBUG_ERROR("Failed to get closest CIF family size");
- return tsk_null;
- }
- return tmedia_get_video_fmtp(cif_vs);
- }
+ if(tsk_striequals(att_name, "fmtp")) {
+ tmedia_pref_video_size_t cif_vs;
+ if(tmedia_video_get_closest_cif_size(TMEDIA_CODEC_VIDEO(codec)->pref_size, &cif_vs)) {
+ TSK_DEBUG_ERROR("Failed to get closest CIF family size");
+ return tsk_null;
+ }
+ return tmedia_get_video_fmtp(cif_vs);
+ }
#if 0
- else if(tsk_striequals(att_name, "imageattr")){
- return tmedia_get_video_imageattr(TMEDIA_CODEC_VIDEO(codec)->pref_size,
- TMEDIA_CODEC_VIDEO(codec)->in.width, TMEDIA_CODEC_VIDEO(codec)->in.height, TMEDIA_CODEC_VIDEO(codec)->out.width, TMEDIA_CODEC_VIDEO(codec)->out.height);
- }
+ else if(tsk_striequals(att_name, "imageattr")) {
+ return tmedia_get_video_imageattr(TMEDIA_CODEC_VIDEO(codec)->pref_size,
+ TMEDIA_CODEC_VIDEO(codec)->in.width, TMEDIA_CODEC_VIDEO(codec)->in.height, TMEDIA_CODEC_VIDEO(codec)->out.width, TMEDIA_CODEC_VIDEO(codec)->out.height);
+ }
#endif
- return tsk_null;
+ return tsk_null;
}
/* constructor */
static tsk_object_t* tdav_codec_h263_ctor(tsk_object_t * self, va_list * app)
{
- tdav_codec_h263_t *h263 = self;
- if(h263){
- /* init base: called by tmedia_codec_create() */
- /* init self */
- tdav_codec_h263_init(TDAV_CODEC_H263(self), tdav_codec_h263_1996, CODEC_ID_H263, CODEC_ID_H263);
- }
- return self;
+ tdav_codec_h263_t *h263 = self;
+ if(h263) {
+ /* init base: called by tmedia_codec_create() */
+ /* init self */
+ tdav_codec_h263_init(TDAV_CODEC_H263(self), tdav_codec_h263_1996, CODEC_ID_H263, CODEC_ID_H263);
+ }
+ return self;
}
/* destructor */
static tsk_object_t* tdav_codec_h263_dtor(tsk_object_t * self)
-{
- tdav_codec_h263_t *h263 = self;
- if(h263){
- /* deinit base */
- tmedia_codec_video_deinit(h263);
- /* deinit self */
- tdav_codec_h263_deinit(TDAV_CODEC_H263(self));
-
- }
-
- return self;
+{
+ tdav_codec_h263_t *h263 = self;
+ if(h263) {
+ /* deinit base */
+ tmedia_codec_video_deinit(h263);
+ /* deinit self */
+ tdav_codec_h263_deinit(TDAV_CODEC_H263(self));
+
+ }
+
+ return self;
}
/* object definition */
-static const tsk_object_def_t tdav_codec_h263_def_s =
-{
- sizeof(tdav_codec_h263_t),
- tdav_codec_h263_ctor,
- tdav_codec_h263_dtor,
- tmedia_codec_cmp,
+static const tsk_object_def_t tdav_codec_h263_def_s = {
+ sizeof(tdav_codec_h263_t),
+ tdav_codec_h263_ctor,
+ tdav_codec_h263_dtor,
+ tmedia_codec_cmp,
};
/* plugin definition*/
-static const tmedia_codec_plugin_def_t tdav_codec_h263_plugin_def_s =
-{
- &tdav_codec_h263_def_s,
-
- tmedia_video,
- tmedia_codec_id_h263,
- "H263",
- "H263-1996 codec (FFmpeg)",
- TMEDIA_CODEC_FORMAT_H263,
- tsk_false,
- 90000, // rate
-
- /* audio */
- { 0 },
-
- /* video */
- {176, 144, 15},
-
- tdav_codec_h263_set,
- tdav_codec_h263_open,
- tdav_codec_h263_close,
- tdav_codec_h263_encode,
- tdav_codec_h263_decode,
- tdav_codec_h263_sdp_att_match,
- tdav_codec_h263_sdp_att_get
+static const tmedia_codec_plugin_def_t tdav_codec_h263_plugin_def_s = {
+ &tdav_codec_h263_def_s,
+
+ tmedia_video,
+ tmedia_codec_id_h263,
+ "H263",
+ "H263-1996 codec (FFmpeg)",
+ TMEDIA_CODEC_FORMAT_H263,
+ tsk_false,
+ 90000, // rate
+
+ /* audio */
+ { 0 },
+
+ /* video */
+ {176, 144, 15},
+
+ tdav_codec_h263_set,
+ tdav_codec_h263_open,
+ tdav_codec_h263_close,
+ tdav_codec_h263_encode,
+ tdav_codec_h263_decode,
+ tdav_codec_h263_sdp_att_match,
+ tdav_codec_h263_sdp_att_get
};
const tmedia_codec_plugin_def_t *tdav_codec_h263_plugin_def_t = &tdav_codec_h263_plugin_def_s;
@@ -629,198 +620,196 @@ const tmedia_codec_plugin_def_t *tdav_codec_h263_plugin_def_t = &tdav_codec_h263
static tsk_size_t tdav_codec_h263p_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)
{
- uint8_t P, V, PLEN, PEBIT;
- uint8_t* pdata = (uint8_t*)in_data;
- const uint8_t* pay_ptr;
- tsk_size_t pay_size;
- int hdr_size = H263P_HEADER_SIZE;
- tsk_size_t xsize, retsize = 0;
- int got_picture_ptr;
- int ret;
-
- tdav_codec_h263_t* h263 = (tdav_codec_h263_t*)self;
- const trtp_rtp_header_t* rtp_hdr = proto_hdr;
-
- if(!self || !in_data || !in_size || ((int)in_size <= hdr_size) || !out_data || !h263->decoder.context){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
-/*
- rfc4629 - 5.1. General H.263+ Payload Header
-
- 0 1
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | RR |P|V| PLEN |PEBIT|
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-*/
- P = (pdata[0] & 0x04)>>2;
- V = (pdata[0] & 0x02)>>1;
- PLEN = (((pdata[0] & 0x01)<<5) | pdata[1]>>3);
- PEBIT = pdata[1] & 0x07;
-
- if(V){
- /*
- Indicates the presence of an 8-bit field containing information
- for Video Redundancy Coding (VRC), which follows immediately after
- the initial 16 bits of the payload header, if present. For syntax
- and semantics of that 8-bit VRC field, see Section 5.2.
- */
- }
- if(PLEN){
- /*
- Length, in bytes, of the extra picture header. If no extra
- picture header is attached, PLEN is 0. If PLEN>0, the extra
- picture header is attached immediately following the rest of the
- payload header. Note that the length reflects the omission of the
- first two bytes of the picture start code (PSC). See Section 6.1.
- */
- hdr_size += PLEN;
- if(PEBIT){
- /*
- Indicates the number of bits that shall be ignored in the last
- byte of the picture header. If PLEN is not zero, the ignored bits
- shall be the least significant bits of the byte. If PLEN is zero,
- then PEBIT shall also be zero.
- */
- TSK_DEBUG_WARN("PEBIT ignored");
- }
- }
- if(P){ /* MUST be done after PLEN and PEBIT */
- /*
- Indicates the picture start or a picture segment (GOB/Slice) start
- or a video sequence end (EOS or EOSBS). Two bytes of zero bits
- then have to be prefixed to the payload of such a packet to
- compose a complete picture/GOB/slice/EOS/EOSBS start code. This
- bit allows the omission of the two first bytes of the start codes,
- thus improving the compression ratio.
- */
- hdr_size -= 2;
- pdata[hdr_size] = 0x00, pdata[hdr_size + 1] = 0x00;
- }
-
- pay_ptr = (pdata + hdr_size);
- pay_size = (in_size - hdr_size);
- xsize = avpicture_get_size(h263->decoder.context->pix_fmt, h263->decoder.context->width, h263->decoder.context->height);
-
- /* Packet lost? */
- if(h263->decoder.last_seq != (rtp_hdr->seq_num - 1) && h263->decoder.last_seq){
- if(h263->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("[H.263+] Packet loss, seq_num=%d", rtp_hdr->seq_num);
- }
- h263->decoder.last_seq = rtp_hdr->seq_num;
-
- if((int)(h263->decoder.accumulator_pos + pay_size) <= xsize){
- /* PEBIT is ignored */
- memcpy(&((uint8_t*)h263->decoder.accumulator)[h263->decoder.accumulator_pos], pay_ptr, pay_size);
- h263->decoder.accumulator_pos += pay_size;
- }
- else{
- TSK_DEBUG_WARN("Buffer overflow");
- h263->decoder.accumulator_pos = 0;
- return 0;
- }
-
- if(rtp_hdr->marker){
- AVPacket packet;
- /* allocate destination buffer */
- if(*out_max_size < xsize){
- if(!(*out_data = tsk_realloc(*out_data, xsize))){
- TSK_DEBUG_ERROR("Failed to allocate new buffer");
- *out_max_size = 0;
- h263->decoder.accumulator_pos = 0;
- return 0;
- }
- *out_max_size = xsize;
- }
-
- /* decode the picture */
- av_init_packet(&packet);
- packet.size = (int)h263->decoder.accumulator_pos;
- packet.data = h263->decoder.accumulator;
- ret = avcodec_decode_video2(h263->decoder.context, h263->decoder.picture, &got_picture_ptr, &packet);
-
- if(ret <0 || !got_picture_ptr){
- TSK_DEBUG_WARN("Failed to decode the buffer");
- }
- else{
- retsize = xsize;
- TMEDIA_CODEC_VIDEO(h263)->in.width = h263->decoder.context->width;
- TMEDIA_CODEC_VIDEO(h263)->in.height = h263->decoder.context->height;
- /* copy picture into a linear buffer */
- avpicture_layout((AVPicture *)h263->decoder.picture, h263->decoder.context->pix_fmt, (int)h263->decoder.context->width, (int)h263->decoder.context->height,
- *out_data, (int)retsize);
- }
- /* in all cases: reset accumulator */
- h263->decoder.accumulator_pos = 0;
- }
-
- return retsize;
+ uint8_t P, V, PLEN, PEBIT;
+ uint8_t* pdata = (uint8_t*)in_data;
+ const uint8_t* pay_ptr;
+ tsk_size_t pay_size;
+ int hdr_size = H263P_HEADER_SIZE;
+ tsk_size_t xsize, retsize = 0;
+ int got_picture_ptr;
+ int ret;
+
+ tdav_codec_h263_t* h263 = (tdav_codec_h263_t*)self;
+ const trtp_rtp_header_t* rtp_hdr = proto_hdr;
+
+ if(!self || !in_data || !in_size || ((int)in_size <= hdr_size) || !out_data || !h263->decoder.context) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ /*
+ rfc4629 - 5.1. General H.263+ Payload Header
+
+ 0 1
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | RR |P|V| PLEN |PEBIT|
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+ P = (pdata[0] & 0x04)>>2;
+ V = (pdata[0] & 0x02)>>1;
+ PLEN = (((pdata[0] & 0x01)<<5) | pdata[1]>>3);
+ PEBIT = pdata[1] & 0x07;
+
+ if(V) {
+ /*
+ Indicates the presence of an 8-bit field containing information
+ for Video Redundancy Coding (VRC), which follows immediately after
+ the initial 16 bits of the payload header, if present. For syntax
+ and semantics of that 8-bit VRC field, see Section 5.2.
+ */
+ }
+ if(PLEN) {
+ /*
+ Length, in bytes, of the extra picture header. If no extra
+ picture header is attached, PLEN is 0. If PLEN>0, the extra
+ picture header is attached immediately following the rest of the
+ payload header. Note that the length reflects the omission of the
+ first two bytes of the picture start code (PSC). See Section 6.1.
+ */
+ hdr_size += PLEN;
+ if(PEBIT) {
+ /*
+ Indicates the number of bits that shall be ignored in the last
+ byte of the picture header. If PLEN is not zero, the ignored bits
+ shall be the least significant bits of the byte. If PLEN is zero,
+ then PEBIT shall also be zero.
+ */
+ TSK_DEBUG_WARN("PEBIT ignored");
+ }
+ }
+ if(P) { /* MUST be done after PLEN and PEBIT */
+ /*
+ Indicates the picture start or a picture segment (GOB/Slice) start
+ or a video sequence end (EOS or EOSBS). Two bytes of zero bits
+ then have to be prefixed to the payload of such a packet to
+ compose a complete picture/GOB/slice/EOS/EOSBS start code. This
+ bit allows the omission of the two first bytes of the start codes,
+ thus improving the compression ratio.
+ */
+ hdr_size -= 2;
+ pdata[hdr_size] = 0x00, pdata[hdr_size + 1] = 0x00;
+ }
+
+ pay_ptr = (pdata + hdr_size);
+ pay_size = (in_size - hdr_size);
+ xsize = avpicture_get_size(h263->decoder.context->pix_fmt, h263->decoder.context->width, h263->decoder.context->height);
+
+ /* Packet lost? */
+ if(h263->decoder.last_seq != (rtp_hdr->seq_num - 1) && h263->decoder.last_seq) {
+ if(h263->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("[H.263+] Packet loss, seq_num=%d", rtp_hdr->seq_num);
+ }
+ h263->decoder.last_seq = rtp_hdr->seq_num;
+
+ if((int)(h263->decoder.accumulator_pos + pay_size) <= xsize) {
+ /* PEBIT is ignored */
+ memcpy(&((uint8_t*)h263->decoder.accumulator)[h263->decoder.accumulator_pos], pay_ptr, pay_size);
+ h263->decoder.accumulator_pos += pay_size;
+ }
+ else {
+ TSK_DEBUG_WARN("Buffer overflow");
+ h263->decoder.accumulator_pos = 0;
+ return 0;
+ }
+
+ if(rtp_hdr->marker) {
+ AVPacket packet;
+ /* allocate destination buffer */
+ if(*out_max_size < xsize) {
+ if(!(*out_data = tsk_realloc(*out_data, xsize))) {
+ TSK_DEBUG_ERROR("Failed to allocate new buffer");
+ *out_max_size = 0;
+ h263->decoder.accumulator_pos = 0;
+ return 0;
+ }
+ *out_max_size = xsize;
+ }
+
+ /* decode the picture */
+ av_init_packet(&packet);
+ packet.size = (int)h263->decoder.accumulator_pos;
+ packet.data = h263->decoder.accumulator;
+ ret = avcodec_decode_video2(h263->decoder.context, h263->decoder.picture, &got_picture_ptr, &packet);
+
+ if(ret <0 || !got_picture_ptr) {
+ TSK_DEBUG_WARN("Failed to decode the buffer");
+ }
+ else {
+ retsize = xsize;
+ TMEDIA_CODEC_VIDEO(h263)->in.width = h263->decoder.context->width;
+ TMEDIA_CODEC_VIDEO(h263)->in.height = h263->decoder.context->height;
+ /* copy picture into a linear buffer */
+ avpicture_layout((AVPicture *)h263->decoder.picture, h263->decoder.context->pix_fmt, (int)h263->decoder.context->width, (int)h263->decoder.context->height,
+ *out_data, (int)retsize);
+ }
+ /* in all cases: reset accumulator */
+ h263->decoder.accumulator_pos = 0;
+ }
+
+ return retsize;
}
/* constructor */
static tsk_object_t* tdav_codec_h263p_ctor(tsk_object_t * self, va_list * app)
{
- tdav_codec_h263p_t *h263p = self;
- if(h263p){
- /* init base: called by tmedia_codec_create() */
- /* init self */
- tdav_codec_h263_init(TDAV_CODEC_H263(self), tdav_codec_h263_1998, CODEC_ID_H263P, CODEC_ID_H263);
- }
- return self;
+ tdav_codec_h263p_t *h263p = self;
+ if(h263p) {
+ /* init base: called by tmedia_codec_create() */
+ /* init self */
+ tdav_codec_h263_init(TDAV_CODEC_H263(self), tdav_codec_h263_1998, CODEC_ID_H263P, CODEC_ID_H263);
+ }
+ return self;
}
/* destructor */
static tsk_object_t* tdav_codec_h263p_dtor(tsk_object_t * self)
-{
- tdav_codec_h263p_t *h263p = self;
- if(h263p){
- /* deinit base */
- tmedia_codec_video_deinit(h263p);
- /* deinit self */
- tdav_codec_h263_deinit(TDAV_CODEC_H263(self));
- }
-
- return self;
+{
+ tdav_codec_h263p_t *h263p = self;
+ if(h263p) {
+ /* deinit base */
+ tmedia_codec_video_deinit(h263p);
+ /* deinit self */
+ tdav_codec_h263_deinit(TDAV_CODEC_H263(self));
+ }
+
+ return self;
}
/* object definition */
-static const tsk_object_def_t tdav_codec_h263p_def_s =
-{
- sizeof(tdav_codec_h263p_t),
- tdav_codec_h263p_ctor,
- tdav_codec_h263p_dtor,
- tmedia_codec_cmp,
+static const tsk_object_def_t tdav_codec_h263p_def_s = {
+ sizeof(tdav_codec_h263p_t),
+ tdav_codec_h263p_ctor,
+ tdav_codec_h263p_dtor,
+ tmedia_codec_cmp,
};
/* plugin definition*/
-static const tmedia_codec_plugin_def_t tdav_codec_h263p_plugin_def_s =
-{
- &tdav_codec_h263p_def_s,
-
- tmedia_video,
- tmedia_codec_id_h263p,
- "H263-1998",
- "H263-1998 codec (FFmpeg)",
- TMEDIA_CODEC_FORMAT_H263_1998,
- tsk_true,
- 90000, // rate
-
- /* audio */
- { 0 },
-
- /* video (width, height, fps) */
- {176, 144, 0},// fps is @deprecated
-
- tdav_codec_h263p_set,
- tdav_codec_h263p_open,
- tdav_codec_h263p_close,
- tdav_codec_h263p_encode,
- tdav_codec_h263p_decode,
- tdav_codec_h263p_sdp_att_match,
- tdav_codec_h263p_sdp_att_get
+static const tmedia_codec_plugin_def_t tdav_codec_h263p_plugin_def_s = {
+ &tdav_codec_h263p_def_s,
+
+ tmedia_video,
+ tmedia_codec_id_h263p,
+ "H263-1998",
+ "H263-1998 codec (FFmpeg)",
+ TMEDIA_CODEC_FORMAT_H263_1998,
+ tsk_true,
+ 90000, // rate
+
+ /* audio */
+ { 0 },
+
+ /* video (width, height, fps) */
+ {176, 144, 0},// fps is @deprecated
+
+ tdav_codec_h263p_set,
+ tdav_codec_h263p_open,
+ tdav_codec_h263p_close,
+ tdav_codec_h263p_encode,
+ tdav_codec_h263p_decode,
+ tdav_codec_h263p_sdp_att_match,
+ tdav_codec_h263p_sdp_att_get
};
const tmedia_codec_plugin_def_t *tdav_codec_h263p_plugin_def_t = &tdav_codec_h263p_plugin_def_s;
@@ -846,61 +835,59 @@ const tmedia_codec_plugin_def_t *tdav_codec_h263p_plugin_def_t = &tdav_codec_h26
/* constructor */
static tsk_object_t* tdav_codec_h263pp_ctor(tsk_object_t * self, va_list * app)
{
- tdav_codec_h263pp_t *h263pp = self;
- if(h263pp){
- /* init base: called by tmedia_codec_create() */
- /* init self */
- tdav_codec_h263_init(TDAV_CODEC_H263(self), tdav_codec_h263_2000, CODEC_ID_H263P, CODEC_ID_H263);
- }
- return self;
+ tdav_codec_h263pp_t *h263pp = self;
+ if(h263pp) {
+ /* init base: called by tmedia_codec_create() */
+ /* init self */
+ tdav_codec_h263_init(TDAV_CODEC_H263(self), tdav_codec_h263_2000, CODEC_ID_H263P, CODEC_ID_H263);
+ }
+ return self;
}
/* destructor */
static tsk_object_t* tdav_codec_h263pp_dtor(tsk_object_t * self)
-{
- tdav_codec_h263pp_t *h263pp = self;
- if(h263pp){
- /* deinit base */
- tmedia_codec_video_deinit(h263pp);
- /* deinit self */
- tdav_codec_h263_deinit(TDAV_CODEC_H263(self));
- }
-
- return self;
+{
+ tdav_codec_h263pp_t *h263pp = self;
+ if(h263pp) {
+ /* deinit base */
+ tmedia_codec_video_deinit(h263pp);
+ /* deinit self */
+ tdav_codec_h263_deinit(TDAV_CODEC_H263(self));
+ }
+
+ return self;
}
/* object definition */
-static const tsk_object_def_t tdav_codec_h263pp_def_s =
-{
- sizeof(tdav_codec_h263pp_t),
- tdav_codec_h263pp_ctor,
- tdav_codec_h263pp_dtor,
- tmedia_codec_cmp,
+static const tsk_object_def_t tdav_codec_h263pp_def_s = {
+ sizeof(tdav_codec_h263pp_t),
+ tdav_codec_h263pp_ctor,
+ tdav_codec_h263pp_dtor,
+ tmedia_codec_cmp,
};
/* plugin definition*/
-static const tmedia_codec_plugin_def_t tdav_codec_h263pp_plugin_def_s =
-{
- &tdav_codec_h263pp_def_s,
-
- tmedia_video,
- tmedia_codec_id_h263pp,
- "H263-2000",
- "H263-2000 codec (FFmpeg)",
- TMEDIA_CODEC_FORMAT_H263_2000,
- tsk_true,
- 90000, // rate
-
- /* audio */
- { 0 },
-
- /* video (width, height, fps)*/
- {176, 144, 0},// fps is @deprecated
-
- tdav_codec_h263pp_set,
- tdav_codec_h263pp_open,
- tdav_codec_h263pp_close,
- tdav_codec_h263pp_encode,
- tdav_codec_h263pp_decode,
- tdav_codec_h263pp_sdp_att_match,
- tdav_codec_h263pp_sdp_att_get
+static const tmedia_codec_plugin_def_t tdav_codec_h263pp_plugin_def_s = {
+ &tdav_codec_h263pp_def_s,
+
+ tmedia_video,
+ tmedia_codec_id_h263pp,
+ "H263-2000",
+ "H263-2000 codec (FFmpeg)",
+ TMEDIA_CODEC_FORMAT_H263_2000,
+ tsk_true,
+ 90000, // rate
+
+ /* audio */
+ { 0 },
+
+ /* video (width, height, fps)*/
+ {176, 144, 0},// fps is @deprecated
+
+ tdav_codec_h263pp_set,
+ tdav_codec_h263pp_open,
+ tdav_codec_h263pp_close,
+ tdav_codec_h263pp_encode,
+ tdav_codec_h263pp_decode,
+ tdav_codec_h263pp_sdp_att_match,
+ tdav_codec_h263pp_sdp_att_get
};
const tmedia_codec_plugin_def_t *tdav_codec_h263pp_plugin_def_t = &tdav_codec_h263pp_plugin_def_s;
@@ -908,465 +895,465 @@ const tmedia_codec_plugin_def_t *tdav_codec_h263pp_plugin_def_t = &tdav_codec_h2
int tdav_codec_h263_open_encoder(tdav_codec_h263_t* self)
{
- int ret;
- int size;
- int32_t max_bw_kpbs;
- if(self->encoder.context){
- TSK_DEBUG_ERROR("Encoder already opened");
- return -1;
- }
-
- self->encoder.context = avcodec_alloc_context();
- avcodec_get_context_defaults(self->encoder.context);
-
- self->encoder.context->pix_fmt = PIX_FMT_YUV420P;
- self->encoder.context->time_base.num = 1;
- self->encoder.context->time_base.den = TMEDIA_CODEC_VIDEO(self)->out.fps;
- self->encoder.context->width = TMEDIA_CODEC_VIDEO(self)->out.width;
- self->encoder.context->height = TMEDIA_CODEC_VIDEO(self)->out.height;
-
- self->encoder.context->qmin = 10;
- self->encoder.context->qmax = 51;
+ int ret;
+ int size;
+ int32_t max_bw_kpbs;
+ if(self->encoder.context) {
+ TSK_DEBUG_ERROR("Encoder already opened");
+ return -1;
+ }
+
+ self->encoder.context = avcodec_alloc_context();
+ avcodec_get_context_defaults(self->encoder.context);
+
+ self->encoder.context->pix_fmt = PIX_FMT_YUV420P;
+ self->encoder.context->time_base.num = 1;
+ self->encoder.context->time_base.den = TMEDIA_CODEC_VIDEO(self)->out.fps;
+ self->encoder.context->width = TMEDIA_CODEC_VIDEO(self)->out.width;
+ self->encoder.context->height = TMEDIA_CODEC_VIDEO(self)->out.height;
+
+ self->encoder.context->qmin = 10;
+ self->encoder.context->qmax = 51;
#if LIBAVCODEC_VERSION_MAJOR <= 53
self->encoder.context->mb_qmin = self->encoder.context->qmin;
- self->encoder.context->mb_qmax = self->encoder.context->qmax;
+ self->encoder.context->mb_qmax = self->encoder.context->qmax;
#endif
- self->encoder.context->mb_decision = FF_MB_DECISION_RD;
- max_bw_kpbs = TSK_CLAMP(
- 0,
- tmedia_get_video_bandwidth_kbps_2(TMEDIA_CODEC_VIDEO(self)->out.width, TMEDIA_CODEC_VIDEO(self)->out.height, TMEDIA_CODEC_VIDEO(self)->out.fps),
- self->encoder.max_bw_kpbs
- );
- self->encoder.context->bit_rate = (max_bw_kpbs * 1024);// bps
- //self->encoder.context->rc_lookahead = 0;
- self->encoder.context->rtp_payload_size = RTP_PAYLOAD_SIZE;
- self->encoder.context->opaque = tsk_null;
- self->encoder.context->gop_size = (TMEDIA_CODEC_VIDEO(self)->out.fps * TDAV_H263_GOP_SIZE_IN_SECONDS);
- self->encoder.context->flags |= CODEC_FLAG_QSCALE;
- self->encoder.context->global_quality = FF_QP2LAMBDA * self->encoder.quality;
- self->encoder.context->max_b_frames = 0;
-
- // Picture (YUV 420)
- if(!(self->encoder.picture = avcodec_alloc_frame())){
- TSK_DEBUG_ERROR("Failed to create encoder picture");
- return -2;
- }
- avcodec_get_frame_defaults(self->encoder.picture);
- //if((ret = avpicture_alloc((AVPicture*)self->encoder.picture, PIX_FMT_YUV420P, self->encoder.context->width, self->encoder.context->height))){
- // TSK_DEBUG_ERROR("Failed to allocate encoder picture");
- // return ret;
- //}
-
- size = avpicture_get_size(PIX_FMT_YUV420P, self->encoder.context->width, self->encoder.context->height);
- if(!(self->encoder.buffer = tsk_calloc(size, sizeof(uint8_t)))){
- TSK_DEBUG_ERROR("Failed to allocate encoder buffer");
- return -2;
- }
-
-
- // RTP Callback
- switch(self->type){
- case tdav_codec_h263_1996:
- { // H263 - 1996
- break;
- }
- case tdav_codec_h263_1998:
- { // H263 - 1998
+ self->encoder.context->mb_decision = FF_MB_DECISION_RD;
+ max_bw_kpbs = TSK_CLAMP(
+ 0,
+ tmedia_get_video_bandwidth_kbps_2(TMEDIA_CODEC_VIDEO(self)->out.width, TMEDIA_CODEC_VIDEO(self)->out.height, TMEDIA_CODEC_VIDEO(self)->out.fps),
+ self->encoder.max_bw_kpbs
+ );
+ self->encoder.context->bit_rate = (max_bw_kpbs * 1024);// bps
+ //self->encoder.context->rc_lookahead = 0;
+ self->encoder.context->rtp_payload_size = RTP_PAYLOAD_SIZE;
+ self->encoder.context->opaque = tsk_null;
+ self->encoder.context->gop_size = (TMEDIA_CODEC_VIDEO(self)->out.fps * TDAV_H263_GOP_SIZE_IN_SECONDS);
+ self->encoder.context->flags |= CODEC_FLAG_QSCALE;
+ self->encoder.context->global_quality = FF_QP2LAMBDA * self->encoder.quality;
+ self->encoder.context->max_b_frames = 0;
+
+ // Picture (YUV 420)
+ if(!(self->encoder.picture = avcodec_alloc_frame())) {
+ TSK_DEBUG_ERROR("Failed to create encoder picture");
+ return -2;
+ }
+ avcodec_get_frame_defaults(self->encoder.picture);
+ //if((ret = avpicture_alloc((AVPicture*)self->encoder.picture, PIX_FMT_YUV420P, self->encoder.context->width, self->encoder.context->height))){
+ // TSK_DEBUG_ERROR("Failed to allocate encoder picture");
+ // return ret;
+ //}
+
+ size = avpicture_get_size(PIX_FMT_YUV420P, self->encoder.context->width, self->encoder.context->height);
+ if(!(self->encoder.buffer = tsk_calloc(size, sizeof(uint8_t)))) {
+ TSK_DEBUG_ERROR("Failed to allocate encoder buffer");
+ return -2;
+ }
+
+
+ // RTP Callback
+ switch(self->type) {
+ case tdav_codec_h263_1996: {
+ // H263 - 1996
+ break;
+ }
+ case tdav_codec_h263_1998: {
+ // H263 - 1998
#if defined(CODEC_FLAG_H263P_UMV)
- self->encoder.context->flags |= CODEC_FLAG_H263P_UMV; // Annex D+
+ self->encoder.context->flags |= CODEC_FLAG_H263P_UMV; // Annex D+
#endif
- self->encoder.context->flags |= CODEC_FLAG_AC_PRED; // Annex I and T
- self->encoder.context->flags |= CODEC_FLAG_LOOP_FILTER; // Annex J
+ self->encoder.context->flags |= CODEC_FLAG_AC_PRED; // Annex I and T
+ self->encoder.context->flags |= CODEC_FLAG_LOOP_FILTER; // Annex J
#if defined(CODEC_FLAG_H263P_SLICE_STRUCT)
- self->encoder.context->flags |= CODEC_FLAG_H263P_SLICE_STRUCT; // Annex K
+ self->encoder.context->flags |= CODEC_FLAG_H263P_SLICE_STRUCT; // Annex K
#endif
#if defined(CODEC_FLAG_H263P_AIV)
- self->encoder.context->flags |= CODEC_FLAG_H263P_AIV; // Annex S
+ self->encoder.context->flags |= CODEC_FLAG_H263P_AIV; // Annex S
#endif
- break;
- }
- case tdav_codec_h263_2000:
- { // H263 - 2000
+ break;
+ }
+ case tdav_codec_h263_2000: {
+ // H263 - 2000
#if defined(CODEC_FLAG_H263P_UMV)
- self->encoder.context->flags |= CODEC_FLAG_H263P_UMV; // Annex D+
+ self->encoder.context->flags |= CODEC_FLAG_H263P_UMV; // Annex D+
#endif
- self->encoder.context->flags |= CODEC_FLAG_AC_PRED; // Annex I and T
- self->encoder.context->flags |= CODEC_FLAG_LOOP_FILTER; // Annex J
+ self->encoder.context->flags |= CODEC_FLAG_AC_PRED; // Annex I and T
+ self->encoder.context->flags |= CODEC_FLAG_LOOP_FILTER; // Annex J
#if defined(CODEC_FLAG_H263P_SLICE_STRUCT)
- self->encoder.context->flags |= CODEC_FLAG_H263P_SLICE_STRUCT; // Annex K
+ self->encoder.context->flags |= CODEC_FLAG_H263P_SLICE_STRUCT; // Annex K
#endif
#if defined(CODEC_FLAG_H263P_AIV)
- self->encoder.context->flags |= CODEC_FLAG_H263P_AIV; // Annex S
+ self->encoder.context->flags |= CODEC_FLAG_H263P_AIV; // Annex S
#endif
- break;
- }
- }
- // Open encoder
- if((ret = avcodec_open(self->encoder.context, self->encoder.codec)) < 0){
- TSK_DEBUG_ERROR("Failed to open [%s] codec", TMEDIA_CODEC(self)->plugin->desc);
- return ret;
- }
-
- TSK_DEBUG_INFO("[H.263] bitrate=%d bps", self->encoder.context->bit_rate);
-
- return ret;
+ break;
+ }
+ }
+ // Open encoder
+ if((ret = avcodec_open(self->encoder.context, self->encoder.codec)) < 0) {
+ TSK_DEBUG_ERROR("Failed to open [%s] codec", TMEDIA_CODEC(self)->plugin->desc);
+ return ret;
+ }
+
+ TSK_DEBUG_INFO("[H.263] bitrate=%d bps", self->encoder.context->bit_rate);
+
+ return ret;
}
int tdav_codec_h263_open_decoder(tdav_codec_h263_t* self)
{
- int ret, size;
-
- if(self->decoder.context){
- TSK_DEBUG_ERROR("Decoder already opened");
- return -1;
- }
-
- self->decoder.context = avcodec_alloc_context();
- avcodec_get_context_defaults(self->decoder.context);
-
- self->decoder.context->pix_fmt = PIX_FMT_YUV420P;
- self->decoder.context->width = TMEDIA_CODEC_VIDEO(self)->in.width;
- self->decoder.context->height = TMEDIA_CODEC_VIDEO(self)->in.height;
-
- // Picture (YUV 420)
- if(!(self->decoder.picture = avcodec_alloc_frame())){
- TSK_DEBUG_ERROR("Failed to create decoder picture");
- return -2;
- }
- avcodec_get_frame_defaults(self->decoder.picture);
-
- size = avpicture_get_size(PIX_FMT_YUV420P, self->decoder.context->width, self->decoder.context->height);
- if(!(self->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(self->decoder.context, self->decoder.codec)) < 0){
- TSK_DEBUG_ERROR("Failed to open [%s] codec", TMEDIA_CODEC(self)->plugin->desc);
- return ret;
- }
-
+ int ret, size;
+
+ if(self->decoder.context) {
+ TSK_DEBUG_ERROR("Decoder already opened");
+ return -1;
+ }
+
+ self->decoder.context = avcodec_alloc_context();
+ avcodec_get_context_defaults(self->decoder.context);
+
+ self->decoder.context->pix_fmt = PIX_FMT_YUV420P;
+ self->decoder.context->width = TMEDIA_CODEC_VIDEO(self)->in.width;
+ self->decoder.context->height = TMEDIA_CODEC_VIDEO(self)->in.height;
+
+ // Picture (YUV 420)
+ if(!(self->decoder.picture = avcodec_alloc_frame())) {
+ TSK_DEBUG_ERROR("Failed to create decoder picture");
+ return -2;
+ }
+ avcodec_get_frame_defaults(self->decoder.picture);
+
+ size = avpicture_get_size(PIX_FMT_YUV420P, self->decoder.context->width, self->decoder.context->height);
+ if(!(self->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(self->decoder.context, self->decoder.codec)) < 0) {
+ TSK_DEBUG_ERROR("Failed to open [%s] codec", TMEDIA_CODEC(self)->plugin->desc);
+ return ret;
+ }
+
self->decoder.last_seq = 0;
- return ret;
+ return ret;
}
int tdav_codec_h263_close_encoder(tdav_codec_h263_t* self)
{
- if(self->encoder.context){
- avcodec_close(self->encoder.context);
- av_free(self->encoder.context);
- self->encoder.context = tsk_null;
- }
- if(self->encoder.picture){
- av_free(self->encoder.picture);
- self->encoder.picture = tsk_null;
- }
- if(self->encoder.buffer){
- TSK_FREE(self->encoder.buffer);
- }
- return 0;
+ if(self->encoder.context) {
+ avcodec_close(self->encoder.context);
+ av_free(self->encoder.context);
+ self->encoder.context = tsk_null;
+ }
+ if(self->encoder.picture) {
+ av_free(self->encoder.picture);
+ self->encoder.picture = tsk_null;
+ }
+ if(self->encoder.buffer) {
+ TSK_FREE(self->encoder.buffer);
+ }
+ return 0;
}
int tdav_codec_h263_close_decoder(tdav_codec_h263_t* self)
{
- if(self->decoder.context){
- avcodec_close(self->decoder.context);
- av_free(self->decoder.context);
- self->decoder.context = tsk_null;
- }
- if(self->decoder.picture){
- av_free(self->decoder.picture);
- self->decoder.picture = tsk_null;
- }
- if(self->decoder.accumulator){
- TSK_FREE(self->decoder.accumulator);
- self->decoder.accumulator_pos = 0;
- }
- return 0;
+ if(self->decoder.context) {
+ avcodec_close(self->decoder.context);
+ av_free(self->decoder.context);
+ self->decoder.context = tsk_null;
+ }
+ if(self->decoder.picture) {
+ av_free(self->decoder.picture);
+ self->decoder.picture = tsk_null;
+ }
+ if(self->decoder.accumulator) {
+ TSK_FREE(self->decoder.accumulator);
+ self->decoder.accumulator_pos = 0;
+ }
+ return 0;
}
/* ============ Callbacks ================= */
static void tdav_codec_h263_encap(const tdav_codec_h263_t* h263, const uint8_t* pdata, tsk_size_t size)
{
- tsk_bool_t frag = tsk_false;
- register uint32_t i, last_index = 0;
-
- if(size < RTP_PAYLOAD_SIZE){
- goto last;
- }
-
- for(i = 4; i<(size - 4); i++){
- if(pdata[i] == 0x00 && pdata[i+1] == 0x00 && pdata[i+2]>=0x80){ /* PSC or (GBSC) found */
- if((i - last_index) >= RTP_PAYLOAD_SIZE || tsk_true/* FIXME */){
- switch(h263->type){
- case tdav_codec_h263_1996:
- tdav_codec_h263_rtp_callback((tdav_codec_h263_t*) h263, pdata+last_index,
- (i - last_index), (last_index == size));
- break;
- default:
- tdav_codec_h263p_rtp_callback((tdav_codec_h263_t*) h263, pdata + last_index,
- (i - last_index), frag, (last_index == size));
- frag = tsk_true;
- break;
- }
- last_index = i;
- }
- }
- }
+ tsk_bool_t frag = tsk_false;
+ register uint32_t i, last_index = 0;
+
+ if(size < RTP_PAYLOAD_SIZE) {
+ goto last;
+ }
+
+ for(i = 4; i<(size - 4); i++) {
+ if(pdata[i] == 0x00 && pdata[i+1] == 0x00 && pdata[i+2]>=0x80) { /* PSC or (GBSC) found */
+ if((i - last_index) >= RTP_PAYLOAD_SIZE || tsk_true/* FIXME */) {
+ switch(h263->type) {
+ case tdav_codec_h263_1996:
+ tdav_codec_h263_rtp_callback((tdav_codec_h263_t*) h263, pdata+last_index,
+ (i - last_index), (last_index == size));
+ break;
+ default:
+ tdav_codec_h263p_rtp_callback((tdav_codec_h263_t*) h263, pdata + last_index,
+ (i - last_index), frag, (last_index == size));
+ frag = tsk_true;
+ break;
+ }
+ last_index = i;
+ }
+ }
+ }
last:
- if(last_index < size){
- switch(h263->type){
- case tdav_codec_h263_1996:
- tdav_codec_h263_rtp_callback((tdav_codec_h263_t*) h263, pdata + last_index,
- (size - last_index), tsk_true);
- break;
- default:
- tdav_codec_h263p_rtp_callback((tdav_codec_h263_t*) h263, pdata + last_index,
- (size - last_index), frag, tsk_true);
- break;
- }
- }
+ if(last_index < size) {
+ switch(h263->type) {
+ case tdav_codec_h263_1996:
+ tdav_codec_h263_rtp_callback((tdav_codec_h263_t*) h263, pdata + last_index,
+ (size - last_index), tsk_true);
+ break;
+ default:
+ tdav_codec_h263p_rtp_callback((tdav_codec_h263_t*) h263, pdata + last_index,
+ (size - last_index), frag, tsk_true);
+ break;
+ }
+ }
}
static void tdav_codec_h263_rtp_callback(tdav_codec_h263_t *self, const void *data, tsk_size_t size, tsk_bool_t marker)
{
- uint8_t* pdata = (uint8_t*)data;
-
- if(self->rtp.size < (size + H263_HEADER_MODE_A_SIZE)){
- if(!(self->rtp.ptr = tsk_realloc(self->rtp.ptr, (size + H263_HEADER_MODE_A_SIZE)))){
- TSK_DEBUG_ERROR("Failed to allocate new buffer");
- return;
- }
- self->rtp.size = (size + H263_HEADER_MODE_A_SIZE);
- }
- memcpy((self->rtp.ptr + H263_HEADER_MODE_A_SIZE), data, size);
-
- /* http://eu.sabotage.org/www/ITU/H/H0263e.pdf section 5.1
- * 5.1.1 Picture Start Code (PSC) (22 bits) - PSC is a word of 22 bits. Its value is 0000 0000 0000 0000 1 00000.
-
- *
- * 5.1.1 Picture Start Code (PSC) (22 bits)
- * 5.1.2 Temporal Reference (TR) (8 bits)
- * 5.1.3 Type Information (PTYPE) (Variable Length)
- * – Bit 1: Always "1", in order to avoid start code emulation.
- * – Bit 2: Always "0", for distinction with Recommendation H.261.
-
- * – Bit 3: Split screen indicator, "0" off, "1" on.
- * – Bit 4: Document camera indicator, "0" off, "1" on.
- * – Bit 5: Full Picture Freeze Release, "0" off, "1" on.
- * – Bits 6-8: Source Format, "000" forbidden, "001" sub-QCIF, "010" QCIF, "011" CIF,
- "100" 4CIF, "101" 16CIF, "110" reserved, "111" extended PTYPE.
- If bits 6-8 are not equal to "111", which indicates an extended PTYPE (PLUSPTYPE), the following
- five bits are also present in PTYPE:
- – Bit 9: Picture Coding Type, "0" INTRA (I-picture), "1" INTER (P-picture).
- – Bit 10: Optional Unrestricted Motion Vector mode (see Annex D), "0" off, "1" on.
- – Bit 11: Optional Syntax-based Arithmetic Coding mode (see Annex E), "0" off, "1" on.
- – Bit 12: Optional Advanced Prediction mode (see Annex F), "0" off, "1" on.
- – Bit 13: Optional PB-frames mode (see Annex G), "0" normal I- or P-picture, "1" PB-frame.
- */
- if(pdata[0] == 0x00 && pdata[1] == 0x00 && (pdata[2] & 0xfc)==0x80){ /* PSC */
- /* RFC 2190 -5.1 Mode A
- 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|P|SBIT |EBIT | SRC |I|U|S|A|R |DBQ| TRB | TR |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
- SRC : 3 bits
- Source format, bit 6,7 and 8 in PTYPE defined by H.263 [4], specifies
- the resolution of the current picture.
-
- I: 1 bit.
- Picture coding type, bit 9 in PTYPE defined by H.263[4], "0" is
- intra-coded, "1" is inter-coded.
- */
-
- // PDATA[4] ======> Bits 3-10 of PTYPE
- uint32_t rtp_hdr = 0;
- uint8_t format, pict_type;
-
- // Source Format = 4,5,6
- format = (pdata[4] & 0x3C)>>2;
- // Picture Coding Type = 7
- pict_type = (pdata[4] & 0x02)>>1;
- // RTP mode A header
- ((uint8_t*)&rtp_hdr)[1] = (format <<5) | (pict_type << 4);
- //rtp_hdr = tnet_htonl(rtp_hdr);
- memcpy(self->rtp.ptr, &rtp_hdr, sizeof(rtp_hdr));
- }
-
- // Send data over the network
- if(TMEDIA_CODEC_VIDEO(self)->out.callback){
- TMEDIA_CODEC_VIDEO(self)->out.result.buffer.ptr = self->rtp.ptr;
- TMEDIA_CODEC_VIDEO(self)->out.result.buffer.size = (size + H263_HEADER_MODE_A_SIZE);
- TMEDIA_CODEC_VIDEO(self)->out.result.duration = (uint32_t)((1./(double)TMEDIA_CODEC_VIDEO(self)->out.fps) * TMEDIA_CODEC(self)->plugin->rate);
- TMEDIA_CODEC_VIDEO(self)->out.result.last_chunck = marker;
- TMEDIA_CODEC_VIDEO(self)->out.callback(&TMEDIA_CODEC_VIDEO(self)->out.result);
- }
+ uint8_t* pdata = (uint8_t*)data;
+
+ if(self->rtp.size < (size + H263_HEADER_MODE_A_SIZE)) {
+ if(!(self->rtp.ptr = tsk_realloc(self->rtp.ptr, (size + H263_HEADER_MODE_A_SIZE)))) {
+ TSK_DEBUG_ERROR("Failed to allocate new buffer");
+ return;
+ }
+ self->rtp.size = (size + H263_HEADER_MODE_A_SIZE);
+ }
+ memcpy((self->rtp.ptr + H263_HEADER_MODE_A_SIZE), data, size);
+
+ /* http://eu.sabotage.org/www/ITU/H/H0263e.pdf section 5.1
+ * 5.1.1 Picture Start Code (PSC) (22 bits) - PSC is a word of 22 bits. Its value is 0000 0000 0000 0000 1 00000.
+
+ *
+ * 5.1.1 Picture Start Code (PSC) (22 bits)
+ * 5.1.2 Temporal Reference (TR) (8 bits)
+ * 5.1.3 Type Information (PTYPE) (Variable Length)
+ * – Bit 1: Always "1", in order to avoid start code emulation.
+ * – Bit 2: Always "0", for distinction with Recommendation H.261.
+
+ * – Bit 3: Split screen indicator, "0" off, "1" on.
+ * – Bit 4: Document camera indicator, "0" off, "1" on.
+ * – Bit 5: Full Picture Freeze Release, "0" off, "1" on.
+ * – Bits 6-8: Source Format, "000" forbidden, "001" sub-QCIF, "010" QCIF, "011" CIF,
+ "100" 4CIF, "101" 16CIF, "110" reserved, "111" extended PTYPE.
+ If bits 6-8 are not equal to "111", which indicates an extended PTYPE (PLUSPTYPE), the following
+ five bits are also present in PTYPE:
+ – Bit 9: Picture Coding Type, "0" INTRA (I-picture), "1" INTER (P-picture).
+ – Bit 10: Optional Unrestricted Motion Vector mode (see Annex D), "0" off, "1" on.
+ – Bit 11: Optional Syntax-based Arithmetic Coding mode (see Annex E), "0" off, "1" on.
+ – Bit 12: Optional Advanced Prediction mode (see Annex F), "0" off, "1" on.
+ – Bit 13: Optional PB-frames mode (see Annex G), "0" normal I- or P-picture, "1" PB-frame.
+ */
+ if(pdata[0] == 0x00 && pdata[1] == 0x00 && (pdata[2] & 0xfc)==0x80) { /* PSC */
+ /* RFC 2190 -5.1 Mode A
+ 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|P|SBIT |EBIT | SRC |I|U|S|A|R |DBQ| TRB | TR |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ SRC : 3 bits
+ Source format, bit 6,7 and 8 in PTYPE defined by H.263 [4], specifies
+ the resolution of the current picture.
+
+ I: 1 bit.
+ Picture coding type, bit 9 in PTYPE defined by H.263[4], "0" is
+ intra-coded, "1" is inter-coded.
+ */
+
+ // PDATA[4] ======> Bits 3-10 of PTYPE
+ uint32_t rtp_hdr = 0;
+ uint8_t format, pict_type;
+
+ // Source Format = 4,5,6
+ format = (pdata[4] & 0x3C)>>2;
+ // Picture Coding Type = 7
+ pict_type = (pdata[4] & 0x02)>>1;
+ // RTP mode A header
+ ((uint8_t*)&rtp_hdr)[1] = (format <<5) | (pict_type << 4);
+ //rtp_hdr = tnet_htonl(rtp_hdr);
+ memcpy(self->rtp.ptr, &rtp_hdr, sizeof(rtp_hdr));
+ }
+
+ // Send data over the network
+ if(TMEDIA_CODEC_VIDEO(self)->out.callback) {
+ TMEDIA_CODEC_VIDEO(self)->out.result.buffer.ptr = self->rtp.ptr;
+ TMEDIA_CODEC_VIDEO(self)->out.result.buffer.size = (size + H263_HEADER_MODE_A_SIZE);
+ TMEDIA_CODEC_VIDEO(self)->out.result.duration = (uint32_t)((1./(double)TMEDIA_CODEC_VIDEO(self)->out.fps) * TMEDIA_CODEC(self)->plugin->rate);
+ TMEDIA_CODEC_VIDEO(self)->out.result.last_chunck = marker;
+ TMEDIA_CODEC_VIDEO(self)->out.callback(&TMEDIA_CODEC_VIDEO(self)->out.result);
+ }
}
static void tdav_codec_h263p_rtp_callback(tdav_codec_h263_t *self, const void *data, tsk_size_t size, tsk_bool_t frag, tsk_bool_t marker)
{
- uint8_t* pdata = (uint8_t*)data;
- //uint8_t rtp_hdr[2] = {0x00, 0x00};
- //tsk_bool_t eos = tsk_false;
+ uint8_t* pdata = (uint8_t*)data;
+ //uint8_t rtp_hdr[2] = {0x00, 0x00};
+ //tsk_bool_t eos = tsk_false;
- const void* _ptr = tsk_null;
- tsk_size_t _size = 0;
- //static tsk_bool_t frag = tsk_false;
- //tsk_bool_t found_gob = tsk_false;
+ const void* _ptr = tsk_null;
+ tsk_size_t _size = 0;
+ //static tsk_bool_t frag = tsk_false;
+ //tsk_bool_t found_gob = tsk_false;
- /* RFC 4629 - 5.1. General H.263+ Payload Header
- The H.263+ payload header is structured as follows:
+ /* RFC 4629 - 5.1. General H.263+ Payload Header
+ The H.263+ payload header is structured as follows:
0 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| RR |P|V| PLEN |PEBIT|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-
- /* http://eu.sabotage.org/www/ITU/H/H0263e.pdf
- *
- * 5.1.1 Picture Start Code (PSC) (22 bits)
- * ->PSC is a word of 22 bits. Its value is 0000 0000 0000 0000 1 00000.
- * 5.1.27 End Of Sequence (EOS) (22 bits)
- * ->A codeword of 22 bits. Its value is 0000 0000 0000 0000 1 11111
- * 5.2.2 Group of Block Start Code (GBSC) (17 bits)
- * ->A word of 17 bits. Its value is 0000 0000 0000 0000 1
- * C.4.1 End Of Sub-Bitstream code (EOSBS) (23 bits)
- * ->The EOSBS code is a codeword of 23 bits. Its value is 0000 0000 0000 0000 1 11110 0
- *
- *
- * 5.2.3 Group Number (GN) (5 bits)
- * -> last 5 bits
- */
- //if(pdata[0] == 0x00 && pdata[1] == 0x00 && pdata[2] >= 0x80){ /* PSC or EOS or GBSC */
- // uint8_t GN = ((pdata[2]>>2) & 0x1F);
- // found_gob = tsk_true;
- // //TSK_DEBUG_INFO("GN=%u", pdata[2]);
- //
- // /* RFC 4629 - 6.1.1. Packets that begin with a Picture Start Code
- // A packet that begins at the location of a Picture, GOB, slice, EOS,
- // or EOSBS start code shall omit the first two (all zero) bytes from
- // the H.263+ bitstream and signify their presence by setting P=1 in the
- // payload header.
- // */
-
- // if(GN == 0x00){ /* PSC 00000 */
- // /* Use the two first bytes as RTP header */
- // //pdata[0] |= 0x04; // P=1
-
- // /*
- // 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
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | RR |1|V|0|0|0|0|0|0|0|0|0| bitstream data without the :
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // : first two 0 bytes of the PSC
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // */
-
- // //TSK_DEBUG_INFO("H263 - PSC");
- // }
- // else if(GN == 0x1F){ /* EOS 11111 */
- // /* Use the two first bytes as RTP header */
- // //pdata[0] |= 0x04; // P=1
- // eos = tsk_true;
- // /* RFC 4629 - 6.1.3. Packets that begin with an EOS or EOSBS Code
- // 0 1 2
- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | RR |1|V|0|0|0|0|0|0|0|0|0|1|1|1|1|1|1|0|0|
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // */
- // //TSK_DEBUG_INFO("H263 - EOS");
- // }
- // else /*if((GN >> 4) == 0x01)*/{ /* GBSC 10000 */
- // /* Use the two first bytes as RTP header */
- // //pdata[0] |= 0x04; // P=1
- //
- // /* RFC 4629 - 6.1.2. Packets that begin with GBSC or SSC
- // 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
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | RR |1|V|0 0 1 0 0 1|PEBIT|1 0 0 0 0 0| picture header :
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // : starting with TR, PTYPE ... |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | ... | bitstream :
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // : data starting with GBSC/SSC without its first two 0 bytes
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // */
- // //TSK_DEBUG_INFO("H263 - GBSC");
- // found_gob = tsk_false;
- // }
- // //else if(EOSBS) -> Not Supported
- //}
- //else{
- // /* 6.2. Encapsulating Follow-on Packet (P=0) */
- // int i = 0;
- // i++;
- //}
-
- //if(/*eos*/!found_gob && frag){
- // if(self->rtp.size < (size + 2/* H263+ Header size */)){
- // if(!(self->rtp.ptr = tsk_realloc(self->rtp.ptr, (size + 2)))){
- // TSK_DEBUG_ERROR("Failed to allocate new buffer");
- // return;
- // }
- // self->rtp.size = (size + 2);
- // }
- // /* RFC 4629 - 6. Packetization Schemes */
- // //rtp_hdr[0] |= 0x00;
- // //memcpy(self->rtp.ptr, rtp_hdr/* zeros-> is it corretc? */, 2);
- // //memcpy((self->rtp.ptr + 2), pdata, size);
- // //_ptr = self->rtp.ptr;
- // //_size = (size + 2);
-
- // pdata[0] |= pdata[2] > 0x80 ? 0x04 : 0x04;
- // _ptr = pdata;
- // _size = size;
- //}
- //else{
- // pdata[0] |= pdata[2] > 0x80 ? 0x04 : 0x04;
- // _ptr = pdata;
- // _size = size;
- //}
+ */
+
+ /* http://eu.sabotage.org/www/ITU/H/H0263e.pdf
+ *
+ * 5.1.1 Picture Start Code (PSC) (22 bits)
+ * ->PSC is a word of 22 bits. Its value is 0000 0000 0000 0000 1 00000.
+ * 5.1.27 End Of Sequence (EOS) (22 bits)
+ * ->A codeword of 22 bits. Its value is 0000 0000 0000 0000 1 11111
+ * 5.2.2 Group of Block Start Code (GBSC) (17 bits)
+ * ->A word of 17 bits. Its value is 0000 0000 0000 0000 1
+ * C.4.1 End Of Sub-Bitstream code (EOSBS) (23 bits)
+ * ->The EOSBS code is a codeword of 23 bits. Its value is 0000 0000 0000 0000 1 11110 0
+ *
+ *
+ * 5.2.3 Group Number (GN) (5 bits)
+ * -> last 5 bits
+ */
+ //if(pdata[0] == 0x00 && pdata[1] == 0x00 && pdata[2] >= 0x80){ /* PSC or EOS or GBSC */
+ // uint8_t GN = ((pdata[2]>>2) & 0x1F);
+ // found_gob = tsk_true;
+ // //TSK_DEBUG_INFO("GN=%u", pdata[2]);
+ //
+ // /* RFC 4629 - 6.1.1. Packets that begin with a Picture Start Code
+ // A packet that begins at the location of a Picture, GOB, slice, EOS,
+ // or EOSBS start code shall omit the first two (all zero) bytes from
+ // the H.263+ bitstream and signify their presence by setting P=1 in the
+ // payload header.
+ // */
+
+ // if(GN == 0x00){ /* PSC 00000 */
+ // /* Use the two first bytes as RTP header */
+ // //pdata[0] |= 0x04; // P=1
+
+ // /*
+ // 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
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | RR |1|V|0|0|0|0|0|0|0|0|0| bitstream data without the :
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // : first two 0 bytes of the PSC
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // */
+
+ // //TSK_DEBUG_INFO("H263 - PSC");
+ // }
+ // else if(GN == 0x1F){ /* EOS 11111 */
+ // /* Use the two first bytes as RTP header */
+ // //pdata[0] |= 0x04; // P=1
+ // eos = tsk_true;
+ // /* RFC 4629 - 6.1.3. Packets that begin with an EOS or EOSBS Code
+ // 0 1 2
+ // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | RR |1|V|0|0|0|0|0|0|0|0|0|1|1|1|1|1|1|0|0|
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // */
+ // //TSK_DEBUG_INFO("H263 - EOS");
+ // }
+ // else /*if((GN >> 4) == 0x01)*/{ /* GBSC 10000 */
+ // /* Use the two first bytes as RTP header */
+ // //pdata[0] |= 0x04; // P=1
+ //
+ // /* RFC 4629 - 6.1.2. Packets that begin with GBSC or SSC
+ // 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
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | RR |1|V|0 0 1 0 0 1|PEBIT|1 0 0 0 0 0| picture header :
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // : starting with TR, PTYPE ... |
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | ... | bitstream :
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // : data starting with GBSC/SSC without its first two 0 bytes
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // */
+ // //TSK_DEBUG_INFO("H263 - GBSC");
+ // found_gob = tsk_false;
+ // }
+ // //else if(EOSBS) -> Not Supported
+ //}
+ //else{
+ // /* 6.2. Encapsulating Follow-on Packet (P=0) */
+ // int i = 0;
+ // i++;
+ //}
+
+ //if(/*eos*/!found_gob && frag){
+ // if(self->rtp.size < (size + 2/* H263+ Header size */)){
+ // if(!(self->rtp.ptr = tsk_realloc(self->rtp.ptr, (size + 2)))){
+ // TSK_DEBUG_ERROR("Failed to allocate new buffer");
+ // return;
+ // }
+ // self->rtp.size = (size + 2);
+ // }
+ // /* RFC 4629 - 6. Packetization Schemes */
+ // //rtp_hdr[0] |= 0x00;
+ // //memcpy(self->rtp.ptr, rtp_hdr/* zeros-> is it corretc? */, 2);
+ // //memcpy((self->rtp.ptr + 2), pdata, size);
+ // //_ptr = self->rtp.ptr;
+ // //_size = (size + 2);
+
+ // pdata[0] |= pdata[2] > 0x80 ? 0x04 : 0x04;
+ // _ptr = pdata;
+ // _size = size;
+ //}
+ //else{
+ // pdata[0] |= pdata[2] > 0x80 ? 0x04 : 0x04;
+ // _ptr = pdata;
+ // _size = size;
+ //}
// FIXME
- pdata[0] |= pdata[2] > 0x80 ? 0x04 : 0x04;
- _ptr = pdata;
- _size = size;
-
-
- // Send data over the network
- if(TMEDIA_CODEC_VIDEO(self)->out.callback){
- TMEDIA_CODEC_VIDEO(self)->out.result.buffer.ptr = _ptr;
- TMEDIA_CODEC_VIDEO(self)->out.result.buffer.size = _size;
- TMEDIA_CODEC_VIDEO(self)->out.result.duration = (uint32_t)((1./(double)TMEDIA_CODEC_VIDEO(self)->out.fps) * TMEDIA_CODEC(self)->plugin->rate);
- TMEDIA_CODEC_VIDEO(self)->out.result.last_chunck = marker;
- TMEDIA_CODEC_VIDEO(self)->out.callback(&TMEDIA_CODEC_VIDEO(self)->out.result);
- }
+ pdata[0] |= pdata[2] > 0x80 ? 0x04 : 0x04;
+ _ptr = pdata;
+ _size = size;
+
+
+ // Send data over the network
+ if(TMEDIA_CODEC_VIDEO(self)->out.callback) {
+ TMEDIA_CODEC_VIDEO(self)->out.result.buffer.ptr = _ptr;
+ TMEDIA_CODEC_VIDEO(self)->out.result.buffer.size = _size;
+ TMEDIA_CODEC_VIDEO(self)->out.result.duration = (uint32_t)((1./(double)TMEDIA_CODEC_VIDEO(self)->out.fps) * TMEDIA_CODEC(self)->plugin->rate);
+ TMEDIA_CODEC_VIDEO(self)->out.result.last_chunck = marker;
+ TMEDIA_CODEC_VIDEO(self)->out.callback(&TMEDIA_CODEC_VIDEO(self)->out.result);
+ }
}
tsk_bool_t tdav_codec_ffmpeg_h263_is_supported()
{
- return (avcodec_find_encoder(CODEC_ID_H263) && avcodec_find_decoder(CODEC_ID_H263));
+ return (avcodec_find_encoder(CODEC_ID_H263) && avcodec_find_decoder(CODEC_ID_H263));
}
tsk_bool_t tdav_codec_ffmpeg_h263p_is_supported()
{
- return (avcodec_find_encoder(CODEC_ID_H263P) && avcodec_find_decoder(CODEC_ID_H263));
+ return (avcodec_find_encoder(CODEC_ID_H263P) && avcodec_find_decoder(CODEC_ID_H263));
}
tsk_bool_t tdav_codec_ffmpeg_h263pp_is_supported()
{
- return tdav_codec_ffmpeg_h263p_is_supported();
+ return tdav_codec_ffmpeg_h263p_is_supported();
}
diff --git a/tinyDAV/src/codecs/h264/tdav_codec_h264.c b/tinyDAV/src/codecs/h264/tdav_codec_h264.c
index 0ec3760..82cd2e5 100755
--- a/tinyDAV/src/codecs/h264/tdav_codec_h264.c
+++ b/tinyDAV/src/codecs/h264/tdav_codec_h264.c
@@ -2,19 +2,19 @@
* Copyright (C) 2010-2011 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.
*
@@ -51,39 +51,38 @@
# endif
#endif
-typedef struct tdav_codec_h264_s
-{
- TDAV_DECLARE_CODEC_H264_COMMON;
+typedef struct tdav_codec_h264_s {
+ TDAV_DECLARE_CODEC_H264_COMMON;
- // Encoder
- struct{
+ // Encoder
+ struct {
#if HAVE_FFMPEG
- AVCodec* codec;
- AVCodecContext* context;
- AVFrame* picture;
+ AVCodec* codec;
+ AVCodecContext* context;
+ AVFrame* picture;
#endif
- void* buffer;
- int64_t frame_count;
- tsk_bool_t force_idr;
- int32_t quality; // [1-31]
- int rotation;
- int32_t max_bw_kpbs;
- tsk_bool_t passthrough; // whether to bypass encoding
- } encoder;
-
- // decoder
- struct{
+ void* buffer;
+ int64_t frame_count;
+ tsk_bool_t force_idr;
+ int32_t quality; // [1-31]
+ int rotation;
+ int32_t max_bw_kpbs;
+ tsk_bool_t passthrough; // whether to bypass encoding
+ } encoder;
+
+ // decoder
+ struct {
#if HAVE_FFMPEG
- AVCodec* codec;
- AVCodecContext* context;
- AVFrame* picture;
+ AVCodec* codec;
+ AVCodecContext* context;
+ AVFrame* picture;
#endif
- void* accumulator;
- tsk_size_t accumulator_pos;
- tsk_size_t accumulator_size;
- uint16_t last_seq;
- tsk_bool_t passthrough; // whether to bypass decoding
- } decoder;
+ void* accumulator;
+ tsk_size_t accumulator_pos;
+ tsk_size_t accumulator_size;
+ uint16_t last_seq;
+ tsk_bool_t passthrough; // whether to bypass decoding
+ } decoder;
}
tdav_codec_h264_t;
@@ -105,401 +104,400 @@ static int tdav_codec_h264_close_decoder(tdav_codec_h264_t* self);
static int tdav_codec_h264_set(tmedia_codec_t* self, const tmedia_param_t* param)
{
- tdav_codec_h264_t* h264 = (tdav_codec_h264_t*)self;
- if (param->value_type == tmedia_pvt_int32) {
- if(tsk_striequals(param->key, "action")){
- tmedia_codec_action_t action = (tmedia_codec_action_t)TSK_TO_INT32((uint8_t*)param->value);
- switch(action){
- case tmedia_codec_action_encode_idr:
- {
- h264->encoder.force_idr = tsk_true;
- break;
- }
- case tmedia_codec_action_bw_down:
- {
- h264->encoder.quality = TSK_CLAMP(1, (h264->encoder.quality + 1), 31);
+ tdav_codec_h264_t* h264 = (tdav_codec_h264_t*)self;
+ if (param->value_type == tmedia_pvt_int32) {
+ if(tsk_striequals(param->key, "action")) {
+ tmedia_codec_action_t action = (tmedia_codec_action_t)TSK_TO_INT32((uint8_t*)param->value);
+ switch(action) {
+ case tmedia_codec_action_encode_idr: {
+ h264->encoder.force_idr = tsk_true;
+ break;
+ }
+ case tmedia_codec_action_bw_down: {
+ h264->encoder.quality = TSK_CLAMP(1, (h264->encoder.quality + 1), 31);
#if HAVE_FFMPEG
- if (h264->encoder.context) {
- h264->encoder.context->global_quality = FF_QP2LAMBDA * h264->encoder.quality;
- }
+ if (h264->encoder.context) {
+ h264->encoder.context->global_quality = FF_QP2LAMBDA * h264->encoder.quality;
+ }
#endif
- break;
- }
- case tmedia_codec_action_bw_up:
- {
- h264->encoder.quality = TSK_CLAMP(1, (h264->encoder.quality - 1), 31);
+ break;
+ }
+ case tmedia_codec_action_bw_up: {
+ h264->encoder.quality = TSK_CLAMP(1, (h264->encoder.quality - 1), 31);
#if HAVE_FFMPEG
- if (h264->encoder.context) {
- h264->encoder.context->global_quality = FF_QP2LAMBDA * h264->encoder.quality;
- }
+ if (h264->encoder.context) {
+ h264->encoder.context->global_quality = FF_QP2LAMBDA * h264->encoder.quality;
+ }
#endif
- break;
- }
- }
- return 0;
- }
- else if(tsk_striequals(param->key, "bw_kbps")){
- int32_t max_bw_userdefine = self->bandwidth_max_upload;
- int32_t max_bw_new = *((int32_t*)param->value);
- if (max_bw_userdefine > 0) {
- // do not use more than what the user defined in it's configuration
- h264->encoder.max_bw_kpbs = TSK_MIN(max_bw_new, max_bw_userdefine);
- }
- else {
- h264->encoder.max_bw_kpbs = max_bw_new;
- }
- return 0;
- }
- else if(tsk_striequals(param->key, "bypass-encoding")){
- h264->encoder.passthrough = *((int32_t*)param->value) ? tsk_true : tsk_false;
- TSK_DEBUG_INFO("[H.264] bypass-encoding = %d", h264->encoder.passthrough);
- return 0;
- }
- else if(tsk_striequals(param->key, "bypass-decoding")){
- h264->decoder.passthrough = *((int32_t*)param->value) ? tsk_true : tsk_false;
- TSK_DEBUG_INFO("[H.264] bypass-decoding = %d", h264->decoder.passthrough);
- return 0;
- }
- else if(tsk_striequals(param->key, "rotation")){
- int32_t rotation = *((int32_t*)param->value);
- if(h264->encoder.rotation != rotation){
+ break;
+ }
+ }
+ return 0;
+ }
+ else if(tsk_striequals(param->key, "bw_kbps")) {
+ int32_t max_bw_userdefine = self->bandwidth_max_upload;
+ int32_t max_bw_new = *((int32_t*)param->value);
+ if (max_bw_userdefine > 0) {
+ // do not use more than what the user defined in it's configuration
+ h264->encoder.max_bw_kpbs = TSK_MIN(max_bw_new, max_bw_userdefine);
+ }
+ else {
+ h264->encoder.max_bw_kpbs = max_bw_new;
+ }
+ // dynamic bandwidth change not implemented for x264
+ // please use openh264 or msf264
+ TSK_DEBUG_INFO("Bandwidth change not supported using x264 ...ignoring new bandwidth value");
+ return 0;
+ }
+ else if(tsk_striequals(param->key, "bypass-encoding")) {
+ h264->encoder.passthrough = *((int32_t*)param->value) ? tsk_true : tsk_false;
+ TSK_DEBUG_INFO("[H.264] bypass-encoding = %d", h264->encoder.passthrough);
+ return 0;
+ }
+ else if(tsk_striequals(param->key, "bypass-decoding")) {
+ h264->decoder.passthrough = *((int32_t*)param->value) ? tsk_true : tsk_false;
+ TSK_DEBUG_INFO("[H.264] bypass-decoding = %d", h264->decoder.passthrough);
+ return 0;
+ }
+ else if(tsk_striequals(param->key, "rotation")) {
+ int32_t rotation = *((int32_t*)param->value);
+ if(h264->encoder.rotation != rotation) {
h264->encoder.rotation = rotation;
- if (self->opened) {
- int ret;
+ if (self->opened) {
+ int ret;
if ((ret = tdav_codec_h264_close_encoder(h264, kResetRotationFalse))) {
return ret;
}
- if ((ret = tdav_codec_h264_open_encoder(h264))) {
- return ret;
- }
+ if ((ret = tdav_codec_h264_open_encoder(h264))) {
+ return ret;
+ }
#if 0 // Not working
- if((ret = avcodec_close(h264->encoder.context))){
- TSK_DEBUG_ERROR("Failed to close [%s] codec", TMEDIA_CODEC(h264)->plugin->desc);
- return ret;
- }
- h264->encoder.context->width = (rotation == 90 || rotation == 270) ? TMEDIA_CODEC_VIDEO(h264)->out.height : TMEDIA_CODEC_VIDEO(h264)->out.width;
- h264->encoder.context->height = (rotation == 90 || rotation == 270) ? TMEDIA_CODEC_VIDEO(h264)->out.width : TMEDIA_CODEC_VIDEO(h264)->out.height;
- if((ret = avcodec_open(h264->encoder.context, h264->encoder.codec)) < 0){
- TSK_DEBUG_ERROR("Failed to open [%s] codec", TMEDIA_CODEC(h264)->plugin->desc);
- return ret;
- }
- h264->encoder.force_idr = tsk_true;
+ if((ret = avcodec_close(h264->encoder.context))) {
+ TSK_DEBUG_ERROR("Failed to close [%s] codec", TMEDIA_CODEC(h264)->plugin->desc);
+ return ret;
+ }
+ h264->encoder.context->width = (rotation == 90 || rotation == 270) ? TMEDIA_CODEC_VIDEO(h264)->out.height : TMEDIA_CODEC_VIDEO(h264)->out.width;
+ h264->encoder.context->height = (rotation == 90 || rotation == 270) ? TMEDIA_CODEC_VIDEO(h264)->out.width : TMEDIA_CODEC_VIDEO(h264)->out.height;
+ if((ret = avcodec_open(h264->encoder.context, h264->encoder.codec)) < 0) {
+ TSK_DEBUG_ERROR("Failed to open [%s] codec", TMEDIA_CODEC(h264)->plugin->desc);
+ return ret;
+ }
+ h264->encoder.force_idr = tsk_true;
#endif
- }
- }
- return 0;
- }
- }
- return -1;
+ }
+ }
+ return 0;
+ }
+ }
+ return -1;
}
static int tdav_codec_h264_open(tmedia_codec_t* self)
{
- int ret;
- tdav_codec_h264_t* h264 = (tdav_codec_h264_t*)self;
-
- if(!h264){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- /* the caller (base class) already checked that the codec is not opened */
-
- // Encoder
- if((ret = tdav_codec_h264_open_encoder(h264))){
- return ret;
- }
-
- // Decoder
- if((ret = tdav_codec_h264_open_decoder(h264))){
- return ret;
- }
-
- return 0;
+ int ret;
+ tdav_codec_h264_t* h264 = (tdav_codec_h264_t*)self;
+
+ if(!h264) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ /* the caller (base class) already checked that the codec is not opened */
+
+ // Encoder
+ if((ret = tdav_codec_h264_open_encoder(h264))) {
+ return ret;
+ }
+
+ // Decoder
+ if((ret = tdav_codec_h264_open_decoder(h264))) {
+ return ret;
+ }
+
+ return 0;
}
static int tdav_codec_h264_close(tmedia_codec_t* self)
{
- tdav_codec_h264_t* h264 = (tdav_codec_h264_t*)self;
+ tdav_codec_h264_t* h264 = (tdav_codec_h264_t*)self;
- if(!h264){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
+ if(!h264) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
- /* the caller (base class) alreasy checked that the codec is opened */
+ /* the caller (base class) alreasy checked that the codec is opened */
- // Encoder
- tdav_codec_h264_close_encoder(h264, kResetRotationTrue);
+ // Encoder
+ tdav_codec_h264_close_encoder(h264, kResetRotationTrue);
- // Decoder
- tdav_codec_h264_close_decoder(h264);
+ // Decoder
+ tdav_codec_h264_close_decoder(h264);
- return 0;
+ return 0;
}
static tsk_size_t tdav_codec_h264_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 = 0;
+ int ret = 0;
#if HAVE_FFMPEG
- int size;
- tsk_bool_t send_idr, send_hdr;
+ int size;
+ tsk_bool_t send_idr, send_hdr;
#endif
- tdav_codec_h264_t* h264 = (tdav_codec_h264_t*)self;
+ tdav_codec_h264_t* h264 = (tdav_codec_h264_t*)self;
- if(!self || !in_data || !in_size){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
+ if(!self || !in_data || !in_size) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
- if(!self->opened){
- TSK_DEBUG_ERROR("Codec not opened");
- return 0;
- }
+ if(!self->opened) {
+ TSK_DEBUG_ERROR("Codec not opened");
+ return 0;
+ }
- if(h264->encoder.passthrough) {
- tdav_codec_h264_rtp_encap(TDAV_CODEC_H264_COMMON(h264), (const uint8_t*)in_data, in_size);
- }
- else { // !h264->encoder.passthrough
+ if(h264->encoder.passthrough) {
+ tdav_codec_h264_rtp_encap(TDAV_CODEC_H264_COMMON(h264), (const uint8_t*)in_data, in_size);
+ }
+ else { // !h264->encoder.passthrough
#if HAVE_FFMPEG // wrap yuv420 buffer
- size = avpicture_fill((AVPicture *)h264->encoder.picture, (uint8_t*)in_data, PIX_FMT_YUV420P, h264->encoder.context->width, h264->encoder.context->height);
- if (size != in_size){
- /* guard */
- TSK_DEBUG_ERROR("Invalid size: %u<>%u", size, in_size);
- return 0;
- }
-
- // send IDR for:
- // - the first frame
- // - remote peer requested an IDR
- // - every second within the first 4seconds
- send_idr = (
- h264->encoder.frame_count++ == 0
- || h264 ->encoder.force_idr
- //|| ( (h264->encoder.frame_count < (int)TMEDIA_CODEC_VIDEO(h264)->out.fps * 4) && ((h264->encoder.frame_count % TMEDIA_CODEC_VIDEO(h264)->out.fps)==0) )
- );
-
- // send SPS and PPS headers for:
- // - IDR frames (not required but it's the easiest way to deal with pkt loss)
- // - every 5 seconds after the first 4seconds
- send_hdr = (
- send_idr
- //|| ( (h264->encoder.frame_count % (TMEDIA_CODEC_VIDEO(h264)->out.fps * 5))==0 )
- );
- if(send_hdr){
- tdav_codec_h264_rtp_encap(TDAV_CODEC_H264_COMMON(h264), h264->encoder.context->extradata, (tsk_size_t)h264->encoder.context->extradata_size);
- }
-
- // Encode data
- #if LIBAVCODEC_VERSION_MAJOR <= 53
- h264->encoder.picture->pict_type = send_idr ? FF_I_TYPE : 0;
- #else
- h264->encoder.picture->pict_type = send_idr ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_NONE;
- #endif
- h264->encoder.picture->key_frame = send_idr ? 1 : 0;
- h264->encoder.picture->pts = AV_NOPTS_VALUE;
- h264->encoder.picture->quality = h264->encoder.context->global_quality;
- // h264->encoder.picture->pts = h264->encoder.frame_count; MUST NOT
- ret = avcodec_encode_video(h264->encoder.context, h264->encoder.buffer, size, h264->encoder.picture);
- if(ret > 0){
- tdav_codec_h264_rtp_encap(TDAV_CODEC_H264_COMMON(h264), h264->encoder.buffer, (tsk_size_t)ret);
- }
- h264 ->encoder.force_idr = tsk_false;
+ size = avpicture_fill((AVPicture *)h264->encoder.picture, (uint8_t*)in_data, PIX_FMT_YUV420P, h264->encoder.context->width, h264->encoder.context->height);
+ if (size != in_size) {
+ /* guard */
+ TSK_DEBUG_ERROR("Invalid size: %u<>%u", size, in_size);
+ return 0;
+ }
+
+ // send IDR for:
+ // - the first frame
+ // - remote peer requested an IDR
+ // - every second within the first 4seconds
+ send_idr = (
+ h264->encoder.frame_count++ == 0
+ || h264 ->encoder.force_idr
+ //|| ( (h264->encoder.frame_count < (int)TMEDIA_CODEC_VIDEO(h264)->out.fps * 4) && ((h264->encoder.frame_count % TMEDIA_CODEC_VIDEO(h264)->out.fps)==0) )
+ );
+
+ // send SPS and PPS headers for:
+ // - IDR frames (not required but it's the easiest way to deal with pkt loss)
+ // - every 5 seconds after the first 4seconds
+ send_hdr = (
+ send_idr
+ //|| ( (h264->encoder.frame_count % (TMEDIA_CODEC_VIDEO(h264)->out.fps * 5))==0 )
+ );
+ if(send_hdr) {
+ tdav_codec_h264_rtp_encap(TDAV_CODEC_H264_COMMON(h264), h264->encoder.context->extradata, (tsk_size_t)h264->encoder.context->extradata_size);
+ }
+
+ // Encode data
+#if LIBAVCODEC_VERSION_MAJOR <= 53
+ h264->encoder.picture->pict_type = send_idr ? FF_I_TYPE : 0;
+#else
+ h264->encoder.picture->pict_type = send_idr ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_NONE;
+#endif
+ h264->encoder.picture->key_frame = send_idr ? 1 : 0;
+ h264->encoder.picture->pts = AV_NOPTS_VALUE;
+ h264->encoder.picture->quality = h264->encoder.context->global_quality;
+ // h264->encoder.picture->pts = h264->encoder.frame_count; MUST NOT
+ ret = avcodec_encode_video(h264->encoder.context, h264->encoder.buffer, size, h264->encoder.picture);
+ if(ret > 0) {
+ tdav_codec_h264_rtp_encap(TDAV_CODEC_H264_COMMON(h264), h264->encoder.buffer, (tsk_size_t)ret);
+ }
+ h264 ->encoder.force_idr = tsk_false;
#endif
- }// else(!h264->encoder.passthrough)
+ }// else(!h264->encoder.passthrough)
- return 0;
+ return 0;
}
static tsk_size_t tdav_codec_h264_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)
{
- tdav_codec_h264_t* h264 = (tdav_codec_h264_t*)self;
- const trtp_rtp_header_t* rtp_hdr = (const trtp_rtp_header_t*)proto_hdr;
-
- const uint8_t* pay_ptr = tsk_null;
- tsk_size_t pay_size = 0;
- int ret;
- tsk_bool_t sps_or_pps, append_scp, end_of_unit;
- tsk_size_t retsize = 0, size_to_copy = 0;
- static const tsk_size_t xmax_size = (3840 * 2160 * 3) >> 3; // >>3 instead of >>1 (not an error)
- static tsk_size_t start_code_prefix_size = sizeof(H264_START_CODE_PREFIX);
+ tdav_codec_h264_t* h264 = (tdav_codec_h264_t*)self;
+ const trtp_rtp_header_t* rtp_hdr = (const trtp_rtp_header_t*)proto_hdr;
+
+ const uint8_t* pay_ptr = tsk_null;
+ tsk_size_t pay_size = 0;
+ int ret;
+ tsk_bool_t sps_or_pps, append_scp, end_of_unit;
+ tsk_size_t retsize = 0, size_to_copy = 0;
+ static const tsk_size_t xmax_size = (3840 * 2160 * 3) >> 3; // >>3 instead of >>1 (not an error)
+ static tsk_size_t start_code_prefix_size = sizeof(H264_START_CODE_PREFIX);
#if HAVE_FFMPEG
- int got_picture_ptr = 0;
+ int got_picture_ptr = 0;
#endif
- if(!h264 || !in_data || !in_size || !out_data
+ if(!h264 || !in_data || !in_size || !out_data
#if HAVE_FFMPEG
- || !h264->decoder.context
+ || !h264->decoder.context
#endif
- )
- {
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- //TSK_DEBUG_INFO("SeqNo=%hu", rtp_hdr->seq_num);
-
- /* Packet lost? */
- if((h264->decoder.last_seq + 1) != rtp_hdr->seq_num && h264->decoder.last_seq){
- TSK_DEBUG_INFO("[H.264] Packet loss, seq_num=%d", (h264->decoder.last_seq + 1));
- }
- h264->decoder.last_seq = rtp_hdr->seq_num;
-
-
- /* 5.3. NAL Unit Octet Usage
- +---------------+
+ ) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ //TSK_DEBUG_INFO("SeqNo=%hu", rtp_hdr->seq_num);
+
+ /* Packet lost? */
+ if((h264->decoder.last_seq + 1) != rtp_hdr->seq_num && h264->decoder.last_seq) {
+ TSK_DEBUG_INFO("[H.264] Packet loss, seq_num=%d", (h264->decoder.last_seq + 1));
+ }
+ h264->decoder.last_seq = rtp_hdr->seq_num;
+
+
+ /* 5.3. NAL Unit Octet Usage
+ +---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|F|NRI| Type |
+---------------+
- */
- if(*((uint8_t*)in_data) & 0x80){
- TSK_DEBUG_WARN("F=1");
- /* reset accumulator */
- h264->decoder.accumulator_pos = 0;
- return 0;
- }
-
- /* get payload */
- if((ret = tdav_codec_h264_get_pay(in_data, in_size, (const void**)&pay_ptr, &pay_size, &append_scp, &end_of_unit)) || !pay_ptr || !pay_size){
- TSK_DEBUG_ERROR("Depayloader failed to get H.264 content");
- return 0;
- }
- //append_scp = tsk_true;
- size_to_copy = pay_size + (append_scp ? start_code_prefix_size : 0);
- // whether it's SPS or PPS (append_scp is false for subsequent FUA chuncks)
- sps_or_pps = append_scp && pay_ptr && ((pay_ptr[0] & 0x1F) == 7 || (pay_ptr[0] & 0x1F) == 8);
-
- // start-accumulator
- if(!h264->decoder.accumulator){
- if(size_to_copy > xmax_size){
- TSK_DEBUG_ERROR("%u too big to contain valid encoded data. xmax_size=%u", size_to_copy, xmax_size);
- return 0;
- }
- if(!(h264->decoder.accumulator = tsk_calloc(size_to_copy, sizeof(uint8_t)))){
- TSK_DEBUG_ERROR("Failed to allocated new buffer");
- return 0;
- }
- h264->decoder.accumulator_size = size_to_copy;
- }
- if((h264->decoder.accumulator_pos + size_to_copy) >= xmax_size){
- TSK_DEBUG_ERROR("BufferOverflow");
- h264->decoder.accumulator_pos = 0;
- return 0;
- }
- if((h264->decoder.accumulator_pos + size_to_copy) > h264->decoder.accumulator_size){
- if(!(h264->decoder.accumulator = tsk_realloc(h264->decoder.accumulator, (h264->decoder.accumulator_pos + size_to_copy)))){
- TSK_DEBUG_ERROR("Failed to reallocated new buffer");
- h264->decoder.accumulator_pos = 0;
- h264->decoder.accumulator_size = 0;
- return 0;
- }
- h264->decoder.accumulator_size = (h264->decoder.accumulator_pos + size_to_copy);
- }
-
- if(append_scp){
- memcpy(&((uint8_t*)h264->decoder.accumulator)[h264->decoder.accumulator_pos], H264_START_CODE_PREFIX, start_code_prefix_size);
- h264->decoder.accumulator_pos += start_code_prefix_size;
- }
- memcpy(&((uint8_t*)h264->decoder.accumulator)[h264->decoder.accumulator_pos], pay_ptr, pay_size);
- h264->decoder.accumulator_pos += pay_size;
- // end-accumulator
-
- if(sps_or_pps){
- // http://libav-users.943685.n4.nabble.com/Decode-H264-streams-how-to-fill-AVCodecContext-from-SPS-PPS-td2484472.html
- // SPS and PPS should be bundled with IDR
- TSK_DEBUG_INFO("Receiving SPS or PPS ...to be tied to an IDR");
- }
- else if(rtp_hdr->marker){
- if(h264->decoder.passthrough){
- if(*out_max_size < h264->decoder.accumulator_pos){
- if((*out_data = tsk_realloc(*out_data, h264->decoder.accumulator_pos))){
- *out_max_size = h264->decoder.accumulator_pos;
- }
- else{
- *out_max_size = 0;
- return 0;
- }
- }
- memcpy(*out_data, h264->decoder.accumulator, h264->decoder.accumulator_pos);
- retsize = h264->decoder.accumulator_pos;
- }
- else { // !h264->decoder.passthrough
+ */
+ if(*((uint8_t*)in_data) & 0x80) {
+ TSK_DEBUG_WARN("F=1");
+ /* reset accumulator */
+ h264->decoder.accumulator_pos = 0;
+ return 0;
+ }
+
+ /* get payload */
+ if((ret = tdav_codec_h264_get_pay(in_data, in_size, (const void**)&pay_ptr, &pay_size, &append_scp, &end_of_unit)) || !pay_ptr || !pay_size) {
+ TSK_DEBUG_ERROR("Depayloader failed to get H.264 content");
+ return 0;
+ }
+ //append_scp = tsk_true;
+ size_to_copy = pay_size + (append_scp ? start_code_prefix_size : 0);
+ // whether it's SPS or PPS (append_scp is false for subsequent FUA chuncks)
+ sps_or_pps = append_scp && pay_ptr && ((pay_ptr[0] & 0x1F) == 7 || (pay_ptr[0] & 0x1F) == 8);
+
+ // start-accumulator
+ if(!h264->decoder.accumulator) {
+ if(size_to_copy > xmax_size) {
+ TSK_DEBUG_ERROR("%u too big to contain valid encoded data. xmax_size=%u", size_to_copy, xmax_size);
+ return 0;
+ }
+ if(!(h264->decoder.accumulator = tsk_calloc(size_to_copy, sizeof(uint8_t)))) {
+ TSK_DEBUG_ERROR("Failed to allocated new buffer");
+ return 0;
+ }
+ h264->decoder.accumulator_size = size_to_copy;
+ }
+ if((h264->decoder.accumulator_pos + size_to_copy) >= xmax_size) {
+ TSK_DEBUG_ERROR("BufferOverflow");
+ h264->decoder.accumulator_pos = 0;
+ return 0;
+ }
+ if((h264->decoder.accumulator_pos + size_to_copy) > h264->decoder.accumulator_size) {
+ if(!(h264->decoder.accumulator = tsk_realloc(h264->decoder.accumulator, (h264->decoder.accumulator_pos + size_to_copy)))) {
+ TSK_DEBUG_ERROR("Failed to reallocated new buffer");
+ h264->decoder.accumulator_pos = 0;
+ h264->decoder.accumulator_size = 0;
+ return 0;
+ }
+ h264->decoder.accumulator_size = (h264->decoder.accumulator_pos + size_to_copy);
+ }
+
+ if(append_scp) {
+ memcpy(&((uint8_t*)h264->decoder.accumulator)[h264->decoder.accumulator_pos], H264_START_CODE_PREFIX, start_code_prefix_size);
+ h264->decoder.accumulator_pos += start_code_prefix_size;
+ }
+ memcpy(&((uint8_t*)h264->decoder.accumulator)[h264->decoder.accumulator_pos], pay_ptr, pay_size);
+ h264->decoder.accumulator_pos += pay_size;
+ // end-accumulator
+
+ if(sps_or_pps) {
+ // http://libav-users.943685.n4.nabble.com/Decode-H264-streams-how-to-fill-AVCodecContext-from-SPS-PPS-td2484472.html
+ // SPS and PPS should be bundled with IDR
+ TSK_DEBUG_INFO("Receiving SPS or PPS ...to be tied to an IDR");
+ }
+ else if(rtp_hdr->marker) {
+ if(h264->decoder.passthrough) {
+ if(*out_max_size < h264->decoder.accumulator_pos) {
+ if((*out_data = tsk_realloc(*out_data, h264->decoder.accumulator_pos))) {
+ *out_max_size = h264->decoder.accumulator_pos;
+ }
+ else {
+ *out_max_size = 0;
+ return 0;
+ }
+ }
+ memcpy(*out_data, h264->decoder.accumulator, h264->decoder.accumulator_pos);
+ retsize = h264->decoder.accumulator_pos;
+ }
+ else { // !h264->decoder.passthrough
#if HAVE_FFMPEG
- AVPacket packet;
-
- /* decode the picture */
- av_init_packet(&packet);
- packet.dts = packet.pts = AV_NOPTS_VALUE;
- packet.size = (int)h264->decoder.accumulator_pos;
- packet.data = h264->decoder.accumulator;
- ret = avcodec_decode_video2(h264->decoder.context, h264->decoder.picture, &got_picture_ptr, &packet);
-
- if(ret <0){
- TSK_DEBUG_INFO("Failed to decode the buffer with error code =%d, size=%u, append=%s", ret, h264->decoder.accumulator_pos, append_scp ? "yes" : "no");
- if(TMEDIA_CODEC_VIDEO(self)->in.callback){
- TMEDIA_CODEC_VIDEO(self)->in.result.type = tmedia_video_decode_result_type_error;
- TMEDIA_CODEC_VIDEO(self)->in.result.proto_hdr = proto_hdr;
- TMEDIA_CODEC_VIDEO(self)->in.callback(&TMEDIA_CODEC_VIDEO(self)->in.result);
- }
- }
- else if(got_picture_ptr){
- tsk_size_t xsize;
-
- /* IDR ? */
- if(((pay_ptr[0] & 0x1F) == 0x05) && TMEDIA_CODEC_VIDEO(self)->in.callback){
- TSK_DEBUG_INFO("Decoded H.264 IDR");
- TMEDIA_CODEC_VIDEO(self)->in.result.type = tmedia_video_decode_result_type_idr;
- TMEDIA_CODEC_VIDEO(self)->in.result.proto_hdr = proto_hdr;
- TMEDIA_CODEC_VIDEO(self)->in.callback(&TMEDIA_CODEC_VIDEO(self)->in.result);
- }
- /* fill out */
- xsize = avpicture_get_size(h264->decoder.context->pix_fmt, h264->decoder.context->width, h264->decoder.context->height);
- if(*out_max_size<xsize){
- if((*out_data = tsk_realloc(*out_data, (xsize + FF_INPUT_BUFFER_PADDING_SIZE)))){
- *out_max_size = xsize;
- }
- else{
- *out_max_size = 0;
- return 0;
- }
- }
- retsize = xsize;
- TMEDIA_CODEC_VIDEO(h264)->in.width = h264->decoder.context->width;
- TMEDIA_CODEC_VIDEO(h264)->in.height = h264->decoder.context->height;
- avpicture_layout((AVPicture *)h264->decoder.picture, h264->decoder.context->pix_fmt, (int)h264->decoder.context->width, (int)h264->decoder.context->height,
- *out_data, (int)retsize);
- }
+ AVPacket packet;
+
+ /* decode the picture */
+ av_init_packet(&packet);
+ packet.dts = packet.pts = AV_NOPTS_VALUE;
+ packet.size = (int)h264->decoder.accumulator_pos;
+ packet.data = h264->decoder.accumulator;
+ ret = avcodec_decode_video2(h264->decoder.context, h264->decoder.picture, &got_picture_ptr, &packet);
+
+ if(ret <0) {
+ TSK_DEBUG_INFO("Failed to decode the buffer with error code =%d, size=%u, append=%s", ret, h264->decoder.accumulator_pos, append_scp ? "yes" : "no");
+ if(TMEDIA_CODEC_VIDEO(self)->in.callback) {
+ TMEDIA_CODEC_VIDEO(self)->in.result.type = tmedia_video_decode_result_type_error;
+ TMEDIA_CODEC_VIDEO(self)->in.result.proto_hdr = proto_hdr;
+ TMEDIA_CODEC_VIDEO(self)->in.callback(&TMEDIA_CODEC_VIDEO(self)->in.result);
+ }
+ }
+ else if(got_picture_ptr) {
+ tsk_size_t xsize;
+
+ /* IDR ? */
+ if(((pay_ptr[0] & 0x1F) == 0x05) && TMEDIA_CODEC_VIDEO(self)->in.callback) {
+ TSK_DEBUG_INFO("Decoded H.264 IDR");
+ TMEDIA_CODEC_VIDEO(self)->in.result.type = tmedia_video_decode_result_type_idr;
+ TMEDIA_CODEC_VIDEO(self)->in.result.proto_hdr = proto_hdr;
+ TMEDIA_CODEC_VIDEO(self)->in.callback(&TMEDIA_CODEC_VIDEO(self)->in.result);
+ }
+ /* fill out */
+ xsize = avpicture_get_size(h264->decoder.context->pix_fmt, h264->decoder.context->width, h264->decoder.context->height);
+ if(*out_max_size<xsize) {
+ if((*out_data = tsk_realloc(*out_data, (xsize + FF_INPUT_BUFFER_PADDING_SIZE)))) {
+ *out_max_size = xsize;
+ }
+ else {
+ *out_max_size = 0;
+ return 0;
+ }
+ }
+ retsize = xsize;
+ TMEDIA_CODEC_VIDEO(h264)->in.width = h264->decoder.context->width;
+ TMEDIA_CODEC_VIDEO(h264)->in.height = h264->decoder.context->height;
+ avpicture_layout((AVPicture *)h264->decoder.picture, h264->decoder.context->pix_fmt, (int)h264->decoder.context->width, (int)h264->decoder.context->height,
+ *out_data, (int)retsize);
+ }
#endif /* HAVE_FFMPEG */
- } // else(h264->decoder.passthrough)
+ } // else(h264->decoder.passthrough)
- h264->decoder.accumulator_pos = 0;
- } // else if(rtp_hdr->marker)
+ h264->decoder.accumulator_pos = 0;
+ } // else if(rtp_hdr->marker)
- return retsize;
+ return retsize;
}
static tsk_bool_t tdav_codec_h264_sdp_att_match(const tmedia_codec_t* self, const char* att_name, const char* att_value)
{
- return tdav_codec_h264_common_sdp_att_match((tdav_codec_h264_common_t*)self, att_name, att_value);
+ return tdav_codec_h264_common_sdp_att_match((tdav_codec_h264_common_t*)self, att_name, att_value);
}
static char* tdav_codec_h264_sdp_att_get(const tmedia_codec_t* self, const char* att_name)
{
- char* att = tdav_codec_h264_common_sdp_att_get((const tdav_codec_h264_common_t*)self, att_name);
- if(att && tsk_striequals(att_name, "fmtp")) {
- tsk_strcat_2(&att, "; impl=%s",
+ char* att = tdav_codec_h264_common_sdp_att_get((const tdav_codec_h264_common_t*)self, att_name);
+ if(att && tsk_striequals(att_name, "fmtp")) {
+ tsk_strcat_2(&att, "; impl=%s",
#if HAVE_FFMPEG
- "FFMPEG"
+ "FFMPEG"
#elif HAVE_H264_PASSTHROUGH
- "PASSTHROUGH"
+ "PASSTHROUGH"
#endif
- );
- }
- return att;
+ );
+ }
+ return att;
}
@@ -510,64 +508,62 @@ static char* tdav_codec_h264_sdp_att_get(const tmedia_codec_t* self, const char*
/* constructor */
static tsk_object_t* tdav_codec_h264_base_ctor(tsk_object_t * self, va_list * app)
{
- tdav_codec_h264_t *h264 = (tdav_codec_h264_t*)self;
- if(h264){
- /* init base: called by tmedia_codec_create() */
- /* init self */
- if(tdav_codec_h264_init(h264, profile_idc_baseline) != 0){
- return tsk_null;
- }
- }
- return self;
+ tdav_codec_h264_t *h264 = (tdav_codec_h264_t*)self;
+ if(h264) {
+ /* init base: called by tmedia_codec_create() */
+ /* init self */
+ if(tdav_codec_h264_init(h264, profile_idc_baseline) != 0) {
+ return tsk_null;
+ }
+ }
+ return self;
}
/* destructor */
static tsk_object_t* tdav_codec_h264_base_dtor(tsk_object_t * self)
-{
- tdav_codec_h264_t *h264 = (tdav_codec_h264_t*)self;
- if(h264){
- /* deinit base */
- tdav_codec_h264_common_deinit((tdav_codec_h264_common_t*)self);
- /* deinit self */
- tdav_codec_h264_deinit(h264);
-
- }
-
- return self;
+{
+ tdav_codec_h264_t *h264 = (tdav_codec_h264_t*)self;
+ if(h264) {
+ /* deinit base */
+ tdav_codec_h264_common_deinit((tdav_codec_h264_common_t*)self);
+ /* deinit self */
+ tdav_codec_h264_deinit(h264);
+
+ }
+
+ return self;
}
/* object definition */
-static const tsk_object_def_t tdav_codec_h264_base_def_s =
-{
- sizeof(tdav_codec_h264_t),
- tdav_codec_h264_base_ctor,
- tdav_codec_h264_base_dtor,
- tmedia_codec_cmp,
+static const tsk_object_def_t tdav_codec_h264_base_def_s = {
+ sizeof(tdav_codec_h264_t),
+ tdav_codec_h264_base_ctor,
+ tdav_codec_h264_base_dtor,
+ tmedia_codec_cmp,
};
/* plugin definition*/
-static const tmedia_codec_plugin_def_t tdav_codec_h264_base_plugin_def_s =
-{
- &tdav_codec_h264_base_def_s,
-
- tmedia_video,
- tmedia_codec_id_h264_bp,
- "H264",
- "H264 Base Profile (FFmpeg, x264)",
- TMEDIA_CODEC_FORMAT_H264_BP,
- tsk_true,
- 90000, // rate
-
- /* audio */
- { 0 },
-
- /* video (width, height, fps) */
- {176, 144, 0}, // fps is @deprecated
-
- tdav_codec_h264_set,
- tdav_codec_h264_open,
- tdav_codec_h264_close,
- tdav_codec_h264_encode,
- tdav_codec_h264_decode,
- tdav_codec_h264_sdp_att_match,
- tdav_codec_h264_sdp_att_get
+static const tmedia_codec_plugin_def_t tdav_codec_h264_base_plugin_def_s = {
+ &tdav_codec_h264_base_def_s,
+
+ tmedia_video,
+ tmedia_codec_id_h264_bp,
+ "H264",
+ "H264 Base Profile (FFmpeg, x264)",
+ TMEDIA_CODEC_FORMAT_H264_BP,
+ tsk_true,
+ 90000, // rate
+
+ /* audio */
+ { 0 },
+
+ /* video (width, height, fps) */
+ {176, 144, 0}, // fps is @deprecated
+
+ tdav_codec_h264_set,
+ tdav_codec_h264_open,
+ tdav_codec_h264_close,
+ tdav_codec_h264_encode,
+ tdav_codec_h264_decode,
+ tdav_codec_h264_sdp_att_match,
+ tdav_codec_h264_sdp_att_get
};
const tmedia_codec_plugin_def_t *tdav_codec_h264_base_plugin_def_t = &tdav_codec_h264_base_plugin_def_s;
@@ -576,64 +572,62 @@ const tmedia_codec_plugin_def_t *tdav_codec_h264_base_plugin_def_t = &tdav_codec
/* constructor */
static tsk_object_t* tdav_codec_h264_main_ctor(tsk_object_t * self, va_list * app)
{
- tdav_codec_h264_t *h264 = (tdav_codec_h264_t*)self;
- if(h264){
- /* init base: called by tmedia_codec_create() */
- /* init self */
- if(tdav_codec_h264_init(h264, profile_idc_main) != 0){
- return tsk_null;
- }
- }
- return self;
+ tdav_codec_h264_t *h264 = (tdav_codec_h264_t*)self;
+ if(h264) {
+ /* init base: called by tmedia_codec_create() */
+ /* init self */
+ if(tdav_codec_h264_init(h264, profile_idc_main) != 0) {
+ return tsk_null;
+ }
+ }
+ return self;
}
/* destructor */
static tsk_object_t* tdav_codec_h264_main_dtor(tsk_object_t * self)
-{
- tdav_codec_h264_t *h264 = (tdav_codec_h264_t*)self;
- if(h264){
- /* deinit base */
- tdav_codec_h264_common_deinit((tdav_codec_h264_common_t*)self);
- /* deinit self */
- tdav_codec_h264_deinit(h264);
-
- }
-
- return self;
+{
+ tdav_codec_h264_t *h264 = (tdav_codec_h264_t*)self;
+ if(h264) {
+ /* deinit base */
+ tdav_codec_h264_common_deinit((tdav_codec_h264_common_t*)self);
+ /* deinit self */
+ tdav_codec_h264_deinit(h264);
+
+ }
+
+ return self;
}
/* object definition */
-static const tsk_object_def_t tdav_codec_h264_main_def_s =
-{
- sizeof(tdav_codec_h264_t),
- tdav_codec_h264_main_ctor,
- tdav_codec_h264_main_dtor,
- tmedia_codec_cmp,
+static const tsk_object_def_t tdav_codec_h264_main_def_s = {
+ sizeof(tdav_codec_h264_t),
+ tdav_codec_h264_main_ctor,
+ tdav_codec_h264_main_dtor,
+ tmedia_codec_cmp,
};
/* plugin definition*/
-static const tmedia_codec_plugin_def_t tdav_codec_h264_main_plugin_def_s =
-{
- &tdav_codec_h264_main_def_s,
-
- tmedia_video,
- tmedia_codec_id_h264_mp,
- "H264",
- "H264 Main Profile (FFmpeg, x264)",
- TMEDIA_CODEC_FORMAT_H264_MP,
- tsk_true,
- 90000, // rate
-
- /* audio */
- { 0 },
-
- /* video (width, height, fps)*/
- {176, 144, 0},// fps is @deprecated
-
- tdav_codec_h264_set,
- tdav_codec_h264_open,
- tdav_codec_h264_close,
- tdav_codec_h264_encode,
- tdav_codec_h264_decode,
- tdav_codec_h264_sdp_att_match,
- tdav_codec_h264_sdp_att_get
+static const tmedia_codec_plugin_def_t tdav_codec_h264_main_plugin_def_s = {
+ &tdav_codec_h264_main_def_s,
+
+ tmedia_video,
+ tmedia_codec_id_h264_mp,
+ "H264",
+ "H264 Main Profile (FFmpeg, x264)",
+ TMEDIA_CODEC_FORMAT_H264_MP,
+ tsk_true,
+ 90000, // rate
+
+ /* audio */
+ { 0 },
+
+ /* video (width, height, fps)*/
+ {176, 144, 0},// fps is @deprecated
+
+ tdav_codec_h264_set,
+ tdav_codec_h264_open,
+ tdav_codec_h264_close,
+ tdav_codec_h264_encode,
+ tdav_codec_h264_decode,
+ tdav_codec_h264_sdp_att_match,
+ tdav_codec_h264_sdp_att_get
};
const tmedia_codec_plugin_def_t *tdav_codec_h264_main_plugin_def_t = &tdav_codec_h264_main_plugin_def_s;
@@ -678,315 +672,315 @@ const tmedia_codec_plugin_def_t *tdav_codec_h264_main_plugin_def_t = &tdav_codec
int tdav_codec_h264_open_encoder(tdav_codec_h264_t* self)
{
#if HAVE_FFMPEG
- int ret;
- tsk_size_t size;
-
- if(self->encoder.context){
- TSK_DEBUG_ERROR("Encoder already opened");
- return -1;
- }
-
+ int ret;
+ tsk_size_t size;
+
+ if(self->encoder.context) {
+ TSK_DEBUG_ERROR("Encoder already opened");
+ return -1;
+ }
+
#if (LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51, 35, 0))
- if((self->encoder.context = avcodec_alloc_context3(self->encoder.codec))){
+ if((self->encoder.context = avcodec_alloc_context3(self->encoder.codec))) {
avcodec_get_context_defaults3(self->encoder.context, self->encoder.codec);
}
#else
- if((self->encoder.context = avcodec_alloc_context())){
+ if((self->encoder.context = avcodec_alloc_context())) {
avcodec_get_context_defaults(self->encoder.context);
}
#endif
-
- if(!self->encoder.context){
+
+ if(!self->encoder.context) {
TSK_DEBUG_ERROR("Failed to allocate context");
- return -1;
+ return -1;
}
#if TDAV_UNDER_X86 && LIBAVCODEC_VERSION_MAJOR <= 53
- self->encoder.context->dsp_mask = (FF_MM_MMX | FF_MM_MMXEXT | FF_MM_SSE);
+ self->encoder.context->dsp_mask = (FF_MM_MMX | FF_MM_MMXEXT | FF_MM_SSE);
#endif
- self->encoder.context->pix_fmt = PIX_FMT_YUV420P;
- self->encoder.context->time_base.num = 1;
- self->encoder.context->time_base.den = TMEDIA_CODEC_VIDEO(self)->out.fps;
- self->encoder.context->width = (self->encoder.rotation == 90 || self->encoder.rotation == 270) ? TMEDIA_CODEC_VIDEO(self)->out.height : TMEDIA_CODEC_VIDEO(self)->out.width;
- self->encoder.context->height = (self->encoder.rotation == 90 || self->encoder.rotation == 270) ? TMEDIA_CODEC_VIDEO(self)->out.width : TMEDIA_CODEC_VIDEO(self)->out.height;
- self->encoder.max_bw_kpbs = TSK_CLAMP(
- 0,
- tmedia_get_video_bandwidth_kbps_2(TMEDIA_CODEC_VIDEO(self)->out.width, TMEDIA_CODEC_VIDEO(self)->out.height, TMEDIA_CODEC_VIDEO(self)->out.fps),
- TMEDIA_CODEC(self)->bandwidth_max_upload
- );
- self->encoder.context->bit_rate = (self->encoder.max_bw_kpbs * 1024);// bps
-
- self->encoder.context->rc_min_rate = (self->encoder.context->bit_rate >> 3);
- self->encoder.context->rc_max_rate = self->encoder.context->bit_rate;
+ self->encoder.context->pix_fmt = PIX_FMT_YUV420P;
+ self->encoder.context->time_base.num = 1;
+ self->encoder.context->time_base.den = TMEDIA_CODEC_VIDEO(self)->out.fps;
+ self->encoder.context->width = (self->encoder.rotation == 90 || self->encoder.rotation == 270) ? TMEDIA_CODEC_VIDEO(self)->out.height : TMEDIA_CODEC_VIDEO(self)->out.width;
+ self->encoder.context->height = (self->encoder.rotation == 90 || self->encoder.rotation == 270) ? TMEDIA_CODEC_VIDEO(self)->out.width : TMEDIA_CODEC_VIDEO(self)->out.height;
+ self->encoder.max_bw_kpbs = TSK_CLAMP(
+ 0,
+ tmedia_get_video_bandwidth_kbps_2(TMEDIA_CODEC_VIDEO(self)->out.width, TMEDIA_CODEC_VIDEO(self)->out.height, TMEDIA_CODEC_VIDEO(self)->out.fps),
+ TMEDIA_CODEC(self)->bandwidth_max_upload
+ );
+ self->encoder.context->bit_rate = (self->encoder.max_bw_kpbs * 1024);// bps
+
+ self->encoder.context->rc_min_rate = (self->encoder.context->bit_rate >> 3);
+ self->encoder.context->rc_max_rate = self->encoder.context->bit_rate;
#if LIBAVCODEC_VERSION_MAJOR <= 53
- self->encoder.context->rc_lookahead = 0;
+ self->encoder.context->rc_lookahead = 0;
#endif
- self->encoder.context->global_quality = FF_QP2LAMBDA * self->encoder.quality;
-
+ self->encoder.context->global_quality = FF_QP2LAMBDA * self->encoder.quality;
+
#if LIBAVCODEC_VERSION_MAJOR <= 53
self->encoder.context->partitions = X264_PART_I4X4 | X264_PART_I8X8 | X264_PART_P8X8 | X264_PART_B8X8;
#endif
self->encoder.context->me_method = ME_UMH;
- self->encoder.context->me_range = 16;
- self->encoder.context->qmin = 10;
- self->encoder.context->qmax = 51;
+ self->encoder.context->me_range = 16;
+ self->encoder.context->qmin = 10;
+ self->encoder.context->qmax = 51;
#if LIBAVCODEC_VERSION_MAJOR <= 53
self->encoder.context->mb_qmin = self->encoder.context->qmin;
- self->encoder.context->mb_qmax = self->encoder.context->qmax;
+ self->encoder.context->mb_qmax = self->encoder.context->qmax;
#endif
- /* METROPOLIS = G2J.COM TelePresence client. Check Issue 378: No video when calling "TANDBERG/4129 (X8.1.1)" */
+ /* METROPOLIS = G2J.COM TelePresence client. Check Issue 378: No video when calling "TANDBERG/4129 (X8.1.1)" */
#if !METROPOLIS && 0
- self->encoder.context->flags |= CODEC_FLAG_GLOBAL_HEADER;
+ self->encoder.context->flags |= CODEC_FLAG_GLOBAL_HEADER;
#endif
self->encoder.context->flags |= CODEC_FLAG_LOW_DELAY;
- if (self->encoder.context->profile == FF_PROFILE_H264_BASELINE) {
- self->encoder.context->max_b_frames = 0;
- }
-
- switch(TDAV_CODEC_H264_COMMON(self)->profile){
- case profile_idc_baseline:
- default:
- self->encoder.context->profile = FF_PROFILE_H264_BASELINE;
- self->encoder.context->level = TDAV_CODEC_H264_COMMON(self)->level;
- break;
- case profile_idc_main:
- self->encoder.context->profile = FF_PROFILE_H264_MAIN;
- self->encoder.context->level = TDAV_CODEC_H264_COMMON(self)->level;
- break;
- }
-
- /* Comment from libavcodec/libx264.c:
+ if (self->encoder.context->profile == FF_PROFILE_H264_BASELINE) {
+ self->encoder.context->max_b_frames = 0;
+ }
+
+ switch(TDAV_CODEC_H264_COMMON(self)->profile) {
+ case profile_idc_baseline:
+ default:
+ self->encoder.context->profile = FF_PROFILE_H264_BASELINE;
+ self->encoder.context->level = TDAV_CODEC_H264_COMMON(self)->level;
+ break;
+ case profile_idc_main:
+ self->encoder.context->profile = FF_PROFILE_H264_MAIN;
+ self->encoder.context->level = TDAV_CODEC_H264_COMMON(self)->level;
+ break;
+ }
+
+ /* Comment from libavcodec/libx264.c:
* Allow x264 to be instructed through AVCodecContext about the maximum
* size of the RTP payload. For example, this enables the production of
* payload suitable for the H.264 RTP packetization-mode 0 i.e. single
* NAL unit per RTP packet.
*/
- self->encoder.context->rtp_payload_size = H264_RTP_PAYLOAD_SIZE;
- self->encoder.context->opaque = tsk_null;
- self->encoder.context->gop_size = (TMEDIA_CODEC_VIDEO(self)->out.fps * TDAV_H264_GOP_SIZE_IN_SECONDS);
-
+ self->encoder.context->rtp_payload_size = H264_RTP_PAYLOAD_SIZE;
+ self->encoder.context->opaque = tsk_null;
+ self->encoder.context->gop_size = (TMEDIA_CODEC_VIDEO(self)->out.fps * TDAV_H264_GOP_SIZE_IN_SECONDS);
+
#if (LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51, 35, 0))
- if((ret = av_opt_set_int(self->encoder.context->priv_data, "slice-max-size", H264_RTP_PAYLOAD_SIZE, 0))){
- TSK_DEBUG_ERROR("Failed to set x264 slice-max-size to %d", H264_RTP_PAYLOAD_SIZE);
- }
- if((ret = av_opt_set(self->encoder.context->priv_data, "profile", (self->encoder.context->profile == FF_PROFILE_H264_BASELINE ? "baseline" : "main"), 0))){
- TSK_DEBUG_ERROR("Failed to set x264 profile");
- }
- if((ret = av_opt_set(self->encoder.context->priv_data, "preset", "veryfast", 0))){
- TSK_DEBUG_ERROR("Failed to set x264 preset to veryfast");
- }
- if((ret = av_opt_set_int(self->encoder.context->priv_data, "rc-lookahead", 0, 0)) && (ret = av_opt_set_int(self->encoder.context->priv_data, "rc_lookahead", 0, 0))){
+ if((ret = av_opt_set_int(self->encoder.context->priv_data, "slice-max-size", H264_RTP_PAYLOAD_SIZE, 0))) {
+ TSK_DEBUG_ERROR("Failed to set x264 slice-max-size to %d", H264_RTP_PAYLOAD_SIZE);
+ }
+ if((ret = av_opt_set(self->encoder.context->priv_data, "profile", (self->encoder.context->profile == FF_PROFILE_H264_BASELINE ? "baseline" : "main"), 0))) {
+ TSK_DEBUG_ERROR("Failed to set x264 profile");
+ }
+ if((ret = av_opt_set(self->encoder.context->priv_data, "preset", "veryfast", 0))) {
+ TSK_DEBUG_ERROR("Failed to set x264 preset to veryfast");
+ }
+ if((ret = av_opt_set_int(self->encoder.context->priv_data, "rc-lookahead", 0, 0)) && (ret = av_opt_set_int(self->encoder.context->priv_data, "rc_lookahead", 0, 0))) {
TSK_DEBUG_ERROR("Failed to set x264 rc_lookahead=0");
}
- if((ret = av_opt_set(self->encoder.context->priv_data, "tune", "animation+zerolatency", 0))){
- TSK_DEBUG_ERROR("Failed to set x264 tune to zerolatency");
- }
+ if((ret = av_opt_set(self->encoder.context->priv_data, "tune", "animation+zerolatency", 0))) {
+ TSK_DEBUG_ERROR("Failed to set x264 tune to zerolatency");
+ }
#endif
- // Picture (YUV 420)
- if(!(self->encoder.picture = avcodec_alloc_frame())){
- TSK_DEBUG_ERROR("Failed to create encoder picture");
- return -2;
- }
- avcodec_get_frame_defaults(self->encoder.picture);
-
-
- size = avpicture_get_size(PIX_FMT_YUV420P, self->encoder.context->width, self->encoder.context->height);
- if(!(self->encoder.buffer = tsk_calloc(size, sizeof(uint8_t)))){
- TSK_DEBUG_ERROR("Failed to allocate encoder buffer");
- return -2;
- }
-
- // Open encoder
- if((ret = avcodec_open(self->encoder.context, self->encoder.codec)) < 0){
- TSK_DEBUG_ERROR("Failed to open [%s] codec", TMEDIA_CODEC(self)->plugin->desc);
- return ret;
- }
-
+ // Picture (YUV 420)
+ if(!(self->encoder.picture = avcodec_alloc_frame())) {
+ TSK_DEBUG_ERROR("Failed to create encoder picture");
+ return -2;
+ }
+ avcodec_get_frame_defaults(self->encoder.picture);
+
+
+ size = avpicture_get_size(PIX_FMT_YUV420P, self->encoder.context->width, self->encoder.context->height);
+ if(!(self->encoder.buffer = tsk_calloc(size, sizeof(uint8_t)))) {
+ TSK_DEBUG_ERROR("Failed to allocate encoder buffer");
+ return -2;
+ }
+
+ // Open encoder
+ if((ret = avcodec_open(self->encoder.context, self->encoder.codec)) < 0) {
+ TSK_DEBUG_ERROR("Failed to open [%s] codec", TMEDIA_CODEC(self)->plugin->desc);
+ return ret;
+ }
+
self->encoder.frame_count = 0;
- TSK_DEBUG_INFO("[H.264] bitrate=%d bps", self->encoder.context->bit_rate);
+ TSK_DEBUG_INFO("[H.264] bitrate=%d bps", self->encoder.context->bit_rate);
- return ret;
+ return ret;
#elif HAVE_H264_PASSTHROUGH
self->encoder.frame_count = 0;
- return 0;
+ return 0;
#endif
- TSK_DEBUG_ERROR("Not expected code called");
- return -1;
+ TSK_DEBUG_ERROR("Not expected code called");
+ return -1;
}
int tdav_codec_h264_close_encoder(tdav_codec_h264_t* self, tsk_bool_t reset_rotation)
{
#if HAVE_FFMPEG
- if(self->encoder.context){
- avcodec_close(self->encoder.context);
- av_free(self->encoder.context);
- self->encoder.context = tsk_null;
- }
- if(self->encoder.picture){
- av_free(self->encoder.picture);
- self->encoder.picture = tsk_null;
- }
+ if(self->encoder.context) {
+ avcodec_close(self->encoder.context);
+ av_free(self->encoder.context);
+ self->encoder.context = tsk_null;
+ }
+ if(self->encoder.picture) {
+ av_free(self->encoder.picture);
+ self->encoder.picture = tsk_null;
+ }
#endif
- if(self->encoder.buffer){
- TSK_FREE(self->encoder.buffer);
- }
- self->encoder.frame_count = 0;
+ if(self->encoder.buffer) {
+ TSK_FREE(self->encoder.buffer);
+ }
+ self->encoder.frame_count = 0;
if (reset_rotation) {
self->encoder.rotation = 0; // reset rotation
}
- return 0;
+ return 0;
}
int tdav_codec_h264_open_decoder(tdav_codec_h264_t* self)
{
#if HAVE_FFMPEG
- int ret;
-
- if(self->decoder.context){
- TSK_DEBUG_ERROR("Decoder already opened");
- return -1;
- }
-
- self->decoder.context = avcodec_alloc_context();
- avcodec_get_context_defaults(self->decoder.context);
-
- self->decoder.context->pix_fmt = PIX_FMT_YUV420P;
- self->decoder.context->flags2 |= CODEC_FLAG2_FAST;
- self->decoder.context->width = TMEDIA_CODEC_VIDEO(self)->in.width;
- self->decoder.context->height = TMEDIA_CODEC_VIDEO(self)->in.height;
-
- // Picture (YUV 420)
- if(!(self->decoder.picture = avcodec_alloc_frame())){
- TSK_DEBUG_ERROR("Failed to create decoder picture");
- return -2;
- }
- avcodec_get_frame_defaults(self->decoder.picture);
-
- // Open decoder
- if((ret = avcodec_open(self->decoder.context, self->decoder.codec)) < 0){
- TSK_DEBUG_ERROR("Failed to open [%s] codec", TMEDIA_CODEC(self)->plugin->desc);
- return ret;
- }
+ int ret;
+
+ if(self->decoder.context) {
+ TSK_DEBUG_ERROR("Decoder already opened");
+ return -1;
+ }
+
+ self->decoder.context = avcodec_alloc_context();
+ avcodec_get_context_defaults(self->decoder.context);
+
+ self->decoder.context->pix_fmt = PIX_FMT_YUV420P;
+ self->decoder.context->flags2 |= CODEC_FLAG2_FAST;
+ self->decoder.context->width = TMEDIA_CODEC_VIDEO(self)->in.width;
+ self->decoder.context->height = TMEDIA_CODEC_VIDEO(self)->in.height;
+
+ // Picture (YUV 420)
+ if(!(self->decoder.picture = avcodec_alloc_frame())) {
+ TSK_DEBUG_ERROR("Failed to create decoder picture");
+ return -2;
+ }
+ avcodec_get_frame_defaults(self->decoder.picture);
+
+ // Open decoder
+ if((ret = avcodec_open(self->decoder.context, self->decoder.codec)) < 0) {
+ TSK_DEBUG_ERROR("Failed to open [%s] codec", TMEDIA_CODEC(self)->plugin->desc);
+ return ret;
+ }
self->decoder.last_seq = 0;
- return ret;
+ return ret;
#elif HAVE_H264_PASSTHROUGH
- return 0;
+ return 0;
#endif
- TSK_DEBUG_ERROR("Unexpected code called");
- return -1;
-
+ TSK_DEBUG_ERROR("Unexpected code called");
+ return -1;
+
}
int tdav_codec_h264_close_decoder(tdav_codec_h264_t* self)
{
#if HAVE_FFMPEG
- if(self->decoder.context){
- avcodec_close(self->decoder.context);
- av_free(self->decoder.context);
- self->decoder.context = tsk_null;
- }
- if(self->decoder.picture){
- av_free(self->decoder.picture);
- self->decoder.picture = tsk_null;
- }
+ if(self->decoder.context) {
+ avcodec_close(self->decoder.context);
+ av_free(self->decoder.context);
+ self->decoder.context = tsk_null;
+ }
+ if(self->decoder.picture) {
+ av_free(self->decoder.picture);
+ self->decoder.picture = tsk_null;
+ }
#endif
- TSK_FREE(self->decoder.accumulator);
- self->decoder.accumulator_pos = 0;
+ TSK_FREE(self->decoder.accumulator);
+ self->decoder.accumulator_pos = 0;
- return 0;
+ return 0;
}
int tdav_codec_h264_init(tdav_codec_h264_t* self, profile_idc_t profile)
{
- int ret = 0;
- level_idc_t level;
-
- if(!self){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- if((ret = tdav_codec_h264_common_init(TDAV_CODEC_H264_COMMON(self)))){
- TSK_DEBUG_ERROR("tdav_codec_h264_common_init() faile with error code=%d", ret);
- return ret;
- }
-
- if((ret = tdav_codec_h264_common_level_from_size(TMEDIA_CODEC_VIDEO(self)->out.width, TMEDIA_CODEC_VIDEO(self)->out.height, &level))){
- TSK_DEBUG_ERROR("Failed to find level for size=[%u, %u]", TMEDIA_CODEC_VIDEO(self)->out.width, TMEDIA_CODEC_VIDEO(self)->out.height);
- return ret;
- }
-
- (self)->encoder.max_bw_kpbs = TMEDIA_CODEC(self)->bandwidth_max_upload;
- TDAV_CODEC_H264_COMMON(self)->pack_mode_local = H264_PACKETIZATION_MODE;
- TDAV_CODEC_H264_COMMON(self)->profile = profile;
- TDAV_CODEC_H264_COMMON(self)->level = level;
- TMEDIA_CODEC_VIDEO(self)->in.max_mbps = TMEDIA_CODEC_VIDEO(self)->out.max_mbps = H264_MAX_MBPS*1000;
- TMEDIA_CODEC_VIDEO(self)->in.max_br = TMEDIA_CODEC_VIDEO(self)->out.max_br = H264_MAX_BR*1000;
+ int ret = 0;
+ level_idc_t level;
+
+ if(!self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if((ret = tdav_codec_h264_common_init(TDAV_CODEC_H264_COMMON(self)))) {
+ TSK_DEBUG_ERROR("tdav_codec_h264_common_init() faile with error code=%d", ret);
+ return ret;
+ }
+
+ if((ret = tdav_codec_h264_common_level_from_size(TMEDIA_CODEC_VIDEO(self)->out.width, TMEDIA_CODEC_VIDEO(self)->out.height, &level))) {
+ TSK_DEBUG_ERROR("Failed to find level for size=[%u, %u]", TMEDIA_CODEC_VIDEO(self)->out.width, TMEDIA_CODEC_VIDEO(self)->out.height);
+ return ret;
+ }
+
+ (self)->encoder.max_bw_kpbs = TMEDIA_CODEC(self)->bandwidth_max_upload;
+ TDAV_CODEC_H264_COMMON(self)->pack_mode_local = H264_PACKETIZATION_MODE;
+ TDAV_CODEC_H264_COMMON(self)->profile = profile;
+ TDAV_CODEC_H264_COMMON(self)->level = level;
+ TMEDIA_CODEC_VIDEO(self)->in.max_mbps = TMEDIA_CODEC_VIDEO(self)->out.max_mbps = H264_MAX_MBPS*1000;
+ TMEDIA_CODEC_VIDEO(self)->in.max_br = TMEDIA_CODEC_VIDEO(self)->out.max_br = H264_MAX_BR*1000;
#if HAVE_FFMPEG
- if(!(self->encoder.codec = avcodec_find_encoder(CODEC_ID_H264))){
- TSK_DEBUG_ERROR("Failed to find H.264 encoder");
- ret = -2;
- }
-
- if(!(self->decoder.codec = avcodec_find_decoder(CODEC_ID_H264))){
- TSK_DEBUG_ERROR("Failed to find H.264 decoder");
- ret = -3;
- }
+ if(!(self->encoder.codec = avcodec_find_encoder(CODEC_ID_H264))) {
+ TSK_DEBUG_ERROR("Failed to find H.264 encoder");
+ ret = -2;
+ }
+
+ if(!(self->decoder.codec = avcodec_find_decoder(CODEC_ID_H264))) {
+ TSK_DEBUG_ERROR("Failed to find H.264 decoder");
+ ret = -3;
+ }
#endif
#if HAVE_H264_PASSTHROUGH
- TMEDIA_CODEC(self)->passthrough = tsk_true;
- self->decoder.passthrough = tsk_true;
- self->encoder.passthrough = tsk_true;
+ TMEDIA_CODEC(self)->passthrough = tsk_true;
+ self->decoder.passthrough = tsk_true;
+ self->encoder.passthrough = tsk_true;
#endif
- self->encoder.quality = 1;
+ self->encoder.quality = 1;
- /* allocations MUST be done by open() */
- return ret;
+ /* allocations MUST be done by open() */
+ return ret;
}
int tdav_codec_h264_deinit(tdav_codec_h264_t* self)
{
- if(!self){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
+ if(!self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
#if HAVE_FFMPEG
- self->encoder.codec = tsk_null;
- self->decoder.codec = tsk_null;
+ self->encoder.codec = tsk_null;
+ self->decoder.codec = tsk_null;
- // FFMpeg resources are destroyed by close()
+ // FFMpeg resources are destroyed by close()
#endif
- return 0;
+ return 0;
}
tsk_bool_t tdav_codec_ffmpeg_h264_is_supported()
{
#if HAVE_FFMPEG
- return (avcodec_find_encoder(CODEC_ID_H264) && avcodec_find_decoder(CODEC_ID_H264));
+ return (avcodec_find_encoder(CODEC_ID_H264) && avcodec_find_decoder(CODEC_ID_H264));
#else
- return tsk_false;
+ return tsk_false;
#endif
}
tsk_bool_t tdav_codec_passthrough_h264_is_supported()
{
#if HAVE_H264_PASSTHROUGH
- return tsk_true;
+ return tsk_true;
#else
- return tsk_false;
+ return tsk_false;
#endif
}
diff --git a/tinyDAV/src/codecs/h264/tdav_codec_h264_cisco.cxx b/tinyDAV/src/codecs/h264/tdav_codec_h264_cisco.cxx
index a501221..4973089 100755
--- a/tinyDAV/src/codecs/h264/tdav_codec_h264_cisco.cxx
+++ b/tinyDAV/src/codecs/h264/tdav_codec_h264_cisco.cxx
@@ -1,19 +1,19 @@
/*
* Copyright (C) 2014-2015 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.
*
@@ -46,33 +46,32 @@ extern "C" {
#include <limits.h> /* INT_MAX */
-typedef struct tdav_codec_h264_cisco_s
-{
- TDAV_DECLARE_CODEC_H264_COMMON;
-
- // Encoder
- struct{
- ISVCEncoder *pInst;
- SEncParamExt sEncParam;
- SSourcePicture sEncPic;
- void* buffer;
- int64_t frame_count;
- tsk_bool_t force_idr;
- int rotation;
- int neg_width;
- int neg_height;
- int neg_fps;
+typedef struct tdav_codec_h264_cisco_s {
+ TDAV_DECLARE_CODEC_H264_COMMON;
+
+ // Encoder
+ struct {
+ ISVCEncoder *pInst;
+ SEncParamExt sEncParam;
+ SSourcePicture sEncPic;
+ void* buffer;
+ int64_t frame_count;
+ tsk_bool_t force_idr;
+ int rotation;
+ int neg_width;
+ int neg_height;
+ int neg_fps;
tsk_mutex_handle_t* mutex;
- } encoder;
-
- // decoder
- struct{
- ISVCDecoder* pInst;
- void* accumulator;
- tsk_size_t accumulator_pos;
- tsk_size_t accumulator_size;
- uint16_t last_seq;
- } decoder;
+ } encoder;
+
+ // decoder
+ struct {
+ ISVCDecoder* pInst;
+ void* accumulator;
+ tsk_size_t accumulator_pos;
+ tsk_size_t accumulator_size;
+ uint16_t last_seq;
+ } decoder;
}
tdav_codec_h264_cisco_t;
@@ -98,448 +97,452 @@ static void (*__tdav_codec_h264_cisco_debug_cb)(void* context, int level, const
static int tdav_codec_h264_cisco_set(tmedia_codec_t* self, const tmedia_param_t* param)
{
- tdav_codec_h264_cisco_t* h264 = (tdav_codec_h264_cisco_t*)self;
- tsk_bool_t reconf = tsk_false;
- if (param->value_type == tmedia_pvt_int32) {
- if (tsk_striequals(param->key, "action")) {
- tmedia_codec_action_t action = (tmedia_codec_action_t)TSK_TO_INT32((uint8_t*)param->value);
- switch (action) {
- case tmedia_codec_action_encode_idr:
- {
- TSK_DEBUG_INFO("OpenH264 force_idr action");
- h264->encoder.force_idr = tsk_true;
- return 0;
- }
- case tmedia_codec_action_bw_up:
- case tmedia_codec_action_bw_down:
- {
- int32_t rc_target_bitrate;
- int32_t bandwidth_max_upload_bps = TMEDIA_CODEC(h264)->bandwidth_max_upload == INT_MAX ? TMEDIA_CODEC(h264)->bandwidth_max_upload : (TMEDIA_CODEC(h264)->bandwidth_max_upload * 1024); // kbps -> bps
- if (action == tmedia_codec_action_bw_up) {
- rc_target_bitrate = TSK_CLAMP(0, (int32_t)((h264->encoder.sEncParam.iTargetBitrate * 3) >> 1), bandwidth_max_upload_bps);
- }
- else {
- rc_target_bitrate = TSK_CLAMP(0, (int32_t)((h264->encoder.sEncParam.iTargetBitrate << 1) / 3), bandwidth_max_upload_bps);
- }
- h264->encoder.sEncParam.iTargetBitrate = rc_target_bitrate;
- h264->encoder.sEncParam.iMaxBitrate = rc_target_bitrate;
- SSpatialLayerConfig* layer = &h264->encoder.sEncParam.sSpatialLayers[0];
- layer->iMaxSpatialBitrate = h264->encoder.sEncParam.iMaxBitrate;
- layer->iSpatialBitrate = h264->encoder.sEncParam.iTargetBitrate;
- reconf = tsk_true;
- TSK_DEBUG_INFO("OpenH264 new target bitrate = %d bps", rc_target_bitrate);
- break;
- }
- }
- }
- else if (tsk_striequals(param->key, "bw_kbps")) { // both up and down (from the SDP)
- int32_t max_bw_userdefine_kbps = tmedia_defaults_get_bandwidth_video_upload_max();
- int32_t max_bw_new_kbps = *((int32_t*)param->value);
- if (max_bw_userdefine_kbps > 0) {
- // do not use more than what the user defined in it's configuration
- TMEDIA_CODEC(h264)->bandwidth_max_upload = TSK_MIN(max_bw_new_kbps, max_bw_userdefine_kbps);
- }
- else {
- TMEDIA_CODEC(h264)->bandwidth_max_upload = max_bw_new_kbps;
- }
- TSK_DEBUG_INFO("OpenH264 codec: bandwidth-max-upload= %d kbps", TMEDIA_CODEC(h264)->bandwidth_max_upload);
- reconf = tsk_true;
- }
- else if (tsk_striequals(param->key, "bandwidth-max-upload")) {
- int32_t bw_max_upload_kbps = *((int32_t*)param->value);
- TSK_DEBUG_INFO("OpenH264 codec: bandwidth-max-upload= %d kbps", bw_max_upload_kbps);
- TMEDIA_CODEC(h264)->bandwidth_max_upload = bw_max_upload_kbps;
- reconf = tsk_true;
- }
- else if (tsk_striequals(param->key, "rotation")) {
- int rotation = *((int32_t*)param->value);
- if (h264->encoder.rotation != rotation) {
+ tdav_codec_h264_cisco_t* h264 = (tdav_codec_h264_cisco_t*)self;
+ tsk_bool_t reconf = tsk_false;
+ if (param->value_type == tmedia_pvt_int32) {
+ if (tsk_striequals(param->key, "action")) {
+ tmedia_codec_action_t action = (tmedia_codec_action_t)TSK_TO_INT32((uint8_t*)param->value);
+ switch (action) {
+ case tmedia_codec_action_encode_idr: {
+ TSK_DEBUG_INFO("OpenH264 force_idr action");
+ h264->encoder.force_idr = tsk_true;
+ return 0;
+ }
+ case tmedia_codec_action_bw_up:
+ case tmedia_codec_action_bw_down: {
+ int32_t rc_target_bitrate;
+ int32_t bandwidth_max_upload_bps = TMEDIA_CODEC(h264)->bandwidth_max_upload == INT_MAX ? TMEDIA_CODEC(h264)->bandwidth_max_upload : (TMEDIA_CODEC(h264)->bandwidth_max_upload * 1024); // kbps -> bps
+ if (action == tmedia_codec_action_bw_up) {
+ rc_target_bitrate = TSK_CLAMP(0, (int32_t)((h264->encoder.sEncParam.iTargetBitrate * 3) >> 1), bandwidth_max_upload_bps);
+ }
+ else {
+ rc_target_bitrate = TSK_CLAMP(0, (int32_t)((h264->encoder.sEncParam.iTargetBitrate << 1) / 3), bandwidth_max_upload_bps);
+ }
+ h264->encoder.sEncParam.iTargetBitrate = rc_target_bitrate;
+ h264->encoder.sEncParam.iMaxBitrate = rc_target_bitrate;
+ SSpatialLayerConfig* layer = &h264->encoder.sEncParam.sSpatialLayers[0];
+ layer->iMaxSpatialBitrate = h264->encoder.sEncParam.iMaxBitrate;
+ layer->iSpatialBitrate = h264->encoder.sEncParam.iTargetBitrate;
+ reconf = tsk_true;
+ TSK_DEBUG_INFO("OpenH264 new target bitrate = %d bps", rc_target_bitrate);
+ break;
+ }
+ }
+ }
+ else if (tsk_striequals(param->key, "bw_kbps")) { // both up and down (from the SDP)
+ int32_t max_bw_userdefine_kbps = tmedia_defaults_get_bandwidth_video_upload_max();
+ int32_t max_bw_new_kbps = *((int32_t*)param->value), max_bitrate_bps;
+ if (max_bw_userdefine_kbps > 0) {
+ // do not use more than what the user defined in it's configuration
+ TMEDIA_CODEC(h264)->bandwidth_max_upload = TSK_MIN(max_bw_new_kbps, max_bw_userdefine_kbps);
+ }
+ else {
+ TMEDIA_CODEC(h264)->bandwidth_max_upload = max_bw_new_kbps;
+ }
+ max_bitrate_bps = TMEDIA_CODEC(h264)->bandwidth_max_upload << 10; // convert from kbps to bps
+ TSK_DEBUG_INFO("OpenH264 codec: bandwidth-max-upload= %dbps, %dkbps", max_bitrate_bps, TMEDIA_CODEC(h264)->bandwidth_max_upload);
+ h264->encoder.sEncParam.iTargetBitrate = max_bitrate_bps;
+ h264->encoder.sEncParam.iMaxBitrate = max_bitrate_bps;
+ SSpatialLayerConfig* layer = &h264->encoder.sEncParam.sSpatialLayers[0];
+ layer->iMaxSpatialBitrate = h264->encoder.sEncParam.iMaxBitrate;
+ layer->iSpatialBitrate = h264->encoder.sEncParam.iTargetBitrate;
+ reconf = tsk_true;
+ }
+ else if (tsk_striequals(param->key, "bandwidth-max-upload")) {
+ int32_t bw_max_upload_kbps = *((int32_t*)param->value);
+ TSK_DEBUG_INFO("OpenH264 codec: bandwidth-max-upload= %d kbps", bw_max_upload_kbps);
+ TMEDIA_CODEC(h264)->bandwidth_max_upload = bw_max_upload_kbps;
+ reconf = tsk_true;
+ }
+ else if (tsk_striequals(param->key, "rotation")) {
+ int rotation = *((int32_t*)param->value);
+ if (h264->encoder.rotation != rotation) {
h264->encoder.rotation = rotation;
- if (self->opened) {
- int ret;
- if ((ret = tdav_codec_h264_cisco_close_encoder(h264, kResetRotationFalse))) {
- return ret;
- }
- if ((ret = tdav_codec_h264_cisco_open_encoder(h264))) {
- return ret;
- }
- }
- }
- return 0;
- }
- }
-
- if (reconf) {
- if (h264->encoder.pInst) {
+ if (self->opened) {
+ int ret;
+ if ((ret = tdav_codec_h264_cisco_close_encoder(h264, kResetRotationFalse))) {
+ return ret;
+ }
+ if ((ret = tdav_codec_h264_cisco_open_encoder(h264))) {
+ return ret;
+ }
+ }
+ }
+ return 0;
+ }
+ }
+
+ if (reconf) {
+ if (h264->encoder.pInst) {
long err;
// lock required because of https://code.google.com/p/doubango/issues/detail?id=422
tsk_mutex_lock(h264->encoder.mutex);
- err = h264->encoder.pInst->InitializeExt(&h264->encoder.sEncParam);
+ err = h264->encoder.pInst->InitializeExt(&h264->encoder.sEncParam);
tsk_mutex_unlock(h264->encoder.mutex);
- if (err != cmResultSuccess) {
- TSK_DEBUG_ERROR("InitializeExt failed: %ld", err);
- return -1;
- }
- }
- return 0;
- }
-
- return -1;
+ if (err != cmResultSuccess) {
+ TSK_DEBUG_ERROR("InitializeExt failed: %ld", err);
+ return -1;
+ }
+ }
+ return 0;
+ }
+
+ return -1;
}
static int tdav_codec_h264_cisco_open(tmedia_codec_t* self)
{
- int ret;
- tdav_codec_h264_cisco_t* h264 = (tdav_codec_h264_cisco_t*)self;
-
- if (!h264) {
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- /* the caller (base class) already checked that the codec is not opened */
-
- // Encoder
- if ((ret = tdav_codec_h264_cisco_open_encoder(h264))) {
- return ret;
- }
-
- // Decoder
- if ((ret = tdav_codec_h264_cisco_open_decoder(h264))) {
- return ret;
- }
-
- return 0;
+ int ret;
+ tdav_codec_h264_cisco_t* h264 = (tdav_codec_h264_cisco_t*)self;
+
+ if (!h264) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ /* the caller (base class) already checked that the codec is not opened */
+
+ // Encoder
+ if ((ret = tdav_codec_h264_cisco_open_encoder(h264))) {
+ return ret;
+ }
+
+ // Decoder
+ if ((ret = tdav_codec_h264_cisco_open_decoder(h264))) {
+ return ret;
+ }
+
+ return 0;
}
static int tdav_codec_h264_cisco_close(tmedia_codec_t* self)
{
- tdav_codec_h264_cisco_t* h264 = (tdav_codec_h264_cisco_t*)self;
+ tdav_codec_h264_cisco_t* h264 = (tdav_codec_h264_cisco_t*)self;
- if (!h264) {
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
+ if (!h264) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
- /* the caller (base class) already checked that the codec is opened */
+ /* the caller (base class) already checked that the codec is opened */
- // Encoder
- tdav_codec_h264_cisco_close_encoder(h264, kResetRotationTrue);
+ // Encoder
+ tdav_codec_h264_cisco_close_encoder(h264, kResetRotationTrue);
- // Decoder
- tdav_codec_h264_cisco_close_decoder(h264);
+ // Decoder
+ tdav_codec_h264_cisco_close_decoder(h264);
- return 0;
+ return 0;
}
static tsk_size_t tdav_codec_h264_cisco_encode(tmedia_codec_t* self, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size)
{
- long err;
- tsk_bool_t send_idr, send_hdr;
- tsk_size_t in_xsize;
- SFrameBSInfo bsInfo;
-
- tdav_codec_h264_cisco_t* h264 = (tdav_codec_h264_cisco_t*)self;
- tdav_codec_h264_common_t* common = (tdav_codec_h264_common_t*)self;
-
- if (!self || !in_data || !in_size) {
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- if (!self->opened || !h264->encoder.pInst) {
- TSK_DEBUG_ERROR("Encoder not opened or not ready");
- return 0;
- }
-
- in_xsize = (h264->encoder.sEncPic.iPicHeight * h264->encoder.sEncPic.iPicWidth * 3) >> 1;
- if (in_xsize != in_size){
- /* guard */
- TSK_DEBUG_ERROR("Invalid size: %u<>%u", in_xsize, in_size);
- return 0;
- }
-
- // send IDR for:
- // - the first frame
- // - remote peer requested an IDR
- // - every second within the first 4seconds
- send_idr = (
- h264->encoder.frame_count++ == 0
- || h264 ->encoder.force_idr
- //|| ( (h264->encoder.frame_count < (int)TMEDIA_CODEC_VIDEO(h264)->out.fps * 4) && ((h264->encoder.frame_count % TMEDIA_CODEC_VIDEO(h264)->out.fps)==0) )
- );
-
- // send SPS and PPS headers for:
- // - IDR frames (not required but it's the easiest way to deal with pkt loss)
- // - every 5 seconds after the first 4seconds
- send_hdr = (
- send_idr
- //|| ( (h264->encoder.frame_count % (TMEDIA_CODEC_VIDEO(h264)->out.fps * 5))==0 )
- );
-
- if (send_idr) {
- TSK_DEBUG_INFO("OpenH264 call ForceIntraFrame");
- if ((err = h264->encoder.pInst->ForceIntraFrame(true)) != cmResultSuccess) {
- TSK_DEBUG_WARN("OpenH264 ForceIntraFrame(%d) failed: %ld", send_idr, err);
- }
- }
- if (send_hdr) {
+ long err;
+ tsk_bool_t send_idr, send_hdr;
+ tsk_size_t in_xsize;
+ SFrameBSInfo bsInfo;
+
+ tdav_codec_h264_cisco_t* h264 = (tdav_codec_h264_cisco_t*)self;
+ tdav_codec_h264_common_t* common = (tdav_codec_h264_common_t*)self;
+
+ if (!self || !in_data || !in_size) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ if (!self->opened || !h264->encoder.pInst) {
+ TSK_DEBUG_ERROR("Encoder not opened or not ready");
+ return 0;
+ }
+
+ in_xsize = (h264->encoder.sEncPic.iPicHeight * h264->encoder.sEncPic.iPicWidth * 3) >> 1;
+ if (in_xsize != in_size) {
+ /* guard */
+ TSK_DEBUG_ERROR("Invalid size: %u<>%u", in_xsize, in_size);
+ return 0;
+ }
+
+ // send IDR for:
+ // - the first frame
+ // - remote peer requested an IDR
+ // - every second within the first 4seconds
+ send_idr = (
+ h264->encoder.frame_count++ == 0
+ || h264 ->encoder.force_idr
+ //|| ( (h264->encoder.frame_count < (int)TMEDIA_CODEC_VIDEO(h264)->out.fps * 4) && ((h264->encoder.frame_count % TMEDIA_CODEC_VIDEO(h264)->out.fps)==0) )
+ );
+
+ // send SPS and PPS headers for:
+ // - IDR frames (not required but it's the easiest way to deal with pkt loss)
+ // - every 5 seconds after the first 4seconds
+ send_hdr = (
+ send_idr
+ //|| ( (h264->encoder.frame_count % (TMEDIA_CODEC_VIDEO(h264)->out.fps * 5))==0 )
+ );
+
+ if (send_idr) {
+ TSK_DEBUG_INFO("OpenH264 call ForceIntraFrame");
+ if ((err = h264->encoder.pInst->ForceIntraFrame(true)) != cmResultSuccess) {
+ TSK_DEBUG_WARN("OpenH264 ForceIntraFrame(%d) failed: %ld", send_idr, err);
+ }
+ }
+ if (send_hdr) {
#if 0 // Not needed
- memset(&bsInfo, 0, sizeof(bsInfo));
- tsk_mutex_lock(h264->encoder.mutex);
- if ((err = h264->encoder.pInst->EncodeParameterSets(&bsInfo)) != cmResultSuccess) {
- TSK_DEBUG_WARN("OpenH264 EncodeParameterSets(%d) failed: %ld", send_idr, err);
- }
- else {
- for (int iLayerNum = 0; iLayerNum < bsInfo.iLayerNum; ++iLayerNum) {
- unsigned char* pBsBuf = bsInfo.sLayerInfo[iLayerNum].pBsBuf;
- int iNalLengthInByte = 0, _iNalLengthInByte;
- for (int iNalCount = 0; iNalCount < bsInfo.sLayerInfo[iLayerNum].iNalCount; ++iNalCount) {
- if ((_iNalLengthInByte = bsInfo.sLayerInfo[iLayerNum].pNalLengthInByte[iNalCount]) > 0) {
- iNalLengthInByte += _iNalLengthInByte;
- }
- }
- if (iNalLengthInByte > 0) {
- tdav_codec_h264_rtp_encap(TDAV_CODEC_H264_COMMON(h264), pBsBuf, (tsk_size_t)iNalLengthInByte);
- }
- }
- }
- tsk_mutex_unlock(h264->encoder.mutex);
+ memset(&bsInfo, 0, sizeof(bsInfo));
+ tsk_mutex_lock(h264->encoder.mutex);
+ if ((err = h264->encoder.pInst->EncodeParameterSets(&bsInfo)) != cmResultSuccess) {
+ TSK_DEBUG_WARN("OpenH264 EncodeParameterSets(%d) failed: %ld", send_idr, err);
+ }
+ else {
+ for (int iLayerNum = 0; iLayerNum < bsInfo.iLayerNum; ++iLayerNum) {
+ unsigned char* pBsBuf = bsInfo.sLayerInfo[iLayerNum].pBsBuf;
+ int iNalLengthInByte = 0, _iNalLengthInByte;
+ for (int iNalCount = 0; iNalCount < bsInfo.sLayerInfo[iLayerNum].iNalCount; ++iNalCount) {
+ if ((_iNalLengthInByte = bsInfo.sLayerInfo[iLayerNum].pNalLengthInByte[iNalCount]) > 0) {
+ iNalLengthInByte += _iNalLengthInByte;
+ }
+ }
+ if (iNalLengthInByte > 0) {
+ tdav_codec_h264_rtp_encap(TDAV_CODEC_H264_COMMON(h264), pBsBuf, (tsk_size_t)iNalLengthInByte);
+ }
+ }
+ }
+ tsk_mutex_unlock(h264->encoder.mutex);
#endif
- }
+ }
- h264->encoder.sEncPic.pData[0] = ((unsigned char*)in_data);
- h264->encoder.sEncPic.pData[1] = h264->encoder.sEncPic.pData[0] + (h264->encoder.sEncPic.iPicHeight * h264->encoder.sEncPic.iPicWidth);
- h264->encoder.sEncPic.pData[2] = h264->encoder.sEncPic.pData[1] + ((h264->encoder.sEncPic.iPicHeight * h264->encoder.sEncPic.iPicWidth) >> 2);
- // h264->encoder.sEncPic.uiTimeStamp = rand();
+ h264->encoder.sEncPic.pData[0] = ((unsigned char*)in_data);
+ h264->encoder.sEncPic.pData[1] = h264->encoder.sEncPic.pData[0] + (h264->encoder.sEncPic.iPicHeight * h264->encoder.sEncPic.iPicWidth);
+ h264->encoder.sEncPic.pData[2] = h264->encoder.sEncPic.pData[1] + ((h264->encoder.sEncPic.iPicHeight * h264->encoder.sEncPic.iPicWidth) >> 2);
+ // h264->encoder.sEncPic.uiTimeStamp = rand();
+
+ memset(&bsInfo, 0, sizeof(bsInfo));
- memset(&bsInfo, 0, sizeof(bsInfo));
-
tsk_mutex_lock(h264->encoder.mutex);
- if ((err = h264->encoder.pInst->EncodeFrame(&h264->encoder.sEncPic, &bsInfo)) != cmResultSuccess) {
- TSK_DEBUG_ERROR("OpenH264 setting EncodeFrame() failed: %ld", err);
+ if ((err = h264->encoder.pInst->EncodeFrame(&h264->encoder.sEncPic, &bsInfo)) != cmResultSuccess) {
+ TSK_DEBUG_ERROR("OpenH264 setting EncodeFrame() failed: %ld", err);
tsk_mutex_unlock(h264->encoder.mutex);
- return 0;
- }
-
+ return 0;
+ }
+
// Memory held by bsInfo is freed when "InitializeExt()" is called this is why the unlock is after reading the output stream
- if (bsInfo.eFrameType != videoFrameTypeInvalid) {
- for (int iLayerNum = 0; iLayerNum < bsInfo.iLayerNum; ++iLayerNum) {
- unsigned char* pBsBuf = bsInfo.sLayerInfo[iLayerNum].pBsBuf;
- int iNalLengthInByte = 0, _iNalLengthInByte;
- for (int iNalCount = 0; iNalCount < bsInfo.sLayerInfo[iLayerNum].iNalCount; ++iNalCount) {
- if ((_iNalLengthInByte = bsInfo.sLayerInfo[iLayerNum].pNalLengthInByte[iNalCount]) > 0) {
- iNalLengthInByte += _iNalLengthInByte;
- }
- }
- if (iNalLengthInByte > 0) {
- tdav_codec_h264_rtp_encap(TDAV_CODEC_H264_COMMON(h264), pBsBuf, (tsk_size_t)iNalLengthInByte);
- }
- }
- }
+ if (bsInfo.eFrameType != videoFrameTypeInvalid) {
+ for (int iLayerNum = 0; iLayerNum < bsInfo.iLayerNum; ++iLayerNum) {
+ unsigned char* pBsBuf = bsInfo.sLayerInfo[iLayerNum].pBsBuf;
+ int iNalLengthInByte = 0, _iNalLengthInByte;
+ for (int iNalCount = 0; iNalCount < bsInfo.sLayerInfo[iLayerNum].iNalCount; ++iNalCount) {
+ if ((_iNalLengthInByte = bsInfo.sLayerInfo[iLayerNum].pNalLengthInByte[iNalCount]) > 0) {
+ iNalLengthInByte += _iNalLengthInByte;
+ }
+ }
+ if (iNalLengthInByte > 0) {
+ tdav_codec_h264_rtp_encap(TDAV_CODEC_H264_COMMON(h264), pBsBuf, (tsk_size_t)iNalLengthInByte);
+ }
+ }
+ }
tsk_mutex_unlock(h264->encoder.mutex);
-
- h264 ->encoder.force_idr = tsk_false; // reset
-
- return 0;
+
+ h264 ->encoder.force_idr = tsk_false; // reset
+
+ return 0;
}
static tsk_size_t tdav_codec_h264_cisco_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)
{
- tdav_codec_h264_cisco_t* h264 = (tdav_codec_h264_cisco_t*)self;
- const trtp_rtp_header_t* rtp_hdr = (const trtp_rtp_header_t*)proto_hdr;
-
- const uint8_t* pay_ptr = tsk_null;
- tsk_size_t pay_size = 0;
- int ret;
- long err = cmResultSuccess;
- tsk_bool_t append_scp, end_of_unit, got_picture_ptr = tsk_false;
- tsk_bool_t sps_or_pps;
- tsk_size_t retsize = 0, size_to_copy = 0;
- static const tsk_size_t xmax_size = (3840 * 2160 * 3) >> 3; // >>3 instead of >>1 (not an error)
- static tsk_size_t start_code_prefix_size = sizeof(H264_START_CODE_PREFIX);
-
- if (!h264 || !in_data || !in_size || !out_data) {
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- if (!self->opened || !h264->encoder.pInst) {
- TSK_DEBUG_ERROR("Decoder not opened or not ready");
- return 0;
- }
-
- /* Packet lost? */
- if ((h264->decoder.last_seq + 1) != rtp_hdr->seq_num && h264->decoder.last_seq) {
- TSK_DEBUG_INFO("[H.264] Packet loss, seq_num=%d", (h264->decoder.last_seq + 1));
- }
- h264->decoder.last_seq = rtp_hdr->seq_num;
-
-
- /* 5.3. NAL Unit Octet Usage
- +---------------+
+ tdav_codec_h264_cisco_t* h264 = (tdav_codec_h264_cisco_t*)self;
+ const trtp_rtp_header_t* rtp_hdr = (const trtp_rtp_header_t*)proto_hdr;
+
+ const uint8_t* pay_ptr = tsk_null;
+ tsk_size_t pay_size = 0;
+ int ret;
+ long err = cmResultSuccess;
+ tsk_bool_t append_scp, end_of_unit, got_picture_ptr = tsk_false;
+ tsk_bool_t sps_or_pps;
+ tsk_size_t retsize = 0, size_to_copy = 0;
+ static const tsk_size_t xmax_size = (3840 * 2160 * 3) >> 3; // >>3 instead of >>1 (not an error)
+ static tsk_size_t start_code_prefix_size = sizeof(H264_START_CODE_PREFIX);
+
+ if (!h264 || !in_data || !in_size || !out_data) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ if (!self->opened || !h264->encoder.pInst) {
+ TSK_DEBUG_ERROR("Decoder not opened or not ready");
+ return 0;
+ }
+
+ /* Packet lost? */
+ if ((h264->decoder.last_seq + 1) != rtp_hdr->seq_num && h264->decoder.last_seq) {
+ TSK_DEBUG_INFO("[H.264] Packet loss, seq_num=%d", (h264->decoder.last_seq + 1));
+ }
+ h264->decoder.last_seq = rtp_hdr->seq_num;
+
+
+ /* 5.3. NAL Unit Octet Usage
+ +---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|F|NRI| Type |
+---------------+
- */
- if (*((uint8_t*)in_data) & 0x80) {
- TSK_DEBUG_WARN("F=1");
- /* reset accumulator */
- h264->decoder.accumulator_pos = 0;
- return 0;
- }
-
- /* get payload */
- if ((ret = tdav_codec_h264_get_pay(in_data, in_size, (const void**)&pay_ptr, &pay_size, &append_scp, &end_of_unit)) || !pay_ptr || !pay_size) {
- TSK_DEBUG_ERROR("Depayloader failed to get H.264 content");
- return 0;
- }
- //append_scp = tsk_true;
- size_to_copy = pay_size + (append_scp ? start_code_prefix_size : 0);
- // whether it's SPS or PPS (append_scp is false for subsequent FUA chuncks)
- sps_or_pps = append_scp && pay_ptr && ((pay_ptr[0] & 0x1F) == 7 || (pay_ptr[0] & 0x1F) == 8);
-
- // start-accumulator
- if (!h264->decoder.accumulator) {
- if (size_to_copy > xmax_size) {
- TSK_DEBUG_ERROR("%u too big to contain valid encoded data. xmax_size=%u", size_to_copy, xmax_size);
- return 0;
- }
- if (!(h264->decoder.accumulator = tsk_calloc(size_to_copy, sizeof(uint8_t)))) {
- TSK_DEBUG_ERROR("Failed to allocated new buffer");
- return 0;
- }
- h264->decoder.accumulator_size = size_to_copy;
- }
- if ((h264->decoder.accumulator_pos + size_to_copy) >= xmax_size) {
- TSK_DEBUG_ERROR("BufferOverflow");
- h264->decoder.accumulator_pos = 0;
- return 0;
- }
- if ((h264->decoder.accumulator_pos + size_to_copy) > h264->decoder.accumulator_size) {
- if (!(h264->decoder.accumulator = tsk_realloc(h264->decoder.accumulator, (h264->decoder.accumulator_pos + size_to_copy)))) {
- TSK_DEBUG_ERROR("Failed to reallocated new buffer");
- h264->decoder.accumulator_pos = 0;
- h264->decoder.accumulator_size = 0;
- return 0;
- }
- h264->decoder.accumulator_size = (h264->decoder.accumulator_pos + size_to_copy);
- }
-
- if (append_scp) {
- memcpy(&((uint8_t*)h264->decoder.accumulator)[h264->decoder.accumulator_pos], H264_START_CODE_PREFIX, start_code_prefix_size);
- h264->decoder.accumulator_pos += start_code_prefix_size;
- }
- memcpy(&((uint8_t*)h264->decoder.accumulator)[h264->decoder.accumulator_pos], pay_ptr, pay_size);
- h264->decoder.accumulator_pos += pay_size;
- // end-accumulator
-
- if (/*rtp_hdr->marker*/end_of_unit) {
- /* decode the picture */
- unsigned char* out_ptr[3] = { NULL };
- int out_stride[2] = {0}, out_width = 0, out_height = 0;
- tsk_size_t out_xsize;
-
- // Decode a Unit
- err = h264->decoder.pInst->DecodeFrame(
- (const unsigned char*)h264->decoder.accumulator, h264->decoder.accumulator_pos,
- out_ptr, out_stride, out_width, out_height);
-
- if (err != cmResultSuccess) {
- if (0 && err == dsDataErrorConcealed) {
- TSK_DEBUG_INFO("OpenH264: Data error concealed");
- err = cmResultSuccess;
- }
- else {
- TSK_DEBUG_WARN("OpenH264: DecodeFrame failed: %ld", err);
- goto bail;
- }
- }
- // Do we have a complete frame?
- if (!(got_picture_ptr = ((out_ptr[0] && out_ptr[1] && out_ptr[2]) && (out_stride[0] && out_stride[1]) && out_width && out_height))) {
- goto bail;
- }
- out_xsize = (out_width * out_height * 3) >> 1; // I420
- /* IDR ? */
- if (((pay_ptr[0] & 0x1F) == 0x05) && TMEDIA_CODEC_VIDEO(self)->in.callback) {
- TSK_DEBUG_INFO("Decoded H.264 IDR");
- TMEDIA_CODEC_VIDEO(self)->in.result.type = tmedia_video_decode_result_type_idr;
- TMEDIA_CODEC_VIDEO(self)->in.result.proto_hdr = proto_hdr;
- TMEDIA_CODEC_VIDEO(self)->in.callback(&TMEDIA_CODEC_VIDEO(self)->in.result);
- }
- /* fill out */
- if (*out_max_size < out_xsize) {
- if ((*out_data = tsk_realloc(*out_data, out_xsize))){
- *out_max_size = out_xsize;
- }
- else {
- *out_max_size = 0;
- return 0;
- }
- }
- TMEDIA_CODEC_VIDEO(h264)->in.width = out_width;
- TMEDIA_CODEC_VIDEO(h264)->in.height = out_height;
- /* layout picture */
- {
- int plane, y, stride;
- retsize = 0;
- for (plane=0; plane < 3; plane++) {
- unsigned char *buf = out_ptr[plane];
- stride = out_stride[plane ? 1 : 0];
- for (y=0; y<out_height >> (plane ? 1 : 0); y++) {
- unsigned int w_count = out_width >> (plane ? 1 : 0);
- if ((ret + w_count) > *out_max_size) {
- TSK_DEBUG_ERROR("BufferOverflow");
- ret = 0;
- goto bail;
- }
- memcpy(((uint8_t*)*out_data) + retsize, buf, w_count);
- retsize += w_count;
- buf += stride;
- }
- }
- }
- } // else if(rtp_hdr->marker)
+ */
+ if (*((uint8_t*)in_data) & 0x80) {
+ TSK_DEBUG_WARN("F=1");
+ /* reset accumulator */
+ h264->decoder.accumulator_pos = 0;
+ return 0;
+ }
+
+ /* get payload */
+ if ((ret = tdav_codec_h264_get_pay(in_data, in_size, (const void**)&pay_ptr, &pay_size, &append_scp, &end_of_unit)) || !pay_ptr || !pay_size) {
+ TSK_DEBUG_ERROR("Depayloader failed to get H.264 content");
+ return 0;
+ }
+ //append_scp = tsk_true;
+ size_to_copy = pay_size + (append_scp ? start_code_prefix_size : 0);
+ // whether it's SPS or PPS (append_scp is false for subsequent FUA chuncks)
+ sps_or_pps = append_scp && pay_ptr && ((pay_ptr[0] & 0x1F) == 7 || (pay_ptr[0] & 0x1F) == 8);
+
+ // start-accumulator
+ if (!h264->decoder.accumulator) {
+ if (size_to_copy > xmax_size) {
+ TSK_DEBUG_ERROR("%u too big to contain valid encoded data. xmax_size=%u", size_to_copy, xmax_size);
+ return 0;
+ }
+ if (!(h264->decoder.accumulator = tsk_calloc(size_to_copy, sizeof(uint8_t)))) {
+ TSK_DEBUG_ERROR("Failed to allocated new buffer");
+ return 0;
+ }
+ h264->decoder.accumulator_size = size_to_copy;
+ }
+ if ((h264->decoder.accumulator_pos + size_to_copy) >= xmax_size) {
+ TSK_DEBUG_ERROR("BufferOverflow");
+ h264->decoder.accumulator_pos = 0;
+ return 0;
+ }
+ if ((h264->decoder.accumulator_pos + size_to_copy) > h264->decoder.accumulator_size) {
+ if (!(h264->decoder.accumulator = tsk_realloc(h264->decoder.accumulator, (h264->decoder.accumulator_pos + size_to_copy)))) {
+ TSK_DEBUG_ERROR("Failed to reallocated new buffer");
+ h264->decoder.accumulator_pos = 0;
+ h264->decoder.accumulator_size = 0;
+ return 0;
+ }
+ h264->decoder.accumulator_size = (h264->decoder.accumulator_pos + size_to_copy);
+ }
+
+ if (append_scp) {
+ memcpy(&((uint8_t*)h264->decoder.accumulator)[h264->decoder.accumulator_pos], H264_START_CODE_PREFIX, start_code_prefix_size);
+ h264->decoder.accumulator_pos += start_code_prefix_size;
+ }
+ memcpy(&((uint8_t*)h264->decoder.accumulator)[h264->decoder.accumulator_pos], pay_ptr, pay_size);
+ h264->decoder.accumulator_pos += pay_size;
+ // end-accumulator
+
+ if (/*rtp_hdr->marker*/end_of_unit) {
+ /* decode the picture */
+ unsigned char* out_ptr[3] = { NULL };
+ int out_stride[2] = {0}, out_width = 0, out_height = 0;
+ tsk_size_t out_xsize;
+
+ // Decode a Unit
+ err = h264->decoder.pInst->DecodeFrame(
+ (const unsigned char*)h264->decoder.accumulator, h264->decoder.accumulator_pos,
+ out_ptr, out_stride, out_width, out_height);
+
+ if (err != cmResultSuccess) {
+ if (0 && err == dsDataErrorConcealed) {
+ TSK_DEBUG_INFO("OpenH264: Data error concealed");
+ err = cmResultSuccess;
+ }
+ else {
+ TSK_DEBUG_WARN("OpenH264: DecodeFrame failed: %ld", err);
+ goto bail;
+ }
+ }
+ // Do we have a complete frame?
+ if (!(got_picture_ptr = ((out_ptr[0] && out_ptr[1] && out_ptr[2]) && (out_stride[0] && out_stride[1]) && out_width && out_height))) {
+ goto bail;
+ }
+ out_xsize = (out_width * out_height * 3) >> 1; // I420
+ /* IDR ? */
+ if (((pay_ptr[0] & 0x1F) == 0x05) && TMEDIA_CODEC_VIDEO(self)->in.callback) {
+ TSK_DEBUG_INFO("Decoded H.264 IDR");
+ TMEDIA_CODEC_VIDEO(self)->in.result.type = tmedia_video_decode_result_type_idr;
+ TMEDIA_CODEC_VIDEO(self)->in.result.proto_hdr = proto_hdr;
+ TMEDIA_CODEC_VIDEO(self)->in.callback(&TMEDIA_CODEC_VIDEO(self)->in.result);
+ }
+ /* fill out */
+ if (*out_max_size < out_xsize) {
+ if ((*out_data = tsk_realloc(*out_data, out_xsize))) {
+ *out_max_size = out_xsize;
+ }
+ else {
+ *out_max_size = 0;
+ return 0;
+ }
+ }
+ TMEDIA_CODEC_VIDEO(h264)->in.width = out_width;
+ TMEDIA_CODEC_VIDEO(h264)->in.height = out_height;
+ /* layout picture */
+ {
+ int plane, y, stride;
+ retsize = 0;
+ for (plane=0; plane < 3; plane++) {
+ unsigned char *buf = out_ptr[plane];
+ stride = out_stride[plane ? 1 : 0];
+ for (y=0; y<out_height >> (plane ? 1 : 0); y++) {
+ unsigned int w_count = out_width >> (plane ? 1 : 0);
+ if ((ret + w_count) > *out_max_size) {
+ TSK_DEBUG_ERROR("BufferOverflow");
+ ret = 0;
+ goto bail;
+ }
+ memcpy(((uint8_t*)*out_data) + retsize, buf, w_count);
+ retsize += w_count;
+ buf += stride;
+ }
+ }
+ }
+ } // else if(rtp_hdr->marker)
bail:
- /* end of frame */
- if (got_picture_ptr) {
- int32_t endOfStream = 1;
- err = h264->decoder.pInst->SetOption(DECODER_OPTION_END_OF_STREAM, (void*)&endOfStream);
- if (err != cmResultSuccess) {
- TSK_DEBUG_WARN("OpenH264 setting DECODER_OPTION_END_OF_STREAM failed: %ld", err);
- goto bail;
- }
- }
- if (/*rtp_hdr->marker*/end_of_unit) {
- /* reset accumulator */
- h264->decoder.accumulator_pos = 0;
- }
- if (err != cmResultSuccess){
- TSK_DEBUG_INFO("Failed to decode the buffer with error code =%ld, size=%u, append=%s", err, h264->decoder.accumulator_pos, append_scp ? "yes" : "no");
- if (TMEDIA_CODEC_VIDEO(self)->in.callback) {
- TMEDIA_CODEC_VIDEO(self)->in.result.type = tmedia_video_decode_result_type_error;
- TMEDIA_CODEC_VIDEO(self)->in.result.proto_hdr = proto_hdr;
- TMEDIA_CODEC_VIDEO(self)->in.callback(&TMEDIA_CODEC_VIDEO(self)->in.result);
- }
- }
- return retsize;
+ /* end of frame */
+ if (got_picture_ptr) {
+ int32_t endOfStream = 1;
+ err = h264->decoder.pInst->SetOption(DECODER_OPTION_END_OF_STREAM, (void*)&endOfStream);
+ if (err != cmResultSuccess) {
+ TSK_DEBUG_WARN("OpenH264 setting DECODER_OPTION_END_OF_STREAM failed: %ld", err);
+ goto bail;
+ }
+ }
+ if (/*rtp_hdr->marker*/end_of_unit) {
+ /* reset accumulator */
+ h264->decoder.accumulator_pos = 0;
+ }
+ if (err != cmResultSuccess) {
+ TSK_DEBUG_INFO("Failed to decode the buffer with error code =%ld, size=%u, append=%s", err, h264->decoder.accumulator_pos, append_scp ? "yes" : "no");
+ if (TMEDIA_CODEC_VIDEO(self)->in.callback) {
+ TMEDIA_CODEC_VIDEO(self)->in.result.type = tmedia_video_decode_result_type_error;
+ TMEDIA_CODEC_VIDEO(self)->in.result.proto_hdr = proto_hdr;
+ TMEDIA_CODEC_VIDEO(self)->in.callback(&TMEDIA_CODEC_VIDEO(self)->in.result);
+ }
+ }
+ return retsize;
}
static tsk_bool_t tdav_codec_h264_cisco_sdp_att_match(const tmedia_codec_t* self, const char* att_name, const char* att_value)
{
- return tdav_codec_h264_common_sdp_att_match((tdav_codec_h264_common_t*)self, att_name, att_value);
+ return tdav_codec_h264_common_sdp_att_match((tdav_codec_h264_common_t*)self, att_name, att_value);
}
static char* tdav_codec_h264_cisco_sdp_att_get(const tmedia_codec_t* self, const char* att_name)
{
- char* att = tdav_codec_h264_common_sdp_att_get((const tdav_codec_h264_common_t*)self, att_name);
- if (att && tsk_striequals(att_name, "fmtp")) {
- tsk_strcat(&att, "; impl=openh264");
- }
- return att;
+ char* att = tdav_codec_h264_common_sdp_att_get((const tdav_codec_h264_common_t*)self, att_name);
+ if (att && tsk_striequals(att_name, "fmtp")) {
+ tsk_strcat(&att, "; impl=openh264");
+ }
+ return att;
}
/* ============ H.264 Base Profile Plugin interface ================= */
@@ -547,63 +550,61 @@ static char* tdav_codec_h264_cisco_sdp_att_get(const tmedia_codec_t* self, const
/* constructor */
static tsk_object_t* tdav_codec_h264_cisco_base_ctor(tsk_object_t * self, va_list * app)
{
- tdav_codec_h264_cisco_t *h264 = (tdav_codec_h264_cisco_t*)self;
- if (h264) {
- /* init base: called by tmedia_codec_create() */
- /* init self */
- if (tdav_codec_h264_cisco_init(h264, profile_idc_baseline) != 0) {
- return tsk_null;
- }
- }
- return self;
+ tdav_codec_h264_cisco_t *h264 = (tdav_codec_h264_cisco_t*)self;
+ if (h264) {
+ /* init base: called by tmedia_codec_create() */
+ /* init self */
+ if (tdav_codec_h264_cisco_init(h264, profile_idc_baseline) != 0) {
+ return tsk_null;
+ }
+ }
+ return self;
}
/* destructor */
static tsk_object_t* tdav_codec_h264_cisco_base_dtor(tsk_object_t * self)
-{
- tdav_codec_h264_cisco_t *h264 = (tdav_codec_h264_cisco_t*)self;
- if (h264) {
- /* deinit base */
- tdav_codec_h264_common_deinit(TDAV_CODEC_H264_COMMON(self));
- /* deinit self */
- tdav_codec_h264_cisco_deinit(h264);
- }
-
- return self;
+{
+ tdav_codec_h264_cisco_t *h264 = (tdav_codec_h264_cisco_t*)self;
+ if (h264) {
+ /* deinit base */
+ tdav_codec_h264_common_deinit(TDAV_CODEC_H264_COMMON(self));
+ /* deinit self */
+ tdav_codec_h264_cisco_deinit(h264);
+ }
+
+ return self;
}
/* object definition */
-static const tsk_object_def_t tdav_codec_h264_cisco_base_def_s =
-{
- sizeof(tdav_codec_h264_cisco_t),
- tdav_codec_h264_cisco_base_ctor,
- tdav_codec_h264_cisco_base_dtor,
- tmedia_codec_cmp,
+static const tsk_object_def_t tdav_codec_h264_cisco_base_def_s = {
+ sizeof(tdav_codec_h264_cisco_t),
+ tdav_codec_h264_cisco_base_ctor,
+ tdav_codec_h264_cisco_base_dtor,
+ tmedia_codec_cmp,
};
/* plugin definition*/
-static const tmedia_codec_plugin_def_t tdav_codec_h264_cisco_base_plugin_def_s =
-{
- &tdav_codec_h264_cisco_base_def_s,
-
- tmedia_video,
- tmedia_codec_id_h264_bp,
- "H264",
- "H264 Base Profile (OpenH264)",
- TMEDIA_CODEC_FORMAT_H264_BP,
- tsk_true,
- 90000, // rate
-
- /* audio */
- { 0 },
-
- /* video (width, height, fps) */
- {176, 144, 0}, // fps is @deprecated
-
- tdav_codec_h264_cisco_set,
- tdav_codec_h264_cisco_open,
- tdav_codec_h264_cisco_close,
- tdav_codec_h264_cisco_encode,
- tdav_codec_h264_cisco_decode,
- tdav_codec_h264_cisco_sdp_att_match,
- tdav_codec_h264_cisco_sdp_att_get
+static const tmedia_codec_plugin_def_t tdav_codec_h264_cisco_base_plugin_def_s = {
+ &tdav_codec_h264_cisco_base_def_s,
+
+ tmedia_video,
+ tmedia_codec_id_h264_bp,
+ "H264",
+ "H264 Base Profile (OpenH264)",
+ TMEDIA_CODEC_FORMAT_H264_BP,
+ tsk_true,
+ 90000, // rate
+
+ /* audio */
+ { 0 },
+
+ /* video (width, height, fps) */
+ {176, 144, 0}, // fps is @deprecated
+
+ tdav_codec_h264_cisco_set,
+ tdav_codec_h264_cisco_open,
+ tdav_codec_h264_cisco_close,
+ tdav_codec_h264_cisco_encode,
+ tdav_codec_h264_cisco_decode,
+ tdav_codec_h264_cisco_sdp_att_match,
+ tdav_codec_h264_cisco_sdp_att_get
};
const tmedia_codec_plugin_def_t *tdav_codec_h264_cisco_base_plugin_def_t = &tdav_codec_h264_cisco_base_plugin_def_s;
@@ -611,117 +612,117 @@ const tmedia_codec_plugin_def_t *tdav_codec_h264_cisco_base_plugin_def_t = &tdav
static int tdav_codec_h264_cisco_open_encoder(tdav_codec_h264_cisco_t* self)
{
- int ret = -1, max_bitrate_bps;
- long err;
- SSpatialLayerConfig* layer;
-
- int32_t max_bw_kpbs;
- tdav_codec_h264_common_t* common = (tdav_codec_h264_common_t*)self;
-
- if (self->encoder.pInst) {
- TSK_DEBUG_ERROR("Encoder already initialized");
- goto bail;
- }
-
- // create encoder
- if ((err = WelsCreateSVCEncoder(&self->encoder.pInst)) != cmResultSuccess) {
- TSK_DEBUG_ERROR("Failed to create ancoder: %ld", err);
- goto bail;
- }
-
- self->encoder.pInst->SetOption(ENCODER_OPTION_TRACE_CALLBACK_CONTEXT, self);
- self->encoder.pInst->SetOption(ENCODER_OPTION_TRACE_CALLBACK, &__tdav_codec_h264_cisco_debug_cb);
-
- if ((err = self->encoder.pInst->GetDefaultParams(&self->encoder.sEncParam)) != cmResultSuccess) {
- TSK_DEBUG_ERROR("GetDefaultParams failed: %ld", err);
- goto bail;
- }
-
- self->encoder.neg_width = (self->encoder.rotation == 90 || self->encoder.rotation == 270) ? TMEDIA_CODEC_VIDEO(self)->out.height : TMEDIA_CODEC_VIDEO(self)->out.width;
- self->encoder.neg_height = (self->encoder.rotation == 90 || self->encoder.rotation == 270) ? TMEDIA_CODEC_VIDEO(self)->out.width : TMEDIA_CODEC_VIDEO(self)->out.height;
- self->encoder.neg_fps = TMEDIA_CODEC_VIDEO(self)->out.fps;
- max_bw_kpbs = TSK_CLAMP(
- 0,
- tmedia_get_video_bandwidth_kbps_2(self->encoder.neg_width, self->encoder.neg_height, self->encoder.neg_fps),
- TMEDIA_CODEC(self)->bandwidth_max_upload
- );
- max_bitrate_bps = (max_bw_kpbs * 1024);
-
- TSK_DEBUG_INFO("[H.264 OpenH264 Encoder] neg_width=%d, neg_height=%d, neg_fps=%d, max_bitrate_bps=%d",
- self->encoder.neg_width,
- self->encoder.neg_height,
- self->encoder.neg_fps,
- max_bitrate_bps
- );
-
- self->encoder.sEncParam.iInputCsp = videoFormatI420;
- self->encoder.sEncParam.iSpatialLayerNum = 1;
- self->encoder.sEncParam.iTemporalLayerNum = 1;
- self->encoder.sEncParam.uiIntraPeriod = (self->encoder.neg_fps * CISCO_H264_GOP_SIZE_IN_SECONDS);
- self->encoder.sEncParam.iUsageType = CAMERA_VIDEO_REAL_TIME; // TODO: use "SCREEN_CONTENT_REAL_TIME" screencast
- self->encoder.sEncParam.iPicWidth = self->encoder.neg_width;
- self->encoder.sEncParam.iPicHeight = self->encoder.neg_height;
- self->encoder.sEncParam.iTargetBitrate = max_bitrate_bps;
- self->encoder.sEncParam.iMaxBitrate = max_bitrate_bps;
- self->encoder.sEncParam.fMaxFrameRate = (float)self->encoder.neg_fps;
- self->encoder.sEncParam.uiMaxNalSize = H264_RTP_PAYLOAD_SIZE;
- self->encoder.sEncParam.bEnableSpsPpsIdAddition = true;
- self->encoder.sEncParam.bEnableFrameCroppingFlag = true;
-
- layer = &self->encoder.sEncParam.sSpatialLayers[0];
- layer->uiProfileIdc = PRO_BASELINE;
+ int ret = -1, max_bitrate_bps;
+ long err;
+ SSpatialLayerConfig* layer;
+
+ int32_t max_bw_kpbs;
+ tdav_codec_h264_common_t* common = (tdav_codec_h264_common_t*)self;
+
+ if (self->encoder.pInst) {
+ TSK_DEBUG_ERROR("Encoder already initialized");
+ goto bail;
+ }
+
+ // create encoder
+ if ((err = WelsCreateSVCEncoder(&self->encoder.pInst)) != cmResultSuccess) {
+ TSK_DEBUG_ERROR("Failed to create ancoder: %ld", err);
+ goto bail;
+ }
+
+ self->encoder.pInst->SetOption(ENCODER_OPTION_TRACE_CALLBACK_CONTEXT, self);
+ self->encoder.pInst->SetOption(ENCODER_OPTION_TRACE_CALLBACK, &__tdav_codec_h264_cisco_debug_cb);
+
+ if ((err = self->encoder.pInst->GetDefaultParams(&self->encoder.sEncParam)) != cmResultSuccess) {
+ TSK_DEBUG_ERROR("GetDefaultParams failed: %ld", err);
+ goto bail;
+ }
+
+ self->encoder.neg_width = (self->encoder.rotation == 90 || self->encoder.rotation == 270) ? TMEDIA_CODEC_VIDEO(self)->out.height : TMEDIA_CODEC_VIDEO(self)->out.width;
+ self->encoder.neg_height = (self->encoder.rotation == 90 || self->encoder.rotation == 270) ? TMEDIA_CODEC_VIDEO(self)->out.width : TMEDIA_CODEC_VIDEO(self)->out.height;
+ self->encoder.neg_fps = TMEDIA_CODEC_VIDEO(self)->out.fps;
+ max_bw_kpbs = TSK_CLAMP(
+ 0,
+ tmedia_get_video_bandwidth_kbps_2(self->encoder.neg_width, self->encoder.neg_height, self->encoder.neg_fps),
+ TMEDIA_CODEC(self)->bandwidth_max_upload
+ );
+ max_bitrate_bps = (max_bw_kpbs * 1024);
+
+ TSK_DEBUG_INFO("[H.264 OpenH264 Encoder] neg_width=%d, neg_height=%d, neg_fps=%d, max_bitrate_bps=%d",
+ self->encoder.neg_width,
+ self->encoder.neg_height,
+ self->encoder.neg_fps,
+ max_bitrate_bps
+ );
+
+ self->encoder.sEncParam.iInputCsp = videoFormatI420;
+ self->encoder.sEncParam.iSpatialLayerNum = 1;
+ self->encoder.sEncParam.iTemporalLayerNum = 1;
+ self->encoder.sEncParam.uiIntraPeriod = (self->encoder.neg_fps * CISCO_H264_GOP_SIZE_IN_SECONDS);
+ self->encoder.sEncParam.iUsageType = CAMERA_VIDEO_REAL_TIME; // TODO: use "SCREEN_CONTENT_REAL_TIME" screencast
+ self->encoder.sEncParam.iPicWidth = self->encoder.neg_width;
+ self->encoder.sEncParam.iPicHeight = self->encoder.neg_height;
+ self->encoder.sEncParam.iTargetBitrate = max_bitrate_bps;
+ self->encoder.sEncParam.iMaxBitrate = max_bitrate_bps;
+ self->encoder.sEncParam.fMaxFrameRate = (float)self->encoder.neg_fps;
+ self->encoder.sEncParam.uiMaxNalSize = H264_RTP_PAYLOAD_SIZE;
+ self->encoder.sEncParam.bEnableSpsPpsIdAddition = true;
+ self->encoder.sEncParam.bEnableFrameCroppingFlag = true;
+
+ layer = &self->encoder.sEncParam.sSpatialLayers[0];
+ layer->uiProfileIdc = PRO_BASELINE;
#if BUILD_TYPE_TCH
- layer->uiLevelIdc = tdav_codec_h264_cisco_convert_level(common->level);
+ layer->uiLevelIdc = tdav_codec_h264_cisco_convert_level(common->level);
#else
- layer->uiLevelIdc = LEVEL_UNKNOWN; // auto-detect
+ layer->uiLevelIdc = LEVEL_UNKNOWN; // auto-detect
#endif
- layer->fFrameRate = self->encoder.sEncParam.fMaxFrameRate;
- layer->iMaxSpatialBitrate = self->encoder.sEncParam.iMaxBitrate;
- layer->iSpatialBitrate = self->encoder.sEncParam.iTargetBitrate;
- layer->iVideoWidth = self->encoder.sEncParam.iPicWidth;
- layer->iVideoHeight = self->encoder.sEncParam.iPicHeight;
- layer->sSliceCfg.uiSliceMode = SM_DYN_SLICE;
- layer->sSliceCfg.sSliceArgument.uiSliceSizeConstraint = H264_RTP_PAYLOAD_SIZE;
- layer->sSliceCfg.sSliceArgument.uiSliceNum = 1;
+ layer->fFrameRate = self->encoder.sEncParam.fMaxFrameRate;
+ layer->iMaxSpatialBitrate = self->encoder.sEncParam.iMaxBitrate;
+ layer->iSpatialBitrate = self->encoder.sEncParam.iTargetBitrate;
+ layer->iVideoWidth = self->encoder.sEncParam.iPicWidth;
+ layer->iVideoHeight = self->encoder.sEncParam.iPicHeight;
+ layer->sSliceCfg.uiSliceMode = SM_DYN_SLICE;
+ layer->sSliceCfg.sSliceArgument.uiSliceSizeConstraint = H264_RTP_PAYLOAD_SIZE;
+ layer->sSliceCfg.sSliceArgument.uiSliceNum = 1;
//layer->sSliceCfg.sSliceArgument.uiSliceMbNum[0] = 960;
- if ((err = self->encoder.pInst->InitializeExt(&self->encoder.sEncParam)) != cmResultSuccess) {
- TSK_DEBUG_ERROR("InitializeExt failed: %ld", err);
- goto bail;
- }
-
- self->encoder.sEncPic.iColorFormat = videoFormatI420;
- self->encoder.sEncPic.iPicWidth = self->encoder.sEncParam.iPicWidth;
- self->encoder.sEncPic.iPicHeight = self->encoder.sEncParam.iPicHeight;
- self->encoder.sEncPic.iStride[0] = self->encoder.sEncPic.iPicWidth;
- self->encoder.sEncPic.iStride[1] = self->encoder.sEncPic.iStride[0] >> 1;
- self->encoder.sEncPic.iStride[2] = self->encoder.sEncPic.iStride[1];
-
+ if ((err = self->encoder.pInst->InitializeExt(&self->encoder.sEncParam)) != cmResultSuccess) {
+ TSK_DEBUG_ERROR("InitializeExt failed: %ld", err);
+ goto bail;
+ }
+
+ self->encoder.sEncPic.iColorFormat = videoFormatI420;
+ self->encoder.sEncPic.iPicWidth = self->encoder.sEncParam.iPicWidth;
+ self->encoder.sEncPic.iPicHeight = self->encoder.sEncParam.iPicHeight;
+ self->encoder.sEncPic.iStride[0] = self->encoder.sEncPic.iPicWidth;
+ self->encoder.sEncPic.iStride[1] = self->encoder.sEncPic.iStride[0] >> 1;
+ self->encoder.sEncPic.iStride[2] = self->encoder.sEncPic.iStride[1];
+
// Create encoder mutex
if (!self->encoder.mutex && !(self->encoder.mutex = tsk_mutex_create())) {
TSK_DEBUG_ERROR("Failed to create mutex for the encoder");
goto bail;
}
-
+
self->encoder.frame_count = 0;
- ret = 0;
+ ret = 0;
bail:
- return ret;
+ return ret;
}
static int tdav_codec_h264_cisco_close_encoder(tdav_codec_h264_cisco_t* self, tsk_bool_t reset_rotation)
{
- if (self) {
- if (self->encoder.pInst) {
- self->encoder.pInst->Uninitialize();
- WelsDestroySVCEncoder(self->encoder.pInst);
- self->encoder.pInst = NULL;
- }
- if (self->encoder.buffer) {
- TSK_FREE(self->encoder.buffer);
- }
+ if (self) {
+ if (self->encoder.pInst) {
+ self->encoder.pInst->Uninitialize();
+ WelsDestroySVCEncoder(self->encoder.pInst);
+ self->encoder.pInst = NULL;
+ }
+ if (self->encoder.buffer) {
+ TSK_FREE(self->encoder.buffer);
+ }
if (self->encoder.mutex) {
tsk_mutex_destroy(&self->encoder.mutex);
}
@@ -729,154 +730,172 @@ static int tdav_codec_h264_cisco_close_encoder(tdav_codec_h264_cisco_t* self, ts
if (reset_rotation) {
self->encoder.rotation = 0; // reset rotation
}
- }
- return 0;
+ }
+ return 0;
}
int tdav_codec_h264_cisco_open_decoder(tdav_codec_h264_cisco_t* self)
{
- int ret = -1;
- long err;
- tdav_codec_h264_common_t* common = (tdav_codec_h264_common_t*)self;
- SDecodingParam sDecParam = { 0 };
-
- if (self->decoder.pInst) {
- TSK_DEBUG_ERROR("Decoder already initialized");
- goto bail;
- }
-
- // create decoder
- if ((err = WelsCreateDecoder(&self->decoder.pInst)) != cmResultSuccess) {
- TSK_DEBUG_ERROR("Failed to create decoder: %ld", err);
- goto bail;
- }
- self->decoder.pInst->SetOption(DECODER_OPTION_TRACE_CALLBACK_CONTEXT, self);
- self->decoder.pInst->SetOption(DECODER_OPTION_TRACE_CALLBACK, &__tdav_codec_h264_cisco_debug_cb);
-
- // initialize decoder
- sDecParam.iOutputColorFormat = videoFormatI420;
- sDecParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_AVC;
- if ((err = self->decoder.pInst->Initialize(&sDecParam)) != cmResultSuccess) {
- TSK_DEBUG_ERROR("Failed to initialize decoder: %ld", err);
- goto bail;
- }
+ int ret = -1;
+ long err;
+ tdav_codec_h264_common_t* common = (tdav_codec_h264_common_t*)self;
+ SDecodingParam sDecParam = { 0 };
+
+ if (self->decoder.pInst) {
+ TSK_DEBUG_ERROR("Decoder already initialized");
+ goto bail;
+ }
+
+ // create decoder
+ if ((err = WelsCreateDecoder(&self->decoder.pInst)) != cmResultSuccess) {
+ TSK_DEBUG_ERROR("Failed to create decoder: %ld", err);
+ goto bail;
+ }
+ self->decoder.pInst->SetOption(DECODER_OPTION_TRACE_CALLBACK_CONTEXT, self);
+ self->decoder.pInst->SetOption(DECODER_OPTION_TRACE_CALLBACK, &__tdav_codec_h264_cisco_debug_cb);
+
+ // initialize decoder
+ sDecParam.iOutputColorFormat = videoFormatI420;
+ sDecParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_AVC;
+ if ((err = self->decoder.pInst->Initialize(&sDecParam)) != cmResultSuccess) {
+ TSK_DEBUG_ERROR("Failed to initialize decoder: %ld", err);
+ goto bail;
+ }
self->decoder.last_seq = 0;
- TSK_DEBUG_INFO("[OpenH264 Decoder] neg_width=%d, neg_height=%d, neg_fps=%d",
- TMEDIA_CODEC_VIDEO(self)->in.width,
- TMEDIA_CODEC_VIDEO(self)->in.height,
- TMEDIA_CODEC_VIDEO(self)->in.fps
- );
- ret = 0;
+ TSK_DEBUG_INFO("[OpenH264 Decoder] neg_width=%d, neg_height=%d, neg_fps=%d",
+ TMEDIA_CODEC_VIDEO(self)->in.width,
+ TMEDIA_CODEC_VIDEO(self)->in.height,
+ TMEDIA_CODEC_VIDEO(self)->in.fps
+ );
+ ret = 0;
bail:
- return ret;
+ return ret;
}
static int tdav_codec_h264_cisco_close_decoder(tdav_codec_h264_cisco_t* self)
{
- if (self) {
- if (self->decoder.pInst) {
- self->decoder.pInst->Uninitialize();
- WelsDestroyDecoder(self->decoder.pInst);
- self->decoder.pInst = NULL;
- }
- TSK_FREE(self->decoder.accumulator);
- self->decoder.accumulator_pos = 0;
- }
-
- return 0;
+ if (self) {
+ if (self->decoder.pInst) {
+ self->decoder.pInst->Uninitialize();
+ WelsDestroyDecoder(self->decoder.pInst);
+ self->decoder.pInst = NULL;
+ }
+ TSK_FREE(self->decoder.accumulator);
+ self->decoder.accumulator_pos = 0;
+ }
+
+ return 0;
}
static ELevelIdc tdav_codec_h264_cisco_convert_level(enum level_idc_e level)
{
- switch(level) {
- case level_idc_1_0: return LEVEL_1_0;
- case level_idc_1_b: return LEVEL_1_B;
- case level_idc_1_1: return LEVEL_1_1;
- case level_idc_1_2: return LEVEL_1_2;
- case level_idc_1_3: return LEVEL_1_3;
- case level_idc_2_0: return LEVEL_2_0;
- case level_idc_2_1: return LEVEL_2_1;
- case level_idc_2_2: return LEVEL_2_2;
- case level_idc_3_0: return LEVEL_3_0;
- case level_idc_3_1: return LEVEL_3_1;
- case level_idc_3_2: return LEVEL_3_2;
- case level_idc_4_0: return LEVEL_4_0;
- case level_idc_4_1: return LEVEL_4_1;
- case level_idc_4_2: return LEVEL_4_2;
- case level_idc_5_0: return LEVEL_5_0;
- case level_idc_5_1: return LEVEL_5_1;
- case level_idc_5_2: return LEVEL_2_2;
- default: return LEVEL_UNKNOWN;
- }
+ switch(level) {
+ case level_idc_1_0:
+ return LEVEL_1_0;
+ case level_idc_1_b:
+ return LEVEL_1_B;
+ case level_idc_1_1:
+ return LEVEL_1_1;
+ case level_idc_1_2:
+ return LEVEL_1_2;
+ case level_idc_1_3:
+ return LEVEL_1_3;
+ case level_idc_2_0:
+ return LEVEL_2_0;
+ case level_idc_2_1:
+ return LEVEL_2_1;
+ case level_idc_2_2:
+ return LEVEL_2_2;
+ case level_idc_3_0:
+ return LEVEL_3_0;
+ case level_idc_3_1:
+ return LEVEL_3_1;
+ case level_idc_3_2:
+ return LEVEL_3_2;
+ case level_idc_4_0:
+ return LEVEL_4_0;
+ case level_idc_4_1:
+ return LEVEL_4_1;
+ case level_idc_4_2:
+ return LEVEL_4_2;
+ case level_idc_5_0:
+ return LEVEL_5_0;
+ case level_idc_5_1:
+ return LEVEL_5_1;
+ case level_idc_5_2:
+ return LEVEL_2_2;
+ default:
+ return LEVEL_UNKNOWN;
+ }
}
static void tdav_codec_h264_cisco_debug_cb(void* context, int level, const char* message)
{
- switch (level) {
- case WELS_LOG_ERROR:
- case WELS_LOG_QUIET:
- TSK_DEBUG_ERROR("OpenH264: level=%d, message=%s", level, message);
- break;
- case WELS_LOG_WARNING:
- TSK_DEBUG_WARN("OpenH264: level=%d, message=%s", level, message);
- break;
- default:
- TSK_DEBUG_INFO("OpenH264: level=%d, message=%s", level, message);
- break;
- }
+ switch (level) {
+ case WELS_LOG_ERROR:
+ case WELS_LOG_QUIET:
+ TSK_DEBUG_ERROR("OpenH264: level=%d, message=%s", level, message);
+ break;
+ case WELS_LOG_WARNING:
+ TSK_DEBUG_WARN("OpenH264: level=%d, message=%s", level, message);
+ break;
+ default:
+ TSK_DEBUG_INFO("OpenH264: level=%d, message=%s", level, message);
+ break;
+ }
}
static int tdav_codec_h264_cisco_init(tdav_codec_h264_cisco_t* self, profile_idc_t profile)
{
- int ret = -1;
- level_idc_t level;
- tdav_codec_h264_common_t* common = (tdav_codec_h264_common_t*)self;
-
- if (!self || profile != profile_idc_baseline) {
- TSK_DEBUG_ERROR("Invalid parameter");
- goto bail;
- }
-
- if ((ret = tdav_codec_h264_common_init(common))) {
- TSK_DEBUG_ERROR("tdav_codec_h264_cisco_common_init() faile with error code=%d", ret);
- goto bail;
- }
-
- if ((ret = tdav_codec_h264_common_level_from_size(TMEDIA_CODEC_VIDEO(self)->out.width, TMEDIA_CODEC_VIDEO(self)->out.height, &level))) {
- TSK_DEBUG_ERROR("Failed to find level for size=[%u, %u]", TMEDIA_CODEC_VIDEO(self)->out.width, TMEDIA_CODEC_VIDEO(self)->out.height);
- goto bail;
- }
-
- common->pack_mode_local = H264_PACKETIZATION_MODE;
- common->profile = profile;
- common->level = level;
- // A.2.1.1 Constrained Baseline profile
- // Conformance of a bitstream to the Constrained Baseline profile is indicated by profile_idc being equal to 66 with
- // constraint_set1_flag being equal to 1.
- common->profile_iop = 0xe0; // "constraint_set0_flag=1 and constraint_set1_flag=1" -> Constrained Baseline profile
- TMEDIA_CODEC_VIDEO(self)->in.max_mbps = TMEDIA_CODEC_VIDEO(self)->out.max_mbps = H264_MAX_MBPS*1000;
- TMEDIA_CODEC_VIDEO(self)->in.max_br = TMEDIA_CODEC_VIDEO(self)->out.max_br = H264_MAX_BR*1000;
-
- TMEDIA_CODEC_VIDEO(self)->in.chroma = tmedia_chroma_yuv420p;
- TMEDIA_CODEC_VIDEO(self)->out.chroma = tmedia_chroma_yuv420p;
-
- ret = 0;
+ int ret = -1;
+ level_idc_t level;
+ tdav_codec_h264_common_t* common = (tdav_codec_h264_common_t*)self;
+
+ if (!self || profile != profile_idc_baseline) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ goto bail;
+ }
+
+ if ((ret = tdav_codec_h264_common_init(common))) {
+ TSK_DEBUG_ERROR("tdav_codec_h264_cisco_common_init() faile with error code=%d", ret);
+ goto bail;
+ }
+
+ if ((ret = tdav_codec_h264_common_level_from_size(TMEDIA_CODEC_VIDEO(self)->out.width, TMEDIA_CODEC_VIDEO(self)->out.height, &level))) {
+ TSK_DEBUG_ERROR("Failed to find level for size=[%u, %u]", TMEDIA_CODEC_VIDEO(self)->out.width, TMEDIA_CODEC_VIDEO(self)->out.height);
+ goto bail;
+ }
+
+ common->pack_mode_local = H264_PACKETIZATION_MODE;
+ common->profile = profile;
+ common->level = level;
+ // A.2.1.1 Constrained Baseline profile
+ // Conformance of a bitstream to the Constrained Baseline profile is indicated by profile_idc being equal to 66 with
+ // constraint_set1_flag being equal to 1.
+ common->profile_iop = 0xe0; // "constraint_set0_flag=1 and constraint_set1_flag=1" -> Constrained Baseline profile
+ TMEDIA_CODEC_VIDEO(self)->in.max_mbps = TMEDIA_CODEC_VIDEO(self)->out.max_mbps = H264_MAX_MBPS*1000;
+ TMEDIA_CODEC_VIDEO(self)->in.max_br = TMEDIA_CODEC_VIDEO(self)->out.max_br = H264_MAX_BR*1000;
+
+ TMEDIA_CODEC_VIDEO(self)->in.chroma = tmedia_chroma_yuv420p;
+ TMEDIA_CODEC_VIDEO(self)->out.chroma = tmedia_chroma_yuv420p;
+
+ ret = 0;
bail:
- return ret;
+ return ret;
}
static int tdav_codec_h264_cisco_deinit(tdav_codec_h264_cisco_t* self)
{
- if (!self) {
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- tdav_codec_h264_cisco_close((tmedia_codec_t*)self);
-
- return 0;
+ if (!self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ tdav_codec_h264_cisco_close((tmedia_codec_t*)self);
+
+ return 0;
}
#endif /* HAVE_OPENH264 */
diff --git a/tinyDAV/src/codecs/h264/tdav_codec_h264_cuda.cxx b/tinyDAV/src/codecs/h264/tdav_codec_h264_cuda.cxx
index f9fbc11..c677550 100755
--- a/tinyDAV/src/codecs/h264/tdav_codec_h264_cuda.cxx
+++ b/tinyDAV/src/codecs/h264/tdav_codec_h264_cuda.cxx
@@ -2,19 +2,19 @@
* 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.
*
@@ -26,7 +26,7 @@
* http://developer.download.nvidia.com/compute/DevZone/docs/html/C/doc/CUDA_VideoDecoder_Library.pdf
* http://developer.download.nvidia.com/compute/DevZone/docs/html/C/doc/CUDA_VideoEncoder_Library.pdf
* 2.0: https://developer.nvidia.com/sites/default/files/akamai/cuda/files/CUDADownloads/NVENC_VideoEncoder_API_ProgGuide.pdf
- *
+ *
* RTP payloader/depayloader follows RFC 3984.
*
* @author Mamadou Diop <diopmamadou(at)doubango(DOT)org>
@@ -50,7 +50,7 @@
#include "tsk_memory.h"
#include "tsk_debug.h"
-#include <cutil_inline.h>
+#include <cutil_inline.h>
#include <cuda.h>
#define tdav_codec_h264_cuda_fmtp_set tsk_null
@@ -89,217 +89,295 @@ static inline tsk_size_t _tdav_codec_h264_cuda_pict_layout(tdav_codec_h264_cuda_
static int tdav_codec_h264_cuda_open(tmedia_codec_t* self)
{
- int ret = 0, i;
- int bestGPU = 0, gpuPerf = 0, adapterCount;
- static int low_latency = 1;
- HRESULT hr;
- CUresult cuResult;
- D3DPRESENT_PARAMETERS d3dpp;
- tdav_codec_h264_cuda_t* h264 = (tdav_codec_h264_cuda_t*)self;
-
- if(!h264){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- //
- // encoder
- //
- memset(&h264->encoder.clb_params, 0, sizeof(h264->encoder.clb_params));
- memset(&h264->encoder.ctx_params, 0, sizeof(h264->encoder.ctx_params));
-
- h264->encoder.ctx_params.iInputSize[0] = TMEDIA_CODEC_VIDEO(h264)->out.width;
- h264->encoder.ctx_params.iInputSize[1] = TMEDIA_CODEC_VIDEO(h264)->out.height;
- h264->encoder.ctx_params.iOutputSize[0] = TMEDIA_CODEC_VIDEO(h264)->out.width;
- h264->encoder.ctx_params.iOutputSize[1] = TMEDIA_CODEC_VIDEO(h264)->out.height;
- h264->encoder.ctx_params.GPUOffloadLevel= NVVE_GPU_OFFLOAD_DEFAULT;
- h264->encoder.ctx_params.iSurfaceFormat = (int)IYUV;
- h264->encoder.ctx_params.iPictureType = (int)FRAME_PICTURE;
- h264->encoder.ctx_params.Fieldmode = MODE_FRAME;
- h264->encoder.ctx_params.Presets = (NVVE_PRESETS_TARGET)-1;//Should be iPod, Zune ...
- h264->encoder.ctx_params.iP_Interval = 1;
- h264->encoder.ctx_params.iAspectRatio[0] = 4;
- h264->encoder.ctx_params.iAspectRatio[1] = 3;
- h264->encoder.ctx_params.iAspectRatio[2] = 0;
- h264->encoder.ctx_params.iIDR_Period = TMEDIA_CODEC_VIDEO(h264)->out.fps * 3;
- h264->encoder.ctx_params.iUseDeviceMem = 0;
- h264->encoder.ctx_params.iDynamicGOP = 0;
- h264->encoder.ctx_params.RCType = RC_VBR;
- h264->encoder.ctx_params.iAvgBitrate = 400000;
- h264->encoder.ctx_params.iPeakBitrate = 800000;
- h264->encoder.ctx_params.iQP_Level_Intra = 25;
- h264->encoder.ctx_params.iQP_Level_InterP = 28;
- h264->encoder.ctx_params.iQP_Level_InterB = 31;
- h264->encoder.ctx_params.iFrameRate[0] = TMEDIA_CODEC_VIDEO(h264)->out.fps * 1000;
- h264->encoder.ctx_params.iFrameRate[1] = 1000;
- h264->encoder.ctx_params.iDeblockMode = 1;
- h264->encoder.ctx_params.iForceIntra = 0;
- h264->encoder.ctx_params.iForceIDR = 0;
- h264->encoder.ctx_params.iClearStat = 0;
- h264->encoder.ctx_params.DIMode = DI_MEDIAN;
- h264->encoder.ctx_params.iDisableSPSPPS = 1; // Do not include SPS/PPS frames
- h264->encoder.ctx_params.iNaluFramingType = 0; // StartCodes
- h264->encoder.ctx_params.iMultiGPU = 1;
- switch(TDAV_CODEC_H264_COMMON(h264)->profile){
- case tdav_codec_h264_bp10:
- h264->encoder.ctx_params.iDisableCabac = 1;
- h264->encoder.ctx_params.iProfileLevel = 0xff42;
- break;
- case tdav_codec_h264_bp20:
- h264->encoder.ctx_params.iDisableCabac = 1;
- h264->encoder.ctx_params.iProfileLevel = 0xff42;
- break;
- case tdav_codec_h264_bp30:
- h264->encoder.ctx_params.iDisableCabac = 1;
- h264->encoder.ctx_params.iProfileLevel = 0xff42;
- break;
- default:
- break;
- }
-
- hr = NVCreateEncoder(&h264->encoder.context);
- if(FAILED(hr)){
- TSK_DEBUG_ERROR("NVCreateEncoder failed with error code = %08x", hr);
- return -2;
- }
-
- hr = NVSetCodec(h264->encoder.context, NV_CODEC_TYPE_H264);
- if(FAILED(hr)){
- TSK_DEBUG_ERROR("NVSetCodec failed with error code = %08x", hr);
- return -2;
- }
-
- hr = NVSetDefaultParam(h264->encoder.context);
- if(FAILED(hr)){
- TSK_DEBUG_ERROR("NVSetDefaultParam() failed with error code = %08x", hr);
- return -2;
- }
-
- hr = NVGetParamValue(h264->encoder.context, NVVE_GET_GPU_COUNT, &h264->encoder.ctx_params.GPU_count);
- if(SUCCEEDED(hr)){
- int temp = 0, deviceCount;
- for (deviceCount=0; deviceCount < h264->encoder.ctx_params.GPU_count; deviceCount++) {
- NVVE_GPUAttributes GPUAttributes = {0};
-
- GPUAttributes.iGpuOrdinal = deviceCount;
- hr = NVGetParamValue(h264->encoder.context, NVVE_GET_GPU_ATTRIBUTES, &GPUAttributes);
- if(FAILED(hr)){
- TSK_DEBUG_ERROR("NVGetParamValue(NVVE_GET_GPU_ATTRIBUTES) failed with error code = %08x", hr);
- continue;
- }
-
- temp = GPUAttributes.iClockRate * GPUAttributes.iMultiProcessorCount;
- temp = temp * _ConvertSMVer2Cores(GPUAttributes.iMajor, GPUAttributes.iMinor);
-
- if(temp > gpuPerf){
- gpuPerf = temp;
- bestGPU = deviceCount;
- }
- }
- }
- else{
- TSK_DEBUG_ERROR("NVGetParamValue(NVVE_GET_GPU_COUNT) failed with error code = %08x", hr);
- return -2;
- }
-
- h264->encoder.ctx_params.iForcedGPU = bestGPU;
- hr = NVSetParamValue(h264->encoder.context, NVVE_FORCE_GPU_SELECTION, &h264->encoder.ctx_params.iForcedGPU);
- if(FAILED(hr)){
- TSK_DEBUG_WARN("NVSetParamValue(NVVE_FORCE_GPU_SELECTION) failed with error code = %08x", hr);
- }
-
- hr = NVSetParamValue(h264->encoder.context, NVVE_DEVICE_MEMORY_INPUT, &(h264->encoder.ctx_params.iUseDeviceMem));
- if(FAILED(hr)){
- TSK_DEBUG_ERROR("NVSetParamValue(NVVE_OUT_SIZE) failed with error code = %08x", hr);
- return -2;
- }
-
- h264->encoder.buffer_size = (h264->encoder.ctx_params.iOutputSize[1] * h264->encoder.ctx_params.iOutputSize[0] * 3) >> 4;
- if(!h264->encoder.buffer && !(h264->encoder.buffer = tsk_realloc(h264->encoder.buffer, h264->encoder.buffer_size))){
- TSK_DEBUG_ERROR("Failed to allocate buffer with size=%u", h264->encoder.buffer_size);
- h264->encoder.buffer_size = 0;
- return -2;
- }
-
- hr = NVSetParamValue(h264->encoder.context,NVVE_OUT_SIZE, &(h264->encoder.ctx_params.iOutputSize)); if (hr!=S_OK) { TSK_DEBUG_WARN("NVSetParamValue(NVVE_OUT_SIZE) failed with error code = %08x", hr); }
- hr = NVSetParamValue(h264->encoder.context,NVVE_IN_SIZE, &(h264->encoder.ctx_params.iInputSize)); if (hr!=S_OK) { TSK_DEBUG_WARN("NVSetParamValue(NVVE_IN_SIZE) failed with error code = %08x", hr); }
- hr = NVSetParamValue(h264->encoder.context,NVVE_MULTI_GPU, &(h264->encoder.ctx_params.iMultiGPU)); if (hr!=S_OK) { TSK_DEBUG_WARN("NVSetParamValue(NVVE_MULTI_GPU) failed with error code = %08x", hr); }
- hr = NVSetParamValue(h264->encoder.context,NVVE_ASPECT_RATIO, &(h264->encoder.ctx_params.iAspectRatio));if (hr!=S_OK) { TSK_DEBUG_WARN("NVSetParamValue(NVVE_ASPECT_RATIO) failed with error code = %08x", hr); }
- hr = NVSetParamValue(h264->encoder.context,NVVE_FIELD_ENC_MODE, &(h264->encoder.ctx_params.Fieldmode)); if (hr!=S_OK) { TSK_DEBUG_WARN("NVSetParamValue(NVVE_FIELD_ENC_MODE) failed with error code = %08x", hr); }
- hr = NVSetParamValue(h264->encoder.context,NVVE_P_INTERVAL, &(h264->encoder.ctx_params.iP_Interval)); if (hr!=S_OK) { TSK_DEBUG_WARN("NVSetParamValue(NVVE_P_INTERVAL) failed with error code = %08x", hr); }
- hr = NVSetParamValue(h264->encoder.context,NVVE_IDR_PERIOD, &(h264->encoder.ctx_params.iIDR_Period)); if (hr!=S_OK) { TSK_DEBUG_WARN("NVSetParamValue(NVVE_IDR_PERIOD) failed with error code = %08x", hr); }
- hr = NVSetParamValue(h264->encoder.context,NVVE_DYNAMIC_GOP, &(h264->encoder.ctx_params.iDynamicGOP)); if (hr!=S_OK) { TSK_DEBUG_WARN("NVSetParamValue(NVVE_DYNAMIC_GOP) failed with error code = %08x", hr); }
- hr = NVSetParamValue(h264->encoder.context,NVVE_RC_TYPE, &(h264->encoder.ctx_params.RCType)); if (hr!=S_OK) { TSK_DEBUG_WARN("NVSetParamValue(NVVE_RC_TYPE) failed with error code = %08x", hr); }
- hr = NVSetParamValue(h264->encoder.context,NVVE_AVG_BITRATE, &(h264->encoder.ctx_params.iAvgBitrate)); if (hr!=S_OK) { TSK_DEBUG_WARN("NVSetParamValue(NVVE_AVG_BITRATE) failed with error code = %08x", hr); }
- hr = NVSetParamValue(h264->encoder.context,NVVE_PEAK_BITRATE, &(h264->encoder.ctx_params.iPeakBitrate)); if (hr!=S_OK) { TSK_DEBUG_WARN("NVSetParamValue(NVVE_PEAK_BITRATE) failed with error code = %08x", hr); }
- hr = NVSetParamValue(h264->encoder.context,NVVE_QP_LEVEL_INTRA, &(h264->encoder.ctx_params.iQP_Level_Intra)); if (hr!=S_OK) { TSK_DEBUG_WARN("NVSetParamValue(NVVE_OUT_SIZE) failed with error code = %08x", hr); }
- hr = NVSetParamValue(h264->encoder.context,NVVE_QP_LEVEL_INTER_P,&(h264->encoder.ctx_params.iQP_Level_InterP)); if (hr!=S_OK) { TSK_DEBUG_WARN("NVSetParamValue(NVVE_QP_LEVEL_INTER_P) failed with error code = %08x", hr); }
- hr = NVSetParamValue(h264->encoder.context,NVVE_QP_LEVEL_INTER_B,&(h264->encoder.ctx_params.iQP_Level_InterB)); if (hr!=S_OK) { TSK_DEBUG_WARN("NVSetParamValue(NVVE_QP_LEVEL_INTER_B) failed with error code = %08x", hr); }
- hr = NVSetParamValue(h264->encoder.context,NVVE_FRAME_RATE, &(h264->encoder.ctx_params.iFrameRate)); if (hr!=S_OK) { TSK_DEBUG_WARN("NVSetParamValue(NVVE_FRAME_RATE) failed with error code = %08x", hr); }
- hr = NVSetParamValue(h264->encoder.context,NVVE_DEBLOCK_MODE, &(h264->encoder.ctx_params.iDeblockMode)); if (hr!=S_OK) { TSK_DEBUG_WARN("NVSetParamValue(NVVE_DEBLOCK_MODE) failed with error code = %08x", hr); }
- hr = NVSetParamValue(h264->encoder.context,NVVE_PROFILE_LEVEL, &(h264->encoder.ctx_params.iProfileLevel)); if (hr!=S_OK) { TSK_DEBUG_WARN("NVSetParamValue(NVVE_PROFILE_LEVEL) failed with error code = %08x", hr); }
- hr = NVSetParamValue(h264->encoder.context,NVVE_FORCE_INTRA, &(h264->encoder.ctx_params.iForceIntra)); if (hr!=S_OK) { TSK_DEBUG_WARN("NVSetParamValue(NVVE_FORCE_INTRA) failed with error code = %08x", hr); }
- hr = NVSetParamValue(h264->encoder.context,NVVE_FORCE_IDR, &(h264->encoder.ctx_params.iForceIDR)); if (hr!=S_OK) { TSK_DEBUG_WARN("NVSetParamValue(NVVE_FORCE_IDR) failed with error code = %08x", hr); }
- hr = NVSetParamValue(h264->encoder.context,NVVE_CLEAR_STAT, &(h264->encoder.ctx_params.iClearStat)); if (hr!=S_OK) { TSK_DEBUG_WARN("NVSetParamValue(NVVE_CLEAR_STAT) failed with error code = %08x", hr); }
- hr = NVSetParamValue(h264->encoder.context,NVVE_SET_DEINTERLACE,&(h264->encoder.ctx_params.DIMode)); if (hr!=S_OK) { TSK_DEBUG_WARN("NVSetParamValue(NVVE_SET_DEINTERLACE) failed with error code = %08x", hr); }
+ int ret = 0, i;
+ int bestGPU = 0, gpuPerf = 0, adapterCount;
+ static int low_latency = 1;
+ HRESULT hr;
+ CUresult cuResult;
+ D3DPRESENT_PARAMETERS d3dpp;
+ tdav_codec_h264_cuda_t* h264 = (tdav_codec_h264_cuda_t*)self;
+
+ if(!h264) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ //
+ // encoder
+ //
+ memset(&h264->encoder.clb_params, 0, sizeof(h264->encoder.clb_params));
+ memset(&h264->encoder.ctx_params, 0, sizeof(h264->encoder.ctx_params));
+
+ h264->encoder.ctx_params.iInputSize[0] = TMEDIA_CODEC_VIDEO(h264)->out.width;
+ h264->encoder.ctx_params.iInputSize[1] = TMEDIA_CODEC_VIDEO(h264)->out.height;
+ h264->encoder.ctx_params.iOutputSize[0] = TMEDIA_CODEC_VIDEO(h264)->out.width;
+ h264->encoder.ctx_params.iOutputSize[1] = TMEDIA_CODEC_VIDEO(h264)->out.height;
+ h264->encoder.ctx_params.GPUOffloadLevel= NVVE_GPU_OFFLOAD_DEFAULT;
+ h264->encoder.ctx_params.iSurfaceFormat = (int)IYUV;
+ h264->encoder.ctx_params.iPictureType = (int)FRAME_PICTURE;
+ h264->encoder.ctx_params.Fieldmode = MODE_FRAME;
+ h264->encoder.ctx_params.Presets = (NVVE_PRESETS_TARGET)-1;//Should be iPod, Zune ...
+ h264->encoder.ctx_params.iP_Interval = 1;
+ h264->encoder.ctx_params.iAspectRatio[0] = 4;
+ h264->encoder.ctx_params.iAspectRatio[1] = 3;
+ h264->encoder.ctx_params.iAspectRatio[2] = 0;
+ h264->encoder.ctx_params.iIDR_Period = TMEDIA_CODEC_VIDEO(h264)->out.fps * 3;
+ h264->encoder.ctx_params.iUseDeviceMem = 0;
+ h264->encoder.ctx_params.iDynamicGOP = 0;
+ h264->encoder.ctx_params.RCType = RC_VBR;
+ h264->encoder.ctx_params.iAvgBitrate = 400000;
+ h264->encoder.ctx_params.iPeakBitrate = 800000;
+ h264->encoder.ctx_params.iQP_Level_Intra = 25;
+ h264->encoder.ctx_params.iQP_Level_InterP = 28;
+ h264->encoder.ctx_params.iQP_Level_InterB = 31;
+ h264->encoder.ctx_params.iFrameRate[0] = TMEDIA_CODEC_VIDEO(h264)->out.fps * 1000;
+ h264->encoder.ctx_params.iFrameRate[1] = 1000;
+ h264->encoder.ctx_params.iDeblockMode = 1;
+ h264->encoder.ctx_params.iForceIntra = 0;
+ h264->encoder.ctx_params.iForceIDR = 0;
+ h264->encoder.ctx_params.iClearStat = 0;
+ h264->encoder.ctx_params.DIMode = DI_MEDIAN;
+ h264->encoder.ctx_params.iDisableSPSPPS = 1; // Do not include SPS/PPS frames
+ h264->encoder.ctx_params.iNaluFramingType = 0; // StartCodes
+ h264->encoder.ctx_params.iMultiGPU = 1;
+ switch(TDAV_CODEC_H264_COMMON(h264)->profile) {
+ case tdav_codec_h264_bp10:
+ h264->encoder.ctx_params.iDisableCabac = 1;
+ h264->encoder.ctx_params.iProfileLevel = 0xff42;
+ break;
+ case tdav_codec_h264_bp20:
+ h264->encoder.ctx_params.iDisableCabac = 1;
+ h264->encoder.ctx_params.iProfileLevel = 0xff42;
+ break;
+ case tdav_codec_h264_bp30:
+ h264->encoder.ctx_params.iDisableCabac = 1;
+ h264->encoder.ctx_params.iProfileLevel = 0xff42;
+ break;
+ default:
+ break;
+ }
+
+ hr = NVCreateEncoder(&h264->encoder.context);
+ if(FAILED(hr)) {
+ TSK_DEBUG_ERROR("NVCreateEncoder failed with error code = %08x", hr);
+ return -2;
+ }
+
+ hr = NVSetCodec(h264->encoder.context, NV_CODEC_TYPE_H264);
+ if(FAILED(hr)) {
+ TSK_DEBUG_ERROR("NVSetCodec failed with error code = %08x", hr);
+ return -2;
+ }
+
+ hr = NVSetDefaultParam(h264->encoder.context);
+ if(FAILED(hr)) {
+ TSK_DEBUG_ERROR("NVSetDefaultParam() failed with error code = %08x", hr);
+ return -2;
+ }
+
+ hr = NVGetParamValue(h264->encoder.context, NVVE_GET_GPU_COUNT, &h264->encoder.ctx_params.GPU_count);
+ if(SUCCEEDED(hr)) {
+ int temp = 0, deviceCount;
+ for (deviceCount=0; deviceCount < h264->encoder.ctx_params.GPU_count; deviceCount++) {
+ NVVE_GPUAttributes GPUAttributes = {0};
+
+ GPUAttributes.iGpuOrdinal = deviceCount;
+ hr = NVGetParamValue(h264->encoder.context, NVVE_GET_GPU_ATTRIBUTES, &GPUAttributes);
+ if(FAILED(hr)) {
+ TSK_DEBUG_ERROR("NVGetParamValue(NVVE_GET_GPU_ATTRIBUTES) failed with error code = %08x", hr);
+ continue;
+ }
+
+ temp = GPUAttributes.iClockRate * GPUAttributes.iMultiProcessorCount;
+ temp = temp * _ConvertSMVer2Cores(GPUAttributes.iMajor, GPUAttributes.iMinor);
+
+ if(temp > gpuPerf) {
+ gpuPerf = temp;
+ bestGPU = deviceCount;
+ }
+ }
+ }
+ else {
+ TSK_DEBUG_ERROR("NVGetParamValue(NVVE_GET_GPU_COUNT) failed with error code = %08x", hr);
+ return -2;
+ }
+
+ h264->encoder.ctx_params.iForcedGPU = bestGPU;
+ hr = NVSetParamValue(h264->encoder.context, NVVE_FORCE_GPU_SELECTION, &h264->encoder.ctx_params.iForcedGPU);
+ if(FAILED(hr)) {
+ TSK_DEBUG_WARN("NVSetParamValue(NVVE_FORCE_GPU_SELECTION) failed with error code = %08x", hr);
+ }
+
+ hr = NVSetParamValue(h264->encoder.context, NVVE_DEVICE_MEMORY_INPUT, &(h264->encoder.ctx_params.iUseDeviceMem));
+ if(FAILED(hr)) {
+ TSK_DEBUG_ERROR("NVSetParamValue(NVVE_OUT_SIZE) failed with error code = %08x", hr);
+ return -2;
+ }
+
+ h264->encoder.buffer_size = (h264->encoder.ctx_params.iOutputSize[1] * h264->encoder.ctx_params.iOutputSize[0] * 3) >> 4;
+ if(!h264->encoder.buffer && !(h264->encoder.buffer = tsk_realloc(h264->encoder.buffer, h264->encoder.buffer_size))) {
+ TSK_DEBUG_ERROR("Failed to allocate buffer with size=%u", h264->encoder.buffer_size);
+ h264->encoder.buffer_size = 0;
+ return -2;
+ }
+
+ hr = NVSetParamValue(h264->encoder.context,NVVE_OUT_SIZE, &(h264->encoder.ctx_params.iOutputSize));
+ if (hr!=S_OK) {
+ TSK_DEBUG_WARN("NVSetParamValue(NVVE_OUT_SIZE) failed with error code = %08x", hr);
+ }
+ hr = NVSetParamValue(h264->encoder.context,NVVE_IN_SIZE, &(h264->encoder.ctx_params.iInputSize));
+ if (hr!=S_OK) {
+ TSK_DEBUG_WARN("NVSetParamValue(NVVE_IN_SIZE) failed with error code = %08x", hr);
+ }
+ hr = NVSetParamValue(h264->encoder.context,NVVE_MULTI_GPU, &(h264->encoder.ctx_params.iMultiGPU));
+ if (hr!=S_OK) {
+ TSK_DEBUG_WARN("NVSetParamValue(NVVE_MULTI_GPU) failed with error code = %08x", hr);
+ }
+ hr = NVSetParamValue(h264->encoder.context,NVVE_ASPECT_RATIO, &(h264->encoder.ctx_params.iAspectRatio));
+ if (hr!=S_OK) {
+ TSK_DEBUG_WARN("NVSetParamValue(NVVE_ASPECT_RATIO) failed with error code = %08x", hr);
+ }
+ hr = NVSetParamValue(h264->encoder.context,NVVE_FIELD_ENC_MODE, &(h264->encoder.ctx_params.Fieldmode));
+ if (hr!=S_OK) {
+ TSK_DEBUG_WARN("NVSetParamValue(NVVE_FIELD_ENC_MODE) failed with error code = %08x", hr);
+ }
+ hr = NVSetParamValue(h264->encoder.context,NVVE_P_INTERVAL, &(h264->encoder.ctx_params.iP_Interval));
+ if (hr!=S_OK) {
+ TSK_DEBUG_WARN("NVSetParamValue(NVVE_P_INTERVAL) failed with error code = %08x", hr);
+ }
+ hr = NVSetParamValue(h264->encoder.context,NVVE_IDR_PERIOD, &(h264->encoder.ctx_params.iIDR_Period));
+ if (hr!=S_OK) {
+ TSK_DEBUG_WARN("NVSetParamValue(NVVE_IDR_PERIOD) failed with error code = %08x", hr);
+ }
+ hr = NVSetParamValue(h264->encoder.context,NVVE_DYNAMIC_GOP, &(h264->encoder.ctx_params.iDynamicGOP));
+ if (hr!=S_OK) {
+ TSK_DEBUG_WARN("NVSetParamValue(NVVE_DYNAMIC_GOP) failed with error code = %08x", hr);
+ }
+ hr = NVSetParamValue(h264->encoder.context,NVVE_RC_TYPE, &(h264->encoder.ctx_params.RCType));
+ if (hr!=S_OK) {
+ TSK_DEBUG_WARN("NVSetParamValue(NVVE_RC_TYPE) failed with error code = %08x", hr);
+ }
+ hr = NVSetParamValue(h264->encoder.context,NVVE_AVG_BITRATE, &(h264->encoder.ctx_params.iAvgBitrate));
+ if (hr!=S_OK) {
+ TSK_DEBUG_WARN("NVSetParamValue(NVVE_AVG_BITRATE) failed with error code = %08x", hr);
+ }
+ hr = NVSetParamValue(h264->encoder.context,NVVE_PEAK_BITRATE, &(h264->encoder.ctx_params.iPeakBitrate));
+ if (hr!=S_OK) {
+ TSK_DEBUG_WARN("NVSetParamValue(NVVE_PEAK_BITRATE) failed with error code = %08x", hr);
+ }
+ hr = NVSetParamValue(h264->encoder.context,NVVE_QP_LEVEL_INTRA, &(h264->encoder.ctx_params.iQP_Level_Intra));
+ if (hr!=S_OK) {
+ TSK_DEBUG_WARN("NVSetParamValue(NVVE_OUT_SIZE) failed with error code = %08x", hr);
+ }
+ hr = NVSetParamValue(h264->encoder.context,NVVE_QP_LEVEL_INTER_P,&(h264->encoder.ctx_params.iQP_Level_InterP));
+ if (hr!=S_OK) {
+ TSK_DEBUG_WARN("NVSetParamValue(NVVE_QP_LEVEL_INTER_P) failed with error code = %08x", hr);
+ }
+ hr = NVSetParamValue(h264->encoder.context,NVVE_QP_LEVEL_INTER_B,&(h264->encoder.ctx_params.iQP_Level_InterB));
+ if (hr!=S_OK) {
+ TSK_DEBUG_WARN("NVSetParamValue(NVVE_QP_LEVEL_INTER_B) failed with error code = %08x", hr);
+ }
+ hr = NVSetParamValue(h264->encoder.context,NVVE_FRAME_RATE, &(h264->encoder.ctx_params.iFrameRate));
+ if (hr!=S_OK) {
+ TSK_DEBUG_WARN("NVSetParamValue(NVVE_FRAME_RATE) failed with error code = %08x", hr);
+ }
+ hr = NVSetParamValue(h264->encoder.context,NVVE_DEBLOCK_MODE, &(h264->encoder.ctx_params.iDeblockMode));
+ if (hr!=S_OK) {
+ TSK_DEBUG_WARN("NVSetParamValue(NVVE_DEBLOCK_MODE) failed with error code = %08x", hr);
+ }
+ hr = NVSetParamValue(h264->encoder.context,NVVE_PROFILE_LEVEL, &(h264->encoder.ctx_params.iProfileLevel));
+ if (hr!=S_OK) {
+ TSK_DEBUG_WARN("NVSetParamValue(NVVE_PROFILE_LEVEL) failed with error code = %08x", hr);
+ }
+ hr = NVSetParamValue(h264->encoder.context,NVVE_FORCE_INTRA, &(h264->encoder.ctx_params.iForceIntra));
+ if (hr!=S_OK) {
+ TSK_DEBUG_WARN("NVSetParamValue(NVVE_FORCE_INTRA) failed with error code = %08x", hr);
+ }
+ hr = NVSetParamValue(h264->encoder.context,NVVE_FORCE_IDR, &(h264->encoder.ctx_params.iForceIDR));
+ if (hr!=S_OK) {
+ TSK_DEBUG_WARN("NVSetParamValue(NVVE_FORCE_IDR) failed with error code = %08x", hr);
+ }
+ hr = NVSetParamValue(h264->encoder.context,NVVE_CLEAR_STAT, &(h264->encoder.ctx_params.iClearStat));
+ if (hr!=S_OK) {
+ TSK_DEBUG_WARN("NVSetParamValue(NVVE_CLEAR_STAT) failed with error code = %08x", hr);
+ }
+ hr = NVSetParamValue(h264->encoder.context,NVVE_SET_DEINTERLACE,&(h264->encoder.ctx_params.DIMode));
+ if (hr!=S_OK) {
+ TSK_DEBUG_WARN("NVSetParamValue(NVVE_SET_DEINTERLACE) failed with error code = %08x", hr);
+ }
if (h264->encoder.ctx_params.Presets != -1) {
- hr = NVSetParamValue(h264->encoder.context,NVVE_PRESETS, &(h264->encoder.ctx_params.Presets)); if (hr!=S_OK) { TSK_DEBUG_WARN("NVSetParamValue(NVVE_PRESETS) failed with error code = %08x", hr); }
- }
- hr = NVSetParamValue(h264->encoder.context,NVVE_DISABLE_CABAC, &(h264->encoder.ctx_params.iDisableCabac)); if (hr!=S_OK) { TSK_DEBUG_WARN("NVSetParamValue(NVVE_DISABLE_CABAC) failed with error code = %08x", hr); }
- hr = NVSetParamValue(h264->encoder.context,NVVE_CONFIGURE_NALU_FRAMING_TYPE, &(h264->encoder.ctx_params.iNaluFramingType)); if (hr!=S_OK) { TSK_DEBUG_WARN("NVSetParamValue(NVVE_CONFIGURE_NALU_FRAMING_TYPE) failed with error code = %08x", hr); }
- hr = NVSetParamValue(h264->encoder.context,NVVE_DISABLE_SPS_PPS,&(h264->encoder.ctx_params.iDisableSPSPPS)); if (hr!=S_OK) { TSK_DEBUG_WARN("NVSetParamValue(NVVE_DISABLE_SPS_PPS) failed with error code = %08x", hr); }
- hr = NVSetParamValue(h264->encoder.context,NVVE_LOW_LATENCY,&low_latency); if (hr!=S_OK) { TSK_DEBUG_WARN("NVSetParamValue(NVVE_LOW_LATENCY) failed with error code = %08x", hr); }
+ hr = NVSetParamValue(h264->encoder.context,NVVE_PRESETS, &(h264->encoder.ctx_params.Presets));
+ if (hr!=S_OK) {
+ TSK_DEBUG_WARN("NVSetParamValue(NVVE_PRESETS) failed with error code = %08x", hr);
+ }
+ }
+ hr = NVSetParamValue(h264->encoder.context,NVVE_DISABLE_CABAC, &(h264->encoder.ctx_params.iDisableCabac));
+ if (hr!=S_OK) {
+ TSK_DEBUG_WARN("NVSetParamValue(NVVE_DISABLE_CABAC) failed with error code = %08x", hr);
+ }
+ hr = NVSetParamValue(h264->encoder.context,NVVE_CONFIGURE_NALU_FRAMING_TYPE, &(h264->encoder.ctx_params.iNaluFramingType));
+ if (hr!=S_OK) {
+ TSK_DEBUG_WARN("NVSetParamValue(NVVE_CONFIGURE_NALU_FRAMING_TYPE) failed with error code = %08x", hr);
+ }
+ hr = NVSetParamValue(h264->encoder.context,NVVE_DISABLE_SPS_PPS,&(h264->encoder.ctx_params.iDisableSPSPPS));
+ if (hr!=S_OK) {
+ TSK_DEBUG_WARN("NVSetParamValue(NVVE_DISABLE_SPS_PPS) failed with error code = %08x", hr);
+ }
+ hr = NVSetParamValue(h264->encoder.context,NVVE_LOW_LATENCY,&low_latency);
+ if (hr!=S_OK) {
+ TSK_DEBUG_WARN("NVSetParamValue(NVVE_LOW_LATENCY) failed with error code = %08x", hr);
+ }
+
+ h264->encoder.clb_params.pfnacquirebitstream = _NVCallback_HandleAcquireBitStream;
+ h264->encoder.clb_params.pfnonbeginframe = _NVCallback_HandleOnBeginFrame;
+ h264->encoder.clb_params.pfnonendframe = _NVCallback_HandleOnEndFrame;
+ h264->encoder.clb_params.pfnreleasebitstream = _NVCallback_HandleReleaseBitStream;
+ NVRegisterCB(h264->encoder.context, h264->encoder.clb_params, h264);
- h264->encoder.clb_params.pfnacquirebitstream = _NVCallback_HandleAcquireBitStream;
- h264->encoder.clb_params.pfnonbeginframe = _NVCallback_HandleOnBeginFrame;
- h264->encoder.clb_params.pfnonendframe = _NVCallback_HandleOnEndFrame;
- h264->encoder.clb_params.pfnreleasebitstream = _NVCallback_HandleReleaseBitStream;
- NVRegisterCB(h264->encoder.context, h264->encoder.clb_params, h264);
-
- hr = NVCreateHWEncoder(h264->encoder.context);
- if(FAILED(hr)){
- TSK_DEBUG_ERROR("NVCreateHWEncoder failed with error code = %08x", hr);
- return -2;
- }
+ hr = NVCreateHWEncoder(h264->encoder.context);
+ if(FAILED(hr)) {
+ TSK_DEBUG_ERROR("NVCreateHWEncoder failed with error code = %08x", hr);
+ return -2;
+ }
- //
- // decoder
- //
- if((cuResult = cuInit(0)) != CUDA_SUCCESS){
- TSK_DEBUG_ERROR("cuInit(0) failed with error code = %d", (int)cuResult);
- return -3;
- }
+ //
+ // decoder
+ //
+ if((cuResult = cuInit(0)) != CUDA_SUCCESS) {
+ TSK_DEBUG_ERROR("cuInit(0) failed with error code = %d", (int)cuResult);
+ return -3;
+ }
- InitH264DecoderInfo(h264);
+ InitH264DecoderInfo(h264);
- h264->decoder.cu_device = cutilDrvGetMaxGflopsGraphicsDeviceId();
+ h264->decoder.cu_device = cutilDrvGetMaxGflopsGraphicsDeviceId();
#if _DEBUG || DEBUG
- {
- int major, minor;
- size_t totalGlobalMem;
- char deviceName[256];
- cuDeviceComputeCapability(&major, &minor, h264->decoder.cu_device);
- cuDeviceGetName(deviceName, sizeof(deviceName), h264->decoder.cu_device);
- TSK_DEBUG_INFO("Using GPU Device %d: %s has SM %d.%d compute capability", h264->decoder.cu_device, deviceName, major, minor);
-
- cutilDrvSafeCallNoSync(cuDeviceTotalMem(&totalGlobalMem, h264->decoder.cu_device) );
- TSK_DEBUG_INFO("Total amount of global memory in GPU device: %4.4f MB", (float)totalGlobalMem/(1024*1024));
- }
+ {
+ int major, minor;
+ size_t totalGlobalMem;
+ char deviceName[256];
+ cuDeviceComputeCapability(&major, &minor, h264->decoder.cu_device);
+ cuDeviceGetName(deviceName, sizeof(deviceName), h264->decoder.cu_device);
+ TSK_DEBUG_INFO("Using GPU Device %d: %s has SM %d.%d compute capability", h264->decoder.cu_device, deviceName, major, minor);
+
+ cutilDrvSafeCallNoSync(cuDeviceTotalMem(&totalGlobalMem, h264->decoder.cu_device) );
+ TSK_DEBUG_INFO("Total amount of global memory in GPU device: %4.4f MB", (float)totalGlobalMem/(1024*1024));
+ }
#endif
- // create Direct3D instance
- h264->decoder.dx_d3d = Direct3DCreate9(D3D_SDK_VERSION);
- if(!h264->decoder.dx_d3d){
- TSK_DEBUG_ERROR("Direct3DCreate9 failed");
- return -3;
- }
- adapterCount = h264->decoder.dx_d3d->GetAdapterCount();
- for(i=0; i<adapterCount; ++i){
- ZeroMemory(&d3dpp, sizeof(d3dpp));
+ // create Direct3D instance
+ h264->decoder.dx_d3d = Direct3DCreate9(D3D_SDK_VERSION);
+ if(!h264->decoder.dx_d3d) {
+ TSK_DEBUG_ERROR("Direct3DCreate9 failed");
+ return -3;
+ }
+ adapterCount = h264->decoder.dx_d3d->GetAdapterCount();
+ for(i=0; i<adapterCount; ++i) {
+ ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = TRUE;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferWidth = h264->decoder.info.ulTargetWidth;
@@ -309,620 +387,621 @@ static int tdav_codec_h264_cuda_open(tmedia_codec_t* self)
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
d3dpp.Flags = D3DPRESENTFLAG_VIDEO;//D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
hr = h264->decoder.dx_d3d->CreateDevice(i,
- D3DDEVTYPE_HAL,
- GetDesktopWindow(),
- D3DCREATE_FPU_PRESERVE | D3DCREATE_MULTITHREADED | D3DCREATE_HARDWARE_VERTEXPROCESSING,
- &d3dpp,
- &h264->decoder.dx_d3ddevice);
- if(hr == S_OK){
+ D3DDEVTYPE_HAL,
+ GetDesktopWindow(),
+ D3DCREATE_FPU_PRESERVE | D3DCREATE_MULTITHREADED | D3DCREATE_HARDWARE_VERTEXPROCESSING,
+ &d3dpp,
+ &h264->decoder.dx_d3ddevice);
+ if(hr == S_OK) {
cuResult = cuD3D9CtxCreate(&h264->decoder.cu_context, &h264->decoder.cu_device, 0, h264->decoder.dx_d3ddevice);
- if(cuResult == CUDA_SUCCESS){
+ if(cuResult == CUDA_SUCCESS) {
break;
- }
- if(h264->decoder.dx_d3ddevice){
- h264->decoder.dx_d3ddevice->Release();
- h264->decoder.dx_d3ddevice = NULL;
- }
+ }
+ if(h264->decoder.dx_d3ddevice) {
+ h264->decoder.dx_d3ddevice->Release();
+ h264->decoder.dx_d3ddevice = NULL;
+ }
}
- }
+ }
- memset(&h264->decoder.cu_paser_params, 0, sizeof(h264->decoder.cu_paser_params));
- h264->decoder.cu_paser_params.CodecType = cudaVideoCodec_H264;
+ memset(&h264->decoder.cu_paser_params, 0, sizeof(h264->decoder.cu_paser_params));
+ h264->decoder.cu_paser_params.CodecType = cudaVideoCodec_H264;
h264->decoder.cu_paser_params.ulMaxNumDecodeSurfaces = CUDA_MAX_FRM_CNT;
h264->decoder.cu_paser_params.pUserData = h264;
h264->decoder.cu_paser_params.pfnSequenceCallback = _NVCallback_HandleVideoSequence;
h264->decoder.cu_paser_params.pfnDecodePicture = _NVCallback_HandlePictureDecode;
h264->decoder.cu_paser_params.pfnDisplayPicture = _NVCallback_HandlePictureDisplay;
cuResult = cuvidCreateVideoParser(&h264->decoder.cu_parser, &h264->decoder.cu_paser_params);
- if(cuResult != CUDA_SUCCESS){
- TSK_DEBUG_ERROR("cuvidCreateVideoParser(0) failed with error code = %d", (int)cuResult);
- return -3;
- }
-
- cuResult = cuvidCreateDecoder(&h264->decoder.context, &h264->decoder.info);
- if(CUDA_SUCCESS != cuResult){
- TSK_DEBUG_ERROR("cuvidCreateDecoder failed with error code=%d", (int)cuResult);
- return -3;
- }
-
- return ret;
+ if(cuResult != CUDA_SUCCESS) {
+ TSK_DEBUG_ERROR("cuvidCreateVideoParser(0) failed with error code = %d", (int)cuResult);
+ return -3;
+ }
+
+ cuResult = cuvidCreateDecoder(&h264->decoder.context, &h264->decoder.info);
+ if(CUDA_SUCCESS != cuResult) {
+ TSK_DEBUG_ERROR("cuvidCreateDecoder failed with error code=%d", (int)cuResult);
+ return -3;
+ }
+
+ return ret;
}
static int tdav_codec_h264_cuda_close(tmedia_codec_t* self)
{
- tdav_codec_h264_cuda_t* h264 = (tdav_codec_h264_cuda_t*)self;
-
- if(!h264){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- if(h264->encoder.context){
+ tdav_codec_h264_cuda_t* h264 = (tdav_codec_h264_cuda_t*)self;
+
+ if(!h264) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if(h264->encoder.context) {
NVDestroyEncoder(h264->encoder.context);
h264->encoder.context = NULL;
}
- return 0;
+ return 0;
}
static tsk_size_t tdav_codec_h264_cuda_encode(tmedia_codec_t* self, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size)
{
- NVVE_EncodeFrameParams efparams;
- int ret = 0;
- unsigned long flags = 0;
- HRESULT hr;
-
- tdav_codec_h264_cuda_t* h264 = (tdav_codec_h264_cuda_t*)self;
-
- if(!self || !in_data || !in_size || !out_data){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- if(!self->opened){
- TSK_DEBUG_ERROR("Codec not opened");
- return 0;
- }
-
- if((h264->encoder.ctx_params.iOutputSize[1] * h264->encoder.ctx_params.iOutputSize[0] * 3)>>1 != in_size){
- /* guard */
- TSK_DEBUG_ERROR("Invalid size");
- return 0;
- }
-
- //return 0;
-
- efparams.Width = h264->encoder.ctx_params.iOutputSize[0];
- efparams.Height = h264->encoder.ctx_params.iOutputSize[1];
- efparams.Pitch = (h264->encoder.ctx_params.nDeviceMemPitch ? h264->encoder.ctx_params.nDeviceMemPitch : h264->encoder.ctx_params.iOutputSize[0]);
- efparams.PictureStruc = (NVVE_PicStruct)h264->encoder.ctx_params.iPictureType;
+ NVVE_EncodeFrameParams efparams;
+ int ret = 0;
+ unsigned long flags = 0;
+ HRESULT hr;
+
+ tdav_codec_h264_cuda_t* h264 = (tdav_codec_h264_cuda_t*)self;
+
+ if(!self || !in_data || !in_size || !out_data) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ if(!self->opened) {
+ TSK_DEBUG_ERROR("Codec not opened");
+ return 0;
+ }
+
+ if((h264->encoder.ctx_params.iOutputSize[1] * h264->encoder.ctx_params.iOutputSize[0] * 3)>>1 != in_size) {
+ /* guard */
+ TSK_DEBUG_ERROR("Invalid size");
+ return 0;
+ }
+
+ //return 0;
+
+ efparams.Width = h264->encoder.ctx_params.iOutputSize[0];
+ efparams.Height = h264->encoder.ctx_params.iOutputSize[1];
+ efparams.Pitch = (h264->encoder.ctx_params.nDeviceMemPitch ? h264->encoder.ctx_params.nDeviceMemPitch : h264->encoder.ctx_params.iOutputSize[0]);
+ efparams.PictureStruc = (NVVE_PicStruct)h264->encoder.ctx_params.iPictureType;
efparams.SurfFmt = (NVVE_SurfaceFormat)h264->encoder.ctx_params.iSurfaceFormat;
- efparams.progressiveFrame = (h264->encoder.ctx_params.iSurfaceFormat == 3) ? 1 : 0;
+ efparams.progressiveFrame = (h264->encoder.ctx_params.iSurfaceFormat == 3) ? 1 : 0;
efparams.repeatFirstField = 0;
- efparams.topfieldfirst = (h264->encoder.ctx_params.iSurfaceFormat == 1) ? 1 : 0;
- efparams.picBuf = (unsigned char *)in_data;
- efparams.bLast = 0;
-
- // send keyframe for:
- // - the first frame
- // - every second within the first 4seconds
- // - every 7 seconds after the first 4seconds
- if(h264->encoder.frame_count++ == 0
- ||
- ( (h264->encoder.frame_count < (int)TMEDIA_CODEC_VIDEO(h264)->out.fps * 4) && ((h264->encoder.frame_count % TMEDIA_CODEC_VIDEO(h264)->out.fps)==0) )
- ||
- ( (h264->encoder.frame_count % (TMEDIA_CODEC_VIDEO(h264)->out.fps * 5))==0 )
- )
- {
- flags |= 0x04; // FORCE IDR
- if(h264->encoder.ctx_params.iDisableSPSPPS){
- unsigned char SPSPPSBuff[1024];
- int SPSPPSBuffSize = sizeof(SPSPPSBuff);
- hr = NVGetSPSPPS(h264->encoder.context, SPSPPSBuff, SPSPPSBuffSize, &SPSPPSBuffSize);
- if(SUCCEEDED(hr)){
- int size = 0;
- while(size < SPSPPSBuffSize - 2){
- int16_t next_size = ((int16_t)SPSPPSBuff[size])<<1 | ((int16_t)SPSPPSBuff[size + 1]);
- _tdav_codec_h264_cuda_encap(h264, &SPSPPSBuff[size + 2], next_size);
- size+=next_size + 2;
- }
- }
- else{
- TSK_DEBUG_ERROR("NVGetSPSPPS failed with error code = %08x", hr)
- }
- }
- }
-
- hr = NVEncodeFrame(h264->encoder.context, &efparams, flags, NULL);
-
- return 0;
+ efparams.topfieldfirst = (h264->encoder.ctx_params.iSurfaceFormat == 1) ? 1 : 0;
+ efparams.picBuf = (unsigned char *)in_data;
+ efparams.bLast = 0;
+
+ // send keyframe for:
+ // - the first frame
+ // - every second within the first 4seconds
+ // - every 7 seconds after the first 4seconds
+ if(h264->encoder.frame_count++ == 0
+ ||
+ ( (h264->encoder.frame_count < (int)TMEDIA_CODEC_VIDEO(h264)->out.fps * 4) && ((h264->encoder.frame_count % TMEDIA_CODEC_VIDEO(h264)->out.fps)==0) )
+ ||
+ ( (h264->encoder.frame_count % (TMEDIA_CODEC_VIDEO(h264)->out.fps * 5))==0 )
+ ) {
+ flags |= 0x04; // FORCE IDR
+ if(h264->encoder.ctx_params.iDisableSPSPPS) {
+ unsigned char SPSPPSBuff[1024];
+ int SPSPPSBuffSize = sizeof(SPSPPSBuff);
+ hr = NVGetSPSPPS(h264->encoder.context, SPSPPSBuff, SPSPPSBuffSize, &SPSPPSBuffSize);
+ if(SUCCEEDED(hr)) {
+ int size = 0;
+ while(size < SPSPPSBuffSize - 2) {
+ int16_t next_size = ((int16_t)SPSPPSBuff[size])<<1 | ((int16_t)SPSPPSBuff[size + 1]);
+ _tdav_codec_h264_cuda_encap(h264, &SPSPPSBuff[size + 2], next_size);
+ size+=next_size + 2;
+ }
+ }
+ else {
+ TSK_DEBUG_ERROR("NVGetSPSPPS failed with error code = %08x", hr)
+ }
+ }
+ }
+
+ hr = NVEncodeFrame(h264->encoder.context, &efparams, flags, NULL);
+
+ return 0;
}
static tsk_size_t tdav_codec_h264_cuda_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)
{
- tdav_codec_h264_cuda_t* h264 = (tdav_codec_h264_cuda_t*)self;
- const trtp_rtp_header_t* rtp_hdr = (const trtp_rtp_header_t*)proto_hdr;
- const uint8_t* pay_ptr = tsk_null;
- tsk_size_t pay_size = 0, retsize = 0, size_to_copy = 0;
- int ret = 0;
- tsk_bool_t append_scp = tsk_false;
- static tsk_size_t xmax_size = (1920 * 1080 * 3) >> 3;
- static tsk_size_t start_code_prefix_size = sizeof(H264_START_CODE_PREFIX);
-
- // Packet lost?
- if(h264->decoder.last_seq != (rtp_hdr->seq_num - 1) && h264->decoder.last_seq){
- if(h264->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);
- }
- h264->decoder.last_seq = rtp_hdr->seq_num;
-
- /* 5.3. NAL Unit Octet Usage
- +---------------+
+ tdav_codec_h264_cuda_t* h264 = (tdav_codec_h264_cuda_t*)self;
+ const trtp_rtp_header_t* rtp_hdr = (const trtp_rtp_header_t*)proto_hdr;
+ const uint8_t* pay_ptr = tsk_null;
+ tsk_size_t pay_size = 0, retsize = 0, size_to_copy = 0;
+ int ret = 0;
+ tsk_bool_t append_scp = tsk_false;
+ static tsk_size_t xmax_size = (1920 * 1080 * 3) >> 3;
+ static tsk_size_t start_code_prefix_size = sizeof(H264_START_CODE_PREFIX);
+
+ // Packet lost?
+ if(h264->decoder.last_seq != (rtp_hdr->seq_num - 1) && h264->decoder.last_seq) {
+ if(h264->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);
+ }
+ h264->decoder.last_seq = rtp_hdr->seq_num;
+
+ /* 5.3. NAL Unit Octet Usage
+ +---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|F|NRI| Type |
+---------------+
- */
- if(*((uint8_t*)in_data) >> 7){
- TSK_DEBUG_WARN("F=1");
- /* reset accumulator */
- h264->decoder.accumulator_pos = 0;
- goto bail;
- }
-
- // get payload
- if((ret = tdav_codec_h264_get_pay(in_data, in_size, (const void**)&pay_ptr, &pay_size, &append_scp)) || !pay_ptr || !pay_size){
- TSK_DEBUG_ERROR("Depayloader failed to get H.264 content");
- goto bail;
- }
- //append_scp = tsk_true;
- size_to_copy = pay_size + (append_scp ? start_code_prefix_size : 0);
-
- // start-accumulator
- if(!h264->decoder.accumulator){
- if(size_to_copy > xmax_size){
- TSK_DEBUG_ERROR("%u too big to contain valid encoded data. xmax_size=%u", size_to_copy, xmax_size);
- goto bail;
- }
- if(!(h264->decoder.accumulator = tsk_calloc(size_to_copy, sizeof(uint8_t)))){
- TSK_DEBUG_ERROR("Failed to allocated new buffer");
- goto bail;
- }
- h264->decoder.accumulator_size = size_to_copy;
- }
- if((h264->decoder.accumulator_pos + size_to_copy) >= xmax_size){
- TSK_DEBUG_ERROR("BufferOverflow");
- h264->decoder.accumulator_pos = 0;
- goto bail;
- }
- if((h264->decoder.accumulator_pos + size_to_copy) > h264->decoder.accumulator_size){
- if(!(h264->decoder.accumulator = tsk_realloc(h264->decoder.accumulator, (h264->decoder.accumulator_pos + size_to_copy)))){
- TSK_DEBUG_ERROR("Failed to reallocated new buffer");
- h264->decoder.accumulator_pos = 0;
- h264->decoder.accumulator_size = 0;
- goto bail;
- }
- h264->decoder.accumulator_size = (h264->decoder.accumulator_pos + size_to_copy);
- }
-
- if(append_scp){
- memcpy(&((uint8_t*)h264->decoder.accumulator)[h264->decoder.accumulator_pos], H264_START_CODE_PREFIX, start_code_prefix_size);
- h264->decoder.accumulator_pos += start_code_prefix_size;
- }
- memcpy(&((uint8_t*)h264->decoder.accumulator)[h264->decoder.accumulator_pos], pay_ptr, pay_size);
- h264->decoder.accumulator_pos += pay_size;
- // end-accumulator
-
- if(rtp_hdr->marker){
- CUVIDSOURCEDATAPACKET pkt;
- CUresult cuResult;
- pkt.flags = 0;
+ */
+ if(*((uint8_t*)in_data) >> 7) {
+ TSK_DEBUG_WARN("F=1");
+ /* reset accumulator */
+ h264->decoder.accumulator_pos = 0;
+ goto bail;
+ }
+
+ // get payload
+ if((ret = tdav_codec_h264_get_pay(in_data, in_size, (const void**)&pay_ptr, &pay_size, &append_scp)) || !pay_ptr || !pay_size) {
+ TSK_DEBUG_ERROR("Depayloader failed to get H.264 content");
+ goto bail;
+ }
+ //append_scp = tsk_true;
+ size_to_copy = pay_size + (append_scp ? start_code_prefix_size : 0);
+
+ // start-accumulator
+ if(!h264->decoder.accumulator) {
+ if(size_to_copy > xmax_size) {
+ TSK_DEBUG_ERROR("%u too big to contain valid encoded data. xmax_size=%u", size_to_copy, xmax_size);
+ goto bail;
+ }
+ if(!(h264->decoder.accumulator = tsk_calloc(size_to_copy, sizeof(uint8_t)))) {
+ TSK_DEBUG_ERROR("Failed to allocated new buffer");
+ goto bail;
+ }
+ h264->decoder.accumulator_size = size_to_copy;
+ }
+ if((h264->decoder.accumulator_pos + size_to_copy) >= xmax_size) {
+ TSK_DEBUG_ERROR("BufferOverflow");
+ h264->decoder.accumulator_pos = 0;
+ goto bail;
+ }
+ if((h264->decoder.accumulator_pos + size_to_copy) > h264->decoder.accumulator_size) {
+ if(!(h264->decoder.accumulator = tsk_realloc(h264->decoder.accumulator, (h264->decoder.accumulator_pos + size_to_copy)))) {
+ TSK_DEBUG_ERROR("Failed to reallocated new buffer");
+ h264->decoder.accumulator_pos = 0;
+ h264->decoder.accumulator_size = 0;
+ goto bail;
+ }
+ h264->decoder.accumulator_size = (h264->decoder.accumulator_pos + size_to_copy);
+ }
+
+ if(append_scp) {
+ memcpy(&((uint8_t*)h264->decoder.accumulator)[h264->decoder.accumulator_pos], H264_START_CODE_PREFIX, start_code_prefix_size);
+ h264->decoder.accumulator_pos += start_code_prefix_size;
+ }
+ memcpy(&((uint8_t*)h264->decoder.accumulator)[h264->decoder.accumulator_pos], pay_ptr, pay_size);
+ h264->decoder.accumulator_pos += pay_size;
+ // end-accumulator
+
+ if(rtp_hdr->marker) {
+ CUVIDSOURCEDATAPACKET pkt;
+ CUresult cuResult;
+ pkt.flags = 0;
pkt.payload_size = (unsigned long) h264->decoder.accumulator_pos;
pkt.payload = (unsigned char *)h264->decoder.accumulator;
pkt.timestamp = 0;
- // reset accumulator
- h264->decoder.accumulator_pos = 0;
+ // reset accumulator
+ h264->decoder.accumulator_pos = 0;
cuResult = cuvidParseVideoData(h264->decoder.cu_parser, &pkt);
- if(cuResult != CUDA_SUCCESS){
- TSK_DEBUG_ERROR("cuvidParseVideoData() failed with error code = %d", (int)cuResult);
- goto bail;
- }
-
- if(h264->decoder.cu_buffer_avail){
- h264->decoder.cu_buffer_avail = tsk_false;
- if((retsize = _tdav_codec_h264_cuda_pict_layout(h264, out_data, out_max_size)) == 0){
- TSK_DEBUG_ERROR("_tdav_codec_h264_cuda_pict_layout failed");
- goto bail;
- }
- }
- }
+ if(cuResult != CUDA_SUCCESS) {
+ TSK_DEBUG_ERROR("cuvidParseVideoData() failed with error code = %d", (int)cuResult);
+ goto bail;
+ }
+
+ if(h264->decoder.cu_buffer_avail) {
+ h264->decoder.cu_buffer_avail = tsk_false;
+ if((retsize = _tdav_codec_h264_cuda_pict_layout(h264, out_data, out_max_size)) == 0) {
+ TSK_DEBUG_ERROR("_tdav_codec_h264_cuda_pict_layout failed");
+ goto bail;
+ }
+ }
+ }
bail:
- return retsize;
+ return retsize;
}
static tsk_bool_t tdav_codec_h264_cuda_sdp_att_match(const tmedia_codec_t* codec, const char* att_name, const char* att_value)
{
- tdav_codec_h264_cuda_t* h264 = (tdav_codec_h264_cuda_t*)codec;
- profile_idc_t profile;
-
- if(!h264){
- TSK_DEBUG_ERROR("Invalid parameter");
- return tsk_false;
- }
-
- /* Check whether the profile match (If the profile is missing, then we consider that it's ok) */
- if(((profile = tdav_codec_h264_common_get_profile(fmtp)) != tdav_codec_h264_bp99) && (profile != TDAV_CODEC_H264_COMMON(h264)->profile)){
- TSK_DEBUG_INFO("Profile not matching");
- return tsk_false;
- }
-
- TMEDIA_CODEC_VIDEO(h264)->in.width = 800, TMEDIA_CODEC_VIDEO(h264)->in.height = 640;
- TMEDIA_CODEC_VIDEO(h264)->out.width = 800, TMEDIA_CODEC_VIDEO(h264)->out.height = 640;
- //TMEDIA_CODEC_VIDEO(h264)->in.width = 352, TMEDIA_CODEC_VIDEO(h264)->in.height = 288;
- //TMEDIA_CODEC_VIDEO(h264)->out.width = 352, TMEDIA_CODEC_VIDEO(h264)->out.height = 288;
-
- return tsk_true;
+ tdav_codec_h264_cuda_t* h264 = (tdav_codec_h264_cuda_t*)codec;
+ profile_idc_t profile;
+
+ if(!h264) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return tsk_false;
+ }
+
+ /* Check whether the profile match (If the profile is missing, then we consider that it's ok) */
+ if(((profile = tdav_codec_h264_common_get_profile(fmtp)) != tdav_codec_h264_bp99) && (profile != TDAV_CODEC_H264_COMMON(h264)->profile)) {
+ TSK_DEBUG_INFO("Profile not matching");
+ return tsk_false;
+ }
+
+ TMEDIA_CODEC_VIDEO(h264)->in.width = 800, TMEDIA_CODEC_VIDEO(h264)->in.height = 640;
+ TMEDIA_CODEC_VIDEO(h264)->out.width = 800, TMEDIA_CODEC_VIDEO(h264)->out.height = 640;
+ //TMEDIA_CODEC_VIDEO(h264)->in.width = 352, TMEDIA_CODEC_VIDEO(h264)->in.height = 288;
+ //TMEDIA_CODEC_VIDEO(h264)->out.width = 352, TMEDIA_CODEC_VIDEO(h264)->out.height = 288;
+
+ return tsk_true;
}
static char* tdav_codec_h264_cuda_sdp_att_get(const tmedia_codec_t* self, const char* att_name)
{
- char* fmtp = tsk_null;
- tdav_codec_h264_cuda_t* h264 = (tdav_codec_h264_cuda_t*)self;
-
- switch(TDAV_CODEC_H264_COMMON(h264)->profile){
- case tdav_codec_h264_bp10:
- fmtp = tsk_strdup("profile-level-id=42e00a");
- break;
- case tdav_codec_h264_bp20:
- fmtp = tsk_strdup("profile-level-id=42e014");
- break;
- case tdav_codec_h264_bp30:
- fmtp = tsk_strdup("profile-level-id=42e01e");
- break;
- }
-
- //1080p(1920 x 1080), 720p(1280 x 720), SVGA(800 x 600), VGA(640 x 480), 4CIF(704 x 576), CIF(352 x 288), QCIF(176 x 144), SQCIF(128 x 96)
- return fmtp;
+ char* fmtp = tsk_null;
+ tdav_codec_h264_cuda_t* h264 = (tdav_codec_h264_cuda_t*)self;
+
+ switch(TDAV_CODEC_H264_COMMON(h264)->profile) {
+ case tdav_codec_h264_bp10:
+ fmtp = tsk_strdup("profile-level-id=42e00a");
+ break;
+ case tdav_codec_h264_bp20:
+ fmtp = tsk_strdup("profile-level-id=42e014");
+ break;
+ case tdav_codec_h264_bp30:
+ fmtp = tsk_strdup("profile-level-id=42e01e");
+ break;
+ }
+
+ //1080p(1920 x 1080), 720p(1280 x 720), SVGA(800 x 600), VGA(640 x 480), 4CIF(704 x 576), CIF(352 x 288), QCIF(176 x 144), SQCIF(128 x 96)
+ return fmtp;
}
tsk_bool_t tdav_codec_h264_cuda_is_supported()
{
- static tsk_bool_t __already_checked = tsk_false;
- static tsk_bool_t __is_supported = tsk_false;
- if(!__already_checked){
- HRESULT hr;
- __already_checked = tsk_true;
- hr = NVGetHWEncodeCaps();
- if(SUCCEEDED(hr)){
- NVEncoder encoder;
- hr = NVCreateEncoder(&encoder);
- if(SUCCEEDED(hr)){
- hr = NVIsSupportedCodec(encoder, NV_CODEC_TYPE_H264);
- __is_supported = SUCCEEDED(hr);
- }
- else{
- TSK_DEBUG_ERROR("NVCreateEncoder() failed with error code = %08x", hr);
- }
- if(encoder){
- NVDestroyEncoder(encoder);
- encoder = NULL;
- }
- }
- }
- return __is_supported;
+ static tsk_bool_t __already_checked = tsk_false;
+ static tsk_bool_t __is_supported = tsk_false;
+ if(!__already_checked) {
+ HRESULT hr;
+ __already_checked = tsk_true;
+ hr = NVGetHWEncodeCaps();
+ if(SUCCEEDED(hr)) {
+ NVEncoder encoder;
+ hr = NVCreateEncoder(&encoder);
+ if(SUCCEEDED(hr)) {
+ hr = NVIsSupportedCodec(encoder, NV_CODEC_TYPE_H264);
+ __is_supported = SUCCEEDED(hr);
+ }
+ else {
+ TSK_DEBUG_ERROR("NVCreateEncoder() failed with error code = %08x", hr);
+ }
+ if(encoder) {
+ NVDestroyEncoder(encoder);
+ encoder = NULL;
+ }
+ }
+ }
+ return __is_supported;
}
static int tdav_codec_h264_cuda_init(tdav_codec_h264_cuda_t* self, profile_idc_t profile)
{
- int ret = 0;
-
- if(!self){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- if((ret = tdav_codec_h264_common_init(TDAV_CODEC_H264_COMMON(self)))){
- TSK_DEBUG_ERROR("tdav_codec_h264_common_init() faile with error code=%d", ret);
- return ret;
- }
-
- if(!self->decoder.mutex && !(self->decoder.mutex = tsk_mutex_create_2(tsk_false))){
- TSK_DEBUG_ERROR("Failed to create mutex");
- return -2;
- }
-
- sem = tsk_semaphore_create_2(1);
-
- TDAV_CODEC_H264_COMMON(self)->pack_mode_local = H264_PACKETIZATION_MODE;
- TDAV_CODEC_H264_COMMON(self)->profile = profile;
- TMEDIA_CODEC_VIDEO(self)->in.max_mbps = TMEDIA_CODEC_VIDEO(self)->out.max_mbps = H264_MAX_MBPS*1000;
- TMEDIA_CODEC_VIDEO(self)->in.max_br = TMEDIA_CODEC_VIDEO(self)->out.max_br = H264_MAX_BR*1000;
-
- // At this time self->plugin is Null
- TMEDIA_CODEC_VIDEO(self)->in.width = TMEDIA_CODEC_VIDEO(self)->out.width = 176;
- TMEDIA_CODEC_VIDEO(self)->in.height = TMEDIA_CODEC_VIDEO(self)->out.height = 144;
- TMEDIA_CODEC_VIDEO(self)->in.fps = TMEDIA_CODEC_VIDEO(self)->out.fps = 15;
- TMEDIA_CODEC_VIDEO(self)->in.chroma = tmedia_chroma_yuv420p;// no choice
-
- return 0;
+ int ret = 0;
+
+ if(!self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if((ret = tdav_codec_h264_common_init(TDAV_CODEC_H264_COMMON(self)))) {
+ TSK_DEBUG_ERROR("tdav_codec_h264_common_init() faile with error code=%d", ret);
+ return ret;
+ }
+
+ if(!self->decoder.mutex && !(self->decoder.mutex = tsk_mutex_create_2(tsk_false))) {
+ TSK_DEBUG_ERROR("Failed to create mutex");
+ return -2;
+ }
+
+ sem = tsk_semaphore_create_2(1);
+
+ TDAV_CODEC_H264_COMMON(self)->pack_mode_local = H264_PACKETIZATION_MODE;
+ TDAV_CODEC_H264_COMMON(self)->profile = profile;
+ TMEDIA_CODEC_VIDEO(self)->in.max_mbps = TMEDIA_CODEC_VIDEO(self)->out.max_mbps = H264_MAX_MBPS*1000;
+ TMEDIA_CODEC_VIDEO(self)->in.max_br = TMEDIA_CODEC_VIDEO(self)->out.max_br = H264_MAX_BR*1000;
+
+ // At this time self->plugin is Null
+ TMEDIA_CODEC_VIDEO(self)->in.width = TMEDIA_CODEC_VIDEO(self)->out.width = 176;
+ TMEDIA_CODEC_VIDEO(self)->in.height = TMEDIA_CODEC_VIDEO(self)->out.height = 144;
+ TMEDIA_CODEC_VIDEO(self)->in.fps = TMEDIA_CODEC_VIDEO(self)->out.fps = 15;
+ TMEDIA_CODEC_VIDEO(self)->in.chroma = tmedia_chroma_yuv420p;// no choice
+
+ return 0;
}
static int tdav_codec_h264_cuda_deinit(tdav_codec_h264_cuda_t* self)
{
- tdav_codec_h264_cuda_t* h264 = (tdav_codec_h264_cuda_t*)self;
-
- if(!h264){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- if(h264->encoder.context){
+ tdav_codec_h264_cuda_t* h264 = (tdav_codec_h264_cuda_t*)self;
+
+ if(!h264) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if(h264->encoder.context) {
NVDestroyEncoder(h264->encoder.context);
h264->encoder.context = NULL;
}
- TSK_FREE(h264->encoder.buffer);
- h264->encoder.buffer_size = 0;
+ TSK_FREE(h264->encoder.buffer);
+ h264->encoder.buffer_size = 0;
- if(h264->decoder.context){
+ if(h264->decoder.context) {
cuvidDestroyDecoder(h264->decoder.context);
h264->decoder.context = NULL;
}
- if(h264->decoder.cu_context){
- cuCtxDestroy(h264->decoder.cu_context);
- h264->decoder.cu_context = NULL;
- }
- if (h264->decoder.dx_d3ddevice){
+ if(h264->decoder.cu_context) {
+ cuCtxDestroy(h264->decoder.cu_context);
+ h264->decoder.cu_context = NULL;
+ }
+ if (h264->decoder.dx_d3ddevice) {
h264->decoder.dx_d3ddevice->Release();
h264->decoder.dx_d3ddevice = NULL;
}
- if (h264->decoder.dx_d3d){
+ if (h264->decoder.dx_d3d) {
h264->decoder.dx_d3d->Release();
h264->decoder.dx_d3d = NULL;
}
- if(h264->decoder.cu_parser){
- cuvidDestroyVideoParser(h264->decoder.cu_parser);
- h264->decoder.cu_parser = NULL;
- }
- if(h264->decoder.cu_buffer){
- cuMemFreeHost(h264->decoder.cu_buffer);
- h264->decoder.cu_buffer = NULL;
- }
- h264->decoder.cu_buffer_size = 0;
- if(self->decoder.mutex){
- tsk_mutex_destroy(&self->decoder.mutex);
- }
-
- TSK_FREE(h264->decoder.accumulator);
- h264->decoder.accumulator_pos = 0;
- h264->decoder.accumulator_size = 0;
-
- return 0;
+ if(h264->decoder.cu_parser) {
+ cuvidDestroyVideoParser(h264->decoder.cu_parser);
+ h264->decoder.cu_parser = NULL;
+ }
+ if(h264->decoder.cu_buffer) {
+ cuMemFreeHost(h264->decoder.cu_buffer);
+ h264->decoder.cu_buffer = NULL;
+ }
+ h264->decoder.cu_buffer_size = 0;
+ if(self->decoder.mutex) {
+ tsk_mutex_destroy(&self->decoder.mutex);
+ }
+
+ TSK_FREE(h264->decoder.accumulator);
+ h264->decoder.accumulator_pos = 0;
+ h264->decoder.accumulator_size = 0;
+
+ return 0;
}
static inline void _tdav_codec_h264_cuda_encap(const tdav_codec_h264_cuda_t* h264, const uint8_t* pdata, tsk_size_t size)
{
- register int32_t i;
- int32_t last_scp, prev_scp;
- static int32_t size_of_scp = sizeof(H264_START_CODE_PREFIX); /* we know it's equal to 4 ..but */
-
- if(!pdata || !size){
- return;
- }
-
- last_scp = 0, prev_scp = 0;
-
- for(i = size_of_scp; i<(int32_t)(size - size_of_scp); i++){
- if(pdata[i] == H264_START_CODE_PREFIX[0] && pdata[i+1] == H264_START_CODE_PREFIX[1] && pdata[i+2] == H264_START_CODE_PREFIX[2] && pdata[i+3] == H264_START_CODE_PREFIX[3]){ /* Found Start Code Prefix */
- prev_scp = last_scp;
- if((i - last_scp) >= H264_RTP_PAYLOAD_SIZE || 1){
- tdav_codec_h264_rtp_callback(TDAV_CODEC_H264_COMMON(h264), pdata + prev_scp,
- (i - prev_scp), (prev_scp == size));
- }
- last_scp = i;
- }
- }
- if(last_scp < (int32_t)size){
- tdav_codec_h264_rtp_callback(TDAV_CODEC_H264_COMMON(h264), pdata + last_scp,
- (size - last_scp), tsk_true);
- }
+ register int32_t i;
+ int32_t last_scp, prev_scp;
+ static int32_t size_of_scp = sizeof(H264_START_CODE_PREFIX); /* we know it's equal to 4 ..but */
+
+ if(!pdata || !size) {
+ return;
+ }
+
+ last_scp = 0, prev_scp = 0;
+
+ for(i = size_of_scp; i<(int32_t)(size - size_of_scp); i++) {
+ if(pdata[i] == H264_START_CODE_PREFIX[0] && pdata[i+1] == H264_START_CODE_PREFIX[1] && pdata[i+2] == H264_START_CODE_PREFIX[2] && pdata[i+3] == H264_START_CODE_PREFIX[3]) { /* Found Start Code Prefix */
+ prev_scp = last_scp;
+ if((i - last_scp) >= H264_RTP_PAYLOAD_SIZE || 1) {
+ tdav_codec_h264_rtp_callback(TDAV_CODEC_H264_COMMON(h264), pdata + prev_scp,
+ (i - prev_scp), (prev_scp == size));
+ }
+ last_scp = i;
+ }
+ }
+ if(last_scp < (int32_t)size) {
+ tdav_codec_h264_rtp_callback(TDAV_CODEC_H264_COMMON(h264), pdata + last_scp,
+ (size - last_scp), tsk_true);
+ }
}
static inline tsk_size_t _tdav_codec_h264_cuda_pict_layout(tdav_codec_h264_cuda_t* self, void**output, tsk_size_t *output_size)
{
- if(self && self->decoder.cu_buffer && self->decoder.cu_buffer_size){
- unsigned int w = TMEDIA_CODEC_VIDEO(self)->in.width;
- unsigned int h = TMEDIA_CODEC_VIDEO(self)->in.height;
- unsigned int pitch = self->decoder.cu_buffer_pitch;
- tsk_size_t xsize = (w * h * 3) >> 1;
- // resize if too short
- if(*output_size<xsize){
- if((*output = tsk_realloc(*output, xsize))){
- *output_size = xsize;
- }
- else{
- *output_size = 0;
- return 0;
- }
- }
-
- tsk_semaphore_decrement(sem);
-
- register unsigned int y;
- register unsigned int x, x2;
+ if(self && self->decoder.cu_buffer && self->decoder.cu_buffer_size) {
+ unsigned int w = TMEDIA_CODEC_VIDEO(self)->in.width;
+ unsigned int h = TMEDIA_CODEC_VIDEO(self)->in.height;
+ unsigned int pitch = self->decoder.cu_buffer_pitch;
+ tsk_size_t xsize = (w * h * 3) >> 1;
+ // resize if too short
+ if(*output_size<xsize) {
+ if((*output = tsk_realloc(*output, xsize))) {
+ *output_size = xsize;
+ }
+ else {
+ *output_size = 0;
+ return 0;
+ }
+ }
+
+ tsk_semaphore_decrement(sem);
+
+ register unsigned int y;
+ register unsigned int x, x2;
const unsigned char *p = (const unsigned char *)self->decoder.cu_buffer;
register unsigned char *iyuv = (unsigned char *)*output, *i = iyuv, *j;
- // copy luma
- for (y=0; y<h; y++){
+ // copy luma
+ for (y=0; y<h; y++) {
memcpy(i+y*w, p+y*pitch, w);
}
- // de-interleave chroma (NV12 stored as U,V,U,V,...)
+ // de-interleave chroma (NV12 stored as U,V,U,V,...)
p += h * pitch;
- i += h * w;
- j = i + (h/2)*(w/2);
- for (y=0; y<h/2; y++){
- for (x=0, x2=0; x<w/2; x++, x2+=2) i[x] = p[x2], j[x] = p[x2+1];
- p += pitch, i += w/2, j += w/2;
+ i += h * w;
+ j = i + (h/2)*(w/2);
+ for (y=0; y<h/2; y++) {
+ for (x=0, x2=0; x<w/2; x++, x2+=2) {
+ i[x] = p[x2], j[x] = p[x2+1];
+ }
+ p += pitch, i += w/2, j += w/2;
}
- tsk_semaphore_increment(sem);
+ tsk_semaphore_increment(sem);
- return xsize;
- }
- return 0;
+ return xsize;
+ }
+ return 0;
}
static int CUDAAPI _NVCallback_HandleVideoSequence(void *pvUserData, CUVIDEOFORMAT *pFormat)
{
- tdav_codec_h264_cuda_t* h264 = (tdav_codec_h264_cuda_t*)pvUserData;
- if(!h264 || !pFormat){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;//error
- }
-
- int ret = 1;
-
- if(pFormat->coded_width != TMEDIA_CODEC_VIDEO(h264)->in.width || pFormat->coded_height != TMEDIA_CODEC_VIDEO(h264)->in.height){
- tsk_mutex_lock(h264->decoder.mutex);
-
- TMEDIA_CODEC_VIDEO(h264)->in.width = pFormat->coded_width;
- TMEDIA_CODEC_VIDEO(h264)->in.height = pFormat->coded_height;
-
- InitH264DecoderInfo(h264);
- CUresult cuResult;
- if(h264->decoder.context){
- cuResult = cuvidDestroyDecoder(h264->decoder.context);
- if(CUDA_SUCCESS != cuResult){
- TSK_DEBUG_ERROR("cuvidDestroyDecoder failed with error code=%d", (int)cuResult);
- ret = 0;
- }
- h264->decoder.context = NULL;
- }
- cuResult = cuvidCreateDecoder(&h264->decoder.context, &h264->decoder.info);
- if(CUDA_SUCCESS != cuResult){
- TSK_DEBUG_ERROR("cuvidCreateDecoder failed with error code=%d", (int)cuResult);
- ret = 0;
- }
-
- tsk_mutex_unlock(h264->decoder.mutex);
- }
-
-
-
- return ret;//success
+ tdav_codec_h264_cuda_t* h264 = (tdav_codec_h264_cuda_t*)pvUserData;
+ if(!h264 || !pFormat) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;//error
+ }
+
+ int ret = 1;
+
+ if(pFormat->coded_width != TMEDIA_CODEC_VIDEO(h264)->in.width || pFormat->coded_height != TMEDIA_CODEC_VIDEO(h264)->in.height) {
+ tsk_mutex_lock(h264->decoder.mutex);
+
+ TMEDIA_CODEC_VIDEO(h264)->in.width = pFormat->coded_width;
+ TMEDIA_CODEC_VIDEO(h264)->in.height = pFormat->coded_height;
+
+ InitH264DecoderInfo(h264);
+ CUresult cuResult;
+ if(h264->decoder.context) {
+ cuResult = cuvidDestroyDecoder(h264->decoder.context);
+ if(CUDA_SUCCESS != cuResult) {
+ TSK_DEBUG_ERROR("cuvidDestroyDecoder failed with error code=%d", (int)cuResult);
+ ret = 0;
+ }
+ h264->decoder.context = NULL;
+ }
+ cuResult = cuvidCreateDecoder(&h264->decoder.context, &h264->decoder.info);
+ if(CUDA_SUCCESS != cuResult) {
+ TSK_DEBUG_ERROR("cuvidCreateDecoder failed with error code=%d", (int)cuResult);
+ ret = 0;
+ }
+
+ tsk_mutex_unlock(h264->decoder.mutex);
+ }
+
+
+
+ return ret;//success
}
static int CUDAAPI _NVCallback_HandlePictureDecode(void *pvUserData, CUVIDPICPARAMS *pPicParams)
{
- tdav_codec_h264_cuda_t* h264 = (tdav_codec_h264_cuda_t*)pvUserData;
- if(!h264 || !pPicParams){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;//error
- }
+ tdav_codec_h264_cuda_t* h264 = (tdav_codec_h264_cuda_t*)pvUserData;
+ if(!h264 || !pPicParams) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;//error
+ }
- tsk_mutex_lock(h264->decoder.mutex);
- CUresult cuResult = cuvidDecodePicture(h264->decoder.context, pPicParams);
- tsk_mutex_unlock(h264->decoder.mutex);
+ tsk_mutex_lock(h264->decoder.mutex);
+ CUresult cuResult = cuvidDecodePicture(h264->decoder.context, pPicParams);
+ tsk_mutex_unlock(h264->decoder.mutex);
- if(cuResult != CUDA_SUCCESS){
- TSK_DEBUG_ERROR("cuvidDecodePicture failed with error code= %d", cuResult);
- return 0;//error
+ if(cuResult != CUDA_SUCCESS) {
+ TSK_DEBUG_ERROR("cuvidDecodePicture failed with error code= %d", cuResult);
+ return 0;//error
}
- return 1;//success
+ return 1;//success
}
static int CUDAAPI _NVCallback_HandlePictureDisplay(void *pvUserData, CUVIDPARSERDISPINFO *pPicParams)
{
- tdav_codec_h264_cuda_t* h264 = (tdav_codec_h264_cuda_t*)pvUserData;
- CUVIDPROCPARAMS vpp;
- CUdeviceptr devPtr;
- CUresult cuResult;
- tsk_size_t nv12_size;
- tsk_bool_t mapped = tsk_false;
- int ret = 1;//success
-
- if(!h264 || !pPicParams){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;//error
- }
-tsk_semaphore_decrement(sem);
- cuResult = cuCtxPushCurrent(h264->decoder.cu_context);
- if(cuResult != CUDA_SUCCESS){
- TSK_DEBUG_ERROR("cuCtxPushCurrent failed with error code = %d", (int)cuResult);
- ret = 0;//error
- goto bail;
- }
-
- memset(&vpp, 0, sizeof(vpp));
- vpp.progressive_frame = pPicParams->progressive_frame;
- vpp.top_field_first = pPicParams->top_field_first;
- cuResult = cuvidMapVideoFrame(h264->decoder.context, pPicParams->picture_index, &devPtr, &h264->decoder.cu_buffer_pitch, &vpp);
-
- if(cuResult != CUDA_SUCCESS){
- TSK_DEBUG_ERROR("cuvidMapVideoFrame failed with error code = %d", (int)cuResult);
- ret = 0;//error
- goto bail;
- }
- mapped = tsk_true;
- nv12_size = h264->decoder.cu_buffer_pitch * (h264->decoder.info.ulTargetHeight + h264->decoder.info.ulTargetHeight/2); // 12bpp
- //nv12_size = (w * h * 3) >> 1;
- if ((!h264->decoder.cu_buffer) || (nv12_size > h264->decoder.cu_buffer_size)){
- h264->decoder.cu_buffer_size = 0;
- if (h264->decoder.cu_buffer){
- cuResult = cuMemFreeHost(h264->decoder.cu_buffer);
- h264->decoder.cu_buffer = NULL;
- }
- cuResult = cuMemAllocHost((void**)&h264->decoder.cu_buffer, nv12_size);
- if (cuResult != CUDA_SUCCESS){
- TSK_DEBUG_ERROR("cuMemAllocHost failed to allocate %d bytes (error code=%d)", nv12_size, (int)cuResult);
- h264->decoder.cu_buffer = 0;
- h264->decoder.cu_buffer_size = 0;
- ret = 0;//error
- }
- else{
- h264->decoder.cu_buffer_size = nv12_size;
- }
- }
- if(h264->decoder.cu_buffer){
- cuResult = cuMemcpyDtoH(h264->decoder.cu_buffer, devPtr, nv12_size);
- }
+ tdav_codec_h264_cuda_t* h264 = (tdav_codec_h264_cuda_t*)pvUserData;
+ CUVIDPROCPARAMS vpp;
+ CUdeviceptr devPtr;
+ CUresult cuResult;
+ tsk_size_t nv12_size;
+ tsk_bool_t mapped = tsk_false;
+ int ret = 1;//success
+
+ if(!h264 || !pPicParams) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;//error
+ }
+ tsk_semaphore_decrement(sem);
+ cuResult = cuCtxPushCurrent(h264->decoder.cu_context);
+ if(cuResult != CUDA_SUCCESS) {
+ TSK_DEBUG_ERROR("cuCtxPushCurrent failed with error code = %d", (int)cuResult);
+ ret = 0;//error
+ goto bail;
+ }
+
+ memset(&vpp, 0, sizeof(vpp));
+ vpp.progressive_frame = pPicParams->progressive_frame;
+ vpp.top_field_first = pPicParams->top_field_first;
+ cuResult = cuvidMapVideoFrame(h264->decoder.context, pPicParams->picture_index, &devPtr, &h264->decoder.cu_buffer_pitch, &vpp);
+
+ if(cuResult != CUDA_SUCCESS) {
+ TSK_DEBUG_ERROR("cuvidMapVideoFrame failed with error code = %d", (int)cuResult);
+ ret = 0;//error
+ goto bail;
+ }
+ mapped = tsk_true;
+ nv12_size = h264->decoder.cu_buffer_pitch * (h264->decoder.info.ulTargetHeight + h264->decoder.info.ulTargetHeight/2); // 12bpp
+ //nv12_size = (w * h * 3) >> 1;
+ if ((!h264->decoder.cu_buffer) || (nv12_size > h264->decoder.cu_buffer_size)) {
+ h264->decoder.cu_buffer_size = 0;
+ if (h264->decoder.cu_buffer) {
+ cuResult = cuMemFreeHost(h264->decoder.cu_buffer);
+ h264->decoder.cu_buffer = NULL;
+ }
+ cuResult = cuMemAllocHost((void**)&h264->decoder.cu_buffer, nv12_size);
+ if (cuResult != CUDA_SUCCESS) {
+ TSK_DEBUG_ERROR("cuMemAllocHost failed to allocate %d bytes (error code=%d)", nv12_size, (int)cuResult);
+ h264->decoder.cu_buffer = 0;
+ h264->decoder.cu_buffer_size = 0;
+ ret = 0;//error
+ }
+ else {
+ h264->decoder.cu_buffer_size = nv12_size;
+ }
+ }
+ if(h264->decoder.cu_buffer) {
+ cuResult = cuMemcpyDtoH(h264->decoder.cu_buffer, devPtr, nv12_size);
+ }
bail:
- if(mapped){
- cuResult = cuvidUnmapVideoFrame(h264->decoder.context, devPtr);
- }
- cuResult = cuCtxPopCurrent(NULL);
-tsk_semaphore_increment(sem);
- h264->decoder.cu_buffer_avail = (ret == 1);
- return ret;
+ if(mapped) {
+ cuResult = cuvidUnmapVideoFrame(h264->decoder.context, devPtr);
+ }
+ cuResult = cuCtxPopCurrent(NULL);
+ tsk_semaphore_increment(sem);
+ h264->decoder.cu_buffer_avail = (ret == 1);
+ return ret;
}
static unsigned char* CUDAAPI _NVCallback_HandleAcquireBitStream(int *pBufferSize, void *pUserdata)
{
- tdav_codec_h264_cuda_t* h264 = (tdav_codec_h264_cuda_t*)pUserdata;
- if(!h264 || !pBufferSize){
- TSK_DEBUG_ERROR("Invalid parameter");
- return tsk_null;
- }
-
- *pBufferSize = (int)h264->encoder.buffer_size;
- return (unsigned char*)h264->encoder.buffer;
+ tdav_codec_h264_cuda_t* h264 = (tdav_codec_h264_cuda_t*)pUserdata;
+ if(!h264 || !pBufferSize) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return tsk_null;
+ }
+
+ *pBufferSize = (int)h264->encoder.buffer_size;
+ return (unsigned char*)h264->encoder.buffer;
}
static void CUDAAPI _NVCallback_HandleReleaseBitStream(int nBytesInBuffer, unsigned char *cb,void *pUserdata)
{
tdav_codec_h264_cuda_t* h264 = (tdav_codec_h264_cuda_t*)pUserdata;
- if(!h264 || !cb || !nBytesInBuffer){
- TSK_DEBUG_ERROR("Invalid parameter");
- return;
- }
- _tdav_codec_h264_cuda_encap(h264, cb, (tsk_size_t)nBytesInBuffer);
-
+ if(!h264 || !cb || !nBytesInBuffer) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return;
+ }
+ _tdav_codec_h264_cuda_encap(h264, cb, (tsk_size_t)nBytesInBuffer);
+
return;
}
@@ -941,60 +1020,58 @@ static void CUDAAPI _NVCallback_HandleOnEndFrame(const NVVE_EndFrameInfo *pefi,
/* constructor */
static tsk_object_t* tdav_codec_h264_cuda_bp10_ctor(tsk_object_t * self, va_list * app)
{
- tdav_codec_h264_cuda_t *h264 = (tdav_codec_h264_cuda_t *)self;
- if(h264){
- /* init base: called by tmedia_codec_create() */
- /* init self */
- tdav_codec_h264_cuda_init(h264, tdav_codec_h264_bp10);
- }
- return self;
+ tdav_codec_h264_cuda_t *h264 = (tdav_codec_h264_cuda_t *)self;
+ if(h264) {
+ /* init base: called by tmedia_codec_create() */
+ /* init self */
+ tdav_codec_h264_cuda_init(h264, tdav_codec_h264_bp10);
+ }
+ return self;
}
/* destructor */
static tsk_object_t* tdav_codec_h264_cuda_bp10_dtor(tsk_object_t * self)
-{
- tdav_codec_h264_cuda_t *h264 = (tdav_codec_h264_cuda_t *)self;
- if(h264){
- /* deinit base */
- tdav_codec_h264_common_deinit(TDAV_CODEC_H264_COMMON(self));
- /* deinit self */
- tdav_codec_h264_cuda_deinit(h264);
- }
-
- return self;
+{
+ tdav_codec_h264_cuda_t *h264 = (tdav_codec_h264_cuda_t *)self;
+ if(h264) {
+ /* deinit base */
+ tdav_codec_h264_common_deinit(TDAV_CODEC_H264_COMMON(self));
+ /* deinit self */
+ tdav_codec_h264_cuda_deinit(h264);
+ }
+
+ return self;
}
/* object definition */
-static const tsk_object_def_t tdav_codec_h264_cuda_bp10_def_s =
-{
- sizeof(tdav_codec_h264_cuda_t),
- tdav_codec_h264_cuda_bp10_ctor,
- tdav_codec_h264_cuda_bp10_dtor,
- tmedia_codec_cmp,
+static const tsk_object_def_t tdav_codec_h264_cuda_bp10_def_s = {
+ sizeof(tdav_codec_h264_cuda_t),
+ tdav_codec_h264_cuda_bp10_ctor,
+ tdav_codec_h264_cuda_bp10_dtor,
+ tmedia_codec_cmp,
};
/* plugin definition*/
-static const tmedia_codec_plugin_def_t tdav_codec_h264_cuda_bp10_plugin_def_s =
-{
- &tdav_codec_h264_cuda_bp10_def_s,
-
- tmedia_video,
- "H264",
- "H264 Base Profile 1.0 using CUDA",
- TMEDIA_CODEC_FORMAT_H264_BP10,
- tsk_true,
- 90000, // rate
-
- /* audio */
- { 0 },
-
- /* video */
- {176, 144, 15},
-
- tdav_codec_h264_cuda_open,
- tdav_codec_h264_cuda_close,
- tdav_codec_h264_cuda_encode,
- tdav_codec_h264_cuda_decode,
- tdav_codec_h264_cuda_sdp_att_match,
- tdav_codec_h264_cuda_sdp_att_get,
- tdav_codec_h264_cuda_fmtp_set
+static const tmedia_codec_plugin_def_t tdav_codec_h264_cuda_bp10_plugin_def_s = {
+ &tdav_codec_h264_cuda_bp10_def_s,
+
+ tmedia_video,
+ "H264",
+ "H264 Base Profile 1.0 using CUDA",
+ TMEDIA_CODEC_FORMAT_H264_BP10,
+ tsk_true,
+ 90000, // rate
+
+ /* audio */
+ { 0 },
+
+ /* video */
+ {176, 144, 15},
+
+ tdav_codec_h264_cuda_open,
+ tdav_codec_h264_cuda_close,
+ tdav_codec_h264_cuda_encode,
+ tdav_codec_h264_cuda_decode,
+ tdav_codec_h264_cuda_sdp_att_match,
+ tdav_codec_h264_cuda_sdp_att_get,
+ tdav_codec_h264_cuda_fmtp_set
};
extern const tmedia_codec_plugin_def_t *tdav_codec_h264_cuda_bp10_plugin_def_t = &tdav_codec_h264_cuda_bp10_plugin_def_s;
@@ -1004,61 +1081,59 @@ extern const tmedia_codec_plugin_def_t *tdav_codec_h264_cuda_bp10_plugin_def_t =
/* constructor */
static tsk_object_t* tdav_codec_h264_cuda_bp20_ctor(tsk_object_t * self, va_list * app)
{
- tdav_codec_h264_cuda_t *h264 = (tdav_codec_h264_cuda_t *)self;
- if(h264){
- /* init base: called by tmedia_codec_create() */
- /* init self */
- tdav_codec_h264_cuda_init(h264, tdav_codec_h264_bp20);
- }
- return self;
+ tdav_codec_h264_cuda_t *h264 = (tdav_codec_h264_cuda_t *)self;
+ if(h264) {
+ /* init base: called by tmedia_codec_create() */
+ /* init self */
+ tdav_codec_h264_cuda_init(h264, tdav_codec_h264_bp20);
+ }
+ return self;
}
/* destructor */
static tsk_object_t* tdav_codec_h264_cuda_bp20_dtor(tsk_object_t * self)
-{
- tdav_codec_h264_cuda_t *h264 = (tdav_codec_h264_cuda_t *)self;
- if(h264){
- /* deinit base */
- tdav_codec_h264_common_deinit(TDAV_CODEC_H264_COMMON(self));
- /* deinit self */
- tdav_codec_h264_cuda_deinit(h264);
-
- }
-
- return self;
+{
+ tdav_codec_h264_cuda_t *h264 = (tdav_codec_h264_cuda_t *)self;
+ if(h264) {
+ /* deinit base */
+ tdav_codec_h264_common_deinit(TDAV_CODEC_H264_COMMON(self));
+ /* deinit self */
+ tdav_codec_h264_cuda_deinit(h264);
+
+ }
+
+ return self;
}
/* object definition */
-static const tsk_object_def_t tdav_codec_h264_cuda_bp20_def_s =
-{
- sizeof(tdav_codec_h264_cuda_t),
- tdav_codec_h264_cuda_bp20_ctor,
- tdav_codec_h264_cuda_bp20_dtor,
- tmedia_codec_cmp,
+static const tsk_object_def_t tdav_codec_h264_cuda_bp20_def_s = {
+ sizeof(tdav_codec_h264_cuda_t),
+ tdav_codec_h264_cuda_bp20_ctor,
+ tdav_codec_h264_cuda_bp20_dtor,
+ tmedia_codec_cmp,
};
/* plugin definition*/
-static const tmedia_codec_plugin_def_t tdav_codec_h264_cuda_bp20_plugin_def_s =
-{
- &tdav_codec_h264_cuda_bp20_def_s,
-
- tmedia_video,
- "H264",
- "H264 Base Profile 2.0 using CUDA",
- TMEDIA_CODEC_FORMAT_H264_BP20,
- tsk_true,
- 90000, // rate
-
- /* audio */
- { 0 },
-
- /* video */
- {352, 288, 15},
-
- tdav_codec_h264_cuda_open,
- tdav_codec_h264_cuda_close,
- tdav_codec_h264_cuda_encode,
- tdav_codec_h264_cuda_decode,
- tdav_codec_h264_cuda_sdp_att_match,
- tdav_codec_h264_cuda_sdp_att_get,
- tdav_codec_h264_cuda_fmtp_set
+static const tmedia_codec_plugin_def_t tdav_codec_h264_cuda_bp20_plugin_def_s = {
+ &tdav_codec_h264_cuda_bp20_def_s,
+
+ tmedia_video,
+ "H264",
+ "H264 Base Profile 2.0 using CUDA",
+ TMEDIA_CODEC_FORMAT_H264_BP20,
+ tsk_true,
+ 90000, // rate
+
+ /* audio */
+ { 0 },
+
+ /* video */
+ {352, 288, 15},
+
+ tdav_codec_h264_cuda_open,
+ tdav_codec_h264_cuda_close,
+ tdav_codec_h264_cuda_encode,
+ tdav_codec_h264_cuda_decode,
+ tdav_codec_h264_cuda_sdp_att_match,
+ tdav_codec_h264_cuda_sdp_att_get,
+ tdav_codec_h264_cuda_fmtp_set
};
extern const tmedia_codec_plugin_def_t *tdav_codec_h264_cuda_bp20_plugin_def_t = &tdav_codec_h264_cuda_bp20_plugin_def_s;
@@ -1068,61 +1143,59 @@ extern const tmedia_codec_plugin_def_t *tdav_codec_h264_cuda_bp20_plugin_def_t =
/* constructor */
static tsk_object_t* tdav_codec_h264_cuda_bp30_ctor(tsk_object_t * self, va_list * app)
{
- tdav_codec_h264_cuda_t *h264 = (tdav_codec_h264_cuda_t *)self;
- if(h264){
- /* init base: called by tmedia_codec_create() */
- /* init self */
- tdav_codec_h264_cuda_init(h264, tdav_codec_h264_bp30);
- }
- return self;
+ tdav_codec_h264_cuda_t *h264 = (tdav_codec_h264_cuda_t *)self;
+ if(h264) {
+ /* init base: called by tmedia_codec_create() */
+ /* init self */
+ tdav_codec_h264_cuda_init(h264, tdav_codec_h264_bp30);
+ }
+ return self;
}
/* destructor */
static tsk_object_t* tdav_codec_h264_cuda_bp30_dtor(tsk_object_t * self)
-{
- tdav_codec_h264_cuda_t *h264 = (tdav_codec_h264_cuda_t *)self;
- if(h264){
- /* deinit base */
- tdav_codec_h264_common_deinit(TDAV_CODEC_H264_COMMON(self));
- /* deinit self */
- tdav_codec_h264_cuda_deinit(h264);
-
- }
-
- return self;
+{
+ tdav_codec_h264_cuda_t *h264 = (tdav_codec_h264_cuda_t *)self;
+ if(h264) {
+ /* deinit base */
+ tdav_codec_h264_common_deinit(TDAV_CODEC_H264_COMMON(self));
+ /* deinit self */
+ tdav_codec_h264_cuda_deinit(h264);
+
+ }
+
+ return self;
}
/* object definition */
-static const tsk_object_def_t tdav_codec_h264_cuda_bp30_def_s =
-{
- sizeof(tdav_codec_h264_cuda_t),
- tdav_codec_h264_cuda_bp30_ctor,
- tdav_codec_h264_cuda_bp30_dtor,
- tmedia_codec_cmp,
+static const tsk_object_def_t tdav_codec_h264_cuda_bp30_def_s = {
+ sizeof(tdav_codec_h264_cuda_t),
+ tdav_codec_h264_cuda_bp30_ctor,
+ tdav_codec_h264_cuda_bp30_dtor,
+ tmedia_codec_cmp,
};
/* plugin definition*/
-static const tmedia_codec_plugin_def_t tdav_codec_h264_cuda_bp30_plugin_def_s =
-{
- &tdav_codec_h264_cuda_bp30_def_s,
-
- tmedia_video,
- "H264",
- "H264 Base Profile 3.0 using CUDA",
- TMEDIA_CODEC_FORMAT_H264_BP30,
- tsk_true,
- 90000, // rate
-
- /* audio */
- { 0 },
-
- /* video */
- {352, 288, 15},
-
- tdav_codec_h264_cuda_open,
- tdav_codec_h264_cuda_close,
- tdav_codec_h264_cuda_encode,
- tdav_codec_h264_cuda_decode,
- tdav_codec_h264_cuda_sdp_att_match,
- tdav_codec_h264_cuda_sdp_att_get,
- tdav_codec_h264_cuda_fmtp_set
+static const tmedia_codec_plugin_def_t tdav_codec_h264_cuda_bp30_plugin_def_s = {
+ &tdav_codec_h264_cuda_bp30_def_s,
+
+ tmedia_video,
+ "H264",
+ "H264 Base Profile 3.0 using CUDA",
+ TMEDIA_CODEC_FORMAT_H264_BP30,
+ tsk_true,
+ 90000, // rate
+
+ /* audio */
+ { 0 },
+
+ /* video */
+ {352, 288, 15},
+
+ tdav_codec_h264_cuda_open,
+ tdav_codec_h264_cuda_close,
+ tdav_codec_h264_cuda_encode,
+ tdav_codec_h264_cuda_decode,
+ tdav_codec_h264_cuda_sdp_att_match,
+ tdav_codec_h264_cuda_sdp_att_get,
+ tdav_codec_h264_cuda_fmtp_set
};
extern const tmedia_codec_plugin_def_t *tdav_codec_h264_cuda_bp30_plugin_def_t = &tdav_codec_h264_cuda_bp30_plugin_def_s;
diff --git a/tinyDAV/src/codecs/h264/tdav_codec_h264_intel.cxx b/tinyDAV/src/codecs/h264/tdav_codec_h264_intel.cxx
index 49f9e1c..7ef6b2c 100755
--- a/tinyDAV/src/codecs/h264/tdav_codec_h264_intel.cxx
+++ b/tinyDAV/src/codecs/h264/tdav_codec_h264_intel.cxx
@@ -76,9 +76,9 @@
static mfxIMPL __IntelDefaultImpl = MFX_IMPL_AUTO_ANY
#if INTEL_DX11_D3D
-| MFX_IMPL_VIA_D3D11
+ | MFX_IMPL_VIA_D3D11
#endif
-;
+ ;
static mfxVersion __IntelDefaultVer = { 0, 1 };
// TODO: Test against FFmpeg, CUDA, OpenH264 and Microsoft implementations
@@ -87,40 +87,39 @@ static mfxVersion __IntelDefaultVer = { 0, 1 };
class IntelCodecEncoder;
class IntelCodecDecoder;
-typedef struct tdav_codec_h264_intel_s
-{
- TDAV_DECLARE_CODEC_H264_COMMON;
+typedef struct tdav_codec_h264_intel_s {
+ TDAV_DECLARE_CODEC_H264_COMMON;
- MFXVideoSession* mfxSession;
+ MFXVideoSession* mfxSession;
- // DX11_D3D
+ // DX11_D3D
#if INTEL_DX11_D3D
- mfxFrameAllocResponse D3D11SavedAllocResponses[2/*Encode=0, Decode=1*/];
- mfxFrameAllocator D3D11Allocator;
-
- CComPtr<ID3D11Device> pD3D11Device;
- CComPtr<ID3D11DeviceContext> pD3D11Ctx;
- CComPtr<IDXGIAdapter>pAdapter;
- CComPtr<IDXGIFactory1> pDXGIFactory;
- CComPtr<IDXGIAdapter> hAdapter;
+ mfxFrameAllocResponse D3D11SavedAllocResponses[2/*Encode=0, Decode=1*/];
+ mfxFrameAllocator D3D11Allocator;
+
+ CComPtr<ID3D11Device> pD3D11Device;
+ CComPtr<ID3D11DeviceContext> pD3D11Ctx;
+ CComPtr<IDXGIAdapter>pAdapter;
+ CComPtr<IDXGIFactory1> pDXGIFactory;
+ CComPtr<IDXGIAdapter> hAdapter;
#endif
- // Encoder
- struct{
- IntelCodecEncoder *pInst;
- int64_t frame_count;
- tsk_bool_t force_idr;
- int rotation;
- int neg_width;
- int neg_height;
- int neg_fps;
- int max_bitrate_bps;
- } encoder;
-
- // decoder
- struct{
- IntelCodecDecoder *pInst;
- } decoder;
+ // Encoder
+ struct {
+ IntelCodecEncoder *pInst;
+ int64_t frame_count;
+ tsk_bool_t force_idr;
+ int rotation;
+ int neg_width;
+ int neg_height;
+ int neg_fps;
+ int max_bitrate_bps;
+ } encoder;
+
+ // decoder
+ struct {
+ IntelCodecDecoder *pInst;
+ } decoder;
}
tdav_codec_h264_intel_t;
@@ -140,19 +139,19 @@ static int tdav_codec_h264_intel_close_decoder(tdav_codec_h264_intel_t* self);
#define D3D11_WILL_WRITE 0x2000
typedef struct {
- mfxMemId memId;
- mfxMemId memIdStage;
- mfxU16 rw;
+ mfxMemId memId;
+ mfxMemId memIdStage;
+ mfxU16 rw;
} CustomMemId;
const struct {
- mfxIMPL impl; // actual implementation
- mfxU32 adapterID; // device adapter number
+ mfxIMPL impl; // actual implementation
+ mfxU32 adapterID; // device adapter number
} implTypes[] = {
- { MFX_IMPL_HARDWARE, 0 },
- { MFX_IMPL_HARDWARE2, 1 },
- { MFX_IMPL_HARDWARE3, 2 },
- { MFX_IMPL_HARDWARE4, 3 }
+ { MFX_IMPL_HARDWARE, 0 },
+ { MFX_IMPL_HARDWARE2, 1 },
+ { MFX_IMPL_HARDWARE3, 2 },
+ { MFX_IMPL_HARDWARE4, 3 }
};
static mfxStatus D3D11_CreateHWDevice(mfxHDL pthis, mfxSession session, mfxHDL* deviceHandle, HWND hWnd);
@@ -174,245 +173,225 @@ static mfxStatus D3D11_SimpleFree(mfxHDL pthis, mfxFrameAllocResponse *response)
class IntelCodec
{
protected:
- IntelCodec(MFXVideoSession* pSession)
- : m_bOpened(false)
- , m_pSession(pSession)
- , n_nNumSurfaces(0)
- , m_nSurfaceWidth(0)
- , m_nSurfaceHeight(0)
- , m_nSurfaceBitsPerPixel(0)
- , m_nSurfaceSize(0)
- , m_pSurfaceBuffers(NULL)
- , m_ppSurfacePtrs(NULL)
- {
- memset(&m_sBitstream, 0, sizeof(m_sBitstream));
- memset(&m_sParamReq, 0, sizeof(m_sParamReq));
- memset(&m_sParamSel, 0, sizeof(m_sParamSel));
- memset(&m_sAllocRequest, 0, sizeof(m_sAllocRequest));
- }
+ IntelCodec(MFXVideoSession* pSession)
+ : m_bOpened(false)
+ , m_pSession(pSession)
+ , n_nNumSurfaces(0)
+ , m_nSurfaceWidth(0)
+ , m_nSurfaceHeight(0)
+ , m_nSurfaceBitsPerPixel(0)
+ , m_nSurfaceSize(0)
+ , m_pSurfaceBuffers(NULL)
+ , m_ppSurfacePtrs(NULL) {
+ memset(&m_sBitstream, 0, sizeof(m_sBitstream));
+ memset(&m_sParamReq, 0, sizeof(m_sParamReq));
+ memset(&m_sParamSel, 0, sizeof(m_sParamSel));
+ memset(&m_sAllocRequest, 0, sizeof(m_sAllocRequest));
+ }
public:
- virtual ~IntelCodec()
- {
- Close();
- }
- virtual mfxStatus Open(struct tdav_codec_h264_intel_s* pWrappedCodec) = 0;
+ virtual ~IntelCodec() {
+ Close();
+ }
+ virtual mfxStatus Open(struct tdav_codec_h264_intel_s* pWrappedCodec) = 0;
- virtual mfxStatus Close()
- {
- DeAllocSurfaces();
- DeAllocateBitstream();
+ virtual mfxStatus Close() {
+ DeAllocSurfaces();
+ DeAllocateBitstream();
- memset(&m_sAllocRequest, 0, sizeof(m_sAllocRequest));
+ memset(&m_sAllocRequest, 0, sizeof(m_sAllocRequest));
- m_bOpened = false;
+ m_bOpened = false;
- return MFX_ERR_NONE;
- }
+ return MFX_ERR_NONE;
+ }
protected:
- int GetFreeSurfaceIndex()
- {
- if (m_ppSurfacePtrs)
- {
- for (mfxU16 i = 0; i < n_nNumSurfaces; i++)
- {
- if (0 == m_ppSurfacePtrs[i]->Data.Locked)
- {
- return i;
- }
- }
- }
- return MFX_ERR_NOT_FOUND;
- }
-
- mfxStatus ReadPlaneData(mfxU16 w, mfxU16 h, mfxU8 *buf, mfxU8 *ptr, mfxU16 pitch, mfxU16 offset, const mfxU8* &src)
- {
- for (mfxU16 i = 0; i < h; i++)
- {
- memcpy(buf, src, w);
- src += w;
-
- for (mfxU16 j = 0; j < w; j++)
- ptr[i * pitch + j * 2 + offset] = buf[j];
- }
- return MFX_ERR_NONE;
- }
-
- mfxStatus LoadRawFrame(int nSurfaceIndex, const mfxU8* src)
- {
- mfxFrameSurface1* pSurface = (m_ppSurfacePtrs && nSurfaceIndex >= 0 && nSurfaceIndex < n_nNumSurfaces) ? m_ppSurfacePtrs[nSurfaceIndex] : NULL;
- if (!pSurface)
- {
- INTEL_DEBUG_ERROR("Failed to find surface at index=%d", nSurfaceIndex);
- return MFX_ERR_NOT_FOUND;
- }
-
- mfxStatus sts = MFX_ERR_NONE;
- mfxU16 w, h, i, pitch;
- mfxU8 *ptr;
- mfxFrameInfo* pInfo = &pSurface->Info;
- mfxFrameData* pData = &pSurface->Data;
-
- if (pInfo->CropH > 0 && pInfo->CropW > 0) {
- w = pInfo->CropW;
- h = pInfo->CropH;
- }
- else {
- w = pInfo->Width;
- h = pInfo->Height;
- }
-
- pitch = pData->Pitch;
- ptr = pData->Y + pInfo->CropX + pInfo->CropY * pData->Pitch;
-
- // read luminance plane
- for (i = 0; i < h; i++)
- {
- memcpy(ptr + i * pitch, src, w);
- src += w;
- }
-
- mfxU8 buf[2048]; // maximum supported chroma width for nv12
- w /= 2;
- h /= 2;
- ptr = pData->UV + pInfo->CropX + (pInfo->CropY / 2) * pitch;
- if (w > 2048)
- return MFX_ERR_UNSUPPORTED;
-
- // load U
- sts = ReadPlaneData(w, h, buf, ptr, pitch, 0, src);
- if (MFX_ERR_NONE != sts) return sts;
- // load V
- sts = ReadPlaneData(w, h, buf, ptr, pitch, 1, src);
- if (MFX_ERR_NONE != sts) return sts;
-
- return MFX_ERR_NONE;
- }
-
- virtual mfxStatus AllocSurfaces(mfxU16 nNumSurfaces, mfxU16 nSurfaceWidth, mfxU16 nSurfaceHeight, const mfxFrameInfo* pcFrameInfo)
- {
- mfxStatus status = MFX_ERR_UNKNOWN;
-
- INTEL_DEBUG_INFO("Alloc surfaces: num=%u, width=%u, height=%u", nNumSurfaces, nSurfaceWidth, nSurfaceHeight);
-
- DeAllocSurfaces();
-
- n_nNumSurfaces = nNumSurfaces;
- m_nSurfaceWidth = (mfxU16)INTEL_ALIGN32(nSurfaceWidth);
- m_nSurfaceHeight = (mfxU16)INTEL_ALIGN32(nSurfaceHeight);
- m_nSurfaceBitsPerPixel = 12; // NV12 format is a 12 bits per pixel format
- m_nSurfaceSize = m_nSurfaceWidth * m_nSurfaceHeight * m_nSurfaceBitsPerPixel / 8;
+ int GetFreeSurfaceIndex() {
+ if (m_ppSurfacePtrs) {
+ for (mfxU16 i = 0; i < n_nNumSurfaces; i++) {
+ if (0 == m_ppSurfacePtrs[i]->Data.Locked) {
+ return i;
+ }
+ }
+ }
+ return MFX_ERR_NOT_FOUND;
+ }
+
+ mfxStatus ReadPlaneData(mfxU16 w, mfxU16 h, mfxU8 *buf, mfxU8 *ptr, mfxU16 pitch, mfxU16 offset, const mfxU8* &src) {
+ for (mfxU16 i = 0; i < h; i++) {
+ memcpy(buf, src, w);
+ src += w;
+
+ for (mfxU16 j = 0; j < w; j++) {
+ ptr[i * pitch + j * 2 + offset] = buf[j];
+ }
+ }
+ return MFX_ERR_NONE;
+ }
+
+ mfxStatus LoadRawFrame(int nSurfaceIndex, const mfxU8* src) {
+ mfxFrameSurface1* pSurface = (m_ppSurfacePtrs && nSurfaceIndex >= 0 && nSurfaceIndex < n_nNumSurfaces) ? m_ppSurfacePtrs[nSurfaceIndex] : NULL;
+ if (!pSurface) {
+ INTEL_DEBUG_ERROR("Failed to find surface at index=%d", nSurfaceIndex);
+ return MFX_ERR_NOT_FOUND;
+ }
+
+ mfxStatus sts = MFX_ERR_NONE;
+ mfxU16 w, h, i, pitch;
+ mfxU8 *ptr;
+ mfxFrameInfo* pInfo = &pSurface->Info;
+ mfxFrameData* pData = &pSurface->Data;
+
+ if (pInfo->CropH > 0 && pInfo->CropW > 0) {
+ w = pInfo->CropW;
+ h = pInfo->CropH;
+ }
+ else {
+ w = pInfo->Width;
+ h = pInfo->Height;
+ }
+
+ pitch = pData->Pitch;
+ ptr = pData->Y + pInfo->CropX + pInfo->CropY * pData->Pitch;
+
+ // read luminance plane
+ for (i = 0; i < h; i++) {
+ memcpy(ptr + i * pitch, src, w);
+ src += w;
+ }
+
+ mfxU8 buf[2048]; // maximum supported chroma width for nv12
+ w /= 2;
+ h /= 2;
+ ptr = pData->UV + pInfo->CropX + (pInfo->CropY / 2) * pitch;
+ if (w > 2048) {
+ return MFX_ERR_UNSUPPORTED;
+ }
+
+ // load U
+ sts = ReadPlaneData(w, h, buf, ptr, pitch, 0, src);
+ if (MFX_ERR_NONE != sts) {
+ return sts;
+ }
+ // load V
+ sts = ReadPlaneData(w, h, buf, ptr, pitch, 1, src);
+ if (MFX_ERR_NONE != sts) {
+ return sts;
+ }
+
+ return MFX_ERR_NONE;
+ }
+
+ virtual mfxStatus AllocSurfaces(mfxU16 nNumSurfaces, mfxU16 nSurfaceWidth, mfxU16 nSurfaceHeight, const mfxFrameInfo* pcFrameInfo) {
+ mfxStatus status = MFX_ERR_UNKNOWN;
+
+ INTEL_DEBUG_INFO("Alloc surfaces: num=%u, width=%u, height=%u", nNumSurfaces, nSurfaceWidth, nSurfaceHeight);
+
+ DeAllocSurfaces();
+
+ n_nNumSurfaces = nNumSurfaces;
+ m_nSurfaceWidth = (mfxU16)INTEL_ALIGN32(nSurfaceWidth);
+ m_nSurfaceHeight = (mfxU16)INTEL_ALIGN32(nSurfaceHeight);
+ m_nSurfaceBitsPerPixel = 12; // NV12 format is a 12 bits per pixel format
+ m_nSurfaceSize = m_nSurfaceWidth * m_nSurfaceHeight * m_nSurfaceBitsPerPixel / 8;
#if !INTEL_DX11_D3D
- if (!(m_pSurfaceBuffers = (mfxU8 *)new mfxU8[m_nSurfaceSize * n_nNumSurfaces]))
- {
- INTEL_CHECK_STATUS(MFX_ERR_MEMORY_ALLOC);
- }
+ if (!(m_pSurfaceBuffers = (mfxU8 *)new mfxU8[m_nSurfaceSize * n_nNumSurfaces])) {
+ INTEL_CHECK_STATUS(MFX_ERR_MEMORY_ALLOC);
+ }
#endif
- if (!(m_ppSurfacePtrs = new mfxFrameSurface1*[n_nNumSurfaces]))
- {
- INTEL_CHECK_STATUS(MFX_ERR_MEMORY_ALLOC);
- }
- for (mfxU16 i = 0; i < n_nNumSurfaces; i++)
- {
- if (!(m_ppSurfacePtrs[i] = new mfxFrameSurface1))
- {
- INTEL_CHECK_STATUS(MFX_ERR_MEMORY_ALLOC);
- }
- memset(m_ppSurfacePtrs[i], 0, sizeof(mfxFrameSurface1));
- memcpy(&(m_ppSurfacePtrs[i]->Info), pcFrameInfo, sizeof(mfxFrameInfo));
+ if (!(m_ppSurfacePtrs = new mfxFrameSurface1*[n_nNumSurfaces])) {
+ INTEL_CHECK_STATUS(MFX_ERR_MEMORY_ALLOC);
+ }
+ for (mfxU16 i = 0; i < n_nNumSurfaces; i++) {
+ if (!(m_ppSurfacePtrs[i] = new mfxFrameSurface1)) {
+ INTEL_CHECK_STATUS(MFX_ERR_MEMORY_ALLOC);
+ }
+ memset(m_ppSurfacePtrs[i], 0, sizeof(mfxFrameSurface1));
+ memcpy(&(m_ppSurfacePtrs[i]->Info), pcFrameInfo, sizeof(mfxFrameInfo));
#if INTEL_DX11_D3D
- m_ppSurfacePtrs[i]->Data.MemId = m_sD3D11Response.mids[i]; // MID (memory id) represent one D3D NV12 surface
+ m_ppSurfacePtrs[i]->Data.MemId = m_sD3D11Response.mids[i]; // MID (memory id) represent one D3D NV12 surface
#else
- m_ppSurfacePtrs[i]->Data.Y = &m_pSurfaceBuffers[m_nSurfaceSize * i];
- m_ppSurfacePtrs[i]->Data.U = m_ppSurfacePtrs[i]->Data.Y + m_nSurfaceWidth * m_nSurfaceHeight;
- m_ppSurfacePtrs[i]->Data.V = m_ppSurfacePtrs[i]->Data.U + 1;
- m_ppSurfacePtrs[i]->Data.Pitch = m_nSurfaceWidth;
+ m_ppSurfacePtrs[i]->Data.Y = &m_pSurfaceBuffers[m_nSurfaceSize * i];
+ m_ppSurfacePtrs[i]->Data.U = m_ppSurfacePtrs[i]->Data.Y + m_nSurfaceWidth * m_nSurfaceHeight;
+ m_ppSurfacePtrs[i]->Data.V = m_ppSurfacePtrs[i]->Data.U + 1;
+ m_ppSurfacePtrs[i]->Data.Pitch = m_nSurfaceWidth;
#endif
- }
+ }
- return MFX_ERR_NONE;
+ return MFX_ERR_NONE;
- bail:
- DeAllocSurfaces();
- return status;
- }
+bail:
+ DeAllocSurfaces();
+ return status;
+ }
- mfxStatus AllocateBitstream(mfxU32 nMaxLength)
- {
- DeAllocateBitstream();
+ mfxStatus AllocateBitstream(mfxU32 nMaxLength) {
+ DeAllocateBitstream();
- m_sBitstream.MaxLength = nMaxLength;
- if (!(m_sBitstream.Data = new mfxU8[nMaxLength]))
- {
- INTEL_CHECK_STATUS(MFX_ERR_MEMORY_ALLOC);
- }
+ m_sBitstream.MaxLength = nMaxLength;
+ if (!(m_sBitstream.Data = new mfxU8[nMaxLength])) {
+ INTEL_CHECK_STATUS(MFX_ERR_MEMORY_ALLOC);
+ }
- return MFX_ERR_NONE;
+ return MFX_ERR_NONE;
- bail:
- return MFX_ERR_MEMORY_ALLOC;
- }
+bail:
+ return MFX_ERR_MEMORY_ALLOC;
+ }
private:
- mfxStatus DeAllocSurfaces()
- {
- if (m_ppSurfacePtrs)
- {
- for (mfxU16 i = 0; i < n_nNumSurfaces; i++)
- {
- if (m_ppSurfacePtrs[i])
- {
- delete m_ppSurfacePtrs[i];
- }
- }
- delete[] m_ppSurfacePtrs;
- m_ppSurfacePtrs = NULL;
- }
- n_nNumSurfaces = 0;
-
- if (m_pSurfaceBuffers)
- {
- delete[] m_pSurfaceBuffers;
- m_pSurfaceBuffers = NULL;
- }
-
- m_nSurfaceWidth = 0;
- m_nSurfaceHeight = 0;
- m_nSurfaceBitsPerPixel = 0;
- m_nSurfaceSize = 0;
-
- return MFX_ERR_NONE;
- }
-
- mfxStatus DeAllocateBitstream()
- {
- if (m_sBitstream.Data)
- {
- delete[]m_sBitstream.Data;
- }
- memset(&m_sBitstream, 0, sizeof(m_sBitstream));
-
- return MFX_ERR_NONE;
- }
+ mfxStatus DeAllocSurfaces() {
+ if (m_ppSurfacePtrs) {
+ for (mfxU16 i = 0; i < n_nNumSurfaces; i++) {
+ if (m_ppSurfacePtrs[i]) {
+ delete m_ppSurfacePtrs[i];
+ }
+ }
+ delete[] m_ppSurfacePtrs;
+ m_ppSurfacePtrs = NULL;
+ }
+ n_nNumSurfaces = 0;
+
+ if (m_pSurfaceBuffers) {
+ delete[] m_pSurfaceBuffers;
+ m_pSurfaceBuffers = NULL;
+ }
+
+ m_nSurfaceWidth = 0;
+ m_nSurfaceHeight = 0;
+ m_nSurfaceBitsPerPixel = 0;
+ m_nSurfaceSize = 0;
+
+ return MFX_ERR_NONE;
+ }
+
+ mfxStatus DeAllocateBitstream() {
+ if (m_sBitstream.Data) {
+ delete[]m_sBitstream.Data;
+ }
+ memset(&m_sBitstream, 0, sizeof(m_sBitstream));
+
+ return MFX_ERR_NONE;
+ }
protected:
- bool m_bOpened;
- MFXVideoSession* m_pSession;
- mfxU16 n_nNumSurfaces;
- mfxU16 m_nSurfaceWidth;
- mfxU16 m_nSurfaceHeight;
- mfxU8 m_nSurfaceBitsPerPixel;
- mfxU32 m_nSurfaceSize;
- mfxU8* m_pSurfaceBuffers; // mfxU8[];
- mfxFrameSurface1** m_ppSurfacePtrs; // mfxFrameSurface1[]
- mfxBitstream m_sBitstream;
- mfxVideoParam m_sParamReq; // requested params
- mfxVideoParam m_sParamSel; // selected params
- mfxFrameAllocRequest m_sAllocRequest;
+ bool m_bOpened;
+ MFXVideoSession* m_pSession;
+ mfxU16 n_nNumSurfaces;
+ mfxU16 m_nSurfaceWidth;
+ mfxU16 m_nSurfaceHeight;
+ mfxU8 m_nSurfaceBitsPerPixel;
+ mfxU32 m_nSurfaceSize;
+ mfxU8* m_pSurfaceBuffers; // mfxU8[];
+ mfxFrameSurface1** m_ppSurfacePtrs; // mfxFrameSurface1[]
+ mfxBitstream m_sBitstream;
+ mfxVideoParam m_sParamReq; // requested params
+ mfxVideoParam m_sParamSel; // selected params
+ mfxFrameAllocRequest m_sAllocRequest;
#if INTEL_DX11_D3D
- mfxFrameAllocResponse m_sD3D11Response;
+ mfxFrameAllocResponse m_sD3D11Response;
#endif
};
@@ -423,349 +402,315 @@ protected:
class IntelCodecEncoder : public IntelCodec
{
public:
- IntelCodecEncoder(MFXVideoSession* pSession)
- : IntelCodec(pSession)
- , m_Inst(*pSession)
- {
- memset(&m_sFrameCtrl, 0, sizeof(m_sFrameCtrl));
- }
- virtual ~IntelCodecEncoder()
- {
- Close();
- }
-
- virtual mfxStatus Close()
- {
- m_Inst.Close();
- memset(&m_sFrameCtrl, 0, sizeof(m_sFrameCtrl));
- return IntelCodec::Close();
- }
-
- mfxStatus Reset()
- {
- if (m_bOpened)
- {
- return m_Inst.Reset(&m_sParamSel);
- }
- return MFX_ERR_NONE;
- }
-
- mfxStatus Open(struct tdav_codec_h264_intel_s* pWrappedCodec)
- {
- int32_t max_bw_kpbs;
- tdav_codec_h264_common_t* pWrappedCodecCommon = (tdav_codec_h264_common_t*)pWrappedCodec;
- mfxStatus status = MFX_ERR_UNKNOWN;
- mfxU16 uSelWidth, uSelHeight;
-
- pWrappedCodec->encoder.neg_width = (pWrappedCodec->encoder.rotation == 90 || pWrappedCodec->encoder.rotation == 270) ? TMEDIA_CODEC_VIDEO(pWrappedCodec)->out.height : TMEDIA_CODEC_VIDEO(pWrappedCodec)->out.width;
- pWrappedCodec->encoder.neg_height = (pWrappedCodec->encoder.rotation == 90 || pWrappedCodec->encoder.rotation == 270) ? TMEDIA_CODEC_VIDEO(pWrappedCodec)->out.width : TMEDIA_CODEC_VIDEO(pWrappedCodec)->out.height;
- pWrappedCodec->encoder.neg_fps = TMEDIA_CODEC_VIDEO(pWrappedCodec)->out.fps;
- max_bw_kpbs = TSK_CLAMP(
- 0,
- tmedia_get_video_bandwidth_kbps_2(pWrappedCodec->encoder.neg_width, pWrappedCodec->encoder.neg_height, pWrappedCodec->encoder.neg_fps),
- TMEDIA_CODEC(pWrappedCodec)->bandwidth_max_upload
- );
- pWrappedCodec->encoder.max_bitrate_bps = (max_bw_kpbs * 1024);
-
- INTEL_DEBUG_INFO("neg_width=%d, neg_height=%d, neg_fps=%d, max_bitrate_bps=%d",
- pWrappedCodec->encoder.neg_width,
- pWrappedCodec->encoder.neg_height,
- pWrappedCodec->encoder.neg_fps,
- pWrappedCodec->encoder.max_bitrate_bps
- );
-
- // Initialize encoder parameters
- memset(&m_sParamReq, 0, sizeof(m_sParamReq));
- m_sParamReq.mfx.CodecId = MFX_CODEC_AVC;
- m_sParamReq.mfx.CodecProfile = pWrappedCodecCommon->profile == profile_idc_main ? MFX_PROFILE_AVC_MAIN : MFX_PROFILE_AVC_BASELINE;
- m_sParamReq.mfx.CodecLevel = (mfxU16)pWrappedCodecCommon->level;
- // TODO: Update "CodecProfile" based on "common->profile_iop"
- m_sParamReq.mfx.TargetUsage = MFX_TARGETUSAGE_BALANCED;
- m_sParamReq.mfx.TargetKbps = max_bw_kpbs;
- m_sParamReq.mfx.RateControlMethod = MFX_RATECONTROL_CBR;
- m_sParamReq.mfx.IdrInterval = (pWrappedCodec->encoder.neg_fps * INTEL_H264_GOP_SIZE_IN_SECONDS);
- m_sParamReq.mfx.FrameInfo.FrameRateExtN = pWrappedCodec->encoder.neg_fps;
- m_sParamReq.mfx.FrameInfo.FrameRateExtD = 1;
- m_sParamReq.mfx.FrameInfo.FourCC = MFX_FOURCC_NV12;
- m_sParamReq.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
- m_sParamReq.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
- m_sParamReq.mfx.FrameInfo.CropX = 0;
- m_sParamReq.mfx.FrameInfo.CropY = 0;
- m_sParamReq.mfx.FrameInfo.CropW = pWrappedCodec->encoder.neg_width;
- m_sParamReq.mfx.FrameInfo.CropH = pWrappedCodec->encoder.neg_height;
- m_sParamReq.mfx.FrameInfo.Width = INTEL_ALIGN16(pWrappedCodec->encoder.neg_width); // must be a multiple of 16
- m_sParamReq.mfx.FrameInfo.Height = INTEL_ALIGN16(pWrappedCodec->encoder.neg_height); // must be a multiple of 16
+ IntelCodecEncoder(MFXVideoSession* pSession)
+ : IntelCodec(pSession)
+ , m_Inst(*pSession) {
+ memset(&m_sFrameCtrl, 0, sizeof(m_sFrameCtrl));
+ }
+ virtual ~IntelCodecEncoder() {
+ Close();
+ }
+
+ virtual mfxStatus Close() {
+ m_Inst.Close();
+ memset(&m_sFrameCtrl, 0, sizeof(m_sFrameCtrl));
+ return IntelCodec::Close();
+ }
+
+ mfxStatus Reset() {
+ if (m_bOpened) {
+ return m_Inst.Reset(&m_sParamSel);
+ }
+ return MFX_ERR_NONE;
+ }
+
+ mfxStatus Open(struct tdav_codec_h264_intel_s* pWrappedCodec) {
+ int32_t max_bw_kpbs;
+ tdav_codec_h264_common_t* pWrappedCodecCommon = (tdav_codec_h264_common_t*)pWrappedCodec;
+ mfxStatus status = MFX_ERR_UNKNOWN;
+ mfxU16 uSelWidth, uSelHeight;
+
+ pWrappedCodec->encoder.neg_width = (pWrappedCodec->encoder.rotation == 90 || pWrappedCodec->encoder.rotation == 270) ? TMEDIA_CODEC_VIDEO(pWrappedCodec)->out.height : TMEDIA_CODEC_VIDEO(pWrappedCodec)->out.width;
+ pWrappedCodec->encoder.neg_height = (pWrappedCodec->encoder.rotation == 90 || pWrappedCodec->encoder.rotation == 270) ? TMEDIA_CODEC_VIDEO(pWrappedCodec)->out.width : TMEDIA_CODEC_VIDEO(pWrappedCodec)->out.height;
+ pWrappedCodec->encoder.neg_fps = TMEDIA_CODEC_VIDEO(pWrappedCodec)->out.fps;
+ max_bw_kpbs = TSK_CLAMP(
+ 0,
+ tmedia_get_video_bandwidth_kbps_2(pWrappedCodec->encoder.neg_width, pWrappedCodec->encoder.neg_height, pWrappedCodec->encoder.neg_fps),
+ TMEDIA_CODEC(pWrappedCodec)->bandwidth_max_upload
+ );
+ pWrappedCodec->encoder.max_bitrate_bps = (max_bw_kpbs * 1024);
+
+ INTEL_DEBUG_INFO("neg_width=%d, neg_height=%d, neg_fps=%d, max_bitrate_bps=%d",
+ pWrappedCodec->encoder.neg_width,
+ pWrappedCodec->encoder.neg_height,
+ pWrappedCodec->encoder.neg_fps,
+ pWrappedCodec->encoder.max_bitrate_bps
+ );
+
+ // Initialize encoder parameters
+ memset(&m_sParamReq, 0, sizeof(m_sParamReq));
+ m_sParamReq.mfx.CodecId = MFX_CODEC_AVC;
+ m_sParamReq.mfx.CodecProfile = pWrappedCodecCommon->profile == profile_idc_main ? MFX_PROFILE_AVC_MAIN : MFX_PROFILE_AVC_BASELINE;
+ m_sParamReq.mfx.CodecLevel = (mfxU16)pWrappedCodecCommon->level;
+ // TODO: Update "CodecProfile" based on "common->profile_iop"
+ m_sParamReq.mfx.TargetUsage = MFX_TARGETUSAGE_BALANCED;
+ m_sParamReq.mfx.TargetKbps = max_bw_kpbs;
+ m_sParamReq.mfx.RateControlMethod = MFX_RATECONTROL_CBR;
+ m_sParamReq.mfx.IdrInterval = (pWrappedCodec->encoder.neg_fps * INTEL_H264_GOP_SIZE_IN_SECONDS);
+ m_sParamReq.mfx.FrameInfo.FrameRateExtN = pWrappedCodec->encoder.neg_fps;
+ m_sParamReq.mfx.FrameInfo.FrameRateExtD = 1;
+ m_sParamReq.mfx.FrameInfo.FourCC = MFX_FOURCC_NV12;
+ m_sParamReq.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
+ m_sParamReq.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
+ m_sParamReq.mfx.FrameInfo.CropX = 0;
+ m_sParamReq.mfx.FrameInfo.CropY = 0;
+ m_sParamReq.mfx.FrameInfo.CropW = pWrappedCodec->encoder.neg_width;
+ m_sParamReq.mfx.FrameInfo.CropH = pWrappedCodec->encoder.neg_height;
+ m_sParamReq.mfx.FrameInfo.Width = INTEL_ALIGN16(pWrappedCodec->encoder.neg_width); // must be a multiple of 16
+ m_sParamReq.mfx.FrameInfo.Height = INTEL_ALIGN16(pWrappedCodec->encoder.neg_height); // must be a multiple of 16
#if INTEL_DX11_D3D
- m_sParamReq.IOPattern = MFX_IOPATTERN_IN_VIDEO_MEMORY;
+ m_sParamReq.IOPattern = MFX_IOPATTERN_IN_VIDEO_MEMORY;
#else
- m_sParamReq.IOPattern = MFX_IOPATTERN_IN_SYSTEM_MEMORY;
+ m_sParamReq.IOPattern = MFX_IOPATTERN_IN_SYSTEM_MEMORY;
#endif
- memset(&m_sOpt2MaxFrameSize, 0, sizeof(m_sOpt2MaxFrameSize));
- m_sOpt2MaxFrameSize.Header.BufferId = MFX_EXTBUFF_CODING_OPTION2;
- m_sOpt2MaxFrameSize.Header.BufferSz = sizeof(m_sOpt2MaxFrameSize);
- m_sOpt2MaxFrameSize.MaxSliceSize = (H264_RTP_PAYLOAD_SIZE - 100);
- m_sOpt2MaxFrameSize.RepeatPPS = MFX_CODINGOPTION_OFF;
- m_pExtendedBuffers[0] = (mfxExtBuffer*)&m_sOpt2MaxFrameSize;
+ memset(&m_sOpt2MaxFrameSize, 0, sizeof(m_sOpt2MaxFrameSize));
+ m_sOpt2MaxFrameSize.Header.BufferId = MFX_EXTBUFF_CODING_OPTION2;
+ m_sOpt2MaxFrameSize.Header.BufferSz = sizeof(m_sOpt2MaxFrameSize);
+ m_sOpt2MaxFrameSize.MaxSliceSize = (H264_RTP_PAYLOAD_SIZE - 100);
+ m_sOpt2MaxFrameSize.RepeatPPS = MFX_CODINGOPTION_OFF;
+ m_pExtendedBuffers[0] = (mfxExtBuffer*)&m_sOpt2MaxFrameSize;
#if INTEL_ENABLE_REALTIME
- m_sParamReq.AsyncDepth = 1; // limits internal frame buffering
- m_sParamReq.mfx.GopRefDist = 1; // No B-Frames
- m_sParamReq.mfx.NumRefFrame = 1;
- memset(&m_sOptLowLatency, 0, sizeof(m_sOptLowLatency));
- m_sOptLowLatency.Header.BufferId = MFX_EXTBUFF_CODING_OPTION;
- m_sOptLowLatency.Header.BufferSz = sizeof(m_sOptLowLatency);
- m_sOptLowLatency.MaxDecFrameBuffering = 1;
- m_pExtendedBuffers[1] = (mfxExtBuffer*)&m_sOptLowLatency;
- m_sParamReq.NumExtParam = 2;
+ m_sParamReq.AsyncDepth = 1; // limits internal frame buffering
+ m_sParamReq.mfx.GopRefDist = 1; // No B-Frames
+ m_sParamReq.mfx.NumRefFrame = 1;
+ memset(&m_sOptLowLatency, 0, sizeof(m_sOptLowLatency));
+ m_sOptLowLatency.Header.BufferId = MFX_EXTBUFF_CODING_OPTION;
+ m_sOptLowLatency.Header.BufferSz = sizeof(m_sOptLowLatency);
+ m_sOptLowLatency.MaxDecFrameBuffering = 1;
+ m_pExtendedBuffers[1] = (mfxExtBuffer*)&m_sOptLowLatency;
+ m_sParamReq.NumExtParam = 2;
#else
- m_sParamReq.NumExtParam = 1;
+ m_sParamReq.NumExtParam = 1;
#endif
- m_sParamReq.ExtParam = m_pExtendedBuffers;
-
- // Check parameters
- status = m_Inst.Query(&m_sParamReq, &m_sParamReq);
- if (status != MFX_ERR_NONE && status != MFX_WRN_INCOMPATIBLE_VIDEO_PARAM /* Best one will be selected by the encoder */) {
- INTEL_CHECK_STATUS(status);
- }
- if (m_sOpt2MaxFrameSize.MaxSliceSize == 0)
- {
- INTEL_DEBUG_INFO("The encoder doesn't support setting 'MaxSliceSize' :(");
- }
-
- // Query number required surfaces for encoder
- memset(&m_sAllocRequest, 0, sizeof(m_sAllocRequest));
- INTEL_CHECK_STATUS(status = m_Inst.QueryIOSurf(&m_sParamReq, &m_sAllocRequest));
- INTEL_DEBUG_INFO("nEncSurfNum = %hu", m_sAllocRequest.NumFrameSuggested);
+ m_sParamReq.ExtParam = m_pExtendedBuffers;
+
+ // Check parameters
+ status = m_Inst.Query(&m_sParamReq, &m_sParamReq);
+ if (status != MFX_ERR_NONE && status != MFX_WRN_INCOMPATIBLE_VIDEO_PARAM /* Best one will be selected by the encoder */) {
+ INTEL_CHECK_STATUS(status);
+ }
+ if (m_sOpt2MaxFrameSize.MaxSliceSize == 0) {
+ INTEL_DEBUG_INFO("The encoder doesn't support setting 'MaxSliceSize' :(");
+ }
+
+ // Query number required surfaces for encoder
+ memset(&m_sAllocRequest, 0, sizeof(m_sAllocRequest));
+ INTEL_CHECK_STATUS(status = m_Inst.QueryIOSurf(&m_sParamReq, &m_sAllocRequest));
+ INTEL_DEBUG_INFO("nEncSurfNum = %hu", m_sAllocRequest.NumFrameSuggested);
#if INTEL_DX11_D3D
- m_sAllocRequest.Type |= D3D11_WILL_WRITE; // Hint to DX11 memory handler that application will write data to input surfaces
+ m_sAllocRequest.Type |= D3D11_WILL_WRITE; // Hint to DX11 memory handler that application will write data to input surfaces
#endif
- // Allocate surfaces for encoder
+ // Allocate surfaces for encoder
#if INTEL_DX11_D3D
- INTEL_CHECK_STATUS(status = pWrappedCodec->D3D11Allocator.Alloc(pWrappedCodec->D3D11Allocator.pthis, &m_sAllocRequest, &m_sD3D11Response));
- if (m_sD3D11Response.NumFrameActual == 0)
- {
- INTEL_CHECK_STATUS(status = MFX_ERR_UNKNOWN);
- }
- INTEL_CHECK_STATUS(status = AllocSurfaces(m_sD3D11Response.NumFrameActual, m_sAllocRequest.Info.Width, m_sAllocRequest.Info.Height, &m_sParamReq.mfx.FrameInfo));
+ INTEL_CHECK_STATUS(status = pWrappedCodec->D3D11Allocator.Alloc(pWrappedCodec->D3D11Allocator.pthis, &m_sAllocRequest, &m_sD3D11Response));
+ if (m_sD3D11Response.NumFrameActual == 0) {
+ INTEL_CHECK_STATUS(status = MFX_ERR_UNKNOWN);
+ }
+ INTEL_CHECK_STATUS(status = AllocSurfaces(m_sD3D11Response.NumFrameActual, m_sAllocRequest.Info.Width, m_sAllocRequest.Info.Height, &m_sParamReq.mfx.FrameInfo));
#else
- INTEL_CHECK_STATUS(status = AllocSurfaces(m_sAllocRequest.NumFrameSuggested, m_sAllocRequest.Info.Width, m_sAllocRequest.Info.Height, &m_sParamReq.mfx.FrameInfo));
+ INTEL_CHECK_STATUS(status = AllocSurfaces(m_sAllocRequest.NumFrameSuggested, m_sAllocRequest.Info.Width, m_sAllocRequest.Info.Height, &m_sParamReq.mfx.FrameInfo));
#endif
- // Initialize the Media SDK encoder
- status = m_Inst.Init(&m_sParamReq);
- if (status != MFX_ERR_NONE && status != MFX_WRN_PARTIAL_ACCELERATION) {
- INTEL_CHECK_STATUS(status);
- }
- INTEL_DEBUG_INFO("Encoder->Init() returned: %d", status);
-
- // Retrieve video parameters selected by encoder.
- memset(&m_sParamSel, 0, sizeof(m_sParamSel));
- INTEL_CHECK_STATUS(status = m_Inst.GetVideoParam(&m_sParamSel));
- INTEL_DEBUG_INFO("sel_width=%u.crop=%u, sel_height=%u.crop=%u, sel_fps=%u/%u",
- m_sParamSel.mfx.FrameInfo.Width, m_sParamSel.mfx.FrameInfo.CropW,
- m_sParamSel.mfx.FrameInfo.Height, m_sParamSel.mfx.FrameInfo.CropH,
- m_sParamReq.mfx.FrameInfo.FrameRateExtN,
- m_sParamReq.mfx.FrameInfo.FrameRateExtD
- );
- if (m_sParamSel.mfx.FrameInfo.CropW > 0 && m_sParamSel.mfx.FrameInfo.CropH > 0)
- {
- uSelWidth = m_sParamSel.mfx.FrameInfo.CropW;
- uSelHeight = m_sParamSel.mfx.FrameInfo.CropH;
- }
- else
- {
- uSelWidth = m_sParamSel.mfx.FrameInfo.Width;
- uSelHeight = m_sParamSel.mfx.FrameInfo.Height;
- }
- if (pWrappedCodec->encoder.neg_width != uSelWidth || pWrappedCodec->encoder.neg_height != uSelHeight) {
- INTEL_DEBUG_INFO("Encoder neg size <> sel size: %dx%d<>%dx%d", pWrappedCodec->encoder.neg_width, pWrappedCodec->encoder.neg_height, uSelWidth, uSelHeight);
- pWrappedCodec->encoder.neg_width = uSelWidth;
- pWrappedCodec->encoder.neg_height = uSelHeight;
- TMEDIA_CODEC_VIDEO(pWrappedCodec)->out.width = pWrappedCodec->encoder.neg_width;
- TMEDIA_CODEC_VIDEO(pWrappedCodec)->out.height = pWrappedCodec->encoder.neg_height;
- }
-
- // Allocate BitStream
- INTEL_CHECK_STATUS(status = AllocateBitstream(m_sParamSel.mfx.BufferSizeInKB * 1000));
-
- m_bOpened = true;
- return MFX_ERR_NONE;
-
- bail:
- Close();
- return status;
- }
-
- mfxStatus UpdateBandwidth(bool bUp, mfxU16 max)
- {
- if (bUp)
- {
- m_sParamSel.mfx.TargetKbps = TSK_CLAMP(0, (mfxU16)((m_sParamSel.mfx.TargetKbps * 3) >> 1), max);
- }
- else
- {
- m_sParamSel.mfx.TargetKbps = TSK_CLAMP(0, (mfxU16)((m_sParamSel.mfx.TargetKbps << 1) / 3), max);
- }
- m_sParamReq.mfx.TargetKbps = m_sParamSel.mfx.TargetKbps;
- INTEL_DEBUG_INFO("Setting new target bandwidth to %ukbps", m_sParamSel.mfx.TargetKbps);
- return m_Inst.Reset(&m_sParamSel);
- }
-
- mfxStatus SetMaxBandwidth(mfxU16 max)
- {
- m_sParamSel.mfx.TargetKbps = TSK_CLAMP(0, m_sParamSel.mfx.TargetKbps, max);
- m_sParamReq.mfx.TargetKbps = m_sParamSel.mfx.TargetKbps;
- INTEL_DEBUG_INFO("Setting new target bandwidth to %ukbps", m_sParamSel.mfx.TargetKbps);
- return m_Inst.Reset(&m_sParamSel);
- }
-
- mfxStatus Encode(struct tmedia_codec_s* pWrappedCodec, const mfxU8* pcInDataPtr, mfxU32 nInDataSize)
- {
- tdav_codec_h264_intel_t* pWrappedCodecH264 = (tdav_codec_h264_intel_t*)pWrappedCodec;
- tdav_codec_h264_common_t* pWrappedCodecCommon = (tdav_codec_h264_common_t*)pWrappedCodec;
- mfxU32 nInDataXSize;
- tsk_bool_t bSendIDR;
- int nEncSurfIdx = 0;
- mfxSyncPoint syncp;
- mfxStatus status = MFX_ERR_UNKNOWN;
-
- if (!pWrappedCodec || !pcInDataPtr || !nInDataSize) {
- INTEL_CHECK_STATUS(MFX_ERR_NULL_PTR);
- }
-
- if (!m_bOpened) {
- INTEL_CHECK_STATUS(MFX_ERR_NOT_INITIALIZED);
- }
-
- nInDataXSize = (pWrappedCodecH264->encoder.neg_width * pWrappedCodecH264->encoder.neg_height * 3) >> 1;
- if (nInDataXSize != nInDataSize)
- {
- /* guard */
- INTEL_DEBUG_ERROR("Invalid size: %u<>%u", nInDataXSize, nInDataSize);
- goto bail;
- }
-
- bSendIDR = (pWrappedCodecH264->encoder.frame_count++ == 0 || pWrappedCodecH264->encoder.force_idr);
-
- nEncSurfIdx = GetFreeSurfaceIndex();
- if (MFX_ERR_NOT_FOUND == nEncSurfIdx)
- {
- INTEL_CHECK_STATUS(MFX_ERR_MEMORY_ALLOC);
- }
-
- // Surface locking required when read/write D3D surfaces
+ // Initialize the Media SDK encoder
+ status = m_Inst.Init(&m_sParamReq);
+ if (status != MFX_ERR_NONE && status != MFX_WRN_PARTIAL_ACCELERATION) {
+ INTEL_CHECK_STATUS(status);
+ }
+ INTEL_DEBUG_INFO("Encoder->Init() returned: %d", status);
+
+ // Retrieve video parameters selected by encoder.
+ memset(&m_sParamSel, 0, sizeof(m_sParamSel));
+ INTEL_CHECK_STATUS(status = m_Inst.GetVideoParam(&m_sParamSel));
+ INTEL_DEBUG_INFO("sel_width=%u.crop=%u, sel_height=%u.crop=%u, sel_fps=%u/%u",
+ m_sParamSel.mfx.FrameInfo.Width, m_sParamSel.mfx.FrameInfo.CropW,
+ m_sParamSel.mfx.FrameInfo.Height, m_sParamSel.mfx.FrameInfo.CropH,
+ m_sParamReq.mfx.FrameInfo.FrameRateExtN,
+ m_sParamReq.mfx.FrameInfo.FrameRateExtD
+ );
+ if (m_sParamSel.mfx.FrameInfo.CropW > 0 && m_sParamSel.mfx.FrameInfo.CropH > 0) {
+ uSelWidth = m_sParamSel.mfx.FrameInfo.CropW;
+ uSelHeight = m_sParamSel.mfx.FrameInfo.CropH;
+ }
+ else {
+ uSelWidth = m_sParamSel.mfx.FrameInfo.Width;
+ uSelHeight = m_sParamSel.mfx.FrameInfo.Height;
+ }
+ if (pWrappedCodec->encoder.neg_width != uSelWidth || pWrappedCodec->encoder.neg_height != uSelHeight) {
+ INTEL_DEBUG_INFO("Encoder neg size <> sel size: %dx%d<>%dx%d", pWrappedCodec->encoder.neg_width, pWrappedCodec->encoder.neg_height, uSelWidth, uSelHeight);
+ pWrappedCodec->encoder.neg_width = uSelWidth;
+ pWrappedCodec->encoder.neg_height = uSelHeight;
+ TMEDIA_CODEC_VIDEO(pWrappedCodec)->out.width = pWrappedCodec->encoder.neg_width;
+ TMEDIA_CODEC_VIDEO(pWrappedCodec)->out.height = pWrappedCodec->encoder.neg_height;
+ }
+
+ // Allocate BitStream
+ INTEL_CHECK_STATUS(status = AllocateBitstream(m_sParamSel.mfx.BufferSizeInKB * 1000));
+
+ m_bOpened = true;
+ return MFX_ERR_NONE;
+
+bail:
+ Close();
+ return status;
+ }
+
+ mfxStatus UpdateBandwidth(bool bUp, mfxU16 max) {
+ if (bUp) {
+ m_sParamSel.mfx.TargetKbps = TSK_CLAMP(0, (mfxU16)((m_sParamSel.mfx.TargetKbps * 3) >> 1), max);
+ }
+ else {
+ m_sParamSel.mfx.TargetKbps = TSK_CLAMP(0, (mfxU16)((m_sParamSel.mfx.TargetKbps << 1) / 3), max);
+ }
+ m_sParamReq.mfx.TargetKbps = m_sParamSel.mfx.TargetKbps;
+ INTEL_DEBUG_INFO("Setting new target bandwidth to %ukbps", m_sParamSel.mfx.TargetKbps);
+ return m_Inst.Reset(&m_sParamSel);
+ }
+
+ mfxStatus SetMaxBandwidth(mfxU16 max) {
+ m_sParamSel.mfx.TargetKbps = TSK_CLAMP(0, m_sParamSel.mfx.TargetKbps, max);
+ m_sParamReq.mfx.TargetKbps = m_sParamSel.mfx.TargetKbps;
+ INTEL_DEBUG_INFO("Setting new target bandwidth to %ukbps", m_sParamSel.mfx.TargetKbps);
+ return m_Inst.Reset(&m_sParamSel);
+ }
+
+ mfxStatus Encode(struct tmedia_codec_s* pWrappedCodec, const mfxU8* pcInDataPtr, mfxU32 nInDataSize) {
+ tdav_codec_h264_intel_t* pWrappedCodecH264 = (tdav_codec_h264_intel_t*)pWrappedCodec;
+ tdav_codec_h264_common_t* pWrappedCodecCommon = (tdav_codec_h264_common_t*)pWrappedCodec;
+ mfxU32 nInDataXSize;
+ tsk_bool_t bSendIDR;
+ int nEncSurfIdx = 0;
+ mfxSyncPoint syncp;
+ mfxStatus status = MFX_ERR_UNKNOWN;
+
+ if (!pWrappedCodec || !pcInDataPtr || !nInDataSize) {
+ INTEL_CHECK_STATUS(MFX_ERR_NULL_PTR);
+ }
+
+ if (!m_bOpened) {
+ INTEL_CHECK_STATUS(MFX_ERR_NOT_INITIALIZED);
+ }
+
+ nInDataXSize = (pWrappedCodecH264->encoder.neg_width * pWrappedCodecH264->encoder.neg_height * 3) >> 1;
+ if (nInDataXSize != nInDataSize) {
+ /* guard */
+ INTEL_DEBUG_ERROR("Invalid size: %u<>%u", nInDataXSize, nInDataSize);
+ goto bail;
+ }
+
+ bSendIDR = (pWrappedCodecH264->encoder.frame_count++ == 0 || pWrappedCodecH264->encoder.force_idr);
+
+ nEncSurfIdx = GetFreeSurfaceIndex();
+ if (MFX_ERR_NOT_FOUND == nEncSurfIdx) {
+ INTEL_CHECK_STATUS(MFX_ERR_MEMORY_ALLOC);
+ }
+
+ // Surface locking required when read/write D3D surfaces
#if INTEL_DX11_D3D
- INTEL_CHECK_STATUS(status = pWrappedCodecH264->D3D11Allocator.Lock(pWrappedCodecH264->D3D11Allocator.pthis, m_ppSurfacePtrs[nEncSurfIdx]->Data.MemId, &(m_ppSurfacePtrs[nEncSurfIdx]->Data)));
+ INTEL_CHECK_STATUS(status = pWrappedCodecH264->D3D11Allocator.Lock(pWrappedCodecH264->D3D11Allocator.pthis, m_ppSurfacePtrs[nEncSurfIdx]->Data.MemId, &(m_ppSurfacePtrs[nEncSurfIdx]->Data)));
#endif
- INTEL_CHECK_STATUS(status = LoadRawFrame(nEncSurfIdx, pcInDataPtr));
+ INTEL_CHECK_STATUS(status = LoadRawFrame(nEncSurfIdx, pcInDataPtr));
#if INTEL_DX11_D3D
- INTEL_CHECK_STATUS(status = pWrappedCodecH264->D3D11Allocator.Unlock(pWrappedCodecH264->D3D11Allocator.pthis, m_ppSurfacePtrs[nEncSurfIdx]->Data.MemId, &(m_ppSurfacePtrs[nEncSurfIdx]->Data)));
+ INTEL_CHECK_STATUS(status = pWrappedCodecH264->D3D11Allocator.Unlock(pWrappedCodecH264->D3D11Allocator.pthis, m_ppSurfacePtrs[nEncSurfIdx]->Data.MemId, &(m_ppSurfacePtrs[nEncSurfIdx]->Data)));
#endif
- m_sFrameCtrl.FrameType = bSendIDR ? (MFX_FRAMETYPE_I | MFX_FRAMETYPE_REF | MFX_FRAMETYPE_IDR) : MFX_FRAMETYPE_UNKNOWN;
-
- //
- // Stage 1: Main encoding loop
- //
- do
- {
- for (;;)
- {
- // Encode a frame asychronously (returns immediately)
- status = m_Inst.EncodeFrameAsync(&m_sFrameCtrl, m_ppSurfacePtrs[nEncSurfIdx], &m_sBitstream, &syncp);
-
- if (MFX_ERR_NONE < status && !syncp) // Repeat the call if warning and no output
- {
- if (MFX_WRN_DEVICE_BUSY == status)
- {
- tsk_thread_sleep(1); // Wait if device is busy, then repeat the same call
- }
- }
- else if (MFX_ERR_NONE < status && syncp)
- {
- status = MFX_ERR_NONE; // Ignore warnings if output is available
- break;
- }
- else if (MFX_ERR_NOT_ENOUGH_BUFFER == status)
- {
- // Allocate more bitstream buffer memory here if needed...
- break;
- }
- else
- {
- if (status != MFX_ERR_MORE_DATA)
- {
- INTEL_CHECK_STATUS(status);
- }
- break;
- }
- }
- if (MFX_ERR_NONE == status)
- {
- INTEL_CHECK_STATUS(m_pSession->SyncOperation(syncp, 60000)); // Synchronize. Wait until encoded frame is ready
- if (m_sBitstream.DataLength > 0)
- {
- tdav_codec_h264_rtp_encap(pWrappedCodecCommon, (const uint8_t*)(m_sBitstream.Data + m_sBitstream.DataOffset), (tsk_size_t)m_sBitstream.DataLength);
- m_sBitstream.DataLength = 0;
- pWrappedCodecH264->encoder.force_idr = tsk_false; // reset
- }
- }
- } while (0);
-
- //
- // Stage 2: Retrieve the buffered encoded frames
- //
- while (MFX_ERR_NONE <= status)
- {
- for (;;)
- {
- // Encode a frame asychronously (returns immediately)
- status = m_Inst.EncodeFrameAsync(&m_sFrameCtrl, NULL, &m_sBitstream, &syncp);
-
- if (MFX_ERR_NONE < status && !syncp) // Repeat the call if warning and no output
- {
- if (MFX_WRN_DEVICE_BUSY == status)
- {
- tsk_thread_sleep(1); // Wait if device is busy, then repeat the same call
- }
- }
- else if (MFX_ERR_NONE < status && syncp)
- {
- status = MFX_ERR_NONE; // Ignore warnings if output is available
- break;
- }
- else
- {
- break;
- }
- }
-
- if (MFX_ERR_NONE == status)
- {
- INTEL_CHECK_STATUS(m_pSession->SyncOperation(syncp, 60000)); // Synchronize. Wait until encoded frame is
- if (m_sBitstream.DataLength > 0)
- {
- tdav_codec_h264_rtp_encap(pWrappedCodecCommon, (const uint8_t*)(m_sBitstream.Data + m_sBitstream.DataOffset), (tsk_size_t)m_sBitstream.DataLength);
- m_sBitstream.DataLength = 0;
- pWrappedCodecH264->encoder.force_idr = tsk_false; // reset
- }
- }
- }
-
- bail:
- return MFX_ERR_NONE;
- }
+ m_sFrameCtrl.FrameType = bSendIDR ? (MFX_FRAMETYPE_I | MFX_FRAMETYPE_REF | MFX_FRAMETYPE_IDR) : MFX_FRAMETYPE_UNKNOWN;
+
+ //
+ // Stage 1: Main encoding loop
+ //
+ do {
+ for (;;) {
+ // Encode a frame asychronously (returns immediately)
+ status = m_Inst.EncodeFrameAsync(&m_sFrameCtrl, m_ppSurfacePtrs[nEncSurfIdx], &m_sBitstream, &syncp);
+
+ if (MFX_ERR_NONE < status && !syncp) { // Repeat the call if warning and no output
+ if (MFX_WRN_DEVICE_BUSY == status) {
+ tsk_thread_sleep(1); // Wait if device is busy, then repeat the same call
+ }
+ }
+ else if (MFX_ERR_NONE < status && syncp) {
+ status = MFX_ERR_NONE; // Ignore warnings if output is available
+ break;
+ }
+ else if (MFX_ERR_NOT_ENOUGH_BUFFER == status) {
+ // Allocate more bitstream buffer memory here if needed...
+ break;
+ }
+ else {
+ if (status != MFX_ERR_MORE_DATA) {
+ INTEL_CHECK_STATUS(status);
+ }
+ break;
+ }
+ }
+ if (MFX_ERR_NONE == status) {
+ INTEL_CHECK_STATUS(m_pSession->SyncOperation(syncp, 60000)); // Synchronize. Wait until encoded frame is ready
+ if (m_sBitstream.DataLength > 0) {
+ tdav_codec_h264_rtp_encap(pWrappedCodecCommon, (const uint8_t*)(m_sBitstream.Data + m_sBitstream.DataOffset), (tsk_size_t)m_sBitstream.DataLength);
+ m_sBitstream.DataLength = 0;
+ pWrappedCodecH264->encoder.force_idr = tsk_false; // reset
+ }
+ }
+ }
+ while (0);
+
+ //
+ // Stage 2: Retrieve the buffered encoded frames
+ //
+ while (MFX_ERR_NONE <= status) {
+ for (;;) {
+ // Encode a frame asychronously (returns immediately)
+ status = m_Inst.EncodeFrameAsync(&m_sFrameCtrl, NULL, &m_sBitstream, &syncp);
+
+ if (MFX_ERR_NONE < status && !syncp) { // Repeat the call if warning and no output
+ if (MFX_WRN_DEVICE_BUSY == status) {
+ tsk_thread_sleep(1); // Wait if device is busy, then repeat the same call
+ }
+ }
+ else if (MFX_ERR_NONE < status && syncp) {
+ status = MFX_ERR_NONE; // Ignore warnings if output is available
+ break;
+ }
+ else {
+ break;
+ }
+ }
+
+ if (MFX_ERR_NONE == status) {
+ INTEL_CHECK_STATUS(m_pSession->SyncOperation(syncp, 60000)); // Synchronize. Wait until encoded frame is
+ if (m_sBitstream.DataLength > 0) {
+ tdav_codec_h264_rtp_encap(pWrappedCodecCommon, (const uint8_t*)(m_sBitstream.Data + m_sBitstream.DataOffset), (tsk_size_t)m_sBitstream.DataLength);
+ m_sBitstream.DataLength = 0;
+ pWrappedCodecH264->encoder.force_idr = tsk_false; // reset
+ }
+ }
+ }
+
+bail:
+ return MFX_ERR_NONE;
+ }
private:
- MFXVideoENCODE m_Inst;
- mfxEncodeCtrl m_sFrameCtrl;
- mfxExtCodingOption m_sOptLowLatency;
- mfxExtCodingOption2 m_sOpt2MaxFrameSize;
- mfxExtBuffer* m_pExtendedBuffers[2]; // Not allocated
+ MFXVideoENCODE m_Inst;
+ mfxEncodeCtrl m_sFrameCtrl;
+ mfxExtCodingOption m_sOptLowLatency;
+ mfxExtCodingOption2 m_sOpt2MaxFrameSize;
+ mfxExtBuffer* m_pExtendedBuffers[2]; // Not allocated
};
@@ -775,253 +720,222 @@ private:
class IntelCodecDecoder : public IntelCodec
{
public:
- IntelCodecDecoder(MFXVideoSession* pSession)
- : IntelCodec(pSession)
- , m_Inst(*pSession)
- , m_pAccumulatorPtr(NULL)
- , m_nAccumulatorSize(0)
- , m_nAccumulatorPos(0)
- , m_bInit(false)
- {
-
- }
- virtual ~IntelCodecDecoder()
- {
- Close();
- }
-
- virtual mfxStatus Close()
- {
- m_Inst.Close();
- TSK_FREE(m_pAccumulatorPtr);
- m_nAccumulatorSize = 0;
- m_nAccumulatorPos = 0;
- m_bInit = false;
- return IntelCodec::Close();
- }
-
- mfxStatus Open(struct tdav_codec_h264_intel_s* pWrappedCodec)
- {
- tdav_codec_h264_common_t* pWrappedCodecCommon = (tdav_codec_h264_common_t*)pWrappedCodec;
-
- INTEL_DEBUG_INFO("Decoder.Open width=%d, height=%d, fps=%d",
- TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.width,
- TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.height,
- TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.fps
- );
-
- // Allocation will be done each time we decode the SPS:PPS header
-
- m_bOpened = true;
- return MFX_ERR_NONE;
- }
-
- mfxU32 Decode(struct tmedia_codec_s* pWrappedCodec, const mfxU8* pcInDataPtr, mfxU32 nInDataSize, void **ppOutDataPtr, tsk_size_t *pOutDataMaxSize, const trtp_rtp_header_t* pcRtpHdr)
- {
- mfxU32 nRetSize = 0, nOutXSize;
- mfxStatus status = MFX_ERR_NONE;
- tsk_bool_t append_scp, end_of_unit;
- tsk_bool_t sps_or_pps;
- const uint8_t* pay_ptr = tsk_null;
- tsk_size_t pay_size = 0, size_to_copy = 0;
- bool bGotFrame = false;
- mfxFrameSurface1* pmfxOutSurface = NULL;
- static const tsk_size_t xmax_size = (3840 * 2160 * 3) >> 3; // >>3 instead of >>1 (not an error)
- static tsk_size_t start_code_prefix_size = sizeof(H264_START_CODE_PREFIX);
-
- tdav_codec_h264_intel_t* pWrappedCodecH264 = (tdav_codec_h264_intel_t*)pWrappedCodec;
- tdav_codec_h264_common_t* pWrappedCodecCommon = (tdav_codec_h264_common_t*)pWrappedCodec;
-
- if (!pWrappedCodec || !pcInDataPtr || !nInDataSize || !ppOutDataPtr)
- {
- INTEL_CHECK_STATUS(MFX_ERR_NULL_PTR);
- }
- //INTEL_DEBUG_INFO("Size=%u", nInDataSize);
- if (!m_bOpened)
- {
- INTEL_CHECK_STATUS(MFX_ERR_NOT_INITIALIZED);
- }
-
-
- /* 5.3. NAL Unit Octet Usage
- +---------------+
- |0|1|2|3|4|5|6|7|
- +-+-+-+-+-+-+-+-+
- |F|NRI| Type |
- +---------------+
- */
- if (pcInDataPtr[0] & 0x80) // F ?== 1
- {
- /* reset accumulator */
- m_nAccumulatorPos = 0;
- INTEL_CHECK_STATUS(status = MFX_ERR_UNDEFINED_BEHAVIOR);
- }
-
- // New frame?
- if (m_nLastRtpTimestamp != pcRtpHdr->timestamp)
- {
- m_nAccumulatorPos = 0;
- m_nLastRtpTimestamp = pcRtpHdr->timestamp;
- }
-
- /* get payload */
- if ((tdav_codec_h264_get_pay(pcInDataPtr, nInDataSize, (const void**)&pay_ptr, &pay_size, &append_scp, &end_of_unit) != 0) || !pay_ptr || !pay_size)
- {
- INTEL_BREAK("Depayloader failed to get H.264 content");
- }
+ IntelCodecDecoder(MFXVideoSession* pSession)
+ : IntelCodec(pSession)
+ , m_Inst(*pSession)
+ , m_pAccumulatorPtr(NULL)
+ , m_nAccumulatorSize(0)
+ , m_nAccumulatorPos(0)
+ , m_bInit(false) {
+
+ }
+ virtual ~IntelCodecDecoder() {
+ Close();
+ }
+
+ virtual mfxStatus Close() {
+ m_Inst.Close();
+ TSK_FREE(m_pAccumulatorPtr);
+ m_nAccumulatorSize = 0;
+ m_nAccumulatorPos = 0;
+ m_bInit = false;
+ return IntelCodec::Close();
+ }
+
+ mfxStatus Open(struct tdav_codec_h264_intel_s* pWrappedCodec) {
+ tdav_codec_h264_common_t* pWrappedCodecCommon = (tdav_codec_h264_common_t*)pWrappedCodec;
+
+ INTEL_DEBUG_INFO("Decoder.Open width=%d, height=%d, fps=%d",
+ TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.width,
+ TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.height,
+ TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.fps
+ );
+
+ // Allocation will be done each time we decode the SPS:PPS header
+
+ m_bOpened = true;
+ return MFX_ERR_NONE;
+ }
+
+ mfxU32 Decode(struct tmedia_codec_s* pWrappedCodec, const mfxU8* pcInDataPtr, mfxU32 nInDataSize, void **ppOutDataPtr, tsk_size_t *pOutDataMaxSize, const trtp_rtp_header_t* pcRtpHdr) {
+ mfxU32 nRetSize = 0, nOutXSize;
+ mfxStatus status = MFX_ERR_NONE;
+ tsk_bool_t append_scp, end_of_unit;
+ tsk_bool_t sps_or_pps;
+ const uint8_t* pay_ptr = tsk_null;
+ tsk_size_t pay_size = 0, size_to_copy = 0;
+ bool bGotFrame = false;
+ mfxFrameSurface1* pmfxOutSurface = NULL;
+ static const tsk_size_t xmax_size = (3840 * 2160 * 3) >> 3; // >>3 instead of >>1 (not an error)
+ static tsk_size_t start_code_prefix_size = sizeof(H264_START_CODE_PREFIX);
+
+ tdav_codec_h264_intel_t* pWrappedCodecH264 = (tdav_codec_h264_intel_t*)pWrappedCodec;
+ tdav_codec_h264_common_t* pWrappedCodecCommon = (tdav_codec_h264_common_t*)pWrappedCodec;
+
+ if (!pWrappedCodec || !pcInDataPtr || !nInDataSize || !ppOutDataPtr) {
+ INTEL_CHECK_STATUS(MFX_ERR_NULL_PTR);
+ }
+ //INTEL_DEBUG_INFO("Size=%u", nInDataSize);
+ if (!m_bOpened) {
+ INTEL_CHECK_STATUS(MFX_ERR_NOT_INITIALIZED);
+ }
+
+
+ /* 5.3. NAL Unit Octet Usage
+ +---------------+
+ |0|1|2|3|4|5|6|7|
+ +-+-+-+-+-+-+-+-+
+ |F|NRI| Type |
+ +---------------+
+ */
+ if (pcInDataPtr[0] & 0x80) { // F ?== 1
+ /* reset accumulator */
+ m_nAccumulatorPos = 0;
+ INTEL_CHECK_STATUS(status = MFX_ERR_UNDEFINED_BEHAVIOR);
+ }
+
+ // New frame?
+ if (m_nLastRtpTimestamp != pcRtpHdr->timestamp) {
+ m_nAccumulatorPos = 0;
+ m_nLastRtpTimestamp = pcRtpHdr->timestamp;
+ }
+
+ /* get payload */
+ if ((tdav_codec_h264_get_pay(pcInDataPtr, nInDataSize, (const void**)&pay_ptr, &pay_size, &append_scp, &end_of_unit) != 0) || !pay_ptr || !pay_size) {
+ INTEL_BREAK("Depayloader failed to get H.264 content");
+ }
#if 1 // TODO: MSDK cannot decode slices
- end_of_unit = pcRtpHdr->marker;
+ end_of_unit = pcRtpHdr->marker;
#endif
- //append_scp = tsk_true;
- size_to_copy = pay_size + (append_scp ? start_code_prefix_size : 0);
- // whether it's SPS or PPS (append_scp is false for subsequent FUA chuncks)
- sps_or_pps = append_scp && pay_ptr && ((pay_ptr[0] & 0x1F) == 7 || (pay_ptr[0] & 0x1F) == 8);
-
- // start-accumulator
- if (!m_pAccumulatorPtr)
- {
- if (size_to_copy > xmax_size)
- {
- INTEL_DEBUG_ERROR("%u too big to contain valid encoded data. xmax_size=%u", size_to_copy, xmax_size);
- m_nAccumulatorPos = 0;
- return 0;
- }
- if (!(m_pAccumulatorPtr = (mfxU8*)tsk_calloc(size_to_copy, sizeof(mfxU8))))
- {
- INTEL_DEBUG_ERROR("Failed to allocated new buffer");
- m_nAccumulatorPos = 0;
- return 0;
- }
- m_nAccumulatorSize = (mfxU32)size_to_copy;
- }
- if ((m_nAccumulatorPos + size_to_copy) >= xmax_size)
- {
- INTEL_DEBUG_ERROR("BufferOverflow");
- m_nAccumulatorPos = 0;
- return 0;
- }
- if ((m_nAccumulatorPos + size_to_copy) > m_nAccumulatorSize)
- {
- if (!(m_pAccumulatorPtr = (mfxU8*)tsk_realloc(m_pAccumulatorPtr, (m_nAccumulatorPos + size_to_copy))))
- {
- INTEL_DEBUG_ERROR("Failed to reallocated new buffer");
- m_nAccumulatorPos = 0;
- m_nAccumulatorSize = 0;
- return 0;
- }
- m_nAccumulatorSize = (mfxU32)(m_nAccumulatorPos + size_to_copy);
- }
-
- if (append_scp)
- {
- memcpy(&m_pAccumulatorPtr[m_nAccumulatorPos], H264_START_CODE_PREFIX, start_code_prefix_size);
- m_nAccumulatorPos += (mfxU32)start_code_prefix_size;
- }
- memcpy(&m_pAccumulatorPtr[m_nAccumulatorPos], pay_ptr, pay_size);
- m_nAccumulatorPos += (mfxU32)pay_size;
- // end-accumulator
-
- if (/*rtp_hdr->marker*/end_of_unit)
- {
- /* decode the picture */
- mfxU32 nOutWidth, nOutHeight;
-
- // Decode a Unit
- status = DecodeFrame(pWrappedCodecH264, m_pAccumulatorPtr, m_nAccumulatorPos, !!sps_or_pps, &pmfxOutSurface, bGotFrame);
- if (status != MFX_ERR_NONE)
- {
- INTEL_DEBUG_WARN("DecodeFrame failed: %d", status);
- goto bail;
- }
-
- // Do we have a complete frame?
- if (!bGotFrame || !pmfxOutSurface)
- {
- goto bail;
- }
+ //append_scp = tsk_true;
+ size_to_copy = pay_size + (append_scp ? start_code_prefix_size : 0);
+ // whether it's SPS or PPS (append_scp is false for subsequent FUA chuncks)
+ sps_or_pps = append_scp && pay_ptr && ((pay_ptr[0] & 0x1F) == 7 || (pay_ptr[0] & 0x1F) == 8);
+
+ // start-accumulator
+ if (!m_pAccumulatorPtr) {
+ if (size_to_copy > xmax_size) {
+ INTEL_DEBUG_ERROR("%u too big to contain valid encoded data. xmax_size=%u", size_to_copy, xmax_size);
+ m_nAccumulatorPos = 0;
+ return 0;
+ }
+ if (!(m_pAccumulatorPtr = (mfxU8*)tsk_calloc(size_to_copy, sizeof(mfxU8)))) {
+ INTEL_DEBUG_ERROR("Failed to allocated new buffer");
+ m_nAccumulatorPos = 0;
+ return 0;
+ }
+ m_nAccumulatorSize = (mfxU32)size_to_copy;
+ }
+ if ((m_nAccumulatorPos + size_to_copy) >= xmax_size) {
+ INTEL_DEBUG_ERROR("BufferOverflow");
+ m_nAccumulatorPos = 0;
+ return 0;
+ }
+ if ((m_nAccumulatorPos + size_to_copy) > m_nAccumulatorSize) {
+ if (!(m_pAccumulatorPtr = (mfxU8*)tsk_realloc(m_pAccumulatorPtr, (m_nAccumulatorPos + size_to_copy)))) {
+ INTEL_DEBUG_ERROR("Failed to reallocated new buffer");
+ m_nAccumulatorPos = 0;
+ m_nAccumulatorSize = 0;
+ return 0;
+ }
+ m_nAccumulatorSize = (mfxU32)(m_nAccumulatorPos + size_to_copy);
+ }
+
+ if (append_scp) {
+ memcpy(&m_pAccumulatorPtr[m_nAccumulatorPos], H264_START_CODE_PREFIX, start_code_prefix_size);
+ m_nAccumulatorPos += (mfxU32)start_code_prefix_size;
+ }
+ memcpy(&m_pAccumulatorPtr[m_nAccumulatorPos], pay_ptr, pay_size);
+ m_nAccumulatorPos += (mfxU32)pay_size;
+ // end-accumulator
+
+ if (/*rtp_hdr->marker*/end_of_unit) {
+ /* decode the picture */
+ mfxU32 nOutWidth, nOutHeight;
+
+ // Decode a Unit
+ status = DecodeFrame(pWrappedCodecH264, m_pAccumulatorPtr, m_nAccumulatorPos, !!sps_or_pps, &pmfxOutSurface, bGotFrame);
+ if (status != MFX_ERR_NONE) {
+ INTEL_DEBUG_WARN("DecodeFrame failed: %d", status);
+ goto bail;
+ }
+
+ // Do we have a complete frame?
+ if (!bGotFrame || !pmfxOutSurface) {
+ goto bail;
+ }
#if INTEL_DX11_D3D
- INTEL_CHECK_STATUS(status = pWrappedCodecH264->D3D11Allocator.Lock(pWrappedCodecH264->D3D11Allocator.pthis, pmfxOutSurface->Data.MemId, &(pmfxOutSurface->Data)));
+ INTEL_CHECK_STATUS(status = pWrappedCodecH264->D3D11Allocator.Lock(pWrappedCodecH264->D3D11Allocator.pthis, pmfxOutSurface->Data.MemId, &(pmfxOutSurface->Data)));
#endif
- if (!pmfxOutSurface->Data.Y || !pmfxOutSurface->Data.U || !pmfxOutSurface->Data.V)
- {
+ if (!pmfxOutSurface->Data.Y || !pmfxOutSurface->Data.U || !pmfxOutSurface->Data.V) {
#if INTEL_DX11_D3D
- INTEL_CHECK_STATUS(status = pWrappedCodecH264->D3D11Allocator.Unlock(pWrappedCodecH264->D3D11Allocator.pthis, pmfxOutSurface->Data.MemId, &(pmfxOutSurface->Data)));
+ INTEL_CHECK_STATUS(status = pWrappedCodecH264->D3D11Allocator.Unlock(pWrappedCodecH264->D3D11Allocator.pthis, pmfxOutSurface->Data.MemId, &(pmfxOutSurface->Data)));
#endif
- goto bail;
- }
-
- if (pmfxOutSurface->Info.CropW > 0 && pmfxOutSurface->Info.CropH > 0)
- {
- nOutWidth = pmfxOutSurface->Info.CropW;
- nOutHeight = pmfxOutSurface->Info.CropH;
- }
- else
- {
- nOutWidth = pmfxOutSurface->Info.Width;
- nOutHeight = pmfxOutSurface->Info.Height;
- }
-
- nOutXSize = (nOutWidth * nOutHeight * 3) >> 1; // I420
- /* IDR ? */
- if (((pay_ptr[0] & 0x1F) == 0x05) && TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.callback)
- {
- INTEL_DEBUG_INFO("Decoded H.264 IDR");
- TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.result.type = tmedia_video_decode_result_type_idr;
- TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.result.proto_hdr = pcRtpHdr;
- TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.callback(&TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.result);
- }
- /* fill out */
- if (*pOutDataMaxSize < nOutXSize)
- {
- if ((*ppOutDataPtr = tsk_realloc(*ppOutDataPtr, nOutXSize)))
- {
- *pOutDataMaxSize = nOutXSize;
- }
- else
- {
- *pOutDataMaxSize = 0;
- return 0;
- }
- }
- TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.width = nOutWidth;
- TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.height = nOutHeight;
-
- /* layout picture */
- INTEL_CHECK_STATUS(status = IntelCodecDecoder::LayoutPicture(pmfxOutSurface, (mfxU8 *)*ppOutDataPtr));
- nRetSize = nOutXSize;
+ goto bail;
+ }
+
+ if (pmfxOutSurface->Info.CropW > 0 && pmfxOutSurface->Info.CropH > 0) {
+ nOutWidth = pmfxOutSurface->Info.CropW;
+ nOutHeight = pmfxOutSurface->Info.CropH;
+ }
+ else {
+ nOutWidth = pmfxOutSurface->Info.Width;
+ nOutHeight = pmfxOutSurface->Info.Height;
+ }
+
+ nOutXSize = (nOutWidth * nOutHeight * 3) >> 1; // I420
+ /* IDR ? */
+ if (((pay_ptr[0] & 0x1F) == 0x05) && TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.callback) {
+ INTEL_DEBUG_INFO("Decoded H.264 IDR");
+ TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.result.type = tmedia_video_decode_result_type_idr;
+ TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.result.proto_hdr = pcRtpHdr;
+ TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.callback(&TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.result);
+ }
+ /* fill out */
+ if (*pOutDataMaxSize < nOutXSize) {
+ if ((*ppOutDataPtr = tsk_realloc(*ppOutDataPtr, nOutXSize))) {
+ *pOutDataMaxSize = nOutXSize;
+ }
+ else {
+ *pOutDataMaxSize = 0;
+ return 0;
+ }
+ }
+ TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.width = nOutWidth;
+ TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.height = nOutHeight;
+
+ /* layout picture */
+ INTEL_CHECK_STATUS(status = IntelCodecDecoder::LayoutPicture(pmfxOutSurface, (mfxU8 *)*ppOutDataPtr));
+ nRetSize = nOutXSize;
#if INTEL_DX11_D3D
- INTEL_CHECK_STATUS(status = pWrappedCodecH264->D3D11Allocator.Unlock(pWrappedCodecH264->D3D11Allocator.pthis, pmfxOutSurface->Data.MemId, &(pmfxOutSurface->Data)));
+ INTEL_CHECK_STATUS(status = pWrappedCodecH264->D3D11Allocator.Unlock(pWrappedCodecH264->D3D11Allocator.pthis, pmfxOutSurface->Data.MemId, &(pmfxOutSurface->Data)));
#endif
- } // else if(rtp_hdr->marker)
-
- bail:
- if (end_of_unit)
- {
- /* reset accumulator */
- m_nAccumulatorPos = 0;
- }
-
- if (status != MFX_ERR_NONE)
- {
- INTEL_DEBUG_INFO("Failed to decode the buffer with error code =%d, size=%u, append=%s", status, m_nAccumulatorPos, append_scp ? "yes" : "no");
- if (TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.callback)
- {
- TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.result.type = tmedia_video_decode_result_type_error;
- TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.result.proto_hdr = pcRtpHdr;
- TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.callback(&TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.result);
- }
- }
- return nRetSize;
- }
+ } // else if(rtp_hdr->marker)
+
+bail:
+ if (end_of_unit) {
+ /* reset accumulator */
+ m_nAccumulatorPos = 0;
+ }
+
+ if (status != MFX_ERR_NONE) {
+ INTEL_DEBUG_INFO("Failed to decode the buffer with error code =%d, size=%u, append=%s", status, m_nAccumulatorPos, append_scp ? "yes" : "no");
+ if (TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.callback) {
+ TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.result.type = tmedia_video_decode_result_type_error;
+ TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.result.proto_hdr = pcRtpHdr;
+ TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.callback(&TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.result);
+ }
+ }
+ return nRetSize;
+ }
private:
#if 0
- static mfxStatus WriteSection(mfxU8* plane, mfxU16 factor, mfxU16 chunksize, mfxFrameInfo *pInfo, mfxFrameData *pData, mfxU32 i, mfxU32 j, mfxU8 *pDstPtr)
- {
- memcpy(pDstPtr, plane + (pInfo->CropY * pData->Pitch / factor + pInfo->CropX) + i * pData->Pitch + j, chunksize);
- return MFX_ERR_NONE;
- }
+ static mfxStatus WriteSection(mfxU8* plane, mfxU16 factor, mfxU16 chunksize, mfxFrameInfo *pInfo, mfxFrameData *pData, mfxU32 i, mfxU32 j, mfxU8 *pDstPtr) {
+ memcpy(pDstPtr, plane + (pInfo->CropY * pData->Pitch / factor + pInfo->CropX) + i * pData->Pitch + j, chunksize);
+ return MFX_ERR_NONE;
+ }
#else
#define WriteSection(_plane, _factor, _chunksize, _pInfo, _pData, _i, _j, _pDstPtr) \
memcpy((_pDstPtr), (_plane) + ((_pInfo)->CropY * (_pData)->Pitch / (_factor) + (_pInfo)->CropX) + (_i) * (_pData)->Pitch + (_j), (_chunksize))
@@ -1029,447 +943,391 @@ private:
*(_pDstPtr) = *((_plane) + ((_pInfo)->CropY * (_pData)->Pitch / (_factor) + (_pInfo)->CropX) + (_i) * (_pData)->Pitch + (_j));
#endif
- static mfxStatus LayoutPicture(mfxFrameSurface1 *pSurface, mfxU8 *pDstPtr)
- {
+ static mfxStatus LayoutPicture(mfxFrameSurface1 *pSurface, mfxU8 *pDstPtr) {
#if 1 // ->YUV420
- mfxFrameInfo *pInfo = &pSurface->Info;
- mfxFrameData *pData = &pSurface->Data;
- mfxU32 i, j, h, w;
-
- if (pSurface->Info.CropW > 0 && pSurface->Info.CropH > 0)
- {
- w = pSurface->Info.CropW;
- h = pSurface->Info.CropH;
- }
- else
- {
- w = pSurface->Info.Width;
- h = pSurface->Info.Height;
- }
-
- for (i = 0; i < h; i++)
- {
- WriteSection(pData->Y, 1, w, pInfo, pData, i, 0, pDstPtr);
- pDstPtr += w;
- }
-
- h >>= 1;
- for (i = 0; i < h; i++)
- {
- for (j = 0; j < w; j += 2)
- {
- WriteSection1(pData->UV, 2, pInfo, pData, i, j, pDstPtr);
- pDstPtr += 1;
- }
- }
-
- for (i = 0; i < h; i++)
- {
- for (j = 1; j < w; j += 2)
- {
- WriteSection1(pData->UV, 2, pInfo, pData, i, j, pDstPtr);
- pDstPtr += 1;
- }
- }
+ mfxFrameInfo *pInfo = &pSurface->Info;
+ mfxFrameData *pData = &pSurface->Data;
+ mfxU32 i, j, h, w;
+
+ if (pSurface->Info.CropW > 0 && pSurface->Info.CropH > 0) {
+ w = pSurface->Info.CropW;
+ h = pSurface->Info.CropH;
+ }
+ else {
+ w = pSurface->Info.Width;
+ h = pSurface->Info.Height;
+ }
+
+ for (i = 0; i < h; i++) {
+ WriteSection(pData->Y, 1, w, pInfo, pData, i, 0, pDstPtr);
+ pDstPtr += w;
+ }
+
+ h >>= 1;
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j += 2) {
+ WriteSection1(pData->UV, 2, pInfo, pData, i, j, pDstPtr);
+ pDstPtr += 1;
+ }
+ }
+
+ for (i = 0; i < h; i++) {
+ for (j = 1; j < w; j += 2) {
+ WriteSection1(pData->UV, 2, pInfo, pData, i, j, pDstPtr);
+ pDstPtr += 1;
+ }
+ }
#elif 1 // ->NV12
- mfxFrameInfo *pInfo = &pSurface->Info;
- mfxFrameData *pData = &pSurface->Data;
- mfxU32 i, j, h, w;
-
- if (pSurface->Info.CropW > 0 && pSurface->Info.CropH > 0)
- {
- w = pSurface->Info.CropW;
- h = pSurface->Info.CropH;
- }
- else
- {
- w = pSurface->Info.Width;
- h = pSurface->Info.Height;
- }
-
- for (i = 0; i < h; i++)
- {
- WriteSection(pData->Y, 1, w, pInfo, pData, i, 0, pDstPtr);
- pDstPtr += w;
- }
-
- h >>= 1;
- for (i = 0; i < h; i++)
- {
- for (j = 0; j < w; j += 2)
- {
- WriteSection1(pData->UV, 2, pInfo, pData, i, j, &pDstPtr[0]);
- WriteSection1(pData->UV, 2, pInfo, pData, i, j + 1, &pDstPtr[1]);
- pDstPtr += 2;
- }
- }
+ mfxFrameInfo *pInfo = &pSurface->Info;
+ mfxFrameData *pData = &pSurface->Data;
+ mfxU32 i, j, h, w;
+
+ if (pSurface->Info.CropW > 0 && pSurface->Info.CropH > 0) {
+ w = pSurface->Info.CropW;
+ h = pSurface->Info.CropH;
+ }
+ else {
+ w = pSurface->Info.Width;
+ h = pSurface->Info.Height;
+ }
+
+ for (i = 0; i < h; i++) {
+ WriteSection(pData->Y, 1, w, pInfo, pData, i, 0, pDstPtr);
+ pDstPtr += w;
+ }
+
+ h >>= 1;
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j += 2) {
+ WriteSection1(pData->UV, 2, pInfo, pData, i, j, &pDstPtr[0]);
+ WriteSection1(pData->UV, 2, pInfo, pData, i, j + 1, &pDstPtr[1]);
+ pDstPtr += 2;
+ }
+ }
#endif
- return MFX_ERR_NONE;
- }
-
- mfxStatus DecodeFrame(struct tdav_codec_h264_intel_s* pWrappedCodec, const mfxU8* pcInDataPtr, mfxU32 nInDataSize, bool bSpsOrPps, mfxFrameSurface1** ppmfxOutSurface, bool &bGotFrame)
- {
- mfxStatus status = MFX_ERR_NONE;
- int nSurfaceIndex;
- mfxSyncPoint syncp;
- bGotFrame = false;
- *ppmfxOutSurface = NULL;
- mfxFrameSurface1* pmfxOutSurface = NULL;
-
-#if 0
- if (!bSpsOrPps && !m_bInit)
- {
- INTEL_CHECK_STATUS(status = MFX_ERR_NOT_INITIALIZED);
- }
+ return MFX_ERR_NONE;
+ }
+
+ mfxStatus DecodeFrame(struct tdav_codec_h264_intel_s* pWrappedCodec, const mfxU8* pcInDataPtr, mfxU32 nInDataSize, bool bSpsOrPps, mfxFrameSurface1** ppmfxOutSurface, bool &bGotFrame) {
+ mfxStatus status = MFX_ERR_NONE;
+ int nSurfaceIndex;
+ mfxSyncPoint syncp;
+ bGotFrame = false;
+ *ppmfxOutSurface = NULL;
+ mfxFrameSurface1* pmfxOutSurface = NULL;
+
+#if 0
+ if (!bSpsOrPps && !m_bInit) {
+ INTEL_CHECK_STATUS(status = MFX_ERR_NOT_INITIALIZED);
+ }
#endif
- if (m_sBitstream.DataLength < nInDataSize)
- {
- INTEL_CHECK_STATUS(status = AllocateBitstream(nInDataSize));
- }
- memcpy(m_sBitstream.Data, pcInDataPtr, nInDataSize);
- m_sBitstream.DataOffset = 0;
- m_sBitstream.DataLength = nInDataSize;
- m_sBitstream.DataFlag = MFX_BITSTREAM_COMPLETE_FRAME;
-
- if (bSpsOrPps || !m_bInit)
- {
- memset(&m_sParamReq, 0, sizeof(m_sParamReq));
- m_sParamReq.mfx.CodecId = MFX_CODEC_AVC;
- m_sParamReq.mfx.FrameInfo.FourCC = MFX_FOURCC_NV12;
- m_sParamReq.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
+ if (m_sBitstream.DataLength < nInDataSize) {
+ INTEL_CHECK_STATUS(status = AllocateBitstream(nInDataSize));
+ }
+ memcpy(m_sBitstream.Data, pcInDataPtr, nInDataSize);
+ m_sBitstream.DataOffset = 0;
+ m_sBitstream.DataLength = nInDataSize;
+ m_sBitstream.DataFlag = MFX_BITSTREAM_COMPLETE_FRAME;
+
+ if (bSpsOrPps || !m_bInit) {
+ memset(&m_sParamReq, 0, sizeof(m_sParamReq));
+ m_sParamReq.mfx.CodecId = MFX_CODEC_AVC;
+ m_sParamReq.mfx.FrameInfo.FourCC = MFX_FOURCC_NV12;
+ m_sParamReq.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
#if INTEL_DX11_D3D
- m_sParamReq.IOPattern = MFX_IOPATTERN_OUT_VIDEO_MEMORY;
+ m_sParamReq.IOPattern = MFX_IOPATTERN_OUT_VIDEO_MEMORY;
#else
- m_sParamReq.IOPattern = MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
+ m_sParamReq.IOPattern = MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
#endif
- m_sParamReq.AsyncDepth = 1; // Low latency: limits internal frame buffering
-
- status = m_Inst.DecodeHeader(&m_sBitstream, &m_sParamReq);
- if (status == MFX_WRN_PARTIAL_ACCELERATION)
- {
- status = MFX_ERR_NONE;
- }
- INTEL_CHECK_STATUS(status);
-
- memcpy(&m_sParamSel, &m_sParamReq, sizeof(m_sParamSel));
-
- // Check parameters
- status = m_Inst.Query(&m_sParamReq, &m_sParamReq);
- if (status != MFX_ERR_NONE && status != MFX_WRN_INCOMPATIBLE_VIDEO_PARAM /* Best one will be selected by the encoder */)
- {
- INTEL_CHECK_STATUS(status);
- }
-
- // Query number required surfaces for encoder
- memset(&m_sAllocRequest, 0, sizeof(m_sAllocRequest));
- INTEL_CHECK_STATUS(status = m_Inst.QueryIOSurf(&m_sParamReq, &m_sAllocRequest));
+ m_sParamReq.AsyncDepth = 1; // Low latency: limits internal frame buffering
+
+ status = m_Inst.DecodeHeader(&m_sBitstream, &m_sParamReq);
+ if (status == MFX_WRN_PARTIAL_ACCELERATION) {
+ status = MFX_ERR_NONE;
+ }
+ INTEL_CHECK_STATUS(status);
+
+ memcpy(&m_sParamSel, &m_sParamReq, sizeof(m_sParamSel));
+
+ // Check parameters
+ status = m_Inst.Query(&m_sParamReq, &m_sParamReq);
+ if (status != MFX_ERR_NONE && status != MFX_WRN_INCOMPATIBLE_VIDEO_PARAM /* Best one will be selected by the encoder */) {
+ INTEL_CHECK_STATUS(status);
+ }
+
+ // Query number required surfaces for encoder
+ memset(&m_sAllocRequest, 0, sizeof(m_sAllocRequest));
+ INTEL_CHECK_STATUS(status = m_Inst.QueryIOSurf(&m_sParamReq, &m_sAllocRequest));
#if INTEL_DX11_D3D
- m_sAllocRequest.Type |= D3D11_WILL_READ; // Hint to DX11 memory handler that application will read data from output surfaces
+ m_sAllocRequest.Type |= D3D11_WILL_READ; // Hint to DX11 memory handler that application will read data from output surfaces
#endif
- // Allocate surfaces for decoder
+ // Allocate surfaces for decoder
#if INTEL_DX11_D3D
- INTEL_CHECK_STATUS(status = pWrappedCodec->D3D11Allocator.Alloc(pWrappedCodec->D3D11Allocator.pthis, &m_sAllocRequest, &m_sD3D11Response));
- if (m_sD3D11Response.NumFrameActual == 0)
- {
- INTEL_CHECK_STATUS(status = MFX_ERR_UNKNOWN);
- }
- INTEL_DEBUG_INFO("nEncSurfNum = %hu", m_sD3D11Response.NumFrameActual);
- INTEL_CHECK_STATUS(status = AllocSurfaces(m_sD3D11Response.NumFrameActual, m_sAllocRequest.Info.Width, m_sAllocRequest.Info.Height, &m_sParamReq.mfx.FrameInfo));
+ INTEL_CHECK_STATUS(status = pWrappedCodec->D3D11Allocator.Alloc(pWrappedCodec->D3D11Allocator.pthis, &m_sAllocRequest, &m_sD3D11Response));
+ if (m_sD3D11Response.NumFrameActual == 0) {
+ INTEL_CHECK_STATUS(status = MFX_ERR_UNKNOWN);
+ }
+ INTEL_DEBUG_INFO("nEncSurfNum = %hu", m_sD3D11Response.NumFrameActual);
+ INTEL_CHECK_STATUS(status = AllocSurfaces(m_sD3D11Response.NumFrameActual, m_sAllocRequest.Info.Width, m_sAllocRequest.Info.Height, &m_sParamReq.mfx.FrameInfo));
#else
- INTEL_DEBUG_INFO("nEncSurfNum = %hu", m_sAllocRequest.NumFrameSuggested);
- INTEL_CHECK_STATUS(status = AllocSurfaces(m_sAllocRequest.NumFrameSuggested, m_sAllocRequest.Info.Width, m_sAllocRequest.Info.Height, &m_sParamReq.mfx.FrameInfo));
-#endif
- // Initialize the Media SDK decoder
- status = m_Inst.Init(&m_sParamReq);
- if (status != MFX_ERR_NONE && status != MFX_WRN_PARTIAL_ACCELERATION)
- {
- INTEL_CHECK_STATUS(status);
- }
- INTEL_DEBUG_INFO("Decoder->Init() returned: %d", status);
-
- m_bInit = true;
- }
-
- //
- // Stage 1: Main decoding loop
- //
- while (MFX_ERR_NONE <= status || MFX_ERR_MORE_DATA == status || MFX_ERR_MORE_SURFACE == status)
- {
- if (MFX_WRN_DEVICE_BUSY == status)
- {
- tsk_thread_sleep(1); // Wait if device is busy, then repeat the same call to DecodeFrameAsync
- }
-
- if (MFX_ERR_MORE_DATA == status)
- {
- return MFX_ERR_NONE;
- }
-
- if (MFX_ERR_MORE_SURFACE == status || MFX_ERR_NONE == status)
- {
- nSurfaceIndex = GetFreeSurfaceIndex(); // Find free frame surface
- if (MFX_ERR_NOT_FOUND == nSurfaceIndex)
- {
- INTEL_CHECK_STATUS((status = MFX_ERR_MEMORY_ALLOC));
- }
- }
-
- // Decode a frame asychronously (returns immediately)
- // - If input bitstream contains multiple frames DecodeFrameAsync will start decoding multiple frames, and remove them from bitstream
- status = m_Inst.DecodeFrameAsync(&m_sBitstream, m_ppSurfacePtrs[nSurfaceIndex], &pmfxOutSurface, &syncp);
-
- // Ignore warnings if output is available,
- // if no output and no action required just repeat the DecodeFrameAsync call
- if (MFX_ERR_NONE < status && syncp)
- {
- status = MFX_ERR_NONE;
- }
-
- if (MFX_ERR_NONE == status)
- {
- status = m_pSession->SyncOperation(syncp, 60000); // Synchronize. Wait until decoded frame is ready
- }
-
- if (MFX_ERR_NONE == status)
- {
- bGotFrame = true;
- if (pmfxOutSurface)
- {
- *ppmfxOutSurface = pmfxOutSurface;
- }
- }
- }
-
- //
- // Stage 2: Retrieve the buffered decoded frames
- //
- while (MFX_ERR_NONE <= status || MFX_ERR_MORE_SURFACE == status)
- {
- if (MFX_WRN_DEVICE_BUSY == status)
- {
- tsk_thread_sleep(1); // Wait if device is busy, then repeat the same call to DecodeFrameAsync
- }
-
- nSurfaceIndex = GetFreeSurfaceIndex(); // Find free frame surface
- if (MFX_ERR_NOT_FOUND == nSurfaceIndex)
- {
- INTEL_CHECK_STATUS((status = MFX_ERR_MEMORY_ALLOC));
- }
-
- // Decode a frame asychronously (returns immediately)
- status = m_Inst.DecodeFrameAsync(NULL, m_ppSurfacePtrs[nSurfaceIndex], ppmfxOutSurface, &syncp);
-
- // Ignore warnings if output is available,
- // if no output and no action required just repeat the DecodeFrameAsync call
- if (MFX_ERR_NONE < status && syncp)
- {
- status = MFX_ERR_NONE;
- }
-
- if (MFX_ERR_NONE == status)
- {
- status = m_pSession->SyncOperation(syncp, 60000); // Synchronize. Waits until decoded frame is ready
- }
-
- if (MFX_ERR_NONE == status)
- {
- bGotFrame = true;
- if (pmfxOutSurface)
- {
- *ppmfxOutSurface = pmfxOutSurface;
- }
- }
- }
-
- status = MFX_ERR_NONE;
-
- bail:
- return status;
- }
+ INTEL_DEBUG_INFO("nEncSurfNum = %hu", m_sAllocRequest.NumFrameSuggested);
+ INTEL_CHECK_STATUS(status = AllocSurfaces(m_sAllocRequest.NumFrameSuggested, m_sAllocRequest.Info.Width, m_sAllocRequest.Info.Height, &m_sParamReq.mfx.FrameInfo));
+#endif
+ // Initialize the Media SDK decoder
+ status = m_Inst.Init(&m_sParamReq);
+ if (status != MFX_ERR_NONE && status != MFX_WRN_PARTIAL_ACCELERATION) {
+ INTEL_CHECK_STATUS(status);
+ }
+ INTEL_DEBUG_INFO("Decoder->Init() returned: %d", status);
+
+ m_bInit = true;
+ }
+
+ //
+ // Stage 1: Main decoding loop
+ //
+ while (MFX_ERR_NONE <= status || MFX_ERR_MORE_DATA == status || MFX_ERR_MORE_SURFACE == status) {
+ if (MFX_WRN_DEVICE_BUSY == status) {
+ tsk_thread_sleep(1); // Wait if device is busy, then repeat the same call to DecodeFrameAsync
+ }
+
+ if (MFX_ERR_MORE_DATA == status) {
+ return MFX_ERR_NONE;
+ }
+
+ if (MFX_ERR_MORE_SURFACE == status || MFX_ERR_NONE == status) {
+ nSurfaceIndex = GetFreeSurfaceIndex(); // Find free frame surface
+ if (MFX_ERR_NOT_FOUND == nSurfaceIndex) {
+ INTEL_CHECK_STATUS((status = MFX_ERR_MEMORY_ALLOC));
+ }
+ }
+
+ // Decode a frame asychronously (returns immediately)
+ // - If input bitstream contains multiple frames DecodeFrameAsync will start decoding multiple frames, and remove them from bitstream
+ status = m_Inst.DecodeFrameAsync(&m_sBitstream, m_ppSurfacePtrs[nSurfaceIndex], &pmfxOutSurface, &syncp);
+
+ // Ignore warnings if output is available,
+ // if no output and no action required just repeat the DecodeFrameAsync call
+ if (MFX_ERR_NONE < status && syncp) {
+ status = MFX_ERR_NONE;
+ }
+
+ if (MFX_ERR_NONE == status) {
+ status = m_pSession->SyncOperation(syncp, 60000); // Synchronize. Wait until decoded frame is ready
+ }
+
+ if (MFX_ERR_NONE == status) {
+ bGotFrame = true;
+ if (pmfxOutSurface) {
+ *ppmfxOutSurface = pmfxOutSurface;
+ }
+ }
+ }
+
+ //
+ // Stage 2: Retrieve the buffered decoded frames
+ //
+ while (MFX_ERR_NONE <= status || MFX_ERR_MORE_SURFACE == status) {
+ if (MFX_WRN_DEVICE_BUSY == status) {
+ tsk_thread_sleep(1); // Wait if device is busy, then repeat the same call to DecodeFrameAsync
+ }
+
+ nSurfaceIndex = GetFreeSurfaceIndex(); // Find free frame surface
+ if (MFX_ERR_NOT_FOUND == nSurfaceIndex) {
+ INTEL_CHECK_STATUS((status = MFX_ERR_MEMORY_ALLOC));
+ }
+
+ // Decode a frame asychronously (returns immediately)
+ status = m_Inst.DecodeFrameAsync(NULL, m_ppSurfacePtrs[nSurfaceIndex], ppmfxOutSurface, &syncp);
+
+ // Ignore warnings if output is available,
+ // if no output and no action required just repeat the DecodeFrameAsync call
+ if (MFX_ERR_NONE < status && syncp) {
+ status = MFX_ERR_NONE;
+ }
+
+ if (MFX_ERR_NONE == status) {
+ status = m_pSession->SyncOperation(syncp, 60000); // Synchronize. Waits until decoded frame is ready
+ }
+
+ if (MFX_ERR_NONE == status) {
+ bGotFrame = true;
+ if (pmfxOutSurface) {
+ *ppmfxOutSurface = pmfxOutSurface;
+ }
+ }
+ }
+
+ status = MFX_ERR_NONE;
+
+bail:
+ return status;
+ }
private:
- mfxU8 *m_pAccumulatorPtr;
- mfxU32 m_nAccumulatorSize;
- mfxU32 m_nAccumulatorPos;
- mfxU32 m_nLastRtpTimestamp;
- MFXVideoDECODE m_Inst;
- bool m_bInit;
+ mfxU8 *m_pAccumulatorPtr;
+ mfxU32 m_nAccumulatorSize;
+ mfxU32 m_nAccumulatorPos;
+ mfxU32 m_nLastRtpTimestamp;
+ MFXVideoDECODE m_Inst;
+ bool m_bInit;
};
/* ============ H.264 Base/Main Profile X.X Plugin interface functions ================= */
static int tdav_codec_h264_intel_set(tmedia_codec_t* self, const tmedia_param_t* param)
{
- tdav_codec_h264_intel_t* h264 = (tdav_codec_h264_intel_t*)self;
- if (param->value_type == tmedia_pvt_int32)
- {
- if (tsk_striequals(param->key, "action"))
- {
- tmedia_codec_action_t action = (tmedia_codec_action_t)TSK_TO_INT32((uint8_t*)param->value);
- switch (action) {
- case tmedia_codec_action_encode_idr:
- {
- h264->encoder.force_idr = tsk_true;
- return 0;
- }
- case tmedia_codec_action_bw_up:
- case tmedia_codec_action_bw_down:
- {
- if (self->opened)
- {
- INTEL_CHECK_STATUS(h264->encoder.pInst->UpdateBandwidth(action == tmedia_codec_action_bw_up, TMEDIA_CODEC(h264)->bandwidth_max_upload));
- }
- break;
- }
- }
- }
- else if (tsk_striequals(param->key, "bw_kbps")) // both up and down (from the SDP)
- {
- int32_t max_bw_userdefine = tmedia_defaults_get_bandwidth_video_upload_max();
- int32_t max_bw_new = *((int32_t*)param->value);
- if (max_bw_userdefine > 0)
- {
- // do not use more than what the user defined in it's configuration
- TMEDIA_CODEC(h264)->bandwidth_max_upload = TSK_MIN(max_bw_new, max_bw_userdefine);
- }
- else
- {
- TMEDIA_CODEC(h264)->bandwidth_max_upload = max_bw_new;
- }
- INTEL_DEBUG_INFO("bandwidth-max-upload=%d", TMEDIA_CODEC(h264)->bandwidth_max_upload);
- if (self->opened)
- {
- INTEL_CHECK_STATUS(h264->encoder.pInst->SetMaxBandwidth(TMEDIA_CODEC(h264)->bandwidth_max_upload));
- }
- return 0;
- }
- else if (tsk_striequals(param->key, "bandwidth-max-upload"))
- {
- int32_t bw_max_upload = *((int32_t*)param->value);
- TSK_DEBUG_INFO("OpenH264 codec: bandwidth-max-upload=%d", bw_max_upload);
- TMEDIA_CODEC(h264)->bandwidth_max_upload = bw_max_upload;
- if (self->opened)
- {
- INTEL_CHECK_STATUS(h264->encoder.pInst->SetMaxBandwidth(TMEDIA_CODEC(h264)->bandwidth_max_upload));
- }
- return 0;
- }
- else if (tsk_striequals(param->key, "rotation"))
- {
- int rotation = *((int32_t*)param->value);
- if (h264->encoder.rotation != rotation)
- {
- if (self->opened)
- {
- int ret;
- h264->encoder.rotation = rotation;
- if ((ret = tdav_codec_h264_intel_close_encoder(h264)))
- {
- return ret;
- }
- if ((ret = tdav_codec_h264_intel_open_encoder(h264)))
- {
- return ret;
- }
- }
- }
- return 0;
- }
- }
+ tdav_codec_h264_intel_t* h264 = (tdav_codec_h264_intel_t*)self;
+ if (param->value_type == tmedia_pvt_int32) {
+ if (tsk_striequals(param->key, "action")) {
+ tmedia_codec_action_t action = (tmedia_codec_action_t)TSK_TO_INT32((uint8_t*)param->value);
+ switch (action) {
+ case tmedia_codec_action_encode_idr: {
+ h264->encoder.force_idr = tsk_true;
+ return 0;
+ }
+ case tmedia_codec_action_bw_up:
+ case tmedia_codec_action_bw_down: {
+ if (self->opened) {
+ INTEL_CHECK_STATUS(h264->encoder.pInst->UpdateBandwidth(action == tmedia_codec_action_bw_up, TMEDIA_CODEC(h264)->bandwidth_max_upload));
+ }
+ break;
+ }
+ }
+ }
+ else if (tsk_striequals(param->key, "bw_kbps")) { // both up and down (from the SDP)
+ int32_t max_bw_userdefine = tmedia_defaults_get_bandwidth_video_upload_max();
+ int32_t max_bw_new = *((int32_t*)param->value);
+ if (max_bw_userdefine > 0) {
+ // do not use more than what the user defined in it's configuration
+ TMEDIA_CODEC(h264)->bandwidth_max_upload = TSK_MIN(max_bw_new, max_bw_userdefine);
+ }
+ else {
+ TMEDIA_CODEC(h264)->bandwidth_max_upload = max_bw_new;
+ }
+ INTEL_DEBUG_INFO("bandwidth-max-upload=%d", TMEDIA_CODEC(h264)->bandwidth_max_upload);
+ if (self->opened) {
+ INTEL_CHECK_STATUS(h264->encoder.pInst->SetMaxBandwidth(TMEDIA_CODEC(h264)->bandwidth_max_upload));
+ }
+ return 0;
+ }
+ else if (tsk_striequals(param->key, "bandwidth-max-upload")) {
+ int32_t bw_max_upload = *((int32_t*)param->value);
+ TSK_DEBUG_INFO("OpenH264 codec: bandwidth-max-upload=%d", bw_max_upload);
+ TMEDIA_CODEC(h264)->bandwidth_max_upload = bw_max_upload;
+ if (self->opened) {
+ INTEL_CHECK_STATUS(h264->encoder.pInst->SetMaxBandwidth(TMEDIA_CODEC(h264)->bandwidth_max_upload));
+ }
+ return 0;
+ }
+ else if (tsk_striequals(param->key, "rotation")) {
+ int rotation = *((int32_t*)param->value);
+ if (h264->encoder.rotation != rotation) {
+ if (self->opened) {
+ int ret;
+ h264->encoder.rotation = rotation;
+ if ((ret = tdav_codec_h264_intel_close_encoder(h264))) {
+ return ret;
+ }
+ if ((ret = tdav_codec_h264_intel_open_encoder(h264))) {
+ return ret;
+ }
+ }
+ }
+ return 0;
+ }
+ }
bail:
- return -1;
+ return -1;
}
static int tdav_codec_h264_intel_open(tmedia_codec_t* self)
{
- int ret;
- tdav_codec_h264_intel_t* h264 = (tdav_codec_h264_intel_t*)self;
+ int ret;
+ tdav_codec_h264_intel_t* h264 = (tdav_codec_h264_intel_t*)self;
- if (!h264) {
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
+ if (!h264) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
- /* the caller (base class) already checked that the codec is not opened */
+ /* the caller (base class) already checked that the codec is not opened */
- // Encoder
- if ((ret = tdav_codec_h264_intel_open_encoder(h264))) {
- return ret;
- }
+ // Encoder
+ if ((ret = tdav_codec_h264_intel_open_encoder(h264))) {
+ return ret;
+ }
- // Decoder
- if ((ret = tdav_codec_h264_intel_open_decoder(h264))) {
- return ret;
- }
+ // Decoder
+ if ((ret = tdav_codec_h264_intel_open_decoder(h264))) {
+ return ret;
+ }
- return 0;
+ return 0;
}
static int tdav_codec_h264_intel_close(tmedia_codec_t* self)
{
- tdav_codec_h264_intel_t* h264 = (tdav_codec_h264_intel_t*)self;
+ tdav_codec_h264_intel_t* h264 = (tdav_codec_h264_intel_t*)self;
- if (!h264)
- {
- INTEL_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
+ if (!h264) {
+ INTEL_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
- /* the caller (base class) alreasy checked that the codec is opened */
+ /* the caller (base class) alreasy checked that the codec is opened */
- // Encoder
- tdav_codec_h264_intel_close_encoder(h264);
+ // Encoder
+ tdav_codec_h264_intel_close_encoder(h264);
- // Decoder
- tdav_codec_h264_intel_close_decoder(h264);
+ // Decoder
+ tdav_codec_h264_intel_close_decoder(h264);
- return 0;
+ return 0;
}
static tsk_size_t tdav_codec_h264_intel_encode(tmedia_codec_t* self, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size)
{
- tdav_codec_h264_intel_t* h264 = (tdav_codec_h264_intel_t*)self;
- (void)(out_data);
- (void)(out_max_size);
-
- if (!h264 || !h264->encoder.pInst)
- {
- INTEL_CHECK_STATUS(MFX_ERR_NULL_PTR);
- }
- INTEL_CHECK_STATUS(h264->encoder.pInst->Encode(self, (const mfxU8*)in_data, (mfxU32)in_size));
+ tdav_codec_h264_intel_t* h264 = (tdav_codec_h264_intel_t*)self;
+ (void)(out_data);
+ (void)(out_max_size);
+
+ if (!h264 || !h264->encoder.pInst) {
+ INTEL_CHECK_STATUS(MFX_ERR_NULL_PTR);
+ }
+ INTEL_CHECK_STATUS(h264->encoder.pInst->Encode(self, (const mfxU8*)in_data, (mfxU32)in_size));
bail:
- return 0;
+ return 0;
}
static tsk_size_t tdav_codec_h264_intel_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)
{
- tdav_codec_h264_intel_t* h264 = (tdav_codec_h264_intel_t*)self;
+ tdav_codec_h264_intel_t* h264 = (tdav_codec_h264_intel_t*)self;
- if (!h264 || !h264->decoder.pInst)
- {
- INTEL_CHECK_STATUS(MFX_ERR_NULL_PTR);
- }
- return (tsk_size_t)h264->decoder.pInst->Decode(self, (const mfxU8*)in_data, (mfxU32)in_size, out_data, out_max_size, (const trtp_rtp_header_t*)proto_hdr);
+ if (!h264 || !h264->decoder.pInst) {
+ INTEL_CHECK_STATUS(MFX_ERR_NULL_PTR);
+ }
+ return (tsk_size_t)h264->decoder.pInst->Decode(self, (const mfxU8*)in_data, (mfxU32)in_size, out_data, out_max_size, (const trtp_rtp_header_t*)proto_hdr);
bail:
- return 0;
+ return 0;
}
static tsk_bool_t tdav_codec_h264_intel_sdp_att_match(const tmedia_codec_t* self, const char* att_name, const char* att_value)
{
- return tdav_codec_h264_common_sdp_att_match((tdav_codec_h264_common_t*)self, att_name, att_value);
+ return tdav_codec_h264_common_sdp_att_match((tdav_codec_h264_common_t*)self, att_name, att_value);
}
static char* tdav_codec_h264_intel_sdp_att_get(const tmedia_codec_t* self, const char* att_name)
{
- char* att = tdav_codec_h264_common_sdp_att_get((const tdav_codec_h264_common_t*)self, att_name);
- if (att && tsk_striequals(att_name, "fmtp")) {
- tsk_strcat(&att, "; impl=intel");
- }
- return att;
+ char* att = tdav_codec_h264_common_sdp_att_get((const tdav_codec_h264_common_t*)self, att_name);
+ if (att && tsk_striequals(att_name, "fmtp")) {
+ tsk_strcat(&att, "; impl=intel");
+ }
+ return att;
}
/* ============ H.264 Base Profile Plugin interface ================= */
@@ -1477,63 +1335,61 @@ static char* tdav_codec_h264_intel_sdp_att_get(const tmedia_codec_t* self, const
/* constructor */
static tsk_object_t* tdav_codec_h264_intel_base_ctor(tsk_object_t * self, va_list * app)
{
- tdav_codec_h264_intel_t *h264 = (tdav_codec_h264_intel_t*)self;
- if (h264) {
- /* init base: called by tmedia_codec_create() */
- /* init self */
- if (tdav_codec_h264_intel_init(h264, profile_idc_baseline) != 0) {
- return tsk_null;
- }
- }
- return self;
+ tdav_codec_h264_intel_t *h264 = (tdav_codec_h264_intel_t*)self;
+ if (h264) {
+ /* init base: called by tmedia_codec_create() */
+ /* init self */
+ if (tdav_codec_h264_intel_init(h264, profile_idc_baseline) != 0) {
+ return tsk_null;
+ }
+ }
+ return self;
}
/* destructor */
static tsk_object_t* tdav_codec_h264_intel_base_dtor(tsk_object_t * self)
{
- tdav_codec_h264_intel_t *h264 = (tdav_codec_h264_intel_t*)self;
- if (h264) {
- /* deinit base */
- tdav_codec_h264_common_deinit(TDAV_CODEC_H264_COMMON(self));
- /* deinit self */
- tdav_codec_h264_intel_deinit(h264);
- }
-
- return self;
+ tdav_codec_h264_intel_t *h264 = (tdav_codec_h264_intel_t*)self;
+ if (h264) {
+ /* deinit base */
+ tdav_codec_h264_common_deinit(TDAV_CODEC_H264_COMMON(self));
+ /* deinit self */
+ tdav_codec_h264_intel_deinit(h264);
+ }
+
+ return self;
}
/* object definition */
-static const tsk_object_def_t tdav_codec_h264_intel_base_def_s =
-{
- sizeof(tdav_codec_h264_intel_t),
- tdav_codec_h264_intel_base_ctor,
- tdav_codec_h264_intel_base_dtor,
- tmedia_codec_cmp,
+static const tsk_object_def_t tdav_codec_h264_intel_base_def_s = {
+ sizeof(tdav_codec_h264_intel_t),
+ tdav_codec_h264_intel_base_ctor,
+ tdav_codec_h264_intel_base_dtor,
+ tmedia_codec_cmp,
};
/* plugin definition*/
-static const tmedia_codec_plugin_def_t tdav_codec_h264_intel_base_plugin_def_s =
-{
- &tdav_codec_h264_intel_base_def_s,
-
- tmedia_video,
- tmedia_codec_id_h264_bp,
- "H264",
- "H264 Base Profile (Intel Media SDK)",
- TMEDIA_CODEC_FORMAT_H264_BP,
- tsk_true,
- 90000, // rate
-
- /* audio */
- { 0 },
-
- /* video (width, height, fps) */
- { 176, 144, 0 }, // fps is @deprecated
-
- tdav_codec_h264_intel_set,
- tdav_codec_h264_intel_open,
- tdav_codec_h264_intel_close,
- tdav_codec_h264_intel_encode,
- tdav_codec_h264_intel_decode,
- tdav_codec_h264_intel_sdp_att_match,
- tdav_codec_h264_intel_sdp_att_get
+static const tmedia_codec_plugin_def_t tdav_codec_h264_intel_base_plugin_def_s = {
+ &tdav_codec_h264_intel_base_def_s,
+
+ tmedia_video,
+ tmedia_codec_id_h264_bp,
+ "H264",
+ "H264 Base Profile (Intel Media SDK)",
+ TMEDIA_CODEC_FORMAT_H264_BP,
+ tsk_true,
+ 90000, // rate
+
+ /* audio */
+ { 0 },
+
+ /* video (width, height, fps) */
+ { 176, 144, 0 }, // fps is @deprecated
+
+ tdav_codec_h264_intel_set,
+ tdav_codec_h264_intel_open,
+ tdav_codec_h264_intel_close,
+ tdav_codec_h264_intel_encode,
+ tdav_codec_h264_intel_decode,
+ tdav_codec_h264_intel_sdp_att_match,
+ tdav_codec_h264_intel_sdp_att_get
};
const tmedia_codec_plugin_def_t *tdav_codec_h264_intel_base_plugin_def_t = &tdav_codec_h264_intel_base_plugin_def_s;
@@ -1543,64 +1399,61 @@ const tmedia_codec_plugin_def_t *tdav_codec_h264_intel_base_plugin_def_t = &tdav
/* constructor */
static tsk_object_t* tdav_codec_h264_intel_main_ctor(tsk_object_t * self, va_list * app)
{
- tdav_codec_h264_intel_t *h264 = (tdav_codec_h264_intel_t*)self;
- if (h264) {
- /* init main: called by tmedia_codec_create() */
- /* init self */
- if (tdav_codec_h264_intel_init(h264, profile_idc_main) != 0) {
- return tsk_null;
- }
- }
- return self;
+ tdav_codec_h264_intel_t *h264 = (tdav_codec_h264_intel_t*)self;
+ if (h264) {
+ /* init main: called by tmedia_codec_create() */
+ /* init self */
+ if (tdav_codec_h264_intel_init(h264, profile_idc_main) != 0) {
+ return tsk_null;
+ }
+ }
+ return self;
}
/* destructor */
static tsk_object_t* tdav_codec_h264_intel_main_dtor(tsk_object_t * self)
{
- tdav_codec_h264_intel_t *h264 = (tdav_codec_h264_intel_t*)self;
- if (h264)
- {
- /* deinit main */
- tdav_codec_h264_common_deinit(TDAV_CODEC_H264_COMMON(self));
- /* deinit self */
- tdav_codec_h264_intel_deinit(h264);
- }
-
- return self;
+ tdav_codec_h264_intel_t *h264 = (tdav_codec_h264_intel_t*)self;
+ if (h264) {
+ /* deinit main */
+ tdav_codec_h264_common_deinit(TDAV_CODEC_H264_COMMON(self));
+ /* deinit self */
+ tdav_codec_h264_intel_deinit(h264);
+ }
+
+ return self;
}
/* object definition */
-static const tsk_object_def_t tdav_codec_h264_intel_main_def_s =
-{
- sizeof(tdav_codec_h264_intel_t),
- tdav_codec_h264_intel_main_ctor,
- tdav_codec_h264_intel_main_dtor,
- tmedia_codec_cmp,
+static const tsk_object_def_t tdav_codec_h264_intel_main_def_s = {
+ sizeof(tdav_codec_h264_intel_t),
+ tdav_codec_h264_intel_main_ctor,
+ tdav_codec_h264_intel_main_dtor,
+ tmedia_codec_cmp,
};
/* plugin definition*/
-static const tmedia_codec_plugin_def_t tdav_codec_h264_intel_main_plugin_def_s =
-{
- &tdav_codec_h264_intel_main_def_s,
-
- tmedia_video,
- tmedia_codec_id_h264_mp,
- "H264",
- "H264 main Profile (Intel Media SDK)",
- TMEDIA_CODEC_FORMAT_H264_MP,
- tsk_true,
- 90000, // rate
-
- /* audio */
- { 0 },
-
- /* video (width, height, fps) */
- { 176, 144, 0 }, // fps is @deprecated
-
- tdav_codec_h264_intel_set,
- tdav_codec_h264_intel_open,
- tdav_codec_h264_intel_close,
- tdav_codec_h264_intel_encode,
- tdav_codec_h264_intel_decode,
- tdav_codec_h264_intel_sdp_att_match,
- tdav_codec_h264_intel_sdp_att_get
+static const tmedia_codec_plugin_def_t tdav_codec_h264_intel_main_plugin_def_s = {
+ &tdav_codec_h264_intel_main_def_s,
+
+ tmedia_video,
+ tmedia_codec_id_h264_mp,
+ "H264",
+ "H264 main Profile (Intel Media SDK)",
+ TMEDIA_CODEC_FORMAT_H264_MP,
+ tsk_true,
+ 90000, // rate
+
+ /* audio */
+ { 0 },
+
+ /* video (width, height, fps) */
+ { 176, 144, 0 }, // fps is @deprecated
+
+ tdav_codec_h264_intel_set,
+ tdav_codec_h264_intel_open,
+ tdav_codec_h264_intel_close,
+ tdav_codec_h264_intel_encode,
+ tdav_codec_h264_intel_decode,
+ tdav_codec_h264_intel_sdp_att_match,
+ tdav_codec_h264_intel_sdp_att_get
};
const tmedia_codec_plugin_def_t *tdav_codec_h264_intel_main_plugin_def_t = &tdav_codec_h264_intel_main_plugin_def_s;
@@ -1608,171 +1461,158 @@ const tmedia_codec_plugin_def_t *tdav_codec_h264_intel_main_plugin_def_t = &tdav
static int tdav_codec_h264_intel_open_encoder(tdav_codec_h264_intel_t* self)
{
- if (self->encoder.pInst)
- {
- INTEL_BREAK("Already initialized");
- }
+ if (self->encoder.pInst) {
+ INTEL_BREAK("Already initialized");
+ }
- if (!(self->encoder.pInst = new IntelCodecEncoder(self->mfxSession)))
- {
- INTEL_CHECK_STATUS(MFX_ERR_MEMORY_ALLOC);
- }
- INTEL_CHECK_STATUS(self->encoder.pInst->Open(self));
+ if (!(self->encoder.pInst = new IntelCodecEncoder(self->mfxSession))) {
+ INTEL_CHECK_STATUS(MFX_ERR_MEMORY_ALLOC);
+ }
+ INTEL_CHECK_STATUS(self->encoder.pInst->Open(self));
- return 0;
+ return 0;
bail:
- if (self->encoder.pInst)
- {
- delete self->encoder.pInst, self->encoder.pInst = NULL;
- }
- return -1;
+ if (self->encoder.pInst) {
+ delete self->encoder.pInst, self->encoder.pInst = NULL;
+ }
+ return -1;
}
static int tdav_codec_h264_intel_close_encoder(tdav_codec_h264_intel_t* self)
{
- if (self)
- {
- if (self->encoder.pInst)
- {
- delete self->encoder.pInst;
- self->encoder.pInst = NULL;
- }
- self->encoder.frame_count = 0;
- }
- return 0;
+ if (self) {
+ if (self->encoder.pInst) {
+ delete self->encoder.pInst;
+ self->encoder.pInst = NULL;
+ }
+ self->encoder.frame_count = 0;
+ }
+ return 0;
}
int tdav_codec_h264_intel_open_decoder(tdav_codec_h264_intel_t* self)
{
- if (self->decoder.pInst)
- {
- INTEL_BREAK("Already initialized");
- }
+ if (self->decoder.pInst) {
+ INTEL_BREAK("Already initialized");
+ }
- if (!(self->decoder.pInst = new IntelCodecDecoder(self->mfxSession)))
- {
- INTEL_CHECK_STATUS(MFX_ERR_MEMORY_ALLOC);
- }
- INTEL_CHECK_STATUS(self->decoder.pInst->Open(self));
+ if (!(self->decoder.pInst = new IntelCodecDecoder(self->mfxSession))) {
+ INTEL_CHECK_STATUS(MFX_ERR_MEMORY_ALLOC);
+ }
+ INTEL_CHECK_STATUS(self->decoder.pInst->Open(self));
- return 0;
+ return 0;
bail:
- if (self->decoder.pInst)
- {
- delete self->decoder.pInst, self->decoder.pInst = NULL;
- }
- return -1;
+ if (self->decoder.pInst) {
+ delete self->decoder.pInst, self->decoder.pInst = NULL;
+ }
+ return -1;
}
static int tdav_codec_h264_intel_close_decoder(tdav_codec_h264_intel_t* self)
{
- if (self)
- {
- if (self->decoder.pInst)
- {
- delete self->decoder.pInst;
- self->decoder.pInst = NULL;
- }
- }
- return 0;
+ if (self) {
+ if (self->decoder.pInst) {
+ delete self->decoder.pInst;
+ self->decoder.pInst = NULL;
+ }
+ }
+ return 0;
}
static int tdav_codec_h264_intel_init(tdav_codec_h264_intel_t* self, profile_idc_t profile)
{
- int ret = -1;
- level_idc_t level;
- tdav_codec_h264_common_t* common = (tdav_codec_h264_common_t*)self;
+ int ret = -1;
+ level_idc_t level;
+ tdav_codec_h264_common_t* common = (tdav_codec_h264_common_t*)self;
#if INTEL_DX11_D3D
- mfxHDL deviceHandle = NULL;
+ mfxHDL deviceHandle = NULL;
#endif
- if (!self) {
- TSK_DEBUG_ERROR("Invalid parameter");
- goto bail;
- }
-
- if ((ret = tdav_codec_h264_common_init(common))) {
- TSK_DEBUG_ERROR("tdav_codec_h264_intel_common_init() faile with error code=%d", ret);
- goto bail;
- }
-
- if ((ret = tdav_codec_h264_common_level_from_size(TMEDIA_CODEC_VIDEO(self)->out.width, TMEDIA_CODEC_VIDEO(self)->out.height, &level))) {
- TSK_DEBUG_ERROR("Failed to find level for size=[%u, %u]", TMEDIA_CODEC_VIDEO(self)->out.width, TMEDIA_CODEC_VIDEO(self)->out.height);
- goto bail;
- }
-
- if (/*MFUtils::IsLowLatencyH264SupportsMaxSliceSize()*/0) { // TODO: MSDK doesn't support PM=0. Neg. PM=1 but try to do the best to produce SingleNalUnits
- common->pack_mode_local = H264_PACKETIZATION_MODE;
- }
- else {
- common->pack_mode_local = Non_Interleaved_Mode;
- }
- common->profile = profile;
- common->level = level;
+ if (!self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ goto bail;
+ }
+
+ if ((ret = tdav_codec_h264_common_init(common))) {
+ TSK_DEBUG_ERROR("tdav_codec_h264_intel_common_init() faile with error code=%d", ret);
+ goto bail;
+ }
+
+ if ((ret = tdav_codec_h264_common_level_from_size(TMEDIA_CODEC_VIDEO(self)->out.width, TMEDIA_CODEC_VIDEO(self)->out.height, &level))) {
+ TSK_DEBUG_ERROR("Failed to find level for size=[%u, %u]", TMEDIA_CODEC_VIDEO(self)->out.width, TMEDIA_CODEC_VIDEO(self)->out.height);
+ goto bail;
+ }
+
+ if (/*MFUtils::IsLowLatencyH264SupportsMaxSliceSize()*/0) { // TODO: MSDK doesn't support PM=0. Neg. PM=1 but try to do the best to produce SingleNalUnits
+ common->pack_mode_local = H264_PACKETIZATION_MODE;
+ }
+ else {
+ common->pack_mode_local = Non_Interleaved_Mode;
+ }
+ common->profile = profile;
+ common->level = level;
#if 0
- // A.2.1.1 Constrained Baseline profile
- // Conformance of a bitstream to the Constrained Baseline profile is indicated by profile_idc being equal to 66 with
- // constraint_set1_flag being equal to 1.
- common->profile_iop = 0xe0; // "constraint_set0_flag=1 and constraint_set1_flag=1" -> Constrained Baseline profile
+ // A.2.1.1 Constrained Baseline profile
+ // Conformance of a bitstream to the Constrained Baseline profile is indicated by profile_idc being equal to 66 with
+ // constraint_set1_flag being equal to 1.
+ common->profile_iop = 0xe0; // "constraint_set0_flag=1 and constraint_set1_flag=1" -> Constrained Baseline profile
#endif
- TMEDIA_CODEC_VIDEO(self)->in.max_mbps = TMEDIA_CODEC_VIDEO(self)->out.max_mbps = H264_MAX_MBPS * 1000;
- TMEDIA_CODEC_VIDEO(self)->in.max_br = TMEDIA_CODEC_VIDEO(self)->out.max_br = H264_MAX_BR * 1000;
+ TMEDIA_CODEC_VIDEO(self)->in.max_mbps = TMEDIA_CODEC_VIDEO(self)->out.max_mbps = H264_MAX_MBPS * 1000;
+ TMEDIA_CODEC_VIDEO(self)->in.max_br = TMEDIA_CODEC_VIDEO(self)->out.max_br = H264_MAX_BR * 1000;
- TMEDIA_CODEC_VIDEO(self)->in.chroma = tmedia_chroma_yuv420p; // decoded
- TMEDIA_CODEC_VIDEO(self)->out.chroma = tmedia_chroma_yuv420p; // encoded
+ TMEDIA_CODEC_VIDEO(self)->in.chroma = tmedia_chroma_yuv420p; // decoded
+ TMEDIA_CODEC_VIDEO(self)->out.chroma = tmedia_chroma_yuv420p; // encoded
- if (!self->mfxSession && !(self->mfxSession = new MFXVideoSession()))
- {
- INTEL_CHECK_STATUS(MFX_ERR_MEMORY_ALLOC);
- }
- INTEL_CHECK_STATUS(self->mfxSession->Init(__IntelDefaultImpl, &__IntelDefaultVer));
+ if (!self->mfxSession && !(self->mfxSession = new MFXVideoSession())) {
+ INTEL_CHECK_STATUS(MFX_ERR_MEMORY_ALLOC);
+ }
+ INTEL_CHECK_STATUS(self->mfxSession->Init(__IntelDefaultImpl, &__IntelDefaultVer));
#if INTEL_DX11_D3D
- // Create DirectX device context
- INTEL_CHECK_STATUS(D3D11_CreateHWDevice(self, *self->mfxSession, &deviceHandle, NULL));
-
- // Provide device manager to Media SDK
- INTEL_CHECK_STATUS(self->mfxSession->SetHandle(MFX_HANDLE_D3D11_DEVICE, deviceHandle));
-
- self->D3D11Allocator.Alloc = D3D11_SimpleAlloc;
- self->D3D11Allocator.Free = D3D11_SimpleFree;
- self->D3D11Allocator.Lock = D3D11_SimpleLock;
- self->D3D11Allocator.Unlock = D3D11_SimpleUnlock;
- self->D3D11Allocator.GetHDL = D3D11_SimpleGethdl;
- self->D3D11Allocator.pthis = self;
-
- // Since we are using video memory we must provide Media SDK with an external allocator
- INTEL_CHECK_STATUS(self->mfxSession->SetFrameAllocator(&self->D3D11Allocator));
+ // Create DirectX device context
+ INTEL_CHECK_STATUS(D3D11_CreateHWDevice(self, *self->mfxSession, &deviceHandle, NULL));
+
+ // Provide device manager to Media SDK
+ INTEL_CHECK_STATUS(self->mfxSession->SetHandle(MFX_HANDLE_D3D11_DEVICE, deviceHandle));
+
+ self->D3D11Allocator.Alloc = D3D11_SimpleAlloc;
+ self->D3D11Allocator.Free = D3D11_SimpleFree;
+ self->D3D11Allocator.Lock = D3D11_SimpleLock;
+ self->D3D11Allocator.Unlock = D3D11_SimpleUnlock;
+ self->D3D11Allocator.GetHDL = D3D11_SimpleGethdl;
+ self->D3D11Allocator.pthis = self;
+
+ // Since we are using video memory we must provide Media SDK with an external allocator
+ INTEL_CHECK_STATUS(self->mfxSession->SetFrameAllocator(&self->D3D11Allocator));
#endif /* INTEL_DX11_D3D */
- ret = 0;
+ ret = 0;
bail:
- return ret;
+ return ret;
}
static int tdav_codec_h264_intel_deinit(tdav_codec_h264_intel_t* self)
{
- if (!self)
- {
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
+ if (!self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
- tdav_codec_h264_intel_close((tmedia_codec_t*)self);
+ tdav_codec_h264_intel_close((tmedia_codec_t*)self);
- if (self->mfxSession)
- {
- delete self->mfxSession, self->mfxSession = NULL;
- }
+ if (self->mfxSession) {
+ delete self->mfxSession, self->mfxSession = NULL;
+ }
#if INTEL_DX11_D3D
- D3D11_CleanupHWDevice(self);
+ D3D11_CleanupHWDevice(self);
#endif /* INTEL_DX11_D3D */
- return 0;
+ return 0;
}
@@ -1780,40 +1620,36 @@ static int tdav_codec_h264_intel_deinit(tdav_codec_h264_intel_t* self)
static IDXGIAdapter* D3D11_GetIntelDeviceAdapterHandle(mfxHDL _pthis, mfxSession session)
{
- mfxU32 adapterNum = 0;
- mfxIMPL impl;
- tdav_codec_h264_intel_t* pthis = (tdav_codec_h264_intel_t*)_pthis;
-
- MFXQueryIMPL(session, &impl);
-
- mfxIMPL baseImpl = MFX_IMPL_BASETYPE(impl); // Extract Media SDK base implementation type
-
- // get corresponding adapter number
- for (mfxU8 i = 0; i < sizeof(implTypes) / sizeof(implTypes[0]); i++)
- {
- if (implTypes[i].impl == baseImpl)
- {
- adapterNum = implTypes[i].adapterID;
- break;
- }
- }
-
- HRESULT hres = CreateDXGIFactory(__uuidof(IDXGIFactory2), (void**)(&pthis->pDXGIFactory));
- if (FAILED(hres))
- {
- INTEL_DEBUG_ERROR("CreateDXGIFactory failed: %ld", hres);
- return NULL;
- }
-
- IDXGIAdapter* adapter = NULL;
- hres = pthis->pDXGIFactory->EnumAdapters(adapterNum, &adapter);
- if (FAILED(hres))
- {
- INTEL_DEBUG_ERROR("EnumAdapters failed: %ld", hres);
- return NULL;
- }
-
- return adapter;
+ mfxU32 adapterNum = 0;
+ mfxIMPL impl;
+ tdav_codec_h264_intel_t* pthis = (tdav_codec_h264_intel_t*)_pthis;
+
+ MFXQueryIMPL(session, &impl);
+
+ mfxIMPL baseImpl = MFX_IMPL_BASETYPE(impl); // Extract Media SDK base implementation type
+
+ // get corresponding adapter number
+ for (mfxU8 i = 0; i < sizeof(implTypes) / sizeof(implTypes[0]); i++) {
+ if (implTypes[i].impl == baseImpl) {
+ adapterNum = implTypes[i].adapterID;
+ break;
+ }
+ }
+
+ HRESULT hres = CreateDXGIFactory(__uuidof(IDXGIFactory2), (void**)(&pthis->pDXGIFactory));
+ if (FAILED(hres)) {
+ INTEL_DEBUG_ERROR("CreateDXGIFactory failed: %ld", hres);
+ return NULL;
+ }
+
+ IDXGIAdapter* adapter = NULL;
+ hres = pthis->pDXGIFactory->EnumAdapters(adapterNum, &adapter);
+ if (FAILED(hres)) {
+ INTEL_DEBUG_ERROR("EnumAdapters failed: %ld", hres);
+ return NULL;
+ }
+
+ return adapter;
}
// Create DirectX 11 device context
@@ -1826,394 +1662,361 @@ static IDXGIAdapter* D3D11_GetIntelDeviceAdapterHandle(mfxHDL _pthis, mfxSession
// - For switchable graphics solutions (mobile) make sure that Intel device is the active device
static mfxStatus D3D11_CreateHWDevice(mfxHDL _pthis, mfxSession session, mfxHDL* deviceHandle, HWND hWnd)
{
- hWnd; // Window handle not required by DX11 since we do not showcase rendering.
-
- HRESULT hres = S_OK;
- tdav_codec_h264_intel_t* pthis = (tdav_codec_h264_intel_t*)_pthis;
-
- static D3D_FEATURE_LEVEL FeatureLevels[] = {
- D3D_FEATURE_LEVEL_11_1,
- D3D_FEATURE_LEVEL_11_0,
- D3D_FEATURE_LEVEL_10_1,
- D3D_FEATURE_LEVEL_10_0
- };
- D3D_FEATURE_LEVEL pFeatureLevelsOut;
-
- pthis->hAdapter = D3D11_GetIntelDeviceAdapterHandle(_pthis, session);
- if (NULL == pthis->hAdapter)
- {
- INTEL_DEBUG_ERROR("D3D11_GetIntelDeviceAdapterHandle failed");
- return MFX_ERR_DEVICE_FAILED;
- }
-
- hres = D3D11CreateDevice(pthis->hAdapter,
- D3D_DRIVER_TYPE_UNKNOWN,
- NULL,
- 0,
- FeatureLevels,
- (sizeof(FeatureLevels) / sizeof(FeatureLevels[0])),
- D3D11_SDK_VERSION,
- &pthis->pD3D11Device,
- &pFeatureLevelsOut,
- &pthis->pD3D11Ctx);
- if (FAILED(hres))
- {
- INTEL_DEBUG_ERROR("D3D11CreateDevice failed: %ld", hres);
- return MFX_ERR_DEVICE_FAILED;
- }
-
- // turn on multithreading for the DX11 cntext
- CComQIPtr<ID3D10Multithread> p_mt(pthis->pD3D11Ctx);
- if (p_mt)
- {
- p_mt->SetMultithreadProtected(true);
- }
- else
- {
- INTEL_DEBUG_ERROR("Failed to create ID3D10Multithread object");
- return MFX_ERR_DEVICE_FAILED;
- }
-
- *deviceHandle = (mfxHDL)pthis->pD3D11Device;
- return MFX_ERR_NONE;
+ hWnd; // Window handle not required by DX11 since we do not showcase rendering.
+
+ HRESULT hres = S_OK;
+ tdav_codec_h264_intel_t* pthis = (tdav_codec_h264_intel_t*)_pthis;
+
+ static D3D_FEATURE_LEVEL FeatureLevels[] = {
+ D3D_FEATURE_LEVEL_11_1,
+ D3D_FEATURE_LEVEL_11_0,
+ D3D_FEATURE_LEVEL_10_1,
+ D3D_FEATURE_LEVEL_10_0
+ };
+ D3D_FEATURE_LEVEL pFeatureLevelsOut;
+
+ pthis->hAdapter = D3D11_GetIntelDeviceAdapterHandle(_pthis, session);
+ if (NULL == pthis->hAdapter) {
+ INTEL_DEBUG_ERROR("D3D11_GetIntelDeviceAdapterHandle failed");
+ return MFX_ERR_DEVICE_FAILED;
+ }
+
+ hres = D3D11CreateDevice(pthis->hAdapter,
+ D3D_DRIVER_TYPE_UNKNOWN,
+ NULL,
+ 0,
+ FeatureLevels,
+ (sizeof(FeatureLevels) / sizeof(FeatureLevels[0])),
+ D3D11_SDK_VERSION,
+ &pthis->pD3D11Device,
+ &pFeatureLevelsOut,
+ &pthis->pD3D11Ctx);
+ if (FAILED(hres)) {
+ INTEL_DEBUG_ERROR("D3D11CreateDevice failed: %ld", hres);
+ return MFX_ERR_DEVICE_FAILED;
+ }
+
+ // turn on multithreading for the DX11 cntext
+ CComQIPtr<ID3D10Multithread> p_mt(pthis->pD3D11Ctx);
+ if (p_mt) {
+ p_mt->SetMultithreadProtected(true);
+ }
+ else {
+ INTEL_DEBUG_ERROR("Failed to create ID3D10Multithread object");
+ return MFX_ERR_DEVICE_FAILED;
+ }
+
+ *deviceHandle = (mfxHDL)pthis->pD3D11Device;
+ return MFX_ERR_NONE;
}
static void D3D11_CleanupHWDevice(mfxHDL _pthis)
{
- tdav_codec_h264_intel_t* pthis = (tdav_codec_h264_intel_t*)_pthis;
- pthis->pD3D11Device = NULL;
- pthis->pDXGIFactory = NULL;
- pthis->pD3D11Ctx = NULL;
- pthis->hAdapter = NULL;
- pthis->pAdapter = NULL;
+ tdav_codec_h264_intel_t* pthis = (tdav_codec_h264_intel_t*)_pthis;
+ pthis->pD3D11Device = NULL;
+ pthis->pDXGIFactory = NULL;
+ pthis->pD3D11Ctx = NULL;
+ pthis->hAdapter = NULL;
+ pthis->pAdapter = NULL;
}
static void D3D11_SetHWDeviceContext(mfxHDL _pthis, CComPtr<ID3D11DeviceContext> devCtx)
{
- tdav_codec_h264_intel_t* pthis = (tdav_codec_h264_intel_t*)_pthis;
- pthis->pD3D11Ctx = devCtx;
- devCtx->GetDevice(&pthis->pD3D11Device);
+ tdav_codec_h264_intel_t* pthis = (tdav_codec_h264_intel_t*)_pthis;
+ pthis->pD3D11Ctx = devCtx;
+ devCtx->GetDevice(&pthis->pD3D11Device);
}
// Intel Media SDK memory allocator entrypoints....
// - A slightly different allocation procedure is used for encode, decode and VPP
static mfxStatus _D3D11_SimpleAlloc(mfxHDL _pthis, mfxFrameAllocRequest *request, mfxFrameAllocResponse *response)
{
- HRESULT hRes;
- tdav_codec_h264_intel_t* pthis = (tdav_codec_h264_intel_t*)_pthis;
-
- // Determine surface format (current simple implementation only supports NV12 and RGB4(32))
- DXGI_FORMAT format;
- if (MFX_FOURCC_NV12 == request->Info.FourCC)
- {
- format = DXGI_FORMAT_NV12;
- }
- else if (MFX_FOURCC_RGB4 == request->Info.FourCC)
- {
- format = DXGI_FORMAT_B8G8R8A8_UNORM;
- }
- else
- {
- format = DXGI_FORMAT_P8;
- }
-
- // Allocate custom container to keep texture and stage buffers for each surface
- // Container also stores the intended read and/or write operation.
- CustomMemId** mids = new CustomMemId *[request->NumFrameSuggested];
- if (!mids) return MFX_ERR_MEMORY_ALLOC;
- for (int i = 0; i < request->NumFrameSuggested; i++)
- {
- mids[i] = new CustomMemId;
- memset(mids[i], 0, sizeof(CustomMemId));
- mids[i]->rw = request->Type & 0xF000; // Set intended read/write operation
- }
-
- request->Type = request->Type & 0x0FFF;
-
- // because P8 data (bitstream) for h264 encoder should be allocated by CreateBuffer()
- // but P8 data (MBData) for MPEG2 encoder should be allocated by CreateTexture2D()
- if (request->Info.FourCC == MFX_FOURCC_P8)
- {
- D3D11_BUFFER_DESC desc = { 0 };
-
- desc.ByteWidth = request->Info.Width * request->Info.Height;
- desc.Usage = D3D11_USAGE_STAGING;
- desc.BindFlags = 0;
- desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
- desc.MiscFlags = 0;
- desc.StructureByteStride = 0;
-
- ID3D11Buffer * buffer = 0;
- hRes = pthis->pD3D11Device->CreateBuffer(&desc, 0, &buffer);
- if (FAILED(hRes))
- {
- INTEL_DEBUG_ERROR("CreateBuffer failed:%ld", hRes);
- return MFX_ERR_MEMORY_ALLOC;
- }
-
- mids[0]->memId = reinterpret_cast<ID3D11Texture2D *>(buffer);
- }
- else
- {
- D3D11_TEXTURE2D_DESC desc = { 0 };
-
- desc.Width = request->Info.Width;
- desc.Height = request->Info.Height;
- desc.MipLevels = 1;
- desc.ArraySize = 1; // number of subresources is 1 in this case
- desc.Format = format;
- desc.SampleDesc.Count = 1;
- desc.Usage = D3D11_USAGE_DEFAULT;
- desc.BindFlags = D3D11_BIND_DECODER;
- desc.MiscFlags = 0;
-
- if ((MFX_MEMTYPE_FROM_VPPIN & request->Type) &&
- (DXGI_FORMAT_B8G8R8A8_UNORM == desc.Format))
- {
- desc.BindFlags = D3D11_BIND_RENDER_TARGET;
- if (desc.ArraySize > 2)
- return MFX_ERR_MEMORY_ALLOC;
- }
-
- if ((MFX_MEMTYPE_FROM_VPPOUT & request->Type) ||
- (MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET & request->Type))
- {
- desc.BindFlags = D3D11_BIND_RENDER_TARGET;
- if (desc.ArraySize > 2)
- {
- return MFX_ERR_MEMORY_ALLOC;
- }
- }
-
- if (DXGI_FORMAT_P8 == desc.Format)
- desc.BindFlags = 0;
-
- ID3D11Texture2D* pTexture2D;
-
- // Create surface textures
- for (size_t i = 0; i < request->NumFrameSuggested / desc.ArraySize; i++)
- {
- hRes = pthis->pD3D11Device->CreateTexture2D(&desc, NULL, &pTexture2D);
-
- if (FAILED(hRes))
- {
- INTEL_DEBUG_ERROR("CreateTexture2D failed:%ld", hRes);
- return MFX_ERR_MEMORY_ALLOC;
- }
-
- mids[i]->memId = pTexture2D;
- }
-
- desc.ArraySize = 1;
- desc.Usage = D3D11_USAGE_STAGING;
- desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ /*| D3D11_CPU_ACCESS_WRITE*/;
- desc.BindFlags = 0;
- desc.MiscFlags = 0;
-
- // Create surface staging textures
- for (size_t i = 0; i < request->NumFrameSuggested; i++)
- {
- hRes = pthis->pD3D11Device->CreateTexture2D(&desc, NULL, &pTexture2D);
-
- if (FAILED(hRes))
- {
- INTEL_DEBUG_ERROR("CreateTexture2D failed:%ld", hRes);
- return MFX_ERR_MEMORY_ALLOC;
- }
-
- mids[i]->memIdStage = pTexture2D;
- }
- }
-
- response->mids = (mfxMemId*)mids;
- response->NumFrameActual = request->NumFrameSuggested;
-
- return MFX_ERR_NONE;
+ HRESULT hRes;
+ tdav_codec_h264_intel_t* pthis = (tdav_codec_h264_intel_t*)_pthis;
+
+ // Determine surface format (current simple implementation only supports NV12 and RGB4(32))
+ DXGI_FORMAT format;
+ if (MFX_FOURCC_NV12 == request->Info.FourCC) {
+ format = DXGI_FORMAT_NV12;
+ }
+ else if (MFX_FOURCC_RGB4 == request->Info.FourCC) {
+ format = DXGI_FORMAT_B8G8R8A8_UNORM;
+ }
+ else {
+ format = DXGI_FORMAT_P8;
+ }
+
+ // Allocate custom container to keep texture and stage buffers for each surface
+ // Container also stores the intended read and/or write operation.
+ CustomMemId** mids = new CustomMemId *[request->NumFrameSuggested];
+ if (!mids) {
+ return MFX_ERR_MEMORY_ALLOC;
+ }
+ for (int i = 0; i < request->NumFrameSuggested; i++) {
+ mids[i] = new CustomMemId;
+ memset(mids[i], 0, sizeof(CustomMemId));
+ mids[i]->rw = request->Type & 0xF000; // Set intended read/write operation
+ }
+
+ request->Type = request->Type & 0x0FFF;
+
+ // because P8 data (bitstream) for h264 encoder should be allocated by CreateBuffer()
+ // but P8 data (MBData) for MPEG2 encoder should be allocated by CreateTexture2D()
+ if (request->Info.FourCC == MFX_FOURCC_P8) {
+ D3D11_BUFFER_DESC desc = { 0 };
+
+ desc.ByteWidth = request->Info.Width * request->Info.Height;
+ desc.Usage = D3D11_USAGE_STAGING;
+ desc.BindFlags = 0;
+ desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
+ desc.MiscFlags = 0;
+ desc.StructureByteStride = 0;
+
+ ID3D11Buffer * buffer = 0;
+ hRes = pthis->pD3D11Device->CreateBuffer(&desc, 0, &buffer);
+ if (FAILED(hRes)) {
+ INTEL_DEBUG_ERROR("CreateBuffer failed:%ld", hRes);
+ return MFX_ERR_MEMORY_ALLOC;
+ }
+
+ mids[0]->memId = reinterpret_cast<ID3D11Texture2D *>(buffer);
+ }
+ else {
+ D3D11_TEXTURE2D_DESC desc = { 0 };
+
+ desc.Width = request->Info.Width;
+ desc.Height = request->Info.Height;
+ desc.MipLevels = 1;
+ desc.ArraySize = 1; // number of subresources is 1 in this case
+ desc.Format = format;
+ desc.SampleDesc.Count = 1;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = D3D11_BIND_DECODER;
+ desc.MiscFlags = 0;
+
+ if ((MFX_MEMTYPE_FROM_VPPIN & request->Type) &&
+ (DXGI_FORMAT_B8G8R8A8_UNORM == desc.Format)) {
+ desc.BindFlags = D3D11_BIND_RENDER_TARGET;
+ if (desc.ArraySize > 2) {
+ return MFX_ERR_MEMORY_ALLOC;
+ }
+ }
+
+ if ((MFX_MEMTYPE_FROM_VPPOUT & request->Type) ||
+ (MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET & request->Type)) {
+ desc.BindFlags = D3D11_BIND_RENDER_TARGET;
+ if (desc.ArraySize > 2) {
+ return MFX_ERR_MEMORY_ALLOC;
+ }
+ }
+
+ if (DXGI_FORMAT_P8 == desc.Format) {
+ desc.BindFlags = 0;
+ }
+
+ ID3D11Texture2D* pTexture2D;
+
+ // Create surface textures
+ for (size_t i = 0; i < request->NumFrameSuggested / desc.ArraySize; i++) {
+ hRes = pthis->pD3D11Device->CreateTexture2D(&desc, NULL, &pTexture2D);
+
+ if (FAILED(hRes)) {
+ INTEL_DEBUG_ERROR("CreateTexture2D failed:%ld", hRes);
+ return MFX_ERR_MEMORY_ALLOC;
+ }
+
+ mids[i]->memId = pTexture2D;
+ }
+
+ desc.ArraySize = 1;
+ desc.Usage = D3D11_USAGE_STAGING;
+ desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ /*| D3D11_CPU_ACCESS_WRITE*/;
+ desc.BindFlags = 0;
+ desc.MiscFlags = 0;
+
+ // Create surface staging textures
+ for (size_t i = 0; i < request->NumFrameSuggested; i++) {
+ hRes = pthis->pD3D11Device->CreateTexture2D(&desc, NULL, &pTexture2D);
+
+ if (FAILED(hRes)) {
+ INTEL_DEBUG_ERROR("CreateTexture2D failed:%ld", hRes);
+ return MFX_ERR_MEMORY_ALLOC;
+ }
+
+ mids[i]->memIdStage = pTexture2D;
+ }
+ }
+
+ response->mids = (mfxMemId*)mids;
+ response->NumFrameActual = request->NumFrameSuggested;
+
+ return MFX_ERR_NONE;
}
static mfxStatus D3D11_SimpleAlloc(mfxHDL _pthis, mfxFrameAllocRequest *request, mfxFrameAllocResponse *response)
{
- tdav_codec_h264_intel_t* pthis = (tdav_codec_h264_intel_t*)_pthis;
- mfxStatus sts = MFX_ERR_NONE;
- int idx = (MFX_MEMTYPE_FROM_DECODE & request->Type) ? 1 : 0;
-
- if (request->NumFrameSuggested <= pthis->D3D11SavedAllocResponses[idx].NumFrameActual &&
- MFX_MEMTYPE_EXTERNAL_FRAME & request->Type &&
- MFX_MEMTYPE_FROM_DECODE & request->Type &&
- pthis->D3D11SavedAllocResponses[idx].NumFrameActual != 0)
- {
- // Memory for this request was already allocated during manual allocation stage. Return saved response
- // When decode acceleration device (DXVA) is created it requires a list of d3d surfaces to be passed.
- // Therefore Media SDK will ask for the surface info/mids again at Init() stage, thus requiring us to return the saved response
- // (No such restriction applies to Encode or VPP)
-
- *response = pthis->D3D11SavedAllocResponses[idx];
- }
- else
- {
- sts = _D3D11_SimpleAlloc(_pthis, request, response);
- pthis->D3D11SavedAllocResponses[idx] = *response;
- }
-
- return sts;
+ tdav_codec_h264_intel_t* pthis = (tdav_codec_h264_intel_t*)_pthis;
+ mfxStatus sts = MFX_ERR_NONE;
+ int idx = (MFX_MEMTYPE_FROM_DECODE & request->Type) ? 1 : 0;
+
+ if (request->NumFrameSuggested <= pthis->D3D11SavedAllocResponses[idx].NumFrameActual &&
+ MFX_MEMTYPE_EXTERNAL_FRAME & request->Type &&
+ MFX_MEMTYPE_FROM_DECODE & request->Type &&
+ pthis->D3D11SavedAllocResponses[idx].NumFrameActual != 0) {
+ // Memory for this request was already allocated during manual allocation stage. Return saved response
+ // When decode acceleration device (DXVA) is created it requires a list of d3d surfaces to be passed.
+ // Therefore Media SDK will ask for the surface info/mids again at Init() stage, thus requiring us to return the saved response
+ // (No such restriction applies to Encode or VPP)
+
+ *response = pthis->D3D11SavedAllocResponses[idx];
+ }
+ else {
+ sts = _D3D11_SimpleAlloc(_pthis, request, response);
+ pthis->D3D11SavedAllocResponses[idx] = *response;
+ }
+
+ return sts;
}
static mfxStatus D3D11_SimpleLock(mfxHDL _pthis, mfxMemId mid, mfxFrameData *ptr)
{
- HRESULT hRes = S_OK;
- tdav_codec_h264_intel_t* pthis = (tdav_codec_h264_intel_t*)_pthis;
-
- D3D11_TEXTURE2D_DESC desc = { 0 };
- D3D11_MAPPED_SUBRESOURCE lockedRect = { 0 };
-
- CustomMemId* memId = (CustomMemId*)mid;
- ID3D11Texture2D* pSurface = (ID3D11Texture2D *)memId->memId;
- ID3D11Texture2D* pStage = (ID3D11Texture2D *)memId->memIdStage;
-
- D3D11_MAP mapType = D3D11_MAP_READ;
- UINT mapFlags = D3D11_MAP_FLAG_DO_NOT_WAIT;
-
- if (NULL == pStage)
- {
- hRes = pthis->pD3D11Ctx->Map(pSurface, 0, mapType, mapFlags, &lockedRect);
- desc.Format = DXGI_FORMAT_P8;
- }
- else
- {
- pSurface->GetDesc(&desc);
-
- // copy data only in case of user wants o read from stored surface
- if (memId->rw & D3D11_WILL_READ)
- {
- pthis->pD3D11Ctx->CopySubresourceRegion(pStage, 0, 0, 0, 0, pSurface, 0, NULL);
- }
-
- do
- {
- hRes = pthis->pD3D11Ctx->Map(pStage, 0, mapType, mapFlags, &lockedRect);
- if (S_OK != hRes && DXGI_ERROR_WAS_STILL_DRAWING != hRes)
- {
- return MFX_ERR_LOCK_MEMORY;
- }
- } while (DXGI_ERROR_WAS_STILL_DRAWING == hRes);
- }
-
- if (FAILED(hRes))
- {
- return MFX_ERR_LOCK_MEMORY;
- }
-
- switch (desc.Format)
- {
- case DXGI_FORMAT_NV12:
- ptr->Pitch = (mfxU16)lockedRect.RowPitch;
- ptr->Y = (mfxU8 *)lockedRect.pData;
- ptr->U = (mfxU8 *)lockedRect.pData + desc.Height * lockedRect.RowPitch;
- ptr->V = ptr->U + 1;
- break;
- case DXGI_FORMAT_B8G8R8A8_UNORM:
- ptr->Pitch = (mfxU16)lockedRect.RowPitch;
- ptr->B = (mfxU8 *)lockedRect.pData;
- ptr->G = ptr->B + 1;
- ptr->R = ptr->B + 2;
- ptr->A = ptr->B + 3;
- break;
- case DXGI_FORMAT_P8:
- ptr->Pitch = (mfxU16)lockedRect.RowPitch;
- ptr->Y = (mfxU8 *)lockedRect.pData;
- ptr->U = 0;
- ptr->V = 0;
- break;
- default:
- return MFX_ERR_LOCK_MEMORY;
- }
-
- return MFX_ERR_NONE;
+ HRESULT hRes = S_OK;
+ tdav_codec_h264_intel_t* pthis = (tdav_codec_h264_intel_t*)_pthis;
+
+ D3D11_TEXTURE2D_DESC desc = { 0 };
+ D3D11_MAPPED_SUBRESOURCE lockedRect = { 0 };
+
+ CustomMemId* memId = (CustomMemId*)mid;
+ ID3D11Texture2D* pSurface = (ID3D11Texture2D *)memId->memId;
+ ID3D11Texture2D* pStage = (ID3D11Texture2D *)memId->memIdStage;
+
+ D3D11_MAP mapType = D3D11_MAP_READ;
+ UINT mapFlags = D3D11_MAP_FLAG_DO_NOT_WAIT;
+
+ if (NULL == pStage) {
+ hRes = pthis->pD3D11Ctx->Map(pSurface, 0, mapType, mapFlags, &lockedRect);
+ desc.Format = DXGI_FORMAT_P8;
+ }
+ else {
+ pSurface->GetDesc(&desc);
+
+ // copy data only in case of user wants o read from stored surface
+ if (memId->rw & D3D11_WILL_READ) {
+ pthis->pD3D11Ctx->CopySubresourceRegion(pStage, 0, 0, 0, 0, pSurface, 0, NULL);
+ }
+
+ do {
+ hRes = pthis->pD3D11Ctx->Map(pStage, 0, mapType, mapFlags, &lockedRect);
+ if (S_OK != hRes && DXGI_ERROR_WAS_STILL_DRAWING != hRes) {
+ return MFX_ERR_LOCK_MEMORY;
+ }
+ }
+ while (DXGI_ERROR_WAS_STILL_DRAWING == hRes);
+ }
+
+ if (FAILED(hRes)) {
+ return MFX_ERR_LOCK_MEMORY;
+ }
+
+ switch (desc.Format) {
+ case DXGI_FORMAT_NV12:
+ ptr->Pitch = (mfxU16)lockedRect.RowPitch;
+ ptr->Y = (mfxU8 *)lockedRect.pData;
+ ptr->U = (mfxU8 *)lockedRect.pData + desc.Height * lockedRect.RowPitch;
+ ptr->V = ptr->U + 1;
+ break;
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ ptr->Pitch = (mfxU16)lockedRect.RowPitch;
+ ptr->B = (mfxU8 *)lockedRect.pData;
+ ptr->G = ptr->B + 1;
+ ptr->R = ptr->B + 2;
+ ptr->A = ptr->B + 3;
+ break;
+ case DXGI_FORMAT_P8:
+ ptr->Pitch = (mfxU16)lockedRect.RowPitch;
+ ptr->Y = (mfxU8 *)lockedRect.pData;
+ ptr->U = 0;
+ ptr->V = 0;
+ break;
+ default:
+ return MFX_ERR_LOCK_MEMORY;
+ }
+
+ return MFX_ERR_NONE;
}
static mfxStatus D3D11_SimpleUnlock(mfxHDL _pthis, mfxMemId mid, mfxFrameData *ptr)
{
- tdav_codec_h264_intel_t* pthis = (tdav_codec_h264_intel_t*)_pthis;
-
- CustomMemId* memId = (CustomMemId*)mid;
- ID3D11Texture2D* pSurface = (ID3D11Texture2D *)memId->memId;
- ID3D11Texture2D* pStage = (ID3D11Texture2D *)memId->memIdStage;
-
- if (NULL == pStage)
- {
- pthis->pD3D11Ctx->Unmap(pSurface, 0);
- }
- else
- {
- pthis->pD3D11Ctx->Unmap(pStage, 0);
- // copy data only in case of user wants to write to stored surface
- if (memId->rw & D3D11_WILL_WRITE)
- {
- pthis->pD3D11Ctx->CopySubresourceRegion(pSurface, 0, 0, 0, 0, pStage, 0, NULL);
- }
- }
-
- if (ptr)
- {
- ptr->Pitch = 0;
- ptr->U = ptr->V = ptr->Y = 0;
- ptr->A = ptr->R = ptr->G = ptr->B = 0;
- }
-
- return MFX_ERR_NONE;
+ tdav_codec_h264_intel_t* pthis = (tdav_codec_h264_intel_t*)_pthis;
+
+ CustomMemId* memId = (CustomMemId*)mid;
+ ID3D11Texture2D* pSurface = (ID3D11Texture2D *)memId->memId;
+ ID3D11Texture2D* pStage = (ID3D11Texture2D *)memId->memIdStage;
+
+ if (NULL == pStage) {
+ pthis->pD3D11Ctx->Unmap(pSurface, 0);
+ }
+ else {
+ pthis->pD3D11Ctx->Unmap(pStage, 0);
+ // copy data only in case of user wants to write to stored surface
+ if (memId->rw & D3D11_WILL_WRITE) {
+ pthis->pD3D11Ctx->CopySubresourceRegion(pSurface, 0, 0, 0, 0, pStage, 0, NULL);
+ }
+ }
+
+ if (ptr) {
+ ptr->Pitch = 0;
+ ptr->U = ptr->V = ptr->Y = 0;
+ ptr->A = ptr->R = ptr->G = ptr->B = 0;
+ }
+
+ return MFX_ERR_NONE;
}
static mfxStatus D3D11_SimpleGethdl(mfxHDL _pthis, mfxMemId mid, mfxHDL *handle)
{
- _pthis;
- if (NULL == handle)
- {
- return MFX_ERR_INVALID_HANDLE;
- }
+ _pthis;
+ if (NULL == handle) {
+ return MFX_ERR_INVALID_HANDLE;
+ }
- mfxHDLPair* pPair = (mfxHDLPair*)handle;
- CustomMemId* memId = (CustomMemId*)mid;
+ mfxHDLPair* pPair = (mfxHDLPair*)handle;
+ CustomMemId* memId = (CustomMemId*)mid;
- pPair->first = memId->memId; // surface texture
- pPair->second = 0;
+ pPair->first = memId->memId; // surface texture
+ pPair->second = 0;
- return MFX_ERR_NONE;
+ return MFX_ERR_NONE;
}
static mfxStatus D3D11_SimpleFree(mfxHDL _pthis, mfxFrameAllocResponse *response)
{
- _pthis;
- if (NULL == response)
- {
- return MFX_ERR_NULL_PTR;
- }
-
- if (response->mids)
- {
- for (mfxU32 i = 0; i < response->NumFrameActual; i++)
- {
- if (response->mids[i])
- {
- CustomMemId* mid = (CustomMemId*)response->mids[i];
- ID3D11Texture2D* pSurface = (ID3D11Texture2D *)mid->memId;
- ID3D11Texture2D* pStage = (ID3D11Texture2D *)mid->memIdStage;
- if (pSurface)
- {
- pSurface->Release();
- }
- if (pStage)
- {
- pStage->Release();
- }
- delete mid;
- }
- }
- }
-
- delete[] response->mids;
- response->mids = 0;
-
- return MFX_ERR_NONE;
+ _pthis;
+ if (NULL == response) {
+ return MFX_ERR_NULL_PTR;
+ }
+
+ if (response->mids) {
+ for (mfxU32 i = 0; i < response->NumFrameActual; i++) {
+ if (response->mids[i]) {
+ CustomMemId* mid = (CustomMemId*)response->mids[i];
+ ID3D11Texture2D* pSurface = (ID3D11Texture2D *)mid->memId;
+ ID3D11Texture2D* pStage = (ID3D11Texture2D *)mid->memIdStage;
+ if (pSurface) {
+ pSurface->Release();
+ }
+ if (pStage) {
+ pStage->Release();
+ }
+ delete mid;
+ }
+ }
+ }
+
+ delete[] response->mids;
+ response->mids = 0;
+
+ return MFX_ERR_NONE;
}
#endif /* INTEL_DX11_D3D */
diff --git a/tinyDAV/src/codecs/h264/tdav_codec_h264_rtp.c b/tinyDAV/src/codecs/h264/tdav_codec_h264_rtp.c
index 5742f43..749433e 100755
--- a/tinyDAV/src/codecs/h264/tdav_codec_h264_rtp.c
+++ b/tinyDAV/src/codecs/h264/tdav_codec_h264_rtp.c
@@ -2,19 +2,19 @@
* Copyright (C) 2010-2011 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.
*
@@ -57,158 +57,158 @@ static int tdav_codec_h264_get_nalunit_pay(const uint8_t* in_data, tsk_size_t in
// 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;
- case level_idc_3_1:
- *l_idc = level_idc_3_1;
- break;
- case level_idc_3_2:
- *l_idc = level_idc_3_2;
- break;
- case level_idc_4_0:
- *l_idc = level_idc_4_0;
- break;
- case level_idc_4_1:
- *l_idc = level_idc_4_1;
- break;
- case level_idc_4_2:
- *l_idc = level_idc_4_2;
- break;
- case level_idc_5_0:
- *l_idc = level_idc_5_0;
- break;
- case level_idc_5_1:
- *l_idc = level_idc_5_1;
- break;
- case level_idc_5_2:
- *l_idc = level_idc_5_2;
- break;
- default:
- *l_idc = level_idc_none;
- break;
- }
- }
-
- return 0;
+ 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;
+ case level_idc_3_1:
+ *l_idc = level_idc_3_1;
+ break;
+ case level_idc_3_2:
+ *l_idc = level_idc_3_2;
+ break;
+ case level_idc_4_0:
+ *l_idc = level_idc_4_0;
+ break;
+ case level_idc_4_1:
+ *l_idc = level_idc_4_1;
+ break;
+ case level_idc_4_2:
+ *l_idc = level_idc_4_2;
+ break;
+ case level_idc_5_0:
+ *l_idc = level_idc_5_0;
+ break;
+ case level_idc_5_1:
+ *l_idc = level_idc_5_1;
+ break;
+ case level_idc_5_2:
+ *l_idc = level_idc_5_2;
+ 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, tsk_bool_t* end_of_unit)
{
- const uint8_t* pdata = (const uint8_t*)in_data;
- uint8_t nal_type;
- if (!in_data || !in_size || !out_data || !out_size || !append_scp || !end_of_unit) {
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- *out_data = tsk_null;
- *out_size = 0;
-
- /* 5.3. NAL Unit Octet Usage
- +---------------+
+ const uint8_t* pdata = (const uint8_t*)in_data;
+ uint8_t nal_type;
+ if (!in_data || !in_size || !out_data || !out_size || !append_scp || !end_of_unit) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ *out_data = tsk_null;
+ *out_size = 0;
+
+ /* 5.3. NAL Unit Octet Usage
+ +---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|F|NRI| Type |
+---------------+
- */
- switch ((nal_type = (pdata[0] & 0x1F))) {
- case undefined_0:
- case undefined_30:
- case undefined_31:
- case stap_a:
- case stap_b:
- case mtap16:
- case mtap24:
- case fu_b:
- break;
- case fu_a:
- return tdav_codec_h264_get_fua_pay(pdata, in_size, out_data, out_size, append_scp, end_of_unit);
- default: /* NAL unit (1-23) */
- *append_scp = tsk_true; //(nal_type != 7 && nal_type != 8); // SPS or PPS
- *end_of_unit = tsk_true;
- 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;
+ */
+ switch ((nal_type = (pdata[0] & 0x1F))) {
+ case undefined_0:
+ case undefined_30:
+ case undefined_31:
+ case stap_a:
+ case stap_b:
+ case mtap16:
+ case mtap24:
+ case fu_b:
+ break;
+ case fu_a:
+ return tdav_codec_h264_get_fua_pay(pdata, in_size, out_data, out_size, append_scp, end_of_unit);
+ default: /* NAL unit (1-23) */
+ *append_scp = tsk_true; //(nal_type != 7 && nal_type != 8); // SPS or PPS
+ *end_of_unit = tsk_true;
+ 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;
}
static 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, tsk_bool_t* end_of_unit)
{
- if (in_size <=H264_FUA_HEADER_SIZE) {
- TSK_DEBUG_ERROR("Too short");
- return -1;
- }
- /* RFC 3984 - 5.8. Fragmentation Units (FUs)
+ if (in_size <=H264_FUA_HEADER_SIZE) {
+ TSK_DEBUG_ERROR("Too short");
+ return -1;
+ }
+ /* RFC 3984 - 5.8. Fragmentation Units (FUs)
- 0 1 2 3
+ 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 | |
@@ -220,7 +220,7 @@ static int tdav_codec_h264_get_fua_pay(const uint8_t* in_data, tsk_size_t in_siz
| :...OPTIONAL RTP padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- The FU indicator octet has the following format:
+ The FU indicator octet has the following format:
+---------------+
|0|1|2|3|4|5|6|7|
@@ -228,27 +228,27 @@ static int tdav_codec_h264_get_fua_pay(const uint8_t* in_data, tsk_size_t in_siz
|F|NRI| Type |
+---------------+
- The FU header has the following format:
+ The FU header has the following format:
+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|S|E|R| Type |
+---------------+
- */
+ */
if (((in_data[1] & 0x80) /*S*/)) {
/* discard "FU indicator" */
*out_data = (in_data + H264_NAL_UNIT_TYPE_HEADER_SIZE);
*out_size = (in_size - H264_NAL_UNIT_TYPE_HEADER_SIZE);
-
+
// Do need to append Start Code Prefix ?
/* 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.*/
*append_scp = tsk_true;
-
+
// F, NRI and Type
*((uint8_t*)*out_data) = (in_data[0] & 0xe0) /* F,NRI from "FU indicator"*/ | (in_data[1] & 0x1f) /* type from "FU header" */;
}
@@ -257,155 +257,155 @@ static int tdav_codec_h264_get_fua_pay(const uint8_t* in_data, tsk_size_t in_siz
*out_data = (in_data + H264_FUA_HEADER_SIZE);
*out_size = (in_size - H264_FUA_HEADER_SIZE);
}
- /*
- E: 1 bit
+ /*
+ E: 1 bit
When set to one, the End bit indicates the end of a fragmented
NAL unit, i.e., the last byte of the payload is also the last
byte of the fragmented NAL unit. When the following FU
payload is not the last fragment of a fragmented NAL unit, the
End bit is set to zero.
- */
- *end_of_unit = (((in_data[1] & 0x40) /*E*/)) ? tsk_true : tsk_false;
+ */
+ *end_of_unit = (((in_data[1] & 0x40) /*E*/)) ? tsk_true : tsk_false;
- return 0;
+ return 0;
}
static 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;
+ /* 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;
}
void tdav_codec_h264_rtp_encap(struct tdav_codec_h264_common_s* self, const uint8_t* pdata, tsk_size_t size)
{
- static const tsk_size_t size_of_scp = sizeof(H264_START_CODE_PREFIX); /* we know it's equal to 4 .. */
- register tsk_size_t i;
- tsk_size_t last_scp, prev_scp;
- tsk_size_t _size;
-
- if (!pdata || size < size_of_scp) {
- return;
- }
-
- if (pdata[0] == 0 && pdata[1] == 0) {
- if (pdata[2] == 1) {
- pdata += 3, size -= 3;
- }
- else if (pdata[2] == 0 && pdata[3] == 1) {
- pdata += 4, size -= 4;
- }
- }
-
- _size = (size - size_of_scp);
- last_scp = 0, prev_scp = 0;
- for (i = size_of_scp; i<_size; i++) {
- if (pdata[i] == 0 && pdata[i+1] == 0 && (pdata[i+2] == 1 || (pdata[i+2] == 0 && pdata[i+3] == 1))) { /* Find Start Code Prefix */
- prev_scp = last_scp;
- if ((i - last_scp) >= H264_RTP_PAYLOAD_SIZE || 1) {
- tdav_codec_h264_rtp_callback(self, pdata + prev_scp,
- (i - prev_scp), (prev_scp == size));
- }
- last_scp = i;
- i += (pdata[i+2] == 1) ? 3 : 4;
- }
- }
-
- if (last_scp < (int32_t)size) {
- tdav_codec_h264_rtp_callback(self, pdata + last_scp,
- (size - last_scp), tsk_true);
- }
+ static const tsk_size_t size_of_scp = sizeof(H264_START_CODE_PREFIX); /* we know it's equal to 4 .. */
+ register tsk_size_t i;
+ tsk_size_t last_scp, prev_scp;
+ tsk_size_t _size;
+
+ if (!pdata || size < size_of_scp) {
+ return;
+ }
+
+ if (pdata[0] == 0 && pdata[1] == 0) {
+ if (pdata[2] == 1) {
+ pdata += 3, size -= 3;
+ }
+ else if (pdata[2] == 0 && pdata[3] == 1) {
+ pdata += 4, size -= 4;
+ }
+ }
+
+ _size = (size - size_of_scp);
+ last_scp = 0, prev_scp = 0;
+ for (i = size_of_scp; i<_size; i++) {
+ if (pdata[i] == 0 && pdata[i+1] == 0 && (pdata[i+2] == 1 || (pdata[i+2] == 0 && pdata[i+3] == 1))) { /* Find Start Code Prefix */
+ prev_scp = last_scp;
+ if ((i - last_scp) >= H264_RTP_PAYLOAD_SIZE || 1) {
+ tdav_codec_h264_rtp_callback(self, pdata + prev_scp,
+ (i - prev_scp), (prev_scp == size));
+ }
+ last_scp = i;
+ i += (pdata[i+2] == 1) ? 3 : 4;
+ }
+ }
+
+ if (last_scp < (int32_t)size) {
+ tdav_codec_h264_rtp_callback(self, pdata + last_scp,
+ (size - last_scp), tsk_true);
+ }
}
void tdav_codec_h264_rtp_callback(struct tdav_codec_h264_common_s *self, const void *data, tsk_size_t size, tsk_bool_t marker)
{
- uint8_t* pdata = (uint8_t*)data;
-
- //TSK_DEBUG_INFO("%x %x %x %x -- %u", pdata[0], pdata[1], pdata[2], pdata[3], size);
-
- 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 (self->pack_mode_local == Single_NAL_Unit_Mode || size < H264_RTP_PAYLOAD_SIZE) {
- if (self->pack_mode_local == Single_NAL_Unit_Mode && size > H264_RTP_PAYLOAD_SIZE) {
- TSK_DEBUG_WARN("pack_mode=Single_NAL_Unit_Mode but size(%d) > H264_RTP_PAYLOAD_SIZE(%d). Did you forget to set \"avctx->rtp_payload_size\"?", size, H264_RTP_PAYLOAD_SIZE);
- }
- // Can be packet in a Single Nal Unit
- // Send data over the network
- if (TMEDIA_CODEC_VIDEO(self)->out.callback) {
- TMEDIA_CODEC_VIDEO(self)->out.result.buffer.ptr = pdata;
- TMEDIA_CODEC_VIDEO(self)->out.result.buffer.size = size;
- TMEDIA_CODEC_VIDEO(self)->out.result.duration = (uint32_t)((1./(double)TMEDIA_CODEC_VIDEO(self)->out.fps) * TMEDIA_CODEC(self)->plugin->rate);
- TMEDIA_CODEC_VIDEO(self)->out.result.last_chunck = marker;
- TMEDIA_CODEC_VIDEO(self)->out.callback(&TMEDIA_CODEC_VIDEO(self)->out.result);
- }
- }
- else if (size > H264_NAL_UNIT_TYPE_HEADER_SIZE) {
- /* 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/* NRI */, 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 = (uint8_t*)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)->out.callback){
- TMEDIA_CODEC_VIDEO(self)->out.result.buffer.ptr = self->rtp.ptr;
- TMEDIA_CODEC_VIDEO(self)->out.result.buffer.size = (packet_size + H264_FUA_HEADER_SIZE);
- TMEDIA_CODEC_VIDEO(self)->out.result.duration = (uint32_t)((1./(double)TMEDIA_CODEC_VIDEO(self)->out.fps) * TMEDIA_CODEC(self)->plugin->rate);
- TMEDIA_CODEC_VIDEO(self)->out.result.last_chunck = (size == 0);
- TMEDIA_CODEC_VIDEO(self)->out.callback(&TMEDIA_CODEC_VIDEO(self)->out.result);
- }
- }
- }
+ uint8_t* pdata = (uint8_t*)data;
+
+ //TSK_DEBUG_INFO("%x %x %x %x -- %u", pdata[0], pdata[1], pdata[2], pdata[3], size);
+
+ 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 (self->pack_mode_local == Single_NAL_Unit_Mode || size < H264_RTP_PAYLOAD_SIZE) {
+ if (self->pack_mode_local == Single_NAL_Unit_Mode && size > H264_RTP_PAYLOAD_SIZE) {
+ TSK_DEBUG_WARN("pack_mode=Single_NAL_Unit_Mode but size(%d) > H264_RTP_PAYLOAD_SIZE(%d). Did you forget to set \"avctx->rtp_payload_size\"?", size, H264_RTP_PAYLOAD_SIZE);
+ }
+ // Can be packet in a Single Nal Unit
+ // Send data over the network
+ if (TMEDIA_CODEC_VIDEO(self)->out.callback) {
+ TMEDIA_CODEC_VIDEO(self)->out.result.buffer.ptr = pdata;
+ TMEDIA_CODEC_VIDEO(self)->out.result.buffer.size = size;
+ TMEDIA_CODEC_VIDEO(self)->out.result.duration = (uint32_t)((1./(double)TMEDIA_CODEC_VIDEO(self)->out.fps) * TMEDIA_CODEC(self)->plugin->rate);
+ TMEDIA_CODEC_VIDEO(self)->out.result.last_chunck = marker;
+ TMEDIA_CODEC_VIDEO(self)->out.callback(&TMEDIA_CODEC_VIDEO(self)->out.result);
+ }
+ }
+ else if (size > H264_NAL_UNIT_TYPE_HEADER_SIZE) {
+ /* 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/* NRI */, 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 = (uint8_t*)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)->out.callback) {
+ TMEDIA_CODEC_VIDEO(self)->out.result.buffer.ptr = self->rtp.ptr;
+ TMEDIA_CODEC_VIDEO(self)->out.result.buffer.size = (packet_size + H264_FUA_HEADER_SIZE);
+ TMEDIA_CODEC_VIDEO(self)->out.result.duration = (uint32_t)((1./(double)TMEDIA_CODEC_VIDEO(self)->out.fps) * TMEDIA_CODEC(self)->plugin->rate);
+ TMEDIA_CODEC_VIDEO(self)->out.result.last_chunck = (size == 0);
+ TMEDIA_CODEC_VIDEO(self)->out.callback(&TMEDIA_CODEC_VIDEO(self)->out.result);
+ }
+ }
+ }
}
diff --git a/tinyDAV/src/codecs/ilbc/tdav_codec_ilbc.c b/tinyDAV/src/codecs/ilbc/tdav_codec_ilbc.c
index 65df6ad..f4378c8 100755
--- a/tinyDAV/src/codecs/ilbc/tdav_codec_ilbc.c
+++ b/tinyDAV/src/codecs/ilbc/tdav_codec_ilbc.c
@@ -2,19 +2,19 @@
* Copyright (C) 2010-2011 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.
*
@@ -43,154 +43,154 @@
static int tdav_codec_ilbc_open(tmedia_codec_t* self)
{
- tdav_codec_ilbc_t* ilbc = (tdav_codec_ilbc_t*)self;
-
- initEncode(&ilbc->encoder, TDAV_ILBC_MODE);
+ tdav_codec_ilbc_t* ilbc = (tdav_codec_ilbc_t*)self;
+
+ initEncode(&ilbc->encoder, TDAV_ILBC_MODE);
initDecode(&ilbc->decoder, TDAV_ILBC_MODE, tsk_true/* Enhancer */);
- return 0;
+ return 0;
}
static int tdav_codec_ilbc_close(tmedia_codec_t* self)
{
- tdav_codec_ilbc_t* ilbc = (tdav_codec_ilbc_t*)self;
+ tdav_codec_ilbc_t* ilbc = (tdav_codec_ilbc_t*)self;
- //ilbc->encoder = {0};
- //ilbc->decoder = {0};
+ //ilbc->encoder = {0};
+ //ilbc->decoder = {0};
- return 0;
+ return 0;
}
static tsk_size_t tdav_codec_ilbc_encode(tmedia_codec_t* self, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size)
-{
- tdav_codec_ilbc_t* ilbc = (tdav_codec_ilbc_t*)self;
- int k;
-
- if(!self || !in_data || !in_size || !out_data){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- /* convert signal to float */
- for(k=0; k<ilbc->encoder.blockl; k++){
- ilbc->encblock[k] = (float)((short*)in_data)[k];
- }
-
- /* allocate new buffer if needed */
- if((int)*out_max_size <ilbc->encoder.no_of_bytes){
- if(!(*out_data = tsk_realloc(*out_data, ilbc->encoder.no_of_bytes))){
- TSK_DEBUG_ERROR("Failed to allocate new buffer");
- *out_max_size = 0;
- return 0;
- }
- *out_max_size = ilbc->encoder.no_of_bytes;
- }
-
- /* do the actual encoding */
+{
+ tdav_codec_ilbc_t* ilbc = (tdav_codec_ilbc_t*)self;
+ int k;
+
+ if(!self || !in_data || !in_size || !out_data) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ /* convert signal to float */
+ for(k=0; k<ilbc->encoder.blockl; k++) {
+ ilbc->encblock[k] = (float)((short*)in_data)[k];
+ }
+
+ /* allocate new buffer if needed */
+ if((int)*out_max_size <ilbc->encoder.no_of_bytes) {
+ if(!(*out_data = tsk_realloc(*out_data, ilbc->encoder.no_of_bytes))) {
+ TSK_DEBUG_ERROR("Failed to allocate new buffer");
+ *out_max_size = 0;
+ return 0;
+ }
+ *out_max_size = ilbc->encoder.no_of_bytes;
+ }
+
+ /* do the actual encoding */
iLBC_encode(*out_data, ilbc->encblock, &ilbc->encoder);
-
- return ilbc->encoder.no_of_bytes;
+
+ return ilbc->encoder.no_of_bytes;
}
static tsk_size_t tdav_codec_ilbc_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)
{
- int blocks, i, k, block_size;
- float dtmp;
- tsk_size_t out_size;
- tdav_codec_ilbc_t* ilbc = (tdav_codec_ilbc_t*)self;
-
- if(!self || !in_data || !in_size || !out_data){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- if((in_size % NO_OF_BYTES_20MS) == 0){
- /* Using 20ms mode */
- blocks = (in_size/NO_OF_BYTES_20MS);
- out_size = (BLOCKL_20MS * blocks) * sizeof(short);
- block_size = out_size/blocks;
- if(ilbc->decoder.mode != 20){
- initDecode(&ilbc->decoder, 20, tsk_true/* Enhancer */);
- }
- }
- else if((in_size % NO_OF_BYTES_30MS) == 0){
- /* Using 30ms mode */
- blocks = (in_size/NO_OF_BYTES_30MS);
- out_size = (BLOCKL_30MS * blocks) * sizeof(short);
- block_size = out_size/blocks;
- if(ilbc->decoder.mode != 30){
- initDecode(&ilbc->decoder, 30, tsk_true/* Enhancer */);
- }
- }
- else{
- TSK_DEBUG_ERROR("Invalid iLBC mode");
- return 0;
- }
-
- /* allocate new buffer if needed */
- if(*out_max_size<out_size){
- if(!(*out_data = tsk_realloc(*out_data, out_size))){
- TSK_DEBUG_ERROR("Failed to allocate new buffer");
- *out_max_size = 0;
- return 0;
- }
- *out_max_size = out_size;
- }
-
- for(i = 0; i<blocks; i++){
- iLBC_decode(ilbc->decblock, &((uint8_t*)in_data)[i*block_size], &ilbc->decoder, 1/* Normal */);
-
- /* convert to short */
- for(k=0; k<ilbc->decoder.blockl; k++){
- dtmp=ilbc->decblock[k];
-
- if(dtmp<MIN_SAMPLE){
- dtmp = MIN_SAMPLE;
- }
- else if(dtmp>MAX_SAMPLE){
- dtmp = MAX_SAMPLE;
- }
-
- ((short*)*out_data)[(i*block_size) + k] = ((short) dtmp);
- }
- }
-
- return out_size;
+ int blocks, i, k, block_size;
+ float dtmp;
+ tsk_size_t out_size;
+ tdav_codec_ilbc_t* ilbc = (tdav_codec_ilbc_t*)self;
+
+ if(!self || !in_data || !in_size || !out_data) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ if((in_size % NO_OF_BYTES_20MS) == 0) {
+ /* Using 20ms mode */
+ blocks = (in_size/NO_OF_BYTES_20MS);
+ out_size = (BLOCKL_20MS * blocks) * sizeof(short);
+ block_size = out_size/blocks;
+ if(ilbc->decoder.mode != 20) {
+ initDecode(&ilbc->decoder, 20, tsk_true/* Enhancer */);
+ }
+ }
+ else if((in_size % NO_OF_BYTES_30MS) == 0) {
+ /* Using 30ms mode */
+ blocks = (in_size/NO_OF_BYTES_30MS);
+ out_size = (BLOCKL_30MS * blocks) * sizeof(short);
+ block_size = out_size/blocks;
+ if(ilbc->decoder.mode != 30) {
+ initDecode(&ilbc->decoder, 30, tsk_true/* Enhancer */);
+ }
+ }
+ else {
+ TSK_DEBUG_ERROR("Invalid iLBC mode");
+ return 0;
+ }
+
+ /* allocate new buffer if needed */
+ if(*out_max_size<out_size) {
+ if(!(*out_data = tsk_realloc(*out_data, out_size))) {
+ TSK_DEBUG_ERROR("Failed to allocate new buffer");
+ *out_max_size = 0;
+ return 0;
+ }
+ *out_max_size = out_size;
+ }
+
+ for(i = 0; i<blocks; i++) {
+ iLBC_decode(ilbc->decblock, &((uint8_t*)in_data)[i*block_size], &ilbc->decoder, 1/* Normal */);
+
+ /* convert to short */
+ for(k=0; k<ilbc->decoder.blockl; k++) {
+ dtmp=ilbc->decblock[k];
+
+ if(dtmp<MIN_SAMPLE) {
+ dtmp = MIN_SAMPLE;
+ }
+ else if(dtmp>MAX_SAMPLE) {
+ dtmp = MAX_SAMPLE;
+ }
+
+ ((short*)*out_data)[(i*block_size) + k] = ((short) dtmp);
+ }
+ }
+
+ return out_size;
}
static char* tdav_codec_ilbc_sdp_att_get(const tmedia_codec_t* codec, const char* att_name)
{
- if(tsk_striequals(att_name, "fmtp")){
- char* fmtp = tsk_null;
- tsk_sprintf(&fmtp, "mode=%d", TDAV_ILBC_MODE);
- return fmtp;
- }
- return tsk_null;
+ if(tsk_striequals(att_name, "fmtp")) {
+ char* fmtp = tsk_null;
+ tsk_sprintf(&fmtp, "mode=%d", TDAV_ILBC_MODE);
+ return fmtp;
+ }
+ return tsk_null;
}
static tsk_bool_t tdav_codec_ilbc_sdp_att_match(const tmedia_codec_t* codec, const char* att_name, const char* att_value)
-{
- if(tsk_striequals(att_name, "fmtp")){
- /* RFC 3952 - 5. Mapping To SDP Parameters
-
- The offer contains the preferred mode of the offerer. The answerer
- may agree to that mode by including the same mode in the answer, or
- may include a different mode. The resulting mode used by both
- parties SHALL be the lower of the bandwidth modes in the offer and
- answer.
-
- That is, an offer of "mode=20" receiving an answer of "mode=30" will
- result in "mode=30" being used by both participants. Similarly, an
- offer of "mode=30" and an answer of "mode=20" will result in
- "mode=30" being used by both participants.
-
- This is important when one end point utilizes a bandwidth constrained
- link (e.g., 28.8k modem link or slower), where only the lower frame
- size will work.
- */
- return tsk_true; // FIXME
- }
- return tsk_true;
+{
+ if(tsk_striequals(att_name, "fmtp")) {
+ /* RFC 3952 - 5. Mapping To SDP Parameters
+
+ The offer contains the preferred mode of the offerer. The answerer
+ may agree to that mode by including the same mode in the answer, or
+ may include a different mode. The resulting mode used by both
+ parties SHALL be the lower of the bandwidth modes in the offer and
+ answer.
+
+ That is, an offer of "mode=20" receiving an answer of "mode=30" will
+ result in "mode=30" being used by both participants. Similarly, an
+ offer of "mode=30" and an answer of "mode=20" will result in
+ "mode=30" being used by both participants.
+
+ This is important when one end point utilizes a bandwidth constrained
+ link (e.g., 28.8k modem link or slower), where only the lower frame
+ size will work.
+ */
+ return tsk_true; // FIXME
+ }
+ return tsk_true;
}
@@ -201,63 +201,61 @@ static tsk_bool_t tdav_codec_ilbc_sdp_att_match(const tmedia_codec_t* codec, con
/* constructor */
static tsk_object_t* tdav_codec_ilbc_ctor(tsk_object_t * self, va_list * app)
{
- tdav_codec_ilbc_t *ilbc = self;
- if(ilbc){
- /* init base: called by tmedia_codec_create() */
- /* init self */
- }
- return self;
+ tdav_codec_ilbc_t *ilbc = self;
+ if(ilbc) {
+ /* init base: called by tmedia_codec_create() */
+ /* init self */
+ }
+ return self;
}
/* destructor */
static tsk_object_t* tdav_codec_ilbc_dtor(tsk_object_t * self)
-{
- tdav_codec_ilbc_t *ilbc = self;
- if(ilbc){
- /* deinit base */
- tmedia_codec_audio_deinit(ilbc);
- /* deinit self */
- //ilbc->encoder = {0};
- //ilbc->decoder = {0};
- }
-
- return self;
+{
+ tdav_codec_ilbc_t *ilbc = self;
+ if(ilbc) {
+ /* deinit base */
+ tmedia_codec_audio_deinit(ilbc);
+ /* deinit self */
+ //ilbc->encoder = {0};
+ //ilbc->decoder = {0};
+ }
+
+ return self;
}
/* object definition */
-static const tsk_object_def_t tdav_codec_ilbc_def_s =
-{
- sizeof(tdav_codec_ilbc_t),
- tdav_codec_ilbc_ctor,
- tdav_codec_ilbc_dtor,
- tmedia_codec_cmp,
+static const tsk_object_def_t tdav_codec_ilbc_def_s = {
+ sizeof(tdav_codec_ilbc_t),
+ tdav_codec_ilbc_ctor,
+ tdav_codec_ilbc_dtor,
+ tmedia_codec_cmp,
};
/* plugin definition*/
-static const tmedia_codec_plugin_def_t tdav_codec_ilbc_plugin_def_s =
-{
- &tdav_codec_ilbc_def_s,
-
- tmedia_audio,
- tmedia_codec_id_ilbc,
- "iLBC",
- "iLBC codec (libILBc)",
- TMEDIA_CODEC_FORMAT_ILBC,
- tsk_true,
- 8000, // rate
-
- { /* audio */
- 1, // channels
- 20 // ptime
- },
-
- /* video */
- {0},
-
- tdav_codec_ilbc_set,
- tdav_codec_ilbc_open,
- tdav_codec_ilbc_close,
- tdav_codec_ilbc_encode,
- tdav_codec_ilbc_decode,
- tdav_codec_ilbc_sdp_att_match,
- tdav_codec_ilbc_sdp_att_get
+static const tmedia_codec_plugin_def_t tdav_codec_ilbc_plugin_def_s = {
+ &tdav_codec_ilbc_def_s,
+
+ tmedia_audio,
+ tmedia_codec_id_ilbc,
+ "iLBC",
+ "iLBC codec (libILBc)",
+ TMEDIA_CODEC_FORMAT_ILBC,
+ tsk_true,
+ 8000, // rate
+
+ { /* audio */
+ 1, // channels
+ 20 // ptime
+ },
+
+ /* video */
+ {0},
+
+ tdav_codec_ilbc_set,
+ tdav_codec_ilbc_open,
+ tdav_codec_ilbc_close,
+ tdav_codec_ilbc_encode,
+ tdav_codec_ilbc_decode,
+ tdav_codec_ilbc_sdp_att_match,
+ tdav_codec_ilbc_sdp_att_get
};
const tmedia_codec_plugin_def_t *tdav_codec_ilbc_plugin_def_t = &tdav_codec_ilbc_plugin_def_s;
diff --git a/tinyDAV/src/codecs/mp4ves/tdav_codec_mp4ves.c b/tinyDAV/src/codecs/mp4ves/tdav_codec_mp4ves.c
index e48cb00..7c99acd 100755
--- a/tinyDAV/src/codecs/mp4ves/tdav_codec_mp4ves.c
+++ b/tinyDAV/src/codecs/mp4ves/tdav_codec_mp4ves.c
@@ -2,19 +2,19 @@
* Copyright (C) 2010-2011 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.
*
@@ -54,103 +54,100 @@
#define MP4V_GOP_SIZE_IN_SECONDS 25
#define MP4V_RTP_PAYLOAD_SIZE 900
-typedef struct tdav_codec_mp4ves_s
-{
- TMEDIA_DECLARE_CODEC_VIDEO;
-
- int profile;
-
- struct{
- uint8_t* ptr;
- tsk_size_t size;
- } rtp;
-
- // Encoder
- struct{
- AVCodec* codec;
- AVCodecContext* context;
- AVFrame* picture;
- void* buffer;
- tsk_bool_t force_idr;
- int quality; // [1-31]
- int rotation;
- int32_t max_bw_kpbs;
- } encoder;
-
- // decoder
- struct{
- AVCodec* codec;
- AVCodecContext* context;
- AVFrame* picture;
-
- void* accumulator;
- uint8_t ebit;
- tsk_size_t accumulator_pos;
- uint16_t last_seq;
- } decoder;
+typedef struct tdav_codec_mp4ves_s {
+ TMEDIA_DECLARE_CODEC_VIDEO;
+
+ int profile;
+
+ struct {
+ uint8_t* ptr;
+ tsk_size_t size;
+ } rtp;
+
+ // Encoder
+ struct {
+ AVCodec* codec;
+ AVCodecContext* context;
+ AVFrame* picture;
+ void* buffer;
+ tsk_bool_t force_idr;
+ int quality; // [1-31]
+ int rotation;
+ int32_t max_bw_kpbs;
+ } encoder;
+
+ // decoder
+ struct {
+ AVCodec* codec;
+ AVCodecContext* context;
+ AVFrame* picture;
+
+ void* accumulator;
+ uint8_t ebit;
+ tsk_size_t accumulator_pos;
+ uint16_t last_seq;
+ } decoder;
}
tdav_codec_mp4ves_t;
// From ISO-IEC-14496-2
-typedef enum mp4v_codes_e
-{
- // To initiate a visual session (6.3.2)
- visual_object_sequence_start_code = 0x000001B0,
- // To terminate a visual session (6.3.2)
- visual_object_sequence_end_code = 0x000001B1,
- // To initiate a visual object (6.3.2)
- visual_object_start_code = 0x000001B5,
- // To identify the beginning of user data. The user data continues until receipt of another start code. (6.3.2.1)
- user_data_start_code = 0x000001B2,
- // The video_object_layer_start_code is a string of 32 bits. The first 28 bits are
- // ‘0000 0000 0000 0000 0000 0001 0010‘ in binary and the last 4-bits represent one of the values in the range of
- // ‘0000’ to ‘1111’ in binary. The video_object_layer_start_code marks a new video object layer. (6.3.3)
- video_object_layer_start_code = 0x0000012,
- // To identify the beginning of a GOV header (6.3.4)
- group_of_vop_start_code = 0x000001B3,
- // To mark the start of a video object plane (6.3.5 )
- vop_start_code = 0x000001B6,
+typedef enum mp4v_codes_e {
+ // To initiate a visual session (6.3.2)
+ visual_object_sequence_start_code = 0x000001B0,
+ // To terminate a visual session (6.3.2)
+ visual_object_sequence_end_code = 0x000001B1,
+ // To initiate a visual object (6.3.2)
+ visual_object_start_code = 0x000001B5,
+ // To identify the beginning of user data. The user data continues until receipt of another start code. (6.3.2.1)
+ user_data_start_code = 0x000001B2,
+ // The video_object_layer_start_code is a string of 32 bits. The first 28 bits are
+ // ‘0000 0000 0000 0000 0000 0001 0010‘ in binary and the last 4-bits represent one of the values in the range of
+ // ‘0000’ to ‘1111’ in binary. The video_object_layer_start_code marks a new video object layer. (6.3.3)
+ video_object_layer_start_code = 0x0000012,
+ // To identify the beginning of a GOV header (6.3.4)
+ group_of_vop_start_code = 0x000001B3,
+ // To mark the start of a video object plane (6.3.5 )
+ vop_start_code = 0x000001B6,
}
mp4v_start_code_t;
// From ISO-IEC-14496-2 Annex G
-typedef enum mp4v_profiles_e
-{
- /* Reserved = 0x00000000 */
- Simple_Profile_Level_1 = 1,
- Simple_Profile_Level_2 = 2,
- Simple_Profile_Level_3 = 3,
- /* Reserved 00000100 ? 00010000 */
- Simple_Scalable_Profile_Level_1 = 17,
- Simple_Scalable_Profile_Level_2 = 18,
- /* Reserved 00010011 ? = 0x00100000 */
- Core_Profile_Level_1 = 33,
- Core_Profile_Level_2 = 34,
- /* Reserved 00100011 ? = 0x00110001 */
- Main_Profile_Level_2 = 50,
- Main_Profile_Level_3 = 51,
- Main_Profile_Level_4 = 52,
- /* Reserved 00110101 ? = 0x01000001 */
- N_bit_Profile_Level_2 = 66,
- /* Reserved 01000011 ? = 0x01010000 */
- Scalable_Texture_Profile_Level_1 = 81,
- /* Reserved 01010010 ? 01100000 */
- Simple_Face_Animation_Profile_Level_1 = 97,
- Simple_Face_Animation_Profile_Level_2 = 98,
- Simple_FBA_Profile_Level_1 = 99,
- Simple_FBA_Profile_Level_2 = 100,
- /* Reserved 01100101 ? 01110000 */
- Basic_Animated_Texture_Profile_Level_1 = 113,
- Basic_Animated_Texture_Profile_Level_2 = 114,
- /* Reserved 01110011 ? 10000000 */
- Hybrid_Profile_Level_1 = 129,
- Hybrid_Profile_Level_2 = 130,
- /* Reserved 10000011 ? 10010000 */
- Advanced_Real_Time_Simple_Profile_Level_1 = 145,
- Advanced_Real_Time_Simple_Profile_Level_2 = 146,
- Advanced_Real_Time_Simple_Profile_Level_3 = 147,
- Advanced_Real_Time_Simple_Profile_Level_4 = 148,
- /* Reserved 10010101 ? 10100000 */
+typedef enum mp4v_profiles_e {
+ /* Reserved = 0x00000000 */
+ Simple_Profile_Level_1 = 1,
+ Simple_Profile_Level_2 = 2,
+ Simple_Profile_Level_3 = 3,
+ /* Reserved 00000100 ? 00010000 */
+ Simple_Scalable_Profile_Level_1 = 17,
+ Simple_Scalable_Profile_Level_2 = 18,
+ /* Reserved 00010011 ? = 0x00100000 */
+ Core_Profile_Level_1 = 33,
+ Core_Profile_Level_2 = 34,
+ /* Reserved 00100011 ? = 0x00110001 */
+ Main_Profile_Level_2 = 50,
+ Main_Profile_Level_3 = 51,
+ Main_Profile_Level_4 = 52,
+ /* Reserved 00110101 ? = 0x01000001 */
+ N_bit_Profile_Level_2 = 66,
+ /* Reserved 01000011 ? = 0x01010000 */
+ Scalable_Texture_Profile_Level_1 = 81,
+ /* Reserved 01010010 ? 01100000 */
+ Simple_Face_Animation_Profile_Level_1 = 97,
+ Simple_Face_Animation_Profile_Level_2 = 98,
+ Simple_FBA_Profile_Level_1 = 99,
+ Simple_FBA_Profile_Level_2 = 100,
+ /* Reserved 01100101 ? 01110000 */
+ Basic_Animated_Texture_Profile_Level_1 = 113,
+ Basic_Animated_Texture_Profile_Level_2 = 114,
+ /* Reserved 01110011 ? 10000000 */
+ Hybrid_Profile_Level_1 = 129,
+ Hybrid_Profile_Level_2 = 130,
+ /* Reserved 10000011 ? 10010000 */
+ Advanced_Real_Time_Simple_Profile_Level_1 = 145,
+ Advanced_Real_Time_Simple_Profile_Level_2 = 146,
+ Advanced_Real_Time_Simple_Profile_Level_3 = 147,
+ Advanced_Real_Time_Simple_Profile_Level_4 = 148,
+ /* Reserved 10010101 ? 10100000 */
}
mp4v_profiles_t;
@@ -166,580 +163,578 @@ static void tdav_codec_mp4ves_rtp_callback(tdav_codec_mp4ves_t *mp4v, const void
static int tdav_codec_mp4ves_set(tmedia_codec_t* self, const tmedia_param_t* param)
{
- tdav_codec_mp4ves_t* mp4ves = (tdav_codec_mp4ves_t*)self;
- if(!self->opened){
- TSK_DEBUG_ERROR("Codec not opened");
- return -1;
- }
- if(param->value_type == tmedia_pvt_int32){
- if(tsk_striequals(param->key, "action")){
- tmedia_codec_action_t action = (tmedia_codec_action_t)TSK_TO_INT32((uint8_t*)param->value);
- switch(action){
- case tmedia_codec_action_encode_idr:
- {
- mp4ves->encoder.force_idr = tsk_true;
- break;
- }
- case tmedia_codec_action_bw_down:
- {
- mp4ves->encoder.quality = TSK_CLAMP(1, (mp4ves->encoder.quality + 1), 31);
- mp4ves->encoder.context->global_quality = FF_QP2LAMBDA * mp4ves->encoder.quality;
- break;
- }
- case tmedia_codec_action_bw_up:
- {
- mp4ves->encoder.quality = TSK_CLAMP(1, (mp4ves->encoder.quality - 1), 31);
- mp4ves->encoder.context->global_quality = FF_QP2LAMBDA * mp4ves->encoder.quality;
- break;
- }
- }
- }
- else if(tsk_striequals(param->key, "rotation")){
- int rotation = *((int32_t*)param->value);
- if(mp4ves->encoder.rotation != rotation){
- if(self->opened){
- int ret;
- mp4ves->encoder.rotation = rotation;
- if((ret = tdav_codec_mp4ves_close_encoder(mp4ves))){
- return ret;
- }
- if((ret = tdav_codec_mp4ves_open_encoder(mp4ves))){
- return ret;
- }
- }
- }
- return 0;
- }
- }
- return -1;
+ tdav_codec_mp4ves_t* mp4ves = (tdav_codec_mp4ves_t*)self;
+ if(!self->opened) {
+ TSK_DEBUG_ERROR("Codec not opened");
+ return -1;
+ }
+ if(param->value_type == tmedia_pvt_int32) {
+ if(tsk_striequals(param->key, "action")) {
+ tmedia_codec_action_t action = (tmedia_codec_action_t)TSK_TO_INT32((uint8_t*)param->value);
+ switch(action) {
+ case tmedia_codec_action_encode_idr: {
+ mp4ves->encoder.force_idr = tsk_true;
+ break;
+ }
+ case tmedia_codec_action_bw_down: {
+ mp4ves->encoder.quality = TSK_CLAMP(1, (mp4ves->encoder.quality + 1), 31);
+ mp4ves->encoder.context->global_quality = FF_QP2LAMBDA * mp4ves->encoder.quality;
+ break;
+ }
+ case tmedia_codec_action_bw_up: {
+ mp4ves->encoder.quality = TSK_CLAMP(1, (mp4ves->encoder.quality - 1), 31);
+ mp4ves->encoder.context->global_quality = FF_QP2LAMBDA * mp4ves->encoder.quality;
+ break;
+ }
+ }
+ }
+ else if(tsk_striequals(param->key, "rotation")) {
+ int rotation = *((int32_t*)param->value);
+ if(mp4ves->encoder.rotation != rotation) {
+ if(self->opened) {
+ int ret;
+ mp4ves->encoder.rotation = rotation;
+ if((ret = tdav_codec_mp4ves_close_encoder(mp4ves))) {
+ return ret;
+ }
+ if((ret = tdav_codec_mp4ves_open_encoder(mp4ves))) {
+ return ret;
+ }
+ }
+ }
+ return 0;
+ }
+ }
+ return -1;
}
int tdav_codec_mp4ves_open(tmedia_codec_t* self)
{
- int ret;
-
- tdav_codec_mp4ves_t* mp4v = (tdav_codec_mp4ves_t*)self;
-
- if(!mp4v){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- /* the caller (base class) already checked that the codec is not opened */
-
-
- // Encoder
- if((ret = tdav_codec_mp4ves_open_encoder(mp4v))){
- return ret;
- }
-
- // Decoder
- if((ret = tdav_codec_mp4ves_open_decoder(mp4v))){
- return ret;
- }
-
- return 0;
+ int ret;
+
+ tdav_codec_mp4ves_t* mp4v = (tdav_codec_mp4ves_t*)self;
+
+ if(!mp4v) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ /* the caller (base class) already checked that the codec is not opened */
+
+
+ // Encoder
+ if((ret = tdav_codec_mp4ves_open_encoder(mp4v))) {
+ return ret;
+ }
+
+ // Decoder
+ if((ret = tdav_codec_mp4ves_open_decoder(mp4v))) {
+ return ret;
+ }
+
+ return 0;
}
int tdav_codec_mp4ves_close(tmedia_codec_t* self)
{
- tdav_codec_mp4ves_t* mp4v = (tdav_codec_mp4ves_t*)self;
+ tdav_codec_mp4ves_t* mp4v = (tdav_codec_mp4ves_t*)self;
+
+ if(!mp4v) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
- if(!mp4v){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
+ /* the caller (base class) already checked that the codec is opened */
- /* the caller (base class) already checked that the codec is opened */
+ // Encoder
+ tdav_codec_mp4ves_close_encoder(mp4v);
- // Encoder
- tdav_codec_mp4ves_close_encoder(mp4v);
-
- // Decoder
- tdav_codec_mp4ves_close_decoder(mp4v);
+ // Decoder
+ tdav_codec_mp4ves_close_decoder(mp4v);
- return 0;
+ return 0;
}
tsk_size_t tdav_codec_mp4ves_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;
+ int ret;
+ int size;
- tdav_codec_mp4ves_t* mp4v = (tdav_codec_mp4ves_t*)self;
+ tdav_codec_mp4ves_t* mp4v = (tdav_codec_mp4ves_t*)self;
- if(!self || !in_data || !in_size || !out_data){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
+ if(!self || !in_data || !in_size || !out_data) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
- // wrap yuv420 buffer
- size = avpicture_fill((AVPicture *)mp4v->encoder.picture, (uint8_t*)in_data, PIX_FMT_YUV420P, mp4v->encoder.context->width, mp4v->encoder.context->height);
- if(size != in_size){
- /* guard */
- TSK_DEBUG_ERROR("Invalid size");
- return 0;
- }
+ // wrap yuv420 buffer
+ size = avpicture_fill((AVPicture *)mp4v->encoder.picture, (uint8_t*)in_data, PIX_FMT_YUV420P, mp4v->encoder.context->width, mp4v->encoder.context->height);
+ if(size != in_size) {
+ /* guard */
+ TSK_DEBUG_ERROR("Invalid size");
+ return 0;
+ }
- if(mp4v->encoder.force_idr){
+ if(mp4v->encoder.force_idr) {
#if LIBAVCODEC_VERSION_MAJOR <= 53
mp4v->encoder.picture->pict_type = FF_I_TYPE;
#else
mp4v->encoder.picture->pict_type = AV_PICTURE_TYPE_I;
#endif
- mp4v->encoder.force_idr = tsk_false;
- }
- else{
- mp4v->encoder.picture->pict_type = 0;// reset
- }
- mp4v->encoder.picture->pts = AV_NOPTS_VALUE;
- mp4v->encoder.picture->quality = mp4v->encoder.context->global_quality;
- ret = avcodec_encode_video(mp4v->encoder.context, mp4v->encoder.buffer, size, mp4v->encoder.picture);
- if(ret > 0){
- tdav_codec_mp4ves_encap(mp4v, mp4v->encoder.buffer, (tsk_size_t)ret);
- }
-
- return 0;
+ mp4v->encoder.force_idr = tsk_false;
+ }
+ else {
+ mp4v->encoder.picture->pict_type = 0;// reset
+ }
+ mp4v->encoder.picture->pts = AV_NOPTS_VALUE;
+ mp4v->encoder.picture->quality = mp4v->encoder.context->global_quality;
+ ret = avcodec_encode_video(mp4v->encoder.context, mp4v->encoder.buffer, size, mp4v->encoder.picture);
+ if(ret > 0) {
+ tdav_codec_mp4ves_encap(mp4v, mp4v->encoder.buffer, (tsk_size_t)ret);
+ }
+
+ return 0;
}
tsk_size_t tdav_codec_mp4ves_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)
-{
- tdav_codec_mp4ves_t* self = (tdav_codec_mp4ves_t*)_self;
- const trtp_rtp_header_t* rtp_hdr = proto_hdr;
-
- tsk_size_t xsize, retsize = 0;
- int got_picture_ptr;
- int ret;
-
- if(!self || !in_data || !in_size || !out_data || !self->decoder.context){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- // get expected size
- xsize = avpicture_get_size(self->decoder.context->pix_fmt, self->decoder.context->width, self->decoder.context->height);
-
- /* Packet lost? */
- if(self->decoder.last_seq != (rtp_hdr->seq_num - 1) && self->decoder.last_seq){
- if(self->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);
- }
- self->decoder.last_seq = rtp_hdr->seq_num;
-
- if((self->decoder.accumulator_pos + in_size) <= xsize){
- memcpy(&((uint8_t*)self->decoder.accumulator)[self->decoder.accumulator_pos], in_data, in_size);
- self->decoder.accumulator_pos += in_size;
- }
- else{
- TSK_DEBUG_WARN("Buffer overflow");
- self->decoder.accumulator_pos = 0;
- return 0;
- }
-
- if(rtp_hdr->marker){
- AVPacket packet;
- /* allocate destination buffer */
- if(*out_max_size <xsize){
- if(!(*out_data = tsk_realloc(*out_data, xsize))){
- TSK_DEBUG_ERROR("Failed to allocate new buffer");
- self->decoder.accumulator_pos = 0;
- *out_max_size = 0;
- return 0;
- }
- *out_max_size = xsize;
- }
-
- av_init_packet(&packet);
- packet.size = (int)self->decoder.accumulator_pos;
- packet.data = self->decoder.accumulator;
- ret = avcodec_decode_video2(self->decoder.context, self->decoder.picture, &got_picture_ptr, &packet);
-
- if(ret < 0){
- TSK_DEBUG_WARN("Failed to decode the buffer with error code = %d", ret);
- if(TMEDIA_CODEC_VIDEO(self)->in.callback){
- TMEDIA_CODEC_VIDEO(self)->in.result.type = tmedia_video_decode_result_type_error;
- TMEDIA_CODEC_VIDEO(self)->in.result.proto_hdr = proto_hdr;
- TMEDIA_CODEC_VIDEO(self)->in.callback(&TMEDIA_CODEC_VIDEO(self)->in.result);
- }
- }
- else if(got_picture_ptr){
- retsize = xsize;
- TMEDIA_CODEC_VIDEO(self)->in.width = self->decoder.context->width;
- TMEDIA_CODEC_VIDEO(self)->in.height = self->decoder.context->height;
-
- /* copy picture into a linear buffer */
- avpicture_layout((AVPicture *)self->decoder.picture, self->decoder.context->pix_fmt, (int)self->decoder.context->width, (int)self->decoder.context->height,
- *out_data, (int)retsize);
- }
- /* in all cases: reset accumulator */
- self->decoder.accumulator_pos = 0;
- }
-
- return retsize;
+{
+ tdav_codec_mp4ves_t* self = (tdav_codec_mp4ves_t*)_self;
+ const trtp_rtp_header_t* rtp_hdr = proto_hdr;
+
+ tsk_size_t xsize, retsize = 0;
+ int got_picture_ptr;
+ int ret;
+
+ if(!self || !in_data || !in_size || !out_data || !self->decoder.context) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ // get expected size
+ xsize = avpicture_get_size(self->decoder.context->pix_fmt, self->decoder.context->width, self->decoder.context->height);
+
+ /* Packet lost? */
+ if(self->decoder.last_seq != (rtp_hdr->seq_num - 1) && self->decoder.last_seq) {
+ if(self->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);
+ }
+ self->decoder.last_seq = rtp_hdr->seq_num;
+
+ if((self->decoder.accumulator_pos + in_size) <= xsize) {
+ memcpy(&((uint8_t*)self->decoder.accumulator)[self->decoder.accumulator_pos], in_data, in_size);
+ self->decoder.accumulator_pos += in_size;
+ }
+ else {
+ TSK_DEBUG_WARN("Buffer overflow");
+ self->decoder.accumulator_pos = 0;
+ return 0;
+ }
+
+ if(rtp_hdr->marker) {
+ AVPacket packet;
+ /* allocate destination buffer */
+ if(*out_max_size <xsize) {
+ if(!(*out_data = tsk_realloc(*out_data, xsize))) {
+ TSK_DEBUG_ERROR("Failed to allocate new buffer");
+ self->decoder.accumulator_pos = 0;
+ *out_max_size = 0;
+ return 0;
+ }
+ *out_max_size = xsize;
+ }
+
+ av_init_packet(&packet);
+ packet.size = (int)self->decoder.accumulator_pos;
+ packet.data = self->decoder.accumulator;
+ ret = avcodec_decode_video2(self->decoder.context, self->decoder.picture, &got_picture_ptr, &packet);
+
+ if(ret < 0) {
+ TSK_DEBUG_WARN("Failed to decode the buffer with error code = %d", ret);
+ if(TMEDIA_CODEC_VIDEO(self)->in.callback) {
+ TMEDIA_CODEC_VIDEO(self)->in.result.type = tmedia_video_decode_result_type_error;
+ TMEDIA_CODEC_VIDEO(self)->in.result.proto_hdr = proto_hdr;
+ TMEDIA_CODEC_VIDEO(self)->in.callback(&TMEDIA_CODEC_VIDEO(self)->in.result);
+ }
+ }
+ else if(got_picture_ptr) {
+ retsize = xsize;
+ TMEDIA_CODEC_VIDEO(self)->in.width = self->decoder.context->width;
+ TMEDIA_CODEC_VIDEO(self)->in.height = self->decoder.context->height;
+
+ /* copy picture into a linear buffer */
+ avpicture_layout((AVPicture *)self->decoder.picture, self->decoder.context->pix_fmt, (int)self->decoder.context->width, (int)self->decoder.context->height,
+ *out_data, (int)retsize);
+ }
+ /* in all cases: reset accumulator */
+ self->decoder.accumulator_pos = 0;
+ }
+
+ return retsize;
}
tsk_bool_t tdav_codec_mp4ves_sdp_att_match(const tmedia_codec_t* _self, const char* att_name, const char* att_value)
{
- tdav_codec_mp4ves_t *self = (tdav_codec_mp4ves_t *)_self;
-
- if(!self){
- TSK_DEBUG_ERROR("Invalid parameter");
- return tsk_false;
- }
-
- if(tsk_striequals(att_name, "fmtp")){
- tsk_params_L_t* params ;
- /* e.g. profile-level-id=1; xx=yy */
- if((params = tsk_params_fromstring(att_value, ";", tsk_true))){
- int val_int;
- if((val_int = tsk_params_get_param_value_as_int(params, "profile-level-id")) != -1){
- TSK_DEBUG_INFO("Proposed profile-level-id=%d", val_int);
- self->profile = val_int; // FIXME: Take the remote profile-level-id even if the bandwidth level doesn't match
- }
- TSK_OBJECT_SAFE_FREE(params);
- }
-
- switch (self->profile ) {
- case Simple_Profile_Level_1:
- TMEDIA_CODEC_VIDEO(self)->out.width = TMEDIA_CODEC_VIDEO(self)->in.width = 176; TMEDIA_CODEC_VIDEO(self)->in.height = TMEDIA_CODEC_VIDEO(self)->out.height = 144;
- break;
- case Simple_Profile_Level_2:
- case Simple_Profile_Level_3:
- default:
- TMEDIA_CODEC_VIDEO(self)->out.width = TMEDIA_CODEC_VIDEO(self)->in.width = 352; TMEDIA_CODEC_VIDEO(self)->in.height = TMEDIA_CODEC_VIDEO(self)->out.height = 288;
- break;
- }
- }
- else if(tsk_striequals(att_name, "imageattr")){
- unsigned in_width, in_height, out_width, out_height;
- if(tmedia_parse_video_imageattr(att_value, TMEDIA_CODEC_VIDEO(self)->pref_size, &in_width, &in_height, &out_width, &out_height) != 0){
- return tsk_false;
- }
- TMEDIA_CODEC_VIDEO(self)->in.width = in_width;
- TMEDIA_CODEC_VIDEO(self)->in.height = in_height;
- TMEDIA_CODEC_VIDEO(self)->out.width = out_width;
- TMEDIA_CODEC_VIDEO(self)->out.height = out_height;
- }
-
- return tsk_true;
+ tdav_codec_mp4ves_t *self = (tdav_codec_mp4ves_t *)_self;
+
+ if(!self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return tsk_false;
+ }
+
+ if(tsk_striequals(att_name, "fmtp")) {
+ tsk_params_L_t* params ;
+ /* e.g. profile-level-id=1; xx=yy */
+ if((params = tsk_params_fromstring(att_value, ";", tsk_true))) {
+ int val_int;
+ if((val_int = tsk_params_get_param_value_as_int(params, "profile-level-id")) != -1) {
+ TSK_DEBUG_INFO("Proposed profile-level-id=%d", val_int);
+ self->profile = val_int; // FIXME: Take the remote profile-level-id even if the bandwidth level doesn't match
+ }
+ TSK_OBJECT_SAFE_FREE(params);
+ }
+
+ switch (self->profile ) {
+ case Simple_Profile_Level_1:
+ TMEDIA_CODEC_VIDEO(self)->out.width = TMEDIA_CODEC_VIDEO(self)->in.width = 176;
+ TMEDIA_CODEC_VIDEO(self)->in.height = TMEDIA_CODEC_VIDEO(self)->out.height = 144;
+ break;
+ case Simple_Profile_Level_2:
+ case Simple_Profile_Level_3:
+ default:
+ TMEDIA_CODEC_VIDEO(self)->out.width = TMEDIA_CODEC_VIDEO(self)->in.width = 352;
+ TMEDIA_CODEC_VIDEO(self)->in.height = TMEDIA_CODEC_VIDEO(self)->out.height = 288;
+ break;
+ }
+ }
+ else if(tsk_striequals(att_name, "imageattr")) {
+ unsigned in_width, in_height, out_width, out_height;
+ if(tmedia_parse_video_imageattr(att_value, TMEDIA_CODEC_VIDEO(self)->pref_size, &in_width, &in_height, &out_width, &out_height) != 0) {
+ return tsk_false;
+ }
+ TMEDIA_CODEC_VIDEO(self)->in.width = in_width;
+ TMEDIA_CODEC_VIDEO(self)->in.height = in_height;
+ TMEDIA_CODEC_VIDEO(self)->out.width = out_width;
+ TMEDIA_CODEC_VIDEO(self)->out.height = out_height;
+ }
+
+ return tsk_true;
}
char* tdav_codec_mp4ves_sdp_att_get(const tmedia_codec_t* _self, const char* att_name)
{
- tdav_codec_mp4ves_t *self = (tdav_codec_mp4ves_t *)_self;
-
- if(tsk_striequals(att_name, "fmtp")){
- char* fmtp = tsk_null;
- switch(_self->bl){//FIXME: deprecated
- case tmedia_bl_low:
- default:
- self->profile = Simple_Profile_Level_1;
- break;
- case tmedia_bl_medium:
- self->profile = Simple_Profile_Level_2;
- break;
- case tmedia_bl_hight:
- case tmedia_bl_unrestricted:
- self->profile = Simple_Profile_Level_3;
- break;
- }
- tsk_sprintf(&fmtp, "profile-level-id=%d", self->profile);
- return fmtp;
- }
- else if(tsk_striequals(att_name, "imageattr")){
- return tmedia_get_video_imageattr(TMEDIA_CODEC_VIDEO(self)->pref_size,
- TMEDIA_CODEC_VIDEO(self)->in.width, TMEDIA_CODEC_VIDEO(self)->in.height, TMEDIA_CODEC_VIDEO(self)->out.width, TMEDIA_CODEC_VIDEO(self)->out.height);
- }
- return tsk_null;
+ tdav_codec_mp4ves_t *self = (tdav_codec_mp4ves_t *)_self;
+
+ if(tsk_striequals(att_name, "fmtp")) {
+ char* fmtp = tsk_null;
+ switch(_self->bl) { //FIXME: deprecated
+ case tmedia_bl_low:
+ default:
+ self->profile = Simple_Profile_Level_1;
+ break;
+ case tmedia_bl_medium:
+ self->profile = Simple_Profile_Level_2;
+ break;
+ case tmedia_bl_hight:
+ case tmedia_bl_unrestricted:
+ self->profile = Simple_Profile_Level_3;
+ break;
+ }
+ tsk_sprintf(&fmtp, "profile-level-id=%d", self->profile);
+ return fmtp;
+ }
+ else if(tsk_striequals(att_name, "imageattr")) {
+ return tmedia_get_video_imageattr(TMEDIA_CODEC_VIDEO(self)->pref_size,
+ TMEDIA_CODEC_VIDEO(self)->in.width, TMEDIA_CODEC_VIDEO(self)->in.height, TMEDIA_CODEC_VIDEO(self)->out.width, TMEDIA_CODEC_VIDEO(self)->out.height);
+ }
+ return tsk_null;
}
/* ============ Internal functions ================= */
int tdav_codec_mp4ves_open_encoder(tdav_codec_mp4ves_t* self)
{
- int ret, size;
- int32_t max_bw_kpbs;
- if(!self->encoder.codec && !(self->encoder.codec = avcodec_find_encoder(CODEC_ID_MPEG4))){
- TSK_DEBUG_ERROR("Failed to find mp4v encoder");
- return -1;
- }
-
- if(self->encoder.context){
- TSK_DEBUG_ERROR("Encoder already opened");
- return -1;
- }
- self->encoder.context = avcodec_alloc_context();
- avcodec_get_context_defaults(self->encoder.context);
-
- self->encoder.context->pix_fmt = PIX_FMT_YUV420P;
- self->encoder.context->time_base.num = 1;
- self->encoder.context->time_base.den = TMEDIA_CODEC_VIDEO(self)->in.fps;
- self->encoder.context->width = (self->encoder.rotation == 90 || self->encoder.rotation == 270) ? TMEDIA_CODEC_VIDEO(self)->out.height : TMEDIA_CODEC_VIDEO(self)->out.width;
- self->encoder.context->height = (self->encoder.rotation == 90 || self->encoder.rotation == 270) ? TMEDIA_CODEC_VIDEO(self)->out.width : TMEDIA_CODEC_VIDEO(self)->out.height;
- self->encoder.context->mb_decision = FF_MB_DECISION_RD;
- self->encoder.context->noise_reduction = 250;
- self->encoder.context->flags |= CODEC_FLAG_QSCALE;
- self->encoder.context->global_quality = FF_QP2LAMBDA * self->encoder.quality;
-
- max_bw_kpbs = TSK_CLAMP(
- 0,
- tmedia_get_video_bandwidth_kbps_2(TMEDIA_CODEC_VIDEO(self)->out.width, TMEDIA_CODEC_VIDEO(self)->out.height, TMEDIA_CODEC_VIDEO(self)->out.fps),
- self->encoder.max_bw_kpbs
- );
- self->encoder.context->bit_rate = (max_bw_kpbs * 1024);// bps
- self->encoder.context->rtp_payload_size = MP4V_RTP_PAYLOAD_SIZE;
- self->encoder.context->opaque = tsk_null;
- self->encoder.context->profile = self->profile>>4;
- self->encoder.context->level = self->profile & 0x0F;
- self->encoder.context->gop_size = (TMEDIA_CODEC_VIDEO(self)->in.fps * MP4V_GOP_SIZE_IN_SECONDS);
- self->encoder.context->max_b_frames = 0;
- self->encoder.context->b_frame_strategy = 1;
+ int ret, size;
+ int32_t max_bw_kpbs;
+ if(!self->encoder.codec && !(self->encoder.codec = avcodec_find_encoder(CODEC_ID_MPEG4))) {
+ TSK_DEBUG_ERROR("Failed to find mp4v encoder");
+ return -1;
+ }
+
+ if(self->encoder.context) {
+ TSK_DEBUG_ERROR("Encoder already opened");
+ return -1;
+ }
+ self->encoder.context = avcodec_alloc_context();
+ avcodec_get_context_defaults(self->encoder.context);
+
+ self->encoder.context->pix_fmt = PIX_FMT_YUV420P;
+ self->encoder.context->time_base.num = 1;
+ self->encoder.context->time_base.den = TMEDIA_CODEC_VIDEO(self)->in.fps;
+ self->encoder.context->width = (self->encoder.rotation == 90 || self->encoder.rotation == 270) ? TMEDIA_CODEC_VIDEO(self)->out.height : TMEDIA_CODEC_VIDEO(self)->out.width;
+ self->encoder.context->height = (self->encoder.rotation == 90 || self->encoder.rotation == 270) ? TMEDIA_CODEC_VIDEO(self)->out.width : TMEDIA_CODEC_VIDEO(self)->out.height;
+ self->encoder.context->mb_decision = FF_MB_DECISION_RD;
+ self->encoder.context->noise_reduction = 250;
+ self->encoder.context->flags |= CODEC_FLAG_QSCALE;
+ self->encoder.context->global_quality = FF_QP2LAMBDA * self->encoder.quality;
+
+ max_bw_kpbs = TSK_CLAMP(
+ 0,
+ tmedia_get_video_bandwidth_kbps_2(TMEDIA_CODEC_VIDEO(self)->out.width, TMEDIA_CODEC_VIDEO(self)->out.height, TMEDIA_CODEC_VIDEO(self)->out.fps),
+ self->encoder.max_bw_kpbs
+ );
+ self->encoder.context->bit_rate = (max_bw_kpbs * 1024);// bps
+ self->encoder.context->rtp_payload_size = MP4V_RTP_PAYLOAD_SIZE;
+ self->encoder.context->opaque = tsk_null;
+ self->encoder.context->profile = self->profile>>4;
+ self->encoder.context->level = self->profile & 0x0F;
+ self->encoder.context->gop_size = (TMEDIA_CODEC_VIDEO(self)->in.fps * MP4V_GOP_SIZE_IN_SECONDS);
+ self->encoder.context->max_b_frames = 0;
+ self->encoder.context->b_frame_strategy = 1;
self->encoder.context->flags |= CODEC_FLAG_AC_PRED;
- // Picture (YUV 420)
- if(!(self->encoder.picture = avcodec_alloc_frame())){
- TSK_DEBUG_ERROR("Failed to create MP4V-ES encoder picture");
- return -2;
- }
- avcodec_get_frame_defaults(self->encoder.picture);
-
- size = avpicture_get_size(PIX_FMT_YUV420P, self->encoder.context->width, self->encoder.context->height);
- if(!(self->encoder.buffer = tsk_calloc(size, sizeof(uint8_t)))){
- TSK_DEBUG_ERROR("Failed to allocate MP4V-ES encoder buffer");
- return -2;
- }
-
- // Open encoder
- if((ret = avcodec_open(self->encoder.context, self->encoder.codec)) < 0){
- TSK_DEBUG_ERROR("Failed to open MP4V-ES encoder");
- return ret;
- }
-
- TSK_DEBUG_INFO("[MP4V-ES] bitrate=%d bps", self->encoder.context->bit_rate);
-
- return ret;
+ // Picture (YUV 420)
+ if(!(self->encoder.picture = avcodec_alloc_frame())) {
+ TSK_DEBUG_ERROR("Failed to create MP4V-ES encoder picture");
+ return -2;
+ }
+ avcodec_get_frame_defaults(self->encoder.picture);
+
+ size = avpicture_get_size(PIX_FMT_YUV420P, self->encoder.context->width, self->encoder.context->height);
+ if(!(self->encoder.buffer = tsk_calloc(size, sizeof(uint8_t)))) {
+ TSK_DEBUG_ERROR("Failed to allocate MP4V-ES encoder buffer");
+ return -2;
+ }
+
+ // Open encoder
+ if((ret = avcodec_open(self->encoder.context, self->encoder.codec)) < 0) {
+ TSK_DEBUG_ERROR("Failed to open MP4V-ES encoder");
+ return ret;
+ }
+
+ TSK_DEBUG_INFO("[MP4V-ES] bitrate=%d bps", self->encoder.context->bit_rate);
+
+ return ret;
}
int tdav_codec_mp4ves_open_decoder(tdav_codec_mp4ves_t* self)
{
- int ret, size;
-
- if(!self->decoder.codec && !(self->decoder.codec = avcodec_find_decoder(CODEC_ID_MPEG4))){
- TSK_DEBUG_ERROR("Failed to find MP4V-ES decoder");
- return -1;
- }
-
- if(self->decoder.context){
- TSK_DEBUG_ERROR("Decoder already opened");
- return -1;
- }
-
- self->decoder.context = avcodec_alloc_context();
- avcodec_get_context_defaults(self->decoder.context);
-
- self->decoder.context->pix_fmt = PIX_FMT_YUV420P;
- self->decoder.context->width = TMEDIA_CODEC_VIDEO(self)->out.width;
- self->decoder.context->height = TMEDIA_CODEC_VIDEO(self)->out.height;
-
- // Picture (YUV 420)
- if(!(self->decoder.picture = avcodec_alloc_frame())){
- TSK_DEBUG_ERROR("Failed to create decoder picture");
- return -2;
- }
- avcodec_get_frame_defaults(self->decoder.picture);
-
- size = avpicture_get_size(PIX_FMT_YUV420P, self->decoder.context->width, self->decoder.context->height);
- if(!(self->decoder.accumulator = tsk_calloc((size + FF_INPUT_BUFFER_PADDING_SIZE), sizeof(uint8_t)))){
- TSK_DEBUG_ERROR("Failed to allocate decoder buffer");
- return -2;
- }
-
- if(!(self->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(self->decoder.context, self->decoder.codec)) < 0){
- TSK_DEBUG_ERROR("Failed to open MP4V-ES decoder");
- return ret;
- }
-
+ int ret, size;
+
+ if(!self->decoder.codec && !(self->decoder.codec = avcodec_find_decoder(CODEC_ID_MPEG4))) {
+ TSK_DEBUG_ERROR("Failed to find MP4V-ES decoder");
+ return -1;
+ }
+
+ if(self->decoder.context) {
+ TSK_DEBUG_ERROR("Decoder already opened");
+ return -1;
+ }
+
+ self->decoder.context = avcodec_alloc_context();
+ avcodec_get_context_defaults(self->decoder.context);
+
+ self->decoder.context->pix_fmt = PIX_FMT_YUV420P;
+ self->decoder.context->width = TMEDIA_CODEC_VIDEO(self)->out.width;
+ self->decoder.context->height = TMEDIA_CODEC_VIDEO(self)->out.height;
+
+ // Picture (YUV 420)
+ if(!(self->decoder.picture = avcodec_alloc_frame())) {
+ TSK_DEBUG_ERROR("Failed to create decoder picture");
+ return -2;
+ }
+ avcodec_get_frame_defaults(self->decoder.picture);
+
+ size = avpicture_get_size(PIX_FMT_YUV420P, self->decoder.context->width, self->decoder.context->height);
+ if(!(self->decoder.accumulator = tsk_calloc((size + FF_INPUT_BUFFER_PADDING_SIZE), sizeof(uint8_t)))) {
+ TSK_DEBUG_ERROR("Failed to allocate decoder buffer");
+ return -2;
+ }
+
+ if(!(self->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(self->decoder.context, self->decoder.codec)) < 0) {
+ TSK_DEBUG_ERROR("Failed to open MP4V-ES decoder");
+ return ret;
+ }
+
self->decoder.last_seq = 0;
- return ret;
+ return ret;
}
int tdav_codec_mp4ves_close_encoder(tdav_codec_mp4ves_t* self)
{
- if(self->encoder.context){
- avcodec_close(self->encoder.context);
- av_free(self->encoder.context);
- self->encoder.context = tsk_null;
- }
- if(self->encoder.picture){
- av_free(self->encoder.picture);
- }
- if(self->encoder.buffer){
- TSK_FREE(self->encoder.buffer);
- }
- return 0;
+ if(self->encoder.context) {
+ avcodec_close(self->encoder.context);
+ av_free(self->encoder.context);
+ self->encoder.context = tsk_null;
+ }
+ if(self->encoder.picture) {
+ av_free(self->encoder.picture);
+ }
+ if(self->encoder.buffer) {
+ TSK_FREE(self->encoder.buffer);
+ }
+ return 0;
}
int tdav_codec_mp4ves_close_decoder(tdav_codec_mp4ves_t* self)
{
- if(self->decoder.context){
- avcodec_close(self->decoder.context);
- if(self->decoder.context->extradata){
- TSK_FREE(self->decoder.context->extradata);
- self->decoder.context->extradata_size = 0;
- }
- av_free(self->decoder.context);
- self->decoder.context = tsk_null;
- }
- if(self->decoder.picture){
- av_free(self->decoder.picture);
- self->decoder.picture = tsk_null;
- }
- if(self->decoder.accumulator){
- TSK_FREE(self->decoder.accumulator);
- }
-
- return 0;
+ if(self->decoder.context) {
+ avcodec_close(self->decoder.context);
+ if(self->decoder.context->extradata) {
+ TSK_FREE(self->decoder.context->extradata);
+ self->decoder.context->extradata_size = 0;
+ }
+ av_free(self->decoder.context);
+ self->decoder.context = tsk_null;
+ }
+ if(self->decoder.picture) {
+ av_free(self->decoder.picture);
+ self->decoder.picture = tsk_null;
+ }
+ if(self->decoder.accumulator) {
+ TSK_FREE(self->decoder.accumulator);
+ }
+
+ return 0;
}
static void tdav_codec_mp4ves_encap(tdav_codec_mp4ves_t* mp4v, const uint8_t* pdata, tsk_size_t size)
{
- uint32_t scode; // start code
-
- if(size <= 4/*32bits: start code size*/){
- TSK_DEBUG_ERROR("Too short");
- return;
- }
- // first 32bits
- scode = tnet_htonl_2(pdata);
-
-/* RFC 3016 - 3.3 Examples of packetized MPEG-4 Visual bitstream
-
- VS= Visual Object Sequence
- VO= Visual Object
- VOL= Visual Object Layer
- VOP= Visual Object Plane
- GOV= Group of Visual Object Plane
- VP= Video Plane
-
- +------+------+------+------+
-(a) | RTP | VS | VO | VOL |
- |header|header|header|header|
- +------+------+------+------+
-
- +------+------+------+------+------------+
-(b) | RTP | VS | VO | VOL |Video Packet|
- |header|header|header|header| |
- +------+------+------+------+------------+
-
- +------+-----+------------------+
-(c) | RTP | GOV |Video Object Plane|
- |header| | |
- +------+-----+------------------+
-
- +------+------+------------+ +------+------+------------+
-(d) | RTP | VOP |Video Packet| | RTP | VP |Video Packet|
- |header|header| (1) | |header|header| (2) |
- +------+------+------------+ +------+------+------------+
-
- +------+------+------------+------+------------+------+------------+
-(e) | RTP | VP |Video Packet| VP |Video Packet| VP |Video Packet|
- |header|header| (1) |header| (2) |header| (3) |
- +------+------+------------+------+------------+------+------------+
-
- +------+------+------------+ +------+------------+
-(f) | RTP | VOP |VOP fragment| | RTP |VOP fragment|
- |header|header| (1) | |header| (2) | ___
- +------+------+------------+ +------+------------+
-
- Figure 2 - Examples of RTP packetized MPEG-4 Visual bitstream
-*/
-
-/* RFC 3016 - 3.2 Fragmentation of MPEG-4 Visual bitstream
-
- A fragmented MPEG-4 Visual bitstream is mapped directly onto the RTP
- payload without any addition of extra header fields or any removal of
- Visual syntax elements. The Combined Configuration/Elementary
- streams mode is used.
-
- In the following, header means one of the following:
-
- - Configuration information (Visual Object Sequence Header, Visual
- Object Header and Video Object Layer Header)
- - visual_object_sequence_end_code
- - The header of the entry point function for an elementary stream
- (Group_of_VideoObjectPlane() or the header of VideoObjectPlane(),
- video_plane_with_short_header(), MeshObject() or FaceObject())
- - The video packet header (video_packet_header() excluding
- next_resync_marker())
- - The header of gob_layer()
- See 6.2.1 "Start codes" of ISO/IEC 14496-2 [2][9][4] for the
- definition of the configuration information and the entry point
- functions.
-*/
-
- switch(scode){
- case visual_object_sequence_start_code:
- case visual_object_start_code:
- case user_data_start_code:
- case video_object_layer_start_code:
- case group_of_vop_start_code:
- case vop_start_code:
- {
- register uint32_t i, last_index = 0;
- int startcode = 0xffffffff;
-
- if(scode == visual_object_sequence_start_code && size >=5){
- //uint8_t profile_and_level_indication = pdata[4]; /* IEC 14496-2: 6.3.2 Visual Object Sequence and Visual Object */
- // TSK_DEBUG_INFO("profile_and_level_indication=%d", profile_and_level_indication);
- }
-
- if(size < MP4V_RTP_PAYLOAD_SIZE){
- goto last;
- }
-
- for(i = 4; i<(size - 4); i++){
- startcode = (startcode <<8) | pdata[i];
- switch(startcode){
- case visual_object_sequence_start_code:
- case group_of_vop_start_code:
- case vop_start_code:
- tdav_codec_mp4ves_rtp_callback(mp4v, pdata + last_index, (i - last_index), (last_index == size));
- last_index = i;
- }
- }
+ uint32_t scode; // start code
+
+ if(size <= 4/*32bits: start code size*/) {
+ TSK_DEBUG_ERROR("Too short");
+ return;
+ }
+ // first 32bits
+ scode = tnet_htonl_2(pdata);
+
+ /* RFC 3016 - 3.3 Examples of packetized MPEG-4 Visual bitstream
+
+ VS= Visual Object Sequence
+ VO= Visual Object
+ VOL= Visual Object Layer
+ VOP= Visual Object Plane
+ GOV= Group of Visual Object Plane
+ VP= Video Plane
+
+ +------+------+------+------+
+ (a) | RTP | VS | VO | VOL |
+ |header|header|header|header|
+ +------+------+------+------+
+
+ +------+------+------+------+------------+
+ (b) | RTP | VS | VO | VOL |Video Packet|
+ |header|header|header|header| |
+ +------+------+------+------+------------+
+
+ +------+-----+------------------+
+ (c) | RTP | GOV |Video Object Plane|
+ |header| | |
+ +------+-----+------------------+
+
+ +------+------+------------+ +------+------+------------+
+ (d) | RTP | VOP |Video Packet| | RTP | VP |Video Packet|
+ |header|header| (1) | |header|header| (2) |
+ +------+------+------------+ +------+------+------------+
+
+ +------+------+------------+------+------------+------+------------+
+ (e) | RTP | VP |Video Packet| VP |Video Packet| VP |Video Packet|
+ |header|header| (1) |header| (2) |header| (3) |
+ +------+------+------------+------+------------+------+------------+
+
+ +------+------+------------+ +------+------------+
+ (f) | RTP | VOP |VOP fragment| | RTP |VOP fragment|
+ |header|header| (1) | |header| (2) | ___
+ +------+------+------------+ +------+------------+
+
+ Figure 2 - Examples of RTP packetized MPEG-4 Visual bitstream
+ */
+
+ /* RFC 3016 - 3.2 Fragmentation of MPEG-4 Visual bitstream
+
+ A fragmented MPEG-4 Visual bitstream is mapped directly onto the RTP
+ payload without any addition of extra header fields or any removal of
+ Visual syntax elements. The Combined Configuration/Elementary
+ streams mode is used.
+
+ In the following, header means one of the following:
+
+ - Configuration information (Visual Object Sequence Header, Visual
+ Object Header and Video Object Layer Header)
+ - visual_object_sequence_end_code
+ - The header of the entry point function for an elementary stream
+ (Group_of_VideoObjectPlane() or the header of VideoObjectPlane(),
+ video_plane_with_short_header(), MeshObject() or FaceObject())
+ - The video packet header (video_packet_header() excluding
+ next_resync_marker())
+ - The header of gob_layer()
+ See 6.2.1 "Start codes" of ISO/IEC 14496-2 [2][9][4] for the
+ definition of the configuration information and the entry point
+ functions.
+ */
+
+ switch(scode) {
+ case visual_object_sequence_start_code:
+ case visual_object_start_code:
+ case user_data_start_code:
+ case video_object_layer_start_code:
+ case group_of_vop_start_code:
+ case vop_start_code: {
+ register uint32_t i, last_index = 0;
+ int startcode = 0xffffffff;
+
+ if(scode == visual_object_sequence_start_code && size >=5) {
+ //uint8_t profile_and_level_indication = pdata[4]; /* IEC 14496-2: 6.3.2 Visual Object Sequence and Visual Object */
+ // TSK_DEBUG_INFO("profile_and_level_indication=%d", profile_and_level_indication);
+ }
+
+ if(size < MP4V_RTP_PAYLOAD_SIZE) {
+ goto last;
+ }
+
+ for(i = 4; i<(size - 4); i++) {
+ startcode = (startcode <<8) | pdata[i];
+ switch(startcode) {
+ case visual_object_sequence_start_code:
+ case group_of_vop_start_code:
+ case vop_start_code:
+ tdav_codec_mp4ves_rtp_callback(mp4v, pdata + last_index, (i - last_index), (last_index == size));
+ last_index = i;
+ }
+ }
last:
- if(last_index < size){
- tdav_codec_mp4ves_rtp_callback(mp4v, pdata + last_index, (size - last_index), tsk_true);
- }
- break;
- }
- default:
- TSK_DEBUG_ERROR("%x is an invalide start code", scode);
- break;
- }
+ if(last_index < size) {
+ tdav_codec_mp4ves_rtp_callback(mp4v, pdata + last_index, (size - last_index), tsk_true);
+ }
+ break;
+ }
+ default:
+ TSK_DEBUG_ERROR("%x is an invalide start code", scode);
+ break;
+ }
}
static void tdav_codec_mp4ves_rtp_callback(tdav_codec_mp4ves_t *mp4v, const void *data, tsk_size_t size, tsk_bool_t marker)
{
- // Send data over the network
- if(TMEDIA_CODEC_VIDEO(mp4v)->out.callback){
- TMEDIA_CODEC_VIDEO(mp4v)->out.result.buffer.ptr = data;
- TMEDIA_CODEC_VIDEO(mp4v)->out.result.buffer.size = size;
- TMEDIA_CODEC_VIDEO(mp4v)->out.result.duration = (uint32_t)((1./(double)TMEDIA_CODEC_VIDEO(mp4v)->out.fps) * TMEDIA_CODEC(mp4v)->plugin->rate);
- TMEDIA_CODEC_VIDEO(mp4v)->out.result.last_chunck = marker;
- TMEDIA_CODEC_VIDEO(mp4v)->out.callback(&TMEDIA_CODEC_VIDEO(mp4v)->out.result);
- }
+ // Send data over the network
+ if(TMEDIA_CODEC_VIDEO(mp4v)->out.callback) {
+ TMEDIA_CODEC_VIDEO(mp4v)->out.result.buffer.ptr = data;
+ TMEDIA_CODEC_VIDEO(mp4v)->out.result.buffer.size = size;
+ TMEDIA_CODEC_VIDEO(mp4v)->out.result.duration = (uint32_t)((1./(double)TMEDIA_CODEC_VIDEO(mp4v)->out.fps) * TMEDIA_CODEC(mp4v)->plugin->rate);
+ TMEDIA_CODEC_VIDEO(mp4v)->out.result.last_chunck = marker;
+ TMEDIA_CODEC_VIDEO(mp4v)->out.callback(&TMEDIA_CODEC_VIDEO(mp4v)->out.result);
+ }
}
@@ -748,70 +743,68 @@ static void tdav_codec_mp4ves_rtp_callback(tdav_codec_mp4ves_t *mp4v, const void
/* constructor */
static tsk_object_t* tdav_codec_mp4ves_ctor(tsk_object_t * _self, va_list * app)
{
- tdav_codec_mp4ves_t *self = _self;
- if(self){
- /* init base: called by tmedia_codec_create() */
- /* init self */
- self->profile = DEFAULT_PROFILE_LEVEL_ID;
- self->encoder.quality = 1;
- self->encoder.max_bw_kpbs = tmedia_defaults_get_bandwidth_video_upload_max();
- }
- return self;
+ tdav_codec_mp4ves_t *self = _self;
+ if(self) {
+ /* init base: called by tmedia_codec_create() */
+ /* init self */
+ self->profile = DEFAULT_PROFILE_LEVEL_ID;
+ self->encoder.quality = 1;
+ self->encoder.max_bw_kpbs = tmedia_defaults_get_bandwidth_video_upload_max();
+ }
+ return self;
}
/* destructor */
static tsk_object_t* tdav_codec_mp4ves_dtor(tsk_object_t * _self)
-{
- tdav_codec_mp4ves_t *self = _self;
- if(self){
- /* deinit base */
- tmedia_codec_video_deinit(self); // will close the codec if opened
- /* deinit self */
- TSK_FREE(self->rtp.ptr);
- self->rtp.size = 0;
- }
-
- return self;
+{
+ tdav_codec_mp4ves_t *self = _self;
+ if(self) {
+ /* deinit base */
+ tmedia_codec_video_deinit(self); // will close the codec if opened
+ /* deinit self */
+ TSK_FREE(self->rtp.ptr);
+ self->rtp.size = 0;
+ }
+
+ return self;
}
/* object definition */
-static const tsk_object_def_t tdav_codec_mp4ves_def_s =
-{
- sizeof(tdav_codec_mp4ves_t),
- tdav_codec_mp4ves_ctor,
- tdav_codec_mp4ves_dtor,
- tmedia_codec_cmp,
+static const tsk_object_def_t tdav_codec_mp4ves_def_s = {
+ sizeof(tdav_codec_mp4ves_t),
+ tdav_codec_mp4ves_ctor,
+ tdav_codec_mp4ves_dtor,
+ tmedia_codec_cmp,
};
/* plugin definition*/
-static const tmedia_codec_plugin_def_t tdav_codec_mp4ves_plugin_def_s =
-{
- &tdav_codec_mp4ves_def_s,
-
- tmedia_video,
- tmedia_codec_id_mp4ves_es,
- "MP4V-ES",
- "MP4V-ES Codec",
- TMEDIA_CODEC_FORMAT_MP4V_ES,
- tsk_true,
- 90000, // rate
-
- /* audio */
- { 0 },
-
- /* video (width, height, fps) */
- {176, 144, 0},// fps is @deprecated
-
- tdav_codec_mp4ves_set,
- tdav_codec_mp4ves_open,
- tdav_codec_mp4ves_close,
- tdav_codec_mp4ves_encode,
- tdav_codec_mp4ves_decode,
- tdav_codec_mp4ves_sdp_att_match,
- tdav_codec_mp4ves_sdp_att_get
+static const tmedia_codec_plugin_def_t tdav_codec_mp4ves_plugin_def_s = {
+ &tdav_codec_mp4ves_def_s,
+
+ tmedia_video,
+ tmedia_codec_id_mp4ves_es,
+ "MP4V-ES",
+ "MP4V-ES Codec",
+ TMEDIA_CODEC_FORMAT_MP4V_ES,
+ tsk_true,
+ 90000, // rate
+
+ /* audio */
+ { 0 },
+
+ /* video (width, height, fps) */
+ {176, 144, 0},// fps is @deprecated
+
+ tdav_codec_mp4ves_set,
+ tdav_codec_mp4ves_open,
+ tdav_codec_mp4ves_close,
+ tdav_codec_mp4ves_encode,
+ tdav_codec_mp4ves_decode,
+ tdav_codec_mp4ves_sdp_att_match,
+ tdav_codec_mp4ves_sdp_att_get
};
const tmedia_codec_plugin_def_t *tdav_codec_mp4ves_plugin_def_t = &tdav_codec_mp4ves_plugin_def_s;
tsk_bool_t tdav_codec_ffmpeg_mp4ves_is_supported()
{
- return (avcodec_find_encoder(CODEC_ID_MPEG4) && avcodec_find_decoder(CODEC_ID_MPEG4));
+ return (avcodec_find_encoder(CODEC_ID_MPEG4) && avcodec_find_decoder(CODEC_ID_MPEG4));
}
#endif /* HAVE_FFMPEG */
diff --git a/tinyDAV/src/codecs/msrp/tdav_codec_msrp.c b/tinyDAV/src/codecs/msrp/tdav_codec_msrp.c
index 5b72ded..a39e90b 100755
--- a/tinyDAV/src/codecs/msrp/tdav_codec_msrp.c
+++ b/tinyDAV/src/codecs/msrp/tdav_codec_msrp.c
@@ -1,19 +1,19 @@
/*
* Copyright (C) 2010-2011 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.
*
@@ -38,8 +38,9 @@
#define tdav_codec_msrp_decode tsk_null
static tsk_bool_t tdav_codec_msrp_sdp_att_match(const tmedia_codec_t* codec, const char* att_name, const char* att_value)
-{ /* always match */
- return tsk_true;
+{
+ /* always match */
+ return tsk_true;
}
//
@@ -49,58 +50,56 @@ static tsk_bool_t tdav_codec_msrp_sdp_att_match(const tmedia_codec_t* codec, con
/* constructor */
static tsk_object_t* tdav_codec_msrp_ctor(tsk_object_t * self, va_list * app)
{
- tdav_codec_msrp_t *msrp = self;
- if(msrp){
- /* init base: called by tmedia_codec_create() */
- /* init self */
- }
- return self;
+ tdav_codec_msrp_t *msrp = self;
+ if(msrp) {
+ /* init base: called by tmedia_codec_create() */
+ /* init self */
+ }
+ return self;
}
/* destructor */
static tsk_object_t* tdav_codec_msrp_dtor(tsk_object_t * self)
-{
- tdav_codec_msrp_t *msrp = self;
- if(msrp){
- /* deinit base */
- tmedia_codec_msrp_deinit(msrp);
- /* deinit self */
- }
+{
+ tdav_codec_msrp_t *msrp = self;
+ if(msrp) {
+ /* deinit base */
+ tmedia_codec_msrp_deinit(msrp);
+ /* deinit self */
+ }
- return self;
+ return self;
}
/* object definition */
-static const tsk_object_def_t tdav_codec_msrp_def_s =
-{
- sizeof(tdav_codec_msrp_t),
- tdav_codec_msrp_ctor,
- tdav_codec_msrp_dtor,
- tmedia_codec_cmp,
+static const tsk_object_def_t tdav_codec_msrp_def_s = {
+ sizeof(tdav_codec_msrp_t),
+ tdav_codec_msrp_ctor,
+ tdav_codec_msrp_dtor,
+ tmedia_codec_cmp,
};
/* plugin definition*/
-static const tmedia_codec_plugin_def_t tdav_codec_msrp_plugin_def_s =
-{
- &tdav_codec_msrp_def_s,
+static const tmedia_codec_plugin_def_t tdav_codec_msrp_plugin_def_s = {
+ &tdav_codec_msrp_def_s,
+
+ tmedia_msrp,
+ tmedia_codec_id_none, // fake codec without real id
+ "message",
+ "MSRP fake codec",
+ TMEDIA_CODEC_FORMAT_MSRP,
+ tsk_false,
+ 0, // rate
- tmedia_msrp,
- tmedia_codec_id_none, // fake codec without real id
- "message",
- "MSRP fake codec",
- TMEDIA_CODEC_FORMAT_MSRP,
- tsk_false,
- 0, // rate
-
- /* audio */
- {0},
+ /* audio */
+ {0},
- /* video */
- {0},
+ /* video */
+ {0},
- tsk_null, // set()
- tdav_codec_msrp_open,
- tdav_codec_msrp_close,
- tdav_codec_msrp_encode,
- tdav_codec_msrp_decode,
- tdav_codec_msrp_sdp_att_match,
- tdav_codec_msrp_sdp_att_get
+ tsk_null, // set()
+ tdav_codec_msrp_open,
+ tdav_codec_msrp_close,
+ tdav_codec_msrp_encode,
+ tdav_codec_msrp_decode,
+ tdav_codec_msrp_sdp_att_match,
+ tdav_codec_msrp_sdp_att_get
};
const tmedia_codec_plugin_def_t *tdav_codec_msrp_plugin_def_t = &tdav_codec_msrp_plugin_def_s;
diff --git a/tinyDAV/src/codecs/opus/tdav_codec_opus.c b/tinyDAV/src/codecs/opus/tdav_codec_opus.c
index 355fc73..4e9392b 100755
--- a/tinyDAV/src/codecs/opus/tdav_codec_opus.c
+++ b/tinyDAV/src/codecs/opus/tdav_codec_opus.c
@@ -7,12 +7,12 @@
* 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.
*
@@ -50,232 +50,237 @@
# define TDAV_OPUS_DTX_ENABLED 0
#endif
-typedef struct tdav_codec_opus_s
-{
- TMEDIA_DECLARE_CODEC_AUDIO;
-
- struct {
- OpusEncoder *inst;
- } encoder;
-
- struct {
- OpusDecoder *inst;
- opus_int16 buff[TDAV_OPUS_MAX_FRAME_SIZE_IN_SAMPLES];
- tsk_bool_t fec_enabled;
- tsk_bool_t dtx_enabled;
- uint16_t last_seq;
- } decoder;
+typedef struct tdav_codec_opus_s {
+ TMEDIA_DECLARE_CODEC_AUDIO;
+
+ struct {
+ OpusEncoder *inst;
+ } encoder;
+
+ struct {
+ OpusDecoder *inst;
+ opus_int16 buff[TDAV_OPUS_MAX_FRAME_SIZE_IN_SAMPLES];
+ tsk_bool_t fec_enabled;
+ tsk_bool_t dtx_enabled;
+ uint16_t last_seq;
+ } decoder;
}
tdav_codec_opus_t;
static tsk_bool_t _tdav_codec_opus_rate_is_valid(const int32_t rate)
{
- switch(rate){
- case 8000: case 12000: case 16000: case 24000: case 48000: return tsk_true;
- default: return tsk_false;
- }
+ switch(rate) {
+ case 8000:
+ case 12000:
+ case 16000:
+ case 24000:
+ case 48000:
+ return tsk_true;
+ default:
+ return tsk_false;
+ }
}
static int tdav_codec_opus_open(tmedia_codec_t* self)
{
- tdav_codec_opus_t* opus = (tdav_codec_opus_t*)self;
- int opus_err;
-
- if(!opus){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- // Initialize the decoder
- if(!opus->decoder.inst){
- TSK_DEBUG_INFO("[OPUS] Open decoder: rate=%d, channels=%d", (int)self->in.rate, (int)TMEDIA_CODEC_AUDIO(self)->in.channels);
- if(!(opus->decoder.inst = opus_decoder_create((opus_int32)self->in.rate, (int)TMEDIA_CODEC_AUDIO(self)->in.channels, &opus_err)) || opus_err != OPUS_OK){
- TSK_DEBUG_ERROR("Failed to create Opus decoder(rate=%d, channels=%d) instance with error code=%d.", (int)self->in.rate, (int)TMEDIA_CODEC_AUDIO(self)->in.channels, opus_err);
- return -2;
- }
- }
+ tdav_codec_opus_t* opus = (tdav_codec_opus_t*)self;
+ int opus_err;
+
+ if(!opus) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ // Initialize the decoder
+ if(!opus->decoder.inst) {
+ TSK_DEBUG_INFO("[OPUS] Open decoder: rate=%d, channels=%d", (int)self->in.rate, (int)TMEDIA_CODEC_AUDIO(self)->in.channels);
+ if(!(opus->decoder.inst = opus_decoder_create((opus_int32)self->in.rate, (int)TMEDIA_CODEC_AUDIO(self)->in.channels, &opus_err)) || opus_err != OPUS_OK) {
+ TSK_DEBUG_ERROR("Failed to create Opus decoder(rate=%d, channels=%d) instance with error code=%d.", (int)self->in.rate, (int)TMEDIA_CODEC_AUDIO(self)->in.channels, opus_err);
+ return -2;
+ }
+ }
opus->decoder.last_seq = 0;
- // Initialize the encoder
- if(!opus->encoder.inst){
- TSK_DEBUG_INFO("[OPUS] Open encoder: rate=%d, channels=%d", (int)self->out.rate, (int)TMEDIA_CODEC_AUDIO(self)->out.channels);
- if(!(opus->encoder.inst = opus_encoder_create((opus_int32)self->out.rate, (int)TMEDIA_CODEC_AUDIO(self)->out.channels, OPUS_APPLICATION_VOIP, &opus_err)) || opus_err != OPUS_OK){
- TSK_DEBUG_ERROR("Failed to create Opus decoder(rate=%d, channels=%d) instance with error code=%d.", (int)self->out.rate, (int)TMEDIA_CODEC_AUDIO(self)->out.channels, opus_err);
- return -2;
- }
- }
+ // Initialize the encoder
+ if(!opus->encoder.inst) {
+ TSK_DEBUG_INFO("[OPUS] Open encoder: rate=%d, channels=%d", (int)self->out.rate, (int)TMEDIA_CODEC_AUDIO(self)->out.channels);
+ if(!(opus->encoder.inst = opus_encoder_create((opus_int32)self->out.rate, (int)TMEDIA_CODEC_AUDIO(self)->out.channels, OPUS_APPLICATION_VOIP, &opus_err)) || opus_err != OPUS_OK) {
+ TSK_DEBUG_ERROR("Failed to create Opus decoder(rate=%d, channels=%d) instance with error code=%d.", (int)self->out.rate, (int)TMEDIA_CODEC_AUDIO(self)->out.channels, opus_err);
+ return -2;
+ }
+ }
#if TDAV_UNDER_MOBILE /* iOS, Android and WP8 */
- opus_encoder_ctl(opus->encoder.inst, OPUS_SET_COMPLEXITY(3));
+ opus_encoder_ctl(opus->encoder.inst, OPUS_SET_COMPLEXITY(3));
#endif
opus_encoder_ctl(opus->encoder.inst, OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE));
- return 0;
+ return 0;
}
static int tdav_codec_opus_close(tmedia_codec_t* self)
{
- tdav_codec_opus_t* opus = (tdav_codec_opus_t*)self;
+ tdav_codec_opus_t* opus = (tdav_codec_opus_t*)self;
- (void)(opus);
-
- /* resources will be freed by the dctor() */
-
- return 0;
+ (void)(opus);
+
+ /* resources will be freed by the dctor() */
+
+ return 0;
}
static tsk_size_t tdav_codec_opus_encode(tmedia_codec_t* self, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size)
{
- tdav_codec_opus_t* opus = (tdav_codec_opus_t*)self;
- opus_int32 ret;
-
- if(!self || !in_data || !in_size || !out_data){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- if(!opus->encoder.inst){
- TSK_DEBUG_ERROR("Encoder not ready");
- return 0;
- }
-
- // we're sure that the output (encoded) size cannot be higher than the input (raw)
- if(*out_max_size < in_size){
- if(!(*out_data = tsk_realloc(*out_data, in_size))){
- TSK_DEBUG_ERROR("Failed to allocate buffer with size = %u", in_size);
- *out_max_size = 0;
- return 0;
- }
- *out_max_size = in_size;
- }
-
- ret = opus_encode(opus->encoder.inst,
- (const opus_int16 *)in_data, (int)(in_size >> 1),
- (unsigned char *)*out_data, (opus_int32)*out_max_size);
-
- if(ret < 0){
- TSK_DEBUG_ERROR("opus_encode() failed with error code = %d", ret);
- return 0;
- }
-
- return (tsk_size_t)ret;
+ tdav_codec_opus_t* opus = (tdav_codec_opus_t*)self;
+ opus_int32 ret;
+
+ if(!self || !in_data || !in_size || !out_data) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ if(!opus->encoder.inst) {
+ TSK_DEBUG_ERROR("Encoder not ready");
+ return 0;
+ }
+
+ // we're sure that the output (encoded) size cannot be higher than the input (raw)
+ if(*out_max_size < in_size) {
+ if(!(*out_data = tsk_realloc(*out_data, in_size))) {
+ TSK_DEBUG_ERROR("Failed to allocate buffer with size = %u", in_size);
+ *out_max_size = 0;
+ return 0;
+ }
+ *out_max_size = in_size;
+ }
+
+ ret = opus_encode(opus->encoder.inst,
+ (const opus_int16 *)in_data, (int)(in_size >> 1),
+ (unsigned char *)*out_data, (opus_int32)*out_max_size);
+
+ if(ret < 0) {
+ TSK_DEBUG_ERROR("opus_encode() failed with error code = %d", ret);
+ return 0;
+ }
+
+ return (tsk_size_t)ret;
}
static tsk_size_t tdav_codec_opus_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)
{
- tdav_codec_opus_t* opus = (tdav_codec_opus_t*)self;
- int frame_size;
- const trtp_rtp_header_t* rtp_hdr = proto_hdr;
-
- if(!self || !in_data || !in_size || !out_data){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- if(!opus->decoder.inst){
- TSK_DEBUG_ERROR("Decoder not ready");
- return 0;
- }
-
- /* Packet loss? */
- if(opus->decoder.last_seq != (rtp_hdr->seq_num - 1) && opus->decoder.last_seq){
- if(opus->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("[Opus] Packet loss, seq_num=%d", rtp_hdr->seq_num);
- opus_decode(opus->decoder.inst, tsk_null/*packet loss*/, (opus_int32)0, opus->decoder.buff, TDAV_OPUS_MAX_FRAME_SIZE_IN_SAMPLES, opus->decoder.fec_enabled);
- }
- opus->decoder.last_seq = rtp_hdr->seq_num;
-
- frame_size = opus_decode(opus->decoder.inst, (const unsigned char *)in_data, (opus_int32)in_size, opus->decoder.buff, TDAV_OPUS_MAX_FRAME_SIZE_IN_SAMPLES, opus->decoder.fec_enabled ? 1 : 0);
- if(frame_size > 0){
- tsk_size_t frame_size_inbytes = (frame_size << 1);
- if(*out_max_size < frame_size_inbytes){
- if(!(*out_data = tsk_realloc(*out_data, frame_size_inbytes))){
- TSK_DEBUG_ERROR("Failed to allocate new buffer");
- *out_max_size = 0;
- return 0;
- }
- *out_max_size = frame_size_inbytes;
- }
- memcpy(*out_data, opus->decoder.buff, frame_size_inbytes);
- return frame_size_inbytes;
- }
- else{
- return 0;
- }
+ tdav_codec_opus_t* opus = (tdav_codec_opus_t*)self;
+ int frame_size;
+ const trtp_rtp_header_t* rtp_hdr = proto_hdr;
+
+ if(!self || !in_data || !in_size || !out_data) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ if(!opus->decoder.inst) {
+ TSK_DEBUG_ERROR("Decoder not ready");
+ return 0;
+ }
+
+ /* Packet loss? */
+ if(opus->decoder.last_seq != (rtp_hdr->seq_num - 1) && opus->decoder.last_seq) {
+ if(opus->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("[Opus] Packet loss, seq_num=%d", rtp_hdr->seq_num);
+ opus_decode(opus->decoder.inst, tsk_null/*packet loss*/, (opus_int32)0, opus->decoder.buff, TDAV_OPUS_MAX_FRAME_SIZE_IN_SAMPLES, opus->decoder.fec_enabled);
+ }
+ opus->decoder.last_seq = rtp_hdr->seq_num;
+
+ frame_size = opus_decode(opus->decoder.inst, (const unsigned char *)in_data, (opus_int32)in_size, opus->decoder.buff, TDAV_OPUS_MAX_FRAME_SIZE_IN_SAMPLES, opus->decoder.fec_enabled ? 1 : 0);
+ if(frame_size > 0) {
+ tsk_size_t frame_size_inbytes = (frame_size << 1);
+ if(*out_max_size < frame_size_inbytes) {
+ if(!(*out_data = tsk_realloc(*out_data, frame_size_inbytes))) {
+ TSK_DEBUG_ERROR("Failed to allocate new buffer");
+ *out_max_size = 0;
+ return 0;
+ }
+ *out_max_size = frame_size_inbytes;
+ }
+ memcpy(*out_data, opus->decoder.buff, frame_size_inbytes);
+ return frame_size_inbytes;
+ }
+ else {
+ return 0;
+ }
}
static tsk_bool_t tdav_codec_opus_sdp_att_match(const tmedia_codec_t* codec, const char* att_name, const char* att_value)
{
- tdav_codec_opus_t* opus = (tdav_codec_opus_t*)codec;
-
- if(!opus){
- TSK_DEBUG_ERROR("Invalid parameter");
- return tsk_false;
- }
-
- TSK_DEBUG_INFO("[OPUS] Trying to match [%s:%s]", att_name, att_value);
-
- if(tsk_striequals(att_name, "fmtp")){
- int val_int;
- tsk_params_L_t* params;
- /* e.g. FIXME */
- if((params = tsk_params_fromstring(att_value, ";", tsk_true))){
- tsk_bool_t ret = tsk_false;
- /* === maxplaybackrate ===*/
- if((val_int = tsk_params_get_param_value_as_int(params, "maxplaybackrate")) != -1){
- if(!_tdav_codec_opus_rate_is_valid(val_int)){
- TSK_DEBUG_ERROR("[OPUS] %d not valid as maxplaybackrate value", val_int);
- goto done;
- }
- TMEDIA_CODEC(opus)->out.rate = TSK_MIN((int32_t)TMEDIA_CODEC(opus)->out.rate, val_int);
- TMEDIA_CODEC_AUDIO(opus)->out.timestamp_multiplier = tmedia_codec_audio_get_timestamp_multiplier(codec->id, codec->out.rate);
- }
- /* === sprop-maxcapturerate ===*/
- if((val_int = tsk_params_get_param_value_as_int(params, "sprop-maxcapturerate")) != -1){
- if(!_tdav_codec_opus_rate_is_valid(val_int)){
- TSK_DEBUG_ERROR("[OPUS] %d not valid as sprop-maxcapturerate value", val_int);
- goto done;
- }
- TMEDIA_CODEC(opus)->in.rate = TSK_MIN((int32_t)TMEDIA_CODEC(opus)->in.rate, val_int);
- TMEDIA_CODEC_AUDIO(opus)->in.timestamp_multiplier = tmedia_codec_audio_get_timestamp_multiplier(codec->id, codec->in.rate);
- }
- ret = tsk_true;
+ tdav_codec_opus_t* opus = (tdav_codec_opus_t*)codec;
+
+ if(!opus) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return tsk_false;
+ }
+
+ TSK_DEBUG_INFO("[OPUS] Trying to match [%s:%s]", att_name, att_value);
+
+ if(tsk_striequals(att_name, "fmtp")) {
+ int val_int;
+ tsk_params_L_t* params;
+ /* e.g. FIXME */
+ if((params = tsk_params_fromstring(att_value, ";", tsk_true))) {
+ tsk_bool_t ret = tsk_false;
+ /* === maxplaybackrate ===*/
+ if((val_int = tsk_params_get_param_value_as_int(params, "maxplaybackrate")) != -1) {
+ if(!_tdav_codec_opus_rate_is_valid(val_int)) {
+ TSK_DEBUG_ERROR("[OPUS] %d not valid as maxplaybackrate value", val_int);
+ goto done;
+ }
+ TMEDIA_CODEC(opus)->out.rate = TSK_MIN((int32_t)TMEDIA_CODEC(opus)->out.rate, val_int);
+ TMEDIA_CODEC_AUDIO(opus)->out.timestamp_multiplier = tmedia_codec_audio_get_timestamp_multiplier(codec->id, codec->out.rate);
+ }
+ /* === sprop-maxcapturerate ===*/
+ if((val_int = tsk_params_get_param_value_as_int(params, "sprop-maxcapturerate")) != -1) {
+ if(!_tdav_codec_opus_rate_is_valid(val_int)) {
+ TSK_DEBUG_ERROR("[OPUS] %d not valid as sprop-maxcapturerate value", val_int);
+ goto done;
+ }
+ TMEDIA_CODEC(opus)->in.rate = TSK_MIN((int32_t)TMEDIA_CODEC(opus)->in.rate, val_int);
+ TMEDIA_CODEC_AUDIO(opus)->in.timestamp_multiplier = tmedia_codec_audio_get_timestamp_multiplier(codec->id, codec->in.rate);
+ }
+ ret = tsk_true;
done:
- TSK_OBJECT_SAFE_FREE(params);
- return ret;
- }
- }
+ TSK_OBJECT_SAFE_FREE(params);
+ return ret;
+ }
+ }
- return tsk_true;
+ return tsk_true;
}
static char* tdav_codec_opus_sdp_att_get(const tmedia_codec_t* codec, const char* att_name)
{
- tdav_codec_opus_t* opus = (tdav_codec_opus_t*)codec;
-
- if(!opus){
- TSK_DEBUG_ERROR("Invalid parameter");
- return tsk_null;
- }
-
- if(tsk_striequals(att_name, "fmtp")){
- char* fmtp = tsk_null;
- tsk_sprintf(&fmtp, "maxplaybackrate=%d; sprop-maxcapturerate=%d; stereo=%d; sprop-stereo=%d; useinbandfec=%d; usedtx=%d",
- TMEDIA_CODEC(opus)->in.rate,
- TMEDIA_CODEC(opus)->out.rate,
- (TMEDIA_CODEC_AUDIO(opus)->in.channels == 2) ? 1 : 0,
- (TMEDIA_CODEC_AUDIO(opus)->out.channels == 2) ? 1 : 0,
- opus->decoder.fec_enabled ? 1 : 0,
- opus->decoder.dtx_enabled ? 1 : 0
- );
- return fmtp;
- }
-
- return tsk_null;
+ tdav_codec_opus_t* opus = (tdav_codec_opus_t*)codec;
+
+ if(!opus) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return tsk_null;
+ }
+
+ if(tsk_striequals(att_name, "fmtp")) {
+ char* fmtp = tsk_null;
+ tsk_sprintf(&fmtp, "maxplaybackrate=%d; sprop-maxcapturerate=%d; stereo=%d; sprop-stereo=%d; useinbandfec=%d; usedtx=%d",
+ TMEDIA_CODEC(opus)->in.rate,
+ TMEDIA_CODEC(opus)->out.rate,
+ (TMEDIA_CODEC_AUDIO(opus)->in.channels == 2) ? 1 : 0,
+ (TMEDIA_CODEC_AUDIO(opus)->out.channels == 2) ? 1 : 0,
+ opus->decoder.fec_enabled ? 1 : 0,
+ opus->decoder.dtx_enabled ? 1 : 0
+ );
+ return fmtp;
+ }
+
+ return tsk_null;
}
//
@@ -285,77 +290,75 @@ static char* tdav_codec_opus_sdp_att_get(const tmedia_codec_t* codec, const char
/* constructor */
static tsk_object_t* tdav_codec_opus_ctor(tsk_object_t * self, va_list * app)
{
- tdav_codec_opus_t *opus = self;
- if(opus){
- /* init base: called by tmedia_codec_create() */
- /* init self */
- TMEDIA_CODEC(opus)->in.rate = tmedia_defaults_get_opus_maxplaybackrate();
- TMEDIA_CODEC(opus)->out.rate = tmedia_defaults_get_opus_maxcapturerate();
- TMEDIA_CODEC_AUDIO(opus)->in.channels = 1;
- TMEDIA_CODEC_AUDIO(opus)->out.channels = 1;
+ tdav_codec_opus_t *opus = self;
+ if(opus) {
+ /* init base: called by tmedia_codec_create() */
+ /* init self */
+ TMEDIA_CODEC(opus)->in.rate = tmedia_defaults_get_opus_maxplaybackrate();
+ TMEDIA_CODEC(opus)->out.rate = tmedia_defaults_get_opus_maxcapturerate();
+ TMEDIA_CODEC_AUDIO(opus)->in.channels = 1;
+ TMEDIA_CODEC_AUDIO(opus)->out.channels = 1;
#if TDAV_OPUS_FEC_ENABLED
- opus->decoder.fec_enabled = tsk_true;
+ opus->decoder.fec_enabled = tsk_true;
#endif
#if TDAV_OPUS_DTX_ENABLED
- opus->decoder.dtx_enabled = tsk_true;
+ opus->decoder.dtx_enabled = tsk_true;
#endif
- }
- return self;
+ }
+ return self;
}
/* destructor */
static tsk_object_t* tdav_codec_opus_dtor(tsk_object_t * self)
-{
- tdav_codec_opus_t *opus = self;
- if(opus){
- /* deinit base */
- tmedia_codec_audio_deinit(opus);
- /* deinit self */
- if(opus->decoder.inst){
- opus_decoder_destroy(opus->decoder.inst), opus->decoder.inst = tsk_null;
- }
- if(opus->encoder.inst){
- opus_encoder_destroy(opus->encoder.inst), opus->encoder.inst = tsk_null;
- }
- }
-
- return self;
+{
+ tdav_codec_opus_t *opus = self;
+ if(opus) {
+ /* deinit base */
+ tmedia_codec_audio_deinit(opus);
+ /* deinit self */
+ if(opus->decoder.inst) {
+ opus_decoder_destroy(opus->decoder.inst), opus->decoder.inst = tsk_null;
+ }
+ if(opus->encoder.inst) {
+ opus_encoder_destroy(opus->encoder.inst), opus->encoder.inst = tsk_null;
+ }
+ }
+
+ return self;
}
/* object definition */
-static const tsk_object_def_t tdav_codec_opus_def_s =
-{
- sizeof(tdav_codec_opus_t),
- tdav_codec_opus_ctor,
- tdav_codec_opus_dtor,
- tmedia_codec_cmp,
+static const tsk_object_def_t tdav_codec_opus_def_s = {
+ sizeof(tdav_codec_opus_t),
+ tdav_codec_opus_ctor,
+ tdav_codec_opus_dtor,
+ tmedia_codec_cmp,
};
/* plugin definition*/
-static const tmedia_codec_plugin_def_t tdav_codec_opus_plugin_def_s =
-{
- &tdav_codec_opus_def_s,
-
- tmedia_audio,
- tmedia_codec_id_opus,
- "opus",
- "opus Codec",
- TMEDIA_CODEC_FORMAT_OPUS,
- tsk_true,
- 48000, // this is the default sample rate
-
- { /* audio */
- 2, // channels
- 0 // ptime @deprecated
- },
-
- /* video */
- {0},
-
- tsk_null, // set()
- tdav_codec_opus_open,
- tdav_codec_opus_close,
- tdav_codec_opus_encode,
- tdav_codec_opus_decode,
- tdav_codec_opus_sdp_att_match,
- tdav_codec_opus_sdp_att_get
+static const tmedia_codec_plugin_def_t tdav_codec_opus_plugin_def_s = {
+ &tdav_codec_opus_def_s,
+
+ tmedia_audio,
+ tmedia_codec_id_opus,
+ "opus",
+ "opus Codec",
+ TMEDIA_CODEC_FORMAT_OPUS,
+ tsk_true,
+ 48000, // this is the default sample rate
+
+ { /* audio */
+ 2, // channels
+ 0 // ptime @deprecated
+ },
+
+ /* video */
+ {0},
+
+ tsk_null, // set()
+ tdav_codec_opus_open,
+ tdav_codec_opus_close,
+ tdav_codec_opus_encode,
+ tdav_codec_opus_decode,
+ tdav_codec_opus_sdp_att_match,
+ tdav_codec_opus_sdp_att_get
};
const tmedia_codec_plugin_def_t *tdav_codec_opus_plugin_def_t = &tdav_codec_opus_plugin_def_s;
diff --git a/tinyDAV/src/codecs/speex/tdav_codec_speex.c b/tinyDAV/src/codecs/speex/tdav_codec_speex.c
index 18c4440..1a237a1 100755
--- a/tinyDAV/src/codecs/speex/tdav_codec_speex.c
+++ b/tinyDAV/src/codecs/speex/tdav_codec_speex.c
@@ -2,19 +2,19 @@
* Copyright (C) 2010-2011 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.
*
@@ -45,132 +45,132 @@ int tdav_codec_speex_deinit(tdav_codec_speex_t* self);
int tdav_codec_speex_open(tmedia_codec_t* self)
{
- static int quality = SPEEX_DEFAULT_QUALITY;
- tdav_codec_speex_t* speex = (tdav_codec_speex_t*)self;
-
- switch(speex->type){
- case tdav_codec_speex_type_nb:
- speex->encoder.state = speex_encoder_init(&speex_nb_mode);
- speex->decoder.state = speex_decoder_init(&speex_nb_mode);
- break;
- case tdav_codec_speex_type_wb:
- speex->encoder.state = speex_encoder_init(&speex_wb_mode);
- speex->decoder.state = speex_decoder_init(&speex_wb_mode);
- break;
- case tdav_codec_speex_type_uwb:
- speex->encoder.state = speex_encoder_init(&speex_uwb_mode);
- speex->decoder.state = speex_decoder_init(&speex_uwb_mode);
- break;
- default:
- TSK_DEBUG_ERROR("Not implemented");
- return -2;
- }
-
- speex_decoder_ctl(speex->decoder.state, SPEEX_GET_FRAME_SIZE, &speex->decoder.size);
- speex->decoder.size *= sizeof(spx_int16_t);
- if(!(speex->decoder.buffer = tsk_calloc(speex->decoder.size, 1))){
- speex->decoder.size = speex->decoder.size = 0;
- TSK_DEBUG_ERROR("Failed to allocate new buffer");
- return -3;
- }
-
- speex_encoder_ctl(speex->encoder.state, SPEEX_SET_QUALITY, &quality);
- speex_encoder_ctl(speex->encoder.state, SPEEX_GET_FRAME_SIZE, &speex->encoder.size);
-
- speex_bits_init(&speex->encoder.bits);
- speex_bits_init(&speex->decoder.bits);
- speex_bits_reset(&speex->encoder.bits);
- speex_bits_reset(&speex->decoder.bits);
-
- return 0;
+ static int quality = SPEEX_DEFAULT_QUALITY;
+ tdav_codec_speex_t* speex = (tdav_codec_speex_t*)self;
+
+ switch(speex->type) {
+ case tdav_codec_speex_type_nb:
+ speex->encoder.state = speex_encoder_init(&speex_nb_mode);
+ speex->decoder.state = speex_decoder_init(&speex_nb_mode);
+ break;
+ case tdav_codec_speex_type_wb:
+ speex->encoder.state = speex_encoder_init(&speex_wb_mode);
+ speex->decoder.state = speex_decoder_init(&speex_wb_mode);
+ break;
+ case tdav_codec_speex_type_uwb:
+ speex->encoder.state = speex_encoder_init(&speex_uwb_mode);
+ speex->decoder.state = speex_decoder_init(&speex_uwb_mode);
+ break;
+ default:
+ TSK_DEBUG_ERROR("Not implemented");
+ return -2;
+ }
+
+ speex_decoder_ctl(speex->decoder.state, SPEEX_GET_FRAME_SIZE, &speex->decoder.size);
+ speex->decoder.size *= sizeof(spx_int16_t);
+ if(!(speex->decoder.buffer = tsk_calloc(speex->decoder.size, 1))) {
+ speex->decoder.size = speex->decoder.size = 0;
+ TSK_DEBUG_ERROR("Failed to allocate new buffer");
+ return -3;
+ }
+
+ speex_encoder_ctl(speex->encoder.state, SPEEX_SET_QUALITY, &quality);
+ speex_encoder_ctl(speex->encoder.state, SPEEX_GET_FRAME_SIZE, &speex->encoder.size);
+
+ speex_bits_init(&speex->encoder.bits);
+ speex_bits_init(&speex->decoder.bits);
+ speex_bits_reset(&speex->encoder.bits);
+ speex_bits_reset(&speex->decoder.bits);
+
+ return 0;
}
int tdav_codec_speex_close(tmedia_codec_t* self)
{
- tdav_codec_speex_t* speex = (tdav_codec_speex_t*)self;
+ tdav_codec_speex_t* speex = (tdav_codec_speex_t*)self;
- (void)(speex);
+ (void)(speex);
- return 0;
+ return 0;
}
tsk_size_t tdav_codec_speex_encode(tmedia_codec_t* self, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size)
-{
- tdav_codec_speex_t* speex = (tdav_codec_speex_t*)self;
- tsk_size_t outsize = 0;
-
- if(!self || !in_data || !in_size || !out_data){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- speex_bits_reset(&speex->encoder.bits);
- speex_encode_int(speex->encoder.state, (spx_int16_t*)in_data, &speex->encoder.bits);
-
- if(*out_max_size <speex->encoder.size){
- if((*out_data = tsk_realloc(*out_data, speex->encoder.size))){
- *out_max_size = speex->encoder.size;
- }
- else{
- *out_max_size = 0;
- return 0;
- }
- }
-
- outsize = speex_bits_write(&speex->encoder.bits, *out_data, (speex->encoder.size >> 1));
-
- return outsize;
+{
+ tdav_codec_speex_t* speex = (tdav_codec_speex_t*)self;
+ tsk_size_t outsize = 0;
+
+ if(!self || !in_data || !in_size || !out_data) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ speex_bits_reset(&speex->encoder.bits);
+ speex_encode_int(speex->encoder.state, (spx_int16_t*)in_data, &speex->encoder.bits);
+
+ if(*out_max_size <speex->encoder.size) {
+ if((*out_data = tsk_realloc(*out_data, speex->encoder.size))) {
+ *out_max_size = speex->encoder.size;
+ }
+ else {
+ *out_max_size = 0;
+ return 0;
+ }
+ }
+
+ outsize = speex_bits_write(&speex->encoder.bits, *out_data, (speex->encoder.size >> 1));
+
+ return outsize;
}
tsk_size_t tdav_codec_speex_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)
{
- int ret;
- tsk_size_t out_size = 0;
- tdav_codec_speex_t* speex = (tdav_codec_speex_t*)self;
-
- if(!self || !in_data || !in_size || !out_data){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- // initializes the bit-stream
- speex_bits_read_from(&speex->decoder.bits, (char*)in_data, in_size);
-
- do{
- // performs decode()
- if((ret = speex_decode_int(speex->decoder.state, &speex->decoder.bits, speex->decoder.buffer))){
- TSK_DEBUG_ERROR("Failed to decode the buffer. retcode=%d", ret);
- break;
- }
-
- if(*out_max_size <(out_size + speex->decoder.size)){
- if((*out_data = tsk_realloc(*out_data, (out_size + speex->decoder.size)))){
- *out_max_size = (out_size + speex->decoder.size);
- }
- else{
- *out_max_size = 0;
- return 0;
- }
- }
-
- // copy output buffer
- memcpy(&((uint8_t*)*out_data)[out_size], speex->decoder.buffer, speex->decoder.size);
- out_size += speex->decoder.size;
- }
- while(speex_bits_remaining(&speex->decoder.bits) >= 5);
-
-
- return out_size;
+ int ret;
+ tsk_size_t out_size = 0;
+ tdav_codec_speex_t* speex = (tdav_codec_speex_t*)self;
+
+ if(!self || !in_data || !in_size || !out_data) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ // initializes the bit-stream
+ speex_bits_read_from(&speex->decoder.bits, (char*)in_data, in_size);
+
+ do {
+ // performs decode()
+ if((ret = speex_decode_int(speex->decoder.state, &speex->decoder.bits, speex->decoder.buffer))) {
+ TSK_DEBUG_ERROR("Failed to decode the buffer. retcode=%d", ret);
+ break;
+ }
+
+ if(*out_max_size <(out_size + speex->decoder.size)) {
+ if((*out_data = tsk_realloc(*out_data, (out_size + speex->decoder.size)))) {
+ *out_max_size = (out_size + speex->decoder.size);
+ }
+ else {
+ *out_max_size = 0;
+ return 0;
+ }
+ }
+
+ // copy output buffer
+ memcpy(&((uint8_t*)*out_data)[out_size], speex->decoder.buffer, speex->decoder.size);
+ out_size += speex->decoder.size;
+ }
+ while(speex_bits_remaining(&speex->decoder.bits) >= 5);
+
+
+ return out_size;
}
char* tdav_codec_speex_sdp_att_get(const tmedia_codec_t* codec, const char* att_name)
{
- return tsk_null;
+ return tsk_null;
}
tsk_bool_t tdav_codec_speex_sdp_att_match(const tmedia_codec_t* codec, const char* att_name, const char* att_value)
-{
- return tsk_true;
+{
+ return tsk_true;
}
@@ -245,42 +245,42 @@ SPEEX_OBJECT_DEFINITION(uwb,"SPEEX","Speex-UWB Codec",TMEDIA_CODEC_FORMAT_SPEEX_
//
int tdav_codec_speex_init(tdav_codec_speex_t* self, tdav_codec_speex_type_t type)
{
- if(self){
- self->type = type;
- return 0;
- }
- else{
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
+ if(self) {
+ self->type = type;
+ return 0;
+ }
+ else {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
}
int tdav_codec_speex_deinit(tdav_codec_speex_t* self)
{
- if(self){
- if(self->decoder.state){
- speex_decoder_destroy(self->decoder.state);
- self->decoder.state = tsk_null;
- }
- speex_bits_destroy(&self->decoder.bits);
- if(self->decoder.buffer){
- TSK_FREE(self->decoder.buffer);
- self->decoder.size = 0;
- }
-
- if(self->encoder.state){
- speex_encoder_destroy(self->encoder.state);
- self->encoder.state = tsk_null;
- }
- speex_bits_destroy(&self->encoder.bits);
- self->encoder.size = 0;
-
- return 0;
- }
- else{
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
+ if(self) {
+ if(self->decoder.state) {
+ speex_decoder_destroy(self->decoder.state);
+ self->decoder.state = tsk_null;
+ }
+ speex_bits_destroy(&self->decoder.bits);
+ if(self->decoder.buffer) {
+ TSK_FREE(self->decoder.buffer);
+ self->decoder.size = 0;
+ }
+
+ if(self->encoder.state) {
+ speex_encoder_destroy(self->encoder.state);
+ self->encoder.state = tsk_null;
+ }
+ speex_bits_destroy(&self->encoder.bits);
+ self->encoder.size = 0;
+
+ return 0;
+ }
+ else {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
}
#endif /* HAVE_LIB_SPEEX */
diff --git a/tinyDAV/src/codecs/t140/tdav_codec_t140.c b/tinyDAV/src/codecs/t140/tdav_codec_t140.c
index b401321..5045fb9 100755
--- a/tinyDAV/src/codecs/t140/tdav_codec_t140.c
+++ b/tinyDAV/src/codecs/t140/tdav_codec_t140.c
@@ -1,18 +1,18 @@
/*
* Copyright (C) 2012 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.
*
@@ -32,83 +32,83 @@
static int tdav_codec_t140_set(tmedia_codec_t* self, const struct tmedia_param_s* param)
{
- return 0;
+ return 0;
}
static int tdav_codec_t140_open(tmedia_codec_t* self)
{
- return 0;
+ return 0;
}
static int tdav_codec_t140_close(tmedia_codec_t* self)
{
- return 0;
+ return 0;
}
static tsk_size_t tdav_codec_t140_encode(tmedia_codec_t* self, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size)
{
- tsk_size_t out_size = in_size;
-
- if(!self || !in_data || !in_size || !out_data){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- if(*out_max_size <out_size){
- if(!(*out_data = tsk_realloc(*out_data, out_size))){
- TSK_DEBUG_ERROR("Failed to allocate new buffer");
- *out_max_size = 0;
- return 0;
- }
- *out_max_size = out_size;
- }
- memcpy(*out_data, in_data, out_size);
-
- return out_size;
+ tsk_size_t out_size = in_size;
+
+ if(!self || !in_data || !in_size || !out_data) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ if(*out_max_size <out_size) {
+ if(!(*out_data = tsk_realloc(*out_data, out_size))) {
+ TSK_DEBUG_ERROR("Failed to allocate new buffer");
+ *out_max_size = 0;
+ return 0;
+ }
+ *out_max_size = out_size;
+ }
+ memcpy(*out_data, in_data, out_size);
+
+ return out_size;
}
static tsk_size_t tdav_codec_t140_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)
{
- tsk_size_t out_size = in_size;
-
- if(!self || !in_data || !in_size || !out_data){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- /* allocate new buffer */
- if(*out_max_size < out_size){
- if(!(*out_data = tsk_realloc(*out_data, out_size))){
- TSK_DEBUG_ERROR("Failed to allocate new buffer");
- *out_max_size = 0;
- return 0;
- }
- *out_max_size = out_size;
- }
- memcpy(*out_data, in_data, out_size);
-
- return out_size;
+ tsk_size_t out_size = in_size;
+
+ if(!self || !in_data || !in_size || !out_data) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ /* allocate new buffer */
+ if(*out_max_size < out_size) {
+ if(!(*out_data = tsk_realloc(*out_data, out_size))) {
+ TSK_DEBUG_ERROR("Failed to allocate new buffer");
+ *out_max_size = 0;
+ return 0;
+ }
+ *out_max_size = out_size;
+ }
+ memcpy(*out_data, in_data, out_size);
+
+ return out_size;
}
static tsk_bool_t tdav_codec_t140_sdp_att_match(const tmedia_codec_t* self, const char* att_name, const char* att_value)
{
- return tsk_true;
+ return tsk_true;
}
static char* tdav_codec_t140_sdp_att_get(const tmedia_codec_t* self, const char* att_name)
{
- if(!self || !att_name){
- TSK_DEBUG_ERROR("Invalid parameter");
- return tsk_null;
- }
-
- if(tsk_striequals("fmtp", att_name)){
- char* fmtp = tsk_null;
- tsk_sprintf(&fmtp, "cps=%d", TDAV_CODEC_T140_CPS);
- return fmtp;
- }
- return tsk_null;
+ if(!self || !att_name) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return tsk_null;
+ }
+
+ if(tsk_striequals("fmtp", att_name)) {
+ char* fmtp = tsk_null;
+ tsk_sprintf(&fmtp, "cps=%d", TDAV_CODEC_T140_CPS);
+ return fmtp;
+ }
+ return tsk_null;
}
@@ -119,57 +119,55 @@ static char* tdav_codec_t140_sdp_att_get(const tmedia_codec_t* self, const char*
/* constructor */
static tsk_object_t* tdav_codec_t140_ctor(tsk_object_t * self, va_list * app)
{
- tdav_codec_t140_t *t140 = self;
- if(t140){
- /* init base: called by tmedia_codec_create() */
- /* init self */
- }
- return self;
+ tdav_codec_t140_t *t140 = self;
+ if(t140) {
+ /* init base: called by tmedia_codec_create() */
+ /* init self */
+ }
+ return self;
}
/* destructor */
static tsk_object_t* tdav_codec_t140_dtor(tsk_object_t * self)
-{
- tdav_codec_t140_t *t140 = self;
- if(t140){
- /* deinit base */
- /* deinit self */
- }
-
- return self;
+{
+ tdav_codec_t140_t *t140 = self;
+ if(t140) {
+ /* deinit base */
+ /* deinit self */
+ }
+
+ return self;
}
/* object definition */
-static const tsk_object_def_t tdav_codec_t140_def_s =
-{
- sizeof(tdav_codec_t140_t),
- tdav_codec_t140_ctor,
- tdav_codec_t140_dtor,
- tmedia_codec_cmp,
+static const tsk_object_def_t tdav_codec_t140_def_s = {
+ sizeof(tdav_codec_t140_t),
+ tdav_codec_t140_ctor,
+ tdav_codec_t140_dtor,
+ tmedia_codec_cmp,
};
/* plugin definition*/
-static const tmedia_codec_plugin_def_t tdav_codec_t140_plugin_def_s =
-{
- &tdav_codec_t140_def_s,
-
- tmedia_t140,
- tmedia_codec_id_t140,
- "t140",
- "T140 codec (From tinyDAV)",
- TMEDIA_CODEC_FORMAT_T140,
- tsk_true,
- 1000, // rate
-
- /* audio */
- {0},
-
- /* video */
- {0},
-
- tdav_codec_t140_set,
- tdav_codec_t140_open,
- tdav_codec_t140_close,
- tdav_codec_t140_encode,
- tdav_codec_t140_decode,
- tdav_codec_t140_sdp_att_match,
- tdav_codec_t140_sdp_att_get
+static const tmedia_codec_plugin_def_t tdav_codec_t140_plugin_def_s = {
+ &tdav_codec_t140_def_s,
+
+ tmedia_t140,
+ tmedia_codec_id_t140,
+ "t140",
+ "T140 codec (From tinyDAV)",
+ TMEDIA_CODEC_FORMAT_T140,
+ tsk_true,
+ 1000, // rate
+
+ /* audio */
+ {0},
+
+ /* video */
+ {0},
+
+ tdav_codec_t140_set,
+ tdav_codec_t140_open,
+ tdav_codec_t140_close,
+ tdav_codec_t140_encode,
+ tdav_codec_t140_decode,
+ tdav_codec_t140_sdp_att_match,
+ tdav_codec_t140_sdp_att_get
};
const tmedia_codec_plugin_def_t *tdav_codec_t140_plugin_def_t = &tdav_codec_t140_plugin_def_s;
diff --git a/tinyDAV/src/codecs/theora/tdav_codec_theora.c b/tinyDAV/src/codecs/theora/tdav_codec_theora.c
index 01072c3..620d6ed 100755
--- a/tinyDAV/src/codecs/theora/tdav_codec_theora.c
+++ b/tinyDAV/src/codecs/theora/tdav_codec_theora.c
@@ -2,19 +2,19 @@
* Copyright (C) 2010-2011 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.
*
@@ -55,64 +55,63 @@
#define THEORA_IDENT_HEADER_SIZE 42 /* 6.2 Identification Header Decode */
#define THEORA_CONF_SEND_COUNT 10 /* at 250ms, 500ms, 1000ms, .... */
-typedef struct tdav_codec_theora_s
-{
- TMEDIA_DECLARE_CODEC_VIDEO;
-
- struct{
- uint8_t* ptr;
- tsk_size_t size;
- } rtp;
-
- // Encoder
- struct{
- AVCodec* codec;
- AVCodecContext* context;
- AVFrame* picture;
- void* buffer;
-
- uint64_t conf_last;
- int conf_count;
- tsk_bool_t force_idr;
- int quality;
- int rotation;
- int32_t max_bw_kpbs;
- } encoder;
-
- // decoder
- struct{
- AVCodec* codec;
- AVCodecContext* context;
- AVFrame* picture;
-
- tsk_bool_t opened;
- uint8_t conf_ident[3];
- tsk_buffer_t* conf_pkt;
-
- void* accumulator;
- uint8_t ebit;
- tsk_size_t accumulator_pos;
- uint16_t last_seq;
- } decoder;
+typedef struct tdav_codec_theora_s {
+ TMEDIA_DECLARE_CODEC_VIDEO;
+
+ struct {
+ uint8_t* ptr;
+ tsk_size_t size;
+ } rtp;
+
+ // Encoder
+ struct {
+ AVCodec* codec;
+ AVCodecContext* context;
+ AVFrame* picture;
+ void* buffer;
+
+ uint64_t conf_last;
+ int conf_count;
+ tsk_bool_t force_idr;
+ int quality;
+ int rotation;
+ int32_t max_bw_kpbs;
+ } encoder;
+
+ // decoder
+ struct {
+ AVCodec* codec;
+ AVCodecContext* context;
+ AVFrame* picture;
+
+ tsk_bool_t opened;
+ uint8_t conf_ident[3];
+ tsk_buffer_t* conf_pkt;
+
+ void* accumulator;
+ uint8_t ebit;
+ tsk_size_t accumulator_pos;
+ uint16_t last_seq;
+ } decoder;
}
tdav_codec_theora_t;
/* 2.2. Payload Header filed 'F'*/
-typedef enum theora_frag_type_e{
- Not_Fragmented = 0,
- Start_Fragment = 1,
- Continuation_Fragment = 2,
- End_Fragment = 3,
+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,
+typedef enum theora_datatype_e {
+ Raw_Theora_payload = 0,
+ Theora_Packed_Configuration_payload = 1,
+ Legacy_Theora_Comment_payload = 2,
+ Reserved = 3,
}
theora_datatype_t;
@@ -130,399 +129,396 @@ static void tdav_codec_theora_encap(tdav_codec_theora_t* theora, const uint8_t*
static int tdav_codec_theora_set(tmedia_codec_t* self, const tmedia_param_t* param)
{
- tdav_codec_theora_t* theora = (tdav_codec_theora_t*)self;
- if(!self->opened){
- TSK_DEBUG_ERROR("Codec not opened");
- return -1;
- }
- if(param->value_type == tmedia_pvt_int32){
- if(tsk_striequals(param->key, "action")){
- tmedia_codec_action_t action = (tmedia_codec_action_t)TSK_TO_INT32((uint8_t*)param->value);
- switch(action){
- case tmedia_codec_action_encode_idr:
- {
- theora->encoder.force_idr = tsk_true;
- break;
- }
- case tmedia_codec_action_bw_down:
- {
- theora->encoder.quality = TSK_CLAMP(1, (theora->encoder.quality + 1), 31);
- theora->encoder.context->global_quality = FF_QP2LAMBDA * theora->encoder.quality;
- break;
- }
- case tmedia_codec_action_bw_up:
- {
- theora->encoder.quality = TSK_CLAMP(1, (theora->encoder.quality - 1), 31);
- theora->encoder.context->global_quality = FF_QP2LAMBDA * theora->encoder.quality;
- break;
- }
- }
- }
- // FIXME: not working as expected
- /*else if(tsk_striequals(param->key, "rotation")){
- int rotation = *((int32_t*)param->value);
- if(theora->encoder.rotation != rotation){
- if(self->opened){
- int ret;
- theora->encoder.rotation = rotation;
- if((ret = tdav_codec_theora_close_encoder(theora))){
- return ret;
- }
- if((ret = tdav_codec_theora_open_encoder(theora))){
- return ret;
- }
- }
- }
- return 0;
- }*/
- }
- return -1;
+ tdav_codec_theora_t* theora = (tdav_codec_theora_t*)self;
+ if(!self->opened) {
+ TSK_DEBUG_ERROR("Codec not opened");
+ return -1;
+ }
+ if(param->value_type == tmedia_pvt_int32) {
+ if(tsk_striequals(param->key, "action")) {
+ tmedia_codec_action_t action = (tmedia_codec_action_t)TSK_TO_INT32((uint8_t*)param->value);
+ switch(action) {
+ case tmedia_codec_action_encode_idr: {
+ theora->encoder.force_idr = tsk_true;
+ break;
+ }
+ case tmedia_codec_action_bw_down: {
+ theora->encoder.quality = TSK_CLAMP(1, (theora->encoder.quality + 1), 31);
+ theora->encoder.context->global_quality = FF_QP2LAMBDA * theora->encoder.quality;
+ break;
+ }
+ case tmedia_codec_action_bw_up: {
+ theora->encoder.quality = TSK_CLAMP(1, (theora->encoder.quality - 1), 31);
+ theora->encoder.context->global_quality = FF_QP2LAMBDA * theora->encoder.quality;
+ break;
+ }
+ }
+ }
+ // FIXME: not working as expected
+ /*else if(tsk_striequals(param->key, "rotation")){
+ int rotation = *((int32_t*)param->value);
+ if(theora->encoder.rotation != rotation){
+ if(self->opened){
+ int ret;
+ theora->encoder.rotation = rotation;
+ if((ret = tdav_codec_theora_close_encoder(theora))){
+ return ret;
+ }
+ if((ret = tdav_codec_theora_open_encoder(theora))){
+ return ret;
+ }
+ }
+ }
+ return 0;
+ }*/
+ }
+ return -1;
}
int tdav_codec_theora_open(tmedia_codec_t* self)
{
- int ret;
-
- 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((ret = tdav_codec_theora_open_encoder(theora))){
- return ret;
- }
-
- // Decoder
- if((ret = tdav_codec_theora_open_decoder(theora))){
- return ret;
- }
-
- return 0;
+ int ret;
+
+ 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((ret = tdav_codec_theora_open_encoder(theora))) {
+ return ret;
+ }
+
+ // Decoder
+ if((ret = tdav_codec_theora_open_decoder(theora))) {
+ return ret;
+ }
+
+ return 0;
}
int tdav_codec_theora_close(tmedia_codec_t* self)
{
- tdav_codec_theora_t* theora = (tdav_codec_theora_t*)self;
+ tdav_codec_theora_t* theora = (tdav_codec_theora_t*)self;
- if(!theora){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
+ if(!theora) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
- /* the caller (base class) already checked that the codec is opened */
+ /* the caller (base class) already checked that the codec is opened */
-
- // Encoder
- tdav_codec_theora_close_encoder(theora);
-
- // Decoder
- tdav_codec_theora_close_decoder(theora);
- return 0;
+ // Encoder
+ tdav_codec_theora_close_encoder(theora);
+
+ // Decoder
+ tdav_codec_theora_close_decoder(theora);
+
+ 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;
- }
-
- // Encode data
+ 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;
+ }
+
+ // Encode data
#if LIBAVCODEC_VERSION_MAJOR <= 53
- theora->encoder.picture->pict_type = theora->encoder.force_idr ? FF_I_TYPE : 0;
+ theora->encoder.picture->pict_type = theora->encoder.force_idr ? FF_I_TYPE : 0;
#else
theora->encoder.picture->pict_type = theora->encoder.force_idr ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_NONE;
#endif
- theora->encoder.picture->pts = AV_NOPTS_VALUE;
- theora->encoder.picture->quality = theora->encoder.context->global_quality;
- 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);
- }
- theora->encoder.force_idr = tsk_false;
-
- return 0;
+ theora->encoder.picture->pts = AV_NOPTS_VALUE;
+ theora->encoder.picture->quality = theora->encoder.context->global_quality;
+ 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);
+ }
+ theora->encoder.force_idr = tsk_false;
+
+ 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 = (int)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){
- TSK_DEBUG_WARN("Failed to decode the buffer with error code = %d", ret);
- if(TMEDIA_CODEC_VIDEO(self)->in.callback){
- TMEDIA_CODEC_VIDEO(self)->in.result.type = tmedia_video_decode_result_type_error;
- TMEDIA_CODEC_VIDEO(self)->in.result.proto_hdr = proto_hdr;
- TMEDIA_CODEC_VIDEO(self)->in.callback(&TMEDIA_CODEC_VIDEO(self)->in.result);
- }
- }
- else if(got_picture_ptr){
- retsize = xsize;
- TMEDIA_CODEC_VIDEO(theora)->in.width = theora->decoder.context->width;
- TMEDIA_CODEC_VIDEO(theora)->in.height = theora->decoder.context->height;
-
- /* 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, (int)theora->decoder.context->width, (int)theora->decoder.context->height,
- *out_data, (int)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 = (int)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;
+ 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 = (int)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) {
+ TSK_DEBUG_WARN("Failed to decode the buffer with error code = %d", ret);
+ if(TMEDIA_CODEC_VIDEO(self)->in.callback) {
+ TMEDIA_CODEC_VIDEO(self)->in.result.type = tmedia_video_decode_result_type_error;
+ TMEDIA_CODEC_VIDEO(self)->in.result.proto_hdr = proto_hdr;
+ TMEDIA_CODEC_VIDEO(self)->in.callback(&TMEDIA_CODEC_VIDEO(self)->in.result);
+ }
+ }
+ else if(got_picture_ptr) {
+ retsize = xsize;
+ TMEDIA_CODEC_VIDEO(theora)->in.width = theora->decoder.context->width;
+ TMEDIA_CODEC_VIDEO(theora)->in.height = theora->decoder.context->height;
+
+ /* 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, (int)theora->decoder.context->width, (int)theora->decoder.context->height,
+ *out_data, (int)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 = (int)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_sdp_att_match(const tmedia_codec_t* codec, const char* att_name, const char* att_value)
{
- tsk_bool_t ret = tsk_true; // accept decoding any size
-
- if(tsk_striequals(att_name, "fmtp")){
- tsk_params_L_t* params;
- if((params = tsk_params_fromstring(att_value, ";", tsk_true))){
- int pref_width, pref_height;
- int prop_width = tsk_params_get_param_value_as_int(params, "width");
- int prop_height = tsk_params_get_param_value_as_int(params, "height");
-
- if(prop_width > 0 && prop_height > 0){
- if(tmedia_video_get_size(TMEDIA_CODEC_VIDEO(codec)->pref_size, (unsigned *)&pref_width, (unsigned *)&pref_height) != 0){
- TSK_OBJECT_SAFE_FREE(params);
- return tsk_false;
- }
- TMEDIA_CODEC_VIDEO(codec)->in.width = TMEDIA_CODEC_VIDEO(codec)->out.width = TSK_MIN(pref_width, prop_width);
- TMEDIA_CODEC_VIDEO(codec)->in.height = TMEDIA_CODEC_VIDEO(codec)->out.height = TSK_MIN(pref_height, prop_height);
- }
- TSK_OBJECT_SAFE_FREE(params);
- }
- }
- else if(tsk_striequals(att_name, "imageattr")){
- unsigned in_width, in_height, out_width, out_height;
- if(tmedia_parse_video_imageattr(att_value, TMEDIA_CODEC_VIDEO(codec)->pref_size, &in_width, &in_height, &out_width, &out_height) != 0){
- return tsk_false;
- }
- TMEDIA_CODEC_VIDEO(codec)->in.width = in_width;
- TMEDIA_CODEC_VIDEO(codec)->in.height = in_height;
- TMEDIA_CODEC_VIDEO(codec)->out.width = out_width;
- TMEDIA_CODEC_VIDEO(codec)->out.height = out_height;
- }
-
- return ret;
+ tsk_bool_t ret = tsk_true; // accept decoding any size
+
+ if(tsk_striequals(att_name, "fmtp")) {
+ tsk_params_L_t* params;
+ if((params = tsk_params_fromstring(att_value, ";", tsk_true))) {
+ int pref_width, pref_height;
+ int prop_width = tsk_params_get_param_value_as_int(params, "width");
+ int prop_height = tsk_params_get_param_value_as_int(params, "height");
+
+ if(prop_width > 0 && prop_height > 0) {
+ if(tmedia_video_get_size(TMEDIA_CODEC_VIDEO(codec)->pref_size, (unsigned *)&pref_width, (unsigned *)&pref_height) != 0) {
+ TSK_OBJECT_SAFE_FREE(params);
+ return tsk_false;
+ }
+ TMEDIA_CODEC_VIDEO(codec)->in.width = TMEDIA_CODEC_VIDEO(codec)->out.width = TSK_MIN(pref_width, prop_width);
+ TMEDIA_CODEC_VIDEO(codec)->in.height = TMEDIA_CODEC_VIDEO(codec)->out.height = TSK_MIN(pref_height, prop_height);
+ }
+ TSK_OBJECT_SAFE_FREE(params);
+ }
+ }
+ else if(tsk_striequals(att_name, "imageattr")) {
+ unsigned in_width, in_height, out_width, out_height;
+ if(tmedia_parse_video_imageattr(att_value, TMEDIA_CODEC_VIDEO(codec)->pref_size, &in_width, &in_height, &out_width, &out_height) != 0) {
+ return tsk_false;
+ }
+ TMEDIA_CODEC_VIDEO(codec)->in.width = in_width;
+ TMEDIA_CODEC_VIDEO(codec)->in.height = in_height;
+ TMEDIA_CODEC_VIDEO(codec)->out.width = out_width;
+ TMEDIA_CODEC_VIDEO(codec)->out.height = out_height;
+ }
+
+ return ret;
}
char* tdav_codec_theora_sdp_att_get(const tmedia_codec_t* codec, const char* att_name)
{
- if(tsk_striequals(att_name, "fmtp")){
- char* fmtp = tsk_null;
- tsk_sprintf(&fmtp, "sampling=YCbCr-4:2:0; width=%u; height=%u", TMEDIA_CODEC_VIDEO(codec)->out.width, TMEDIA_CODEC_VIDEO(codec)->out.height);
- return fmtp;
- }
- else if(tsk_striequals(att_name, "imageattr")){
- return tmedia_get_video_imageattr(TMEDIA_CODEC_VIDEO(codec)->pref_size,
- TMEDIA_CODEC_VIDEO(codec)->in.width, TMEDIA_CODEC_VIDEO(codec)->in.height, TMEDIA_CODEC_VIDEO(codec)->out.width, TMEDIA_CODEC_VIDEO(codec)->out.height);
- }
- return tsk_null;
+ if(tsk_striequals(att_name, "fmtp")) {
+ char* fmtp = tsk_null;
+ tsk_sprintf(&fmtp, "sampling=YCbCr-4:2:0; width=%u; height=%u", TMEDIA_CODEC_VIDEO(codec)->out.width, TMEDIA_CODEC_VIDEO(codec)->out.height);
+ return fmtp;
+ }
+ else if(tsk_striequals(att_name, "imageattr")) {
+ return tmedia_get_video_imageattr(TMEDIA_CODEC_VIDEO(codec)->pref_size,
+ TMEDIA_CODEC_VIDEO(codec)->in.width, TMEDIA_CODEC_VIDEO(codec)->in.height, TMEDIA_CODEC_VIDEO(codec)->out.width, TMEDIA_CODEC_VIDEO(codec)->out.height);
+ }
+ return tsk_null;
}
@@ -530,64 +526,62 @@ char* tdav_codec_theora_sdp_att_get(const tmedia_codec_t* codec, const char* att
/* 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 */
- theora->encoder.quality = 1;
- theora->encoder.max_bw_kpbs = tmedia_defaults_get_bandwidth_video_upload_max();
- }
- return self;
+ tdav_codec_theora_t *theora = self;
+ if(theora) {
+ /* init base: called by tmedia_codec_create() */
+ /* init self */
+ theora->encoder.quality = 1;
+ theora->encoder.max_bw_kpbs = tmedia_defaults_get_bandwidth_video_upload_max();
+ }
+ 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;
+{
+ 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,
+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,
- tmedia_codec_id_theora,
- "theora",
- "Theora Codec",
- TMEDIA_CODEC_FORMAT_THEORA,
- tsk_true,
- 90000, // rate
-
- /* audio */
- { 0 },
-
- /* video (width, height, fps)*/
- {176, 144, 0},// fps is @deprecated
-
- tdav_codec_theora_set,
- tdav_codec_theora_open,
- tdav_codec_theora_close,
- tdav_codec_theora_encode,
- tdav_codec_theora_decode,
- tdav_codec_theora_sdp_att_match,
- tdav_codec_theora_sdp_att_get
+static const tmedia_codec_plugin_def_t tdav_codec_theora_plugin_def_s = {
+ &tdav_codec_theora_def_s,
+
+ tmedia_video,
+ tmedia_codec_id_theora,
+ "theora",
+ "Theora Codec",
+ TMEDIA_CODEC_FORMAT_THEORA,
+ tsk_true,
+ 90000, // rate
+
+ /* audio */
+ { 0 },
+
+ /* video (width, height, fps)*/
+ {176, 144, 0},// fps is @deprecated
+
+ tdav_codec_theora_set,
+ tdav_codec_theora_open,
+ tdav_codec_theora_close,
+ tdav_codec_theora_encode,
+ tdav_codec_theora_decode,
+ tdav_codec_theora_sdp_att_match,
+ tdav_codec_theora_sdp_att_get
};
const tmedia_codec_plugin_def_t *tdav_codec_theora_plugin_def_t = &tdav_codec_theora_plugin_def_s;
@@ -595,268 +589,268 @@ const tmedia_codec_plugin_def_t *tdav_codec_theora_plugin_def_t = &tdav_codec_th
int tdav_codec_theora_open_encoder(tdav_codec_theora_t* self)
{
- int ret, size;
- int32_t max_bw_kpbs;
- if(!self->encoder.codec && !(self->encoder.codec = avcodec_find_encoder(CODEC_ID_THEORA))){
- TSK_DEBUG_ERROR("Failed to find Theora encoder");
- return -1;
- }
- if(self->encoder.context){
- TSK_DEBUG_ERROR("Encoder already initialized");
- return -1;
- }
- self->encoder.context = avcodec_alloc_context();
- avcodec_get_context_defaults(self->encoder.context);
-
- self->encoder.context->pix_fmt = PIX_FMT_YUV420P;
- self->encoder.context->time_base.num = 1;
- self->encoder.context->time_base.den = TMEDIA_CODEC_VIDEO(self)->out.fps;
- self->encoder.context->width = (self->encoder.rotation == 90 || self->encoder.rotation == 270) ? TMEDIA_CODEC_VIDEO(self)->out.height : TMEDIA_CODEC_VIDEO(self)->out.width;
- self->encoder.context->height = (self->encoder.rotation == 90 || self->encoder.rotation == 270) ? TMEDIA_CODEC_VIDEO(self)->out.width : TMEDIA_CODEC_VIDEO(self)->out.height;
- self->encoder.context->mb_decision = FF_MB_DECISION_RD;
-
- // Theoraenc doesn't honor 'CODEC_FLAG_QSCALE'
- max_bw_kpbs = TSK_CLAMP(
- 0,
- tmedia_get_video_bandwidth_kbps_2(TMEDIA_CODEC_VIDEO(self)->out.width, TMEDIA_CODEC_VIDEO(self)->out.height, TMEDIA_CODEC_VIDEO(self)->out.fps),
- self->encoder.max_bw_kpbs
- );
- self->encoder.context->bit_rate = (max_bw_kpbs * 1024);// bps
+ int ret, size;
+ int32_t max_bw_kpbs;
+ if(!self->encoder.codec && !(self->encoder.codec = avcodec_find_encoder(CODEC_ID_THEORA))) {
+ TSK_DEBUG_ERROR("Failed to find Theora encoder");
+ return -1;
+ }
+ if(self->encoder.context) {
+ TSK_DEBUG_ERROR("Encoder already initialized");
+ return -1;
+ }
+ self->encoder.context = avcodec_alloc_context();
+ avcodec_get_context_defaults(self->encoder.context);
+
+ self->encoder.context->pix_fmt = PIX_FMT_YUV420P;
+ self->encoder.context->time_base.num = 1;
+ self->encoder.context->time_base.den = TMEDIA_CODEC_VIDEO(self)->out.fps;
+ self->encoder.context->width = (self->encoder.rotation == 90 || self->encoder.rotation == 270) ? TMEDIA_CODEC_VIDEO(self)->out.height : TMEDIA_CODEC_VIDEO(self)->out.width;
+ self->encoder.context->height = (self->encoder.rotation == 90 || self->encoder.rotation == 270) ? TMEDIA_CODEC_VIDEO(self)->out.width : TMEDIA_CODEC_VIDEO(self)->out.height;
+ self->encoder.context->mb_decision = FF_MB_DECISION_RD;
+
+ // Theoraenc doesn't honor 'CODEC_FLAG_QSCALE'
+ max_bw_kpbs = TSK_CLAMP(
+ 0,
+ tmedia_get_video_bandwidth_kbps_2(TMEDIA_CODEC_VIDEO(self)->out.width, TMEDIA_CODEC_VIDEO(self)->out.height, TMEDIA_CODEC_VIDEO(self)->out.fps),
+ self->encoder.max_bw_kpbs
+ );
+ self->encoder.context->bit_rate = (max_bw_kpbs * 1024);// bps
#if LIBAVCODEC_VERSION_MAJOR <= 53
- self->encoder.context->rc_lookahead = 0;
+ self->encoder.context->rc_lookahead = 0;
#endif
- self->encoder.context->global_quality = FF_QP2LAMBDA * self->encoder.quality;
-
- self->encoder.context->thread_count = 0;
- self->encoder.context->rtp_payload_size = THEORA_RTP_PAYLOAD_SIZE;
- self->encoder.context->opaque = tsk_null;
- self->encoder.context->gop_size = (TMEDIA_CODEC_VIDEO(self)->out.fps * THEORA_GOP_SIZE_IN_SECONDS);
-
- // Picture (YUV 420)
- if(!(self->encoder.picture = avcodec_alloc_frame())){
- TSK_DEBUG_ERROR("Failed to create encoder picture");
- return -2;
- }
- avcodec_get_frame_defaults(self->encoder.picture);
-
- size = avpicture_get_size(PIX_FMT_YUV420P, self->encoder.context->width, self->encoder.context->height);
- if(!(self->encoder.buffer = tsk_calloc(size, sizeof(uint8_t)))){
- TSK_DEBUG_ERROR("Failed to allocate encoder buffer");
- return -2;
- }
-
- // Open encoder
- if((ret = avcodec_open(self->encoder.context, self->encoder.codec)) < 0){
- TSK_DEBUG_ERROR("Failed to open Theora encoder");
- return ret;
- }
-
- self->encoder.conf_last = 0;
- self->encoder.conf_count = 0;
-
- TSK_DEBUG_INFO("[THEORA] bitrate=%d bps", self->encoder.context->bit_rate);
-
- return ret;
+ self->encoder.context->global_quality = FF_QP2LAMBDA * self->encoder.quality;
+
+ self->encoder.context->thread_count = 0;
+ self->encoder.context->rtp_payload_size = THEORA_RTP_PAYLOAD_SIZE;
+ self->encoder.context->opaque = tsk_null;
+ self->encoder.context->gop_size = (TMEDIA_CODEC_VIDEO(self)->out.fps * THEORA_GOP_SIZE_IN_SECONDS);
+
+ // Picture (YUV 420)
+ if(!(self->encoder.picture = avcodec_alloc_frame())) {
+ TSK_DEBUG_ERROR("Failed to create encoder picture");
+ return -2;
+ }
+ avcodec_get_frame_defaults(self->encoder.picture);
+
+ size = avpicture_get_size(PIX_FMT_YUV420P, self->encoder.context->width, self->encoder.context->height);
+ if(!(self->encoder.buffer = tsk_calloc(size, sizeof(uint8_t)))) {
+ TSK_DEBUG_ERROR("Failed to allocate encoder buffer");
+ return -2;
+ }
+
+ // Open encoder
+ if((ret = avcodec_open(self->encoder.context, self->encoder.codec)) < 0) {
+ TSK_DEBUG_ERROR("Failed to open Theora encoder");
+ return ret;
+ }
+
+ self->encoder.conf_last = 0;
+ self->encoder.conf_count = 0;
+
+ TSK_DEBUG_INFO("[THEORA] bitrate=%d bps", self->encoder.context->bit_rate);
+
+ return ret;
}
int tdav_codec_theora_open_decoder(tdav_codec_theora_t* self)
{
- int size;
- if(!self->decoder.codec && !(self->decoder.codec = avcodec_find_decoder(CODEC_ID_THEORA))){
- TSK_DEBUG_ERROR("Failed to find Theora decoder");
- return -1;
- }
- if(self->decoder.context){
- TSK_DEBUG_ERROR("Decoder already opened");
- return -1;
- }
- self->decoder.context = avcodec_alloc_context();
- avcodec_get_context_defaults(self->decoder.context);
-
- self->decoder.context->pix_fmt = PIX_FMT_YUV420P;
- self->decoder.context->width = TMEDIA_CODEC_VIDEO(self)->in.width;
- self->decoder.context->height = TMEDIA_CODEC_VIDEO(self)->in.height;
-
- // Picture (YUV 420)
- if(!(self->decoder.picture = avcodec_alloc_frame())){
- TSK_DEBUG_ERROR("Failed to create decoder picture");
- return -2;
- }
- avcodec_get_frame_defaults(self->decoder.picture);
-
- size = avpicture_get_size(PIX_FMT_YUV420P, self->decoder.context->width, self->decoder.context->height);
- if(!(self->decoder.accumulator = tsk_calloc((size + FF_INPUT_BUFFER_PADDING_SIZE), sizeof(uint8_t)))){
- TSK_DEBUG_ERROR("Failed to allocate decoder buffer");
- return -2;
- }
-
- if(!(self->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(self->decoder.context, self->decoder.codec)) < 0){
- // TSK_DEBUG_ERROR("Failed to open Theora decoder");
- // return ret;
- //}
-
- return 0;
+ int size;
+ if(!self->decoder.codec && !(self->decoder.codec = avcodec_find_decoder(CODEC_ID_THEORA))) {
+ TSK_DEBUG_ERROR("Failed to find Theora decoder");
+ return -1;
+ }
+ if(self->decoder.context) {
+ TSK_DEBUG_ERROR("Decoder already opened");
+ return -1;
+ }
+ self->decoder.context = avcodec_alloc_context();
+ avcodec_get_context_defaults(self->decoder.context);
+
+ self->decoder.context->pix_fmt = PIX_FMT_YUV420P;
+ self->decoder.context->width = TMEDIA_CODEC_VIDEO(self)->in.width;
+ self->decoder.context->height = TMEDIA_CODEC_VIDEO(self)->in.height;
+
+ // Picture (YUV 420)
+ if(!(self->decoder.picture = avcodec_alloc_frame())) {
+ TSK_DEBUG_ERROR("Failed to create decoder picture");
+ return -2;
+ }
+ avcodec_get_frame_defaults(self->decoder.picture);
+
+ size = avpicture_get_size(PIX_FMT_YUV420P, self->decoder.context->width, self->decoder.context->height);
+ if(!(self->decoder.accumulator = tsk_calloc((size + FF_INPUT_BUFFER_PADDING_SIZE), sizeof(uint8_t)))) {
+ TSK_DEBUG_ERROR("Failed to allocate decoder buffer");
+ return -2;
+ }
+
+ if(!(self->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(self->decoder.context, self->decoder.codec)) < 0){
+ // TSK_DEBUG_ERROR("Failed to open Theora decoder");
+ // return ret;
+ //}
+
+ return 0;
}
int tdav_codec_theora_close_encoder(tdav_codec_theora_t* self)
{
- if(self->encoder.context){
- avcodec_close(self->encoder.context);
- av_free(self->encoder.context);
- self->encoder.context = tsk_null;
- }
- if(self->encoder.picture){
- av_free(self->encoder.picture);
- self->encoder.picture = tsk_null;
- }
- if(self->encoder.buffer){
- TSK_FREE(self->encoder.buffer);
- }
- return 0;
+ if(self->encoder.context) {
+ avcodec_close(self->encoder.context);
+ av_free(self->encoder.context);
+ self->encoder.context = tsk_null;
+ }
+ if(self->encoder.picture) {
+ av_free(self->encoder.picture);
+ self->encoder.picture = tsk_null;
+ }
+ if(self->encoder.buffer) {
+ TSK_FREE(self->encoder.buffer);
+ }
+ return 0;
}
int tdav_codec_theora_close_decoder(tdav_codec_theora_t* self)
{
- if(self->decoder.context){
- avcodec_close(self->decoder.context);
- if(self->decoder.context->extradata){
- TSK_FREE(self->decoder.context->extradata);
- self->decoder.context->extradata_size = 0;
- }
- av_free(self->decoder.context);
- self->decoder.context = tsk_null;
- }
- if(self->decoder.picture){
- av_free(self->decoder.picture);
- self->decoder.picture = tsk_null;
- }
- if(self->decoder.accumulator){
- TSK_FREE(self->decoder.accumulator);
- }
- return 0;
+ if(self->decoder.context) {
+ avcodec_close(self->decoder.context);
+ if(self->decoder.context->extradata) {
+ TSK_FREE(self->decoder.context->extradata);
+ self->decoder.context->extradata_size = 0;
+ }
+ av_free(self->decoder.context);
+ self->decoder.context = tsk_null;
+ }
+ if(self->decoder.picture) {
+ av_free(self->decoder.picture);
+ self->decoder.picture = tsk_null;
+ }
+ if(self->decoder.accumulator) {
+ TSK_FREE(self->decoder.accumulator);
+ }
+ return 0;
}
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_now()){
- 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_now();
- theora->encoder.conf_count++;
- }
- }
-
- /* Send Theora Raw data */
- tdav_codec_theora_send(theora, pdata, size, Raw_Theora_payload);
+ 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_now()) {
+ 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_now();
+ 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] = (uint8_t)(pay_size >> 8), pay_hdr[5] = (uint8_t)(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)->out.callback){
- TMEDIA_CODEC_VIDEO(self)->out.result.buffer.ptr = self->rtp.ptr;
- TMEDIA_CODEC_VIDEO(self)->out.result.buffer.size = (pay_size + sizeof(pay_hdr));
- TMEDIA_CODEC_VIDEO(self)->out.result.duration = (1./(double)TMEDIA_CODEC_VIDEO(self)->out.fps) * TMEDIA_CODEC(self)->plugin->rate;
- TMEDIA_CODEC_VIDEO(self)->out.result.last_chunck = (size == 0);
- TMEDIA_CODEC_VIDEO(self)->out.callback(&TMEDIA_CODEC_VIDEO(self)->out.result);
- }
- }
-
- return 0;
+{
+ /* 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] = (uint8_t)(pay_size >> 8), pay_hdr[5] = (uint8_t)(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)->out.callback) {
+ TMEDIA_CODEC_VIDEO(self)->out.result.buffer.ptr = self->rtp.ptr;
+ TMEDIA_CODEC_VIDEO(self)->out.result.buffer.size = (pay_size + sizeof(pay_hdr));
+ TMEDIA_CODEC_VIDEO(self)->out.result.duration = (1./(double)TMEDIA_CODEC_VIDEO(self)->out.fps) * TMEDIA_CODEC(self)->plugin->rate;
+ TMEDIA_CODEC_VIDEO(self)->out.result.last_chunck = (size == 0);
+ TMEDIA_CODEC_VIDEO(self)->out.callback(&TMEDIA_CODEC_VIDEO(self)->out.result);
+ }
+ }
+
+ return 0;
}
tsk_bool_t tdav_codec_ffmpeg_theora_is_supported()
{
- return (avcodec_find_encoder(CODEC_ID_THEORA) && avcodec_find_decoder(CODEC_ID_THEORA));
+ return (avcodec_find_encoder(CODEC_ID_THEORA) && avcodec_find_decoder(CODEC_ID_THEORA));
}
#endif /* HAVE_FFMPEG */ \ No newline at end of file
diff --git a/tinyDAV/src/codecs/vpx/tdav_codec_vp8.c b/tinyDAV/src/codecs/vpx/tdav_codec_vp8.c
index 5ed2f80..25434c8 100755
--- a/tinyDAV/src/codecs/vpx/tdav_codec_vp8.c
+++ b/tinyDAV/src/codecs/vpx/tdav_codec_vp8.c
@@ -70,43 +70,42 @@
#endif
/* VP8 codec */
-typedef struct tdav_codec_vp8_s
-{
- TMEDIA_DECLARE_CODEC_VIDEO;
-
- // Encoder
- struct {
- vpx_codec_enc_cfg_t cfg;
- tsk_bool_t initialized;
- vpx_codec_pts_t pts;
- vpx_codec_ctx_t context;
- unsigned pic_id : 15;
- uint64_t frame_count;
- tsk_bool_t force_idr;
- int rotation;
-
- struct {
- uint8_t* ptr;
- tsk_size_t size;
- } rtp;
-
- tsk_mutex_handle_t* mutex;
- } encoder;
-
- // decoder
- struct {
- vpx_codec_dec_cfg_t cfg;
- unsigned initialized : 1;
- vpx_codec_ctx_t context;
- void* accumulator;
- tsk_size_t accumulator_pos;
- tsk_size_t accumulator_size;
- tsk_size_t first_part_size;
- uint16_t last_seq;
- uint32_t last_timestamp;
- tsk_bool_t idr;
- tsk_bool_t corrupted;
- } decoder;
+typedef struct tdav_codec_vp8_s {
+ TMEDIA_DECLARE_CODEC_VIDEO;
+
+ // Encoder
+ struct {
+ vpx_codec_enc_cfg_t cfg;
+ tsk_bool_t initialized;
+ vpx_codec_pts_t pts;
+ vpx_codec_ctx_t context;
+ unsigned pic_id : 15;
+ uint64_t frame_count;
+ tsk_bool_t force_idr;
+ int rotation;
+
+ struct {
+ uint8_t* ptr;
+ tsk_size_t size;
+ } rtp;
+
+ tsk_mutex_handle_t* mutex;
+ } encoder;
+
+ // decoder
+ struct {
+ vpx_codec_dec_cfg_t cfg;
+ unsigned initialized : 1;
+ vpx_codec_ctx_t context;
+ void* accumulator;
+ tsk_size_t accumulator_pos;
+ tsk_size_t accumulator_size;
+ tsk_size_t first_part_size;
+ uint16_t last_seq;
+ uint32_t last_timestamp;
+ tsk_bool_t idr;
+ tsk_bool_t corrupted;
+ } decoder;
}
tdav_codec_vp8_t;
@@ -125,500 +124,508 @@ static void tdav_codec_vp8_rtp_callback(tdav_codec_vp8_t *self, const void *data
static int tdav_codec_vp8_set(tmedia_codec_t* self, const tmedia_param_t* param)
{
- tdav_codec_vp8_t* vp8 = (tdav_codec_vp8_t*)self;
- vpx_codec_err_t vpx_ret = VPX_CODEC_OK;
- tsk_bool_t reconf = tsk_false;
-
- if (param->value_type == tmedia_pvt_int32) {
- if (tsk_striequals(param->key, "action")) {
- tmedia_codec_action_t action = (tmedia_codec_action_t)TSK_TO_INT32((uint8_t*)param->value);
- switch (action) {
- case tmedia_codec_action_encode_idr:
- {
- vp8->encoder.force_idr = tsk_true;
- return 0;
- }
- case tmedia_codec_action_bw_down:
- {
- vp8->encoder.cfg.rc_target_bitrate = TSK_CLAMP(0, (int32_t)((vp8->encoder.cfg.rc_target_bitrate << 1) / 3), TMEDIA_CODEC(vp8)->bandwidth_max_upload);
- TSK_DEBUG_INFO("New target bitrate = %d kbps", vp8->encoder.cfg.rc_target_bitrate);
- reconf = tsk_true;
- break;
- }
- case tmedia_codec_action_bw_up:
- {
- vp8->encoder.cfg.rc_target_bitrate = TSK_CLAMP(0, (int32_t)((vp8->encoder.cfg.rc_target_bitrate * 3) >> 1), TMEDIA_CODEC(vp8)->bandwidth_max_upload);
- TSK_DEBUG_INFO("New target bitrate = %d kbps", vp8->encoder.cfg.rc_target_bitrate);
- reconf = tsk_true;
- break;
- }
- }
- }
- else if (tsk_striequals(param->key, "bw_kbps")) { // both up and down (from the SDP)
- int32_t max_bw_userdefine = tmedia_defaults_get_bandwidth_video_upload_max();
- int32_t max_bw_new = *((int32_t*)param->value);
- if (max_bw_userdefine > 0) {
- // do not use more than what the user defined in it's configuration
- TMEDIA_CODEC(vp8)->bandwidth_max_upload = TSK_MIN(max_bw_new, max_bw_userdefine);
- }
- else {
- TMEDIA_CODEC(vp8)->bandwidth_max_upload = max_bw_new;
- }
+ tdav_codec_vp8_t* vp8 = (tdav_codec_vp8_t*)self;
+ vpx_codec_err_t vpx_ret = VPX_CODEC_OK;
+ tsk_bool_t reconf = tsk_false;
+
+ if (param->value_type == tmedia_pvt_int32) {
+ if (tsk_striequals(param->key, "action")) {
+ tmedia_codec_action_t action = (tmedia_codec_action_t)TSK_TO_INT32((uint8_t*)param->value);
+ switch (action) {
+ case tmedia_codec_action_encode_idr: {
+ vp8->encoder.force_idr = tsk_true;
+ return 0;
+ }
+ case tmedia_codec_action_bw_down: {
+ vp8->encoder.cfg.rc_target_bitrate = TSK_CLAMP(0, (int32_t)((vp8->encoder.cfg.rc_target_bitrate << 1) / 3), TMEDIA_CODEC(vp8)->bandwidth_max_upload);
+ TSK_DEBUG_INFO("New target bitrate = %d kbps", vp8->encoder.cfg.rc_target_bitrate);
+ reconf = tsk_true;
+ break;
+ }
+ case tmedia_codec_action_bw_up: {
+ vp8->encoder.cfg.rc_target_bitrate = TSK_CLAMP(0, (int32_t)((vp8->encoder.cfg.rc_target_bitrate * 3) >> 1), TMEDIA_CODEC(vp8)->bandwidth_max_upload);
+ TSK_DEBUG_INFO("New target bitrate = %d kbps", vp8->encoder.cfg.rc_target_bitrate);
+ reconf = tsk_true;
+ break;
+ }
+ }
+ }
+ else if (tsk_striequals(param->key, "bw_kbps")) { // both up and down (from the SDP)
+ int32_t max_bw_userdefine = tmedia_defaults_get_bandwidth_video_upload_max();
+ int32_t max_bw_new = *((int32_t*)param->value);
+ if (max_bw_userdefine > 0) {
+ // do not use more than what the user defined in it's configuration
+ TMEDIA_CODEC(vp8)->bandwidth_max_upload = TSK_MIN(max_bw_new, max_bw_userdefine);
+ }
+ else {
+ TMEDIA_CODEC(vp8)->bandwidth_max_upload = max_bw_new;
+ }
vp8->encoder.cfg.rc_target_bitrate = TSK_CLAMP(0, (unsigned int)vp8->encoder.cfg.rc_target_bitrate, (unsigned int)TMEDIA_CODEC(vp8)->bandwidth_max_upload);
TSK_DEBUG_INFO("New target bitrate = %d kbps", vp8->encoder.cfg.rc_target_bitrate);
- reconf = tsk_true;
- }
- else if (tsk_striequals(param->key, "bandwidth-max-upload")) {
- int32_t bw_max_upload = *((int32_t*)param->value);
- TSK_DEBUG_INFO("VP8 codec: bandwidth-max-upload=%d", bw_max_upload);
- TMEDIA_CODEC(vp8)->bandwidth_max_upload = bw_max_upload;
- reconf = tsk_true;
- }
- else if (tsk_striequals(param->key, "rotation")) {
- // IMPORTANT: changing resolution requires at least libvpx v1.1.0 "Eider"
- int32_t rotation = *((int32_t*)param->value);
- if (vp8->encoder.rotation != rotation) {
- vp8->encoder.rotation = rotation;
- vp8->encoder.cfg.g_w = (rotation == 90 || rotation == 270) ? TMEDIA_CODEC_VIDEO(vp8)->out.height : TMEDIA_CODEC_VIDEO(vp8)->out.width;
- vp8->encoder.cfg.g_h = (rotation == 90 || rotation == 270) ? TMEDIA_CODEC_VIDEO(vp8)->out.width : TMEDIA_CODEC_VIDEO(vp8)->out.height;
- reconf = tsk_true;
- }
- }
- }
-
- if (reconf) {
- if (vp8->encoder.initialized) {
- // The encoder isn't thread safe. Without this lock (and the one in the encode() function) we may have corruptions in the video (issue report from GE).
- // Google says the encoder is thread-safe but this is not the case. But it is *multi-instance* thread-safe.
- tsk_mutex_lock(vp8->encoder.mutex);
- if ((vpx_ret = vpx_codec_enc_config_set(&vp8->encoder.context, &vp8->encoder.cfg)) != VPX_CODEC_OK) {
- TSK_DEBUG_ERROR("vpx_codec_enc_config_set failed with error =%s", vpx_codec_err_to_string(vpx_ret));
- }
- tsk_mutex_unlock(vp8->encoder.mutex);
- }
- return (vpx_ret == VPX_CODEC_OK) ? 0 : -2;
- }
-
- return -1;
+ reconf = tsk_true;
+ }
+ else if (tsk_striequals(param->key, "bandwidth-max-upload")) {
+ int32_t bw_max_upload = *((int32_t*)param->value);
+ TSK_DEBUG_INFO("VP8 codec: bandwidth-max-upload=%d", bw_max_upload);
+ TMEDIA_CODEC(vp8)->bandwidth_max_upload = bw_max_upload;
+ reconf = tsk_true;
+ }
+ else if (tsk_striequals(param->key, "rotation")) {
+ // IMPORTANT: changing resolution requires at least libvpx v1.1.0 "Eider"
+ int32_t rotation = *((int32_t*)param->value);
+ if (vp8->encoder.rotation != rotation) {
+ vp8->encoder.rotation = rotation;
+ vp8->encoder.cfg.g_w = (rotation == 90 || rotation == 270) ? TMEDIA_CODEC_VIDEO(vp8)->out.height : TMEDIA_CODEC_VIDEO(vp8)->out.width;
+ vp8->encoder.cfg.g_h = (rotation == 90 || rotation == 270) ? TMEDIA_CODEC_VIDEO(vp8)->out.width : TMEDIA_CODEC_VIDEO(vp8)->out.height;
+ reconf = tsk_true;
+ }
+ }
+ }
+
+ if (reconf) {
+ if (vp8->encoder.initialized) {
+ // The encoder isn't thread safe. Without this lock (and the one in the encode() function) we may have corruptions in the video (issue report from GE).
+ // Google says the encoder is thread-safe but this is not the case. But it is *multi-instance* thread-safe.
+ tsk_mutex_lock(vp8->encoder.mutex);
+ if ((vpx_ret = vpx_codec_enc_config_set(&vp8->encoder.context, &vp8->encoder.cfg)) != VPX_CODEC_OK) {
+ TSK_DEBUG_ERROR("vpx_codec_enc_config_set failed with error =%s", vpx_codec_err_to_string(vpx_ret));
+ }
+ tsk_mutex_unlock(vp8->encoder.mutex);
+ }
+ return (vpx_ret == VPX_CODEC_OK) ? 0 : -2;
+ }
+
+ return -1;
}
static int tdav_codec_vp8_open(tmedia_codec_t* self)
{
- tdav_codec_vp8_t* vp8 = (tdav_codec_vp8_t*)self;
- int ret;
+ tdav_codec_vp8_t* vp8 = (tdav_codec_vp8_t*)self;
+ int ret;
- if (!vp8) {
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
+ if (!vp8) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
- /* the caller (base class) already checked that the codec is not opened */
+ /* the caller (base class) already checked that the codec is not opened */
- // Encoder
- if ((ret = tdav_codec_vp8_open_encoder(vp8))) {
- return ret;
- }
+ // Encoder
+ if ((ret = tdav_codec_vp8_open_encoder(vp8))) {
+ return ret;
+ }
- // Decoder
- if ((ret = tdav_codec_vp8_open_decoder(vp8))) {
- return ret;
- }
+ // Decoder
+ if ((ret = tdav_codec_vp8_open_decoder(vp8))) {
+ return ret;
+ }
- return ret;
+ return ret;
}
static int tdav_codec_vp8_close(tmedia_codec_t* self)
{
- tdav_codec_vp8_t* vp8 = (tdav_codec_vp8_t*)self;
+ tdav_codec_vp8_t* vp8 = (tdav_codec_vp8_t*)self;
- if (!vp8) {
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
+ if (!vp8) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
- tdav_codec_vp8_close_encoder(vp8);
- tdav_codec_vp8_close_decoder(vp8);
+ tdav_codec_vp8_close_encoder(vp8);
+ tdav_codec_vp8_close_decoder(vp8);
- return 0;
+ return 0;
}
static tsk_size_t tdav_codec_vp8_encode(tmedia_codec_t* self, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size)
{
- tdav_codec_vp8_t* vp8 = (tdav_codec_vp8_t*)self;
- vpx_enc_frame_flags_t flags = 0;
- vpx_codec_err_t vpx_ret = VPX_CODEC_OK;
- const vpx_codec_cx_pkt_t *pkt;
- vpx_codec_iter_t iter = tsk_null;
- vpx_image_t image = {0};
-
- if (!vp8 || !in_data || !in_size) {
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- if (in_size != (vp8->encoder.context.config.enc->g_w * vp8->encoder.context.config.enc->g_h * 3) >> 1) {
- TSK_DEBUG_ERROR("Invalid size");
- return 0;
- }
-
- // wrap yuv420 buffer
- if (!vpx_img_wrap(&image, VPX_IMG_FMT_I420, vp8->encoder.context.config.enc->g_w, vp8->encoder.context.config.enc->g_h, 1, (unsigned char*)in_data)) {
- TSK_DEBUG_ERROR("vpx_img_wrap failed");
- return 0;
- }
-
- // encode data
- ++vp8->encoder.pts;
- if (vp8->encoder.force_idr) {
- flags |= VPX_EFLAG_FORCE_KF;
- vp8->encoder.force_idr = tsk_false;
- }
- tsk_mutex_lock(vp8->encoder.mutex); // must
- vpx_ret = vpx_codec_encode(&vp8->encoder.context, &image, vp8->encoder.pts, 1, flags, VPX_DL_REALTIME);
- tsk_mutex_unlock(vp8->encoder.mutex);
-
- if (vpx_ret != VPX_CODEC_OK) {
- TSK_DEBUG_ERROR("vpx_codec_encode failed with error =%s", vpx_codec_err_to_string(vpx_ret));
- goto bail;
- }
-
- ++vp8->encoder.frame_count;
- ++vp8->encoder.pic_id;
-
- while ((pkt = vpx_codec_get_cx_data(&vp8->encoder.context, &iter))) {
- switch (pkt->kind) {
- case VPX_CODEC_CX_FRAME_PKT:
- {
- tdav_codec_vp8_encap(vp8, pkt);
- break;
- }
- default:
- case VPX_CODEC_STATS_PKT: /**< Two-pass statistics for this frame */
- case VPX_CODEC_PSNR_PKT: /**< PSNR statistics for this frame */
- case VPX_CODEC_CUSTOM_PKT: /**< Algorithm extensions */
- {
- TSK_DEBUG_INFO("pkt->kind=%d not supported", (int)pkt->kind);
- break;
- }
- }
- }
+ tdav_codec_vp8_t* vp8 = (tdav_codec_vp8_t*)self;
+ vpx_enc_frame_flags_t flags = 0;
+ vpx_codec_err_t vpx_ret = VPX_CODEC_OK;
+ const vpx_codec_cx_pkt_t *pkt;
+ vpx_codec_iter_t iter = tsk_null;
+ vpx_image_t image = {0};
+
+ if (!vp8 || !in_data || !in_size) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ if (in_size != (vp8->encoder.context.config.enc->g_w * vp8->encoder.context.config.enc->g_h * 3) >> 1) {
+ TSK_DEBUG_ERROR("Invalid size");
+ return 0;
+ }
+
+ // wrap yuv420 buffer
+ if (!vpx_img_wrap(&image, VPX_IMG_FMT_I420, vp8->encoder.context.config.enc->g_w, vp8->encoder.context.config.enc->g_h, 1, (unsigned char*)in_data)) {
+ TSK_DEBUG_ERROR("vpx_img_wrap failed");
+ return 0;
+ }
+
+ // encode data
+ ++vp8->encoder.pts;
+ if (vp8->encoder.force_idr) {
+ flags |= VPX_EFLAG_FORCE_KF;
+ vp8->encoder.force_idr = tsk_false;
+ }
+ tsk_mutex_lock(vp8->encoder.mutex); // must
+ vpx_ret = vpx_codec_encode(&vp8->encoder.context, &image, vp8->encoder.pts, 1, flags, VPX_DL_REALTIME);
+ tsk_mutex_unlock(vp8->encoder.mutex);
+
+ if (vpx_ret != VPX_CODEC_OK) {
+ TSK_DEBUG_ERROR("vpx_codec_encode failed with error =%s", vpx_codec_err_to_string(vpx_ret));
+ goto bail;
+ }
+
+ ++vp8->encoder.frame_count;
+ ++vp8->encoder.pic_id;
+
+ while ((pkt = vpx_codec_get_cx_data(&vp8->encoder.context, &iter))) {
+ switch (pkt->kind) {
+ case VPX_CODEC_CX_FRAME_PKT: {
+ tdav_codec_vp8_encap(vp8, pkt);
+ break;
+ }
+ default:
+ case VPX_CODEC_STATS_PKT: /**< Two-pass statistics for this frame */
+ case VPX_CODEC_PSNR_PKT: /**< PSNR statistics for this frame */
+ case VPX_CODEC_CUSTOM_PKT: { /**< Algorithm extensions */
+ TSK_DEBUG_INFO("pkt->kind=%d not supported", (int)pkt->kind);
+ break;
+ }
+ }
+ }
bail:
- vpx_img_free(&image);
- return 0;
+ vpx_img_free(&image);
+ return 0;
}
static tsk_size_t tdav_codec_vp8_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)
{
- tdav_codec_vp8_t* vp8 = (tdav_codec_vp8_t*)self;
- const trtp_rtp_header_t* rtp_hdr = proto_hdr;
- const uint8_t* pdata = in_data;
- const uint8_t* pdata_end = (pdata + in_size);
- tsk_size_t ret = 0;
- tsk_bool_t fatal_error = tsk_false;
- static const tsk_size_t xmax_size = (3840 * 2160 * 3) >> 3; // >>3 instead of >>1 (not an error)
- uint8_t S, PartID;
-
- if (!self || !in_data || in_size < 1 || !out_data || !vp8->decoder.initialized) {
- TSK_DEBUG_ERROR("Invalid parameter");
- return 0;
- }
-
- { /* 4.2. VP8 Payload Descriptor */
- uint8_t X, R, N, I, L, T, K;//TODO: store
-
- X = ((*pdata & 0x80) >> 7);
- R = ((*pdata & 0x40) >> 6);
- if (R) {
- TSK_DEBUG_ERROR("R<>0");
- fatal_error = tsk_true;
- goto bail;
- }
- N = ((*pdata & 0x20) >> 5);
- S = ((*pdata & 0x10) >> 4);
- PartID = (*pdata & 0x0F);
- // skip "REQUIRED" header
- if (++pdata >= pdata_end) {
- TSK_DEBUG_ERROR("Too short"); goto bail;
- }
- // check "OPTIONAL" headers
- if (X) {
- I = (*pdata & 0x80);
- L = (*pdata & 0x40);
- T = (*pdata & 0x20);
- K = (*pdata & 0x10);
- if (++pdata >= pdata_end) {
- TSK_DEBUG_ERROR("Too short"); goto bail;
- }
-
- if (I) {
- if (*pdata & 0x80) { // M
- // PictureID on 16bits
- if ((pdata += 2) >= pdata_end) {
- TSK_DEBUG_ERROR("Too short"); goto bail;
- }
- }
- else {
- // PictureID on 8bits
- if (++pdata >= pdata_end) {
- TSK_DEBUG_ERROR("Too short"); goto bail;
- }
- }
- }
- if (L) {
- if (++pdata >= pdata_end) {
- TSK_DEBUG_ERROR("Too short"); goto bail;
- }
- }
- if (T || K) {
- if (++pdata >= pdata_end) {
- TSK_DEBUG_ERROR("Too short"); goto bail;
- }
- }
- }
- }
-
- in_size = (pdata_end - pdata);
-
- // Packet lost?
- if (vp8->decoder.last_seq && (vp8->decoder.last_seq + 1) != rtp_hdr->seq_num) {
- TSK_DEBUG_INFO("[VP8] Packet loss, seq_num=%d", (vp8->decoder.last_seq + 1));
- vp8->decoder.corrupted = tsk_true;
- }
- vp8->decoder.last_seq = rtp_hdr->seq_num;
-
- // New frame ?
- if (vp8->decoder.last_timestamp != rtp_hdr->timestamp) {
- /* 4.3. VP8 Payload Header
- Note that the header is present only in packets
- which have the S bit equal to one and the PartID equal to zero in the
- payload descriptor. Subsequent packets for the same frame do not
- carry the payload header.
- 0 1 2 3 4 5 6 7
- +-+-+-+-+-+-+-+-+
- |Size0|H| VER |P|
- +-+-+-+-+-+-+-+-+
- | Size1 |
- +-+-+-+-+-+-+-+-+
- | Size2 |
- +-+-+-+-+-+-+-+-+
- | Bytes 4..N of |
- | VP8 payload |
- : :
- +-+-+-+-+-+-+-+-+
- | OPTIONAL RTP |
- | padding |
- : :
- +-+-+-+-+-+-+-+-+
- P: Inverse key frame flag. When set to 0 the current frame is a key
- frame. When set to 1 the current frame is an interframe. Defined
- in [RFC6386]
- */
-
- // Reset accumulator position
- vp8->decoder.accumulator_pos = 0;
-
- // Make sure the header is present
- if (S != 1 || PartID != 0 || in_size < 3) {
- TSK_DEBUG_WARN("VP8 payload header is missing");
+ tdav_codec_vp8_t* vp8 = (tdav_codec_vp8_t*)self;
+ const trtp_rtp_header_t* rtp_hdr = proto_hdr;
+ const uint8_t* pdata = in_data;
+ const uint8_t* pdata_end = (pdata + in_size);
+ tsk_size_t ret = 0;
+ tsk_bool_t fatal_error = tsk_false;
+ static const tsk_size_t xmax_size = (3840 * 2160 * 3) >> 3; // >>3 instead of >>1 (not an error)
+ uint8_t S, PartID;
+
+ if (!self || !in_data || in_size < 1 || !out_data || !vp8->decoder.initialized) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+
+ { /* 4.2. VP8 Payload Descriptor */
+ uint8_t X, R, N, I, L, T, K;//TODO: store
+
+ X = ((*pdata & 0x80) >> 7);
+ R = ((*pdata & 0x40) >> 6);
+ if (R) {
+ TSK_DEBUG_ERROR("R<>0");
+ fatal_error = tsk_true;
+ goto bail;
+ }
+ N = ((*pdata & 0x20) >> 5);
+ S = ((*pdata & 0x10) >> 4);
+ PartID = (*pdata & 0x0F);
+ // skip "REQUIRED" header
+ if (++pdata >= pdata_end) {
+ TSK_DEBUG_ERROR("Too short");
+ goto bail;
+ }
+ // check "OPTIONAL" headers
+ if (X) {
+ I = (*pdata & 0x80);
+ L = (*pdata & 0x40);
+ T = (*pdata & 0x20);
+ K = (*pdata & 0x10);
+ if (++pdata >= pdata_end) {
+ TSK_DEBUG_ERROR("Too short");
+ goto bail;
+ }
+
+ if (I) {
+ if (*pdata & 0x80) { // M
+ // PictureID on 16bits
+ if ((pdata += 2) >= pdata_end) {
+ TSK_DEBUG_ERROR("Too short");
+ goto bail;
+ }
+ }
+ else {
+ // PictureID on 8bits
+ if (++pdata >= pdata_end) {
+ TSK_DEBUG_ERROR("Too short");
+ goto bail;
+ }
+ }
+ }
+ if (L) {
+ if (++pdata >= pdata_end) {
+ TSK_DEBUG_ERROR("Too short");
+ goto bail;
+ }
+ }
+ if (T || K) {
+ if (++pdata >= pdata_end) {
+ TSK_DEBUG_ERROR("Too short");
+ goto bail;
+ }
+ }
+ }
+ }
+
+ in_size = (pdata_end - pdata);
+
+ // Packet lost?
+ if (vp8->decoder.last_seq && (vp8->decoder.last_seq + 1) != rtp_hdr->seq_num) {
+ TSK_DEBUG_INFO("[VP8] Packet loss, seq_num=%d", (vp8->decoder.last_seq + 1));
+ vp8->decoder.corrupted = tsk_true;
+ }
+ vp8->decoder.last_seq = rtp_hdr->seq_num;
+
+ // New frame ?
+ if (vp8->decoder.last_timestamp != rtp_hdr->timestamp) {
+ /* 4.3. VP8 Payload Header
+ Note that the header is present only in packets
+ which have the S bit equal to one and the PartID equal to zero in the
+ payload descriptor. Subsequent packets for the same frame do not
+ carry the payload header.
+ 0 1 2 3 4 5 6 7
+ +-+-+-+-+-+-+-+-+
+ |Size0|H| VER |P|
+ +-+-+-+-+-+-+-+-+
+ | Size1 |
+ +-+-+-+-+-+-+-+-+
+ | Size2 |
+ +-+-+-+-+-+-+-+-+
+ | Bytes 4..N of |
+ | VP8 payload |
+ : :
+ +-+-+-+-+-+-+-+-+
+ | OPTIONAL RTP |
+ | padding |
+ : :
+ +-+-+-+-+-+-+-+-+
+ P: Inverse key frame flag. When set to 0 the current frame is a key
+ frame. When set to 1 the current frame is an interframe. Defined
+ in [RFC6386]
+ */
+
+ // Reset accumulator position
+ vp8->decoder.accumulator_pos = 0;
+
+ // Make sure the header is present
+ if (S != 1 || PartID != 0 || in_size < 3) {
+ TSK_DEBUG_WARN("VP8 payload header is missing");
#if 0
- if (in_size < 3)
+ if (in_size < 3)
#endif
- {
- fatal_error = tsk_true;
- goto bail;
- }
- }
- {
- /* SizeN: The size of the first partition in bytes is calculated from
- the 19 bits in Size0, Size1, and Size2 as 1stPartitionSize = Size0
- + 8 * Size1 + 2048 * Size2. [RFC6386]. */
- vp8->decoder.first_part_size = ((pdata[0] >> 5) & 0xFF) + 8 * pdata[1] + 2048 * pdata[2];
- }
-
- // Starting new frame...reset "corrupted" value
- vp8->decoder.corrupted = tsk_false;
-
- // Key frame?
- vp8->decoder.idr = !(pdata[0] & 0x01);
-
- // Update timestamp
- vp8->decoder.last_timestamp = rtp_hdr->timestamp;
- }
-
- if (in_size > xmax_size) {
- vp8->decoder.accumulator_pos = 0;
- TSK_DEBUG_ERROR("%u too big to contain valid encoded data. xmax_size=%u", (unsigned)in_size, (unsigned)xmax_size);
- fatal_error = tsk_true;
- goto bail;
- }
- // start-accumulator
- if (!vp8->decoder.accumulator) {
- if (!(vp8->decoder.accumulator = tsk_calloc(in_size, sizeof(uint8_t)))) {
- TSK_DEBUG_ERROR("Failed to allocated new buffer");
- fatal_error = tsk_true;
- goto bail;
- }
- vp8->decoder.accumulator_size = in_size;
- }
- if ((vp8->decoder.accumulator_pos + in_size) >= xmax_size) {
- TSK_DEBUG_ERROR("BufferOverflow");
- vp8->decoder.accumulator_pos = 0;
- fatal_error = tsk_true;
- goto bail;
- }
- if ((vp8->decoder.accumulator_pos + in_size) > vp8->decoder.accumulator_size) {
- if (!(vp8->decoder.accumulator = tsk_realloc(vp8->decoder.accumulator, (vp8->decoder.accumulator_pos + in_size)))) {
- TSK_DEBUG_ERROR("Failed to reallocated new buffer");
- vp8->decoder.accumulator_pos = 0;
- vp8->decoder.accumulator_size = 0;
- fatal_error = tsk_true;
- goto bail;
- }
- vp8->decoder.accumulator_size = (vp8->decoder.accumulator_pos + in_size);
- }
-
- memcpy(&((uint8_t*)vp8->decoder.accumulator)[vp8->decoder.accumulator_pos], pdata, in_size);
- vp8->decoder.accumulator_pos += in_size;
- // end-accumulator
-
- // Decode the frame if we have a marker or the first partition is complete and not corrupted
- if (rtp_hdr->marker /*|| (!vp8->decoder.corrupted && vp8->decoder.first_part_size == vp8->decoder.accumulator_pos)*/) {
- vpx_image_t *img;
- vpx_codec_iter_t iter = tsk_null;
- vpx_codec_err_t vpx_ret;
- const uint8_t* pay_ptr = (const uint8_t*)vp8->decoder.accumulator;
- const tsk_size_t pay_size = vp8->decoder.accumulator_pos;
-
- // in all cases: reset accumulator position
- vp8->decoder.accumulator_pos = 0;
+ {
+ fatal_error = tsk_true;
+ goto bail;
+ }
+ }
+ {
+ /* SizeN: The size of the first partition in bytes is calculated from
+ the 19 bits in Size0, Size1, and Size2 as 1stPartitionSize = Size0
+ + 8 * Size1 + 2048 * Size2. [RFC6386]. */
+ vp8->decoder.first_part_size = ((pdata[0] >> 5) & 0xFF) + 8 * pdata[1] + 2048 * pdata[2];
+ }
+
+ // Starting new frame...reset "corrupted" value
+ vp8->decoder.corrupted = tsk_false;
+
+ // Key frame?
+ vp8->decoder.idr = !(pdata[0] & 0x01);
+
+ // Update timestamp
+ vp8->decoder.last_timestamp = rtp_hdr->timestamp;
+ }
+
+ if (in_size > xmax_size) {
+ vp8->decoder.accumulator_pos = 0;
+ TSK_DEBUG_ERROR("%u too big to contain valid encoded data. xmax_size=%u", (unsigned)in_size, (unsigned)xmax_size);
+ fatal_error = tsk_true;
+ goto bail;
+ }
+ // start-accumulator
+ if (!vp8->decoder.accumulator) {
+ if (!(vp8->decoder.accumulator = tsk_calloc(in_size, sizeof(uint8_t)))) {
+ TSK_DEBUG_ERROR("Failed to allocated new buffer");
+ fatal_error = tsk_true;
+ goto bail;
+ }
+ vp8->decoder.accumulator_size = in_size;
+ }
+ if ((vp8->decoder.accumulator_pos + in_size) >= xmax_size) {
+ TSK_DEBUG_ERROR("BufferOverflow");
+ vp8->decoder.accumulator_pos = 0;
+ fatal_error = tsk_true;
+ goto bail;
+ }
+ if ((vp8->decoder.accumulator_pos + in_size) > vp8->decoder.accumulator_size) {
+ if (!(vp8->decoder.accumulator = tsk_realloc(vp8->decoder.accumulator, (vp8->decoder.accumulator_pos + in_size)))) {
+ TSK_DEBUG_ERROR("Failed to reallocated new buffer");
+ vp8->decoder.accumulator_pos = 0;
+ vp8->decoder.accumulator_size = 0;
+ fatal_error = tsk_true;
+ goto bail;
+ }
+ vp8->decoder.accumulator_size = (vp8->decoder.accumulator_pos + in_size);
+ }
+
+ memcpy(&((uint8_t*)vp8->decoder.accumulator)[vp8->decoder.accumulator_pos], pdata, in_size);
+ vp8->decoder.accumulator_pos += in_size;
+ // end-accumulator
+
+ // Decode the frame if we have a marker or the first partition is complete and not corrupted
+ if (rtp_hdr->marker /*|| (!vp8->decoder.corrupted && vp8->decoder.first_part_size == vp8->decoder.accumulator_pos)*/) {
+ vpx_image_t *img;
+ vpx_codec_iter_t iter = tsk_null;
+ vpx_codec_err_t vpx_ret;
+ const uint8_t* pay_ptr = (const uint8_t*)vp8->decoder.accumulator;
+ const tsk_size_t pay_size = vp8->decoder.accumulator_pos;
+
+ // in all cases: reset accumulator position
+ vp8->decoder.accumulator_pos = 0;
#if 0 /* http://groups.google.com/a/webmproject.org/group/apps-devel/browse_thread/thread/c84438e70fe122fa/2dfc322018aa22a8 */
- // libvpx will crash very ofen when the frame is corrupted => for now we decided not to decode such frame
- // according to the latest release there is a function to check if the frame
- // is corrupted or not => To be checked
- if(vp8->decoder.corrupted) {
- vp8->decoder.corrupted = tsk_false;
- goto bail;
- }
+ // libvpx will crash very ofen when the frame is corrupted => for now we decided not to decode such frame
+ // according to the latest release there is a function to check if the frame
+ // is corrupted or not => To be checked
+ if(vp8->decoder.corrupted) {
+ vp8->decoder.corrupted = tsk_false;
+ goto bail;
+ }
#endif
- if (pay_size < vp8->decoder.first_part_size) {
- TSK_DEBUG_WARN("[VP8] No enough bytes for the first part: %u < %u", (unsigned)pay_size, (unsigned)vp8->decoder.first_part_size);
- // Not a fatal error
- goto bail;
- }
-
- vpx_ret = vpx_codec_decode(&vp8->decoder.context, pay_ptr, (int)pay_size, tsk_null, 0);
-
- if (vpx_ret != VPX_CODEC_OK) {
- TSK_DEBUG_INFO("vpx_codec_decode failed with error =%s", vpx_codec_err_to_string(vpx_ret));
- fatal_error = tsk_true;
- goto bail;
- }
- else if (vp8->decoder.idr) {
- TSK_DEBUG_INFO("Decoded VP8 IDR");
- if (TMEDIA_CODEC_VIDEO(self)->in.callback) {
- TMEDIA_CODEC_VIDEO(self)->in.result.type = tmedia_video_decode_result_type_idr;
- TMEDIA_CODEC_VIDEO(self)->in.result.proto_hdr = proto_hdr;
- TMEDIA_CODEC_VIDEO(self)->in.callback(&TMEDIA_CODEC_VIDEO(self)->in.result);
- }
- }
-
- // copy decoded data
- ret = 0;
- while ((img = vpx_codec_get_frame(&vp8->decoder.context, &iter))) {
- unsigned int plane, y;
- tsk_size_t xsize;
-
- // update sizes
- TMEDIA_CODEC_VIDEO(vp8)->in.width = img->d_w;
- TMEDIA_CODEC_VIDEO(vp8)->in.height = img->d_h;
- xsize = (TMEDIA_CODEC_VIDEO(vp8)->in.width * TMEDIA_CODEC_VIDEO(vp8)->in.height * 3) >> 1;
- // allocate destination buffer
- if (*out_max_size < xsize) {
- if (!(*out_data = tsk_realloc(*out_data, xsize))) {
- TSK_DEBUG_ERROR("Failed to allocate new buffer");
- *out_max_size = 0;
- goto bail;
- }
- *out_max_size = xsize;
- }
-
- // layout picture
- for (plane = 0; plane < 3; plane++) {
- unsigned char *buf = img->planes[plane];
- for (y = 0; y < img->d_h >> (plane ? 1 : 0); y++) {
- unsigned int w_count = img->d_w >> (plane ? 1 : 0);
- if ((ret + w_count) > *out_max_size) {
- TSK_DEBUG_ERROR("BufferOverflow");
- ret = 0;
- goto bail;
- }
- memcpy(((uint8_t*)*out_data) + ret, buf, w_count);
- ret += w_count;
- buf += img->stride[plane];
- }
- }
- }
- }
+ if (pay_size < vp8->decoder.first_part_size) {
+ TSK_DEBUG_WARN("[VP8] No enough bytes for the first part: %u < %u", (unsigned)pay_size, (unsigned)vp8->decoder.first_part_size);
+ // Not a fatal error
+ goto bail;
+ }
+
+ vpx_ret = vpx_codec_decode(&vp8->decoder.context, pay_ptr, (int)pay_size, tsk_null, 0);
+
+ if (vpx_ret != VPX_CODEC_OK) {
+ TSK_DEBUG_INFO("vpx_codec_decode failed with error =%s", vpx_codec_err_to_string(vpx_ret));
+ fatal_error = tsk_true;
+ goto bail;
+ }
+ else if (vp8->decoder.idr) {
+ TSK_DEBUG_INFO("Decoded VP8 IDR");
+ if (TMEDIA_CODEC_VIDEO(self)->in.callback) {
+ TMEDIA_CODEC_VIDEO(self)->in.result.type = tmedia_video_decode_result_type_idr;
+ TMEDIA_CODEC_VIDEO(self)->in.result.proto_hdr = proto_hdr;
+ TMEDIA_CODEC_VIDEO(self)->in.callback(&TMEDIA_CODEC_VIDEO(self)->in.result);
+ }
+ }
+
+ // copy decoded data
+ ret = 0;
+ while ((img = vpx_codec_get_frame(&vp8->decoder.context, &iter))) {
+ unsigned int plane, y;
+ tsk_size_t xsize;
+
+ // update sizes
+ TMEDIA_CODEC_VIDEO(vp8)->in.width = img->d_w;
+ TMEDIA_CODEC_VIDEO(vp8)->in.height = img->d_h;
+ xsize = (TMEDIA_CODEC_VIDEO(vp8)->in.width * TMEDIA_CODEC_VIDEO(vp8)->in.height * 3) >> 1;
+ // allocate destination buffer
+ if (*out_max_size < xsize) {
+ if (!(*out_data = tsk_realloc(*out_data, xsize))) {
+ TSK_DEBUG_ERROR("Failed to allocate new buffer");
+ *out_max_size = 0;
+ goto bail;
+ }
+ *out_max_size = xsize;
+ }
+
+ // layout picture
+ for (plane = 0; plane < 3; plane++) {
+ unsigned char *buf = img->planes[plane];
+ for (y = 0; y < img->d_h >> (plane ? 1 : 0); y++) {
+ unsigned int w_count = img->d_w >> (plane ? 1 : 0);
+ if ((ret + w_count) > *out_max_size) {
+ TSK_DEBUG_ERROR("BufferOverflow");
+ ret = 0;
+ goto bail;
+ }
+ memcpy(((uint8_t*)*out_data) + ret, buf, w_count);
+ ret += w_count;
+ buf += img->stride[plane];
+ }
+ }
+ }
+ }
bail:
- if (fatal_error && TMEDIA_CODEC_VIDEO(self)->in.callback) {
- TMEDIA_CODEC_VIDEO(self)->in.result.type = tmedia_video_decode_result_type_error;
- TMEDIA_CODEC_VIDEO(self)->in.result.proto_hdr = proto_hdr;
- TMEDIA_CODEC_VIDEO(self)->in.callback(&TMEDIA_CODEC_VIDEO(self)->in.result);
- }
-
- // vp8->decoder.last_PartID = PartID;
- // vp8->decoder.last_S = S;
- // vp8->decoder.last_N = N;
- return ret;
+ if (fatal_error && TMEDIA_CODEC_VIDEO(self)->in.callback) {
+ TMEDIA_CODEC_VIDEO(self)->in.result.type = tmedia_video_decode_result_type_error;
+ TMEDIA_CODEC_VIDEO(self)->in.result.proto_hdr = proto_hdr;
+ TMEDIA_CODEC_VIDEO(self)->in.callback(&TMEDIA_CODEC_VIDEO(self)->in.result);
+ }
+
+ // vp8->decoder.last_PartID = PartID;
+ // vp8->decoder.last_S = S;
+ // vp8->decoder.last_N = N;
+ return ret;
}
static tsk_bool_t tdav_codec_vp8_sdp_att_match(const tmedia_codec_t* codec, const char* att_name, const char* att_value)
{
#if 0
- if(tsk_striequals(att_name, "fmtp")) {
- unsigned width, height, fps;
- if(tmedia_parse_video_fmtp(att_value, TMEDIA_CODEC_VIDEO(codec)->pref_size, &width, &height, &fps)) {
- TSK_DEBUG_ERROR("Failed to match fmtp=%s", att_value);
- return tsk_false;
- }
- TMEDIA_CODEC_VIDEO(codec)->in.width = TMEDIA_CODEC_VIDEO(codec)->out.width = width;
- TMEDIA_CODEC_VIDEO(codec)->in.height = TMEDIA_CODEC_VIDEO(codec)->out.height = height;
- TMEDIA_CODEC_VIDEO(codec)->in.fps = TMEDIA_CODEC_VIDEO(codec)->out.fps = fps;
- }
- else
+ if(tsk_striequals(att_name, "fmtp")) {
+ unsigned width, height, fps;
+ if(tmedia_parse_video_fmtp(att_value, TMEDIA_CODEC_VIDEO(codec)->pref_size, &width, &height, &fps)) {
+ TSK_DEBUG_ERROR("Failed to match fmtp=%s", att_value);
+ return tsk_false;
+ }
+ TMEDIA_CODEC_VIDEO(codec)->in.width = TMEDIA_CODEC_VIDEO(codec)->out.width = width;
+ TMEDIA_CODEC_VIDEO(codec)->in.height = TMEDIA_CODEC_VIDEO(codec)->out.height = height;
+ TMEDIA_CODEC_VIDEO(codec)->in.fps = TMEDIA_CODEC_VIDEO(codec)->out.fps = fps;
+ }
+ else
#endif
- if (tsk_striequals(att_name, "imageattr")) {
- unsigned in_width, in_height, out_width, out_height;
- if (tmedia_parse_video_imageattr(att_value, TMEDIA_CODEC_VIDEO(codec)->pref_size, &in_width, &in_height, &out_width, &out_height) != 0) {
- return tsk_false;
- }
- TMEDIA_CODEC_VIDEO(codec)->in.width = in_width;
- TMEDIA_CODEC_VIDEO(codec)->in.height = in_height;
- TMEDIA_CODEC_VIDEO(codec)->out.width = out_width;
- TMEDIA_CODEC_VIDEO(codec)->out.height = out_height;
- }
-
- return tsk_true;
+ if (tsk_striequals(att_name, "imageattr")) {
+ unsigned in_width, in_height, out_width, out_height;
+ if (tmedia_parse_video_imageattr(att_value, TMEDIA_CODEC_VIDEO(codec)->pref_size, &in_width, &in_height, &out_width, &out_height) != 0) {
+ return tsk_false;
+ }
+ TMEDIA_CODEC_VIDEO(codec)->in.width = in_width;
+ TMEDIA_CODEC_VIDEO(codec)->in.height = in_height;
+ TMEDIA_CODEC_VIDEO(codec)->out.width = out_width;
+ TMEDIA_CODEC_VIDEO(codec)->out.height = out_height;
+ // clamp the output size to the defined max range
+ if (tmedia_defaults_get_adapt_video_size_range_enabled()) {
+ if (tmedia_codec_video_clamp_out_size_to_range_max(TMEDIA_CODEC_VIDEO(codec)) != 0) {
+ return tsk_false;
+ }
+ }
+ }
+
+
+ return tsk_true;
}
static char* tdav_codec_vp8_sdp_att_get(const tmedia_codec_t* codec, const char* att_name)
{
#if 0
- if(tsk_striequals(att_name, "fmtp")) {
- return tmedia_get_video_fmtp(TMEDIA_CODEC_VIDEO(codec)->pref_size);
- }
- else
+ if(tsk_striequals(att_name, "fmtp")) {
+ return tmedia_get_video_fmtp(TMEDIA_CODEC_VIDEO(codec)->pref_size);
+ }
+ else
#endif
- if (tsk_striequals(att_name, "imageattr")) {
- return tmedia_get_video_imageattr(TMEDIA_CODEC_VIDEO(codec)->pref_size,
- TMEDIA_CODEC_VIDEO(codec)->in.width, TMEDIA_CODEC_VIDEO(codec)->in.height, TMEDIA_CODEC_VIDEO(codec)->out.width, TMEDIA_CODEC_VIDEO(codec)->out.height);
- }
- return tsk_null;
+ if (tsk_striequals(att_name, "imageattr")) {
+ return tmedia_get_video_imageattr(TMEDIA_CODEC_VIDEO(codec)->pref_size,
+ TMEDIA_CODEC_VIDEO(codec)->in.width, TMEDIA_CODEC_VIDEO(codec)->in.height, TMEDIA_CODEC_VIDEO(codec)->out.width, TMEDIA_CODEC_VIDEO(codec)->out.height);
+ }
+ return tsk_null;
}
/* ============ VP8 object definition ================= */
@@ -626,62 +633,60 @@ static char* tdav_codec_vp8_sdp_att_get(const tmedia_codec_t* codec, const char*
/* constructor */
static tsk_object_t* tdav_codec_vp8_ctor(tsk_object_t * self, va_list * app)
{
- tdav_codec_vp8_t *vp8 = self;
- if (vp8) {
- /* init base: called by tmedia_codec_create() */
- /* init self */
- }
- return self;
+ tdav_codec_vp8_t *vp8 = self;
+ if (vp8) {
+ /* init base: called by tmedia_codec_create() */
+ /* init self */
+ }
+ return self;
}
/* destructor */
static tsk_object_t* tdav_codec_vp8_dtor(tsk_object_t * self)
{
- tdav_codec_vp8_t *vp8 = self;
- TSK_DEBUG_INFO("*** tdav_codec_vp8_dtor destroyed ***");
- if (vp8) {
- /* deinit base */
- tmedia_codec_video_deinit(vp8);
- /* deinit self */
- tdav_codec_vp8_close_encoder(vp8);
- tdav_codec_vp8_close_decoder(vp8);
- }
-
- return self;
+ tdav_codec_vp8_t *vp8 = self;
+ TSK_DEBUG_INFO("*** tdav_codec_vp8_dtor destroyed ***");
+ if (vp8) {
+ /* deinit base */
+ tmedia_codec_video_deinit(vp8);
+ /* deinit self */
+ tdav_codec_vp8_close_encoder(vp8);
+ tdav_codec_vp8_close_decoder(vp8);
+ }
+
+ return self;
}
/* object definition */
-static const tsk_object_def_t tdav_codec_vp8_def_s =
-{
- sizeof(tdav_codec_vp8_t),
- tdav_codec_vp8_ctor,
- tdav_codec_vp8_dtor,
- tmedia_codec_cmp,
+static const tsk_object_def_t tdav_codec_vp8_def_s = {
+ sizeof(tdav_codec_vp8_t),
+ tdav_codec_vp8_ctor,
+ tdav_codec_vp8_dtor,
+ tmedia_codec_cmp,
};
/* plugin definition*/
-static const tmedia_codec_plugin_def_t tdav_codec_vp8_plugin_def_s =
-{
- &tdav_codec_vp8_def_s,
-
- tmedia_video,
- tmedia_codec_id_vp8,
- "VP8",
- "VP8 codec (libvpx)",
- TMEDIA_CODEC_FORMAT_VP8,
- tsk_true,
- 90000, // rate
-
- /* audio */
- { 0 },
-
- /* video (defaul width,height,fps) */
- { 176, 144, 0 }, // fps is @deprecated
-
- tdav_codec_vp8_set,
- tdav_codec_vp8_open,
- tdav_codec_vp8_close,
- tdav_codec_vp8_encode,
- tdav_codec_vp8_decode,
- tdav_codec_vp8_sdp_att_match,
- tdav_codec_vp8_sdp_att_get
+static const tmedia_codec_plugin_def_t tdav_codec_vp8_plugin_def_s = {
+ &tdav_codec_vp8_def_s,
+
+ tmedia_video,
+ tmedia_codec_id_vp8,
+ "VP8",
+ "VP8 codec (libvpx)",
+ TMEDIA_CODEC_FORMAT_VP8,
+ tsk_true,
+ 90000, // rate
+
+ /* audio */
+ { 0 },
+
+ /* video (defaul width,height,fps) */
+ { 176, 144, 0 }, // fps is @deprecated
+
+ tdav_codec_vp8_set,
+ tdav_codec_vp8_open,
+ tdav_codec_vp8_close,
+ tdav_codec_vp8_encode,
+ tdav_codec_vp8_decode,
+ tdav_codec_vp8_sdp_att_match,
+ tdav_codec_vp8_sdp_att_get
};
const tmedia_codec_plugin_def_t *tdav_codec_vp8_plugin_def_t = &tdav_codec_vp8_plugin_def_s;
@@ -689,193 +694,193 @@ const tmedia_codec_plugin_def_t *tdav_codec_vp8_plugin_def_t = &tdav_codec_vp8_p
int tdav_codec_vp8_open_encoder(tdav_codec_vp8_t* self)
{
- vpx_codec_err_t vpx_ret;
- vpx_enc_frame_flags_t enc_flags = 0; // VPX_EFLAG_XXX
-
- if (self->encoder.initialized) {
- TSK_DEBUG_ERROR("VP8 encoder already inialized");
- return -1;
- }
-
- if ((vpx_ret = vpx_codec_enc_config_default(vp8_interface_enc, &self->encoder.cfg, 0)) != VPX_CODEC_OK) {
- TSK_DEBUG_ERROR("vpx_codec_enc_config_default failed with error =%s", vpx_codec_err_to_string(vpx_ret));
- return -2;
- }
- self->encoder.cfg.g_timebase.num = 1;
- self->encoder.cfg.g_timebase.den = TMEDIA_CODEC_VIDEO(self)->out.fps;
- self->encoder.cfg.rc_target_bitrate = TSK_CLAMP(
- 0,
- tmedia_get_video_bandwidth_kbps_2(TMEDIA_CODEC_VIDEO(self)->out.width, TMEDIA_CODEC_VIDEO(self)->out.height, TMEDIA_CODEC_VIDEO(self)->out.fps),
- TMEDIA_CODEC(self)->bandwidth_max_upload
- );
- self->encoder.cfg.g_w = (self->encoder.rotation == 90 || self->encoder.rotation == 270) ? TMEDIA_CODEC_VIDEO(self)->out.height : TMEDIA_CODEC_VIDEO(self)->out.width;
- self->encoder.cfg.g_h = (self->encoder.rotation == 90 || self->encoder.rotation == 270) ? TMEDIA_CODEC_VIDEO(self)->out.width : TMEDIA_CODEC_VIDEO(self)->out.height;
- self->encoder.cfg.kf_mode = VPX_KF_AUTO;
- /*self->encoder.cfg.kf_min_dist =*/ self->encoder.cfg.kf_max_dist = (TDAV_VP8_GOP_SIZE_IN_SECONDS * TMEDIA_CODEC_VIDEO(self)->out.fps);
+ vpx_codec_err_t vpx_ret;
+ vpx_enc_frame_flags_t enc_flags = 0; // VPX_EFLAG_XXX
+
+ if (self->encoder.initialized) {
+ TSK_DEBUG_ERROR("VP8 encoder already inialized");
+ return -1;
+ }
+
+ if ((vpx_ret = vpx_codec_enc_config_default(vp8_interface_enc, &self->encoder.cfg, 0)) != VPX_CODEC_OK) {
+ TSK_DEBUG_ERROR("vpx_codec_enc_config_default failed with error =%s", vpx_codec_err_to_string(vpx_ret));
+ return -2;
+ }
+ self->encoder.cfg.g_timebase.num = 1;
+ self->encoder.cfg.g_timebase.den = TMEDIA_CODEC_VIDEO(self)->out.fps;
+ self->encoder.cfg.rc_target_bitrate = TSK_CLAMP(
+ 0,
+ tmedia_get_video_bandwidth_kbps_2(TMEDIA_CODEC_VIDEO(self)->out.width, TMEDIA_CODEC_VIDEO(self)->out.height, TMEDIA_CODEC_VIDEO(self)->out.fps),
+ TMEDIA_CODEC(self)->bandwidth_max_upload
+ );
+ self->encoder.cfg.g_w = (self->encoder.rotation == 90 || self->encoder.rotation == 270) ? TMEDIA_CODEC_VIDEO(self)->out.height : TMEDIA_CODEC_VIDEO(self)->out.width;
+ self->encoder.cfg.g_h = (self->encoder.rotation == 90 || self->encoder.rotation == 270) ? TMEDIA_CODEC_VIDEO(self)->out.width : TMEDIA_CODEC_VIDEO(self)->out.height;
+ self->encoder.cfg.kf_mode = VPX_KF_AUTO;
+ /*self->encoder.cfg.kf_min_dist =*/ self->encoder.cfg.kf_max_dist = (TDAV_VP8_GOP_SIZE_IN_SECONDS * TMEDIA_CODEC_VIDEO(self)->out.fps);
#if defined(VPX_ERROR_RESILIENT_DEFAULT)
- self->encoder.cfg.g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT;
+ self->encoder.cfg.g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT;
#else
- self->encoder.cfg.g_error_resilient = 1;
+ self->encoder.cfg.g_error_resilient = 1;
#endif
#if defined(VPX_ERROR_RESILIENT_PARTITIONS)
- self->encoder.cfg.g_error_resilient |= VPX_ERROR_RESILIENT_PARTITIONS;
+ self->encoder.cfg.g_error_resilient |= VPX_ERROR_RESILIENT_PARTITIONS;
#endif
#if defined(VPX_CODEC_USE_OUTPUT_PARTITION)
- enc_flags |= VPX_CODEC_USE_OUTPUT_PARTITION;
+ enc_flags |= VPX_CODEC_USE_OUTPUT_PARTITION;
#endif
- self->encoder.cfg.g_lag_in_frames = 0;
+ self->encoder.cfg.g_lag_in_frames = 0;
#if TDAV_UNDER_WINDOWS
- {
- SYSTEM_INFO SystemInfo;
- GetSystemInfo(&SystemInfo);
- self->encoder.cfg.g_threads = SystemInfo.dwNumberOfProcessors;
- }
+ {
+ SYSTEM_INFO SystemInfo;
+ GetSystemInfo(&SystemInfo);
+ self->encoder.cfg.g_threads = SystemInfo.dwNumberOfProcessors;
+ }
#endif
- self->encoder.cfg.rc_end_usage = VPX_CBR;
- self->encoder.cfg.g_pass = VPX_RC_ONE_PASS;
+ self->encoder.cfg.rc_end_usage = VPX_CBR;
+ self->encoder.cfg.g_pass = VPX_RC_ONE_PASS;
#if 0
- self->encoder.cfg.rc_dropframe_thresh = 30;
- self->encoder.cfg.rc_resize_allowed = 0;
- self->encoder.cfg.rc_min_quantizer = 2;
- self->encoder.cfg.rc_max_quantizer = 56;
- self->encoder.cfg.rc_undershoot_pct = 100;
- self->encoder.cfg.rc_overshoot_pct = 15;
- self->encoder.cfg.rc_buf_initial_sz = 500;
- self->encoder.cfg.rc_buf_optimal_sz = 600;
- self->encoder.cfg.rc_buf_sz = 1000;
+ self->encoder.cfg.rc_dropframe_thresh = 30;
+ self->encoder.cfg.rc_resize_allowed = 0;
+ self->encoder.cfg.rc_min_quantizer = 2;
+ self->encoder.cfg.rc_max_quantizer = 56;
+ self->encoder.cfg.rc_undershoot_pct = 100;
+ self->encoder.cfg.rc_overshoot_pct = 15;
+ self->encoder.cfg.rc_buf_initial_sz = 500;
+ self->encoder.cfg.rc_buf_optimal_sz = 600;
+ self->encoder.cfg.rc_buf_sz = 1000;
#endif
- if ((vpx_ret = vpx_codec_enc_init(&self->encoder.context, vp8_interface_enc, &self->encoder.cfg, enc_flags)) != VPX_CODEC_OK) {
- TSK_DEBUG_ERROR("vpx_codec_enc_init failed with error =%s", vpx_codec_err_to_string(vpx_ret));
- return -3;
- }
- self->encoder.pic_id = /*(rand() ^ rand()) % 0x7FFF*/0/*Use zero: why do you want to make your life harder?*/;
+ if ((vpx_ret = vpx_codec_enc_init(&self->encoder.context, vp8_interface_enc, &self->encoder.cfg, enc_flags)) != VPX_CODEC_OK) {
+ TSK_DEBUG_ERROR("vpx_codec_enc_init failed with error =%s", vpx_codec_err_to_string(vpx_ret));
+ return -3;
+ }
+ self->encoder.pic_id = /*(rand() ^ rand()) % 0x7FFF*/0/*Use zero: why do you want to make your life harder?*/;
- /* vpx_codec_control(&self->encoder.context, VP8E_SET_STATIC_THRESHOLD, 800); */
+ /* vpx_codec_control(&self->encoder.context, VP8E_SET_STATIC_THRESHOLD, 800); */
#if !TDAV_UNDER_MOBILE /* must not remove: crash on Android for sure and probably on iOS also (all ARM devices ?) */
- vpx_codec_control(&self->encoder.context, VP8E_SET_NOISE_SENSITIVITY, 2);
+ vpx_codec_control(&self->encoder.context, VP8E_SET_NOISE_SENSITIVITY, 2);
#elif TDAV_UNDER_WINDOWS_CE
- vpx_codec_control(&self->encoder.context, VP8E_SET_NOISE_SENSITIVITY, 16);
- vpx_codec_control(&self->encoder.context, VP8E_SET_CPUUSED, 16);
- vpx_codec_control(&self->encoder.context, VP8E_SET_STATIC_THRESHOLD, 16);
- vpx_codec_control(&self->encoder.context, VP8E_SET_SHARPNESS, 16);
+ vpx_codec_control(&self->encoder.context, VP8E_SET_NOISE_SENSITIVITY, 16);
+ vpx_codec_control(&self->encoder.context, VP8E_SET_CPUUSED, 16);
+ vpx_codec_control(&self->encoder.context, VP8E_SET_STATIC_THRESHOLD, 16);
+ vpx_codec_control(&self->encoder.context, VP8E_SET_SHARPNESS, 16);
#endif
- // Set number of partitions
+ // Set number of partitions
#if defined(VPX_CODEC_USE_OUTPUT_PARTITION)
- {
- unsigned _s = TMEDIA_CODEC_VIDEO(self)->out.height * TMEDIA_CODEC_VIDEO(self)->out.width;
- if (_s < (352 * 288)) {
- vpx_codec_control(&self->encoder.context, VP8E_SET_TOKEN_PARTITIONS, VP8_ONE_TOKENPARTITION);
- }
- else if (_s < (352 * 288) * 2 * 2) {
- vpx_codec_control(&self->encoder.context, VP8E_SET_TOKEN_PARTITIONS, VP8_TWO_TOKENPARTITION);
- }
- else if (_s < (352 * 288) * 4 * 4) {
- vpx_codec_control(&self->encoder.context, VP8E_SET_TOKEN_PARTITIONS, VP8_FOUR_TOKENPARTITION);
- }
- else if (_s < (352 * 288) * 8 * 8) {
- vpx_codec_control(&self->encoder.context, VP8E_SET_TOKEN_PARTITIONS, VP8_EIGHT_TOKENPARTITION);
- }
- }
+ {
+ unsigned _s = TMEDIA_CODEC_VIDEO(self)->out.height * TMEDIA_CODEC_VIDEO(self)->out.width;
+ if (_s < (352 * 288)) {
+ vpx_codec_control(&self->encoder.context, VP8E_SET_TOKEN_PARTITIONS, VP8_ONE_TOKENPARTITION);
+ }
+ else if (_s < (352 * 288) * 2 * 2) {
+ vpx_codec_control(&self->encoder.context, VP8E_SET_TOKEN_PARTITIONS, VP8_TWO_TOKENPARTITION);
+ }
+ else if (_s < (352 * 288) * 4 * 4) {
+ vpx_codec_control(&self->encoder.context, VP8E_SET_TOKEN_PARTITIONS, VP8_FOUR_TOKENPARTITION);
+ }
+ else if (_s < (352 * 288) * 8 * 8) {
+ vpx_codec_control(&self->encoder.context, VP8E_SET_TOKEN_PARTITIONS, VP8_EIGHT_TOKENPARTITION);
+ }
+ }
#endif
- // Create the mutex if not already done
- if (!self->encoder.mutex && !(self->encoder.mutex = tsk_mutex_create())) {
- vpx_codec_destroy(&self->encoder.context);
- TSK_DEBUG_ERROR("Failed to create mutex");
- return -4;
- }
+ // Create the mutex if not already done
+ if (!self->encoder.mutex && !(self->encoder.mutex = tsk_mutex_create())) {
+ vpx_codec_destroy(&self->encoder.context);
+ TSK_DEBUG_ERROR("Failed to create mutex");
+ return -4;
+ }
- self->encoder.frame_count = 0;
+ self->encoder.frame_count = 0;
- self->encoder.initialized = tsk_true;
+ self->encoder.initialized = tsk_true;
- TSK_DEBUG_INFO("[VP8] target_bitrate=%d kbps", self->encoder.cfg.rc_target_bitrate);
+ TSK_DEBUG_INFO("[VP8] target_bitrate=%d kbps", self->encoder.cfg.rc_target_bitrate);
- return 0;
+ return 0;
}
int tdav_codec_vp8_open_decoder(tdav_codec_vp8_t* self)
{
- vpx_codec_err_t vpx_ret;
- vpx_codec_caps_t dec_caps;
- vpx_codec_flags_t dec_flags = 0;
+ vpx_codec_err_t vpx_ret;
+ vpx_codec_caps_t dec_caps;
+ vpx_codec_flags_t dec_flags = 0;
#if !TDAV_UNDER_MOBILE
- static vp8_postproc_cfg_t __pp = { VP8_DEBLOCK | VP8_DEMACROBLOCK, 4, 0 };
+ static vp8_postproc_cfg_t __pp = { VP8_DEBLOCK | VP8_DEMACROBLOCK, 4, 0 };
#endif
- if (self->decoder.initialized) {
- TSK_DEBUG_ERROR("VP8 decoder already initialized");
- return -1;
- }
+ if (self->decoder.initialized) {
+ TSK_DEBUG_ERROR("VP8 decoder already initialized");
+ return -1;
+ }
- self->decoder.cfg.w = TMEDIA_CODEC_VIDEO(self)->out.width;
- self->decoder.cfg.h = TMEDIA_CODEC_VIDEO(self)->out.height;
+ self->decoder.cfg.w = TMEDIA_CODEC_VIDEO(self)->out.width;
+ self->decoder.cfg.h = TMEDIA_CODEC_VIDEO(self)->out.height;
#if TDAV_UNDER_WINDOWS
- {
- SYSTEM_INFO SystemInfo;
- GetSystemInfo(&SystemInfo);
- self->decoder.cfg.threads = SystemInfo.dwNumberOfProcessors;
- }
+ {
+ SYSTEM_INFO SystemInfo;
+ GetSystemInfo(&SystemInfo);
+ self->decoder.cfg.threads = SystemInfo.dwNumberOfProcessors;
+ }
#endif
- dec_caps = vpx_codec_get_caps(&vpx_codec_vp8_dx_algo);
+ dec_caps = vpx_codec_get_caps(&vpx_codec_vp8_dx_algo);
#if !TDAV_UNDER_MOBILE
- if (dec_caps & VPX_CODEC_CAP_POSTPROC) {
- dec_flags |= VPX_CODEC_USE_POSTPROC;
- }
+ if (dec_caps & VPX_CODEC_CAP_POSTPROC) {
+ dec_flags |= VPX_CODEC_USE_POSTPROC;
+ }
#endif
#if defined(VPX_CODEC_CAP_ERROR_CONCEALMENT)
- if (dec_caps & VPX_CODEC_CAP_ERROR_CONCEALMENT) {
- dec_flags |= VPX_CODEC_USE_ERROR_CONCEALMENT;
- }
+ if (dec_caps & VPX_CODEC_CAP_ERROR_CONCEALMENT) {
+ dec_flags |= VPX_CODEC_USE_ERROR_CONCEALMENT;
+ }
#endif
- if ((vpx_ret = vpx_codec_dec_init(&self->decoder.context, vp8_interface_dec, &self->decoder.cfg, dec_flags)) != VPX_CODEC_OK) {
- TSK_DEBUG_ERROR("vpx_codec_dec_init failed with error =%s", vpx_codec_err_to_string(vpx_ret));
- return -4;
- }
+ if ((vpx_ret = vpx_codec_dec_init(&self->decoder.context, vp8_interface_dec, &self->decoder.cfg, dec_flags)) != VPX_CODEC_OK) {
+ TSK_DEBUG_ERROR("vpx_codec_dec_init failed with error =%s", vpx_codec_err_to_string(vpx_ret));
+ return -4;
+ }
#if !TDAV_UNDER_MOBILE
- if ((vpx_ret = vpx_codec_control(&self->decoder.context, VP8_SET_POSTPROC, &__pp))) {
- TSK_DEBUG_WARN("vpx_codec_dec_init failed with error =%s", vpx_codec_err_to_string(vpx_ret));
- }
+ if ((vpx_ret = vpx_codec_control(&self->decoder.context, VP8_SET_POSTPROC, &__pp))) {
+ TSK_DEBUG_WARN("vpx_codec_dec_init failed with error =%s", vpx_codec_err_to_string(vpx_ret));
+ }
#endif
- self->decoder.initialized = tsk_true;
+ self->decoder.initialized = tsk_true;
- return 0;
+ return 0;
}
int tdav_codec_vp8_close_encoder(tdav_codec_vp8_t* self)
{
- TSK_DEBUG_INFO("tdav_codec_vp8_close_encoder(begin)");
- if (self->encoder.initialized) {
- vpx_codec_destroy(&self->encoder.context);
- self->encoder.initialized = tsk_false;
- }
- if (self->encoder.mutex) {
- tsk_mutex_destroy(&self->encoder.mutex);
- }
- TSK_FREE(self->encoder.rtp.ptr);
- self->encoder.rtp.size = 0;
- self->encoder.rotation = 0; // reset rotation
- TSK_DEBUG_INFO("tdav_codec_vp8_close_encoder(end)");
- return 0;
+ TSK_DEBUG_INFO("tdav_codec_vp8_close_encoder(begin)");
+ if (self->encoder.initialized) {
+ vpx_codec_destroy(&self->encoder.context);
+ self->encoder.initialized = tsk_false;
+ }
+ if (self->encoder.mutex) {
+ tsk_mutex_destroy(&self->encoder.mutex);
+ }
+ TSK_FREE(self->encoder.rtp.ptr);
+ self->encoder.rtp.size = 0;
+ self->encoder.rotation = 0; // reset rotation
+ TSK_DEBUG_INFO("tdav_codec_vp8_close_encoder(end)");
+ return 0;
}
int tdav_codec_vp8_close_decoder(tdav_codec_vp8_t* self)
{
- TSK_DEBUG_INFO("tdav_codec_vp8_close_decoder(begin)");
- if (self->decoder.initialized) {
- vpx_codec_destroy(&self->decoder.context);
- self->decoder.initialized = tsk_false;
- }
- TSK_FREE(self->decoder.accumulator);
- self->decoder.accumulator_size = 0;
- self->decoder.accumulator_pos = 0;
- TSK_DEBUG_INFO("tdav_codec_vp8_close_decoder(end)");
-
- return 0;
+ TSK_DEBUG_INFO("tdav_codec_vp8_close_decoder(begin)");
+ if (self->decoder.initialized) {
+ vpx_codec_destroy(&self->decoder.context);
+ self->decoder.initialized = tsk_false;
+ }
+ TSK_FREE(self->decoder.accumulator);
+ self->decoder.accumulator_size = 0;
+ self->decoder.accumulator_pos = 0;
+ TSK_DEBUG_INFO("tdav_codec_vp8_close_decoder(end)");
+
+ return 0;
}
/* ============ VP8 RTP packetizer/depacketizer ================= */
@@ -883,177 +888,177 @@ int tdav_codec_vp8_close_decoder(tdav_codec_vp8_t* self)
static void tdav_codec_vp8_encap(tdav_codec_vp8_t* self, const vpx_codec_cx_pkt_t *pkt)
{
- tsk_bool_t non_ref, is_keyframe, part_start;
- uint8_t *frame_ptr;
- uint32_t part_size, part_ID, pkt_size, index;
+ tsk_bool_t non_ref, is_keyframe, part_start;
+ uint8_t *frame_ptr;
+ uint32_t part_size, part_ID, pkt_size, index;
- if (!self || !pkt || !pkt->data.frame.buf || !pkt->data.frame.sz) {
- TSK_DEBUG_ERROR("Invalid parameter");
- return;
- }
+ if (!self || !pkt || !pkt->data.frame.buf || !pkt->data.frame.sz) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return;
+ }
- index = 0;
- frame_ptr = pkt->data.frame.buf;
- pkt_size = (uint32_t)pkt->data.frame.sz;
- non_ref = (pkt->data.frame.flags & VPX_FRAME_IS_DROPPABLE);
- is_keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY);
+ index = 0;
+ frame_ptr = pkt->data.frame.buf;
+ pkt_size = (uint32_t)pkt->data.frame.sz;
+ non_ref = (pkt->data.frame.flags & VPX_FRAME_IS_DROPPABLE);
+ is_keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY);
#if defined(VPX_CODEC_USE_OUTPUT_PARTITION)
- part_ID = pkt->data.frame.partition_id;
- part_start = tsk_true;
- part_size = pkt_size;
- while (index < part_size) {
- uint32_t frag_size = TSK_MIN(TDAV_VP8_RTP_PAYLOAD_MAX_SIZE, (part_size - index));
- tdav_codec_vp8_rtp_callback(
- self,
- &frame_ptr[index],
- frag_size,
- part_ID,
- part_start,
- non_ref,
- ((pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT) == 0 && (index + frag_size) == part_size) // RTP marker?
- );
- part_start = tsk_false;
- index += frag_size;
- }
+ part_ID = pkt->data.frame.partition_id;
+ part_start = tsk_true;
+ part_size = pkt_size;
+ while (index < part_size) {
+ uint32_t frag_size = TSK_MIN(TDAV_VP8_RTP_PAYLOAD_MAX_SIZE, (part_size - index));
+ tdav_codec_vp8_rtp_callback(
+ self,
+ &frame_ptr[index],
+ frag_size,
+ part_ID,
+ part_start,
+ non_ref,
+ ((pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT) == 0 && (index + frag_size) == part_size) // RTP marker?
+ );
+ part_start = tsk_false;
+ index += frag_size;
+ }
#else
- // first partition (contains modes and motion vectors)
- part_ID = 0; // The first VP8 partition(containing modes and motion vectors) MUST be labeled with PartID = 0
- part_start = tsk_true;
- part_size = (frame_ptr[2] << 16) | (frame_ptr[1] << 8) | frame_ptr[0];
- part_size = (part_size >> 5) & 0x7FFFF;
- if (part_size > pkt_size) {
- TSK_DEBUG_ERROR("part_size is > pkt_size(%u,%u)", part_size, pkt_size);
- return;
- }
-
- // first,first,....partitions (or fragment if part_size > TDAV_VP8_RTP_PAYLOAD_MAX_SIZE)
- while (index<part_size) {
- uint32_t frag_size = TSK_MIN(TDAV_VP8_RTP_PAYLOAD_MAX_SIZE, (part_size - index));
- tdav_codec_vp8_rtp_callback(self, &frame_ptr[index], frag_size, part_ID, part_start, non_ref, tsk_false);
- part_start = tsk_false;
- index += frag_size;
- }
-
- // second,third,... partitions (or fragment if part_size > TDAV_VP8_RTP_PAYLOAD_MAX_SIZE)
- // FIXME: low FEC
- part_start = tsk_true;
- while (index<pkt_size) {
- if (part_start) {
- /* PartID SHOULD be incremented for each subsequent partition,
- but MAY be kept at 0 for all packets. PartID MUST NOT be larger
- than 8.
- */
- part_ID++;
- }
- part_size = TSK_MIN(TDAV_VP8_RTP_PAYLOAD_MAX_SIZE, (pkt_size - index));
-
- tdav_codec_vp8_rtp_callback(self, &frame_ptr[index], part_size, part_ID, part_start, non_ref, (index + part_size)==pkt_size);
- index += part_size;
- /*
- If more than one packet in an encoded frame contains the
- same PartID, the S bit MUST NOT be set for any other packet than
- the first packet with that PartID.
- */
- part_start = tsk_false;
- }
+ // first partition (contains modes and motion vectors)
+ part_ID = 0; // The first VP8 partition(containing modes and motion vectors) MUST be labeled with PartID = 0
+ part_start = tsk_true;
+ part_size = (frame_ptr[2] << 16) | (frame_ptr[1] << 8) | frame_ptr[0];
+ part_size = (part_size >> 5) & 0x7FFFF;
+ if (part_size > pkt_size) {
+ TSK_DEBUG_ERROR("part_size is > pkt_size(%u,%u)", part_size, pkt_size);
+ return;
+ }
+
+ // first,first,....partitions (or fragment if part_size > TDAV_VP8_RTP_PAYLOAD_MAX_SIZE)
+ while (index<part_size) {
+ uint32_t frag_size = TSK_MIN(TDAV_VP8_RTP_PAYLOAD_MAX_SIZE, (part_size - index));
+ tdav_codec_vp8_rtp_callback(self, &frame_ptr[index], frag_size, part_ID, part_start, non_ref, tsk_false);
+ part_start = tsk_false;
+ index += frag_size;
+ }
+
+ // second,third,... partitions (or fragment if part_size > TDAV_VP8_RTP_PAYLOAD_MAX_SIZE)
+ // FIXME: low FEC
+ part_start = tsk_true;
+ while (index<pkt_size) {
+ if (part_start) {
+ /* PartID SHOULD be incremented for each subsequent partition,
+ but MAY be kept at 0 for all packets. PartID MUST NOT be larger
+ than 8.
+ */
+ part_ID++;
+ }
+ part_size = TSK_MIN(TDAV_VP8_RTP_PAYLOAD_MAX_SIZE, (pkt_size - index));
+
+ tdav_codec_vp8_rtp_callback(self, &frame_ptr[index], part_size, part_ID, part_start, non_ref, (index + part_size)==pkt_size);
+ index += part_size;
+ /*
+ If more than one packet in an encoded frame contains the
+ same PartID, the S bit MUST NOT be set for any other packet than
+ the first packet with that PartID.
+ */
+ part_start = tsk_false;
+ }
#endif /* VPX_CODEC_USE_OUTPUT_PARTITION */
}
static void tdav_codec_vp8_rtp_callback(tdav_codec_vp8_t *self, const void *data, tsk_size_t size, uint32_t partID, tsk_bool_t part_start, tsk_bool_t non_ref, tsk_bool_t last)
{
- tsk_size_t paydesc_and_hdr_size = TDAV_VP8_PAY_DESC_SIZE;
- tsk_bool_t has_hdr;
- /* draft-ietf-payload-vp8-04 - 4.2. VP8 Payload Descriptor
- 0 1 2 3 4 5 6 7
- +-+-+-+-+-+-+-+-+
- |X|R|N|S|PartID | (REQUIRED)
- +-+-+-+-+-+-+-+-+
- X: |I|L|T|K| RSV | (OPTIONAL)
- +-+-+-+-+-+-+-+-+
- I: |M| PictureID | (OPTIONAL)
- +-+-+-+-+-+-+-+-+
- L: | TL0PICIDX | (OPTIONAL)
- +-+-+-+-+-+-+-+-+
- T/K: |TID|Y| KEYIDX | (OPTIONAL)
- +-+-+-+-+-+-+-+-+
-
- draft-ietf-payload-vp8-04 - 4.3. VP8 Payload Header
- 0 1 2 3 4 5 6 7
- +-+-+-+-+-+-+-+-+
- |Size0|H| VER |P|
- +-+-+-+-+-+-+-+-+
- | Size1 |
- +-+-+-+-+-+-+-+-+
- | Size2 |
- +-+-+-+-+-+-+-+-+
- | Bytes 4..N of |
- | VP8 payload |
- : :
- +-+-+-+-+-+-+-+-+
- | OPTIONAL RTP |
- | padding |
- : :
- +-+-+-+-+-+-+-+-+
- */
-
- /*
- Note that the header is present only in packets which have the S bit equal to one and the
- PartID equal to zero in the payload descriptor.
- */
- if ((has_hdr = (part_start && partID == 0))) {
- has_hdr = tsk_true;
- paydesc_and_hdr_size += 0; // encoded data already contains payload header?
- }
-
- if (!data || !size) {
- TSK_DEBUG_ERROR("Invalid parameter");
- return;
- }
- if (self->encoder.rtp.size < (size + paydesc_and_hdr_size)) {
- if (!(self->encoder.rtp.ptr = tsk_realloc(self->encoder.rtp.ptr, (size + paydesc_and_hdr_size)))) {
- TSK_DEBUG_ERROR("Failed to allocate new buffer");
- return;
- }
- self->encoder.rtp.size = (size + paydesc_and_hdr_size);
- }
- memcpy((self->encoder.rtp.ptr + paydesc_and_hdr_size), data, size);
-
- /* VP8 Payload Descriptor */
- // |X|R|N|S|PartID|
- self->encoder.rtp.ptr[0] = (partID & 0x0F) // PartID
- | ((part_start << 4) & 0x10)// S
- | ((non_ref << 5) & 0x20) // N
- // R = 0
+ tsk_size_t paydesc_and_hdr_size = TDAV_VP8_PAY_DESC_SIZE;
+ tsk_bool_t has_hdr;
+ /* draft-ietf-payload-vp8-04 - 4.2. VP8 Payload Descriptor
+ 0 1 2 3 4 5 6 7
+ +-+-+-+-+-+-+-+-+
+ |X|R|N|S|PartID | (REQUIRED)
+ +-+-+-+-+-+-+-+-+
+ X: |I|L|T|K| RSV | (OPTIONAL)
+ +-+-+-+-+-+-+-+-+
+ I: |M| PictureID | (OPTIONAL)
+ +-+-+-+-+-+-+-+-+
+ L: | TL0PICIDX | (OPTIONAL)
+ +-+-+-+-+-+-+-+-+
+ T/K: |TID|Y| KEYIDX | (OPTIONAL)
+ +-+-+-+-+-+-+-+-+
+
+ draft-ietf-payload-vp8-04 - 4.3. VP8 Payload Header
+ 0 1 2 3 4 5 6 7
+ +-+-+-+-+-+-+-+-+
+ |Size0|H| VER |P|
+ +-+-+-+-+-+-+-+-+
+ | Size1 |
+ +-+-+-+-+-+-+-+-+
+ | Size2 |
+ +-+-+-+-+-+-+-+-+
+ | Bytes 4..N of |
+ | VP8 payload |
+ : :
+ +-+-+-+-+-+-+-+-+
+ | OPTIONAL RTP |
+ | padding |
+ : :
+ +-+-+-+-+-+-+-+-+
+ */
+
+ /*
+ Note that the header is present only in packets which have the S bit equal to one and the
+ PartID equal to zero in the payload descriptor.
+ */
+ if ((has_hdr = (part_start && partID == 0))) {
+ has_hdr = tsk_true;
+ paydesc_and_hdr_size += 0; // encoded data already contains payload header?
+ }
+
+ if (!data || !size) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return;
+ }
+ if (self->encoder.rtp.size < (size + paydesc_and_hdr_size)) {
+ if (!(self->encoder.rtp.ptr = tsk_realloc(self->encoder.rtp.ptr, (size + paydesc_and_hdr_size)))) {
+ TSK_DEBUG_ERROR("Failed to allocate new buffer");
+ return;
+ }
+ self->encoder.rtp.size = (size + paydesc_and_hdr_size);
+ }
+ memcpy((self->encoder.rtp.ptr + paydesc_and_hdr_size), data, size);
+
+ /* VP8 Payload Descriptor */
+ // |X|R|N|S|PartID|
+ self->encoder.rtp.ptr[0] = (partID & 0x0F) // PartID
+ | ((part_start << 4) & 0x10)// S
+ | ((non_ref << 5) & 0x20) // N
+ // R = 0
#if TDAV_VP8_DISABLE_EXTENSION
- | (0x00) // X=0
+ | (0x00) // X=0
#else
- | (0x80) // X=1
+ | (0x80) // X=1
#endif
- ;
+ ;
#if !TDAV_VP8_DISABLE_EXTENSION
- // X: |I|L|T|K| RSV |
- self->encoder.rtp.ptr[1] = 0x80; // I = 1, L = 0, T = 0, K = 0, RSV = 0
- // I: |M| PictureID |
- self->encoder.rtp.ptr[2] = (0x80 | ((self->encoder.pic_id >> 8) & 0x7F)); // M = 1 (PictureID on 15 bits)
- self->encoder.rtp.ptr[3] = (self->encoder.pic_id & 0xFF);
+ // X: |I|L|T|K| RSV |
+ self->encoder.rtp.ptr[1] = 0x80; // I = 1, L = 0, T = 0, K = 0, RSV = 0
+ // I: |M| PictureID |
+ self->encoder.rtp.ptr[2] = (0x80 | ((self->encoder.pic_id >> 8) & 0x7F)); // M = 1 (PictureID on 15 bits)
+ self->encoder.rtp.ptr[3] = (self->encoder.pic_id & 0xFF);
#endif
- /* 4.2. VP8 Payload Header */
- //if(has_hdr) {
- // already part of the encoded stream
- //}
-
- // Send data over the network
- if (TMEDIA_CODEC_VIDEO(self)->out.callback) {
- TMEDIA_CODEC_VIDEO(self)->out.result.buffer.ptr = self->encoder.rtp.ptr;
- TMEDIA_CODEC_VIDEO(self)->out.result.buffer.size = (size + TDAV_VP8_PAY_DESC_SIZE);
- TMEDIA_CODEC_VIDEO(self)->out.result.duration = (uint32_t)((1. / (double)TMEDIA_CODEC_VIDEO(self)->out.fps) * TMEDIA_CODEC(self)->plugin->rate);
- TMEDIA_CODEC_VIDEO(self)->out.result.last_chunck = last;
- TMEDIA_CODEC_VIDEO(self)->out.callback(&TMEDIA_CODEC_VIDEO(self)->out.result);
- }
+ /* 4.2. VP8 Payload Header */
+ //if(has_hdr) {
+ // already part of the encoded stream
+ //}
+
+ // Send data over the network
+ if (TMEDIA_CODEC_VIDEO(self)->out.callback) {
+ TMEDIA_CODEC_VIDEO(self)->out.result.buffer.ptr = self->encoder.rtp.ptr;
+ TMEDIA_CODEC_VIDEO(self)->out.result.buffer.size = (size + TDAV_VP8_PAY_DESC_SIZE);
+ TMEDIA_CODEC_VIDEO(self)->out.result.duration = (uint32_t)((1. / (double)TMEDIA_CODEC_VIDEO(self)->out.fps) * TMEDIA_CODEC(self)->plugin->rate);
+ TMEDIA_CODEC_VIDEO(self)->out.result.last_chunck = last;
+ TMEDIA_CODEC_VIDEO(self)->out.callback(&TMEDIA_CODEC_VIDEO(self)->out.result);
+ }
}
#endif /* HAVE_LIBVPX */
OpenPOWER on IntegriCloud