summaryrefslogtreecommitdiffstats
path: root/tinyDAV/src/codecs/h264
diff options
context:
space:
mode:
Diffstat (limited to 'tinyDAV/src/codecs/h264')
-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
5 files changed, 4155 insertions, 4266 deletions
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);
+ }
+ }
+ }
}
OpenPOWER on IntegriCloud