You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1938 lines
70 KiB
1938 lines
70 KiB
/******************************************************************************
|
|
*
|
|
* 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
|
|
*/
|
|
#include <string.h>
|
|
#ifdef __ANDROID__
|
|
#include <log/log.h>
|
|
#endif
|
|
#include "iv_datatypedef.h"
|
|
#include "iv.h"
|
|
#include "ivd.h"
|
|
#include "impeg2_macros.h"
|
|
#include "impeg2_buf_mgr.h"
|
|
#include "impeg2_disp_mgr.h"
|
|
#include "impeg2_defs.h"
|
|
#include "impeg2_inter_pred.h"
|
|
#include "impeg2_idct.h"
|
|
#include "impeg2_format_conv.h"
|
|
#include "impeg2_mem_func.h"
|
|
#include "impeg2_platform_macros.h"
|
|
#include "ithread.h"
|
|
#include "impeg2_job_queue.h"
|
|
|
|
#include "impeg2d.h"
|
|
#include "impeg2d_bitstream.h"
|
|
#include "impeg2d_api.h"
|
|
#include "impeg2d_structs.h"
|
|
#include "impeg2_globals.h"
|
|
#include "impeg2d_pic_proc.h"
|
|
#include "impeg2d_deinterlace.h"
|
|
|
|
|
|
/*****************************************************************************
|
|
* MPEG2 Constants for Parse Check
|
|
******************************************************************************/
|
|
#define MPEG2_MAX_FRAME_RATE_CODE 8
|
|
|
|
/******************************************************************************
|
|
* Function Name : impeg2d_next_start_code
|
|
*
|
|
* Description : Peek for next_start_code from the stream_t.
|
|
*
|
|
* Arguments :
|
|
* dec : Decoder Context
|
|
*
|
|
* Values Returned : None
|
|
******************************************************************************/
|
|
void impeg2d_next_start_code(dec_state_t *ps_dec)
|
|
{
|
|
stream_t *ps_stream;
|
|
ps_stream = &ps_dec->s_bit_stream;
|
|
impeg2d_bit_stream_flush_to_byte_boundary(ps_stream);
|
|
|
|
while ((impeg2d_bit_stream_nxt(ps_stream,START_CODE_PREFIX_LEN) != START_CODE_PREFIX)
|
|
&& (ps_dec->s_bit_stream.u4_offset < ps_dec->s_bit_stream.u4_max_offset))
|
|
{
|
|
impeg2d_bit_stream_get(ps_stream,8);
|
|
}
|
|
return;
|
|
}
|
|
/******************************************************************************
|
|
* Function Name : impeg2d_next_code
|
|
*
|
|
* Description : Peek for next_start_code from the stream_t.
|
|
*
|
|
* Arguments :
|
|
* dec : Decoder Context
|
|
*
|
|
* Values Returned : None
|
|
******************************************************************************/
|
|
void impeg2d_next_code(dec_state_t *ps_dec, UWORD32 u4_start_code_val)
|
|
{
|
|
stream_t *ps_stream;
|
|
ps_stream = &ps_dec->s_bit_stream;
|
|
impeg2d_bit_stream_flush_to_byte_boundary(ps_stream);
|
|
|
|
while ((impeg2d_bit_stream_nxt(ps_stream,START_CODE_LEN) != u4_start_code_val) &&
|
|
(ps_dec->s_bit_stream.u4_offset < ps_dec->s_bit_stream.u4_max_offset))
|
|
{
|
|
|
|
if (impeg2d_bit_stream_get(ps_stream,8) != 0)
|
|
{
|
|
/* Ignore stuffing bit errors. */
|
|
}
|
|
|
|
}
|
|
return;
|
|
}
|
|
/******************************************************************************
|
|
* Function Name : impeg2d_peek_next_start_code
|
|
*
|
|
* Description : Peek for next_start_code from the stream_t.
|
|
*
|
|
* Arguments :
|
|
* dec : Decoder Context
|
|
*
|
|
* Values Returned : None
|
|
******************************************************************************/
|
|
void impeg2d_peek_next_start_code(dec_state_t *ps_dec)
|
|
{
|
|
stream_t *ps_stream;
|
|
ps_stream = &ps_dec->s_bit_stream;
|
|
impeg2d_bit_stream_flush_to_byte_boundary(ps_stream);
|
|
|
|
while ((impeg2d_bit_stream_nxt(ps_stream,START_CODE_PREFIX_LEN) != START_CODE_PREFIX)
|
|
&& (ps_dec->s_bit_stream.u4_offset < ps_dec->s_bit_stream.u4_max_offset))
|
|
{
|
|
impeg2d_bit_stream_get(ps_stream,8);
|
|
}
|
|
return;
|
|
}
|
|
/******************************************************************************
|
|
*
|
|
* Function Name : impeg2d_dec_seq_hdr
|
|
*
|
|
* Description : Decodes Sequence header information
|
|
*
|
|
* Arguments :
|
|
* dec : Decoder Context
|
|
*
|
|
* Values Returned : None
|
|
******************************************************************************/
|
|
IMPEG2D_ERROR_CODES_T impeg2d_dec_seq_hdr(dec_state_t *ps_dec)
|
|
{
|
|
stream_t *ps_stream;
|
|
ps_stream = &ps_dec->s_bit_stream;
|
|
UWORD16 u2_height;
|
|
UWORD16 u2_width;
|
|
|
|
if (impeg2d_bit_stream_nxt(ps_stream,START_CODE_LEN) != SEQUENCE_HEADER_CODE)
|
|
{
|
|
impeg2d_bit_stream_flush(ps_stream,START_CODE_LEN);
|
|
return IMPEG2D_FRM_HDR_START_CODE_NOT_FOUND;
|
|
|
|
}
|
|
impeg2d_bit_stream_flush(ps_stream,START_CODE_LEN);
|
|
|
|
u2_width = impeg2d_bit_stream_get(ps_stream,12);
|
|
u2_height = impeg2d_bit_stream_get(ps_stream,12);
|
|
|
|
if (0 == u2_width || 0 == u2_height)
|
|
{
|
|
IMPEG2D_ERROR_CODES_T e_error = IMPEG2D_FRM_HDR_DECODE_ERR;
|
|
return e_error;
|
|
}
|
|
|
|
if ((u2_width != ps_dec->u2_horizontal_size)
|
|
|| (u2_height != ps_dec->u2_vertical_size))
|
|
{
|
|
if (0 == ps_dec->u2_header_done)
|
|
{
|
|
/* This is the first time we are reading the resolution */
|
|
ps_dec->u2_horizontal_size = u2_width;
|
|
ps_dec->u2_vertical_size = u2_height;
|
|
}
|
|
else
|
|
{
|
|
if (0 == ps_dec->i4_pic_count)
|
|
{
|
|
/* Decoder has not decoded a single frame since the last
|
|
* reset/init. This implies that we have two headers in the
|
|
* input stream. So, do not indicate a resolution change, since
|
|
* this can take the decoder into an infinite loop.
|
|
*/
|
|
return (IMPEG2D_ERROR_CODES_T) IMPEG2D_FRM_HDR_DECODE_ERR;
|
|
}
|
|
else if((u2_width > ps_dec->u2_create_max_width)
|
|
|| (u2_height > ps_dec->u2_create_max_height))
|
|
{
|
|
IMPEG2D_ERROR_CODES_T e_error = IMPEG2D_UNSUPPORTED_DIMENSIONS;
|
|
|
|
ps_dec->u2_reinit_max_height = u2_height;
|
|
ps_dec->u2_reinit_max_width = u2_width;
|
|
|
|
return e_error;
|
|
}
|
|
else if((ps_dec->u2_horizontal_size < MIN_WIDTH)
|
|
|| (ps_dec->u2_vertical_size < MIN_HEIGHT))
|
|
{
|
|
return IMPEG2D_UNSUPPORTED_DIMENSIONS;
|
|
}
|
|
else
|
|
{
|
|
/* The resolution has changed */
|
|
return (IMPEG2D_ERROR_CODES_T)IVD_RES_CHANGED;
|
|
}
|
|
}
|
|
}
|
|
|
|
if((ps_dec->u2_horizontal_size > ps_dec->u2_create_max_width)
|
|
|| (ps_dec->u2_vertical_size > ps_dec->u2_create_max_height))
|
|
{
|
|
IMPEG2D_ERROR_CODES_T e_error = IMPEG2D_UNSUPPORTED_DIMENSIONS;
|
|
ps_dec->u2_reinit_max_height = ps_dec->u2_vertical_size;
|
|
ps_dec->u2_reinit_max_width = ps_dec->u2_horizontal_size;
|
|
return e_error;
|
|
}
|
|
|
|
if((ps_dec->u2_horizontal_size < MIN_WIDTH)
|
|
|| (ps_dec->u2_vertical_size < MIN_HEIGHT))
|
|
{
|
|
return IMPEG2D_UNSUPPORTED_DIMENSIONS;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
/* Flush the following as they are not being used */
|
|
/* aspect_ratio_info (4 bits) */
|
|
/*------------------------------------------------------------------------*/
|
|
ps_dec->u2_aspect_ratio_info = impeg2d_bit_stream_get(ps_stream,4);
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
/* Frame rate code(4 bits) */
|
|
/*------------------------------------------------------------------------*/
|
|
ps_dec->u2_frame_rate_code = impeg2d_bit_stream_get(ps_stream,4);
|
|
if (ps_dec->u2_frame_rate_code > MPEG2_MAX_FRAME_RATE_CODE)
|
|
{
|
|
return IMPEG2D_FRM_HDR_DECODE_ERR;
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
/* Flush the following as they are not being used */
|
|
/* bit_rate_value (18 bits) */
|
|
/*------------------------------------------------------------------------*/
|
|
impeg2d_bit_stream_flush(ps_stream,18);
|
|
GET_MARKER_BIT(ps_dec,ps_stream);
|
|
/*------------------------------------------------------------------------*/
|
|
/* Flush the following as they are not being used */
|
|
/* vbv_buffer_size_value(10 bits), constrained_parameter_flag (1 bit) */
|
|
/*------------------------------------------------------------------------*/
|
|
impeg2d_bit_stream_flush(ps_stream,11);
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
/* Quantization matrix for the intra blocks */
|
|
/*------------------------------------------------------------------------*/
|
|
if(impeg2d_bit_stream_get_bit(ps_stream) == 1)
|
|
{
|
|
UWORD16 i;
|
|
for(i = 0; i < NUM_PELS_IN_BLOCK; i++)
|
|
{
|
|
ps_dec->au1_intra_quant_matrix[gau1_impeg2_inv_scan_zig_zag[i]] = (UWORD8)impeg2d_bit_stream_get(ps_stream,8);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
memcpy(ps_dec->au1_intra_quant_matrix,gau1_impeg2_intra_quant_matrix_default,
|
|
NUM_PELS_IN_BLOCK);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
/* Quantization matrix for the inter blocks */
|
|
/*------------------------------------------------------------------------*/
|
|
if(impeg2d_bit_stream_get_bit(ps_stream) == 1)
|
|
{
|
|
UWORD16 i;
|
|
for(i = 0; i < NUM_PELS_IN_BLOCK; i++)
|
|
{
|
|
ps_dec->au1_inter_quant_matrix[gau1_impeg2_inv_scan_zig_zag[i]] = (UWORD8)impeg2d_bit_stream_get(ps_stream,8);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
memcpy(ps_dec->au1_inter_quant_matrix,gau1_impeg2_inter_quant_matrix_default,
|
|
NUM_PELS_IN_BLOCK);
|
|
}
|
|
impeg2d_next_start_code(ps_dec);
|
|
|
|
return (IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Function Name : impeg2d_dec_seq_ext
|
|
*
|
|
* Description : Gets additional sequence data.
|
|
*
|
|
* Arguments :
|
|
* dec : Decoder Context
|
|
*
|
|
* Values Returned : None
|
|
******************************************************************************/
|
|
IMPEG2D_ERROR_CODES_T impeg2d_dec_seq_ext(dec_state_t *ps_dec)
|
|
{
|
|
stream_t *ps_stream;
|
|
UWORD16 horizontal_value;
|
|
UWORD16 vertical_value;
|
|
|
|
ps_stream = &ps_dec->s_bit_stream;
|
|
|
|
if (impeg2d_bit_stream_nxt(ps_stream,START_CODE_LEN) != EXTENSION_START_CODE)
|
|
{
|
|
impeg2d_bit_stream_flush(ps_stream,START_CODE_LEN);
|
|
return IMPEG2D_FRM_HDR_START_CODE_NOT_FOUND;
|
|
|
|
}
|
|
/* Flush the extension start code */
|
|
impeg2d_bit_stream_flush(ps_stream,START_CODE_LEN);
|
|
|
|
/* Flush extension start code identifier */
|
|
impeg2d_bit_stream_flush(ps_stream,4);
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* Profile and Level information */
|
|
/*----------------------------------------------------------------------*/
|
|
{
|
|
UWORD32 u4_esc_bit, u4_profile, u4_level;
|
|
|
|
/* Read the profile and level information */
|
|
/* check_profile_and_level: Table 8-1 */
|
|
/* [7:7] 1 Escape bit */
|
|
/* [6:4] 3 Profile identification */
|
|
/* [3:0] 4 Level identification */
|
|
|
|
u4_esc_bit = impeg2d_bit_stream_get_bit(ps_stream);
|
|
u4_profile = impeg2d_bit_stream_get(ps_stream,3);
|
|
u4_level = impeg2d_bit_stream_get(ps_stream,4);
|
|
UNUSED(u4_profile);
|
|
UNUSED(u4_level);
|
|
/*
|
|
if( escBit == 1 ||
|
|
profile < MPEG2_MAIN_PROFILE ||
|
|
level < MPEG2_MAIN_LEVEL)
|
|
*/
|
|
if (1 == u4_esc_bit)
|
|
{
|
|
return IMPEG2D_PROF_LEVEL_NOT_SUPPORTED;
|
|
}
|
|
}
|
|
|
|
ps_dec->u2_progressive_sequence = impeg2d_bit_stream_get_bit(ps_stream);
|
|
|
|
/* Read the chrominance format */
|
|
if(impeg2d_bit_stream_get(ps_stream,2) != 0x1)
|
|
return IMPEG2D_CHROMA_FMT_NOT_SUP;
|
|
|
|
/* Error resilience: store the 2 most significant bit in horizontal and vertical */
|
|
/* variables.Use it only if adding them to the vertical and horizontal sizes */
|
|
/* respectively, doesn't exceed the MAX_WD and MAX_HT supported by the application.*/
|
|
|
|
|
|
/* Read the 2 most significant bits from horizontal_size */
|
|
horizontal_value = (impeg2d_bit_stream_get(ps_stream,2) << 12);
|
|
|
|
/* Read the 2 most significant bits from vertical_size */
|
|
vertical_value = (impeg2d_bit_stream_get(ps_stream,2) << 12);
|
|
|
|
/* Error resilience: The height and width should not be more than the*/
|
|
/*max height and width the application can support*/
|
|
if(ps_dec->u2_create_max_height < (ps_dec->u2_vertical_size + vertical_value))
|
|
{
|
|
return (IMPEG2D_ERROR_CODES_T) IVD_STREAM_WIDTH_HEIGHT_NOT_SUPPORTED;
|
|
}
|
|
|
|
if(ps_dec->u2_create_max_width < (ps_dec->u2_horizontal_size + horizontal_value))
|
|
{
|
|
return (IMPEG2D_ERROR_CODES_T) IVD_STREAM_WIDTH_HEIGHT_NOT_SUPPORTED;
|
|
}
|
|
ps_dec->u2_vertical_size += vertical_value;
|
|
ps_dec->u2_horizontal_size += horizontal_value;
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
/* Flush the following as they are not used now */
|
|
/* bit_rate_extension 12 */
|
|
/* marker_bit 1 */
|
|
/* vbv_buffer_size_extension 8 */
|
|
/* low_delay 1 */
|
|
/*-----------------------------------------------------------------------*/
|
|
impeg2d_bit_stream_flush(ps_stream,12);
|
|
GET_MARKER_BIT(ps_dec,ps_stream);
|
|
impeg2d_bit_stream_flush(ps_stream,9);
|
|
/*-----------------------------------------------------------------------*/
|
|
/* frame_rate_extension_n 2 */
|
|
/* frame_rate_extension_d 5 */
|
|
/*-----------------------------------------------------------------------*/
|
|
ps_dec->u2_frame_rate_extension_n = impeg2d_bit_stream_get(ps_stream,2);
|
|
ps_dec->u2_frame_rate_extension_d = impeg2d_bit_stream_get(ps_stream,5);
|
|
|
|
return (IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* Function Name : impeg2d_dec_seq_disp_ext
|
|
*
|
|
* Description : This function is eqvt to sequence_display_extension() of
|
|
* standard. It flushes data present as it is not being used
|
|
*
|
|
* Arguments :
|
|
* dec : Decoder Context
|
|
*
|
|
* Values Returned : None
|
|
******************************************************************************/
|
|
void impeg2d_dec_seq_disp_ext(dec_state_t *ps_dec)
|
|
{
|
|
stream_t *ps_stream;
|
|
ps_stream = &ps_dec->s_bit_stream;
|
|
|
|
/*
|
|
sequence_display_extension()
|
|
{
|
|
extension_start_code_identifier 4
|
|
video_format 3
|
|
colour_description 1
|
|
if (colour_description)
|
|
{
|
|
colour_primaries 8
|
|
transfer_characteristics 8
|
|
matrix_coefficients 8
|
|
}
|
|
display_horizontal_size 14
|
|
marker_bit 1
|
|
display_vertical_size 14
|
|
next_start_code()
|
|
}
|
|
*/
|
|
|
|
impeg2d_bit_stream_get(ps_stream, 4);
|
|
ps_dec->u1_video_format = impeg2d_bit_stream_get(ps_stream, 3);
|
|
ps_dec->u1_colour_description = impeg2d_bit_stream_get(ps_stream, 1);
|
|
ps_dec->u1_colour_primaries = 2;
|
|
ps_dec->u1_transfer_characteristics = 2;
|
|
ps_dec->u1_matrix_coefficients = 2;
|
|
if(ps_dec->u1_colour_description)
|
|
{
|
|
ps_dec->u1_colour_primaries = impeg2d_bit_stream_get(ps_stream, 8);
|
|
ps_dec->u1_transfer_characteristics = impeg2d_bit_stream_get(ps_stream, 8);
|
|
ps_dec->u1_matrix_coefficients = impeg2d_bit_stream_get(ps_stream, 8);
|
|
}
|
|
|
|
/* display_horizontal_size and display_vertical_size */
|
|
ps_dec->u2_display_horizontal_size = impeg2d_bit_stream_get(ps_stream,14);;
|
|
GET_MARKER_BIT(ps_dec,ps_stream);
|
|
ps_dec->u2_display_vertical_size = impeg2d_bit_stream_get(ps_stream,14);
|
|
|
|
ps_dec->u1_seq_disp_extn_present = 1;
|
|
impeg2d_next_start_code(ps_dec);
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* Function Name : impeg2d_dec_seq_scale_ext
|
|
*
|
|
* Description : This function is eqvt to sequence_scalable_extension() of
|
|
* standard.
|
|
*
|
|
* Arguments : Decoder context
|
|
*
|
|
* Values Returned : None
|
|
*******************************************************************************/
|
|
IMPEG2D_ERROR_CODES_T impeg2d_dec_seq_scale_ext(dec_state_t *ps_dec)
|
|
{
|
|
UNUSED(ps_dec);
|
|
return IMPEG2D_SCALABILITIY_NOT_SUPPORTED;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* Function Name : impeg2d_dec_quant_matrix_ext
|
|
*
|
|
* Description : Gets Intra and NonIntra quantizer matrix from the stream.
|
|
*
|
|
* Arguments : Decoder context
|
|
*
|
|
* Values Returned : None
|
|
*******************************************************************************/
|
|
void impeg2d_dec_quant_matrix_ext(dec_state_t *ps_dec)
|
|
{
|
|
stream_t *ps_stream;
|
|
|
|
ps_stream = &ps_dec->s_bit_stream;
|
|
/* Flush extension_start_code_identifier */
|
|
impeg2d_bit_stream_flush(ps_stream,4);
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
/* Quantization matrix for the intra blocks */
|
|
/*------------------------------------------------------------------------*/
|
|
if(impeg2d_bit_stream_get(ps_stream,1) == 1)
|
|
{
|
|
UWORD16 i;
|
|
for(i = 0; i < NUM_PELS_IN_BLOCK; i++)
|
|
{
|
|
ps_dec->au1_intra_quant_matrix[gau1_impeg2_inv_scan_zig_zag[i]] = (UWORD8)impeg2d_bit_stream_get(ps_stream,8);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
/* Quantization matrix for the inter blocks */
|
|
/*------------------------------------------------------------------------*/
|
|
if(impeg2d_bit_stream_get(ps_stream,1) == 1)
|
|
{
|
|
UWORD16 i;
|
|
for(i = 0; i < NUM_PELS_IN_BLOCK; i++)
|
|
{
|
|
ps_dec->au1_inter_quant_matrix[gau1_impeg2_inv_scan_zig_zag[i]] = (UWORD8)impeg2d_bit_stream_get(ps_stream,8);
|
|
}
|
|
}
|
|
|
|
/* Note : chroma intra quantizer matrix and chroma non
|
|
intra quantizer matrix are not needed for 4:2:0 format */
|
|
impeg2d_next_start_code(ps_dec);
|
|
}
|
|
/*******************************************************************************
|
|
*
|
|
* Function Name : impeg2d_dec_pic_disp_ext
|
|
*
|
|
* Description : This function is eqvt to picture_display_extension() of
|
|
* standard.The parameters are not used by decoder
|
|
*
|
|
* Arguments : Pointer to dec_state_t
|
|
*
|
|
* Values Returned : Decoder context
|
|
*
|
|
* Values Returned : None
|
|
*******************************************************************************/
|
|
void impeg2d_dec_pic_disp_ext(dec_state_t *ps_dec)
|
|
{
|
|
WORD16 i2_number_of_frame_centre_offsets ;
|
|
stream_t *ps_stream;
|
|
|
|
ps_stream = &ps_dec->s_bit_stream;
|
|
impeg2d_bit_stream_flush(ps_stream,4);
|
|
|
|
if (ps_dec->u2_progressive_sequence)
|
|
{
|
|
i2_number_of_frame_centre_offsets = (ps_dec->u2_repeat_first_field) ?
|
|
2 + ps_dec->u2_top_field_first : 1;
|
|
}
|
|
else
|
|
{
|
|
i2_number_of_frame_centre_offsets =
|
|
(ps_dec->u2_picture_structure != FRAME_PICTURE) ?
|
|
1 : 2 + ps_dec->u2_repeat_first_field;
|
|
}
|
|
while(i2_number_of_frame_centre_offsets--)
|
|
{
|
|
/* frame_centre_horizontal_offset */
|
|
impeg2d_bit_stream_get(ps_stream,16);
|
|
GET_MARKER_BIT(ps_dec,ps_stream);
|
|
/* frame_centre_vertical_offset */
|
|
impeg2d_bit_stream_get(ps_stream,16);
|
|
GET_MARKER_BIT(ps_dec,ps_stream);
|
|
}
|
|
impeg2d_next_start_code(ps_dec);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* Function Name : impeg2d_dec_itu_t_ext
|
|
*
|
|
* Description : This function is eqvt to ITU-T_extension() of
|
|
* standard.The parameters are not used by decoder
|
|
*
|
|
* Arguments : Decoder context
|
|
*
|
|
* Values Returned : None
|
|
*******************************************************************************/
|
|
void impeg2d_dec_itu_t_ext(dec_state_t *ps_dec)
|
|
{
|
|
impeg2d_bit_stream_flush(&ps_dec->s_bit_stream,EXT_ID_LEN);
|
|
impeg2d_next_start_code(ps_dec);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* Function Name : impeg2d_dec_copyright_ext
|
|
*
|
|
* Description : This function is eqvt to copyright_extension() of
|
|
* standard. The parameters are not used by decoder
|
|
*
|
|
* Arguments : Decoder context
|
|
*
|
|
* Values Returned : None
|
|
*******************************************************************************/
|
|
|
|
|
|
void impeg2d_dec_copyright_ext(dec_state_t *ps_dec)
|
|
{
|
|
UWORD32 u4_bits_to_flush;
|
|
|
|
u4_bits_to_flush = COPYRIGHT_EXTENSION_LEN;
|
|
|
|
while(u4_bits_to_flush >= 32 )
|
|
{
|
|
impeg2d_bit_stream_flush(&ps_dec->s_bit_stream,32);
|
|
u4_bits_to_flush = u4_bits_to_flush - 32;
|
|
}
|
|
|
|
if(u4_bits_to_flush > 0)
|
|
{
|
|
impeg2d_bit_stream_flush(&ps_dec->s_bit_stream,u4_bits_to_flush);
|
|
}
|
|
|
|
|
|
impeg2d_next_start_code(ps_dec);
|
|
}
|
|
/*******************************************************************************
|
|
* Function Name : impeg2d_dec_cam_param_ext
|
|
*
|
|
* Description : This function is eqvt to camera_parameters_extension() of
|
|
* standard. The parameters are not used by decoder
|
|
*
|
|
* Arguments : Decoder context
|
|
*
|
|
* Values Returned : None
|
|
*******************************************************************************/
|
|
|
|
|
|
void impeg2d_dec_cam_param_ext(dec_state_t *ps_dec)
|
|
{
|
|
|
|
UWORD32 u4_bits_to_flush;
|
|
|
|
u4_bits_to_flush = CAMERA_PARAMETER_EXTENSION_LEN;
|
|
|
|
while(u4_bits_to_flush >= 32 )
|
|
{
|
|
impeg2d_bit_stream_flush(&ps_dec->s_bit_stream,32);
|
|
u4_bits_to_flush = u4_bits_to_flush - 32;
|
|
}
|
|
|
|
if(u4_bits_to_flush > 0)
|
|
{
|
|
impeg2d_bit_stream_flush(&ps_dec->s_bit_stream,u4_bits_to_flush);
|
|
}
|
|
|
|
impeg2d_next_start_code(ps_dec);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* Function Name : impeg2d_dec_grp_of_pic_hdr
|
|
*
|
|
* Description : Gets information at the GOP level.
|
|
*
|
|
* Arguments : Decoder context
|
|
*
|
|
* Values Returned : None
|
|
*******************************************************************************/
|
|
|
|
|
|
void impeg2d_dec_grp_of_pic_hdr(dec_state_t *ps_dec)
|
|
{
|
|
|
|
UWORD32 u4_bits_to_flush;
|
|
|
|
u4_bits_to_flush = GROUP_OF_PICTURE_LEN;
|
|
|
|
while(u4_bits_to_flush >= 32 )
|
|
{
|
|
impeg2d_bit_stream_flush(&ps_dec->s_bit_stream,32);
|
|
u4_bits_to_flush = u4_bits_to_flush - 32;
|
|
}
|
|
|
|
if(u4_bits_to_flush > 0)
|
|
{
|
|
impeg2d_bit_stream_flush(&ps_dec->s_bit_stream,u4_bits_to_flush);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* Function Name : impeg2d_dec_pic_hdr
|
|
*
|
|
* Description : Gets the picture header information.
|
|
*
|
|
* Arguments : Decoder context
|
|
*
|
|
* Values Returned : None
|
|
*******************************************************************************/
|
|
IMPEG2D_ERROR_CODES_T impeg2d_dec_pic_hdr(dec_state_t *ps_dec)
|
|
{
|
|
stream_t *ps_stream;
|
|
ps_stream = &ps_dec->s_bit_stream;
|
|
|
|
impeg2d_bit_stream_flush(ps_stream,START_CODE_LEN);
|
|
/* Flush temporal reference */
|
|
impeg2d_bit_stream_get(ps_stream,10);
|
|
|
|
/* Picture type */
|
|
ps_dec->e_pic_type = (e_pic_type_t)impeg2d_bit_stream_get(ps_stream,3);
|
|
if((ps_dec->e_pic_type < I_PIC) || (ps_dec->e_pic_type > D_PIC))
|
|
{
|
|
impeg2d_next_code(ps_dec, PICTURE_START_CODE);
|
|
return IMPEG2D_INVALID_PIC_TYPE;
|
|
}
|
|
|
|
/* Flush vbv_delay */
|
|
impeg2d_bit_stream_get(ps_stream,16);
|
|
|
|
if(ps_dec->e_pic_type == P_PIC || ps_dec->e_pic_type == B_PIC)
|
|
{
|
|
ps_dec->u2_full_pel_forw_vector = impeg2d_bit_stream_get_bit(ps_stream);
|
|
ps_dec->u2_forw_f_code = impeg2d_bit_stream_get(ps_stream,3);
|
|
}
|
|
if(ps_dec->e_pic_type == B_PIC)
|
|
{
|
|
ps_dec->u2_full_pel_back_vector = impeg2d_bit_stream_get_bit(ps_stream);
|
|
ps_dec->u2_back_f_code = impeg2d_bit_stream_get(ps_stream,3);
|
|
}
|
|
|
|
if(ps_dec->u2_is_mpeg2 == 0)
|
|
{
|
|
if (ps_dec->u2_forw_f_code < 1 || ps_dec->u2_forw_f_code > 7 ||
|
|
ps_dec->u2_back_f_code < 1 || ps_dec->u2_back_f_code > 7)
|
|
{
|
|
return IMPEG2D_UNKNOWN_ERROR;
|
|
}
|
|
ps_dec->au2_f_code[0][0] = ps_dec->au2_f_code[0][1] = ps_dec->u2_forw_f_code;
|
|
ps_dec->au2_f_code[1][0] = ps_dec->au2_f_code[1][1] = ps_dec->u2_back_f_code;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
/* Flush the extra bit value */
|
|
/* */
|
|
/* while(impeg2d_bit_stream_nxt() == '1') */
|
|
/* { */
|
|
/* extra_bit_picture 1 */
|
|
/* extra_information_picture 8 */
|
|
/* } */
|
|
/* extra_bit_picture 1 */
|
|
/*-----------------------------------------------------------------------*/
|
|
while (impeg2d_bit_stream_nxt(ps_stream,1) == 1 &&
|
|
ps_stream->u4_offset < ps_stream->u4_max_offset)
|
|
{
|
|
impeg2d_bit_stream_get(ps_stream,9);
|
|
}
|
|
impeg2d_bit_stream_get_bit(ps_stream);
|
|
impeg2d_next_start_code(ps_dec);
|
|
|
|
return (IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE;
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* Function Name : impeg2d_dec_pic_coding_ext
|
|
*
|
|
* Description : Reads more picture level parameters
|
|
*
|
|
* Arguments :
|
|
* dec : Decoder context
|
|
*
|
|
* Values Returned : Error
|
|
*******************************************************************************/
|
|
IMPEG2D_ERROR_CODES_T impeg2d_dec_pic_coding_ext(dec_state_t *ps_dec)
|
|
{
|
|
|
|
UWORD32 u4_val;
|
|
stream_t *ps_stream;
|
|
IMPEG2D_ERROR_CODES_T e_error = (IMPEG2D_ERROR_CODES_T) IV_SUCCESS;
|
|
|
|
ps_stream = &ps_dec->s_bit_stream;
|
|
impeg2d_bit_stream_flush(ps_stream,START_CODE_LEN);
|
|
/* extension code identifier */
|
|
impeg2d_bit_stream_get(ps_stream,4);
|
|
|
|
u4_val = impeg2d_bit_stream_get(ps_stream,4);
|
|
if(u4_val == 0)
|
|
return IMPEG2D_UNKNOWN_ERROR;
|
|
ps_dec->au2_f_code[0][0] = u4_val;
|
|
|
|
u4_val = impeg2d_bit_stream_get(ps_stream,4);
|
|
if(u4_val == 0)
|
|
return IMPEG2D_UNKNOWN_ERROR;
|
|
ps_dec->au2_f_code[0][1] = u4_val;
|
|
|
|
u4_val = impeg2d_bit_stream_get(ps_stream,4);
|
|
if(u4_val == 0)
|
|
return IMPEG2D_UNKNOWN_ERROR;
|
|
ps_dec->au2_f_code[1][0] = u4_val;
|
|
|
|
u4_val = impeg2d_bit_stream_get(ps_stream,4);
|
|
if(u4_val == 0)
|
|
return IMPEG2D_UNKNOWN_ERROR;
|
|
ps_dec->au2_f_code[1][1] = u4_val;
|
|
|
|
ps_dec->u2_intra_dc_precision = impeg2d_bit_stream_get(ps_stream,2);
|
|
ps_dec->u2_picture_structure = impeg2d_bit_stream_get(ps_stream,2);
|
|
if (ps_dec->u2_picture_structure < TOP_FIELD ||
|
|
ps_dec->u2_picture_structure > FRAME_PICTURE)
|
|
{
|
|
return IMPEG2D_FRM_HDR_DECODE_ERR;
|
|
}
|
|
ps_dec->u2_top_field_first = impeg2d_bit_stream_get_bit(ps_stream);
|
|
ps_dec->u2_frame_pred_frame_dct = impeg2d_bit_stream_get_bit(ps_stream);
|
|
ps_dec->u2_concealment_motion_vectors = impeg2d_bit_stream_get_bit(ps_stream);
|
|
ps_dec->u2_q_scale_type = impeg2d_bit_stream_get_bit(ps_stream);
|
|
ps_dec->u2_intra_vlc_format = impeg2d_bit_stream_get_bit(ps_stream);
|
|
ps_dec->u2_alternate_scan = impeg2d_bit_stream_get_bit(ps_stream);
|
|
ps_dec->u2_repeat_first_field = impeg2d_bit_stream_get_bit(ps_stream);
|
|
/* Flush chroma_420_type */
|
|
impeg2d_bit_stream_get_bit(ps_stream);
|
|
|
|
ps_dec->u2_progressive_frame = impeg2d_bit_stream_get_bit(ps_stream);
|
|
if (impeg2d_bit_stream_get_bit(ps_stream))
|
|
{
|
|
/* Flush v_axis, field_sequence, burst_amplitude, sub_carrier_phase */
|
|
impeg2d_bit_stream_flush(ps_stream,20);
|
|
}
|
|
impeg2d_next_start_code(ps_dec);
|
|
|
|
|
|
if(VERTICAL_SCAN == ps_dec->u2_alternate_scan)
|
|
{
|
|
ps_dec->pu1_inv_scan_matrix = (UWORD8 *)gau1_impeg2_inv_scan_vertical;
|
|
}
|
|
else
|
|
{
|
|
ps_dec->pu1_inv_scan_matrix = (UWORD8 *)gau1_impeg2_inv_scan_zig_zag;
|
|
}
|
|
return e_error;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* Function Name : impeg2d_dec_slice
|
|
*
|
|
* Description : Reads Slice level parameters and calls functions that
|
|
* decode individual MBs of slice
|
|
*
|
|
* Arguments :
|
|
* dec : Decoder context
|
|
*
|
|
* Values Returned : None
|
|
*******************************************************************************/
|
|
IMPEG2D_ERROR_CODES_T impeg2d_dec_slice(dec_state_t *ps_dec)
|
|
{
|
|
stream_t *ps_stream;
|
|
UWORD32 u4_slice_vertical_position;
|
|
UWORD32 u4_slice_vertical_position_extension;
|
|
IMPEG2D_ERROR_CODES_T e_error;
|
|
|
|
ps_stream = &ps_dec->s_bit_stream;
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
/* All the profiles supported require restricted slice structure. Hence */
|
|
/* there is no need to store slice_vertical_position. Note that max */
|
|
/* height supported does not exceed 2800 and scalablity is not supported */
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
/* Remove the slice start code */
|
|
impeg2d_bit_stream_flush(ps_stream,START_CODE_PREFIX_LEN);
|
|
u4_slice_vertical_position = impeg2d_bit_stream_get(ps_stream, 8);
|
|
if(u4_slice_vertical_position > 2800)
|
|
{
|
|
u4_slice_vertical_position_extension = impeg2d_bit_stream_get(ps_stream, 3);
|
|
u4_slice_vertical_position += (u4_slice_vertical_position_extension << 7);
|
|
}
|
|
|
|
if((u4_slice_vertical_position > ps_dec->u2_num_vert_mb) ||
|
|
(u4_slice_vertical_position == 0))
|
|
{
|
|
return IMPEG2D_INVALID_VERT_SIZE;
|
|
}
|
|
|
|
// change the mb_y to point to slice_vertical_position
|
|
u4_slice_vertical_position--;
|
|
if (ps_dec->u2_mb_y != u4_slice_vertical_position)
|
|
{
|
|
ps_dec->u2_mb_y = u4_slice_vertical_position;
|
|
ps_dec->u2_mb_x = 0;
|
|
|
|
/* Update the number of MBs left, since we have probably missed a slice
|
|
* (that's why we see a mismatch between u2_mb_y and current position).
|
|
*/
|
|
ps_dec->u2_num_mbs_left = (ps_dec->u2_num_vert_mb - ps_dec->u2_mb_y)
|
|
* ps_dec->u2_num_horiz_mb;
|
|
}
|
|
ps_dec->u2_first_mb = 1;
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
/* Quant scale code decoding */
|
|
/*------------------------------------------------------------------------*/
|
|
{
|
|
UWORD16 u2_quant_scale_code;
|
|
u2_quant_scale_code = impeg2d_bit_stream_get(ps_stream,5);
|
|
ps_dec->u1_quant_scale = (ps_dec->u2_q_scale_type) ?
|
|
gau1_impeg2_non_linear_quant_scale[u2_quant_scale_code] : (u2_quant_scale_code << 1);
|
|
}
|
|
|
|
if (impeg2d_bit_stream_nxt(ps_stream,1) == 1)
|
|
{
|
|
impeg2d_bit_stream_flush(ps_stream,9);
|
|
/* Flush extra bit information */
|
|
while (impeg2d_bit_stream_nxt(ps_stream,1) == 1 &&
|
|
ps_stream->u4_offset < ps_stream->u4_max_offset)
|
|
{
|
|
impeg2d_bit_stream_flush(ps_stream,9);
|
|
}
|
|
}
|
|
impeg2d_bit_stream_get_bit(ps_stream);
|
|
|
|
/* Reset the DC predictors to reset values given in Table 7.2 at the start*/
|
|
/* of slice data */
|
|
ps_dec->u2_def_dc_pred[Y_LUMA] = 128 << ps_dec->u2_intra_dc_precision;
|
|
ps_dec->u2_def_dc_pred[U_CHROMA] = 128 << ps_dec->u2_intra_dc_precision;
|
|
ps_dec->u2_def_dc_pred[V_CHROMA] = 128 << ps_dec->u2_intra_dc_precision;
|
|
/*------------------------------------------------------------------------*/
|
|
/* dec->DecMBsinSlice() implements the following psuedo code from standard*/
|
|
/* do */
|
|
/* { */
|
|
/* macroblock() */
|
|
/* } while (impeg2d_bit_stream_nxt() != '000 0000 0000 0000 0000 0000') */
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
e_error = ps_dec->pf_decode_slice(ps_dec);
|
|
if ((IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE != e_error)
|
|
{
|
|
return e_error;
|
|
}
|
|
|
|
/* Check for the MBy index instead of number of MBs left, because the
|
|
* number of MBs left in case of multi-thread decode is the number of MBs
|
|
* in that row only
|
|
*/
|
|
if(ps_dec->u2_mb_y < ps_dec->u2_num_vert_mb)
|
|
impeg2d_next_start_code(ps_dec);
|
|
|
|
return (IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE;
|
|
}
|
|
|
|
void impeg2d_dec_pic_data_thread(dec_state_t *ps_dec)
|
|
{
|
|
WORD32 i4_continue_decode;
|
|
|
|
WORD32 i4_cur_row, temp;
|
|
UWORD32 u4_bits_read;
|
|
WORD32 i4_dequeue_job;
|
|
IMPEG2D_ERROR_CODES_T e_error;
|
|
|
|
i4_cur_row = ps_dec->u2_mb_y + 1;
|
|
|
|
i4_continue_decode = 1;
|
|
|
|
i4_dequeue_job = 1;
|
|
do
|
|
{
|
|
if(i4_cur_row > ps_dec->u2_num_vert_mb)
|
|
{
|
|
i4_continue_decode = 0;
|
|
break;
|
|
}
|
|
|
|
{
|
|
if((ps_dec->i4_num_cores> 1) && (i4_dequeue_job))
|
|
{
|
|
job_t s_job;
|
|
IV_API_CALL_STATUS_T e_ret;
|
|
UWORD8 *pu1_buf;
|
|
|
|
e_ret = impeg2_jobq_dequeue(ps_dec->pv_jobq, &s_job, sizeof(s_job), 1, 1);
|
|
if(e_ret != IV_SUCCESS)
|
|
break;
|
|
|
|
if(CMD_PROCESS == s_job.i4_cmd)
|
|
{
|
|
pu1_buf = ps_dec->pu1_inp_bits_buf + s_job.i4_bistream_ofst;
|
|
impeg2d_bit_stream_init(&(ps_dec->s_bit_stream), pu1_buf,
|
|
(ps_dec->u4_num_inp_bytes - s_job.i4_bistream_ofst));
|
|
i4_cur_row = s_job.i2_start_mb_y;
|
|
ps_dec->i4_start_mb_y = s_job.i2_start_mb_y;
|
|
ps_dec->i4_end_mb_y = s_job.i2_end_mb_y;
|
|
ps_dec->u2_mb_x = 0;
|
|
ps_dec->u2_mb_y = ps_dec->i4_start_mb_y;
|
|
ps_dec->u2_num_mbs_left = (ps_dec->i4_end_mb_y - ps_dec->i4_start_mb_y) * ps_dec->u2_num_horiz_mb;
|
|
|
|
}
|
|
else
|
|
{
|
|
WORD32 start_row;
|
|
WORD32 num_rows;
|
|
start_row = s_job.i2_start_mb_y << 4;
|
|
num_rows = MIN((s_job.i2_end_mb_y << 4), ps_dec->u2_vertical_size);
|
|
num_rows -= start_row;
|
|
|
|
if(ps_dec->u4_deinterlace && (0 == ps_dec->u2_progressive_frame))
|
|
{
|
|
impeg2d_deinterlace(ps_dec,
|
|
ps_dec->ps_disp_pic,
|
|
ps_dec->ps_disp_frm_buf,
|
|
start_row,
|
|
num_rows);
|
|
|
|
}
|
|
else
|
|
{
|
|
impeg2d_format_convert(ps_dec, ps_dec->ps_disp_pic,
|
|
ps_dec->ps_disp_frm_buf,
|
|
start_row, num_rows);
|
|
}
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
e_error = impeg2d_dec_slice(ps_dec);
|
|
|
|
if ((IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE != e_error)
|
|
{
|
|
impeg2d_next_start_code(ps_dec);
|
|
if(ps_dec->s_bit_stream.u4_offset >= ps_dec->s_bit_stream.u4_max_offset)
|
|
{
|
|
ps_dec->u4_error_code = IMPEG2D_BITSTREAM_BUFF_EXCEEDED_ERR;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Detecting next slice start code */
|
|
while(1)
|
|
{
|
|
// skip (dec->u4_num_cores-1) rows
|
|
u4_bits_read = impeg2d_bit_stream_nxt(&ps_dec->s_bit_stream,START_CODE_LEN);
|
|
temp = u4_bits_read & 0xFF;
|
|
i4_continue_decode = (((u4_bits_read >> 8) == 0x01) && (temp) && (temp <= 0xAF));
|
|
|
|
if (1 == ps_dec->i4_num_cores && 0 == ps_dec->u2_num_mbs_left)
|
|
{
|
|
i4_continue_decode = 0;
|
|
#ifdef __ANDROID__
|
|
android_errorWriteLog(0x534e4554, "26070014");
|
|
#endif
|
|
}
|
|
|
|
if(i4_continue_decode)
|
|
{
|
|
if (0 != ps_dec->u2_num_mbs_left)
|
|
{
|
|
/* If the slice is from the same row, then continue decoding without dequeue */
|
|
if((temp - 1) == i4_cur_row)
|
|
{
|
|
i4_dequeue_job = 0;
|
|
}
|
|
else
|
|
{
|
|
if(temp < ps_dec->i4_end_mb_y)
|
|
{
|
|
i4_cur_row = ps_dec->u2_mb_y;
|
|
}
|
|
else
|
|
{
|
|
i4_dequeue_job = 1;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
i4_dequeue_job = 1;
|
|
}
|
|
break;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
|
|
}while(i4_continue_decode);
|
|
if(ps_dec->i4_num_cores > 1)
|
|
{
|
|
while(1)
|
|
{
|
|
job_t s_job;
|
|
IV_API_CALL_STATUS_T e_ret;
|
|
|
|
e_ret = impeg2_jobq_dequeue(ps_dec->pv_jobq, &s_job, sizeof(s_job), 1, 1);
|
|
if(e_ret != IV_SUCCESS)
|
|
break;
|
|
if(CMD_FMTCONV == s_job.i4_cmd)
|
|
{
|
|
WORD32 start_row;
|
|
WORD32 num_rows;
|
|
start_row = s_job.i2_start_mb_y << 4;
|
|
num_rows = MIN((s_job.i2_end_mb_y << 4), ps_dec->u2_vertical_size);
|
|
num_rows -= start_row;
|
|
if(ps_dec->u4_deinterlace && (0 == ps_dec->u2_progressive_frame))
|
|
{
|
|
impeg2d_deinterlace(ps_dec,
|
|
ps_dec->ps_disp_pic,
|
|
ps_dec->ps_disp_frm_buf,
|
|
start_row,
|
|
num_rows);
|
|
|
|
}
|
|
else
|
|
{
|
|
impeg2d_format_convert(ps_dec,
|
|
ps_dec->ps_disp_pic,
|
|
ps_dec->ps_disp_frm_buf,
|
|
start_row,
|
|
num_rows);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if((NULL != ps_dec->ps_disp_pic) && ((0 == ps_dec->u4_share_disp_buf) || (IV_YUV_420P != ps_dec->i4_chromaFormat)))
|
|
{
|
|
if(ps_dec->u4_deinterlace && (0 == ps_dec->u2_progressive_frame))
|
|
{
|
|
impeg2d_deinterlace(ps_dec,
|
|
ps_dec->ps_disp_pic,
|
|
ps_dec->ps_disp_frm_buf,
|
|
0,
|
|
ps_dec->u2_vertical_size);
|
|
|
|
}
|
|
else
|
|
{
|
|
impeg2d_format_convert(ps_dec, ps_dec->ps_disp_pic,
|
|
ps_dec->ps_disp_frm_buf,
|
|
0, ps_dec->u2_vertical_size);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static WORD32 impeg2d_init_thread_dec_ctxt(dec_state_t *ps_dec,
|
|
dec_state_t *ps_dec_thd,
|
|
WORD32 i4_min_mb_y)
|
|
{
|
|
UNUSED(i4_min_mb_y);
|
|
ps_dec_thd->i4_start_mb_y = 0;
|
|
ps_dec_thd->i4_end_mb_y = ps_dec->u2_num_vert_mb;
|
|
ps_dec_thd->u2_mb_x = 0;
|
|
ps_dec_thd->u2_mb_y = 0;
|
|
ps_dec_thd->u2_is_mpeg2 = ps_dec->u2_is_mpeg2;
|
|
ps_dec_thd->i4_pic_count = ps_dec->i4_pic_count;
|
|
ps_dec_thd->u2_frame_width = ps_dec->u2_frame_width;
|
|
ps_dec_thd->u2_frame_height = ps_dec->u2_frame_height;
|
|
ps_dec_thd->u2_picture_width = ps_dec->u2_picture_width;
|
|
ps_dec_thd->u2_horizontal_size = ps_dec->u2_horizontal_size;
|
|
ps_dec_thd->u2_vertical_size = ps_dec->u2_vertical_size;
|
|
ps_dec_thd->u2_create_max_width = ps_dec->u2_create_max_width;
|
|
ps_dec_thd->u2_create_max_height = ps_dec->u2_create_max_height;
|
|
ps_dec_thd->u2_header_done = ps_dec->u2_header_done;
|
|
ps_dec_thd->u2_decode_header = ps_dec->u2_decode_header;
|
|
|
|
ps_dec_thd->u2_num_horiz_mb = ps_dec->u2_num_horiz_mb;
|
|
ps_dec_thd->u2_num_vert_mb = ps_dec->u2_num_vert_mb;
|
|
ps_dec_thd->u2_num_flds_decoded = ps_dec->u2_num_flds_decoded;
|
|
|
|
ps_dec_thd->u4_frm_buf_stride = ps_dec->u4_frm_buf_stride;
|
|
|
|
ps_dec_thd->u2_field_dct = ps_dec->u2_field_dct;
|
|
ps_dec_thd->u2_read_dct_type = ps_dec->u2_read_dct_type;
|
|
|
|
ps_dec_thd->u2_read_motion_type = ps_dec->u2_read_motion_type;
|
|
ps_dec_thd->u2_motion_type = ps_dec->u2_motion_type;
|
|
|
|
ps_dec_thd->pu2_mb_type = ps_dec->pu2_mb_type;
|
|
ps_dec_thd->u2_fld_pic = ps_dec->u2_fld_pic;
|
|
ps_dec_thd->u2_frm_pic = ps_dec->u2_frm_pic;
|
|
|
|
ps_dec_thd->u2_fld_parity = ps_dec->u2_fld_parity;
|
|
|
|
ps_dec_thd->au2_fcode_data[0] = ps_dec->au2_fcode_data[0];
|
|
ps_dec_thd->au2_fcode_data[1] = ps_dec->au2_fcode_data[1];
|
|
|
|
ps_dec_thd->u1_quant_scale = ps_dec->u1_quant_scale;
|
|
|
|
ps_dec_thd->u2_num_mbs_left = ps_dec->u2_num_mbs_left;
|
|
ps_dec_thd->u2_first_mb = ps_dec->u2_first_mb;
|
|
ps_dec_thd->u2_num_skipped_mbs = ps_dec->u2_num_skipped_mbs;
|
|
|
|
memcpy(&ps_dec_thd->s_cur_frm_buf, &ps_dec->s_cur_frm_buf, sizeof(yuv_buf_t));
|
|
memcpy(&ps_dec_thd->as_recent_fld[0][0], &ps_dec->as_recent_fld[0][0], sizeof(yuv_buf_t));
|
|
memcpy(&ps_dec_thd->as_recent_fld[0][1], &ps_dec->as_recent_fld[0][1], sizeof(yuv_buf_t));
|
|
memcpy(&ps_dec_thd->as_recent_fld[1][0], &ps_dec->as_recent_fld[1][0], sizeof(yuv_buf_t));
|
|
memcpy(&ps_dec_thd->as_recent_fld[1][1], &ps_dec->as_recent_fld[1][1], sizeof(yuv_buf_t));
|
|
memcpy(&ps_dec_thd->as_ref_buf, &ps_dec->as_ref_buf, sizeof(yuv_buf_t) * 2 * 2);
|
|
|
|
|
|
ps_dec_thd->pf_decode_slice = ps_dec->pf_decode_slice;
|
|
|
|
ps_dec_thd->pf_vld_inv_quant = ps_dec->pf_vld_inv_quant;
|
|
|
|
memcpy(ps_dec_thd->pf_idct_recon, ps_dec->pf_idct_recon, sizeof(ps_dec->pf_idct_recon));
|
|
|
|
memcpy(ps_dec_thd->pf_mc, ps_dec->pf_mc, sizeof(ps_dec->pf_mc));
|
|
ps_dec_thd->pf_interpolate = ps_dec->pf_interpolate;
|
|
ps_dec_thd->pf_copy_mb = ps_dec->pf_copy_mb;
|
|
ps_dec_thd->pf_fullx_halfy_8x8 = ps_dec->pf_fullx_halfy_8x8;
|
|
ps_dec_thd->pf_halfx_fully_8x8 = ps_dec->pf_halfx_fully_8x8;
|
|
ps_dec_thd->pf_halfx_halfy_8x8 = ps_dec->pf_halfx_halfy_8x8;
|
|
ps_dec_thd->pf_fullx_fully_8x8 = ps_dec->pf_fullx_fully_8x8;
|
|
|
|
ps_dec_thd->pf_memset_8bit_8x8_block = ps_dec->pf_memset_8bit_8x8_block;
|
|
ps_dec_thd->pf_memset_16bit_8x8_linear_block = ps_dec->pf_memset_16bit_8x8_linear_block;
|
|
ps_dec_thd->pf_copy_yuv420p_buf = ps_dec->pf_copy_yuv420p_buf;
|
|
ps_dec_thd->pf_fmt_conv_yuv420p_to_yuv422ile = ps_dec->pf_fmt_conv_yuv420p_to_yuv422ile;
|
|
ps_dec_thd->pf_fmt_conv_yuv420p_to_yuv420sp_uv = ps_dec->pf_fmt_conv_yuv420p_to_yuv420sp_uv;
|
|
ps_dec_thd->pf_fmt_conv_yuv420p_to_yuv420sp_vu = ps_dec->pf_fmt_conv_yuv420p_to_yuv420sp_vu;
|
|
|
|
|
|
memcpy(ps_dec_thd->au1_intra_quant_matrix, ps_dec->au1_intra_quant_matrix, NUM_PELS_IN_BLOCK * sizeof(UWORD8));
|
|
memcpy(ps_dec_thd->au1_inter_quant_matrix, ps_dec->au1_inter_quant_matrix, NUM_PELS_IN_BLOCK * sizeof(UWORD8));
|
|
ps_dec_thd->pu1_inv_scan_matrix = ps_dec->pu1_inv_scan_matrix;
|
|
|
|
|
|
ps_dec_thd->u2_progressive_sequence = ps_dec->u2_progressive_sequence;
|
|
ps_dec_thd->e_pic_type = ps_dec->e_pic_type;
|
|
ps_dec_thd->u2_full_pel_forw_vector = ps_dec->u2_full_pel_forw_vector;
|
|
ps_dec_thd->u2_forw_f_code = ps_dec->u2_forw_f_code;
|
|
ps_dec_thd->u2_full_pel_back_vector = ps_dec->u2_full_pel_back_vector;
|
|
ps_dec_thd->u2_back_f_code = ps_dec->u2_back_f_code;
|
|
|
|
memcpy(ps_dec_thd->ai2_mv, ps_dec->ai2_mv, (2*2*2)*sizeof(WORD16));
|
|
memcpy(ps_dec_thd->au2_f_code, ps_dec->au2_f_code, (2*2)*sizeof(UWORD16));
|
|
ps_dec_thd->u2_intra_dc_precision = ps_dec->u2_intra_dc_precision;
|
|
ps_dec_thd->u2_picture_structure = ps_dec->u2_picture_structure;
|
|
ps_dec_thd->u2_top_field_first = ps_dec->u2_top_field_first;
|
|
ps_dec_thd->u2_frame_pred_frame_dct = ps_dec->u2_frame_pred_frame_dct;
|
|
ps_dec_thd->u2_concealment_motion_vectors = ps_dec->u2_concealment_motion_vectors;
|
|
ps_dec_thd->u2_q_scale_type = ps_dec->u2_q_scale_type;
|
|
ps_dec_thd->u2_intra_vlc_format = ps_dec->u2_intra_vlc_format;
|
|
ps_dec_thd->u2_alternate_scan = ps_dec->u2_alternate_scan;
|
|
ps_dec_thd->u2_repeat_first_field = ps_dec->u2_repeat_first_field;
|
|
ps_dec_thd->u2_progressive_frame = ps_dec->u2_progressive_frame;
|
|
ps_dec_thd->pu1_inp_bits_buf = ps_dec->pu1_inp_bits_buf;
|
|
ps_dec_thd->u4_num_inp_bytes = ps_dec->u4_num_inp_bytes;
|
|
ps_dec_thd->pv_jobq = ps_dec->pv_jobq;
|
|
ps_dec_thd->pv_jobq_buf = ps_dec->pv_jobq_buf;
|
|
ps_dec_thd->i4_jobq_buf_size = ps_dec->i4_jobq_buf_size;
|
|
|
|
|
|
ps_dec_thd->u2_frame_rate_code = ps_dec->u2_frame_rate_code;
|
|
ps_dec_thd->u2_frame_rate_extension_n = ps_dec->u2_frame_rate_extension_n;
|
|
ps_dec_thd->u2_frame_rate_extension_d = ps_dec->u2_frame_rate_extension_d;
|
|
ps_dec_thd->u2_framePeriod = ps_dec->u2_framePeriod;
|
|
ps_dec_thd->u2_display_horizontal_size = ps_dec->u2_display_horizontal_size;
|
|
ps_dec_thd->u2_display_vertical_size = ps_dec->u2_display_vertical_size;
|
|
ps_dec_thd->u2_aspect_ratio_info = ps_dec->u2_aspect_ratio_info;
|
|
|
|
ps_dec_thd->ps_func_bi_direct = ps_dec->ps_func_bi_direct;
|
|
ps_dec_thd->ps_func_forw_or_back = ps_dec->ps_func_forw_or_back;
|
|
ps_dec_thd->pv_deinterlacer_ctxt = ps_dec->pv_deinterlacer_ctxt;
|
|
ps_dec_thd->ps_deint_pic = ps_dec->ps_deint_pic;
|
|
ps_dec_thd->pu1_deint_fmt_buf = ps_dec->pu1_deint_fmt_buf;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
WORD32 impeg2d_get_slice_pos(dec_state_multi_core_t *ps_dec_state_multi_core)
|
|
{
|
|
WORD32 u4_bits;
|
|
WORD32 i4_row;
|
|
|
|
|
|
dec_state_t *ps_dec = ps_dec_state_multi_core->ps_dec_state[0];
|
|
WORD32 i4_prev_row;
|
|
stream_t s_bitstrm;
|
|
WORD32 i4_start_row;
|
|
WORD32 i4_slice_bistream_ofst;
|
|
WORD32 i;
|
|
s_bitstrm = ps_dec->s_bit_stream;
|
|
i4_prev_row = -1;
|
|
|
|
ps_dec_state_multi_core->ps_dec_state[0]->i4_start_mb_y = 0;
|
|
ps_dec_state_multi_core->ps_dec_state[1]->i4_start_mb_y = -1;
|
|
ps_dec_state_multi_core->ps_dec_state[2]->i4_start_mb_y = -1;
|
|
ps_dec_state_multi_core->ps_dec_state[3]->i4_start_mb_y = -1;
|
|
|
|
ps_dec_state_multi_core->ps_dec_state[0]->i4_end_mb_y = ps_dec->u2_num_vert_mb;
|
|
ps_dec_state_multi_core->ps_dec_state[1]->i4_end_mb_y = -1;
|
|
ps_dec_state_multi_core->ps_dec_state[2]->i4_end_mb_y = -1;
|
|
ps_dec_state_multi_core->ps_dec_state[3]->i4_end_mb_y = -1;
|
|
|
|
if(ps_dec->i4_num_cores == 1)
|
|
return 0;
|
|
/* Reset the jobq to start of the jobq buffer */
|
|
impeg2_jobq_reset((jobq_t *)ps_dec->pv_jobq);
|
|
|
|
i4_start_row = -1;
|
|
i4_slice_bistream_ofst = 0;
|
|
while(1)
|
|
{
|
|
WORD32 i4_is_slice;
|
|
|
|
if(s_bitstrm.u4_offset + START_CODE_LEN >= s_bitstrm.u4_max_offset)
|
|
{
|
|
break;
|
|
}
|
|
u4_bits = impeg2d_bit_stream_nxt(&s_bitstrm,START_CODE_LEN);
|
|
|
|
i4_row = u4_bits & 0xFF;
|
|
|
|
/* Detect end of frame */
|
|
i4_is_slice = (((u4_bits >> 8) == 0x01) && (i4_row) && (i4_row <= ps_dec->u2_num_vert_mb));
|
|
if(!i4_is_slice)
|
|
break;
|
|
|
|
i4_row -= 1;
|
|
|
|
|
|
if(i4_prev_row < i4_row)
|
|
{
|
|
/* Create a job for previous slice row */
|
|
if(i4_start_row != -1)
|
|
{
|
|
job_t s_job;
|
|
IV_API_CALL_STATUS_T ret;
|
|
s_job.i2_start_mb_y = i4_start_row;
|
|
s_job.i2_end_mb_y = i4_row;
|
|
s_job.i4_cmd = CMD_PROCESS;
|
|
s_job.i4_bistream_ofst = i4_slice_bistream_ofst;
|
|
ret = impeg2_jobq_queue(ps_dec->pv_jobq, &s_job, sizeof(s_job), 1, 0);
|
|
if(ret != IV_SUCCESS)
|
|
return ret;
|
|
|
|
}
|
|
/* Store current slice's bitstream offset */
|
|
i4_slice_bistream_ofst = s_bitstrm.u4_offset >> 3;
|
|
i4_slice_bistream_ofst -= (size_t)s_bitstrm.pv_bs_buf & 3;
|
|
i4_prev_row = i4_row;
|
|
|
|
/* Store current slice's row position */
|
|
i4_start_row = i4_row;
|
|
|
|
}
|
|
#ifdef __ANDROID__
|
|
else if (i4_prev_row > i4_row)
|
|
{
|
|
android_errorWriteLog(0x534e4554, "26070014");
|
|
}
|
|
#endif
|
|
|
|
impeg2d_bit_stream_flush(&s_bitstrm, START_CODE_LEN);
|
|
|
|
// flush bytes till next start code
|
|
/* Flush the bytes till a start code is encountered */
|
|
while(impeg2d_bit_stream_nxt(&s_bitstrm, 24) != START_CODE_PREFIX)
|
|
{
|
|
impeg2d_bit_stream_get(&s_bitstrm, 8);
|
|
|
|
if(s_bitstrm.u4_offset >= s_bitstrm.u4_max_offset)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Create job for the last slice row */
|
|
{
|
|
job_t s_job;
|
|
IV_API_CALL_STATUS_T e_ret;
|
|
s_job.i2_start_mb_y = i4_start_row;
|
|
s_job.i2_end_mb_y = ps_dec->u2_num_vert_mb;
|
|
s_job.i4_cmd = CMD_PROCESS;
|
|
s_job.i4_bistream_ofst = i4_slice_bistream_ofst;
|
|
e_ret = impeg2_jobq_queue(ps_dec->pv_jobq, &s_job, sizeof(s_job), 1, 0);
|
|
if(e_ret != IV_SUCCESS)
|
|
return e_ret;
|
|
|
|
}
|
|
if((NULL != ps_dec->ps_disp_pic) && ((0 == ps_dec->u4_share_disp_buf) || (IV_YUV_420P != ps_dec->i4_chromaFormat)))
|
|
{
|
|
for(i = 0; i < ps_dec->u2_vertical_size; i+=64)
|
|
{
|
|
job_t s_job;
|
|
IV_API_CALL_STATUS_T ret;
|
|
s_job.i2_start_mb_y = i;
|
|
s_job.i2_start_mb_y >>= 4;
|
|
s_job.i2_end_mb_y = (i + 64);
|
|
s_job.i2_end_mb_y >>= 4;
|
|
s_job.i4_cmd = CMD_FMTCONV;
|
|
s_job.i4_bistream_ofst = 0;
|
|
ret = impeg2_jobq_queue(ps_dec->pv_jobq, &s_job, sizeof(s_job), 1, 0);
|
|
if(ret != IV_SUCCESS)
|
|
return ret;
|
|
|
|
}
|
|
}
|
|
|
|
impeg2_jobq_terminate(ps_dec->pv_jobq);
|
|
ps_dec->i4_bytes_consumed = s_bitstrm.u4_offset >> 3;
|
|
ps_dec->i4_bytes_consumed -= ((size_t)s_bitstrm.pv_bs_buf & 3);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* Function Name : impeg2d_dec_pic_data
|
|
*
|
|
* Description : It intializes several parameters and decodes a Picture
|
|
* till any slice is left.
|
|
*
|
|
* Arguments :
|
|
* dec : Decoder context
|
|
*
|
|
* Values Returned : None
|
|
*******************************************************************************/
|
|
|
|
void impeg2d_dec_pic_data(dec_state_t *ps_dec)
|
|
{
|
|
|
|
WORD32 i;
|
|
dec_state_multi_core_t *ps_dec_state_multi_core;
|
|
|
|
dec_state_t *ps_dec_thd;
|
|
WORD32 i4_status;
|
|
WORD32 i4_min_mb_y;
|
|
|
|
|
|
/* Resetting the MB address and MB coordinates at the start of the Frame */
|
|
ps_dec->u2_mb_x = ps_dec->u2_mb_y = 0;
|
|
|
|
ps_dec_state_multi_core = ps_dec->ps_dec_state_multi_core;
|
|
impeg2d_get_slice_pos(ps_dec_state_multi_core);
|
|
|
|
i4_min_mb_y = 1;
|
|
for(i=0; i < ps_dec->i4_num_cores - 1; i++)
|
|
{
|
|
// initialize decoder context for thread
|
|
// launch dec->u4_num_cores-1 threads
|
|
|
|
ps_dec_thd = ps_dec_state_multi_core->ps_dec_state[i+1];
|
|
|
|
ps_dec_thd->ps_disp_pic = ps_dec->ps_disp_pic;
|
|
ps_dec_thd->ps_disp_frm_buf = ps_dec->ps_disp_frm_buf;
|
|
|
|
i4_status = impeg2d_init_thread_dec_ctxt(ps_dec, ps_dec_thd, i4_min_mb_y);
|
|
//impeg2d_dec_pic_data_thread(ps_dec_thd);
|
|
|
|
if(i4_status == 0)
|
|
{
|
|
ithread_create(ps_dec_thd->pv_codec_thread_handle, NULL, (void *)impeg2d_dec_pic_data_thread, ps_dec_thd);
|
|
ps_dec_state_multi_core->au4_thread_launched[i + 1] = 1;
|
|
i4_min_mb_y = ps_dec_thd->u2_mb_y + 1;
|
|
}
|
|
else
|
|
{
|
|
ps_dec_state_multi_core->au4_thread_launched[i + 1] = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
impeg2d_dec_pic_data_thread(ps_dec);
|
|
|
|
// wait for threads to complete
|
|
for(i=0; i < (ps_dec->i4_num_cores - 1); i++)
|
|
{
|
|
if(ps_dec_state_multi_core->au4_thread_launched[i + 1] == 1)
|
|
{
|
|
ps_dec_thd = ps_dec_state_multi_core->ps_dec_state[i+1];
|
|
ithread_join(ps_dec_thd->pv_codec_thread_handle, NULL);
|
|
}
|
|
}
|
|
|
|
}
|
|
/*******************************************************************************
|
|
*
|
|
* Function Name : impeg2d_flush_ext_and_user_data
|
|
*
|
|
* Description : Flushes the extension and user data present in the
|
|
* stream_t
|
|
*
|
|
* Arguments :
|
|
* dec : Decoder context
|
|
*
|
|
* Values Returned : None
|
|
*******************************************************************************/
|
|
void impeg2d_flush_ext_and_user_data(dec_state_t *ps_dec)
|
|
{
|
|
UWORD32 u4_start_code;
|
|
stream_t *ps_stream;
|
|
|
|
ps_stream = &ps_dec->s_bit_stream;
|
|
u4_start_code = impeg2d_bit_stream_nxt(ps_stream,START_CODE_LEN);
|
|
|
|
while((u4_start_code == EXTENSION_START_CODE || u4_start_code == USER_DATA_START_CODE) &&
|
|
(ps_stream->u4_offset < ps_stream->u4_max_offset))
|
|
{
|
|
impeg2d_bit_stream_flush(ps_stream,START_CODE_LEN);
|
|
while(impeg2d_bit_stream_nxt(ps_stream,START_CODE_PREFIX_LEN) != START_CODE_PREFIX &&
|
|
(ps_stream->u4_offset < ps_stream->u4_max_offset))
|
|
{
|
|
impeg2d_bit_stream_flush(ps_stream,8);
|
|
}
|
|
u4_start_code = impeg2d_bit_stream_nxt(ps_stream,START_CODE_LEN);
|
|
}
|
|
}
|
|
/*******************************************************************************
|
|
*
|
|
* Function Name : impeg2d_dec_user_data
|
|
*
|
|
* Description : Flushes the user data present in the stream_t
|
|
*
|
|
* Arguments :
|
|
* dec : Decoder context
|
|
*
|
|
* Values Returned : None
|
|
*******************************************************************************/
|
|
void impeg2d_dec_user_data(dec_state_t *ps_dec)
|
|
{
|
|
UWORD32 u4_start_code;
|
|
stream_t *ps_stream;
|
|
|
|
ps_stream = &ps_dec->s_bit_stream;
|
|
u4_start_code = impeg2d_bit_stream_nxt(ps_stream,START_CODE_LEN);
|
|
|
|
while(u4_start_code == USER_DATA_START_CODE)
|
|
{
|
|
impeg2d_bit_stream_flush(ps_stream,START_CODE_LEN);
|
|
while((impeg2d_bit_stream_nxt(ps_stream,START_CODE_PREFIX_LEN) != START_CODE_PREFIX) &&
|
|
(ps_stream->u4_offset < ps_stream->u4_max_offset))
|
|
{
|
|
impeg2d_bit_stream_flush(ps_stream,8);
|
|
}
|
|
u4_start_code = impeg2d_bit_stream_nxt(ps_stream,START_CODE_LEN);
|
|
}
|
|
}
|
|
/*******************************************************************************
|
|
* Function Name : impeg2d_dec_seq_ext_data
|
|
*
|
|
* Description : Decodes the extension data following Sequence
|
|
* Extension. It flushes any user data if present
|
|
*
|
|
* Arguments :
|
|
* dec : Decoder context
|
|
*
|
|
* Values Returned : None
|
|
*******************************************************************************/
|
|
IMPEG2D_ERROR_CODES_T impeg2d_dec_seq_ext_data(dec_state_t *ps_dec)
|
|
{
|
|
stream_t *ps_stream;
|
|
UWORD32 u4_start_code;
|
|
IMPEG2D_ERROR_CODES_T e_error;
|
|
|
|
e_error = (IMPEG2D_ERROR_CODES_T) IVD_ERROR_NONE;
|
|
|
|
ps_stream = &ps_dec->s_bit_stream;
|
|
u4_start_code = impeg2d_bit_stream_nxt(ps_stream,START_CODE_LEN);
|
|
while( (u4_start_code == EXTENSION_START_CODE ||
|
|
u4_start_code == USER_DATA_START_CODE) &&
|
|
(IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE == e_error &&
|
|
(ps_stream->u4_offset < ps_stream->u4_max_offset))
|
|
{
|
|
if(u4_start_code == USER_DATA_START_CODE)
|
|
{
|
|
impeg2d_dec_user_data(ps_dec);
|
|
}
|
|
else
|
|
{
|
|
impeg2d_bit_stream_flush(ps_stream,START_CODE_LEN);
|
|
u4_start_code = impeg2d_bit_stream_nxt(ps_stream,EXT_ID_LEN);
|
|
switch(u4_start_code)
|
|
{
|
|
case SEQ_DISPLAY_EXT_ID:
|
|
impeg2d_dec_seq_disp_ext(ps_dec);
|
|
break;
|
|
case SEQ_SCALABLE_EXT_ID:
|
|
e_error = IMPEG2D_SCALABILITIY_NOT_SUPPORTED;
|
|
break;
|
|
default:
|
|
/* In case its a reserved extension code */
|
|
impeg2d_bit_stream_flush(ps_stream,EXT_ID_LEN);
|
|
impeg2d_peek_next_start_code(ps_dec);
|
|
break;
|
|
}
|
|
}
|
|
u4_start_code = impeg2d_bit_stream_nxt(ps_stream,START_CODE_LEN);
|
|
}
|
|
return e_error;
|
|
}
|
|
/*******************************************************************************
|
|
* Function Name : impeg2d_dec_pic_ext_data
|
|
*
|
|
* Description : Decodes the extension data following Picture Coding
|
|
* Extension. It flushes any user data if present
|
|
*
|
|
* Arguments :
|
|
* dec : Decoder context
|
|
*
|
|
* Values Returned : None
|
|
*******************************************************************************/
|
|
IMPEG2D_ERROR_CODES_T impeg2d_dec_pic_ext_data(dec_state_t *ps_dec)
|
|
{
|
|
stream_t *ps_stream;
|
|
UWORD32 u4_start_code;
|
|
IMPEG2D_ERROR_CODES_T e_error;
|
|
|
|
e_error = (IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE;
|
|
|
|
ps_stream = &ps_dec->s_bit_stream;
|
|
u4_start_code = impeg2d_bit_stream_nxt(ps_stream,START_CODE_LEN);
|
|
while ( (u4_start_code == EXTENSION_START_CODE ||
|
|
u4_start_code == USER_DATA_START_CODE) &&
|
|
(IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE == e_error &&
|
|
(ps_stream->u4_offset < ps_stream->u4_max_offset))
|
|
{
|
|
if(u4_start_code == USER_DATA_START_CODE)
|
|
{
|
|
impeg2d_dec_user_data(ps_dec);
|
|
}
|
|
else
|
|
{
|
|
impeg2d_bit_stream_flush(ps_stream,START_CODE_LEN);
|
|
u4_start_code = impeg2d_bit_stream_nxt(ps_stream,EXT_ID_LEN);
|
|
switch(u4_start_code)
|
|
{
|
|
case QUANT_MATRIX_EXT_ID:
|
|
impeg2d_dec_quant_matrix_ext(ps_dec);
|
|
break;
|
|
case COPYRIGHT_EXT_ID:
|
|
impeg2d_dec_copyright_ext(ps_dec);
|
|
break;
|
|
case PIC_DISPLAY_EXT_ID:
|
|
impeg2d_dec_pic_disp_ext(ps_dec);
|
|
break;
|
|
case CAMERA_PARAM_EXT_ID:
|
|
impeg2d_dec_cam_param_ext(ps_dec);
|
|
break;
|
|
case ITU_T_EXT_ID:
|
|
impeg2d_dec_itu_t_ext(ps_dec);
|
|
break;
|
|
case PIC_SPATIAL_SCALABLE_EXT_ID:
|
|
case PIC_TEMPORAL_SCALABLE_EXT_ID:
|
|
e_error = IMPEG2D_SCALABLITY_NOT_SUP;
|
|
break;
|
|
default:
|
|
/* In case its a reserved extension code */
|
|
impeg2d_bit_stream_flush(ps_stream,EXT_ID_LEN);
|
|
impeg2d_next_start_code(ps_dec);
|
|
break;
|
|
}
|
|
}
|
|
u4_start_code = impeg2d_bit_stream_nxt(ps_stream,START_CODE_LEN);
|
|
}
|
|
return e_error;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* Function Name : impeg2d_process_video_header
|
|
*
|
|
* Description : Processes video sequence header information
|
|
*
|
|
* Arguments :
|
|
* dec : Decoder context
|
|
*
|
|
* Values Returned : None
|
|
*******************************************************************************/
|
|
IMPEG2D_ERROR_CODES_T impeg2d_process_video_header(dec_state_t *ps_dec)
|
|
{
|
|
stream_t *ps_stream;
|
|
ps_stream = &ps_dec->s_bit_stream;
|
|
IMPEG2D_ERROR_CODES_T e_error;
|
|
|
|
impeg2d_next_code(ps_dec, SEQUENCE_HEADER_CODE);
|
|
if(ps_dec->s_bit_stream.u4_offset < ps_dec->s_bit_stream.u4_max_offset)
|
|
{
|
|
e_error = impeg2d_dec_seq_hdr(ps_dec);
|
|
if ((IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE != e_error)
|
|
{
|
|
return e_error;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return IMPEG2D_BITSTREAM_BUFF_EXCEEDED_ERR;
|
|
}
|
|
if (impeg2d_bit_stream_nxt(ps_stream,START_CODE_LEN) == EXTENSION_START_CODE)
|
|
{
|
|
/* MPEG2 Decoder */
|
|
if(ps_dec->s_bit_stream.u4_offset < ps_dec->s_bit_stream.u4_max_offset)
|
|
{
|
|
e_error = impeg2d_dec_seq_ext(ps_dec);
|
|
if ((IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE != e_error)
|
|
{
|
|
return e_error;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return IMPEG2D_BITSTREAM_BUFF_EXCEEDED_ERR;
|
|
}
|
|
if(ps_dec->s_bit_stream.u4_offset < ps_dec->s_bit_stream.u4_max_offset)
|
|
{
|
|
e_error = impeg2d_dec_seq_ext_data(ps_dec);
|
|
if ((IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE != e_error)
|
|
{
|
|
return e_error;
|
|
}
|
|
}
|
|
return impeg2d_init_video_state(ps_dec,MPEG_2_VIDEO);
|
|
}
|
|
else
|
|
{
|
|
/* MPEG1 Decoder */
|
|
if(ps_dec->s_bit_stream.u4_offset < ps_dec->s_bit_stream.u4_max_offset)
|
|
{
|
|
impeg2d_flush_ext_and_user_data(ps_dec);
|
|
}
|
|
return impeg2d_init_video_state(ps_dec,MPEG_1_VIDEO);
|
|
}
|
|
}
|
|
/*******************************************************************************
|
|
*
|
|
* Function Name : impeg2d_process_video_bit_stream
|
|
*
|
|
* Description : Processes video sequence header information
|
|
*
|
|
* Arguments :
|
|
* dec : Decoder context
|
|
*
|
|
* Values Returned : None
|
|
*******************************************************************************/
|
|
IMPEG2D_ERROR_CODES_T impeg2d_process_video_bit_stream(dec_state_t *ps_dec)
|
|
{
|
|
stream_t *ps_stream;
|
|
UWORD32 u4_next_bits, u4_start_code_found;
|
|
IMPEG2D_ERROR_CODES_T e_error;
|
|
|
|
ps_stream = &ps_dec->s_bit_stream;
|
|
impeg2d_next_start_code(ps_dec);
|
|
/* If the stream is MPEG-2 compliant stream */
|
|
u4_start_code_found = 0;
|
|
|
|
if(ps_dec->u2_is_mpeg2)
|
|
{
|
|
/* MPEG2 decoding starts */
|
|
while((u4_start_code_found == 0) && (ps_dec->s_bit_stream.u4_offset < ps_dec->s_bit_stream.u4_max_offset))
|
|
{
|
|
u4_next_bits = impeg2d_bit_stream_nxt(ps_stream,START_CODE_LEN);
|
|
|
|
if(u4_next_bits == SEQUENCE_HEADER_CODE)
|
|
{
|
|
if(ps_dec->s_bit_stream.u4_offset < ps_dec->s_bit_stream.u4_max_offset)
|
|
{
|
|
e_error = impeg2d_dec_seq_hdr(ps_dec);
|
|
if ((IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE != e_error)
|
|
{
|
|
return e_error;
|
|
}
|
|
|
|
u4_start_code_found = 0;
|
|
|
|
}
|
|
else
|
|
{
|
|
return IMPEG2D_BITSTREAM_BUFF_EXCEEDED_ERR;
|
|
}
|
|
|
|
|
|
if(ps_dec->s_bit_stream.u4_offset < ps_dec->s_bit_stream.u4_max_offset)
|
|
{
|
|
IMPEG2D_ERROR_CODES_T e_error;
|
|
e_error = impeg2d_dec_seq_ext(ps_dec);
|
|
if ((IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE != e_error)
|
|
{
|
|
return e_error;
|
|
}
|
|
u4_start_code_found = 0;
|
|
|
|
}
|
|
else
|
|
{
|
|
return IMPEG2D_BITSTREAM_BUFF_EXCEEDED_ERR;
|
|
}
|
|
}
|
|
else if((u4_next_bits == USER_DATA_START_CODE) || (u4_next_bits == EXTENSION_START_CODE))
|
|
{
|
|
if(ps_dec->s_bit_stream.u4_offset < ps_dec->s_bit_stream.u4_max_offset)
|
|
{
|
|
impeg2d_dec_seq_ext_data(ps_dec);
|
|
u4_start_code_found = 0;
|
|
|
|
}
|
|
|
|
}
|
|
else if((ps_dec->s_bit_stream.u4_offset < ps_dec->s_bit_stream.u4_max_offset)
|
|
&& (u4_next_bits == GOP_START_CODE))
|
|
{
|
|
impeg2d_dec_grp_of_pic_hdr(ps_dec);
|
|
impeg2d_dec_user_data(ps_dec);
|
|
u4_start_code_found = 0;
|
|
|
|
}
|
|
else if((ps_dec->s_bit_stream.u4_offset < ps_dec->s_bit_stream.u4_max_offset)
|
|
&& (u4_next_bits == PICTURE_START_CODE))
|
|
{
|
|
ps_dec->i4_pic_count++;
|
|
|
|
e_error = impeg2d_dec_pic_hdr(ps_dec);
|
|
if ((IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE != e_error)
|
|
{
|
|
return e_error;
|
|
}
|
|
e_error = impeg2d_dec_pic_coding_ext(ps_dec);
|
|
if ((IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE != e_error)
|
|
{
|
|
return e_error;
|
|
}
|
|
e_error = impeg2d_dec_pic_ext_data(ps_dec);
|
|
if ((IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE != e_error)
|
|
{
|
|
return e_error;
|
|
}
|
|
e_error = impeg2d_pre_pic_dec_proc(ps_dec);
|
|
if ((IMPEG2D_ERROR_CODES_T) IVD_ERROR_NONE != e_error)
|
|
{
|
|
return e_error;
|
|
}
|
|
impeg2d_dec_pic_data(ps_dec);
|
|
impeg2d_post_pic_dec_proc(ps_dec);
|
|
u4_start_code_found = 1;
|
|
}
|
|
else
|
|
|
|
{
|
|
FLUSH_BITS(ps_dec->s_bit_stream.u4_offset, ps_dec->s_bit_stream.u4_buf, ps_dec->s_bit_stream.u4_buf_nxt, 8, ps_dec->s_bit_stream.pu4_buf_aligned);
|
|
|
|
}
|
|
if(u4_start_code_found == 0)
|
|
{
|
|
impeg2d_next_start_code(ps_dec);
|
|
/* In case a dec_pic_data call has not been made, the number of
|
|
* bytes consumed in the previous header decode has to be
|
|
* consumed. Not consuming it will result in zero bytes consumed
|
|
* loops in case there are multiple headers and the second
|
|
* or a future header has a resolution change/other error where
|
|
* the bytes of the last header are not consumed.
|
|
*/
|
|
ps_dec->i4_bytes_consumed = (ps_dec->s_bit_stream.u4_offset + 7) >> 3;
|
|
ps_dec->i4_bytes_consumed -= ((size_t)ps_dec->s_bit_stream.pv_bs_buf & 3);
|
|
}
|
|
}
|
|
if((u4_start_code_found == 0) && (ps_dec->s_bit_stream.u4_offset > ps_dec->s_bit_stream.u4_max_offset))
|
|
{
|
|
return IMPEG2D_FRM_HDR_START_CODE_NOT_FOUND;
|
|
}
|
|
|
|
}
|
|
/* If the stream is MPEG-1 compliant stream */
|
|
else
|
|
{
|
|
while((u4_start_code_found == 0) && (ps_dec->s_bit_stream.u4_offset < ps_dec->s_bit_stream.u4_max_offset))
|
|
{
|
|
u4_next_bits = impeg2d_bit_stream_nxt(ps_stream,START_CODE_LEN);
|
|
|
|
if(impeg2d_bit_stream_nxt(ps_stream,START_CODE_LEN) == SEQUENCE_HEADER_CODE)
|
|
{
|
|
if(ps_dec->s_bit_stream.u4_offset < ps_dec->s_bit_stream.u4_max_offset)
|
|
{
|
|
e_error = impeg2d_dec_seq_hdr(ps_dec);
|
|
if ((IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE != e_error)
|
|
{
|
|
return e_error;
|
|
}
|
|
|
|
u4_start_code_found = 0;
|
|
}
|
|
else
|
|
{
|
|
return IMPEG2D_BITSTREAM_BUFF_EXCEEDED_ERR;
|
|
}
|
|
}
|
|
else if((ps_dec->s_bit_stream.u4_offset < ps_dec->s_bit_stream.u4_max_offset) && (u4_next_bits == EXTENSION_START_CODE || u4_next_bits == USER_DATA_START_CODE))
|
|
{
|
|
impeg2d_flush_ext_and_user_data(ps_dec);
|
|
u4_start_code_found = 0;
|
|
}
|
|
|
|
|
|
else if ((impeg2d_bit_stream_nxt(ps_stream,START_CODE_LEN) == GOP_START_CODE)
|
|
&& (ps_dec->s_bit_stream.u4_offset < ps_dec->s_bit_stream.u4_max_offset))
|
|
{
|
|
impeg2d_dec_grp_of_pic_hdr(ps_dec);
|
|
impeg2d_flush_ext_and_user_data(ps_dec);
|
|
u4_start_code_found = 0;
|
|
}
|
|
else if ((impeg2d_bit_stream_nxt(ps_stream,START_CODE_LEN) == PICTURE_START_CODE)
|
|
&& (ps_dec->s_bit_stream.u4_offset < ps_dec->s_bit_stream.u4_max_offset))
|
|
{
|
|
ps_dec->i4_pic_count++;
|
|
|
|
e_error = impeg2d_dec_pic_hdr(ps_dec);
|
|
if ((IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE != e_error)
|
|
{
|
|
return e_error;
|
|
}
|
|
impeg2d_flush_ext_and_user_data(ps_dec);
|
|
e_error = impeg2d_pre_pic_dec_proc(ps_dec);
|
|
if ((IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE != e_error)
|
|
{
|
|
return e_error;
|
|
}
|
|
impeg2d_dec_pic_data(ps_dec);
|
|
impeg2d_post_pic_dec_proc(ps_dec);
|
|
u4_start_code_found = 1;
|
|
}
|
|
else
|
|
{
|
|
FLUSH_BITS(ps_dec->s_bit_stream.u4_offset, ps_dec->s_bit_stream.u4_buf, ps_dec->s_bit_stream.u4_buf_nxt, 8, ps_dec->s_bit_stream.pu4_buf_aligned);
|
|
}
|
|
impeg2d_next_start_code(ps_dec);
|
|
if (0 == u4_start_code_found)
|
|
{
|
|
/* In case a dec_pic_data call has not been made, the number of
|
|
* bytes consumed in the previous header decode has to be
|
|
* consumed. Not consuming it will result in zero bytes consumed
|
|
* loops in case there are multiple headers and the second
|
|
* or a future header has a resolution change/other error where
|
|
* the bytes of the last header are not consumed.
|
|
*/
|
|
ps_dec->i4_bytes_consumed = (ps_dec->s_bit_stream.u4_offset + 7) >> 3;
|
|
ps_dec->i4_bytes_consumed -= ((size_t)ps_dec->s_bit_stream.pv_bs_buf & 3);
|
|
}
|
|
}
|
|
if((u4_start_code_found == 0) && (ps_dec->s_bit_stream.u4_offset > ps_dec->s_bit_stream.u4_max_offset))
|
|
{
|
|
return IMPEG2D_FRM_HDR_START_CODE_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
return (IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE;
|
|
}
|