mirror of
https://github.com/cemu-project/Cemu.git
synced 2024-12-27 18:21:52 +01:00
394 lines
11 KiB
C
394 lines
11 KiB
C
|
/******************************************************************************
|
||
|
*
|
||
|
* 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 ih264d_nal.c
|
||
|
*
|
||
|
* \brief NAL parsing routines
|
||
|
*
|
||
|
* Detailed_description
|
||
|
*
|
||
|
* \author
|
||
|
* - AI 19 11 2002 Creation
|
||
|
**************************************************************************
|
||
|
*/
|
||
|
#include "ih264d_bitstrm.h"
|
||
|
#include "ih264d_defs.h"
|
||
|
#include "ih264_typedefs.h"
|
||
|
#include "ih264_macros.h"
|
||
|
#include "ih264_platform_macros.h"
|
||
|
#include "ih264d_defs.h"
|
||
|
#define NUM_OF_ZERO_BYTES_BEFORE_START_CODE 2
|
||
|
#define EMULATION_PREVENTION_BYTE 0x03
|
||
|
|
||
|
#define NAL_FIRST_BYTE_SIZE 1
|
||
|
|
||
|
/*!
|
||
|
**************************************************************************
|
||
|
* \if Function name : ih264d_find_start_code \endif
|
||
|
*
|
||
|
* \brief
|
||
|
* This function searches for the Start Code Prefix.
|
||
|
*
|
||
|
* \param pu1_buf : Pointer to char buffer which contains bitstream.
|
||
|
* \param u4_cur_pos : Current position in the buffer.
|
||
|
* \param u4_max_ofst : Number of bytes in Buffer.
|
||
|
* \param pu4_length_of_start_code : Poiter to length of Start Code.
|
||
|
*
|
||
|
* \return
|
||
|
* Returns 0 on success and -1 on error.
|
||
|
*
|
||
|
**************************************************************************
|
||
|
*/
|
||
|
#define START_CODE_NOT_FOUND -1
|
||
|
#define END_OF_STREAM_BUFFER -2
|
||
|
#define END_OF_STREAM -1
|
||
|
|
||
|
void ih264d_check_if_aud(UWORD8 *pu1_buf,
|
||
|
UWORD32 u4_cur_pos,
|
||
|
UWORD32 u4_max_ofst,
|
||
|
UWORD32 *pu4_next_is_aud)
|
||
|
{
|
||
|
UWORD8 u1_first_byte, u1_nal_unit_type;
|
||
|
if(u4_cur_pos + 1 < u4_max_ofst)
|
||
|
{
|
||
|
u1_first_byte = pu1_buf[u4_cur_pos + 1];
|
||
|
u1_nal_unit_type = NAL_UNIT_TYPE(u1_first_byte);
|
||
|
|
||
|
if(u1_nal_unit_type == ACCESS_UNIT_DELIMITER_RBSP)
|
||
|
{
|
||
|
*pu4_next_is_aud = 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
WORD32 ih264d_find_start_code(UWORD8 *pu1_buf,
|
||
|
UWORD32 u4_cur_pos,
|
||
|
UWORD32 u4_max_ofst,
|
||
|
UWORD32 *pu4_length_of_start_code,
|
||
|
UWORD32 *pu4_next_is_aud)
|
||
|
{
|
||
|
WORD32 zero_byte_cnt = 0;
|
||
|
UWORD32 ui_curPosTemp;
|
||
|
|
||
|
*pu4_length_of_start_code = 0;
|
||
|
/*Find first start code */
|
||
|
while(u4_cur_pos < u4_max_ofst)
|
||
|
{
|
||
|
if(pu1_buf[u4_cur_pos] == 0)
|
||
|
zero_byte_cnt++;
|
||
|
else if(pu1_buf[u4_cur_pos]
|
||
|
== 0x01 && zero_byte_cnt >= NUM_OF_ZERO_BYTES_BEFORE_START_CODE)
|
||
|
{
|
||
|
/* Found the start code */
|
||
|
u4_cur_pos++;
|
||
|
break;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
zero_byte_cnt = 0;
|
||
|
}
|
||
|
u4_cur_pos++;
|
||
|
}
|
||
|
/*Find Next Start Code */
|
||
|
*pu4_length_of_start_code = u4_cur_pos;
|
||
|
zero_byte_cnt = 0;
|
||
|
ui_curPosTemp = u4_cur_pos;
|
||
|
while(u4_cur_pos < u4_max_ofst)
|
||
|
{
|
||
|
|
||
|
if(pu1_buf[u4_cur_pos] == 0)
|
||
|
zero_byte_cnt++;
|
||
|
else if(pu1_buf[u4_cur_pos]
|
||
|
== 0x01 && zero_byte_cnt >= NUM_OF_ZERO_BYTES_BEFORE_START_CODE)
|
||
|
{
|
||
|
/* Found the start code */
|
||
|
ih264d_check_if_aud(pu1_buf, u4_cur_pos, u4_max_ofst,
|
||
|
pu4_next_is_aud);
|
||
|
return (u4_cur_pos - zero_byte_cnt - ui_curPosTemp);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
zero_byte_cnt = 0;
|
||
|
}
|
||
|
u4_cur_pos++;
|
||
|
}
|
||
|
|
||
|
return (u4_cur_pos - zero_byte_cnt - ui_curPosTemp); //(START_CODE_NOT_FOUND);
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
**************************************************************************
|
||
|
* \if Function name : ih264d_get_next_nal_unit \endif
|
||
|
*
|
||
|
* \brief
|
||
|
* This function reads one NAl unit.
|
||
|
*
|
||
|
* \param ps_nalStream : Poiter to NalUnitStream structure.
|
||
|
* \param ps_nalUnit : Pointer to NalUnit.
|
||
|
*
|
||
|
* \return
|
||
|
* Returns 0 on success and -1 on error.
|
||
|
*
|
||
|
**************************************************************************
|
||
|
*/
|
||
|
WORD32 ih264d_get_next_nal_unit(UWORD8 *pu1_buf,
|
||
|
UWORD32 u4_cur_pos,
|
||
|
UWORD32 u4_max_ofst,
|
||
|
UWORD32 *pu4_length_of_start_code)
|
||
|
{
|
||
|
|
||
|
WORD32 i_length_of_nal_unit = 0;
|
||
|
UWORD32 u4_next_is_aud;
|
||
|
|
||
|
/* NAL Thread starts */
|
||
|
|
||
|
ih264d_find_start_code(pu1_buf, u4_cur_pos, u4_max_ofst,
|
||
|
pu4_length_of_start_code, &u4_next_is_aud);
|
||
|
|
||
|
return (i_length_of_nal_unit);
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
**************************************************************************
|
||
|
* \if Function name : ih264d_process_nal_unit \endif
|
||
|
*
|
||
|
* \brief
|
||
|
* This function removes emulation byte "0x03" from bitstream (EBSP to RBSP).
|
||
|
* It also converts bytestream format into 32 bit little-endian format.
|
||
|
*
|
||
|
* \param ps_bitstrm : Poiter to dec_bit_stream_t structure.
|
||
|
* \param pu1_nal_unit : Pointer to char buffer of NalUnit.
|
||
|
* \param u4_numbytes_in_nal_unit : Number bytes in NalUnit buffer.
|
||
|
*
|
||
|
* \return
|
||
|
* Returns number of bytes in RBSP ps_bitstrm.
|
||
|
*
|
||
|
* \note
|
||
|
* This function is same as nal_unit() of 7.3.1. Apart from nal_unit()
|
||
|
* implementation it converts char buffer into 32 bit Buffer. This
|
||
|
* facilitates efficient access of bitstream. This has been done taking
|
||
|
* into account present processor architectures.
|
||
|
*
|
||
|
**************************************************************************
|
||
|
*/
|
||
|
WORD32 ih264d_process_nal_unit(dec_bit_stream_t *ps_bitstrm,
|
||
|
UWORD8 *pu1_nal_unit,
|
||
|
UWORD32 u4_numbytes_in_nal_unit)
|
||
|
{
|
||
|
UWORD32 u4_num_bytes_in_rbsp;
|
||
|
UWORD8 u1_cur_byte;
|
||
|
WORD32 i = 0;
|
||
|
WORD8 c_count;
|
||
|
UWORD32 ui_word;
|
||
|
UWORD32 *puc_bitstream_buffer = (UWORD32*)pu1_nal_unit;
|
||
|
ps_bitstrm->pu4_buffer = puc_bitstream_buffer;
|
||
|
|
||
|
/*--------------------------------------------------------------------*/
|
||
|
/* First Byte of the NAL Unit */
|
||
|
/*--------------------------------------------------------------------*/
|
||
|
|
||
|
ui_word = *pu1_nal_unit++;
|
||
|
|
||
|
/*--------------------------------------------------------------------*/
|
||
|
/* Convertion of the EBSP to RBSP */
|
||
|
/* ie Remove the emulation_prevention_byte [equal to 0x03] */
|
||
|
/*--------------------------------------------------------------------*/
|
||
|
u4_num_bytes_in_rbsp = 0;
|
||
|
c_count = 0;
|
||
|
|
||
|
//first iteration
|
||
|
|
||
|
u1_cur_byte = *pu1_nal_unit++;
|
||
|
|
||
|
ui_word = ((ui_word << 8) | u1_cur_byte);
|
||
|
|
||
|
c_count++;
|
||
|
if(u1_cur_byte != 0x00)
|
||
|
c_count = 0;
|
||
|
|
||
|
//second iteration
|
||
|
|
||
|
u1_cur_byte = *pu1_nal_unit++;
|
||
|
|
||
|
ui_word = ((ui_word << 8) | u1_cur_byte);
|
||
|
u4_num_bytes_in_rbsp = 2;
|
||
|
|
||
|
c_count++;
|
||
|
if(u1_cur_byte != 0x00)
|
||
|
c_count = 0;
|
||
|
|
||
|
if(u4_numbytes_in_nal_unit > 2)
|
||
|
{
|
||
|
i = ((u4_numbytes_in_nal_unit - 3));
|
||
|
}
|
||
|
|
||
|
for(; i > 8; i -= 4)
|
||
|
{
|
||
|
|
||
|
// loop 0
|
||
|
u1_cur_byte = *pu1_nal_unit++;
|
||
|
|
||
|
if(c_count == NUM_OF_ZERO_BYTES_BEFORE_START_CODE
|
||
|
&& u1_cur_byte == EMULATION_PREVENTION_BYTE)
|
||
|
{
|
||
|
c_count = 0;
|
||
|
u1_cur_byte = *pu1_nal_unit++;
|
||
|
i--;
|
||
|
}
|
||
|
|
||
|
ui_word = ((ui_word << 8) | u1_cur_byte);
|
||
|
*puc_bitstream_buffer = ui_word;
|
||
|
puc_bitstream_buffer++;
|
||
|
c_count++;
|
||
|
if(u1_cur_byte != 0x00)
|
||
|
c_count = 0;
|
||
|
|
||
|
// loop 1
|
||
|
u1_cur_byte = *pu1_nal_unit++;
|
||
|
|
||
|
if(c_count == NUM_OF_ZERO_BYTES_BEFORE_START_CODE
|
||
|
&& u1_cur_byte == EMULATION_PREVENTION_BYTE)
|
||
|
{
|
||
|
c_count = 0;
|
||
|
u1_cur_byte = *pu1_nal_unit++;
|
||
|
i--;
|
||
|
}
|
||
|
ui_word = ((ui_word << 8) | u1_cur_byte);
|
||
|
|
||
|
c_count++;
|
||
|
if(u1_cur_byte != 0x00)
|
||
|
c_count = 0;
|
||
|
|
||
|
// loop 2
|
||
|
u1_cur_byte = *pu1_nal_unit++;
|
||
|
|
||
|
if(c_count == NUM_OF_ZERO_BYTES_BEFORE_START_CODE
|
||
|
&& u1_cur_byte == EMULATION_PREVENTION_BYTE)
|
||
|
{
|
||
|
c_count = 0;
|
||
|
u1_cur_byte = *pu1_nal_unit++;
|
||
|
i--;
|
||
|
}
|
||
|
|
||
|
ui_word = ((ui_word << 8) | u1_cur_byte);
|
||
|
|
||
|
c_count++;
|
||
|
if(u1_cur_byte != 0x00)
|
||
|
c_count = 0;
|
||
|
|
||
|
// loop 3
|
||
|
u1_cur_byte = *pu1_nal_unit++;
|
||
|
|
||
|
if(c_count == NUM_OF_ZERO_BYTES_BEFORE_START_CODE
|
||
|
&& u1_cur_byte == EMULATION_PREVENTION_BYTE)
|
||
|
{
|
||
|
c_count = 0;
|
||
|
u1_cur_byte = *pu1_nal_unit++;
|
||
|
i--;
|
||
|
}
|
||
|
|
||
|
ui_word = ((ui_word << 8) | u1_cur_byte);
|
||
|
|
||
|
c_count++;
|
||
|
if(u1_cur_byte != 0x00)
|
||
|
c_count = 0;
|
||
|
|
||
|
u4_num_bytes_in_rbsp += 4;
|
||
|
|
||
|
}
|
||
|
|
||
|
for(; i > 0; i--)
|
||
|
{
|
||
|
u1_cur_byte = *pu1_nal_unit++;
|
||
|
|
||
|
if(c_count == NUM_OF_ZERO_BYTES_BEFORE_START_CODE
|
||
|
&& u1_cur_byte == EMULATION_PREVENTION_BYTE)
|
||
|
{
|
||
|
c_count = 0;
|
||
|
i--;
|
||
|
u1_cur_byte = *pu1_nal_unit++;
|
||
|
}
|
||
|
|
||
|
ui_word = ((ui_word << 8) | u1_cur_byte);
|
||
|
u4_num_bytes_in_rbsp++;
|
||
|
|
||
|
if((u4_num_bytes_in_rbsp & 0x03) == 0x03)
|
||
|
{
|
||
|
*puc_bitstream_buffer = ui_word;
|
||
|
puc_bitstream_buffer++;
|
||
|
}
|
||
|
c_count++;
|
||
|
if(u1_cur_byte != 0x00)
|
||
|
c_count = 0;
|
||
|
|
||
|
}
|
||
|
|
||
|
*puc_bitstream_buffer = (ui_word
|
||
|
<< ((3 - (((u4_num_bytes_in_rbsp << 30) >> 30))) << 3));
|
||
|
ps_bitstrm->u4_ofst = 0;
|
||
|
ps_bitstrm->u4_max_ofst = ((u4_num_bytes_in_rbsp + NAL_FIRST_BYTE_SIZE) << 3);
|
||
|
|
||
|
return (u4_num_bytes_in_rbsp);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*!
|
||
|
**************************************************************************
|
||
|
* \if Function name : ih264d_rbsp_to_sodb \endif
|
||
|
*
|
||
|
* \brief
|
||
|
* This function converts RBSP to SODB.
|
||
|
*
|
||
|
* \param ps_bitstrm : Poiter to dec_bit_stream_t structure.
|
||
|
*
|
||
|
* \return
|
||
|
* None.
|
||
|
*
|
||
|
**************************************************************************
|
||
|
*/
|
||
|
void ih264d_rbsp_to_sodb(dec_bit_stream_t *ps_bitstrm)
|
||
|
{
|
||
|
UWORD32 ui_lastWord;
|
||
|
UWORD32 ui_word;
|
||
|
UWORD8 uc_lastByte;
|
||
|
WORD8 i;
|
||
|
|
||
|
ui_lastWord = (ps_bitstrm->u4_max_ofst >> 5);
|
||
|
i = (ps_bitstrm->u4_max_ofst >> 3) & 0x03;
|
||
|
|
||
|
if(i)
|
||
|
{
|
||
|
ui_word = ps_bitstrm->pu4_buffer[ui_lastWord];
|
||
|
uc_lastByte = ((ui_word << ((i - 1) << 3)) >> 24);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ui_word = ps_bitstrm->pu4_buffer[ui_lastWord - 1];
|
||
|
uc_lastByte = ((ui_word << 24) >> 24);
|
||
|
}
|
||
|
/*--------------------------------------------------------------------*/
|
||
|
/* Find out the rbsp_stop_bit position in the last byte of rbsp */
|
||
|
/*--------------------------------------------------------------------*/
|
||
|
for(i = 0; (i < 8) && !CHECKBIT(uc_lastByte, i); ++i)
|
||
|
;
|
||
|
ps_bitstrm->u4_max_ofst = ps_bitstrm->u4_max_ofst - (i + 1);
|
||
|
}
|