blob: 7603cd7b095d84cc29d64f392d645b41d478b05f [file] [log] [blame]
#include "viddec_mp4_shortheader.h"
#ifdef ANDROID
#include "viddec_types.h"
#endif
typedef struct
{
uint16_t vop_width;
uint16_t vop_height;
uint16_t num_macroblocks_in_gob;
uint16_t num_gobs_in_vop;
uint8_t num_rows_in_gob;
} svh_src_fmt_params_t;
const svh_src_fmt_params_t svh_src_fmt_defaults[5] =
{
{128, 96, 8, 6, 1},
{176, 144, 11, 9, 1},
{352, 288, 22, 18, 1},
{704, 576, 88, 18, 2},
{1408, 1152, 352, 18, 4},
};
mp4_Status_t mp4_Parse_VideoObjectPlane_svh(void *parent, viddec_mp4_parser_t *parser)
{
mp4_Status_t ret = MP4_STATUS_OK;
unsigned int data;
mp4_VideoObjectPlaneH263 *svh = &(parser->info.VisualObject.VideoObject.VideoObjectPlaneH263);
int32_t getbits = 0;
uint8_t pei = 0;
do
{
//temporal reference
getbits = viddec_pm_get_bits(parent, &data, 8);
BREAK_GETBITS_REQD_MISSING(getbits, ret);
svh->temporal_reference = (data & 0xff);
//marker bit
getbits = viddec_pm_get_bits(parent, &data, 1);
BREAK_GETBITS_REQD_MISSING(getbits, ret);
if( 1 != (data & 0x1))
{
ret = MP4_STATUS_NOTSUPPORT;
break;
}
//zero bit
getbits = viddec_pm_get_bits(parent, &data, 1);
BREAK_GETBITS_REQD_MISSING(getbits, ret);
if( 0 != (data & 0x1))
{
ret = MP4_STATUS_NOTSUPPORT;
break;
}
//split_screen_indicator, document_camera_indicator, full_picture_freeze_release
getbits = viddec_pm_get_bits(parent, &data, 3);
BREAK_GETBITS_REQD_MISSING(getbits, ret);
//source format
getbits = viddec_pm_get_bits(parent, &data, 3);
BREAK_GETBITS_REQD_MISSING(getbits, ret);
svh->source_format = (data & 0x7);
if (svh->source_format == 0 || svh->source_format == 6)
{
DEB("Error: Bad value for VideoPlaneWithShortHeader.source_format\n");
ret = MP4_STATUS_NOTSUPPORT;
break;
}
if(svh->source_format != 7)
{
//picture coding type
getbits = viddec_pm_get_bits(parent, &data, 1);
BREAK_GETBITS_REQD_MISSING(getbits, ret);
svh->picture_coding_type = (data & 0x1);
//reserved zero bits
getbits = viddec_pm_get_bits(parent, &data, 4);
BREAK_GETBITS_REQD_MISSING(getbits, ret);
if( 0 != (data & 0xf))
{
ret = MP4_STATUS_NOTSUPPORT;
break;
}
//vop quant
getbits = viddec_pm_get_bits(parent, &data, 5);
BREAK_GETBITS_REQD_MISSING(getbits, ret);
svh->vop_quant = (data & 0x1f);
//zero bit
getbits = viddec_pm_get_bits(parent, &data, 1);
BREAK_GETBITS_REQD_MISSING(getbits, ret);
if( 0 != (data & 0x1))
{
ret = MP4_STATUS_NOTSUPPORT;
break;
}
}
else //extended PTYPE (PLUSPTYPE)
{
//ufep
getbits = viddec_pm_get_bits(parent, &data, 3);
BREAK_GETBITS_REQD_MISSING(getbits, ret);
svh->ufep = (data & 0x7); //ufep
if(svh->ufep == 0x0)
{
DEB("Info: don't support to handle the 0x000 case of Update Full Extended PTYPE\n");
ret = MP4_STATUS_NOTSUPPORT;
break;
}
else if (svh->ufep == 0x1)
{
//source format
getbits = viddec_pm_get_bits(parent, &data, 3);
BREAK_GETBITS_REQD_MISSING(getbits, ret);
svh->source_format = (data & 0x7);
if(svh->source_format < 1 || svh->source_format > 6)
{
DEB("Error: bad value of source_format\n");
ret = MP4_STATUS_PARSE_ERROR;
break;
}
//optional indicators
getbits = viddec_pm_get_bits(parent, &data, 8);
BREAK_GETBITS_REQD_MISSING(getbits, ret);
if( 0 != (data & 0xff))
{
ret = MP4_STATUS_PARSE_ERROR;
break;
}
//reserved zero bits
getbits = viddec_pm_get_bits(parent, &data, 3);
BREAK_GETBITS_REQD_MISSING(getbits, ret);
if( 0 != (data & 0x7))
{
ret = MP4_STATUS_PARSE_ERROR;
break;
}
//marker bit
getbits = viddec_pm_get_bits(parent, &data, 1);
BREAK_GETBITS_REQD_MISSING(getbits, ret);
if( 1 != (data & 0x1))
{
ret = MP4_STATUS_PARSE_ERROR;
break;
}
//reserved zero bits
getbits = viddec_pm_get_bits(parent, &data, 3);
BREAK_GETBITS_REQD_MISSING(getbits, ret);
if( 0 != (data & 0x7))
{
ret = MP4_STATUS_PARSE_ERROR;
break;
}
}
else
{
DEB("Info: don't support to handle the other case of Update Full Extended PTYPE\n");
ret = MP4_STATUS_NOTSUPPORT;
break;
}
//MPPTYPE
//picture coding type
getbits = viddec_pm_get_bits(parent, &data, 3);
BREAK_GETBITS_REQD_MISSING(getbits, ret);
svh->picture_coding_type = (data & 0x7);
if(svh->picture_coding_type > 1)
{
DEB("Info: only support I and P frames\n");
ret = MP4_STATUS_NOTSUPPORT;
break;
}
//optional RPR mode
getbits = viddec_pm_get_bits(parent, &data, 1);
BREAK_GETBITS_REQD_MISSING(getbits, ret);
if( 0 != (data & 0x1))
{
ret = MP4_STATUS_PARSE_ERROR;
break;
}
//optional PRU mode
getbits = viddec_pm_get_bits(parent, &data, 1);
BREAK_GETBITS_REQD_MISSING(getbits, ret);
if( 0 != (data & 0x1))
{
ret = MP4_STATUS_PARSE_ERROR;
break;
}
//vop rounding type
getbits = viddec_pm_get_bits(parent, &data, 1);
BREAK_GETBITS_REQD_MISSING(getbits, ret);
svh->vop_rounding_type = (data & 0x1);
//reserved zero bits
getbits = viddec_pm_get_bits(parent, &data, 2);
BREAK_GETBITS_REQD_MISSING(getbits, ret);
if( 0 != (data & 0x3))
{
ret = MP4_STATUS_PARSE_ERROR;
break;
}
//marker bit
getbits = viddec_pm_get_bits(parent, &data, 1);
BREAK_GETBITS_REQD_MISSING(getbits, ret);
if( 1 != (data & 0x1))
{
ret = MP4_STATUS_PARSE_ERROR;
break;
}
//cpm
getbits = viddec_pm_get_bits(parent, &data, 1);
BREAK_GETBITS_REQD_MISSING(getbits, ret);
if(svh->ufep == 1 && svh->source_format == 6)
{ //CPFMT
getbits = viddec_pm_get_bits(parent, &data, 4);
BREAK_GETBITS_REQD_MISSING(getbits, ret);
svh->pixel_aspect_ratio_code = (data & 0xf);
//
getbits = viddec_pm_get_bits(parent, &data, 9);
BREAK_GETBITS_REQD_MISSING(getbits, ret);
svh->picture_width_indication = (data & 0x1ff);
//marker bit
getbits = viddec_pm_get_bits(parent, &data, 1);
BREAK_GETBITS_REQD_MISSING(getbits, ret);
if( 1 != (data & 0x1))
{
ret = MP4_STATUS_PARSE_ERROR;
break;
}
//
getbits = viddec_pm_get_bits(parent, &data, 9);
BREAK_GETBITS_REQD_MISSING(getbits, ret);
svh->picture_height_indication = (data & 0x1ff);
}
viddec_pm_get_bits(parent, &data, 5);
BREAK_GETBITS_REQD_MISSING(getbits, ret);
svh->vop_quant = (data & 0x1f);
}
//PEI
do
{
getbits = viddec_pm_get_bits(parent, &data, 1); // pei
BREAK_GETBITS_FAIL(getbits, ret);
pei = (data & 0x1);
if(0 != pei)
{
getbits = viddec_pm_get_bits(parent, &data, 8); // psupp
BREAK_GETBITS_FAIL(getbits, ret);
}
}while( 1 == pei);
// Anything after this needs to be fed to the decoder as PIXEL_ES
} while(0);
return ret;
}
mp4_Status_t mp4_Parse_VideoObject_svh(void *parent, viddec_mp4_parser_t *parser)
{
mp4_Status_t ret=MP4_STATUS_OK;
mp4_Info_t *pInfo = &(parser->info);
mp4_VideoSignalType_t *vst = &(pInfo->VisualObject.VideoSignalType);
mp4_VideoObjectLayer_t *vol = &(pInfo->VisualObject.VideoObject);
mp4_VideoObjectPlane_t *vop = &(pInfo->VisualObject.VideoObject.VideoObjectPlane);
mp4_VideoObjectPlaneH263 *svh = &(pInfo->VisualObject.VideoObject.VideoObjectPlaneH263);
uint8_t index = 0;
uint8_t k = 0;
ret = mp4_Parse_VideoObjectPlane_svh(parent, parser);
if(ret == MP4_STATUS_OK)
{
// Populate defaults for the svh
vol->short_video_header = 1;
vol->video_object_layer_shape = MP4_SHAPE_TYPE_RECTANGULAR;
vol->obmc_disable = 1;
vol->quant_type = 0;
vol->resync_marker_disable = 1;
vol->data_partitioned = 0;
vol->reversible_vlc = 0;
vol->interlaced = 0;
vol->complexity_estimation_disable = 1;
vol->scalability = 0;
vol->not_8_bit = 0;
vol->bits_per_pixel = 8;
vol->quant_precision = 5;
vol->vop_time_increment_resolution = 30000;
vol->fixed_vop_time_increment = 1001;
vol->aspect_ratio_info = MP4_ASPECT_RATIO_12_11;
vop->vop_rounding_type = svh->vop_rounding_type;
vop->vop_fcode_forward = 1;
vop->vop_coded = 1;
vop->vop_coding_type = svh->picture_coding_type ? MP4_VOP_TYPE_P: MP4_VOP_TYPE_I;
vop->vop_quant = svh->vop_quant;
vst->colour_primaries = 1;
vst->transfer_characteristics = 1;
vst->matrix_coefficients = 6;
if(svh->source_format >= 1 && svh->source_format <= 5)
{
index = svh->source_format - 1;
vol->video_object_layer_width = svh_src_fmt_defaults[index].vop_width;
vol->video_object_layer_height = svh_src_fmt_defaults[index].vop_height;
svh->num_macroblocks_in_gob = svh_src_fmt_defaults[index].num_macroblocks_in_gob;
svh->num_gobs_in_vop = svh_src_fmt_defaults[index].num_gobs_in_vop;
svh->num_rows_in_gob = svh_src_fmt_defaults[index].num_rows_in_gob;
}
else if(svh->source_format == 6) //custom format
{
vol->video_object_layer_width = (svh->picture_width_indication + 1)*4;
vol->video_object_layer_height = (svh->picture_height_indication)*4;
if(vol->video_object_layer_height < 404)
{
k = 1;
}
else if (vol->video_object_layer_height < 804)
{
k = 2;
}
else
{
k = 4;
}
svh->num_macroblocks_in_gob = (vol->video_object_layer_width/16)*k;
svh->num_gobs_in_vop = (vol->video_object_layer_height)/(16*k);
svh->num_rows_in_gob = k;
}
else
{
DEB("Error: Bad value for VideoPlaneWithShortHeader.source_format\n");
ret = MP4_STATUS_NOTSUPPORT;
return ret;
}
}
mp4_set_hdr_bitstream_error(parser, false, ret);
// POPULATE WORKLOAD ITEM
{
viddec_workload_item_t wi;
wi.vwi_type = VIDDEC_WORKLOAD_MPEG4_VIDEO_PLANE_SHORT;
wi.mp4_vpsh.info = 0;
wi.mp4_vpsh.pad1 = 0;
wi.mp4_vpsh.pad2 = 0;
viddec_fw_mp4_vpsh_set_source_format(&wi.mp4_vpsh, svh->source_format);
ret = viddec_pm_append_workitem(parent, &wi, false);
if(ret == 1)
ret = MP4_STATUS_OK;
}
return ret;
}