[BZ1235] sync libmix to froyo stable branch
Change-Id: If25ea8cf0730289d0ae029f5e7462bd7051905d5
Signed-off-by: xli111 <xiaowei.a.li@intel.com>
diff --git a/mix_vbp/viddec_fw/fw/codecs/h264/include/h264.h b/mix_vbp/viddec_fw/fw/codecs/h264/include/h264.h
index 1976567..a3490b4 100644
--- a/mix_vbp/viddec_fw/fw/codecs/h264/include/h264.h
+++ b/mix_vbp/viddec_fw/fw/codecs/h264/include/h264.h
@@ -505,6 +505,7 @@
#ifdef VBP
uint8_t video_full_range_flag; // u(1)
uint8_t matrix_coefficients; // u(8)
+ uint32_t bit_rate_value;
#endif
uint8_t colour_description_present_flag; // u(1)
@@ -785,6 +786,9 @@
uint8_t mb_adaptive_frame_field_flag;
uint8_t direct_8x8_inference_flag;
uint8_t frame_cropping_flag;
+#ifdef VBP
+ uint8_t separate_colour_plane_flag;
+#endif
uint16_t vui_parameters_present_flag;
uint16_t chroma_format_idc;
diff --git a/mix_vbp/viddec_fw/fw/codecs/h264/parser/h264parse_sps.c b/mix_vbp/viddec_fw/fw/codecs/h264/parser/h264parse_sps.c
index 8cedd1f..4a329b0 100644
--- a/mix_vbp/viddec_fw/fw/codecs/h264/parser/h264parse_sps.c
+++ b/mix_vbp/viddec_fw/fw/codecs/h264/parser/h264parse_sps.c
@@ -3,6 +3,9 @@
#include "h264.h"
#include "h264parse.h"
+#ifdef VBP
+#include<math.h>
+#endif
/// SPS extension unit (unit_type = 13)
@@ -300,11 +303,20 @@
//SPS->constraint_set2_flag = h264_GetBits(pInfo, 1, "constraint_set2_flag");
//SPS->constraint_set3_flag = h264_GetBits(pInfo, 1, "constraint_set3_flag");
+#ifdef VBP
+ viddec_pm_get_bits(parent, &code, 5); //constraint flag set0...set4 (h.264 Spec v2009)
+ SPS->constraint_set_flags = (uint8_t)code;
+
+ //// reserved_zero_3bits
+ viddec_pm_get_bits(parent, (uint32_t *)&code, 3); //3bits zero reserved (h.264 Spec v2009)
+#else
+
viddec_pm_get_bits(parent, &code, 4);
SPS->constraint_set_flags = (uint8_t)code;
//// reserved_zero_4bits
viddec_pm_get_bits(parent, (uint32_t *)&code, 4);
+#endif
viddec_pm_get_bits(parent, &code, 8);
SPS->level_idc = (uint8_t)code;
@@ -338,6 +350,9 @@
//// seq_parameter_set_id ---[0,31]
if (SPS->seq_parameter_set_id > MAX_NUM_SPS -1)
break;
+#ifdef VBP
+ SPS->sps_disp.separate_colour_plane_flag = 0;
+#endif
if ((SPS->profile_idc == h264_ProfileHigh) || (SPS->profile_idc == h264_ProfileHigh10) ||
(SPS->profile_idc == h264_ProfileHigh422) || (SPS->profile_idc == h264_ProfileHigh444) )
@@ -349,6 +364,12 @@
SPS->sps_disp.chroma_format_idc = (uint8_t)data;
//if(SPS->sps_disp.chroma_format_idc == H264_CHROMA_444) {}
+#ifdef VBP
+ if(SPS->sps_disp.chroma_format_idc == H264_CHROMA_444) {
+ viddec_pm_get_bits(parent, &code, 1);
+ SPS->sps_disp.separate_colour_plane_flag = (uint8_t)data;
+ }
+#endif
//// bit_depth_luma_minus8 ---[0,4], -----only support 8-bit pixel
data = h264_GetVLCElement(parent, pInfo, false);
if ( data)
@@ -502,13 +523,112 @@
if (SPS->sps_disp.vui_parameters_present_flag)
{
-#ifndef VBP // Ignore VUI parsing result
- ret =
+#ifndef VBP
+ ret = h264_Parse_Vui_Parameters(parent, pInfo, SPS, pVUI_Seq_Not_Used);
+#else
+ // Ignore VUI parsing result
+ h264_Parse_Vui_Parameters(parent, pInfo, SPS, pVUI_Seq_Not_Used);
+ if (SPS->sps_disp.vui_seq_parameters.nal_hrd_parameters_present_flag)
+ {
+ i = SPS->sps_disp.vui_seq_parameters.nal_hrd_cpb_cnt_minus1;
+ uint32_t bit_rate_value = 0;
+ bit_rate_value = pVUI_Seq_Not_Used->nal_hrd_parameters.bit_rate_value_minus1[i] + 1;
+ bit_rate_value *= pow(2, 6 + pVUI_Seq_Not_Used->nal_hrd_bit_rate_scale);
+ SPS->sps_disp.vui_seq_parameters.bit_rate_value = bit_rate_value;
+ }
+ /*
+ else if (SPS->sps_disp.vui_seq_parameters.vcl_hrd_parameters_present_flag)
+ {
+ i = SPS->sps_disp.vui_seq_parameters.vcl_hrd_cpb_cnt_minus1;
+ uint32_t bit_rate_value = 0;
+ bit_rate_value = pVUI_Seq_Not_Used->vcl_hrd_parameters.bit_rate_value_minus1[i] + 1;
+ bit_rate_value *= pow(2, 6 + pVUI_Seq_Not_Used->vcl_hrd_bit_rate_scale);
+ SPS->sps_disp.vui_seq_parameters.bit_rate_value = bit_rate_value;
+ }*/
+
#endif
- h264_Parse_Vui_Parameters(parent, pInfo, SPS, pVUI_Seq_Not_Used);
+ }
+ } while (0);
+#ifdef VBP
+ if (SPS->sps_disp.vui_seq_parameters.bit_rate_value == 0)
+ {
+ int maxBR = 0;
+ switch(SPS->level_idc)
+ {
+ case h264_Level1:
+ maxBR = 64;
+ break;
+
+ case h264_Level1b:
+ maxBR = 128;
+ break;
+
+ case h264_Level11:
+ maxBR = 192;
+ break;
+
+ case h264_Level12:
+ maxBR = 384;
+ break;
+
+ case h264_Level13:
+ maxBR = 768;
+ break;
+
+ case h264_Level2:
+ maxBR = 2000;
+ break;
+
+ case h264_Level21:
+ case h264_Level22:
+ maxBR = 4000;
+ break;
+
+ case h264_Level3:
+ maxBR = 10000;
+ break;
+
+ case h264_Level31:
+ maxBR = 14000;
+ break;
+
+ case h264_Level32:
+ case h264_Level4:
+ maxBR = 20000;
+ break;
+
+ case h264_Level41:
+ case h264_Level42:
+ maxBR = 50000;
+ break;
+
+ case h264_Level5:
+ maxBR = 135000;
+ break;
+
+ case h264_Level51:
+ maxBR = 240000;
+ break;
}
- } while (0);
+ uint32_t cpbBrVclFactor = 1200;
+ if (SPS->profile_idc == 100)
+ {
+ cpbBrVclFactor = 1500; // HIGH
+ }
+ else if (SPS->profile_idc == 110)
+ {
+ cpbBrVclFactor = 3600; // HIGH 10
+ }
+ else if (SPS->profile_idc == 122 ||
+ SPS->profile_idc == 144)
+ {
+ cpbBrVclFactor = 4800; // HIGH 4:2:2 and HIGH 4:4:4
+ }
+
+ SPS->sps_disp.vui_seq_parameters.bit_rate_value = maxBR * cpbBrVclFactor;
+ }
+#endif
//h264_Parse_rbsp_trailing_bits(pInfo);
diff --git a/mix_vbp/viddec_fw/fw/codecs/vc1/parser/vc1parse.c b/mix_vbp/viddec_fw/fw/codecs/vc1/parser/vc1parse.c
index fb59613..0fe26c9 100644
--- a/mix_vbp/viddec_fw/fw/codecs/vc1/parser/vc1parse.c
+++ b/mix_vbp/viddec_fw/fw/codecs/vc1/parser/vc1parse.c
@@ -37,6 +37,13 @@
result = viddec_pm_get_bits(ctxt, &rcv.struct_a_rcv, 32);
md->width = rcv.struct_a.HORIZ_SIZE;
md->height = rcv.struct_a.VERT_SIZE;
+#ifdef VBP
+ //The HRD rate and HRD buffer size may be encoded according to a 64 bit sequence header data structure B
+ //if there is no data strcuture B metadata contained in the bitstream, we will not be able to get the
+ //bitrate data, hence we set it to 0 for now
+ md->HRD_NUM_LEAKY_BUCKETS = 0;
+ md->hrd_initial_state.sLeakyBucket[0].HRD_RATE = 0;
+#endif
result = viddec_pm_get_bits(ctxt, &rcv.struct_c_rcv, 32);
md->PROFILE = rcv.struct_c.PROFILE >> 2;
@@ -203,11 +210,44 @@
result = viddec_pm_get_bits(ctxt, &tempValue, 5);
sh.HRD_NUM_LEAKY_BUCKETS = tempValue;
md->HRD_NUM_LEAKY_BUCKETS = sh.HRD_NUM_LEAKY_BUCKETS;
+#ifndef VBP
// Skip the rest of the parsing - hrdinfo is not required for decode or for attributes
+#else
+ {
+ uint8_t count;
+ uint8_t bitRateExponent;
+ uint8_t bufferSizeExponent;
+
+ /* bit_rate_exponent */
+ result = viddec_pm_get_bits(ctxt, &tempValue, 4);
+ bitRateExponent = (uint8_t)(tempValue + 6);
+
+ /* buffer_size_exponent */
+ result = viddec_pm_get_bits(ctxt, &tempValue, 4);
+ bufferSizeExponent = (uint8_t)(tempValue + 4);
+ md->hrd_initial_state.BUFFER_SIZE_EXPONENT = bufferSizeExponent;
+
+ for(count = 0; count < sh.HRD_NUM_LEAKY_BUCKETS; count++)
+ {
+ /* hrd_rate */
+ result = viddec_pm_get_bits(ctxt, &tempValue, 16);
+ md->hrd_initial_state.sLeakyBucket[count].HRD_RATE =
+ (uint32_t)(tempValue + 1) << bitRateExponent;
+
+ /* hrd_buffer */
+ result = viddec_pm_get_bits(ctxt, &tempValue, 16);
+ md->hrd_initial_state.sLeakyBucket[count].HRD_BUFFER =
+ (uint32_t)(tempValue + 1) << bufferSizeExponent;
+ }
+ }
+#endif
}
else
{
md->HRD_NUM_LEAKY_BUCKETS = 0;
+#ifdef VBP
+ md->hrd_initial_state.sLeakyBucket[0].HRD_RATE = 0;
+#endif
}
md->widthMB = (((md->width + 1) * 2) + 15) / VC1_PIXEL_IN_LUMA;
diff --git a/mix_vbp/viddec_fw/fw/codecs/vc1/parser/vc1parse_common_defs.h b/mix_vbp/viddec_fw/fw/codecs/vc1/parser/vc1parse_common_defs.h
index 821df32..e474800 100644
--- a/mix_vbp/viddec_fw/fw/codecs/vc1/parser/vc1parse_common_defs.h
+++ b/mix_vbp/viddec_fw/fw/codecs/vc1/parser/vc1parse_common_defs.h
@@ -141,6 +141,27 @@
uint32_t *databits;
} vc1_Bitplane;
+#ifdef VBP
+#define VC1_MAX_HRD_NUM_LEAKY_BUCKETS 32
+
+ typedef struct
+ {
+ uint32_t HRD_RATE; /** Maximum bit rate in bits per second */
+ uint32_t HRD_BUFFER; /** Buffer size in bits */
+ uint32_t HRD_FULLNESS; /** Buffer fullness in complete bits */
+ uint32_t HRD_FULLFRACTION; /** Numerator of fractional bit buffer fullness count */
+ uint32_t HRD_FULLDENOMINATOR; /** Denominator of fractional bit buffer fullness count */
+ } vc1_leaky_bucket;
+
+ typedef struct _vc1_hrd_state
+ {
+ uint8_t BIT_RATE_EXPONENT; /** Buckets
+ (0 if none specified) */
+ uint8_t BUFFER_SIZE_EXPONENT;
+ vc1_leaky_bucket sLeakyBucket[VC1_MAX_HRD_NUM_LEAKY_BUCKETS]; /** Per-bucket information */
+ } vc1_hrd_state, *vc1_hrd_state_ptr;
+#endif
+
/** This structure represents all bitstream metadata needed for register programming. */
typedef struct
{
@@ -214,7 +235,7 @@
uint8_t ASPECT_RATIO;
uint8_t ASPECT_HORIZ_SIZE;
uint8_t ASPECT_VERT_SIZE;
-
+ vc1_hrd_state hrd_initial_state;
#endif
} vc1_metadata_t;
diff --git a/mix_vbp/viddec_fw/fw/codecs/vc1/parser/viddec_vc1_parse.c b/mix_vbp/viddec_fw/fw/codecs/vc1/parser/viddec_vc1_parse.c
index a1b47ff..8a90804 100644
--- a/mix_vbp/viddec_fw/fw/codecs/vc1/parser/viddec_vc1_parse.c
+++ b/mix_vbp/viddec_fw/fw/codecs/vc1/parser/viddec_vc1_parse.c
@@ -119,6 +119,55 @@
parser->sc_seen_since_last_wkld |= VC1_SC_SEQ;
#ifdef VBP
parser->start_code = VC1_SC_SEQ;
+ if (parser->info.metadata.HRD_NUM_LEAKY_BUCKETS == 0)
+ {
+ if (parser->info.metadata.PROFILE == VC1_PROFILE_SIMPLE)
+ {
+ switch(parser->info.metadata.LEVEL)
+ {
+ case 0:
+ parser->info.metadata.hrd_initial_state.sLeakyBucket[0].HRD_RATE = 96000;
+ break;
+ case 1:
+ parser->info.metadata.hrd_initial_state.sLeakyBucket[0].HRD_RATE = 384000;
+ break;
+ }
+ }
+ else if (parser->info.metadata.PROFILE == VC1_PROFILE_MAIN)
+ {
+ switch(parser->info.metadata.LEVEL)
+ {
+ case 0:
+ parser->info.metadata.hrd_initial_state.sLeakyBucket[0].HRD_RATE = 2000000;
+ break;
+ case 1:
+ parser->info.metadata.hrd_initial_state.sLeakyBucket[0].HRD_RATE = 10000000;
+ break;
+ case 2:
+ parser->info.metadata.hrd_initial_state.sLeakyBucket[0].HRD_RATE = 20000000;
+ break;
+ }
+ }
+ else if (parser->info.metadata.PROFILE == VC1_PROFILE_ADVANCED)
+ {
+ switch(parser->info.metadata.LEVEL)
+ {
+ case 0:
+ parser->info.metadata.hrd_initial_state.sLeakyBucket[0].HRD_RATE = 2000000;
+ break;
+ case 1:
+ parser->info.metadata.hrd_initial_state.sLeakyBucket[0].HRD_RATE = 10000000;
+ break;
+ case 2:
+ parser->info.metadata.hrd_initial_state.sLeakyBucket[0].HRD_RATE = 20000000;
+ break;
+ case 3:
+ parser->info.metadata.hrd_initial_state.sLeakyBucket[0].HRD_RATE = 45000000;
+ break;
+ }
+ }
+ }
+
#endif
break;
}
diff --git a/mix_vbp/viddec_fw/fw/parser/vbp_h264_parser.c b/mix_vbp/viddec_fw/fw/parser/vbp_h264_parser.c
index dd3c12d..f01dc3b 100644
--- a/mix_vbp/viddec_fw/fw/parser/vbp_h264_parser.c
+++ b/mix_vbp/viddec_fw/fw/parser/vbp_h264_parser.c
@@ -792,8 +792,12 @@
codec_data->level_idc = parser->info.active_SPS.level_idc;
- codec_data->constraint_set1_flag = (parser->info.active_SPS.constraint_set_flags & 0x4) >> 2;
-
+ /*constraint flag sets (h.264 Spec v2009)*/
+ codec_data->constraint_set0_flag = (parser->info.active_SPS.constraint_set_flags & 0x10) >> 4;
+ codec_data->constraint_set1_flag = (parser->info.active_SPS.constraint_set_flags & 0x8) >> 3;
+ codec_data->constraint_set2_flag = (parser->info.active_SPS.constraint_set_flags & 0x4) >> 2;
+ codec_data->constraint_set3_flag = (parser->info.active_SPS.constraint_set_flags & 0x2) >> 1;
+ codec_data->constraint_set4_flag = parser->info.active_SPS.constraint_set_flags & 0x1;
/* reference frames */
codec_data->num_ref_frames = parser->info.active_SPS.num_ref_frames;
@@ -817,6 +821,41 @@
codec_data->frame_height = (2 - parser->info.active_SPS.sps_disp.frame_mbs_only_flag) *
(parser->info.active_SPS.sps_disp.pic_height_in_map_units_minus1 + 1) * 16;
+ /* cropping information */
+ codec_data->crop_left = 0;
+ codec_data->crop_right = 0;
+ codec_data->crop_top = 0;
+ codec_data->crop_bottom = 0;
+ if(parser->info.active_SPS.sps_disp.frame_cropping_flag) {
+ int CropUnitX = 0, CropUnitY = 0, SubWidthC = 0, SubHeightC = 0;
+ int ChromaArrayType = 0;
+ if(parser->info.active_SPS.sps_disp.separate_colour_plane_flag == 0) {
+ if(parser->info.active_SPS.sps_disp.chroma_format_idc == 1) {
+ SubWidthC = 2;
+ SubHeightC = 2;
+ } else if( parser->info.active_SPS.sps_disp.chroma_format_idc == 2) {
+ SubWidthC = 2;
+ SubHeightC = 1;
+ } else if( parser->info.active_SPS.sps_disp.chroma_format_idc == 3) {
+ SubWidthC = 1;
+ SubHeightC = 1;
+ }
+ ChromaArrayType = parser->info.active_SPS.sps_disp.chroma_format_idc;
+ }
+
+ if(ChromaArrayType == 0) {
+ CropUnitX = 1;
+ CropUnitY = 2 - parser->info.active_SPS.sps_disp.frame_mbs_only_flag;
+ } else {
+ CropUnitX = SubWidthC;
+ CropUnitY = SubHeightC * ( 2 - parser->info.active_SPS.sps_disp.frame_mbs_only_flag);
+ }
+
+ codec_data->crop_left = CropUnitX * parser->info.active_SPS.sps_disp.frame_crop_rect_left_offset;
+ codec_data->crop_right = CropUnitX * parser->info.active_SPS.sps_disp.frame_crop_rect_right_offset; // + 1;
+ codec_data->crop_top = CropUnitY * parser->info.active_SPS.sps_disp.frame_crop_rect_top_offset;
+ codec_data->crop_bottom = CropUnitY * parser->info.active_SPS.sps_disp.frame_crop_rect_bottom_offset; // + 1;
+ }
/* aspect ratio */
if (parser->info.active_SPS.sps_disp.vui_seq_parameters.aspect_ratio_info_present_flag)
@@ -878,6 +917,7 @@
codec_data->matrix_coefficients = 2;
}
+ codec_data->bit_rate = parser->info.active_SPS.sps_disp.vui_seq_parameters.bit_rate_value;
/* picture order type and count */
codec_data->log2_max_pic_order_cnt_lsb_minus4 = parser->info.active_SPS.log2_max_pic_order_cnt_lsb_minus4;
@@ -1340,6 +1380,9 @@
int i = 0;
viddec_pm_cxt_t *cxt = pcontext->parser_cxt;
+ //Enable emulation prevention
+ cxt->getbits.is_emul_reqd = 1;
+
/* check if configuration data is start code prefix */
viddec_sc_parse_cubby_cxt_t cubby = cxt->parse_cubby;
viddec_parser_ops_t *ops = pcontext->parser_ops;
@@ -1725,17 +1768,15 @@
break;
case h264_NAL_UNIT_TYPE_SPS:
- if (query_data->has_sps)
- query_data->new_sps = 1;
+
+ query_data->new_sps = 1;
query_data->has_sps = 1;
query_data->has_pps = 0;
ITRACE("SPS header is parsed.");
break;
case h264_NAL_UNIT_TYPE_PPS:
- if (query_data->has_pps || query_data->new_sps)
- query_data->new_pps = 1;
-
+ query_data->new_pps = 1;
query_data->has_pps = 1;
ITRACE("PPS header is parsed.");
break;
diff --git a/mix_vbp/viddec_fw/fw/parser/vbp_loader.h b/mix_vbp/viddec_fw/fw/parser/vbp_loader.h
index 0ef4fbf..ccf8e00 100644
--- a/mix_vbp/viddec_fw/fw/parser/vbp_loader.h
+++ b/mix_vbp/viddec_fw/fw/parser/vbp_loader.h
@@ -61,6 +61,8 @@
uint8 par_width;
uint8 par_height;
+ // bit rate
+ int bit_rate;
} vbp_codec_data_mp42;
typedef struct _vbp_slice_data_mp42
@@ -108,7 +110,12 @@
uint8 profile_idc;
uint8 level_idc;
+ /*constraint flag sets (h.264 Spec v2009)*/
+ uint8 constraint_set0_flag;
uint8 constraint_set1_flag;
+ uint8 constraint_set2_flag;
+ uint8 constraint_set3_flag;
+ uint8 constraint_set4_flag;
uint8 num_ref_frames;
uint8 gaps_in_frame_num_value_allowed_flag;
@@ -126,6 +133,12 @@
uint16 sar_width;
uint16 sar_height;
+ /* cropping information */
+ int crop_top;
+ int crop_bottom;
+ int crop_left;
+ int crop_right;
+
/* video fromat */
// default 5 unspecified
@@ -254,7 +267,8 @@
uint8 ASPECT_HORIZ_SIZE;
uint8 ASPECT_VERT_SIZE;
-
+ // bit rate
+ int bit_rate;
} vbp_codec_data_vc1;
typedef struct _vbp_slice_data_vc1
diff --git a/mix_vbp/viddec_fw/fw/parser/vbp_mp42_parser.c b/mix_vbp/viddec_fw/fw/parser/vbp_mp42_parser.c
index 740235d..e1a0829 100644
--- a/mix_vbp/viddec_fw/fw/parser/vbp_mp42_parser.c
+++ b/mix_vbp/viddec_fw/fw/parser/vbp_mp42_parser.c
@@ -346,6 +346,8 @@
vbp_data_mp42 *query_data = (vbp_data_mp42 *) pcontext->query_data;
vbp_codec_data_mp42* codec_data = &(query_data->codec_data);
+ codec_data->bit_rate = parser->info.VisualObject.VideoObject.VOLControlParameters.bit_rate;
+
codec_data->profile_and_level_indication
= parser->info.profile_and_level_indication;
diff --git a/mix_vbp/viddec_fw/fw/parser/vbp_vc1_parser.c b/mix_vbp/viddec_fw/fw/parser/vbp_vc1_parser.c
index 21c431a..f84dbd7 100644
--- a/mix_vbp/viddec_fw/fw/parser/vbp_vc1_parser.c
+++ b/mix_vbp/viddec_fw/fw/parser/vbp_vc1_parser.c
@@ -692,6 +692,14 @@
/* first we get the SH/EP data. Can we cut down on this? */
vbp_codec_data_vc1 *se_data = query_data->se_data;
+
+
+ uint32_t curHrdNum = seqLayerHeader->HRD_NUM_LEAKY_BUCKETS;
+
+ se_data->bit_rate = curHrdNum ?
+ seqLayerHeader->hrd_initial_state.sLeakyBucket[curHrdNum -1].HRD_RATE :
+ seqLayerHeader->hrd_initial_state.sLeakyBucket[0].HRD_RATE;
+
se_data->PROFILE = seqLayerHeader->PROFILE;
se_data->LEVEL = seqLayerHeader->LEVEL;
se_data->POSTPROCFLAG = seqLayerHeader->POSTPROCFLAG;
diff --git a/mix_video/src/mixframemanager.cpp b/mix_video/src/mixframemanager.cpp
index 31b84fc..adfc53e 100644
--- a/mix_video/src/mixframemanager.cpp
+++ b/mix_video/src/mixframemanager.cpp
@@ -236,10 +236,13 @@
if (fm->mode == MIX_DISPLAY_ORDER_PICNUMBER) {
uint32 num;
mix_videoframe_get_displayorder(mvf, &num);
- LOG_V("pic %d is enqueued.\n", num);
+ uint64 ts;
+ mix_videoframe_get_timestamp(mvf, &ts);
+ LOG_V("pic %d is enqueued, ts = %"INT64_FORMAT"\n", num, ts);
}
- if (fm->mode == MIX_DISPLAY_ORDER_TIMESTAMP) {
+ else// if (fm->mode == MIX_DISPLAY_ORDER_TIMESTAMP) {
+ {
uint64 ts;
mix_videoframe_get_timestamp(mvf, &ts);
LOG_V("ts %"UINT64_FORMAT" is enqueued.\n", ts);
@@ -337,6 +340,11 @@
{
first_i_or_p = p;
}
+
+ // When there are more than 1 i or p frame in queue,
+ // we shouldn't update the B frame's time stamp again.
+ if (num_i_or_p > 1)
+ break;
}
// if there are more than one reference frame in the list, the first one is dequeued.
@@ -461,12 +469,17 @@
uint32 picnum;
uint32 next_picnum_pending;
+ int least_poc_index;
+ uint32 least_poc;
+
len = j_slist_length(fm->frame_list);
retry:
next_picnum_pending = (uint32)-1;
+ least_poc_index = -1;
+ least_poc = (uint32)-1;
- for (i = 0; i < len; i++)
+ for (i = 0; i < len; )
{
p = (MixVideoFrame*)j_slist_nth_data(fm->frame_list, i);
mix_videoframe_get_displayorder(p, &picnum);
@@ -482,6 +495,23 @@
return MIX_RESULT_SUCCESS;
}
+ if(picnum == 0) {
+ if(i == 0) {
+ fm->next_frame_picnumber = 0;
+ } else {
+ fm->next_frame_picnumber = least_poc;
+ i = least_poc_index;
+ }
+ continue;
+ }
+ if(picnum < least_poc) {
+ least_poc = picnum;
+ least_poc_index = i;
+ LOG_V("least_poc_index = %d\n", least_poc_index);
+ }
+
+ ++i;
+
if (picnum > fm->next_frame_picnumber &&
picnum < next_picnum_pending)
{
diff --git a/mix_video/src/mixsurfacepool.cpp b/mix_video/src/mixsurfacepool.cpp
index 5c6899c..d5328bc 100644
--- a/mix_video/src/mixsurfacepool.cpp
+++ b/mix_video/src/mixsurfacepool.cpp
@@ -392,9 +392,9 @@
obj->mLock.unlock();
- LOG_E( "Element is null\n");
+ LOG_E( "Element associated with the given frame index is null\n");
- return MIX_RESULT_FAIL;
+ return MIX_RESULT_DROPFRAME;
} else {
//Concat the element to the in_use_list
obj->in_use_list = j_slist_concat(obj->in_use_list, element);
diff --git a/mix_video/src/mixvideoconfigparamsdec.cpp b/mix_video/src/mixvideoconfigparamsdec.cpp
index 3500b3c..0d6e72f 100644
--- a/mix_video/src/mixvideoconfigparamsdec.cpp
+++ b/mix_video/src/mixvideoconfigparamsdec.cpp
@@ -32,25 +32,30 @@
MixVideoConfigParamsDec::MixVideoConfigParamsDec()
- :frame_order_mode(MIX_FRAMEORDER_MODE_DISPLAYORDER)
- ,mime_type(NULL)
- ,frame_rate_num(0)
- ,frame_rate_denom(0)
- ,picture_width(0)
- ,picture_height(0)
- ,raw_format(0)
- ,rate_control(0)
- ,mixbuffer_pool_size(0)
- ,extra_surface_allocation(0)
- ,video_range(0)
- ,color_matrix(0)
- ,bit_rate(0)
- ,par_num(0)
- ,par_denom(0)
- ,reserved1(NULL)
- ,reserved2(NULL)
- ,reserved3(NULL)
- ,reserved4(NULL)
+ :frame_order_mode(MIX_FRAMEORDER_MODE_DISPLAYORDER)
+ ,mime_type(NULL)
+ ,frame_rate_num(1)
+ ,frame_rate_denom(1)
+ ,picture_width(0)
+ ,picture_height(0)
+ ,raw_format(0)
+ ,rate_control(0)
+ ,mixbuffer_pool_size(0)
+ ,extra_surface_allocation(0)
+ ,video_range(0)
+ ,color_matrix(0)
+ ,bit_rate(0)
+ ,par_num(0)
+ ,par_denom(0)
+ ,crop_left(0)
+ ,crop_right(0)
+ ,crop_top(0)
+ ,crop_bottom(0)
+ ,error_concealment(TRUE)
+ ,reserved1(NULL)
+ ,reserved2(NULL)
+ ,reserved3(NULL)
+ ,reserved4(NULL)
{
memset(&this->header, 0, sizeof(header));
@@ -91,6 +96,11 @@
this_target->bit_rate = this->bit_rate;
this_target->par_num = this->par_num;
this_target->par_denom = this->par_denom;
+ this_target->crop_left = this->crop_left;
+ this_target->crop_right = this->crop_right;
+ this_target->crop_top = this->crop_top;
+ this_target->crop_bottom = this->crop_bottom;
+ this_target->error_concealment = this->error_concealment;
/* copy properties of non-primitive */
@@ -214,6 +224,27 @@
if (this->par_denom != this_obj->par_denom) {
goto not_equal;
}
+
+ if (this->crop_left != this_obj->crop_left)
+ {
+ goto not_equal;
+ }
+ if (this->crop_right != this_obj->crop_right)
+ {
+ goto not_equal;
+ }
+ if (this->crop_top != this_obj->crop_top)
+ {
+ goto not_equal;
+ }
+ if (this->crop_bottom != this_obj->crop_bottom)
+ {
+ goto not_equal;
+ }
+ if (this->error_concealment != this_obj->error_concealment)
+ {
+ goto not_equal;
+ }
ret = TRUE;
not_equal:
@@ -502,4 +533,44 @@
return MIX_RESULT_SUCCESS;
}
+MIX_RESULT mix_videoconfigparamsdec_set_cropping_info(MixVideoConfigParamsDec * obj,
+ uint crop_left, uint crop_right, uint crop_top, uint crop_bottom)
+{
+ MIX_VIDEOCONFIGPARAMSDEC_SETTER_CHECK_INPUT (obj);
+ obj->crop_left = crop_left;
+ obj->crop_right = crop_right;
+ obj->crop_top = crop_top;
+ obj->crop_bottom = crop_bottom;
+ return MIX_RESULT_SUCCESS;
+}
+
+MIX_RESULT mix_videoconfigparamsdec_get_cropping_info(MixVideoConfigParamsDec * obj,
+ uint *crop_left, uint *crop_right, uint *crop_top, uint *crop_bottom)
+{
+ MIX_VIDEOCONFIGPARAMSDEC_GETTER_CHECK_INPUT_PAIR (obj, crop_left, crop_right);
+ if(!crop_top || !crop_bottom ) {
+ return MIX_RESULT_NULL_PTR;
+ }
+ *crop_left = obj->crop_left;
+ *crop_right = obj->crop_right;
+ *crop_top = obj->crop_top;
+ *crop_bottom = obj->crop_bottom;
+ return MIX_RESULT_SUCCESS;
+}
+
+MIX_RESULT mix_videoconfigparamsdec_set_error_concealment (
+ MixVideoConfigParamsDec * obj, bool error_concealment) {
+ MIX_VIDEOCONFIGPARAMSDEC_SETTER_CHECK_INPUT (obj);
+
+ obj->error_concealment = error_concealment;
+ return MIX_RESULT_SUCCESS;
+}
+
+MIX_RESULT mix_videoconfigparamsdec_get_error_concealment(
+ MixVideoConfigParamsDec * obj, bool *error_concealment) {
+ MIX_VIDEOCONFIGPARAMSDEC_GETTER_CHECK_INPUT (obj, error_concealment);
+
+ *error_concealment = obj->error_concealment;
+ return MIX_RESULT_SUCCESS;
+}
diff --git a/mix_video/src/mixvideoconfigparamsdec.h b/mix_video/src/mixvideoconfigparamsdec.h
index f492128..a3778ee 100644
--- a/mix_video/src/mixvideoconfigparamsdec.h
+++ b/mix_video/src/mixvideoconfigparamsdec.h
@@ -92,7 +92,7 @@
uint8 color_matrix;
/* bit rate in bps, output only */
- uint8 bit_rate;
+ uint bit_rate;
/* Pixel aspect ratio numerator value */
uint par_num;
@@ -100,6 +100,14 @@
/* Pixel aspect ratio denominator value */
uint par_denom;
+ uint crop_left;
+ uint crop_right;
+ uint crop_top;
+ uint crop_bottom;
+
+ /* Error concealment enabled/disabled */
+ bool error_concealment;
+
/* Reserved for future use */
void *reserved1;
@@ -452,6 +460,57 @@
MIX_RESULT mix_videoconfigparamsdec_get_pixel_aspect_ratio(MixVideoConfigParamsDec * obj,
uint * par_num, uint * par_denom);
+/**
+ * mix_videoconfigparamsdec_set_cropping_info:
+ * @obj: #MixVideoConfigParamsDec object
+ * @crop_left: left cropping value
+ * @crop_right: right cropping value
+ * @crop_top: top cropping value
+ * @crop_bottom: bottom cropping value
+ * @returns: <link linkend="MixVideo-mixvideodef">Common Video Error Return Codes</link>
+ *
+ * Set cropping information
+ */
+MIX_RESULT mix_videoconfigparamsdec_set_cropping_info(MixVideoConfigParamsDec * obj,
+ uint crop_left, uint crop_right, uint crop_top, uint crop_bottom);
+
+/**
+ * mix_videoconfigparamsdec_get_cropping_info:
+ * @obj: #MixVideoConfigParamsDec object
+ * @crop_left: left cropping value
+ * @crop_right: right cropping value
+ * @crop_top: top cropping value
+ * @crop_bottom: bottom cropping value
+ * @returns: <link linkend="MixVideo-mixvideodef">Common Video Error Return Codes</link>
+ *
+ * Get cropping information
+ */
+MIX_RESULT mix_videoconfigparamsdec_get_cropping_info(MixVideoConfigParamsDec * obj,
+ uint *crop_left, uint *crop_right, uint *crop_top, uint *crop_bottom);
+
+
+/**
+ * mix_videoconfigparamsdec_set_error_concealment:
+ * @obj: #MixVideoConfigParamsDec object
+ * @error_concealment: A flag to indicate whether error concealment is enabled for decoder
+ * @returns: <link linkend="MixVideo-mixvideodef">Common Video Error Return Codes</link>
+ *
+ * Set the flag that indicates whether error concealment is enabled
+ */
+MIX_RESULT mix_videoconfigparamsdec_set_error_concealment (MixVideoConfigParamsDec * obj,
+ bool error_concealment);
+
+/**
+ * mix_videoconfigparamsdec_get_error_concealment:
+ * @obj: #MixVideoConfigParamsDec object
+ * @error_concealment: the flag to be returned that indicates error concealment is enabled for decoder
+ * @returns: <link linkend="MixVideo-mixvideodef">Common Video Error Return Codes</link>
+ *
+ * Get the flag that indicates whether error concealment is enabled
+ */
+MIX_RESULT mix_videoconfigparamsdec_get_error_concealment(MixVideoConfigParamsDec * obj,
+ bool *error_concealment);
+
/* TODO: Add getters and setters for other properties */
diff --git a/mix_video/src/mixvideoconfigparamsdec_h264.cpp b/mix_video/src/mixvideoconfigparamsdec_h264.cpp
index 64dfdf7..bfbcacc 100644
--- a/mix_video/src/mixvideoconfigparamsdec_h264.cpp
+++ b/mix_video/src/mixvideoconfigparamsdec_h264.cpp
@@ -16,10 +16,11 @@
#include "mixvideoconfigparamsdec_h264.h"
MixVideoConfigParamsDecH264::MixVideoConfigParamsDecH264()
- :reserved1(NULL)
- ,reserved2(NULL)
- ,reserved3(NULL)
- ,reserved4(NULL) {
+ :va_setup_flag(FALSE)
+ ,reserved1(NULL)
+ ,reserved2(NULL)
+ ,reserved3(NULL)
+ ,reserved4(NULL) {
}
MixVideoConfigParamsDecH264::~MixVideoConfigParamsDecH264() {
}
@@ -27,6 +28,8 @@
bool MixVideoConfigParamsDecH264::copy(MixParams *target) const {
bool ret = FALSE;
MixVideoConfigParamsDecH264 * this_target = MIX_VIDEOCONFIGPARAMSDEC_H264(target);
+
+ this_target->va_setup_flag = this->va_setup_flag;
if (NULL != this_target)
ret = MixVideoConfigParamsDec::copy(target);
return ret;
@@ -35,6 +38,18 @@
bool MixVideoConfigParamsDecH264::equal(MixParams* obj) const {
bool ret = FALSE;
MixVideoConfigParamsDecH264 * this_obj = MIX_VIDEOCONFIGPARAMSDEC_H264(obj);
+
+ if (this->va_setup_flag != this_obj->va_setup_flag) {
+ goto not_equal;
+ }
+
+ ret = TRUE;
+
+not_equal:
+
+ if (ret != TRUE) {
+ return ret;
+ }
if (NULL != this_obj)
ret = MixVideoConfigParamsDec::equal(this_obj);
return ret;
@@ -63,4 +78,28 @@
return mix;
}
-/* TODO: Add getters and setters for properties if any */
+#define MIX_VIDEOCONFIGPARAMSDEC_H264_SETTER_CHECK_INPUT(obj) \
+ if(!obj) return MIX_RESULT_NULL_PTR; \
+ if(!MIX_IS_VIDEOCONFIGPARAMSDEC_H264(obj)) return MIX_RESULT_FAIL; \
+
+#define MIX_VIDEOCONFIGPARAMSDEC_H264_GETTER_CHECK_INPUT(obj, prop) \
+ if(!obj || !prop) return MIX_RESULT_NULL_PTR; \
+ if(!MIX_IS_VIDEOCONFIGPARAMSDEC_H264(obj)) return MIX_RESULT_FAIL; \
+
+
+MIX_RESULT mix_videoconfigparamsdec_h264_set_va_setup_flag (MixVideoConfigParamsDecH264 * obj,
+ bool va_setup_flag) {
+
+ MIX_VIDEOCONFIGPARAMSDEC_H264_SETTER_CHECK_INPUT (obj);
+ obj->va_setup_flag = va_setup_flag;
+ return MIX_RESULT_SUCCESS;
+}
+
+MIX_RESULT mix_videoconfigparamsenc_h264_get_va_setup_flag (MixVideoConfigParamsDecH264 * obj,
+ bool *va_setup_flag) {
+
+ MIX_VIDEOCONFIGPARAMSDEC_H264_GETTER_CHECK_INPUT (obj, va_setup_flag);
+ *va_setup_flag = obj->va_setup_flag;
+ return MIX_RESULT_SUCCESS;
+}
+
diff --git a/mix_video/src/mixvideoconfigparamsdec_h264.h b/mix_video/src/mixvideoconfigparamsdec_h264.h
index ee8b786..e461765 100644
--- a/mix_video/src/mixvideoconfigparamsdec_h264.h
+++ b/mix_video/src/mixvideoconfigparamsdec_h264.h
@@ -44,6 +44,7 @@
/*< public > */
/* TODO: Add H.264 configuration paramters */
+ bool va_setup_flag;
/* Reserved for future use */
void *reserved1;
@@ -95,5 +96,26 @@
/* Class Methods */
-/* TODO: Add getters and setters for other properties */
+/**
+ * mix_videoconfigparamsenc_h264_set_va_setup_flag:
+ * @obj: #MixVideoConfigParamsDecH264 object
+ * @va_setup_flag: The flag to enable/disable setup va directly
+ * @returns: <link linkend="MixVideo-mixvideodef">Common Video Error Return Codes</link>
+ *
+ * Set the The flag to enable/disable setup va directly
+ */
+MIX_RESULT mix_videoconfigparamsdec_h264_set_va_setup_flag (MixVideoConfigParamsDecH264 * obj,
+ bool va_setup_flag);
+
+/**
+ * mix_videoconfigparamsenc_h264_get_va_setup_flag:
+ * @obj: #MixVideoConfigParamsDecH264 object
+ * @va_setup_flag: The flag to enable/disable setup va directly
+ * @returns: <link linkend="MixVideo-mixvideodef">Common Video Error Return Codes</link>
+ *
+ * Get the The flag to enable/disable setup va directly
+ */
+MIX_RESULT mix_videoconfigparamsenc_h264_get_va_setup_flag (MixVideoConfigParamsDecH264 * obj,
+ bool *va_setup_flag);
+
#endif /* __MIX_VIDEOCONFIGPARAMSDEC_H264_H__ */
diff --git a/mix_video/src/mixvideodecodeparams.cpp b/mix_video/src/mixvideodecodeparams.cpp
index a0965eb..a6979f8 100644
--- a/mix_video/src/mixvideodecodeparams.cpp
+++ b/mix_video/src/mixvideodecodeparams.cpp
@@ -26,13 +26,14 @@
MixVideoDecodeParams::MixVideoDecodeParams()
- :timestamp(0)
- ,discontinuity(FALSE)
- ,new_sequence(FALSE)
- ,reserved1(NULL)
- ,reserved2(NULL)
- ,reserved3(NULL)
- ,reserved4(NULL) {
+ :timestamp(0)
+ ,discontinuity(FALSE)
+ ,new_sequence(FALSE)
+ ,complete_frame(FALSE)
+ ,reserved1(NULL)
+ ,reserved2(NULL)
+ ,reserved3(NULL)
+ ,reserved4(NULL) {
}
MixVideoDecodeParams::~MixVideoDecodeParams() {
@@ -123,3 +124,18 @@
return MIX_RESULT_SUCCESS;
}
+MIX_RESULT mix_videodecodeparams_set_complete_frame(MixVideoDecodeParams * obj,
+ bool complete_frame) {
+ MIX_VIDEODECODEPARAMS_SETTER_CHECK_INPUT (obj);
+ obj->complete_frame = complete_frame;
+ return MIX_RESULT_SUCCESS;
+}
+
+MIX_RESULT mix_videodecodeparams_get_complete_frame(MixVideoDecodeParams * obj,
+ bool *complete_frame) {
+ MIX_VIDEODECODEPARAMS_GETTER_CHECK_INPUT (obj, complete_frame);
+ *complete_frame = obj->complete_frame;
+ return MIX_RESULT_SUCCESS;
+}
+
+
diff --git a/mix_video/src/mixvideodecodeparams.h b/mix_video/src/mixvideodecodeparams.h
index 1da4cdb..aa5e799 100644
--- a/mix_video/src/mixvideodecodeparams.h
+++ b/mix_video/src/mixvideodecodeparams.h
@@ -53,6 +53,9 @@
/* output only, indicate if stream contains a new sequence */
bool new_sequence;
+ /* Indicates a complete frame */
+ bool complete_frame;
+
/* Reserved for future use */
void *reserved1;
@@ -164,5 +167,29 @@
MIX_RESULT mix_videodecodeparams_get_new_sequence(MixVideoDecodeParams * obj,
bool *new_sequence);
+/**
+ * mix_videodecodeparams_get_complete_frame:
+ * @obj: #MixVideoDecodeParams object
+ * @complete_frame: complete_frame flag to be returned
+ * @returns: <link linkend="MixVideo-mixvideodef">Common Video Error Return Codes</link>
+ *
+ * Get complete_frame flag
+ */
+MIX_RESULT mix_videodecodeparams_get_complete_frame(MixVideoDecodeParams * obj,
+ bool *complete_frame);
+
+
+/**
+ * mix_videodecodeparams_set_complete_frame:
+ * @obj: #MixVideoDecodeParams object
+ * @complete_frame: Flag to indicate if frame is a complete frame or not
+ * @returns: <link linkend="MixVideo-mixvideodef">Common Video Error Return Codes</link>
+ *
+ * Set new_sequence flag
+ */
+MIX_RESULT mix_videodecodeparams_set_complete_frame(MixVideoDecodeParams * obj,
+ bool complete_frame);
+
+
#endif /* __MIX_VIDEODECODEPARAMS_H__ */
diff --git a/mix_video/src/mixvideodef.h b/mix_video/src/mixvideodef.h
index aea6ad6..1c0aa02 100644
--- a/mix_video/src/mixvideodef.h
+++ b/mix_video/src/mixvideodef.h
@@ -72,6 +72,7 @@
uchar *data;
int buffer_size;
int data_size;
+ bool is_key_frame;
} MixIOVec;
typedef struct _MixRect {
diff --git a/mix_video/src/mixvideoformat.cpp b/mix_video/src/mixvideoformat.cpp
index 09984cb..a566694 100644
--- a/mix_video/src/mixvideoformat.cpp
+++ b/mix_video/src/mixvideoformat.cpp
@@ -15,30 +15,32 @@
#define MIXUNREF(obj, unref) if(obj) { unref(obj); obj = NULL; }
MixVideoFormat::MixVideoFormat()
- :mLock()
- ,initialized(FALSE)
- ,va_initialized(FALSE)
- ,framemgr(NULL)
- ,surfacepool(NULL)
- ,inputbufpool(NULL)
- ,inputbufqueue(NULL)
- ,va_display(NULL)
- ,va_context(VA_INVALID_ID)
- ,va_config(VA_INVALID_ID)
- ,va_surfaces(NULL)
- ,va_num_surfaces(0)
- ,mime_type(NULL)
- ,frame_rate_num(0)
- ,frame_rate_denom(0)
- ,picture_width(0)
- ,picture_height(0)
- ,parse_in_progress(FALSE)
- ,current_timestamp((uint64)-1)
- ,end_picture_pending(FALSE)
- ,video_frame(NULL)
- ,extra_surfaces(0)
- ,config_params(NULL)
- ,ref_count(1) {
+ :mLock()
+ ,initialized(FALSE)
+ ,va_initialized(FALSE)
+ ,framemgr(NULL)
+ ,surfacepool(NULL)
+ ,inputbufpool(NULL)
+ ,inputbufqueue(NULL)
+ ,va_display(NULL)
+ ,va_context(VA_INVALID_ID)
+ ,va_config(VA_INVALID_ID)
+ ,va_surfaces(NULL)
+ ,va_num_surfaces(0)
+ ,mime_type(NULL)
+ ,frame_rate_num(0)
+ ,frame_rate_denom(0)
+ ,picture_width(0)
+ ,picture_height(0)
+ ,parse_in_progress(FALSE)
+ ,current_timestamp((uint64)-1)
+ ,end_picture_pending(FALSE)
+ ,video_frame(NULL)
+ ,extra_surfaces(0)
+ ,config_params(NULL)
+ ,error_concealment(TRUE)
+ ,ref_count(1)
+{
}
MixVideoFormat::~MixVideoFormat() {
diff --git a/mix_video/src/mixvideoformat.h b/mix_video/src/mixvideoformat.h
index cda1804..bfaa440 100644
--- a/mix_video/src/mixvideoformat.h
+++ b/mix_video/src/mixvideoformat.h
@@ -121,8 +121,9 @@
bool end_picture_pending;
MixVideoFrame* video_frame;
uint extra_surfaces;
+ bool error_concealment;
MixVideoConfigParamsDec * config_params;
- uint ref_count ;
+ int ref_count;
};
diff --git a/mix_video/src/mixvideoformat_h264.cpp b/mix_video/src/mixvideoformat_h264.cpp
index 08d8e78..0bbe19a 100644
--- a/mix_video/src/mixvideoformat_h264.cpp
+++ b/mix_video/src/mixvideoformat_h264.cpp
@@ -13,11 +13,18 @@
#include "mixvideolog.h"
#include "mixvideoformat_h264.h"
+#include "mixvideoconfigparamsdec_h264.h"
#ifdef MIX_LOG_ENABLE
static int mix_video_h264_counter = 0;
#endif /* MIX_LOG_ENABLE */
+#define HACK_DPB
+#ifdef HACK_DPB
+static inline MIX_RESULT mix_videofmt_h264_hack_dpb( MixVideoFormat *mix, vbp_picture_data_h264* pic_data);
+#endif
+
+
// Local Help Funcs
@@ -74,6 +81,9 @@
vbp_data_h264 *data = NULL;
MixIOVec *header = NULL;
+ MixVideoConfigParamsDecH264 *config_params_h264 = NULL;
+ bool va_setup_flag = FALSE;
+
if (config_params == NULL || frame_mgr == NULL ||
input_buf_pool == NULL || va_display == NULL) {
LOG_E( "NUll pointer passed in\n");
@@ -118,6 +128,28 @@
goto CLEAN_UP;
}
+ ret = mix_videoconfigparamsdec_get_error_concealment(
+ config_params,
+ &this->error_concealment);
+
+ if (ret != MIX_RESULT_SUCCESS)
+ {
+ ret = MIX_RESULT_FAIL;
+ LOG_E( "Cannot get error_concealment flag\n");
+ goto CLEAN_UP;
+ }
+
+ config_params_h264 = MIX_VIDEOCONFIGPARAMSDEC_H264(config_params);
+ ret = mix_videoconfigparamsenc_h264_get_va_setup_flag(config_params_h264, &va_setup_flag);
+ if (ret != MIX_RESULT_SUCCESS)
+ {
+ ret = MIX_RESULT_FAIL;
+ LOG_E( "Failed to get va_setup_flag\n");
+ return ret;
+ }
+
+ LOG_V("va_setup_flag = %d\n", va_setup_flag);
+
LOG_V( "Before vbp_open\n");
//Load the bitstream parser
pret = vbp_open(ptype, &(this->parser_handle));
@@ -130,6 +162,17 @@
}
LOG_V( "Opened parser\n");
+ if(va_setup_flag) {
+ LOG_V("calling to mix_videofmt_h264_initialize_va(mix, NULL)\n");
+ ret = _initialize_va( NULL);
+ LOG_V("ret = 0x%x\n", ret);
+ if (ret != MIX_RESULT_SUCCESS)
+ {
+ LOG_E( "Error initializing va. \n");
+ }
+ goto CLEAN_UP;
+ }
+
ret = mix_videoconfigparamsdec_get_header(config_params, &header);
if ((MIX_RESULT_SUCCESS != ret) || (NULL == header)) {
@@ -143,7 +186,7 @@
pret = vbp_parse(this->parser_handle, header->data, header->data_size, TRUE);
- if ((VBP_OK != pret) && (VBP_DONE != pret)) {
+ if (VBP_OK != pret) {
ret = MIX_RESULT_FAIL;
LOG_E( "Error parsing header data\n");
goto CLEAN_UP;
@@ -154,7 +197,7 @@
//Get the header data and save
pret = vbp_query(this->parser_handle, (void **)&data);
- if ((VBP_OK != pret) || (NULL == data)) {
+ if (VBP_OK != pret) {
ret = MIX_RESULT_FAIL;
LOG_E( "Error reading parsed header data\n");
goto CLEAN_UP;
@@ -236,7 +279,13 @@
for (i = 0; i < bufincnt; i++) {
LOG_V( "Decoding a buf %x, size %d\n", (uint)bufin[i]->data, bufin[i]->size);
// decode a buffer at a time
- ret = _decode_a_buffer(bufin[i], ts, discontinuity, decode_params);
+ ret = _decode_a_buffer(
+ bufin[i],
+ ts,
+ discontinuity,
+ decode_params,
+ (i == bufincnt-1 ? decode_params->complete_frame : 0));
+
if (MIX_RESULT_SUCCESS != ret) {
LOG_E("mix_videofmt_h264_decode_a_buffer failed.\n");
goto CLEAN_UP;
@@ -361,6 +410,17 @@
data->codec_data->sar_height);
mix_videoconfigparamsdec_set_bit_rate(
this->config_params, data->codec_data->bit_rate);
+
+ LOG_V("crop_left = %d crop_right = %d crop_top = %d crop_bottom = %d\n",
+ data->codec_data->crop_left, data->codec_data->crop_right,
+ data->codec_data->crop_top, data->codec_data->crop_bottom);
+
+ mix_videoconfigparamsdec_set_cropping_info(
+ this->config_params,
+ data->codec_data->crop_left,
+ data->codec_data->crop_right,
+ data->codec_data->crop_top,
+ data->codec_data->crop_bottom);
return MIX_RESULT_SUCCESS;
}
@@ -379,20 +439,50 @@
attrib.value = VA_RT_FORMAT_YUV420;
//Initialize and save the VA config ID
- //We use high profile for all kinds of H.264 profiles (baseline, main and high)
- vret = vaCreateConfig(this->va_display, VAProfileH264High,
- VAEntrypointVLD, &attrib, 1, &(this->va_config));
-
+#ifdef ANDROID
+ if((this->error_concealment == TRUE) && (data == NULL || (data != NULL && ((data->codec_data->profile_idc == 66) || (data->codec_data->constraint_set0_flag == 1)) &&
+ (data->codec_data->constraint_set1_flag == 1))))
+ {
+ //it is constrained baseline profile according to subclause A.2.1.1 in H.264 Spec v200903
+ vret = vaCreateConfig(
+ this->va_display,
+ VAProfileH264ConstrainedBaseline,
+ VAEntrypointVLD,
+ &attrib,
+ 1,
+ &(this->va_config));
+ }
+ else
+ {
+#endif
+ //We use high profile for all kinds of H.264 profiles (baseline, main and high) except for constrained baseline
+ vret = vaCreateConfig(
+ this->va_display,
+ VAProfileH264High,
+ VAEntrypointVLD,
+ &attrib,
+ 1,
+ &(this->va_config));
+#ifdef ANDROID
+ }
+#endif
if (VA_STATUS_SUCCESS != vret) {
ret = MIX_RESULT_NO_MEMORY; // MIX_RESULT_FAIL;
LOG_E("vaCreateConfig failed\n");
return ret;
}
- LOG_V( "Codec data says num_ref_frames is %d\n", data->codec_data->num_ref_frames);
+#ifdef MIX_LOG_ENABLE
+ if(data) {
+ LOG_V( "Codec data says num_ref_frames is %d\n", data->codec_data->num_ref_frames);
+ }
+#endif
// handle both frame and field coding for interlaced content
- int num_ref_pictures = data->codec_data->num_ref_frames;
+ int num_ref_pictures = 0;
+ if(data) {
+ num_ref_pictures = data->codec_data->num_ref_frames;
+ }
//Adding 1 to work around VBLANK issue, and another 1 to compensate cached frame that
// will not start decoding until a new frame is received.
@@ -407,10 +497,14 @@
return ret;
}
- LOG_V( "Codec data says picture size is %d x %d\n",
- (data->pic_data[0].pic_parms->picture_width_in_mbs_minus1 + 1) * 16,
- (data->pic_data[0].pic_parms->picture_height_in_mbs_minus1 + 1) * 16);
- LOG_V( "getcaps says picture size is %d x %d\n", this->picture_width, this->picture_height);
+#ifdef MIX_LOG_ENABLE
+ if(data) {
+ LOG_V( "Codec data says picture size is %d x %d\n",
+ (data->pic_data[0].pic_parms->picture_width_in_mbs_minus1 + 1) * 16,
+ (data->pic_data[0].pic_parms->picture_height_in_mbs_minus1 + 1) * 16);
+ LOG_V( "getcaps says picture size is %d x %d\n", this->picture_width, this->picture_height);
+ }
+#endif
vret = vaCreateSurfaces(
this->va_display,
@@ -445,11 +539,13 @@
return ret;
break;
}
+#if 0 // NOTE: We don't use the value in frame manager, comment out the following lines
if (data->codec_data->pic_order_cnt_type == 0) {
int max = (int)pow(2, data->codec_data->log2_max_pic_order_cnt_lsb_minus4 + 4);
mix_framemanager_set_max_picture_number(this->framemgr, max);
}
+#endif
//Initialize and save the VA context ID
//Note: VA_PROGRESSIVE libva flag is only relevant to MPEG2
@@ -601,7 +697,7 @@
if (ret != MIX_RESULT_SUCCESS) {
LOG_E( "Error reference frame not found\n");
//Need to remove the frame we inserted in _handle_ref_frames above, since we are not going to decode it
- _cleanup_ref_frame(pic_params, this->frame);
+ _cleanup_ref_frame(pic_params, this->video_frame);
LOG_V( "End\n");
return ret;
}
@@ -1004,7 +1100,8 @@
MixBuffer * bufin,
uint64 ts,
bool discontinuity,
- MixVideoDecodeParams * decode_params) {
+ MixVideoDecodeParams * decode_params,
+ bool complete_frame) {
uint32 pret = 0;
MIX_RESULT ret = MIX_RESULT_SUCCESS;
vbp_data_h264 *data = NULL;
@@ -1017,7 +1114,7 @@
FALSE);
LOG_V( "Called parse for current frame\n");
- if ((pret != VBP_DONE) &&(pret != VBP_OK)) {
+ if (pret != VBP_OK) {
ret = MIX_RESULT_ERROR_PROCESS_STREAM; // MIX_RESULT_DROPFRAME;
LOG_E( "vbp_parse failed.\n");
LOG_V("End\n");
@@ -1108,6 +1205,16 @@
return ret;
}
}
+ if (complete_frame)
+ {
+ // finish decoding current frame
+ ret = _decode_end(FALSE);
+ if (ret != MIX_RESULT_SUCCESS)
+ {
+ LOG_V("mix_videofmt_h264_decode_end failed.\n");
+ return ret;
+ }
+ }
LOG_V("End\n");
return ret;
@@ -1115,7 +1222,6 @@
-#define HACK_DPB
#ifdef HACK_DPB
static inline MIX_RESULT mix_videofmt_h264_hack_dpb(MixVideoFormat *mix,
vbp_picture_data_h264* pic_data
diff --git a/mix_video/src/mixvideoformat_h264.h b/mix_video/src/mixvideoformat_h264.h
index ce16281..b85d6df 100644
--- a/mix_video/src/mixvideoformat_h264.h
+++ b/mix_video/src/mixvideoformat_h264.h
@@ -47,7 +47,7 @@
MIX_RESULT _update_config_params(vbp_data_h264 *data);
MIX_RESULT _initialize_va(vbp_data_h264 *data);
MIX_RESULT _decode_a_buffer(MixBuffer * bufin, uint64 ts,
- bool discontinuity, MixVideoDecodeParams * decode_params);
+ bool discontinuity, MixVideoDecodeParams * decode_params,bool complete_frame);
MIX_RESULT _decode_end(bool drop_picture);
MIX_RESULT _handle_new_sequence(vbp_data_h264 *data);
MIX_RESULT _decode_begin(vbp_data_h264 *data);
diff --git a/mix_video/src/mixvideoformat_mp42.cpp b/mix_video/src/mixvideoformat_mp42.cpp
index 8264a38..755501a 100644
--- a/mix_video/src/mixvideoformat_mp42.cpp
+++ b/mix_video/src/mixvideoformat_mp42.cpp
@@ -120,6 +120,11 @@
mix_videoconfigparamsdec_set_pixel_aspect_ratio(
this->config_params, data->codec_data.par_width, data->codec_data.par_height);
+
+ mix_videoconfigparamsdec_set_bit_rate(
+ this->config_params,
+ data->codec_data.bit_rate);
+
return MIX_RESULT_SUCCESS;
}
@@ -717,7 +722,7 @@
}
MIX_RESULT MixVideoFormat_MP42::_decode_a_buffer(
- MixBuffer * bufin, uint64 ts, bool discontinuity) {
+ MixBuffer * bufin, uint64 ts, bool discontinuity,bool complete_frame) {
uint32 pret = 0;
MIX_RESULT ret = MIX_RESULT_SUCCESS;
vbp_data_mp42 *data = NULL;
@@ -791,6 +796,16 @@
goto CLEAN_UP;
}
}
+ if (complete_frame)
+ {
+ // finish decoding current frame
+ ret = _decode_end(FALSE);
+ if (ret != MIX_RESULT_SUCCESS)
+ {
+ LOG_V("mix_videofmt_mp42_decode_end failed.\n");
+ goto CLEAN_UP;
+ }
+ }
CLEAN_UP:
LOG_V( "End\n");
@@ -964,7 +979,11 @@
for (int i = 0; i < bufincnt; i++) {
LOG_V("decode buffer %d in total %d \n", i, bufincnt);
// decode a buffer at a time
- ret = _decode_a_buffer(bufin[i], ts, discontinuity);
+ ret = _decode_a_buffer(
+ bufin[i],
+ ts,
+ discontinuity,
+ ((i == bufincnt - 1) ? decode_params->complete_frame : 0));
if (ret != MIX_RESULT_SUCCESS) {
LOG_E("mix_videofmt_mp42_decode_a_buffer failed.\n");
break;
diff --git a/mix_video/src/mixvideoformat_mp42.h b/mix_video/src/mixvideoformat_mp42.h
index e05d3be..9d00d1a 100644
--- a/mix_video/src/mixvideoformat_mp42.h
+++ b/mix_video/src/mixvideoformat_mp42.h
@@ -50,7 +50,7 @@
MIX_RESULT _decode_continue(vbp_data_mp42 *data);
MIX_RESULT _decode_begin(vbp_data_mp42* data);
MIX_RESULT _decode_a_buffer(
- MixBuffer * bufin, uint64 ts, bool discontinuity);
+ MixBuffer * bufin, uint64 ts, bool discontinuity,bool complete_frame);
public:
/*< public > */
diff --git a/mix_video/src/mixvideoformat_vc1.cpp b/mix_video/src/mixvideoformat_vc1.cpp
index 342c49d..cd672d9 100644
--- a/mix_video/src/mixvideoformat_vc1.cpp
+++ b/mix_video/src/mixvideoformat_vc1.cpp
@@ -13,13 +13,9 @@
#include <va/va_x11.h>
#endif
-#ifdef YUVDUMP
-//TODO Complete YUVDUMP code and move into base class
-#include <stdio.h>
-#endif /* YUVDUMP */
#include <string.h>
-#include <stdlib.h>
+
#ifdef MIX_LOG_ENABLE
static int mix_video_vc1_counter = 0;
@@ -32,7 +28,6 @@
}
MixVideoFormat_VC1::~MixVideoFormat_VC1() {
- int32 pret = VBP_OK;
/* clean up here. */
Lock();
//surfacepool is deallocated by parent
@@ -54,10 +49,10 @@
this->current_timestamp = (uint64)-1;
//Close the parser
- pret = vbp_close(this->parser_handle);
- this->parser_handle = NULL;
- if (pret != VBP_OK) {
- LOG_E( "Error closing parser\n");
+ if (this->parser_handle)
+ {
+ vbp_close(this->parser_handle);
+ this->parser_handle = NULL;
}
Unlock();
@@ -176,9 +171,155 @@
this->config_params,
data->se_data->ASPECT_HORIZ_SIZE,
data->se_data->ASPECT_VERT_SIZE);
+
+ mix_videoconfigparamsdec_set_bit_rate(
+ this->config_params,
+ data->se_data->bit_rate);
return MIX_RESULT_SUCCESS;
}
+MIX_RESULT MixVideoFormat_VC1::_initialize_va(vbp_data_vc1 *data) {
+ MIX_RESULT ret = MIX_RESULT_SUCCESS;
+ VAStatus vret = VA_STATUS_SUCCESS;
+ VAConfigAttrib attrib;
+ VAProfile va_profile;
+
+ LOG_V( "Begin\n");
+ if (this->va_initialized) {
+ LOG_W("va already initialized.\n");
+ return MIX_RESULT_SUCCESS;
+ }
+
+ //We are requesting RT attributes
+ attrib.type = VAConfigAttribRTFormat;
+ attrib.value = VA_RT_FORMAT_YUV420;
+
+ //Initialize and save the VA config ID
+ switch (data->se_data->PROFILE) {
+ case 0:
+ va_profile = VAProfileVC1Simple;
+ break;
+ case 1:
+ va_profile = VAProfileVC1Main;
+ break;
+
+ default:
+ va_profile = VAProfileVC1Advanced;
+ break;
+ }
+
+ vret = vaCreateConfig(
+ this->va_display,
+ va_profile,
+ VAEntrypointVLD,
+ &attrib,
+ 1,
+ &(this->va_config));
+
+ if (vret != VA_STATUS_SUCCESS) {
+ ret = MIX_RESULT_FAIL;
+ LOG_E("vaCreateConfig failed\n");
+ goto cleanup;
+ }
+
+
+ //Check for loop filtering
+ if (data->se_data->LOOPFILTER == 1)
+ this->loopFilter = TRUE;
+ else
+ this->loopFilter = FALSE;
+
+ LOG_V( "loop filter is %d, TFCNTRFLAG is %d\n", data->se_data->LOOPFILTER, data->se_data->TFCNTRFLAG);
+
+ if ((data->se_data->MAXBFRAMES > 0) || (data->se_data->PROFILE == 3) || (data->se_data->PROFILE == 1)) {
+ //If Advanced profile, have to assume B frames may be present, since MAXBFRAMES is not valid for this prof
+ this->haveBframes = TRUE;
+ }
+ else {
+ this->haveBframes = FALSE;
+ }
+
+ //Calculate VC1 numSurfaces based on max number of B frames or
+ // MIX_VIDEO_VC1_SURFACE_NUM, whichever is less
+
+ //Adding 1 to work around VBLANK issue
+ this->va_num_surfaces = 1 + this->extra_surfaces + ((3 + (this->haveBframes ? 1 : 0) <
+ MIX_VIDEO_VC1_SURFACE_NUM) ?
+ (3 + (this->haveBframes ? 1 : 0))
+ : MIX_VIDEO_VC1_SURFACE_NUM);
+
+ this->va_surfaces = new VASurfaceID[this->va_num_surfaces];
+ if (this->va_surfaces == NULL) {
+ ret = MIX_RESULT_FAIL;
+ LOG_E( "parent->va_surfaces == NULL. \n");
+ goto cleanup;
+ }
+
+ vret = vaCreateSurfaces(
+ this->va_display,
+ this->picture_width,
+ this->picture_height,
+ VA_RT_FORMAT_YUV420,
+ this->va_num_surfaces,
+ this->va_surfaces);
+
+ if (vret != VA_STATUS_SUCCESS) {
+ ret = MIX_RESULT_FAIL;
+ LOG_E( "Error allocating surfaces\n");
+ goto cleanup;
+ }
+
+ LOG_V( "Created %d libva surfaces\n", this->va_num_surfaces);
+
+ //Initialize the surface pool
+ ret = mix_surfacepool_initialize(
+ this->surfacepool,
+ this->va_surfaces,
+ this->va_num_surfaces,
+ this->va_display);
+
+ switch (ret) {
+ case MIX_RESULT_SUCCESS:
+ break;
+ case MIX_RESULT_ALREADY_INIT: //This case is for future use when we can be initialized multiple times. It is to detect when we have not been reset before re-initializing.
+ default:
+ ret = MIX_RESULT_ALREADY_INIT;
+ LOG_E( "Error init surface pool\n");
+ goto cleanup;
+ break;
+ }
+
+ //Initialize and save the VA context ID
+ //Note: VA_PROGRESSIVE libva flag is only relevant to MPEG2
+ vret = vaCreateContext(
+ this->va_display,
+ this->va_config,
+ this->picture_width,
+ this->picture_height,
+ 0,
+ this->va_surfaces,
+ this->va_num_surfaces,
+ &(this->va_context));
+
+ if (vret != VA_STATUS_SUCCESS) {
+ ret = MIX_RESULT_FAIL;
+ LOG_E( "Error initializing video driver\n");
+ goto cleanup;
+ }
+
+ LOG_V( "mix_video vinfo: Content type %s\n", (data->se_data->INTERLACE) ? "interlaced" : "progressive");
+ LOG_V( "mix_video vinfo: Content width %d, height %d\n", this->picture_width, this->picture_height);
+ LOG_V( "mix_video vinfo: MAXBFRAMES %d (note that for Advanced profile, MAXBFRAMES can be zero and there still can be B frames in the content)\n", data->se_data->MAXBFRAMES);
+ LOG_V( "mix_video vinfo: PROFILE %d, LEVEL %d\n", data->se_data->PROFILE, data->se_data->LEVEL);
+
+ this->va_initialized = TRUE;
+cleanup:
+ /* nothing to clean up */
+
+ return ret;
+
+}
+
MIX_RESULT MixVideoFormat_VC1::Initialize(
MixVideoConfigParamsDec * config_params,
MixFrameManager * frame_mgr,
@@ -191,18 +332,6 @@
enum _vbp_parser_type ptype = VBP_VC1;
vbp_data_vc1 *data = NULL;
MixIOVec *header = NULL;
- int numprofs = 0, numactualprofs = 0;
- int numentrypts = 0, numactualentrypts = 0;
- VADisplay vadisplay = NULL;
- VAProfile *profiles = NULL;
- VAEntrypoint *entrypts = NULL;
- VAConfigAttrib attrib;
- VAStatus vret = VA_STATUS_SUCCESS;
- uint extra_surfaces = 0;
- VASurfaceID *surfaces = NULL;
- uint numSurfaces = 0;
- int vaentrypt = 0;
- int vaprof = 0;
//TODO Partition this method into smaller methods
if (config_params == NULL || frame_mgr == NULL ||
@@ -223,13 +352,34 @@
//From now on, we exit this function through cleanup:
Lock();
+ this->surfacepool = mix_surfacepool_new();
+ *surface_pool = this->surfacepool;
+
+ if (this->surfacepool == NULL)
+ {
+ ret = MIX_RESULT_NO_MEMORY;
+ LOG_E( "parent->surfacepool == NULL.\n");
+ goto cleanup;
+ }
+
+ ret = mix_videoconfigparamsdec_get_extra_surface_allocation(config_params,
+ &this->extra_surfaces);
+
+ if (ret != MIX_RESULT_SUCCESS)
+ {
+ ret = MIX_RESULT_FAIL;
+ LOG_E( "Cannot get extra surface allocation setting\n");
+ goto cleanup;
+ }
+
+
//Load the bitstream parser
pret = vbp_open(ptype, &(this->parser_handle));
if (!(pret == VBP_OK)) {
ret = MIX_RESULT_FAIL;
LOG_E( "Error opening parser\n");
- goto CLEAN_UP;
+ goto cleanup;
}
LOG_V( "Opened parser\n");
@@ -238,36 +388,29 @@
&header);
if ((ret != MIX_RESULT_SUCCESS) || (header == NULL)) {
- ret = MIX_RESULT_FAIL;
- LOG_E( "Cannot get header data\n");
- goto CLEAN_UP;
- }
+ ret = MIX_RESULT_SUCCESS;
+ LOG_W( "Codec data is not available in the configuration parameter.\n");
- ret = mix_videoconfigparamsdec_get_extra_surface_allocation(config_params,
- &extra_surfaces);
-
- if (ret != MIX_RESULT_SUCCESS) {
- ret = MIX_RESULT_FAIL;
- LOG_E( "Cannot get extra surface allocation setting\n");
- goto CLEAN_UP;
+ goto cleanup;
}
LOG_V( "Calling parse on header data, handle %d\n", (int)this->parser_handle);
+ LOG_V( "mix_video vinfo: Content type %s, %s\n", (header->data_size > 8) ? "VC-1" : "WMV", (data->se_data->INTERLACE) ? "interlaced" : "progressive");
ret = _update_seq_header(config_params, header);
if (ret != MIX_RESULT_SUCCESS) {
ret = MIX_RESULT_FAIL;
LOG_E( "Error updating sequence header\n");
- goto CLEAN_UP;
+ goto cleanup;
}
pret = vbp_parse(this->parser_handle, header->data,
header->data_size, TRUE);
- if (!((pret == VBP_OK) || (pret == VBP_DONE))) {
+ if ((pret != VBP_OK)) {
ret = MIX_RESULT_FAIL;
LOG_E( "Error parsing header data, size %d\n", header->data_size);
- goto CLEAN_UP;
+ goto cleanup;
}
@@ -278,207 +421,19 @@
if ((pret != VBP_OK) || (data == NULL)) {
ret = MIX_RESULT_FAIL;
LOG_E( "Error reading parsed header data\n");
- goto CLEAN_UP;
+ goto cleanup;
}
LOG_V( "Queried parser for header data\n");
_update_config_params(data);
- //Time for libva initialization
- vadisplay = this->va_display;
- numprofs = vaMaxNumProfiles(vadisplay);
- profiles = reinterpret_cast<VAProfile*>(malloc(numprofs*sizeof(VAProfile)));
-
- if (!profiles) {
- ret = MIX_RESULT_NO_MEMORY;
- LOG_E( "Error allocating memory\n");
- goto CLEAN_UP;
+ ret = _initialize_va(data);
+ if (ret != MIX_RESULT_SUCCESS) {
+ LOG_E( "Error initializing va. \n");
+ goto cleanup;
}
- vret = vaQueryConfigProfiles(vadisplay, profiles,
- &numactualprofs);
- if (!(vret == VA_STATUS_SUCCESS)) {
- ret = MIX_RESULT_FAIL;
- LOG_E( "Error initializing video driver\n");
- goto CLEAN_UP;
- }
-
- //check the desired profile support
-
- VAProfile profile;
- switch (data->se_data->PROFILE) {
- case 0:
- profile = VAProfileVC1Simple;
- break;
- case 1:
- profile = VAProfileVC1Main;
- break;
- default:
- profile = VAProfileVC1Advanced;
- break;
- }
-
- for (; vaprof < numactualprofs; vaprof++) {
- if (profiles[vaprof] == profile)
- break;
- }
- if (vaprof >= numprofs || profiles[vaprof] != profile) {
- ret = MIX_RESULT_FAIL;
- LOG_E( "Profile not supported by driver\n");
- goto CLEAN_UP;
- }
-
- numentrypts = vaMaxNumEntrypoints(vadisplay);
- entrypts = reinterpret_cast<VAEntrypoint*>(malloc(numentrypts*sizeof(VAEntrypoint)));
-
- if (!entrypts) {
- ret = MIX_RESULT_NO_MEMORY;
- LOG_E( "Error allocating memory\n");
- goto CLEAN_UP;
- }
-
- vret = vaQueryConfigEntrypoints(vadisplay, profiles[vaprof],
- entrypts, &numactualentrypts);
-
- if (!(vret == VA_STATUS_SUCCESS)) {
- ret = MIX_RESULT_FAIL;
- LOG_E( "Error initializing driver\n");
- goto CLEAN_UP;
- }
-
- for (; vaentrypt < numactualentrypts; vaentrypt++) {
- if (entrypts[vaentrypt] == VAEntrypointVLD)
- break;
- }
- if (vaentrypt >= numentrypts || entrypts[vaentrypt] != VAEntrypointVLD) {
- ret = MIX_RESULT_FAIL;
- LOG_E( "Entry point not supported by driver\n");
- goto CLEAN_UP;
- }
-
- //We are requesting RT attributes
- attrib.type = VAConfigAttribRTFormat;
-
- vret = vaGetConfigAttributes(vadisplay, profiles[vaprof],
- entrypts[vaentrypt], &attrib, 1);
-
- //TODO Handle other values returned for RT format
- // and check with requested format provided in config params
- //Right now only YUV 4:2:0 is supported by libva
- // and this is our default
- if (((attrib.value & VA_RT_FORMAT_YUV420) == 0) || vret != VA_STATUS_SUCCESS) {
- ret = MIX_RESULT_FAIL;
- LOG_E( "Error initializing driver\n");
- goto CLEAN_UP;
- }
-
- //Initialize and save the VA config ID
- vret = vaCreateConfig(vadisplay, profiles[vaprof],
- entrypts[vaentrypt], &attrib, 1, &(this->va_config));
-
- if (!(vret == VA_STATUS_SUCCESS)) {
- ret = MIX_RESULT_FAIL;
- LOG_E( "Error initializing driver\n");
- goto CLEAN_UP;
- }
-
- LOG_V( "Created libva config with profile %d\n", vaprof);
-
- //Check for loop filtering
- if (data->se_data->LOOPFILTER == 1)
- this->loopFilter = TRUE;
- else
- this->loopFilter = FALSE;
-
- LOG_V( "loop filter is %d, TFCNTRFLAG is %d\n",
- data->se_data->LOOPFILTER, data->se_data->TFCNTRFLAG);
-
- //Initialize the surface pool
- if ((data->se_data->MAXBFRAMES > 0) ||
- (data->se_data->PROFILE == 3) ||
- (data->se_data->PROFILE == 1))
- //If Advanced profile, have to assume B frames may be present, since MAXBFRAMES is not valid for this prof
- this->haveBframes = TRUE;
- else
- this->haveBframes = FALSE;
-
- //Calculate VC1 numSurfaces based on max number of B frames or
- // MIX_VIDEO_VC1_SURFACE_NUM, whichever is less
-
- //Adding 1 to work around VBLANK issue
- this->va_num_surfaces = 1 + extra_surfaces +
- ((3 + (this->haveBframes ? 1 : 0) < MIX_VIDEO_VC1_SURFACE_NUM) ?
- (3 + (this->haveBframes ? 1 : 0)) : MIX_VIDEO_VC1_SURFACE_NUM);
- numSurfaces = this->va_num_surfaces;
- this->va_surfaces = reinterpret_cast<VASurfaceID*>(malloc(sizeof(VASurfaceID)*numSurfaces));
- surfaces = this->va_surfaces;
-
- if (surfaces == NULL) {
- ret = MIX_RESULT_FAIL;
- LOG_E( "Cannot allocate temporary data\n");
- goto CLEAN_UP;
- }
-
- vret = vaCreateSurfaces(
- vadisplay, this->picture_width,
- this->picture_height, entrypts[vaentrypt],
- numSurfaces, surfaces);
- if (!(vret == VA_STATUS_SUCCESS)) {
- ret = MIX_RESULT_FAIL;
- LOG_E( "Error allocating surfaces\n");
- goto CLEAN_UP;
- }
-
- this->surfacepool = mix_surfacepool_new();
- *surface_pool = this->surfacepool;
- if (this->surfacepool == NULL) {
- ret = MIX_RESULT_FAIL;
- LOG_E( "Error initializing surface pool\n");
- goto CLEAN_UP;
- }
-
-
- ret = mix_surfacepool_initialize(this->surfacepool,
- surfaces, numSurfaces, vadisplay);
-
- switch (ret) {
- case MIX_RESULT_SUCCESS:
- break;
- case MIX_RESULT_ALREADY_INIT:
- default:
- ret = MIX_RESULT_ALREADY_INIT;
- LOG_E( "Error init failure\n");
- goto CLEAN_UP;
- break;
- }
-
- LOG_V( "Created %d libva surfaces, MAXBFRAMES is %d\n",
- numSurfaces, data->se_data->MAXBFRAMES);
-
- //Initialize and save the VA context ID
- //Note: VA_PROGRESSIVE libva flag is only relevant to MPEG2
- vret = vaCreateContext(vadisplay, this->va_config,
- this->picture_width, this->picture_height,
- 0, surfaces, numSurfaces,
- &(this->va_context));
- if (!(vret == VA_STATUS_SUCCESS)) {
- ret = MIX_RESULT_FAIL;
- LOG_E( "Error initializing video driver\n");
- goto CLEAN_UP;
- }
-
- LOG_V( "Created libva context width %d, height %d\n",
- this->picture_width, this->picture_height);
- LOG_V( "mix_video vinfo: Content type %s, %s\n",
- (header->data_size > 8) ? "VC-1" : "WMV", (data->se_data->INTERLACE) ? "interlaced" : "progressive");
- LOG_V( "mix_video vinfo: Content width %d, height %d\n",
- this->picture_width, this->picture_height);
- LOG_V( "mix_video vinfo: MAXBFRAMES %d (note that for Advanced profile, MAXBFRAMES can be zero and there still can be B frames in the content)\n",
- data->se_data->MAXBFRAMES);
- LOG_V( "mix_video vinfo: PROFILE %d, LEVEL %d\n",
- data->se_data->PROFILE, data->se_data->LEVEL);
-
-CLEAN_UP:
+cleanup:
if (ret != MIX_RESULT_SUCCESS) {
pret = vbp_close(this->parser_handle);
this->parser_handle = NULL;
@@ -486,14 +441,14 @@
} else {
this->initialized = TRUE;
}
+
if (header != NULL) {
if (header->data != NULL)
- free(header->data);
- free(header);
+ delete[](header->data);
+ delete(header);
header = NULL;
}
- free(profiles);
- free(entrypts);
+
this->lastFrame = NULL;
LOG_V( "Unlocking\n");
Unlock();
@@ -511,7 +466,6 @@
uint64 ts = 0;
vbp_data_vc1 *data = NULL;
bool discontinuity = FALSE;
- MixInputBufferEntry *bufentry = NULL;
if (bufin == NULL || decode_params == NULL) {
LOG_E( "NUll pointer passed in\n");
return MIX_RESULT_NULL_PTR;
@@ -542,29 +496,6 @@
LOG_V( "Locking\n");
Lock();
- //If this is a new frame and we haven't retrieved parser
- // workload data from previous frame yet, do so
- if ((ts != this->current_timestamp) &&
- (this->parse_in_progress)) {
- //query for data
- pret = vbp_query(this->parser_handle, (void **) &data);
- if ((pret != VBP_OK) || (data == NULL)) {
- ret = MIX_RESULT_FAIL;
- LOG_E( "Error initializing parser\n");
- goto CLEAN_UP;
- }
- LOG_V( "Queried for last frame data\n");
- //process and decode data
- ret = _process_decode(data, this->current_timestamp, this->discontinuity_frame_in_progress);
-
- if (ret != MIX_RESULT_SUCCESS) {
- //We log this but need to process the new frame data, so do not return
- LOG_E( "process_decode failed.\n");
- }
- LOG_V( "Called process and decode for last frame\n");
- this->parse_in_progress = FALSE;
- }
-
this->current_timestamp = ts;
this->discontinuity_frame_in_progress = discontinuity;
LOG_V( "Starting current frame %d, timestamp %"UINT64_FORMAT"\n", mix_video_vc1_counter++, ts);
@@ -574,74 +505,42 @@
(int)this->parser_handle, (uint)bufin[i]->data, bufin[i]->size);
pret = vbp_parse(this->parser_handle, bufin[i]->data, bufin[i]->size, FALSE);
LOG_V( "Called parse for current frame\n");
- if (pret == VBP_DONE) {
- //query for data
- pret = vbp_query(this->parser_handle, (void **) &data);
- if ((pret != VBP_OK) || (data == NULL)) {
- ret = MIX_RESULT_FAIL;
- LOG_E( "Error getting parser data\n");
- goto CLEAN_UP;
- }
- LOG_V( "Called query for current frame\n");
- //Increase the ref count of this input buffer
- mix_buffer_ref(bufin[i]);
- //Create a new MixInputBufferEntry
- //TODO make this from a pool to optimize
- bufentry = reinterpret_cast<MixInputBufferEntry*>(malloc(sizeof(
- MixInputBufferEntry)));
- if (bufentry == NULL) {
- ret = MIX_RESULT_NO_MEMORY;
- LOG_E( "Error allocating bufentry\n");
- goto CLEAN_UP;
- }
-
- bufentry->buf = bufin[i];
- LOG_V( "Setting bufentry %x for mixbuffer %x ts to %"UINT64_FORMAT"\n",
- (uint)bufentry, (uint)bufentry->buf, ts);
- bufentry->timestamp = ts;
-
- LOG_V( "Enqueue this input buffer for current frame\n");
- LOG_V( "bufentry->timestamp %"UINT64_FORMAT"\n", bufentry->timestamp);
-
- //Enqueue this input buffer
- j_queue_push_tail(this->inputbufqueue,
- (void*)bufentry);
-
- //process and decode data
- ret = _process_decode(data, ts, discontinuity);
-
- if (ret != MIX_RESULT_SUCCESS) {
- //We log this but continue since we need to complete our processing of input buffers
- LOG_E( "Process_decode failed.\n");
- }
-
- LOG_V( "Called process and decode for current frame\n");
- this->parse_in_progress = FALSE;
- } else if (pret != VBP_OK) {
- //We log this but continue since we need to complete our processing of input buffers
- LOG_E( "Parsing failed.\n");
+ if (pret != VBP_OK) {
ret = MIX_RESULT_FAIL;
- } else {
- LOG_V( "Enqueuing buffer and going on to next (if any) for this frame\n");
- //Increase the ref count of this input buffer
- mix_buffer_ref(bufin[i]);
- //Create a new MixInputBufferEntry
- //TODO make this from a pool to optimize
- bufentry = reinterpret_cast<MixInputBufferEntry*>(malloc(sizeof(MixInputBufferEntry)));
- if (bufentry == NULL) {
- ret = MIX_RESULT_NO_MEMORY;
- LOG_E( "Error allocating bufentry\n");
+ LOG_E( "Error parsing data\n");
+ goto CLEAN_UP;
+ }
+ //query for data
+ pret = vbp_query(this->parser_handle, (void **) &data);
+ if ((pret != VBP_OK) || (data == NULL)) {
+ ret = MIX_RESULT_FAIL;
+ LOG_E( "Error getting parser data\n");
+ goto CLEAN_UP;
+ }
+ if (this->va_initialized == FALSE) {
+ _update_config_params(data);
+
+ LOG_V("try initializing VA...\n");
+ ret = _initialize_va(data);
+ if (ret != MIX_RESULT_SUCCESS) {
+ LOG_V("mix_videofmt_vc1_initialize_va failed.\n");
goto CLEAN_UP;
}
- bufentry->buf = bufin[i];
- bufentry->timestamp = ts;
-
- //Enqueue this input buffer
- j_queue_push_tail(this->inputbufqueue,
- (void*)bufentry);
- this->parse_in_progress = TRUE;
}
+
+ LOG_V( "Called query for current frame\n");
+
+ //process and decode data
+ ret = _process_decode(data, ts, discontinuity);
+ if (ret != MIX_RESULT_SUCCESS)
+ {
+ //We log this but continue since we need to complete our processing of input buffers
+ LOG_E( "Process_decode failed.\n");
+ goto CLEAN_UP;
+ }
+
}
+
CLEAN_UP:
LOG_V( "Unlocking\n");
Unlock();
@@ -650,81 +549,6 @@
}
-#ifdef YUVDUMP
-//TODO Complete this YUVDUMP code and move into base class
-MIX_RESULT MixVideoFormat_VC1::_get_Img_from_surface (MixVideoFrame * frame) {
- VAStatus vaStatus = VA_STATUS_SUCCESS;
- VAImageFormat va_image_format;
- VAImage va_image;
- unsigned char* pBuffer;
- unsigned int ui32SrcWidth = this->picture_width;
- unsigned int ui32SrcHeight = this->picture_height;
- unsigned int ui32Stride;
- unsigned int ui32ChromaOffset;
- FILE *fp = NULL;
- int r = 0;
- int i;
- g_print ("_get_Img_from_surface \n");
-
- if (NULL == frame) {
- LOG_E( "Null pointer passed in\n");
- return MIX_RESULT_NULL_PTR;
- }
- fp = fopen("yuvdump.yuv", "a+");
-
- static int have_va_image = 0;
-
- if (!have_va_image) {
- va_image_format.fourcc = VA_FOURCC_NV12;
- //va_image_format.fourcc = VA_FOURCC_YV12;
- vaStatus = vaCreateImage(
- this->va_display, &va_image_format,
- ui32SrcWidth, ui32SrcHeight, &va_image);
- have_va_image = 1;
- }
-
- vaStatus = vaGetImage(
- this->va_display, frame->frame_id, 0, 0,
- ui32SrcWidth, ui32SrcHeight, va_image.image_id );
- vaStatus = vaMapBuffer(this->va_display, va_image.buf, (void **) &pBuffer);
- ui32ChromaOffset = va_image.offsets[1];
- ui32Stride = va_image.pitches[0];
-
- if (VA_STATUS_SUCCESS != vaStatus) {
- g_print ("VideoProcessBlt: Unable to copy surface\n\r");
- return vaStatus;
- }
-
- {
- g_print ("before copy memory....\n");
- g_print ("width = %d, height = %d\n", ui32SrcWidth, ui32SrcHeight);
- g_print ("data_size = %d\n", va_image.data_size);
- g_print ("num_planes = %d\n", va_image.num_planes);
- g_print ("va_image.pitches[0] = %d\n", va_image.pitches[0]);
- g_print ("va_image.pitches[1] = %d\n", va_image.pitches[1]);
- g_print ("va_image.pitches[2] = %d\n", va_image.pitches[2]);
- g_print ("va_image.offsets[0] = %d\n", va_image.offsets[0]);
- g_print ("va_image.offsets[1] = %d\n", va_image.offsets[1]);
- g_print ("va_image.offsets[2] = %d\n", va_image.offsets[2]);
- // r = fwrite (pBuffer, 1, va_image.offsets[1], fp);
-
- r = fwrite (pBuffer, va_image.offsets[1], 1, fp);
-
- for (i = 0; i < ui32SrcWidth * ui32SrcHeight / 2; i +=2)
- r = fwrite (pBuffer + va_image.offsets[1] + i / 2, 1, 1, fp);
-
- for (i = 0; i < ui32SrcWidth * ui32SrcHeight / 2; i +=2)
- r = fwrite (pBuffer + va_image.offsets[1] + i / 2 + 1, 1, 1, fp);
-
- g_print ("ui32ChromaOffset = %d, ui32Stride = %d\n", ui32ChromaOffset, ui32Stride);
-
- }
-
- vaStatus = vaUnmapBuffer(this->va_display, va_image.buf);
- return vaStatus;
-}
-#endif /* YUVDUMP */
-
MIX_RESULT MixVideoFormat_VC1::_decode_a_picture(
vbp_data_vc1 *data, int pic_index, MixVideoFrame *frame) {
MIX_RESULT ret = MIX_RESULT_SUCCESS;
@@ -792,7 +616,8 @@
case VC1_PTYPE_BI: // BI frame type
ret = mix_videoframe_set_frame_type(frame, TYPE_B);
break;
- //Not indicated here case VC1_PTYPE_SKIPPED:
+ //Not indicated here
+ case VC1_PTYPE_SKIPPED:
default:
break;
}
@@ -913,6 +738,17 @@
//Libva buffer set up
vadisplay = this->va_display;
vacontext = this->va_context;
+ LOG_V( "Calling vaBeginPicture\n");
+
+ //Now we can begin the picture
+ vret = vaBeginPicture(vadisplay, vacontext, surface);
+
+ if (vret != VA_STATUS_SUCCESS)
+ {
+ ret = MIX_RESULT_FAIL;
+ LOG_E( "Video driver returned error from vaBeginPicture\n");
+ goto CLEAN_UP;
+ }
LOG_V( "Creating libva picture parameter buffer\n");
@@ -1003,18 +839,6 @@
}
}
-
- LOG_V( "Calling vaBeginPicture\n");
-
- //Now we can begin the picture
- vret = vaBeginPicture(vadisplay, vacontext, surface);
-
- if (vret != VA_STATUS_SUCCESS) {
- ret = MIX_RESULT_FAIL;
- LOG_E( "Video driver returned error from vaBeginPicture\n");
- goto CLEAN_UP;
- }
-
LOG_V( "Calling vaRenderPicture\n");
//Render the picture
@@ -1065,7 +889,6 @@
MIX_RESULT ret = MIX_RESULT_SUCCESS;
LOG_V( "Begin\n");
uint32 pret = 0;
- MixInputBufferEntry *bufentry = NULL;
/* Chainup parent method.
We are not chaining up to parent method for now.
*/
@@ -1078,16 +901,7 @@
Lock();
//Clear the contents of inputbufqueue
- while (!j_queue_is_empty(this->inputbufqueue)) {
- bufentry = (MixInputBufferEntry *) j_queue_pop_head(this->inputbufqueue);
- if (bufentry == NULL)
- continue;
- mix_buffer_unref(bufentry->buf);
- free(bufentry);
- }
- //Clear parse_in_progress flag and current timestamp
- this->parse_in_progress = FALSE;
this->discontinuity_frame_in_progress = FALSE;
this->current_timestamp = (uint64)-1;
@@ -1111,8 +925,7 @@
MIX_RESULT MixVideoFormat_VC1::EndOfStream() {
MIX_RESULT ret = MIX_RESULT_SUCCESS;
- vbp_data_vc1 *data = NULL;
- uint32 pret = 0;
+
LOG_V( "Begin\n");
/* Chainup parent method.
We are not chaining up to parent method for now.
@@ -1123,27 +936,8 @@
return parent_class->eos(mix, msg);
}
#endif
- Lock();
- //if a frame is in progress, process the frame
- if (this->parse_in_progress) {
- //query for data
- pret = vbp_query(this->parser_handle, (void **) &data);
- if ((pret != VBP_OK) || (data == NULL)) {
- ret = MIX_RESULT_FAIL;
- LOG_E( "Error getting last parse data\n");
- goto CLEAN_UP;
- }
- //process and decode data
- ret = _process_decode(data, this->current_timestamp, this->discontinuity_frame_in_progress);
- this->parse_in_progress = FALSE;
- if (ret != MIX_RESULT_SUCCESS) {
- LOG_E( "Error processing last frame\n");
- goto CLEAN_UP;
- }
- }
-CLEAN_UP:
- Unlock();
+ //Call Frame Manager with _eos()
ret = mix_framemanager_eos(this->framemgr);
LOG_V( "End\n");
return ret;
@@ -1306,12 +1100,6 @@
_handle_ref_frames(frame_type, frame);
}
-//TODO Complete YUVDUMP code and move into base class
-#ifdef YUVDUMP
- if (mix_video_vc1_counter < 10)
- ret = _get_Img_from_surface(frame);
- //g_usleep(5000000);
-#endif /* YUVDUMP */
LOG_V( "Enqueueing the frame with frame manager, timestamp %"UINT64_FORMAT"\n", timestamp);
@@ -1325,7 +1113,7 @@
unrefVideoFrame = FALSE;
CLEAN_UP:
- _release_input_buffers(timestamp);
+
if (unrefVideoFrame)
mix_videoframe_unref(frame);
LOG_V( "End\n");
@@ -1333,32 +1121,11 @@
}
MIX_RESULT MixVideoFormat_VC1::_release_input_buffers(uint64 timestamp) {
- MixInputBufferEntry *bufentry = NULL;
- bool done = FALSE;
+
LOG_V( "Begin\n");
- //Dequeue and release all input buffers for this frame
- LOG_V( "Releasing all the MixBuffers for this frame\n");
- //While the head of the queue has timestamp == current ts
- //dequeue the entry, unref the MixBuffer, and free the struct
- done = FALSE;
- while (!done) {
- bufentry = (MixInputBufferEntry *) j_queue_peek_head(this->inputbufqueue);
- if (bufentry == NULL)
- break;
- LOG_V( "head of queue buf %x, timestamp %"UINT64_FORMAT", buffer timestamp %"UINT64_FORMAT"\n",
- (uint)bufentry->buf, timestamp, bufentry->timestamp);
- if (bufentry->timestamp != timestamp) {
- LOG_V( "buf %x, timestamp %"UINT64_FORMAT", buffer timestamp %"UINT64_FORMAT"\n",
- (uint)bufentry->buf, timestamp, bufentry->timestamp);
- done = TRUE;
- break;
- }
- bufentry = (MixInputBufferEntry *) j_queue_pop_head(this->inputbufqueue);
- LOG_V( "Unref this MixBuffers %x\n", (uint)bufentry->buf);
- mix_buffer_unref(bufentry->buf);
- free(bufentry);
- }
+ // Nothing to release. Deprecated.
+
LOG_V( "End\n");
return MIX_RESULT_SUCCESS;
}
diff --git a/mix_video/src/mixvideoformat_vc1.h b/mix_video/src/mixvideoformat_vc1.h
index 8ec0eea..80659f3 100644
--- a/mix_video/src/mixvideoformat_vc1.h
+++ b/mix_video/src/mixvideoformat_vc1.h
@@ -50,6 +50,7 @@
MIX_RESULT _update_config_params(vbp_data_vc1 *data);
MIX_RESULT _decode_a_picture(
vbp_data_vc1 *data, int pic_index, MixVideoFrame *frame);
+ MIX_RESULT _initialize_va(vbp_data_vc1 *data);
#ifdef YUVDUMP
MIX_RESULT _get_Img_from_surface (MixVideoFrame * frame);
#endif