blob: 2ebf38609b14967def5165ba0ab4a6bf1064d6ac [file] [log] [blame]
/******************************************************************************
*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*****************************************************************************
* Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
*/
/*****************************************************************************/
/* */
/* File Name : ih264d_api.c */
/* */
/* Description : Has all API related functions */
/* */
/* */
/* List of Functions : api_check_struct_sanity */
/* ih264d_set_processor */
/* ih264d_create */
/* ih264d_delete */
/* ih264d_init */
/* ih264d_map_error */
/* ih264d_video_decode */
/* ih264d_get_version */
/* ih264d_get_display_frame */
/* ih264d_set_display_frame */
/* ih264d_set_flush_mode */
/* ih264d_get_status */
/* ih264d_get_buf_info */
/* ih264d_set_params */
/* ih264d_set_default_params */
/* ih264d_reset */
/* ih264d_ctl */
/* ih264d_rel_display_frame */
/* ih264d_set_degrade */
/* ih264d_get_frame_dimensions */
/* ih264d_set_num_cores */
/* ih264d_fill_output_struct_from_context */
/* ih264d_api_function */
/* */
/* Issues / Problems : None */
/* */
/* Revision History : */
/* */
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
/* 14 10 2008 100356(SKV) Draft */
/* */
/*****************************************************************************/
#include "ih264_typedefs.h"
#include "ih264_macros.h"
#include "ih264_platform_macros.h"
#include "ih264d_tables.h"
#include "iv.h"
#include "ivd.h"
#include "ih264d.h"
#include "ih264d_defs.h"
#include <string.h>
#include <limits.h>
#include <stddef.h>
#include "ih264d_inter_pred.h"
#include "ih264d_structs.h"
#include "ih264d_nal.h"
#include "ih264d_error_handler.h"
#include "ih264d_defs.h"
#include "ithread.h"
#include "ih264d_parse_slice.h"
#include "ih264d_function_selector.h"
#include "ih264_error.h"
#include "ih264_disp_mgr.h"
#include "ih264_buf_mgr.h"
#include "ih264d_deblocking.h"
#include "ih264d_parse_cavlc.h"
#include "ih264d_parse_cabac.h"
#include "ih264d_utils.h"
#include "ih264d_format_conv.h"
#include "ih264d_parse_headers.h"
#include "ih264d_thread_compute_bs.h"
#include <assert.h>
/*********************/
/* Codec Versioning */
/*********************/
//Move this to where it is used
#define CODEC_NAME "H264VDEC"
#define CODEC_RELEASE_TYPE "production"
#define CODEC_RELEASE_VER "05.00"
#define CODEC_VENDOR "ITTIAM"
#define MAXVERSION_STRLEN 511
#ifdef __ANDROID__
#define VERSION(version_string, codec_name, codec_release_type, codec_release_ver, codec_vendor) \
snprintf(version_string, MAXVERSION_STRLEN, \
"@(#)Id:%s_%s Ver:%s Released by %s", \
codec_name, codec_release_type, codec_release_ver, codec_vendor)
#else
#define VERSION(version_string, codec_name, codec_release_type, codec_release_ver, codec_vendor) \
snprintf(version_string, MAXVERSION_STRLEN, \
"@(#)Id:%s_%s Ver:%s Released by %s Build: %s @ %s", \
codec_name, codec_release_type, codec_release_ver, codec_vendor, __DATE__, __TIME__)
#endif
#define MIN_IN_BUFS 1
#define MIN_OUT_BUFS_420 3
#define MIN_OUT_BUFS_422ILE 1
#define MIN_OUT_BUFS_RGB565 1
#define MIN_OUT_BUFS_420SP 2
#define NUM_FRAMES_LIMIT_ENABLED 0
#if NUM_FRAMES_LIMIT_ENABLED
#define NUM_FRAMES_LIMIT 10000
#else
#define NUM_FRAMES_LIMIT 0x7FFFFFFF
#endif
UWORD32 ih264d_get_extra_mem_external(UWORD32 width, UWORD32 height);
WORD32 ih264d_get_frame_dimensions(iv_obj_t *dec_hdl,
void *pv_api_ip,
void *pv_api_op);
WORD32 ih264d_get_vui_params(iv_obj_t *dec_hdl,
void *pv_api_ip,
void *pv_api_op);
WORD32 ih264d_set_num_cores(iv_obj_t *dec_hdl, void *pv_api_ip, void *pv_api_op);
WORD32 ih264d_deblock_display(dec_struct_t *ps_dec);
void ih264d_signal_decode_thread(dec_struct_t *ps_dec);
void ih264d_signal_bs_deblk_thread(dec_struct_t *ps_dec);
void ih264d_decode_picture_thread(dec_struct_t *ps_dec);
WORD32 ih264d_set_degrade(iv_obj_t *ps_codec_obj,
void *pv_api_ip,
void *pv_api_op);
void ih264d_fill_output_struct_from_context(dec_struct_t *ps_dec,
ivd_video_decode_op_t *ps_dec_op);
static IV_API_CALL_STATUS_T api_check_struct_sanity(iv_obj_t *ps_handle,
void *pv_api_ip,
void *pv_api_op)
{
IVD_API_COMMAND_TYPE_T e_cmd;
UWORD32 *pu4_api_ip;
UWORD32 *pu4_api_op;
UWORD32 i, j;
if(NULL == pv_api_op)
return (IV_FAIL);
if(NULL == pv_api_ip)
return (IV_FAIL);
pu4_api_ip = (UWORD32 *)pv_api_ip;
pu4_api_op = (UWORD32 *)pv_api_op;
e_cmd = *(pu4_api_ip + 1);
/* error checks on handle */
switch((WORD32)e_cmd)
{
case IVD_CMD_CREATE:
break;
case IVD_CMD_REL_DISPLAY_FRAME:
case IVD_CMD_SET_DISPLAY_FRAME:
case IVD_CMD_GET_DISPLAY_FRAME:
case IVD_CMD_VIDEO_DECODE:
case IVD_CMD_DELETE:
case IVD_CMD_VIDEO_CTL:
if(ps_handle == NULL)
{
*(pu4_api_op + 1) |= 1 << IVD_UNSUPPORTEDPARAM;
*(pu4_api_op + 1) |= IVD_HANDLE_NULL;
return IV_FAIL;
}
if(ps_handle->u4_size != sizeof(iv_obj_t))
{
*(pu4_api_op + 1) |= 1 << IVD_UNSUPPORTEDPARAM;
*(pu4_api_op + 1) |= IVD_HANDLE_STRUCT_SIZE_INCORRECT;
return IV_FAIL;
}
if(ps_handle->pv_fxns != ih264d_api_function)
{
*(pu4_api_op + 1) |= 1 << IVD_UNSUPPORTEDPARAM;
*(pu4_api_op + 1) |= IVD_INVALID_HANDLE_NULL;
return IV_FAIL;
}
if(ps_handle->pv_codec_handle == NULL)
{
*(pu4_api_op + 1) |= 1 << IVD_UNSUPPORTEDPARAM;
*(pu4_api_op + 1) |= IVD_INVALID_HANDLE_NULL;
return IV_FAIL;
}
break;
default:
*(pu4_api_op + 1) |= 1 << IVD_UNSUPPORTEDPARAM;
*(pu4_api_op + 1) |= IVD_INVALID_API_CMD;
return IV_FAIL;
}
switch((WORD32)e_cmd)
{
case IVD_CMD_CREATE:
{
ih264d_create_ip_t *ps_ip = (ih264d_create_ip_t *)pv_api_ip;
ih264d_create_op_t *ps_op = (ih264d_create_op_t *)pv_api_op;
ps_op->s_ivd_create_op_t.u4_error_code = 0;
if((ps_ip->s_ivd_create_ip_t.u4_size > sizeof(ih264d_create_ip_t))
|| (ps_ip->s_ivd_create_ip_t.u4_size
< sizeof(ivd_create_ip_t)))
{
ps_op->s_ivd_create_op_t.u4_error_code |= 1
<< IVD_UNSUPPORTEDPARAM;
ps_op->s_ivd_create_op_t.u4_error_code |=
IVD_IP_API_STRUCT_SIZE_INCORRECT;
H264_DEC_DEBUG_PRINT("\n");
return (IV_FAIL);
}
if((ps_op->s_ivd_create_op_t.u4_size != sizeof(ih264d_create_op_t))
&& (ps_op->s_ivd_create_op_t.u4_size
!= sizeof(ivd_create_op_t)))
{
ps_op->s_ivd_create_op_t.u4_error_code |= 1
<< IVD_UNSUPPORTEDPARAM;
ps_op->s_ivd_create_op_t.u4_error_code |=
IVD_OP_API_STRUCT_SIZE_INCORRECT;
H264_DEC_DEBUG_PRINT("\n");
return (IV_FAIL);
}
if((ps_ip->s_ivd_create_ip_t.e_output_format != IV_YUV_420P)
&& (ps_ip->s_ivd_create_ip_t.e_output_format
!= IV_YUV_422ILE)
&& (ps_ip->s_ivd_create_ip_t.e_output_format
!= IV_RGB_565)
&& (ps_ip->s_ivd_create_ip_t.e_output_format
!= IV_YUV_420SP_UV)
&& (ps_ip->s_ivd_create_ip_t.e_output_format
!= IV_YUV_420SP_VU))
{
ps_op->s_ivd_create_op_t.u4_error_code |= 1
<< IVD_UNSUPPORTEDPARAM;
ps_op->s_ivd_create_op_t.u4_error_code |=
IVD_INIT_DEC_COL_FMT_NOT_SUPPORTED;
H264_DEC_DEBUG_PRINT("\n");
return (IV_FAIL);
}
}
break;
case IVD_CMD_GET_DISPLAY_FRAME:
{
ih264d_get_display_frame_ip_t *ps_ip =
(ih264d_get_display_frame_ip_t *)pv_api_ip;
ih264d_get_display_frame_op_t *ps_op =
(ih264d_get_display_frame_op_t *)pv_api_op;
ps_op->s_ivd_get_display_frame_op_t.u4_error_code = 0;
if((ps_ip->s_ivd_get_display_frame_ip_t.u4_size
!= sizeof(ih264d_get_display_frame_ip_t))
&& (ps_ip->s_ivd_get_display_frame_ip_t.u4_size
!= sizeof(ivd_get_display_frame_ip_t)))
{
ps_op->s_ivd_get_display_frame_op_t.u4_error_code |= 1
<< IVD_UNSUPPORTEDPARAM;
ps_op->s_ivd_get_display_frame_op_t.u4_error_code |=
IVD_IP_API_STRUCT_SIZE_INCORRECT;
return (IV_FAIL);
}
if((ps_op->s_ivd_get_display_frame_op_t.u4_size
!= sizeof(ih264d_get_display_frame_op_t))
&& (ps_op->s_ivd_get_display_frame_op_t.u4_size
!= sizeof(ivd_get_display_frame_op_t)))
{
ps_op->s_ivd_get_display_frame_op_t.u4_error_code |= 1
<< IVD_UNSUPPORTEDPARAM;
ps_op->s_ivd_get_display_frame_op_t.u4_error_code |=
IVD_OP_API_STRUCT_SIZE_INCORRECT;
return (IV_FAIL);
}
}
break;
case IVD_CMD_REL_DISPLAY_FRAME:
{
ih264d_rel_display_frame_ip_t *ps_ip =
(ih264d_rel_display_frame_ip_t *)pv_api_ip;
ih264d_rel_display_frame_op_t *ps_op =
(ih264d_rel_display_frame_op_t *)pv_api_op;
ps_op->s_ivd_rel_display_frame_op_t.u4_error_code = 0;
if((ps_ip->s_ivd_rel_display_frame_ip_t.u4_size
!= sizeof(ih264d_rel_display_frame_ip_t))
&& (ps_ip->s_ivd_rel_display_frame_ip_t.u4_size
!= sizeof(ivd_rel_display_frame_ip_t)))
{
ps_op->s_ivd_rel_display_frame_op_t.u4_error_code |= 1
<< IVD_UNSUPPORTEDPARAM;
ps_op->s_ivd_rel_display_frame_op_t.u4_error_code |=
IVD_IP_API_STRUCT_SIZE_INCORRECT;
return (IV_FAIL);
}
if((ps_op->s_ivd_rel_display_frame_op_t.u4_size
!= sizeof(ih264d_rel_display_frame_op_t))
&& (ps_op->s_ivd_rel_display_frame_op_t.u4_size
!= sizeof(ivd_rel_display_frame_op_t)))
{
ps_op->s_ivd_rel_display_frame_op_t.u4_error_code |= 1
<< IVD_UNSUPPORTEDPARAM;
ps_op->s_ivd_rel_display_frame_op_t.u4_error_code |=
IVD_OP_API_STRUCT_SIZE_INCORRECT;
return (IV_FAIL);
}
}
break;
case IVD_CMD_SET_DISPLAY_FRAME:
{
ih264d_set_display_frame_ip_t *ps_ip =
(ih264d_set_display_frame_ip_t *)pv_api_ip;
ih264d_set_display_frame_op_t *ps_op =
(ih264d_set_display_frame_op_t *)pv_api_op;
UWORD32 j;
ps_op->s_ivd_set_display_frame_op_t.u4_error_code = 0;
if((ps_ip->s_ivd_set_display_frame_ip_t.u4_size
!= sizeof(ih264d_set_display_frame_ip_t))
&& (ps_ip->s_ivd_set_display_frame_ip_t.u4_size
!= sizeof(ivd_set_display_frame_ip_t)))
{
ps_op->s_ivd_set_display_frame_op_t.u4_error_code |= 1
<< IVD_UNSUPPORTEDPARAM;
ps_op->s_ivd_set_display_frame_op_t.u4_error_code |=
IVD_IP_API_STRUCT_SIZE_INCORRECT;
return (IV_FAIL);
}
if((ps_op->s_ivd_set_display_frame_op_t.u4_size
!= sizeof(ih264d_set_display_frame_op_t))
&& (ps_op->s_ivd_set_display_frame_op_t.u4_size
!= sizeof(ivd_set_display_frame_op_t)))
{
ps_op->s_ivd_set_display_frame_op_t.u4_error_code |= 1
<< IVD_UNSUPPORTEDPARAM;
ps_op->s_ivd_set_display_frame_op_t.u4_error_code |=
IVD_OP_API_STRUCT_SIZE_INCORRECT;
return (IV_FAIL);
}
if(ps_ip->s_ivd_set_display_frame_ip_t.num_disp_bufs == 0)
{
ps_op->s_ivd_set_display_frame_op_t.u4_error_code |= 1
<< IVD_UNSUPPORTEDPARAM;
ps_op->s_ivd_set_display_frame_op_t.u4_error_code |=
IVD_DISP_FRM_ZERO_OP_BUFS;
return IV_FAIL;
}
for(j = 0; j < ps_ip->s_ivd_set_display_frame_ip_t.num_disp_bufs;
j++)
{
if(ps_ip->s_ivd_set_display_frame_ip_t.s_disp_buffer[j].u4_num_bufs
== 0)
{
ps_op->s_ivd_set_display_frame_op_t.u4_error_code |= 1
<< IVD_UNSUPPORTEDPARAM;
ps_op->s_ivd_set_display_frame_op_t.u4_error_code |=
IVD_DISP_FRM_ZERO_OP_BUFS;
return IV_FAIL;
}
for(i = 0;
i
< ps_ip->s_ivd_set_display_frame_ip_t.s_disp_buffer[j].u4_num_bufs;
i++)
{
if(ps_ip->s_ivd_set_display_frame_ip_t.s_disp_buffer[j].pu1_bufs[i]
== NULL)
{
ps_op->s_ivd_set_display_frame_op_t.u4_error_code |= 1
<< IVD_UNSUPPORTEDPARAM;
ps_op->s_ivd_set_display_frame_op_t.u4_error_code |=
IVD_DISP_FRM_OP_BUF_NULL;
return IV_FAIL;
}
if(ps_ip->s_ivd_set_display_frame_ip_t.s_disp_buffer[j].u4_min_out_buf_size[i]
== 0)
{
ps_op->s_ivd_set_display_frame_op_t.u4_error_code |= 1
<< IVD_UNSUPPORTEDPARAM;
ps_op->s_ivd_set_display_frame_op_t.u4_error_code |=
IVD_DISP_FRM_ZERO_OP_BUF_SIZE;
return IV_FAIL;
}
}
}
}
break;
case IVD_CMD_VIDEO_DECODE:
{
ih264d_video_decode_ip_t *ps_ip =
(ih264d_video_decode_ip_t *)pv_api_ip;
ih264d_video_decode_op_t *ps_op =
(ih264d_video_decode_op_t *)pv_api_op;
H264_DEC_DEBUG_PRINT("The input bytes is: %d",
ps_ip->s_ivd_video_decode_ip_t.u4_num_Bytes);
ps_op->s_ivd_video_decode_op_t.u4_error_code = 0;
if(ps_ip->s_ivd_video_decode_ip_t.u4_size
!= sizeof(ih264d_video_decode_ip_t)&&
ps_ip->s_ivd_video_decode_ip_t.u4_size != offsetof(ivd_video_decode_ip_t, s_out_buffer))
{
ps_op->s_ivd_video_decode_op_t.u4_error_code |= 1
<< IVD_UNSUPPORTEDPARAM;
ps_op->s_ivd_video_decode_op_t.u4_error_code |=
IVD_IP_API_STRUCT_SIZE_INCORRECT;
return (IV_FAIL);
}
if(ps_op->s_ivd_video_decode_op_t.u4_size
!= sizeof(ih264d_video_decode_op_t)&&
ps_op->s_ivd_video_decode_op_t.u4_size != offsetof(ivd_video_decode_op_t, u4_output_present))
{
ps_op->s_ivd_video_decode_op_t.u4_error_code |= 1
<< IVD_UNSUPPORTEDPARAM;
ps_op->s_ivd_video_decode_op_t.u4_error_code |=
IVD_OP_API_STRUCT_SIZE_INCORRECT;
return (IV_FAIL);
}
}
break;
case IVD_CMD_DELETE:
{
ih264d_delete_ip_t *ps_ip =
(ih264d_delete_ip_t *)pv_api_ip;
ih264d_delete_op_t *ps_op =
(ih264d_delete_op_t *)pv_api_op;
ps_op->s_ivd_delete_op_t.u4_error_code = 0;
if(ps_ip->s_ivd_delete_ip_t.u4_size
!= sizeof(ih264d_delete_ip_t))
{
ps_op->s_ivd_delete_op_t.u4_error_code |= 1
<< IVD_UNSUPPORTEDPARAM;
ps_op->s_ivd_delete_op_t.u4_error_code |=
IVD_IP_API_STRUCT_SIZE_INCORRECT;
return (IV_FAIL);
}
if(ps_op->s_ivd_delete_op_t.u4_size
!= sizeof(ih264d_delete_op_t))
{
ps_op->s_ivd_delete_op_t.u4_error_code |= 1
<< IVD_UNSUPPORTEDPARAM;
ps_op->s_ivd_delete_op_t.u4_error_code |=
IVD_OP_API_STRUCT_SIZE_INCORRECT;
return (IV_FAIL);
}
}
break;
case IVD_CMD_VIDEO_CTL:
{
UWORD32 *pu4_ptr_cmd;
UWORD32 sub_command;
pu4_ptr_cmd = (UWORD32 *)pv_api_ip;
pu4_ptr_cmd += 2;
sub_command = *pu4_ptr_cmd;
switch(sub_command)
{
case IVD_CMD_CTL_SETPARAMS:
{
ih264d_ctl_set_config_ip_t *ps_ip;
ih264d_ctl_set_config_op_t *ps_op;
ps_ip = (ih264d_ctl_set_config_ip_t *)pv_api_ip;
ps_op = (ih264d_ctl_set_config_op_t *)pv_api_op;
if(ps_ip->s_ivd_ctl_set_config_ip_t.u4_size
!= sizeof(ih264d_ctl_set_config_ip_t))
{
ps_op->s_ivd_ctl_set_config_op_t.u4_error_code |= 1
<< IVD_UNSUPPORTEDPARAM;
ps_op->s_ivd_ctl_set_config_op_t.u4_error_code |=
IVD_IP_API_STRUCT_SIZE_INCORRECT;
return IV_FAIL;
}
}
//no break; is needed here
case IVD_CMD_CTL_SETDEFAULT:
{
ih264d_ctl_set_config_op_t *ps_op;
ps_op = (ih264d_ctl_set_config_op_t *)pv_api_op;
if(ps_op->s_ivd_ctl_set_config_op_t.u4_size
!= sizeof(ih264d_ctl_set_config_op_t))
{
ps_op->s_ivd_ctl_set_config_op_t.u4_error_code |= 1
<< IVD_UNSUPPORTEDPARAM;
ps_op->s_ivd_ctl_set_config_op_t.u4_error_code |=
IVD_OP_API_STRUCT_SIZE_INCORRECT;
return IV_FAIL;
}
}
break;
case IVD_CMD_CTL_GETPARAMS:
{
ih264d_ctl_getstatus_ip_t *ps_ip;
ih264d_ctl_getstatus_op_t *ps_op;
ps_ip = (ih264d_ctl_getstatus_ip_t *)pv_api_ip;
ps_op = (ih264d_ctl_getstatus_op_t *)pv_api_op;
if(ps_ip->s_ivd_ctl_getstatus_ip_t.u4_size
!= sizeof(ih264d_ctl_getstatus_ip_t))
{
ps_op->s_ivd_ctl_getstatus_op_t.u4_error_code |= 1
<< IVD_UNSUPPORTEDPARAM;
ps_op->s_ivd_ctl_getstatus_op_t.u4_error_code |=
IVD_IP_API_STRUCT_SIZE_INCORRECT;
return IV_FAIL;
}
if(ps_op->s_ivd_ctl_getstatus_op_t.u4_size
!= sizeof(ih264d_ctl_getstatus_op_t))
{
ps_op->s_ivd_ctl_getstatus_op_t.u4_error_code |= 1
<< IVD_UNSUPPORTEDPARAM;
ps_op->s_ivd_ctl_getstatus_op_t.u4_error_code |=
IVD_OP_API_STRUCT_SIZE_INCORRECT;
return IV_FAIL;
}
}
break;
case IVD_CMD_CTL_GETBUFINFO:
{
ih264d_ctl_getbufinfo_ip_t *ps_ip;
ih264d_ctl_getbufinfo_op_t *ps_op;
ps_ip = (ih264d_ctl_getbufinfo_ip_t *)pv_api_ip;
ps_op = (ih264d_ctl_getbufinfo_op_t *)pv_api_op;
if(ps_ip->s_ivd_ctl_getbufinfo_ip_t.u4_size
!= sizeof(ih264d_ctl_getbufinfo_ip_t))
{
ps_op->s_ivd_ctl_getbufinfo_op_t.u4_error_code |= 1
<< IVD_UNSUPPORTEDPARAM;
ps_op->s_ivd_ctl_getbufinfo_op_t.u4_error_code |=
IVD_IP_API_STRUCT_SIZE_INCORRECT;
return IV_FAIL;
}
if(ps_op->s_ivd_ctl_getbufinfo_op_t.u4_size
!= sizeof(ih264d_ctl_getbufinfo_op_t))
{
ps_op->s_ivd_ctl_getbufinfo_op_t.u4_error_code |= 1
<< IVD_UNSUPPORTEDPARAM;
ps_op->s_ivd_ctl_getbufinfo_op_t.u4_error_code |=
IVD_OP_API_STRUCT_SIZE_INCORRECT;
return IV_FAIL;
}
}
break;
case IVD_CMD_CTL_GETVERSION:
{
ih264d_ctl_getversioninfo_ip_t *ps_ip;
ih264d_ctl_getversioninfo_op_t *ps_op;
ps_ip = (ih264d_ctl_getversioninfo_ip_t *)pv_api_ip;
ps_op = (ih264d_ctl_getversioninfo_op_t *)pv_api_op;
if(ps_ip->s_ivd_ctl_getversioninfo_ip_t.u4_size
!= sizeof(ih264d_ctl_getversioninfo_ip_t))
{
ps_op->s_ivd_ctl_getversioninfo_op_t.u4_error_code |= 1
<< IVD_UNSUPPORTEDPARAM;
ps_op->s_ivd_ctl_getversioninfo_op_t.u4_error_code |=
IVD_IP_API_STRUCT_SIZE_INCORRECT;
return IV_FAIL;
}
if(ps_op->s_ivd_ctl_getversioninfo_op_t.u4_size
!= sizeof(ih264d_ctl_getversioninfo_op_t))
{
ps_op->s_ivd_ctl_getversioninfo_op_t.u4_error_code |= 1
<< IVD_UNSUPPORTEDPARAM;
ps_op->s_ivd_ctl_getversioninfo_op_t.u4_error_code |=
IVD_OP_API_STRUCT_SIZE_INCORRECT;
return IV_FAIL;
}
}
break;
case IVD_CMD_CTL_FLUSH:
{
ih264d_ctl_flush_ip_t *ps_ip;
ih264d_ctl_flush_op_t *ps_op;
ps_ip = (ih264d_ctl_flush_ip_t *)pv_api_ip;
ps_op = (ih264d_ctl_flush_op_t *)pv_api_op;
if(ps_ip->s_ivd_ctl_flush_ip_t.u4_size
!= sizeof(ih264d_ctl_flush_ip_t))
{
ps_op->s_ivd_ctl_flush_op_t.u4_error_code |= 1
<< IVD_UNSUPPORTEDPARAM;
ps_op->s_ivd_ctl_flush_op_t.u4_error_code |=
IVD_IP_API_STRUCT_SIZE_INCORRECT;
return IV_FAIL;
}
if(ps_op->s_ivd_ctl_flush_op_t.u4_size
!= sizeof(ih264d_ctl_flush_op_t))
{
ps_op->s_ivd_ctl_flush_op_t.u4_error_code |= 1
<< IVD_UNSUPPORTEDPARAM;
ps_op->s_ivd_ctl_flush_op_t.u4_error_code |=
IVD_OP_API_STRUCT_SIZE_INCORRECT;
return IV_FAIL;
}
}
break;
case IVD_CMD_CTL_RESET:
{
ih264d_ctl_reset_ip_t *ps_ip;
ih264d_ctl_reset_op_t *ps_op;
ps_ip = (ih264d_ctl_reset_ip_t *)pv_api_ip;
ps_op = (ih264d_ctl_reset_op_t *)pv_api_op;
if(ps_ip->s_ivd_ctl_reset_ip_t.u4_size
!= sizeof(ih264d_ctl_reset_ip_t))
{
ps_op->s_ivd_ctl_reset_op_t.u4_error_code |= 1
<< IVD_UNSUPPORTEDPARAM;
ps_op->s_ivd_ctl_reset_op_t.u4_error_code |=
IVD_IP_API_STRUCT_SIZE_INCORRECT;
return IV_FAIL;
}
if(ps_op->s_ivd_ctl_reset_op_t.u4_size
!= sizeof(ih264d_ctl_reset_op_t))
{
ps_op->s_ivd_ctl_reset_op_t.u4_error_code |= 1
<< IVD_UNSUPPORTEDPARAM;
ps_op->s_ivd_ctl_reset_op_t.u4_error_code |=
IVD_OP_API_STRUCT_SIZE_INCORRECT;
return IV_FAIL;
}
}
break;
case IH264D_CMD_CTL_DEGRADE:
{
ih264d_ctl_degrade_ip_t *ps_ip;
ih264d_ctl_degrade_op_t *ps_op;
ps_ip = (ih264d_ctl_degrade_ip_t *)pv_api_ip;
ps_op = (ih264d_ctl_degrade_op_t *)pv_api_op;
if(ps_ip->u4_size != sizeof(ih264d_ctl_degrade_ip_t))
{
ps_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM;
ps_op->u4_error_code |=
IVD_IP_API_STRUCT_SIZE_INCORRECT;
return IV_FAIL;
}
if(ps_op->u4_size != sizeof(ih264d_ctl_degrade_op_t))
{
ps_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM;
ps_op->u4_error_code |=
IVD_OP_API_STRUCT_SIZE_INCORRECT;
return IV_FAIL;
}
if((ps_ip->i4_degrade_pics < 0)
|| (ps_ip->i4_degrade_pics > 4)
|| (ps_ip->i4_nondegrade_interval < 0)
|| (ps_ip->i4_degrade_type < 0)
|| (ps_ip->i4_degrade_type > 15))
{
ps_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM;
return IV_FAIL;
}
break;
}
case IH264D_CMD_CTL_GET_BUFFER_DIMENSIONS:
{
ih264d_ctl_get_frame_dimensions_ip_t *ps_ip;
ih264d_ctl_get_frame_dimensions_op_t *ps_op;
ps_ip = (ih264d_ctl_get_frame_dimensions_ip_t *)pv_api_ip;
ps_op = (ih264d_ctl_get_frame_dimensions_op_t *)pv_api_op;
if(ps_ip->u4_size
!= sizeof(ih264d_ctl_get_frame_dimensions_ip_t))
{
ps_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM;
ps_op->u4_error_code |=
IVD_IP_API_STRUCT_SIZE_INCORRECT;
return IV_FAIL;
}
if(ps_op->u4_size
!= sizeof(ih264d_ctl_get_frame_dimensions_op_t))
{
ps_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM;
ps_op->u4_error_code |=
IVD_OP_API_STRUCT_SIZE_INCORRECT;
return IV_FAIL;
}
break;
}
case IH264D_CMD_CTL_GET_VUI_PARAMS:
{
ih264d_ctl_get_vui_params_ip_t *ps_ip;
ih264d_ctl_get_vui_params_op_t *ps_op;
ps_ip =
(ih264d_ctl_get_vui_params_ip_t *)pv_api_ip;
ps_op =
(ih264d_ctl_get_vui_params_op_t *)pv_api_op;
if(ps_ip->u4_size
!= sizeof(ih264d_ctl_get_vui_params_ip_t))
{
ps_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM;
ps_op->u4_error_code |=
IVD_IP_API_STRUCT_SIZE_INCORRECT;
return IV_FAIL;
}
if(ps_op->u4_size
!= sizeof(ih264d_ctl_get_vui_params_op_t))
{
ps_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM;
ps_op->u4_error_code |=
IVD_OP_API_STRUCT_SIZE_INCORRECT;
return IV_FAIL;
}
break;
}
case IH264D_CMD_CTL_SET_NUM_CORES:
{
ih264d_ctl_set_num_cores_ip_t *ps_ip;
ih264d_ctl_set_num_cores_op_t *ps_op;
ps_ip = (ih264d_ctl_set_num_cores_ip_t *)pv_api_ip;
ps_op = (ih264d_ctl_set_num_cores_op_t *)pv_api_op;
if(ps_ip->u4_size != sizeof(ih264d_ctl_set_num_cores_ip_t))
{
ps_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM;
ps_op->u4_error_code |=
IVD_IP_API_STRUCT_SIZE_INCORRECT;
return IV_FAIL;
}
if(ps_op->u4_size != sizeof(ih264d_ctl_set_num_cores_op_t))
{
ps_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM;
ps_op->u4_error_code |=
IVD_OP_API_STRUCT_SIZE_INCORRECT;
return IV_FAIL;
}
if((ps_ip->u4_num_cores != 1) && (ps_ip->u4_num_cores != 2)
&& (ps_ip->u4_num_cores != 3)
&& (ps_ip->u4_num_cores != 4))
{
ps_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM;
return IV_FAIL;
}
break;
}
case IH264D_CMD_CTL_SET_PROCESSOR:
{
ih264d_ctl_set_processor_ip_t *ps_ip;
ih264d_ctl_set_processor_op_t *ps_op;
ps_ip = (ih264d_ctl_set_processor_ip_t *)pv_api_ip;
ps_op = (ih264d_ctl_set_processor_op_t *)pv_api_op;
if(ps_ip->u4_size != sizeof(ih264d_ctl_set_processor_ip_t))
{
ps_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM;
ps_op->u4_error_code |=
IVD_IP_API_STRUCT_SIZE_INCORRECT;
return IV_FAIL;
}
if(ps_op->u4_size != sizeof(ih264d_ctl_set_processor_op_t))
{
ps_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM;
ps_op->u4_error_code |=
IVD_OP_API_STRUCT_SIZE_INCORRECT;
return IV_FAIL;
}
break;
}
default:
*(pu4_api_op + 1) |= 1 << IVD_UNSUPPORTEDPARAM;
*(pu4_api_op + 1) |= IVD_UNSUPPORTED_API_CMD;
return IV_FAIL;
break;
}
}
break;
}
return IV_SUCCESS;
}
/**
*******************************************************************************
*
* @brief
* Sets Processor type
*
* @par Description:
* Sets Processor type
*
* @param[in] ps_codec_obj
* Pointer to codec object at API level
*
* @param[in] pv_api_ip
* Pointer to input argument structure
*
* @param[out] pv_api_op
* Pointer to output argument structure
*
* @returns Status
*
* @remarks
*
*
*******************************************************************************
*/
WORD32 ih264d_set_processor(iv_obj_t *dec_hdl, void *pv_api_ip, void *pv_api_op)
{
ih264d_ctl_set_processor_ip_t *ps_ip;
ih264d_ctl_set_processor_op_t *ps_op;
dec_struct_t *ps_codec = (dec_struct_t *)dec_hdl->pv_codec_handle;
ps_ip = (ih264d_ctl_set_processor_ip_t *)pv_api_ip;
ps_op = (ih264d_ctl_set_processor_op_t *)pv_api_op;
ps_codec->e_processor_arch = (IVD_ARCH_T)ps_ip->u4_arch;
ps_codec->e_processor_soc = (IVD_SOC_T)ps_ip->u4_soc;
ih264d_init_function_ptr(ps_codec);
ps_op->u4_error_code = 0;
return IV_SUCCESS;
}
/**************************************************************************
* \if Function name : ih264d_init_decoder \endif
*
*
* \brief
* Initializes the decoder
*
* \param apiVersion : Version of the api being used.
* \param errorHandlingMechanism : Mechanism to be used for errror handling.
* \param postFilteringType: Type of post filtering operation to be used.
* \param uc_outputFormat: Format of the decoded picture [default 4:2:0].
* \param uc_dispBufs: Number of Display Buffers.
* \param p_NALBufAPI: Pointer to NAL Buffer API.
* \param p_DispBufAPI: Pointer to Display Buffer API.
* \param ih264d_dec_mem_manager :Pointer to the function that will be called by decoder
* for memory allocation and freeing.
*
* \return
* 0 on Success and -1 on error
*
**************************************************************************
*/
void ih264d_init_decoder(void * ps_dec_params)
{
dec_struct_t * ps_dec = (dec_struct_t *)ps_dec_params;
dec_slice_params_t *ps_cur_slice;
pocstruct_t *ps_prev_poc, *ps_cur_poc;
WORD32 size;
size = sizeof(pred_info_t) * 2 * 32;
memset(ps_dec->ps_pred, 0 , size);
size = sizeof(disp_mgr_t);
memset(ps_dec->pv_disp_buf_mgr, 0 , size);
size = sizeof(buf_mgr_t) + ithread_get_mutex_lock_size();
memset(ps_dec->pv_pic_buf_mgr, 0, size);
size = sizeof(dec_err_status_t);
memset(ps_dec->ps_dec_err_status, 0, size);
size = sizeof(sei);
memset(ps_dec->ps_sei, 0, size);
size = sizeof(dpb_commands_t);
memset(ps_dec->ps_dpb_cmds, 0, size);
size = sizeof(dec_bit_stream_t);
memset(ps_dec->ps_bitstrm, 0, size);
size = sizeof(dec_slice_params_t);
memset(ps_dec->ps_cur_slice, 0, size);
size = MAX(sizeof(dec_seq_params_t), sizeof(dec_pic_params_t));
memset(ps_dec->pv_scratch_sps_pps, 0, size);
size = sizeof(ctxt_inc_mb_info_t);
memset(ps_dec->ps_left_mb_ctxt_info, 0, size);
size = (sizeof(neighbouradd_t) << 2);
memset(ps_dec->ps_left_mvpred_addr, 0 ,size);
size = sizeof(buf_mgr_t) + ithread_get_mutex_lock_size();
memset(ps_dec->pv_mv_buf_mgr, 0, size);
/* Free any dynamic buffers that are allocated */
ih264d_free_dynamic_bufs(ps_dec);
{
UWORD8 i;
struct pic_buffer_t *ps_init_dpb;
ps_init_dpb = ps_dec->ps_dpb_mgr->ps_init_dpb[0][0];
for(i = 0; i < 2 * MAX_REF_BUFS; i++)
{
ps_init_dpb->pu1_buf1 = NULL;
ps_init_dpb->u1_long_term_frm_idx = MAX_REF_BUFS + 1;
ps_dec->ps_dpb_mgr->ps_init_dpb[0][i] = ps_init_dpb;
ps_dec->ps_dpb_mgr->ps_mod_dpb[0][i] = ps_init_dpb;
ps_init_dpb++;
}
ps_init_dpb = ps_dec->ps_dpb_mgr->ps_init_dpb[1][0];
for(i = 0; i < 2 * MAX_REF_BUFS; i++)
{
ps_init_dpb->pu1_buf1 = NULL;
ps_init_dpb->u1_long_term_frm_idx = MAX_REF_BUFS + 1;
ps_dec->ps_dpb_mgr->ps_init_dpb[1][i] = ps_init_dpb;
ps_dec->ps_dpb_mgr->ps_mod_dpb[1][i] = ps_init_dpb;
ps_init_dpb++;
}
}
ps_cur_slice = ps_dec->ps_cur_slice;
ps_dec->init_done = 0;
ps_dec->u4_num_cores = 1;
ps_dec->u2_pic_ht = ps_dec->u2_pic_wd = 0;
ps_dec->u1_separate_parse = DEFAULT_SEPARATE_PARSE;
ps_dec->u4_app_disable_deblk_frm = 0;
ps_dec->i4_degrade_type = 0;
ps_dec->i4_degrade_pics = 0;
ps_dec->i4_app_skip_mode = IVD_SKIP_NONE;
ps_dec->i4_dec_skip_mode = IVD_SKIP_NONE;
memset(ps_dec->ps_pps, 0,
((sizeof(dec_pic_params_t)) * MAX_NUM_PIC_PARAMS));
memset(ps_dec->ps_sps, 0,
((sizeof(dec_seq_params_t)) * MAX_NUM_SEQ_PARAMS));
/* Initialization of function pointers ih264d_deblock_picture function*/
ps_dec->p_DeblockPicture[0] = ih264d_deblock_picture_non_mbaff;
ps_dec->p_DeblockPicture[1] = ih264d_deblock_picture_mbaff;
ps_dec->s_cab_dec_env.pv_codec_handle = ps_dec;
ps_dec->u4_num_fld_in_frm = 0;
ps_dec->ps_dpb_mgr->pv_codec_handle = ps_dec;
/* Initialize the sei validity u4_flag with zero indiacting sei is not valid*/
ps_dec->ps_sei->u1_is_valid = 0;
/* decParams Initializations */
ps_dec->ps_cur_pps = NULL;
ps_dec->ps_cur_sps = NULL;
ps_dec->u1_init_dec_flag = 0;
ps_dec->u1_first_slice_in_stream = 1;
ps_dec->u1_last_pic_not_decoded = 0;
ps_dec->u4_app_disp_width = 0;
ps_dec->i4_header_decoded = 0;
ps_dec->u4_total_frames_decoded = 0;
ps_dec->i4_error_code = 0;
ps_dec->i4_content_type = -1;
ps_dec->ps_cur_slice->u1_mbaff_frame_flag = 0;
ps_dec->ps_dec_err_status->u1_err_flag = ACCEPT_ALL_PICS; //REJECT_PB_PICS;
ps_dec->ps_dec_err_status->u1_cur_pic_type = PIC_TYPE_UNKNOWN;
ps_dec->ps_dec_err_status->u4_frm_sei_sync = SYNC_FRM_DEFAULT;
ps_dec->ps_dec_err_status->u4_cur_frm = INIT_FRAME;
ps_dec->ps_dec_err_status->u1_pic_aud_i = PIC_TYPE_UNKNOWN;
ps_dec->u1_pr_sl_type = 0xFF;
ps_dec->u2_mbx = 0xffff;
ps_dec->u2_mby = 0;
ps_dec->u2_total_mbs_coded = 0;
/* POC initializations */
ps_prev_poc = &ps_dec->s_prev_pic_poc;
ps_cur_poc = &ps_dec->s_cur_pic_poc;
ps_prev_poc->i4_pic_order_cnt_lsb = ps_cur_poc->i4_pic_order_cnt_lsb = 0;
ps_prev_poc->i4_pic_order_cnt_msb = ps_cur_poc->i4_pic_order_cnt_msb = 0;
ps_prev_poc->i4_delta_pic_order_cnt_bottom =
ps_cur_poc->i4_delta_pic_order_cnt_bottom = 0;
ps_prev_poc->i4_delta_pic_order_cnt[0] =
ps_cur_poc->i4_delta_pic_order_cnt[0] = 0;
ps_prev_poc->i4_delta_pic_order_cnt[1] =
ps_cur_poc->i4_delta_pic_order_cnt[1] = 0;
ps_prev_poc->u1_mmco_equalto5 = ps_cur_poc->u1_mmco_equalto5 = 0;
ps_prev_poc->i4_top_field_order_count = ps_cur_poc->i4_top_field_order_count =
0;
ps_prev_poc->i4_bottom_field_order_count =
ps_cur_poc->i4_bottom_field_order_count = 0;
ps_prev_poc->u1_bot_field = ps_cur_poc->u1_bot_field = 0;
ps_prev_poc->u1_mmco_equalto5 = ps_cur_poc->u1_mmco_equalto5 = 0;
ps_prev_poc->i4_prev_frame_num_ofst = ps_cur_poc->i4_prev_frame_num_ofst = 0;
ps_cur_slice->u1_mmco_equalto5 = 0;
ps_cur_slice->u2_frame_num = 0;
ps_dec->i4_max_poc = 0;
ps_dec->i4_prev_max_display_seq = 0;
ps_dec->u1_recon_mb_grp = 4;
/* Field PIC initializations */
ps_dec->u1_second_field = 0;
ps_dec->s_prev_seq_params.u1_eoseq_pending = 0;
/* Set the cropping parameters as zero */
ps_dec->u2_crop_offset_y = 0;
ps_dec->u2_crop_offset_uv = 0;
/* The Initial Frame Rate Info is not Present */
ps_dec->i4_vui_frame_rate = -1;
ps_dec->i4_pic_type = -1;
ps_dec->i4_frametype = -1;
ps_dec->i4_content_type = -1;
ps_dec->u1_res_changed = 0;
ps_dec->u1_frame_decoded_flag = 0;
/* Set the default frame seek mask mode */
ps_dec->u4_skip_frm_mask = SKIP_NONE;
/********************************************************/
/* Initialize CAVLC residual decoding function pointers */
/********************************************************/
ps_dec->pf_cavlc_4x4res_block[0] = ih264d_cavlc_4x4res_block_totalcoeff_1;
ps_dec->pf_cavlc_4x4res_block[1] =
ih264d_cavlc_4x4res_block_totalcoeff_2to10;
ps_dec->pf_cavlc_4x4res_block[2] =
ih264d_cavlc_4x4res_block_totalcoeff_11to16;
ps_dec->pf_cavlc_parse4x4coeff[0] = ih264d_cavlc_parse4x4coeff_n0to7;
ps_dec->pf_cavlc_parse4x4coeff[1] = ih264d_cavlc_parse4x4coeff_n8;
ps_dec->pf_cavlc_parse_8x8block[0] =
ih264d_cavlc_parse_8x8block_none_available;
ps_dec->pf_cavlc_parse_8x8block[1] =
ih264d_cavlc_parse_8x8block_left_available;
ps_dec->pf_cavlc_parse_8x8block[2] =
ih264d_cavlc_parse_8x8block_top_available;
ps_dec->pf_cavlc_parse_8x8block[3] =
ih264d_cavlc_parse_8x8block_both_available;
/***************************************************************************/
/* Initialize Bs calculation function pointers for P and B, 16x16/non16x16 */
/***************************************************************************/
ps_dec->pf_fill_bs1[0][0] = ih264d_fill_bs1_16x16mb_pslice;
ps_dec->pf_fill_bs1[0][1] = ih264d_fill_bs1_non16x16mb_pslice;
ps_dec->pf_fill_bs1[1][0] = ih264d_fill_bs1_16x16mb_bslice;
ps_dec->pf_fill_bs1[1][1] = ih264d_fill_bs1_non16x16mb_bslice;
ps_dec->pf_fill_bs_xtra_left_edge[0] =
ih264d_fill_bs_xtra_left_edge_cur_frm;
ps_dec->pf_fill_bs_xtra_left_edge[1] =
ih264d_fill_bs_xtra_left_edge_cur_fld;
/* Initialize Reference Pic Buffers */
ih264d_init_ref_bufs(ps_dec->ps_dpb_mgr);
ps_dec->u2_prv_frame_num = 0;
ps_dec->u1_top_bottom_decoded = 0;
ps_dec->u1_dangling_field = 0;
ps_dec->s_cab_dec_env.cabac_table = gau4_ih264d_cabac_table;
ps_dec->pu1_left_mv_ctxt_inc = ps_dec->u1_left_mv_ctxt_inc_arr[0];
ps_dec->pi1_left_ref_idx_ctxt_inc =
&ps_dec->i1_left_ref_idx_ctx_inc_arr[0][0];
ps_dec->pu1_left_yuv_dc_csbp = &ps_dec->u1_yuv_dc_csbp_topmb;
/* ! */
/* Initializing flush frame u4_flag */
ps_dec->u1_flushfrm = 0;
{
ps_dec->s_cab_dec_env.pv_codec_handle = (void*)ps_dec;
ps_dec->ps_bitstrm->pv_codec_handle = (void*)ps_dec;
ps_dec->ps_cur_slice->pv_codec_handle = (void*)ps_dec;
ps_dec->ps_dpb_mgr->pv_codec_handle = (void*)ps_dec;
}
memset(ps_dec->disp_bufs, 0, (MAX_DISP_BUFS_NEW) * sizeof(disp_buf_t));
memset(ps_dec->u4_disp_buf_mapping, 0,
(MAX_DISP_BUFS_NEW) * sizeof(UWORD32));
memset(ps_dec->u4_disp_buf_to_be_freed, 0,
(MAX_DISP_BUFS_NEW) * sizeof(UWORD32));
memset(ps_dec->ps_cur_slice, 0, sizeof(dec_slice_params_t));
ih264d_init_arch(ps_dec);
ih264d_init_function_ptr(ps_dec);
ps_dec->e_frm_out_mode = IVD_DISPLAY_FRAME_OUT;
ps_dec->init_done = 1;
}
WORD32 ih264d_free_static_bufs(iv_obj_t *dec_hdl)
{
dec_struct_t *ps_dec;
void (*pf_aligned_free)(void *pv_mem_ctxt, void *pv_buf);
void *pv_mem_ctxt;
ps_dec = (dec_struct_t *)dec_hdl->pv_codec_handle;
pf_aligned_free = ps_dec->pf_aligned_free;
pv_mem_ctxt = ps_dec->pv_mem_ctxt;
PS_DEC_ALIGNED_FREE(ps_dec, ps_dec->ps_sps);
PS_DEC_ALIGNED_FREE(ps_dec, ps_dec->ps_pps);
PS_DEC_ALIGNED_FREE(ps_dec, ps_dec->pv_dec_thread_handle);
PS_DEC_ALIGNED_FREE(ps_dec, ps_dec->pv_bs_deblk_thread_handle);
PS_DEC_ALIGNED_FREE(ps_dec, ps_dec->ps_dpb_mgr);
PS_DEC_ALIGNED_FREE(ps_dec, ps_dec->ps_pred);
PS_DEC_ALIGNED_FREE(ps_dec, ps_dec->pv_disp_buf_mgr);
PS_DEC_ALIGNED_FREE(ps_dec, ps_dec->pv_pic_buf_mgr);
PS_DEC_ALIGNED_FREE(ps_dec, ps_dec->ps_pic_buf_base);
PS_DEC_ALIGNED_FREE(ps_dec, ps_dec->ps_dec_err_status);
PS_DEC_ALIGNED_FREE(ps_dec, ps_dec->ps_sei);
PS_DEC_ALIGNED_FREE(ps_dec, ps_dec->ps_dpb_cmds);
PS_DEC_ALIGNED_FREE(ps_dec, ps_dec->ps_bitstrm);
PS_DEC_ALIGNED_FREE(ps_dec, ps_dec->ps_cur_slice);
PS_DEC_ALIGNED_FREE(ps_dec, ps_dec->pv_scratch_sps_pps);
PS_DEC_ALIGNED_FREE(ps_dec, ps_dec->pu1_bits_buf_static);
PS_DEC_ALIGNED_FREE(ps_dec, ps_dec->ppv_map_ref_idx_to_poc_base);
PS_DEC_ALIGNED_FREE(ps_dec, ps_dec->p_cabac_ctxt_table_t);
PS_DEC_ALIGNED_FREE(ps_dec, ps_dec->ps_left_mb_ctxt_info);
PS_DEC_ALIGNED_FREE(ps_dec, ps_dec->pu1_ref_buff_base);
PS_DEC_ALIGNED_FREE(ps_dec, ps_dec->pi2_pred1);
PS_DEC_ALIGNED_FREE(ps_dec, ps_dec->pu1_temp_mc_buffer);
PS_DEC_ALIGNED_FREE(ps_dec, ps_dec->pu1_init_dpb_base);
PS_DEC_ALIGNED_FREE(ps_dec, ps_dec->pu4_mbaff_wt_mat);
PS_DEC_ALIGNED_FREE(ps_dec, ps_dec->pu4_wts_ofsts_mat);
PS_DEC_ALIGNED_FREE(ps_dec, ps_dec->ps_left_mvpred_addr);
PS_DEC_ALIGNED_FREE(ps_dec, ps_dec->pv_mv_buf_mgr);
PS_DEC_ALIGNED_FREE(ps_dec, ps_dec->ps_col_mv_base);
PS_DEC_ALIGNED_FREE(ps_dec, dec_hdl->pv_codec_handle);
if(dec_hdl)
{
pf_aligned_free(pv_mem_ctxt, dec_hdl);
}
return IV_SUCCESS;
}
/*****************************************************************************/
/* */
/* Function Name : ih264d_create */
/* */
/* Description : creates decoder */
/* */
/* Inputs :iv_obj_t decoder handle */
/* :pv_api_ip pointer to input structure */
/* :pv_api_op pointer to output structure */
/* Outputs : */
/* Returns : void */
/* */
/* Issues : none */
/* */
/* Revision History: */
/* */
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
/* 22 10 2008 100356 Draft */
/* */
/*****************************************************************************/
WORD32 ih264d_allocate_static_bufs(iv_obj_t **dec_hdl, void *pv_api_ip, void *pv_api_op)
{
ih264d_create_ip_t *ps_create_ip;
ih264d_create_op_t *ps_create_op;
void *pv_buf;
UWORD8 *pu1_buf;
dec_struct_t *ps_dec;
void *(*pf_aligned_alloc)(void *pv_mem_ctxt, WORD32 alignment, WORD32 size);
void (*pf_aligned_free)(void *pv_mem_ctxt, void *pv_buf);
void *pv_mem_ctxt;
WORD32 size;
ps_create_ip = (ih264d_create_ip_t *)pv_api_ip;
ps_create_op = (ih264d_create_op_t *)pv_api_op;
ps_create_op->s_ivd_create_op_t.u4_error_code = 0;
pf_aligned_alloc = ps_create_ip->s_ivd_create_ip_t.pf_aligned_alloc;
pf_aligned_free = ps_create_ip->s_ivd_create_ip_t.pf_aligned_free;
pv_mem_ctxt = ps_create_ip->s_ivd_create_ip_t.pv_mem_ctxt;
/* Initialize return handle to NULL */
ps_create_op->s_ivd_create_op_t.pv_handle = NULL;
pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, sizeof(iv_obj_t));
RETURN_IF((NULL == pv_buf), IV_FAIL);
*dec_hdl = (iv_obj_t *)pv_buf;
ps_create_op->s_ivd_create_op_t.pv_handle = *dec_hdl;
(*dec_hdl)->pv_codec_handle = NULL;
pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, sizeof(dec_struct_t));
RETURN_IF((NULL == pv_buf), IV_FAIL);
(*dec_hdl)->pv_codec_handle = (dec_struct_t *)pv_buf;
ps_dec = (dec_struct_t *)pv_buf;
memset(ps_dec, 0, sizeof(dec_struct_t));
#ifndef LOGO_EN
ps_dec->u4_share_disp_buf = ps_create_ip->s_ivd_create_ip_t.u4_share_disp_buf;
#else
ps_dec->u4_share_disp_buf = 0;
#endif
ps_dec->u1_chroma_format =
(UWORD8)(ps_create_ip->s_ivd_create_ip_t.e_output_format);
if((ps_dec->u1_chroma_format != IV_YUV_420P)
&& (ps_dec->u1_chroma_format
!= IV_YUV_420SP_UV)
&& (ps_dec->u1_chroma_format
!= IV_YUV_420SP_VU))
{
ps_dec->u4_share_disp_buf = 0;
}
ps_dec->pf_aligned_alloc = pf_aligned_alloc;
ps_dec->pf_aligned_free = pf_aligned_free;
ps_dec->pv_mem_ctxt = pv_mem_ctxt;
size = ((sizeof(dec_seq_params_t)) * MAX_NUM_SEQ_PARAMS);
pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, size);
RETURN_IF((NULL == pv_buf), IV_FAIL);
ps_dec->ps_sps = pv_buf;
size = (sizeof(dec_pic_params_t)) * MAX_NUM_PIC_PARAMS;
pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, size);
RETURN_IF((NULL == pv_buf), IV_FAIL);
ps_dec->ps_pps = pv_buf;
size = ithread_get_handle_size();
pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, size);
RETURN_IF((NULL == pv_buf), IV_FAIL);
ps_dec->pv_dec_thread_handle = pv_buf;
size = ithread_get_handle_size();
pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, size);
RETURN_IF((NULL == pv_buf), IV_FAIL);
ps_dec->pv_bs_deblk_thread_handle = pv_buf;
size = sizeof(dpb_manager_t);
pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, size);
RETURN_IF((NULL == pv_buf), IV_FAIL);
ps_dec->ps_dpb_mgr = pv_buf;
size = sizeof(pred_info_t) * 2 * 32;
pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, size);
RETURN_IF((NULL == pv_buf), IV_FAIL);
ps_dec->ps_pred = pv_buf;
size = sizeof(disp_mgr_t);
pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, size);
RETURN_IF((NULL == pv_buf), IV_FAIL);
ps_dec->pv_disp_buf_mgr = pv_buf;
size = sizeof(buf_mgr_t) + ithread_get_mutex_lock_size();
pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, size);
RETURN_IF((NULL == pv_buf), IV_FAIL);
ps_dec->pv_pic_buf_mgr = pv_buf;
size = sizeof(struct pic_buffer_t) * (H264_MAX_REF_PICS * 2);
pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, size);
RETURN_IF((NULL == pv_buf), IV_FAIL);
ps_dec->ps_pic_buf_base = pv_buf;
size = sizeof(dec_err_status_t);
pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, size);
RETURN_IF((NULL == pv_buf), IV_FAIL);
ps_dec->ps_dec_err_status = (dec_err_status_t *)pv_buf;
size = sizeof(sei);
pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, size);
RETURN_IF((NULL == pv_buf), IV_FAIL);
ps_dec->ps_sei = (sei *)pv_buf;
size = sizeof(dpb_commands_t);
pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, size);
RETURN_IF((NULL == pv_buf), IV_FAIL);
ps_dec->ps_dpb_cmds = (dpb_commands_t *)pv_buf;
size = sizeof(dec_bit_stream_t);
pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, size);
RETURN_IF((NULL == pv_buf), IV_FAIL);
ps_dec->ps_bitstrm = (dec_bit_stream_t *)pv_buf;
size = sizeof(dec_slice_params_t);
pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, size);
RETURN_IF((NULL == pv_buf), IV_FAIL);
ps_dec->ps_cur_slice = (dec_slice_params_t *)pv_buf;
size = MAX(sizeof(dec_seq_params_t), sizeof(dec_pic_params_t));
pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, size);
RETURN_IF((NULL == pv_buf), IV_FAIL);
ps_dec->pv_scratch_sps_pps = pv_buf;
ps_dec->u4_static_bits_buf_size = 256000;
pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, ps_dec->u4_static_bits_buf_size);
RETURN_IF((NULL == pv_buf), IV_FAIL);
ps_dec->pu1_bits_buf_static = pv_buf;
size = ((TOTAL_LIST_ENTRIES + PAD_MAP_IDX_POC)
* sizeof(void *));
pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, size);
RETURN_IF((NULL == pv_buf), IV_FAIL);
ps_dec->ppv_map_ref_idx_to_poc_base = pv_buf;
memset(ps_dec->ppv_map_ref_idx_to_poc_base, 0, size);
ps_dec->ppv_map_ref_idx_to_poc = ps_dec->ppv_map_ref_idx_to_poc_base + OFFSET_MAP_IDX_POC;
size = (sizeof(bin_ctxt_model_t) * NUM_CABAC_CTXTS);
pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, size);
RETURN_IF((NULL == pv_buf), IV_FAIL);
ps_dec->p_cabac_ctxt_table_t = pv_buf;
size = sizeof(ctxt_inc_mb_info_t);
pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, size);
RETURN_IF((NULL == pv_buf), IV_FAIL);
ps_dec->ps_left_mb_ctxt_info = pv_buf;
size = MAX_REF_BUF_SIZE * 2;
pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, size);
RETURN_IF((NULL == pv_buf), IV_FAIL);
ps_dec->pu1_ref_buff_base = pv_buf;
ps_dec->pu1_ref_buff = ps_dec->pu1_ref_buff_base + MAX_REF_BUF_SIZE;
size = ((sizeof(WORD16)) * PRED_BUFFER_WIDTH
* PRED_BUFFER_HEIGHT * 2);
pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, size);
RETURN_IF((NULL == pv_buf), IV_FAIL);
ps_dec->pi2_pred1 = pv_buf;
size = sizeof(UWORD8) * (MB_LUM_SIZE);
pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, size);
RETURN_IF((NULL == pv_buf), IV_FAIL);
ps_dec->pu1_temp_mc_buffer = pv_buf;
size = 8 * MAX_REF_BUFS * sizeof(struct pic_buffer_t);
pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, size);
RETURN_IF((NULL == pv_buf), IV_FAIL);
ps_dec->pu1_init_dpb_base = pv_buf;
pu1_buf = pv_buf;
ps_dec->ps_dpb_mgr->ps_init_dpb[0][0] = (struct pic_buffer_t *)pu1_buf;
pu1_buf += size / 2;
ps_dec->ps_dpb_mgr->ps_init_dpb[1][0] = (struct pic_buffer_t *)pu1_buf;
size = (sizeof(UWORD32) * 2 * 3
* ((MAX_FRAMES << 1) * (MAX_FRAMES << 1)) * 2);
pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, size);
RETURN_IF((NULL == pv_buf), IV_FAIL);
ps_dec->pu4_mbaff_wt_mat = pv_buf;
size = sizeof(UWORD32) * 2 * 3
* ((MAX_FRAMES << 1) * (MAX_FRAMES << 1));
pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, size);
RETURN_IF((NULL == pv_buf), IV_FAIL);
ps_dec->pu4_wts_ofsts_mat = pv_buf;
size = (sizeof(neighbouradd_t) << 2);
pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, size);
RETURN_IF((NULL == pv_buf), IV_FAIL);
ps_dec->ps_left_mvpred_addr = pv_buf;
size = sizeof(buf_mgr_t) + ithread_get_mutex_lock_size();
pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, size);
RETURN_IF((NULL == pv_buf), IV_FAIL);
ps_dec->pv_mv_buf_mgr = pv_buf;
size = sizeof(col_mv_buf_t) * (H264_MAX_REF_PICS * 2);
pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, size);
RETURN_IF((NULL == pv_buf), IV_FAIL);
ps_dec->ps_col_mv_base = pv_buf;
memset(ps_dec->ps_col_mv_base, 0, size);
ih264d_init_decoder(ps_dec);
return IV_SUCCESS;
}
/*****************************************************************************/
/* */
/* Function Name : ih264d_create */
/* */
/* Description : creates decoder */
/* */
/* Inputs :iv_obj_t decoder handle */
/* :pv_api_ip pointer to input structure */
/* :pv_api_op pointer to output structure */
/* Outputs : */
/* Returns : void */
/* */
/* Issues : none */
/* */
/* Revision History: */
/* */
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
/* 22 10 2008 100356 Draft */
/* */
/*****************************************************************************/
WORD32 ih264d_create(iv_obj_t *dec_hdl, void *pv_api_ip, void *pv_api_op)
{
ih264d_create_ip_t *ps_create_ip;
ih264d_create_op_t *ps_create_op;
WORD32 ret;
ps_create_ip = (ih264d_create_ip_t *)pv_api_ip;
ps_create_op = (ih264d_create_op_t *)pv_api_op;
ps_create_op->s_ivd_create_op_t.u4_error_code = 0;
dec_hdl = NULL;
ret = ih264d_allocate_static_bufs(&dec_hdl, pv_api_ip, pv_api_op);
/* If allocation of some buffer fails, then free buffers allocated till then */
if(IV_FAIL == ret)
{
if(dec_hdl)
{
if(dec_hdl->pv_codec_handle)
{
ih264d_free_static_bufs(dec_hdl);
}
else
{
void (*pf_aligned_free)(void *pv_mem_ctxt, void *pv_buf);
void *pv_mem_ctxt;
pf_aligned_free = ps_create_ip->s_ivd_create_ip_t.pf_aligned_free;
pv_mem_ctxt = ps_create_ip->s_ivd_create_ip_t.pv_mem_ctxt;
pf_aligned_free(pv_mem_ctxt, dec_hdl);
}
}
ps_create_op->s_ivd_create_op_t.u4_error_code = IVD_MEM_ALLOC_FAILED;
ps_create_op->s_ivd_create_op_t.u4_error_code = 1 << IVD_FATALERROR;
return IV_FAIL;
}
return IV_SUCCESS;
}
/*****************************************************************************/
/* */
/* Function Name : ih264d_map_error */
/* */
/* Description : Maps error codes to IVD error groups */
/* */
/* Inputs : */
/* Globals : <Does it use any global variables?> */
/* Outputs : */
/* Returns : void */
/* */
/* Issues : none */
/* */
/* Revision History: */
/* */
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
/* 22 10 2008 100356 Draft */
/* */
/*****************************************************************************/
UWORD32 ih264d_map_error(UWORD32 i4_err_status)
{
UWORD32 temp = 0;
switch(i4_err_status)
{
case ERROR_MEM_ALLOC_ISRAM_T:
case ERROR_MEM_ALLOC_SDRAM_T:
case ERROR_BUF_MGR:
case ERROR_MB_GROUP_ASSGN_T:
case ERROR_FRAME_LIMIT_OVER:
case ERROR_ACTUAL_RESOLUTION_GREATER_THAN_INIT:
case ERROR_PROFILE_NOT_SUPPORTED:
case ERROR_INIT_NOT_DONE:
case IVD_MEM_ALLOC_FAILED:
temp = 1 << IVD_FATALERROR;
H264_DEC_DEBUG_PRINT("\nFatal Error\n");
break;
case ERROR_DBP_MANAGER_T:
case ERROR_GAPS_IN_FRM_NUM:
case ERROR_UNKNOWN_NAL:
case ERROR_INV_MB_SLC_GRP_T:
case ERROR_MULTIPLE_SLC_GRP_T:
case ERROR_UNKNOWN_LEVEL:
case ERROR_UNAVAIL_PICBUF_T:
case ERROR_UNAVAIL_MVBUF_T:
case ERROR_UNAVAIL_DISPBUF_T:
case ERROR_NUM_REF:
case ERROR_REFIDX_ORDER_T:
case ERROR_PIC0_NOT_FOUND_T:
case ERROR_MB_TYPE:
case ERROR_SUB_MB_TYPE:
case ERROR_CBP:
case ERROR_REF_IDX:
case ERROR_NUM_MV:
case ERROR_CHROMA_PRED_MODE:
case ERROR_INTRAPRED:
case ERROR_NEXT_MB_ADDRESS_T:
case ERROR_MB_ADDRESS_T:
case ERROR_PIC1_NOT_FOUND_T:
case ERROR_CAVLC_NUM_COEFF_T:
case ERROR_CAVLC_SCAN_POS_T:
case ERROR_PRED_WEIGHT_TABLE_T:
case ERROR_CORRUPTED_SLICE:
temp = 1 << IVD_CORRUPTEDDATA;
break;
case ERROR_NOT_SUPP_RESOLUTION:
case ERROR_FEATURE_UNAVAIL:
case ERROR_ACTUAL_LEVEL_GREATER_THAN_INIT:
temp = 1 << IVD_UNSUPPORTEDINPUT;
break;
case ERROR_INVALID_PIC_PARAM:
case ERROR_INVALID_SEQ_PARAM:
case ERROR_EGC_EXCEED_32_1_T:
case ERROR_EGC_EXCEED_32_2_T:
case ERROR_INV_RANGE_TEV_T:
case ERROR_INV_SLC_TYPE_T:
case ERROR_INV_POC_TYPE_T:
case ERROR_INV_RANGE_QP_T:
case ERROR_INV_SPS_PPS_T:
case ERROR_INV_SLICE_HDR_T:
temp = 1 << IVD_CORRUPTEDHEADER;
break;
case ERROR_EOB_FLUSHBITS_T:
case ERROR_EOB_GETBITS_T:
case ERROR_EOB_GETBIT_T:
case ERROR_EOB_BYPASS_T:
case ERROR_EOB_DECISION_T:
case ERROR_EOB_TERMINATE_T:
case ERROR_EOB_READCOEFF4X4CAB_T:
temp = 1 << IVD_INSUFFICIENTDATA;
break;
case ERROR_DYNAMIC_RESOLUTION_NOT_SUPPORTED:
case ERROR_DISP_WIDTH_RESET_TO_PIC_WIDTH:
temp = 1 << IVD_UNSUPPORTEDPARAM | 1 << IVD_FATALERROR;
break;
case ERROR_DANGLING_FIELD_IN_PIC:
temp = 1 << IVD_APPLIEDCONCEALMENT;
break;
}
return temp;
}
UWORD32 ih264d_get_outbuf_size(WORD32 pic_wd,
UWORD32 pic_ht,
UWORD8 u1_chroma_format,
UWORD32 *p_buf_size)
{
UWORD32 u4_min_num_out_bufs = 0;
if(u1_chroma_format == IV_YUV_420P)
u4_min_num_out_bufs = MIN_OUT_BUFS_420;
else if(u1_chroma_format == IV_YUV_422ILE)
u4_min_num_out_bufs = MIN_OUT_BUFS_422ILE;
else if(u1_chroma_format == IV_RGB_565)
u4_min_num_out_bufs = MIN_OUT_BUFS_RGB565;
else if((u1_chroma_format == IV_YUV_420SP_UV)
|| (u1_chroma_format == IV_YUV_420SP_VU))
u4_min_num_out_bufs = MIN_OUT_BUFS_420SP;
if(u1_chroma_format == IV_YUV_420P)
{
p_buf_size[0] = (pic_wd * pic_ht);
p_buf_size[1] = (pic_wd * pic_ht) >> 2;
p_buf_size[2] = (pic_wd * pic_ht) >> 2;
}
else if(u1_chroma_format == IV_YUV_422ILE)
{
p_buf_size[0] = (pic_wd * pic_ht) * 2;
p_buf_size[1] = p_buf_size[2] = 0;
}
else if(u1_chroma_format == IV_RGB_565)
{
p_buf_size[0] = (pic_wd * pic_ht) * 2;
p_buf_size[1] = p_buf_size[2] = 0;
}
else if((u1_chroma_format == IV_YUV_420SP_UV)
|| (u1_chroma_format == IV_YUV_420SP_VU))
{
p_buf_size[0] = (pic_wd * pic_ht);
p_buf_size[1] = (pic_wd * pic_ht) >> 1;
p_buf_size[2] = 0;
}
return u4_min_num_out_bufs;
}
WORD32 check_app_out_buf_size(dec_struct_t *ps_dec)
{
UWORD32 au4_min_out_buf_size[IVD_VIDDEC_MAX_IO_BUFFERS];
UWORD32 u4_min_num_out_bufs, i;
UWORD32 pic_wd, pic_ht;
if(0 == ps_dec->u4_share_disp_buf)
{
pic_wd = ps_dec->u2_disp_width;
pic_ht = ps_dec->u2_disp_height;
}
else
{
pic_wd = ps_dec->u2_frm_wd_y;
pic_ht = ps_dec->u2_frm_ht_y;
}
if(ps_dec->u4_app_disp_width > pic_wd)
pic_wd = ps_dec->u4_app_disp_width;
u4_min_num_out_bufs = ih264d_get_outbuf_size(pic_wd, pic_ht,
ps_dec->u1_chroma_format,
&au4_min_out_buf_size[0]);
if(0 == ps_dec->u4_share_disp_buf)
{
if(ps_dec->ps_out_buffer->u4_num_bufs < u4_min_num_out_bufs)
return IV_FAIL;
for(i = 0; i < u4_min_num_out_bufs; i++)
{
if(ps_dec->ps_out_buffer->u4_min_out_buf_size[i]
< au4_min_out_buf_size[i])
return (IV_FAIL);
}
}
else
{
if(ps_dec->disp_bufs[0].u4_num_bufs < u4_min_num_out_bufs)
return IV_FAIL;
for(i = 0; i < u4_min_num_out_bufs; i++)
{
/* We need to check only with the disp_buffer[0], because we have
* already ensured that all the buffers are of the same size in
* ih264d_set_display_frame.
*/
if(ps_dec->disp_bufs[0].u4_bufsize[i] < au4_min_out_buf_size[i])
return (IV_FAIL);
}
}
return (IV_SUCCESS);
}
/*****************************************************************************/
/* */
/* Function Name : ih264d_video_decode */
/* */
/* Description : handle video decode API command */
/* */
/* Inputs :iv_obj_t decoder handle */
/* :pv_api_ip pointer to input structure */
/* :pv_api_op pointer to output structure */
/* Outputs : */
/* Returns : void */
/* */
/* Issues : none */
/* */
/* Revision History: */
/* */
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
/* 22 10 2008 100356 Draft */
/* */
/*****************************************************************************/
WORD32 ih264d_video_decode(iv_obj_t *dec_hdl, void *pv_api_ip, void *pv_api_op)
{
/* ! */
dec_struct_t * ps_dec = (dec_struct_t *)(dec_hdl->pv_codec_handle);
WORD32 i4_err_status = 0;
UWORD8 *pu1_buf = NULL;
WORD32 buflen;
UWORD32 u4_max_ofst, u4_length_of_start_code = 0;
UWORD32 bytes_consumed = 0;
UWORD32 cur_slice_is_nonref = 0;
UWORD32 u4_next_is_aud;
UWORD32 u4_first_start_code_found = 0;
WORD32 ret = 0,api_ret_value = IV_SUCCESS;
WORD32 header_data_left = 0,frame_data_left = 0;
UWORD8 *pu1_bitstrm_buf;
ivd_video_decode_ip_t *ps_dec_ip;
ivd_video_decode_op_t *ps_dec_op;
ithread_set_name((void*)"Parse_thread");
ps_dec_ip = (ivd_video_decode_ip_t *)pv_api_ip;
ps_dec_op = (ivd_video_decode_op_t *)pv_api_op;
{
UWORD32 u4_size;
u4_size = ps_dec_op->u4_size;
memset(ps_dec_op, 0, sizeof(ivd_video_decode_op_t));
ps_dec_op->u4_size = u4_size;
}
ps_dec->pv_dec_out = ps_dec_op;
if(ps_dec->init_done != 1)
{
return IV_FAIL;
}
/*Data memory barries instruction,so that bitstream write by the application is complete*/
DATA_SYNC();
if(0 == ps_dec->u1_flushfrm)
{
if(ps_dec_ip->pv_stream_buffer == NULL)
{
ps_dec_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM;
ps_dec_op->u4_error_code |= IVD_DEC_FRM_BS_BUF_NULL;
return IV_FAIL;
}
if(ps_dec_ip->u4_num_Bytes <= 0)
{
ps_dec_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM;
ps_dec_op->u4_error_code |= IVD_DEC_NUMBYTES_INV;
return IV_FAIL;
}
}
ps_dec->u1_pic_decode_done = 0;
ps_dec_op->u4_num_bytes_consumed = 0;
ps_dec->ps_out_buffer = NULL;
if(ps_dec_ip->u4_size
>= offsetof(ivd_video_decode_ip_t, s_out_buffer))
ps_dec->ps_out_buffer = &ps_dec_ip->s_out_buffer;
ps_dec->u4_fmt_conv_cur_row = 0;
ps_dec->u4_output_present = 0;
ps_dec->s_disp_op.u4_error_code = 1;
ps_dec->u4_fmt_conv_num_rows = FMT_CONV_NUM_ROWS;
if(0 == ps_dec->u4_share_disp_buf
&& ps_dec->i4_decode_header == 0)
{
UWORD32 i;
if((ps_dec->ps_out_buffer->u4_num_bufs == 0) ||
(ps_dec->ps_out_buffer->u4_num_bufs > IVD_VIDDEC_MAX_IO_BUFFERS))
{
ps_dec_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM;
ps_dec_op->u4_error_code |= IVD_DISP_FRM_ZERO_OP_BUFS;
return IV_FAIL;
}
for(i = 0; i < ps_dec->ps_out_buffer->u4_num_bufs; i++)
{
if(ps_dec->ps_out_buffer->pu1_bufs[i] == NULL)
{
ps_dec_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM;
ps_dec_op->u4_error_code |= IVD_DISP_FRM_OP_BUF_NULL;
return IV_FAIL;
}
if(ps_dec->ps_out_buffer->u4_min_out_buf_size[i] == 0)
{
ps_dec_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM;
ps_dec_op->u4_error_code |=
IVD_DISP_FRM_ZERO_OP_BUF_SIZE;
return IV_FAIL;
}
}
}
if(ps_dec->u4_total_frames_decoded >= NUM_FRAMES_LIMIT)
{
ps_dec_op->u4_error_code = ERROR_FRAME_LIMIT_OVER;
return IV_FAIL;
}
/* ! */
ps_dec->u4_ts = ps_dec_ip->u4_ts;
ps_dec_op->u4_error_code = 0;
ps_dec_op->e_pic_type = -1;
ps_dec_op->u4_output_present = 0;
ps_dec_op->u4_frame_decoded_flag = 0;
ps_dec->i4_frametype = -1;
ps_dec->i4_content_type = -1;
ps_dec->u4_slice_start_code_found = 0;
/* In case the deocder is not in flush mode(in shared mode),
then decoder has to pick up a buffer to write current frame.
Check if a frame is available in such cases */
if(ps_dec->u1_init_dec_flag == 1 && ps_dec->u4_share_disp_buf == 1
&& ps_dec->u1_flushfrm == 0)
{
UWORD32 i;
WORD32 disp_avail = 0, free_id;
/* Check if at least one buffer is available with the codec */
/* If not then return to application with error */
for(i = 0; i < ps_dec->u1_pic_bufs; i++)
{
if(0 == ps_dec->u4_disp_buf_mapping[i]
|| 1 == ps_dec->u4_disp_buf_to_be_freed[i])
{
disp_avail = 1;
break;
}
}
if(0 == disp_avail)
{
/* If something is queued for display wait for that buffer to be returned */
ps_dec_op->u4_error_code = IVD_DEC_REF_BUF_NULL;
ps_dec_op->u4_error_code |= (1 << IVD_UNSUPPORTEDPARAM);
return (IV_FAIL);
}
while(1)
{
pic_buffer_t *ps_pic_buf;
ps_pic_buf = (pic_buffer_t *)ih264_buf_mgr_get_next_free(
(buf_mgr_t *)ps_dec->pv_pic_buf_mgr, &free_id);
if(ps_pic_buf == NULL)
{
UWORD32 i, display_queued = 0;
/* check if any buffer was given for display which is not returned yet */
for(i = 0; i < (MAX_DISP_BUFS_NEW); i++)
{
if(0 != ps_dec->u4_disp_buf_mapping[i])
{
display_queued = 1;
break;
}
}
/* If some buffer is queued for display, then codec has to singal an error and wait
for that buffer to be returned.
If nothing is queued for display then codec has ownership of all display buffers
and it can reuse any of the existing buffers and continue decoding */
if(1 == display_queued)
{
/* If something is queued for display wait for that buffer to be returned */
ps_dec_op->u4_error_code = IVD_DEC_REF_BUF_NULL;
ps_dec_op->u4_error_code |= (1
<< IVD_UNSUPPORTEDPARAM);
return (IV_FAIL);
}
}
else
{
/* If the buffer is with display, then mark it as in use and then look for a buffer again */
if(1 == ps_dec->u4_disp_buf_mapping[free_id])
{
ih264_buf_mgr_set_status(
(buf_mgr_t *)ps_dec->pv_pic_buf_mgr,
free_id,
BUF_MGR_IO);
}
else
{
/**
* Found a free buffer for present call. Release it now.
* Will be again obtained later.
*/
ih264_buf_mgr_release((buf_mgr_t *)ps_dec->pv_pic_buf_mgr,
free_id,
BUF_MGR_IO);
break;
}
}
}
}
if(ps_dec->u1_flushfrm)
{
if(ps_dec->u1_init_dec_flag == 0)
{
/*Come out of flush mode and return*/
ps_dec->u1_flushfrm = 0;
return (IV_FAIL);
}
ih264d_get_next_display_field(ps_dec, ps_dec->ps_out_buffer,
&(ps_dec->s_disp_op));
if(0 == ps_dec->s_disp_op.u4_error_code)
{
/* check output buffer size given by the application */
if(check_app_out_buf_size(ps_dec) != IV_SUCCESS)
{
ps_dec_op->u4_error_code= IVD_DISP_FRM_ZERO_OP_BUF_SIZE;
return (IV_FAIL);
}
ps_dec->u4_fmt_conv_cur_row = 0;
ps_dec->u4_fmt_conv_num_rows = ps_dec->s_disp_frame_info.u4_y_ht;
ih264d_format_convert(ps_dec, &(ps_dec->s_disp_op),
ps_dec->u4_fmt_conv_cur_row,
ps_dec->u4_fmt_conv_num_rows);
ps_dec->u4_fmt_conv_cur_row += ps_dec->u4_fmt_conv_num_rows;
ps_dec->u4_output_present = 1;
}
ih264d_release_display_field(ps_dec, &(ps_dec->s_disp_op));
ps_dec_op->u4_pic_wd = (UWORD32)ps_dec->u2_disp_width;
ps_dec_op->u4_pic_ht = (UWORD32)ps_dec->u2_disp_height;
ps_dec_op->u4_new_seq = 0;
ps_dec_op->u4_output_present = ps_dec->u4_output_present;
ps_dec_op->u4_progressive_frame_flag =
ps_dec->s_disp_op.u4_progressive_frame_flag;
ps_dec_op->e_output_format =
ps_dec->s_disp_op.e_output_format;
ps_dec_op->s_disp_frm_buf = ps_dec->s_disp_op.s_disp_frm_buf;
ps_dec_op->e4_fld_type = ps_dec->s_disp_op.e4_fld_type;
ps_dec_op->u4_ts = ps_dec->s_disp_op.u4_ts;
ps_dec_op->u4_disp_buf_id = ps_dec->s_disp_op.u4_disp_buf_id;
/*In the case of flush ,since no frame is decoded set pic type as invalid*/
ps_dec_op->u4_is_ref_flag = -1;
ps_dec_op->e_pic_type = IV_NA_FRAME;
ps_dec_op->u4_frame_decoded_flag = 0;
if(0 == ps_dec->s_disp_op.u4_error_code)
{
return (IV_SUCCESS);
}
else
return (IV_FAIL);
}
if(ps_dec->u1_res_changed == 1)
{
/*if resolution has changed and all buffers have been flushed, reset decoder*/
ih264d_init_decoder(ps_dec);
}
ps_dec->u4_prev_nal_skipped = 0;
ps_dec->u2_cur_mb_addr = 0;
ps_dec->u2_total_mbs_coded = 0;
ps_dec->u2_cur_slice_num = 0;
ps_dec->cur_dec_mb_num = 0;
ps_dec->cur_recon_mb_num = 0;
ps_dec->u4_first_slice_in_pic = 1;
ps_dec->u1_slice_header_done = 0;
ps_dec->u1_dangling_field = 0;
ps_dec->u4_dec_thread_created = 0;
ps_dec->u4_bs_deblk_thread_created = 0;
ps_dec->u4_cur_bs_mb_num = 0;
ps_dec->u4_start_recon_deblk = 0;
ps_dec->u4_sps_cnt_in_process = 0;
DEBUG_THREADS_PRINTF(" Starting process call\n");
ps_dec->u4_pic_buf_got = 0;
do
{
WORD32 buf_size;
pu1_buf = (UWORD8*)ps_dec_ip->pv_stream_buffer
+ ps_dec_op->u4_num_bytes_consumed;
u4_max_ofst = ps_dec_ip->u4_num_Bytes
- ps_dec_op->u4_num_bytes_consumed;
/* If dynamic bitstream buffer is not allocated and
* header decode is done, then allocate dynamic bitstream buffer
*/
if((NULL == ps_dec->pu1_bits_buf_dynamic) &&
(ps_dec->i4_header_decoded & 1))
{
WORD32 size;
void *pv_buf;
void *pv_mem_ctxt = ps_dec->pv_mem_ctxt;
size = MAX(256000, ps_dec->u2_pic_wd * ps_dec->u2_pic_ht * 3 / 2);
pv_buf = ps_dec->pf_aligned_alloc(pv_mem_ctxt, 128,
size + EXTRA_BS_OFFSET);
RETURN_IF((NULL == pv_buf), IV_FAIL);
ps_dec->pu1_bits_buf_dynamic = pv_buf;
ps_dec->u4_dynamic_bits_buf_size = size;
}
if(ps_dec->pu1_bits_buf_dynamic)
{
pu1_bitstrm_buf = ps_dec->pu1_bits_buf_dynamic;
buf_size = ps_dec->u4_dynamic_bits_buf_size;
}
else
{
pu1_bitstrm_buf = ps_dec->pu1_bits_buf_static;
buf_size = ps_dec->u4_static_bits_buf_size;
}
u4_next_is_aud = 0;
buflen = ih264d_find_start_code(pu1_buf, 0, u4_max_ofst,
&u4_length_of_start_code,
&u4_next_is_aud);
if(buflen == -1)
buflen = 0;
/* Ignore bytes beyond the allocated size of intermediate buffer */
/* Since 8 bytes are read ahead, ensure 8 bytes are free at the
end of the buffer, which will be memset to 0 after emulation prevention */
buflen = MIN(buflen, buf_size - 8);
bytes_consumed = buflen + u4_length_of_start_code;
ps_dec_op->u4_num_bytes_consumed += bytes_consumed;
{
UWORD8 u1_firstbyte, u1_nal_ref_idc;
if(ps_dec->i4_app_skip_mode == IVD_SKIP_B)
{
u1_firstbyte = *(pu1_buf + u4_length_of_start_code);
u1_nal_ref_idc = (UWORD8)(NAL_REF_IDC(u1_firstbyte));
if(u1_nal_ref_idc == 0)
{
/*skip non reference frames*/
cur_slice_is_nonref = 1;
continue;
}
else
{
if(1 == cur_slice_is_nonref)
{
/*We have encountered a referenced frame,return to app*/
ps_dec_op->u4_num_bytes_consumed -=
bytes_consumed;
ps_dec_op->e_pic_type = IV_B_FRAME;
ps_dec_op->u4_error_code =
IVD_DEC_FRM_SKIPPED;
ps_dec_op->u4_error_code |= (1
<< IVD_UNSUPPORTEDPARAM);
ps_dec_op->u4_frame_decoded_flag = 0;
ps_dec_op->u4_size =
sizeof(ivd_video_decode_op_t);
/*signal the decode thread*/
ih264d_signal_decode_thread(ps_dec);
/* close deblock thread if it is not closed yet*/
if(ps_dec->u4_num_cores == 3)
{
ih264d_signal_bs_deblk_thread(ps_dec);
}
return (IV_FAIL);
}
}
}
}
if(buflen)
{
memcpy(pu1_bitstrm_buf, pu1_buf + u4_length_of_start_code,
buflen);
/* Decoder may read extra 8 bytes near end of the frame */
if((buflen + 8) < buf_size)
{
memset(pu1_bitstrm_buf + buflen, 0, 8);
}
u4_first_start_code_found = 1;
}
else
{
/*start code not found*/
if(u4_first_start_code_found == 0)
{
/*no start codes found in current process call*/
ps_dec->i4_error_code = ERROR_START_CODE_NOT_FOUND;
ps_dec_op->u4_error_code |= 1 << IVD_INSUFFICIENTDATA;
if(ps_dec->u4_pic_buf_got == 0)
{
ih264d_fill_output_struct_from_context(ps_dec,
ps_dec_op);
ps_dec_op->u4_error_code = ps_dec->i4_error_code;
ps_dec_op->u4_frame_decoded_flag = 0;
return (IV_FAIL);
}
else
{
ps_dec->u1_pic_decode_done = 1;
continue;
}
}
else
{
/* a start code has already been found earlier in the same process call*/
frame_data_left = 0;
header_data_left = 0;
continue;
}
}
ps_dec->u4_return_to_app = 0;
ret = ih264d_parse_nal_unit(dec_hdl, ps_dec_op,
pu1_bitstrm_buf, buflen);
if(ret != OK)
{
UWORD32 error = ih264d_map_error(ret);
ps_dec_op->u4_error_code = error | ret;
api_ret_value = IV_FAIL;
if((ret == IVD_RES_CHANGED)
|| (ret == IVD_MEM_ALLOC_FAILED)
|| (ret == ERROR_UNAVAIL_PICBUF_T)
|| (ret == ERROR_UNAVAIL_MVBUF_T)
|| (ret == ERROR_INV_SPS_PPS_T)
|| (ret == IVD_DISP_FRM_ZERO_OP_BUF_SIZE))
{
ps_dec->u4_slice_start_code_found = 0;
break;
}
if((ret == ERROR_INCOMPLETE_FRAME) || (ret == ERROR_DANGLING_FIELD_IN_PIC))
{
ps_dec_op->u4_num_bytes_consumed -= bytes_consumed;
api_ret_value = IV_FAIL;
break;
}
if(ret == ERROR_IN_LAST_SLICE_OF_PIC)
{
api_ret_value = IV_FAIL;
break;
}
}
if(ps_dec->u4_return_to_app)
{
/*We have encountered a referenced frame,return to app*/
ps_dec_op->u4_num_bytes_consumed -= bytes_consumed;
ps_dec_op->u4_error_code = IVD_DEC_FRM_SKIPPED;
ps_dec_op->u4_error_code |= (1 << IVD_UNSUPPORTEDPARAM);
ps_dec_op->u4_frame_decoded_flag = 0;
ps_dec_op->u4_size = sizeof(ivd_video_decode_op_t);
/*signal the decode thread*/
ih264d_signal_decode_thread(ps_dec);
/* close deblock thread if it is not closed yet*/
if(ps_dec->u4_num_cores == 3)
{
ih264d_signal_bs_deblk_thread(ps_dec);
}
return (IV_FAIL);
}
header_data_left = ((ps_dec->i4_decode_header == 1)
&& (ps_dec->i4_header_decoded != 3)
&& (ps_dec_op->u4_num_bytes_consumed
< ps_dec_ip->u4_num_Bytes));
frame_data_left = (((ps_dec->i4_decode_header == 0)
&& ((ps_dec->u1_pic_decode_done == 0)
|| (u4_next_is_aud == 1)))
&& (ps_dec_op->u4_num_bytes_consumed
< ps_dec_ip->u4_num_Bytes));
}
while(( header_data_left == 1)||(frame_data_left == 1));
if((ps_dec->u4_pic_buf_got == 1)
&& (ret != IVD_MEM_ALLOC_FAILED)
&& ps_dec->u2_total_mbs_coded < ps_dec->u2_frm_ht_in_mbs * ps_dec->u2_frm_wd_in_mbs)
{
// last slice - missing/corruption
WORD32 num_mb_skipped;
WORD32 prev_slice_err;
pocstruct_t temp_poc;
WORD32 ret1;
WORD32 ht_in_mbs;
ht_in_mbs = ps_dec->u2_pic_ht >> (4 + ps_dec->ps_cur_slice->u1_field_pic_flag);
num_mb_skipped = (ht_in_mbs * ps_dec->u2_frm_wd_in_mbs)
- ps_dec->u2_total_mbs_coded;
if(ps_dec->u4_first_slice_in_pic && (ps_dec->u4_pic_buf_got == 0))
prev_slice_err = 1;
else
prev_slice_err = 2;
if(ps_dec->u4_first_slice_in_pic && (ps_dec->u2_total_mbs_coded == 0))
prev_slice_err = 1;
ret1 = ih264d_mark_err_slice_skip(ps_dec, num_mb_skipped, ps_dec->u1_nal_unit_type == IDR_SLICE_NAL, ps_dec->ps_cur_slice->u2_frame_num,
&temp_poc, prev_slice_err);
if((ret1 == ERROR_UNAVAIL_PICBUF_T) || (ret1 == ERROR_UNAVAIL_MVBUF_T) ||
(ret1 == ERROR_INV_SPS_PPS_T))
{
ret = ret1;
}
}
if((ret == IVD_RES_CHANGED)
|| (ret == IVD_MEM_ALLOC_FAILED)
|| (ret == ERROR_UNAVAIL_PICBUF_T)
|| (ret == ERROR_UNAVAIL_MVBUF_T)
|| (ret == ERROR_INV_SPS_PPS_T))
{
/* signal the decode thread */
ih264d_signal_decode_thread(ps_dec);
/* close deblock thread if it is not closed yet */
if(ps_dec->u4_num_cores == 3)
{
ih264d_signal_bs_deblk_thread(ps_dec);
}
/* dont consume bitstream for change in resolution case */
if(ret == IVD_RES_CHANGED)
{
ps_dec_op->u4_num_bytes_consumed -= bytes_consumed;
}
return IV_FAIL;
}
if(ps_dec->u1_separate_parse)
{
/* If Format conversion is not complete,
complete it here */
if(ps_dec->u4_num_cores == 2)
{
/*do deblocking of all mbs*/
if((ps_dec->u4_nmb_deblk == 0) &&(ps_dec->u4_start_recon_deblk == 1) && (ps_dec->ps_cur_sps->u1_mb_aff_flag == 0))
{
UWORD32 u4_num_mbs,u4_max_addr;
tfr_ctxt_t s_tfr_ctxt;
tfr_ctxt_t *ps_tfr_cxt = &s_tfr_ctxt;
pad_mgr_t *ps_pad_mgr = &ps_dec->s_pad_mgr;
/*BS is done for all mbs while parsing*/
u4_max_addr = (ps_dec->u2_frm_wd_in_mbs * ps_dec->u2_frm_ht_in_mbs) - 1;
ps_dec->u4_cur_bs_mb_num = u4_max_addr + 1;
ih264d_init_deblk_tfr_ctxt(ps_dec, ps_pad_mgr, ps_tfr_cxt,
ps_dec->u2_frm_wd_in_mbs, 0);
u4_num_mbs = u4_max_addr
- ps_dec->u4_cur_deblk_mb_num + 1;
DEBUG_PERF_PRINTF("mbs left for deblocking= %d \n",u4_num_mbs);
if(u4_num_mbs != 0)
ih264d_check_mb_map_deblk(ps_dec, u4_num_mbs,
ps_tfr_cxt,1);
ps_dec->u4_start_recon_deblk = 0;
}
}
/*signal the decode thread*/
ih264d_signal_decode_thread(ps_dec);
/* close deblock thread if it is not closed yet*/
if(ps_dec->u4_num_cores == 3)
{
ih264d_signal_bs_deblk_thread(ps_dec);
}
}
DATA_SYNC();
if((ps_dec_op->u4_error_code & 0xff)
!= ERROR_DYNAMIC_RESOLUTION_NOT_SUPPORTED)
{
ps_dec_op->u4_pic_wd = (UWORD32)ps_dec->u2_disp_width;
ps_dec_op->u4_pic_ht = (UWORD32)ps_dec->u2_disp_height;
}
//Report if header (sps and pps) has not been decoded yet
if(ps_dec->i4_header_decoded != 3)
{
ps_dec_op->u4_error_code |= (1 << IVD_INSUFFICIENTDATA);
}
if(ps_dec->i4_decode_header == 1 && ps_dec->i4_header_decoded != 3)
{
ps_dec_op->u4_error_code |= (1 << IVD_INSUFFICIENTDATA);
}
if(ps_dec->u4_prev_nal_skipped)
{
/*We have encountered a referenced frame,return to app*/
ps_dec_op->u4_error_code = IVD_DEC_FRM_SKIPPED;
ps_dec_op->u4_error_code |= (1 << IVD_UNSUPPORTEDPARAM);
ps_dec_op->u4_frame_decoded_flag = 0;
ps_dec_op->u4_size = sizeof(ivd_video_decode_op_t);
/* close deblock thread if it is not closed yet*/
if(ps_dec->u4_num_cores == 3)
{
ih264d_signal_bs_deblk_thread(ps_dec);
}
return (IV_FAIL);
}
if((ps_dec->u4_pic_buf_got == 1)
&& (ERROR_DANGLING_FIELD_IN_PIC != i4_err_status))
{
/*
* For field pictures, set the bottom and top picture decoded u4_flag correctly.
*/
if(ps_dec->ps_cur_slice->u1_field_pic_flag)
{
if(1 == ps_dec->ps_cur_slice->u1_bottom_field_flag)
{
ps_dec->u1_top_bottom_decoded |= BOT_FIELD_ONLY;
}
else
{
ps_dec->u1_top_bottom_decoded |= TOP_FIELD_ONLY;
}
}
else
{
ps_dec->u1_top_bottom_decoded = TOP_FIELD_ONLY | BOT_FIELD_ONLY;
}
/* if new frame in not found (if we are still getting slices from previous frame)
* ih264d_deblock_display is not called. Such frames will not be added to reference /display
*/
if ((ps_dec->ps_dec_err_status->u1_err_flag & REJECT_CUR_PIC) == 0)
{
/* Calling Function to deblock Picture and Display */
ret = ih264d_deblock_display(ps_dec);
}
/*set to complete ,as we dont support partial frame decode*/
if(ps_dec->i4_header_decoded == 3)
{
ps_dec->u2_total_mbs_coded = ps_dec->ps_cur_sps->u2_max_mb_addr + 1;
}
/*Update the i4_frametype at the end of picture*/
if(ps_dec->ps_cur_slice->u1_nal_unit_type == IDR_SLICE_NAL)
{
ps_dec->i4_frametype = IV_IDR_FRAME;
}
else if(ps_dec->i4_pic_type == B_SLICE)
{
ps_dec->i4_frametype = IV_B_FRAME;
}
else if(ps_dec->i4_pic_type == P_SLICE)
{
ps_dec->i4_frametype = IV_P_FRAME;
}
else if(ps_dec->i4_pic_type == I_SLICE)
{
ps_dec->i4_frametype = IV_I_FRAME;
}
else
{
H264_DEC_DEBUG_PRINT("Shouldn't come here\n");
}
//Update the content type
ps_dec->i4_content_type = ps_dec->ps_cur_slice->u1_field_pic_flag;
ps_dec->u4_total_frames_decoded = ps_dec->u4_total_frames_decoded + 2;
ps_dec->u4_total_frames_decoded = ps_dec->u4_total_frames_decoded
- ps_dec->ps_cur_slice->u1_field_pic_flag;
}
/* close deblock thread if it is not closed yet*/
if(ps_dec->u4_num_cores == 3)
{
ih264d_signal_bs_deblk_thread(ps_dec);
}
{
/* In case the decoder is configured to run in low delay mode,
* then get display buffer and then format convert.
* Note in this mode, format conversion does not run paralelly in a thread and adds to the codec cycles
*/
if((IVD_DECODE_FRAME_OUT == ps_dec->e_frm_out_mode)
&& ps_dec->u1_init_dec_flag)
{
ih264d_get_next_display_field(ps_dec, ps_dec->ps_out_buffer,
&(ps_dec->s_disp_op));
if(0 == ps_dec->s_disp_op.u4_error_code)
{
ps_dec->u4_fmt_conv_cur_row = 0;
ps_dec->u4_output_present = 1;
}
}
ih264d_fill_output_struct_from_context(ps_dec, ps_dec_op);
/* If Format conversion is not complete,
complete it here */
if(ps_dec->u4_output_present &&
(ps_dec->u4_fmt_conv_cur_row < ps_dec->s_disp_frame_info.u4_y_ht))
{
ps_dec->u4_fmt_conv_num_rows = ps_dec->s_disp_frame_info.u4_y_ht
- ps_dec->u4_fmt_conv_cur_row;
ih264d_format_convert(ps_dec, &(ps_dec->s_disp_op),
ps_dec->u4_fmt_conv_cur_row,
ps_dec->u4_fmt_conv_num_rows);
ps_dec->u4_fmt_conv_cur_row += ps_dec->u4_fmt_conv_num_rows;
}
ih264d_release_display_field(ps_dec, &(ps_dec->s_disp_op));
}
if(ps_dec->i4_decode_header == 1 && (ps_dec->i4_header_decoded & 1) == 1)
{
ps_dec_op->u4_progressive_frame_flag = 1;
if((NULL != ps_dec->ps_cur_sps) && (1 == (ps_dec->ps_cur_sps->u1_is_valid)))
{
if((0 == ps_dec->ps_sps->u1_frame_mbs_only_flag)
&& (0 == ps_dec->ps_sps->u1_mb_aff_flag))
ps_dec_op->u4_progressive_frame_flag = 0;
}
}
if((TOP_FIELD_ONLY | BOT_FIELD_ONLY) == ps_dec->u1_top_bottom_decoded)
{
ps_dec->u1_top_bottom_decoded = 0;
}
/*--------------------------------------------------------------------*/
/* Do End of Pic processing. */
/* Should be called only if frame was decoded in previous process call*/
/*--------------------------------------------------------------------*/
if(ps_dec->u4_pic_buf_got == 1)
{
if(1 == ps_dec->u1_last_pic_not_decoded)
{
ret = ih264d_end_of_pic_dispbuf_mgr(ps_dec);
if(ret != OK)
return ret;
ret = ih264d_end_of_pic(ps_dec);
if(ret != OK)
return ret;
}
else
{
ret = ih264d_end_of_pic(ps_dec);
if(ret != OK)
return ret;
}
}
/*Data memory barrier instruction,so that yuv write by the library is complete*/
DATA_SYNC();
H264_DEC_DEBUG_PRINT("The num bytes consumed: %d\n",
ps_dec_op->u4_num_bytes_consumed);
return api_ret_value;
}
WORD32 ih264d_get_version(iv_obj_t *dec_hdl, void *pv_api_ip, void *pv_api_op)
{
char version_string[MAXVERSION_STRLEN + 1];
UWORD32 version_string_len;
ivd_ctl_getversioninfo_ip_t *ps_ip;
ivd_ctl_getversioninfo_op_t *ps_op;
ps_ip = (ivd_ctl_getversioninfo_ip_t *)pv_api_ip;
ps_op = (ivd_ctl_getversioninfo_op_t *)pv_api_op;
UNUSED(dec_hdl);
ps_op->u4_error_code = IV_SUCCESS;
VERSION(version_string, CODEC_NAME, CODEC_RELEASE_TYPE, CODEC_RELEASE_VER,
CODEC_VENDOR);
if((WORD32)ps_ip->u4_version_buffer_size <= 0)
{
ps_op->u4_error_code = IH264D_VERS_BUF_INSUFFICIENT;
return (IV_FAIL);
}
version_string_len = strnlen(version_string, MAXVERSION_STRLEN) + 1;
if(ps_ip->u4_version_buffer_size >= version_string_len) //(WORD32)sizeof(sizeof(version_string)))
{
memcpy(ps_ip->pv_version_buffer, version_string, version_string_len);
ps_op->u4_error_code = IV_SUCCESS;
}
else
{
ps_op->u4_error_code = IH264D_VERS_BUF_INSUFFICIENT;
return IV_FAIL;
}
return (IV_SUCCESS);
}
/*****************************************************************************/
/* */
/* Function Name : ih264d_get_display_frame */
/* */
/* Description : */
/* Inputs :iv_obj_t decoder handle */
/* :pv_api_ip pointer to input structure */
/* :pv_api_op pointer to output structure */
/* Outputs : */
/* Returns : void */
/* */
/* Issues : none */
/* */
/* Revision History: */
/* */
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
/* 22 10 2008 100356 Draft */
/* */
/*****************************************************************************/
WORD32 ih264d_get_display_frame(iv_obj_t *dec_hdl,
void *pv_api_ip,
void *pv_api_op)
{
UNUSED(dec_hdl);
UNUSED(pv_api_ip);
UNUSED(pv_api_op);
// This function is no longer needed, output is returned in the process()
return IV_FAIL;
}
/*****************************************************************************/
/* */
/* Function Name : ih264d_set_display_frame */
/* */
/* Description : */
/* */
/* Inputs :iv_obj_t decoder handle */
/* :pv_api_ip pointer to input structure */
/* :pv_api_op pointer to output structure */
/* Outputs : */
/* Returns : void */
/* */
/* Issues : none */
/* */
/* Revision History: */
/* */
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
/* 22 10 2008 100356 Draft */
/* */
/*****************************************************************************/
WORD32 ih264d_set_display_frame(iv_obj_t *dec_hdl,
void *pv_api_ip,
void *pv_api_op)
{
UWORD32 u4_disp_buf_size[3], u4_num_disp_bufs;
ivd_set_display_frame_ip_t *dec_disp_ip;
ivd_set_display_frame_op_t *dec_disp_op;
UWORD32 i;
dec_struct_t * ps_dec = (dec_struct_t *)(dec_hdl->pv_codec_handle);
dec_disp_ip = (ivd_set_display_frame_ip_t *)pv_api_ip;
dec_disp_op = (ivd_set_display_frame_op_t *)pv_api_op;
dec_disp_op->u4_error_code = 0;
ps_dec->u4_num_disp_bufs = 0;
if(ps_dec->u4_share_disp_buf)
{
UWORD32 u4_num_bufs = dec_disp_ip->num_disp_bufs;
u4_num_bufs = MIN(u4_num_bufs, MAX_DISP_BUFS_NEW);
ps_dec->u4_num_disp_bufs = u4_num_bufs;
/* Get the number and sizes of the first buffer. Compare this with the
* rest to make sure all the buffers are of the same size.
*/
u4_num_disp_bufs = dec_disp_ip->s_disp_buffer[0].u4_num_bufs;
u4_disp_buf_size[0] =
dec_disp_ip->s_disp_buffer[0].u4_min_out_buf_size[0];
u4_disp_buf_size[1] =
dec_disp_ip->s_disp_buffer[0].u4_min_out_buf_size[1];
u4_disp_buf_size[2] =
dec_disp_ip->s_disp_buffer[0].u4_min_out_buf_size[2];
for(i = 0; i < u4_num_bufs; i++)
{
if(dec_disp_ip->s_disp_buffer[i].u4_num_bufs != u4_num_disp_bufs)
{
return IV_FAIL;
}
if((dec_disp_ip->s_disp_buffer[i].u4_min_out_buf_size[0]
!= u4_disp_buf_size[0])
|| (dec_disp_ip->s_disp_buffer[i].u4_min_out_buf_size[1]
!= u4_disp_buf_size[1])
|| (dec_disp_ip->s_disp_buffer[i].u4_min_out_buf_size[2]
!= u4_disp_buf_size[2]))
{
return IV_FAIL;
}
ps_dec->disp_bufs[i].u4_num_bufs =
dec_disp_ip->s_disp_buffer[i].u4_num_bufs;
ps_dec->disp_bufs[i].buf[0] =
dec_disp_ip->s_disp_buffer[i].pu1_bufs[0];
ps_dec->disp_bufs[i].buf[1] =
dec_disp_ip->s_disp_buffer[i].pu1_bufs[1];
ps_dec->disp_bufs[i].buf[2] =
dec_disp_ip->s_disp_buffer[i].pu1_bufs[2];
ps_dec->disp_bufs[i].u4_bufsize[0] =
dec_disp_ip->s_disp_buffer[i].u4_min_out_buf_size[0];
ps_dec->disp_bufs[i].u4_bufsize[1] =
dec_disp_ip->s_disp_buffer[i].u4_min_out_buf_size[1];
ps_dec->disp_bufs[i].u4_bufsize[2] =
dec_disp_ip->s_disp_buffer[i].u4_min_out_buf_size[2];
}
}
return IV_SUCCESS;
}
/*****************************************************************************/
/* */
/* Function Name : ih264d_set_flush_mode */
/* */
/* Description : */
/* */
/* Inputs :iv_obj_t decoder handle */
/* :pv_api_ip pointer to input structure */
/* :pv_api_op pointer to output structure */
/* Globals : <Does it use any global variables?> */
/* Outputs : */
/* Returns : void */
/* */
/* Issues : none */
/* */
/* Revision History: */
/* */
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
/* 22 10 2008 100356 Draft */
/* */
/*****************************************************************************/
WORD32 ih264d_set_flush_mode(iv_obj_t *dec_hdl, void *pv_api_ip, void *pv_api_op)
{
dec_struct_t * ps_dec;
ivd_ctl_flush_op_t *ps_ctl_op = (ivd_ctl_flush_op_t*)pv_api_op;
ps_ctl_op->u4_error_code = 0;
ps_dec = (dec_struct_t *)(dec_hdl->pv_codec_handle);
UNUSED(pv_api_ip);
/* ! */
/* Signal flush frame control call */
ps_dec->u1_flushfrm = 1;
if(ps_dec->u1_init_dec_flag == 1)
{
ih264d_release_pics_in_dpb((void *)ps_dec, ps_dec->u1_pic_bufs);
ih264d_release_display_bufs(ps_dec);
}
ps_ctl_op->u4_error_code = 0;
/* Ignore dangling fields during flush */
ps_dec->u1_top_bottom_decoded = 0;
return IV_SUCCESS;
}
/*****************************************************************************/
/* */
/* Function Name : ih264d_get_status */
/* */
/* Description : */
/* */
/* Inputs :iv_obj_t decoder handle */
/* :pv_api_ip pointer to input structure */
/* :pv_api_op pointer to output structure */
/* Globals : <Does it use any global variables?> */
/* Outputs : */
/* Returns : void */
/* */
/* Issues : none */
/* */
/* Revision History: */
/* */
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
/* 22 10 2008 100356 Draft */
/* */
/*****************************************************************************/
WORD32 ih264d_get_status(iv_obj_t *dec_hdl, void *pv_api_ip, void *pv_api_op)
{
UWORD32 i;
dec_struct_t * ps_dec;
UWORD32 pic_wd, pic_ht;
ivd_ctl_getstatus_op_t *ps_ctl_op = (ivd_ctl_getstatus_op_t*)pv_api_op;
UNUSED(pv_api_ip);
ps_ctl_op->u4_error_code = 0;
ps_dec = (dec_struct_t *)(dec_hdl->pv_codec_handle);
if((NULL != ps_dec->ps_cur_sps) && (1 == (ps_dec->ps_cur_sps->u1_is_valid)))
{
ps_ctl_op->u4_pic_ht = ps_dec->u2_disp_height;
ps_ctl_op->u4_pic_wd = ps_dec->u2_disp_width;
if(0 == ps_dec->u4_share_disp_buf)
{
pic_wd = ps_dec->u2_disp_width;
pic_ht = ps_dec->u2_disp_height;
}
else
{
pic_wd = ps_dec->u2_frm_wd_y;
pic_ht = ps_dec->u2_frm_ht_y;
}
}
else
{
pic_wd = 0;
pic_ht = 0;
ps_ctl_op->u4_pic_ht = pic_wd;
ps_ctl_op->u4_pic_wd = pic_ht;
if(1 == ps_dec->u4_share_disp_buf)
{
pic_wd += (PAD_LEN_Y_H << 1);
pic_ht += (PAD_LEN_Y_V << 2);
}
}
if(ps_dec->u4_app_disp_width > pic_wd)
pic_wd = ps_dec->u4_app_disp_width;
if(0 == ps_dec->u4_share_disp_buf)
ps_ctl_op->u4_num_disp_bufs = 1;
else
{
if((NULL != ps_dec->ps_cur_sps) && (1 == (ps_dec->ps_cur_sps->u1_is_valid)))
{
if((ps_dec->ps_cur_sps->u1_vui_parameters_present_flag == 1) &&
(1 == ps_dec->ps_cur_sps->s_vui.u1_bitstream_restriction_flag))
{
ps_ctl_op->u4_num_disp_bufs =
ps_dec->ps_cur_sps->s_vui.u4_num_reorder_frames + 1;
}
else
{
/*if VUI is not present assume maximum possible refrence frames for the level,
* as max reorder frames*/
ps_ctl_op->u4_num_disp_bufs = ih264d_get_dpb_size(ps_dec->ps_cur_sps);
}
ps_ctl_op->u4_num_disp_bufs +=
ps_dec->ps_cur_sps->u1_num_ref_frames + 1;
}
else
{
ps_ctl_op->u4_num_disp_bufs = 32;
}
ps_ctl_op->u4_num_disp_bufs = MAX(
ps_ctl_op->u4_num_disp_bufs, 6);
ps_ctl_op->u4_num_disp_bufs = MIN(
ps_ctl_op->u4_num_disp_bufs, 32);
}
ps_ctl_op->u4_error_code = ps_dec->i4_error_code;
ps_ctl_op->u4_frame_rate = 0; //make it proper
ps_ctl_op->u4_bit_rate = 0; //make it proper
ps_ctl_op->e_content_type = ps_dec->i4_content_type;
ps_ctl_op->e_output_chroma_format = ps_dec->u1_chroma_format;
ps_ctl_op->u4_min_num_in_bufs = MIN_IN_BUFS;
if(ps_dec->u1_chroma_format == IV_YUV_420P)
{
ps_ctl_op->u4_min_num_out_bufs = MIN_OUT_BUFS_420;
}
else if(ps_dec->u1_chroma_format == IV_YUV_422ILE)
{
ps_ctl_op->u4_min_num_out_bufs = MIN_OUT_BUFS_422ILE;
}
else if(ps_dec->u1_chroma_format == IV_RGB_565)
{
ps_ctl_op->u4_min_num_out_bufs = MIN_OUT_BUFS_RGB565;
}
else if((ps_dec->u1_chroma_format == IV_YUV_420SP_UV)
|| (ps_dec->u1_chroma_format == IV_YUV_420SP_VU))
{
ps_ctl_op->u4_min_num_out_bufs = MIN_OUT_BUFS_420SP;
}
else
{
//Invalid chroma format; Error code may be updated, verify in testing if needed
ps_ctl_op->u4_error_code = ERROR_FEATURE_UNAVAIL;
return IV_FAIL;
}
for(i = 0; i < ps_ctl_op->u4_min_num_in_bufs; i++)
{
ps_ctl_op->u4_min_in_buf_size[i] = MAX(256000, pic_wd * pic_ht * 3 / 2);
}
/*!*/
if(ps_dec->u1_chroma_format == IV_YUV_420P)
{
ps_ctl_op->u4_min_out_buf_size[0] = (pic_wd * pic_ht);
ps_ctl_op->u4_min_out_buf_size[1] = (pic_wd * pic_ht)
>> 2;
ps_ctl_op->u4_min_out_buf_size[2] = (pic_wd * pic_ht)
>> 2;
}
else if(ps_dec->u1_chroma_format == IV_YUV_422ILE)
{
ps_ctl_op->u4_min_out_buf_size[0] = (pic_wd * pic_ht)
* 2;
ps_ctl_op->u4_min_out_buf_size[1] =
ps_ctl_op->u4_min_out_buf_size[2] = 0;
}
else if(ps_dec->u1_chroma_format == IV_RGB_565)
{
ps_ctl_op->u4_min_out_buf_size[0] = (pic_wd * pic_ht)
* 2;
ps_ctl_op->u4_min_out_buf_size[1] =
ps_ctl_op->u4_min_out_buf_size[2] = 0;
}
else if((ps_dec->u1_chroma_format == IV_YUV_420SP_UV)
|| (ps_dec->u1_chroma_format == IV_YUV_420SP_VU))
{
ps_ctl_op->u4_min_out_buf_size[0] = (pic_wd * pic_ht);
ps_ctl_op->u4_min_out_buf_size[1] = (pic_wd * pic_ht)
>> 1;
ps_ctl_op->u4_min_out_buf_size[2] = 0;
}
ps_dec->u4_num_disp_bufs_requested = ps_ctl_op->u4_num_disp_bufs;
return IV_SUCCESS;
}
/*****************************************************************************/
/* */
/* Function Name : ih264d_get_buf_info */
/* */
/* Description : */
/* */
/* Inputs :iv_obj_t decoder handle */
/* :pv_api_ip pointer to input structure */
/* :pv_api_op pointer to output structure */
/* Globals : <Does it use any global variables?> */
/* Outputs : */
/* Returns : void */
/* */
/* Issues : none */
/* */
/* Revision History: */
/* */
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
/* 22 10 2008 100356 Draft */
/* */
/*****************************************************************************/
WORD32 ih264d_get_buf_info(iv_obj_t *dec_hdl, void *pv_api_ip, void *pv_api_op)
{
dec_struct_t * ps_dec;
UWORD8 i = 0; // Default for 420P format
UWORD16 pic_wd, pic_ht;
ivd_ctl_getbufinfo_op_t *ps_ctl_op =
(ivd_ctl_getbufinfo_op_t*)pv_api_op;
UWORD32 au4_min_out_buf_size[IVD_VIDDEC_MAX_IO_BUFFERS];
UNUSED(pv_api_ip);
ps_ctl_op->u4_error_code = 0;
ps_dec = (dec_struct_t *)(dec_hdl->pv_codec_handle);
ps_ctl_op->u4_min_num_in_bufs = MIN_IN_BUFS;
ps_ctl_op->u4_num_disp_bufs = 1;
pic_wd = 0;
pic_ht = 0;
if(ps_dec->i4_header_decoded == 3)
{
if(0 == ps_dec->u4_share_disp_buf)
{
pic_wd = ps_dec->u2_disp_width;
pic_ht = ps_dec->u2_disp_height;
}
else
{
pic_wd = ps_dec->u2_frm_wd_y;
pic_ht = ps_dec->u2_frm_ht_y;
}
}
for(i = 0; i < ps_ctl_op->u4_min_num_in_bufs; i++)
{
ps_ctl_op->u4_min_in_buf_size[i] = MAX(256000, pic_wd * pic_ht * 3 / 2);
}
if((WORD32)ps_dec->u4_app_disp_width > pic_wd)
pic_wd = ps_dec->u4_app_disp_width;
if(0 == ps_dec->u4_share_disp_buf)
ps_ctl_op->u4_num_disp_bufs = 1;
else
{
if((NULL != ps_dec->ps_cur_sps) && (1 == (ps_dec->ps_cur_sps->u1_is_valid)))
{
if((ps_dec->ps_cur_sps->u1_vui_parameters_present_flag == 1) &&
(1 == ps_dec->ps_cur_sps->s_vui.u1_bitstream_restriction_flag))
{
ps_ctl_op->u4_num_disp_bufs =
ps_dec->ps_cur_sps->s_vui.u4_num_reorder_frames + 1;
}