blob: 7202f982eba516c2c0fff136e573ab3017e4e3a7 [file] [log] [blame]
/* ------------------------------------------------------------------
* Copyright (C) 1998-2009 PacketVideo
*
* 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.
* -------------------------------------------------------------------
*/
/*
* ------------------------------------------------------------------- *
* MPEG-4 Simple Profile Video Decoder *
* ------------------------------------------------------------------- *
*
* This software module was originally developed by
*
* Paulo Nunes (IST / ACTS-MoMuSyS)
* Robert Danielsen (Telenor / ACTS-MoMuSyS)
*
* in the course of development of the MPEG-4 Video (ISO/IEC 14496-2) standard.
* This software module is an implementation of a part of one or more MPEG-4
* Video (ISO/IEC 14496-2) tools as specified by the MPEG-4 Video (ISO/IEC
* 14496-2) standard.
*
* ISO/IEC gives users of the MPEG-4 Video (ISO/IEC 14496-2) standard free
* license to this software module or modifications thereof for use in hardware
* or software products claiming conformance to the MPEG-4 Video (ISO/IEC
* 14496-2) standard.
*
* Those intending to use this software module in hardware or software products
* are advised that its use may infringe existing patents. The original
* developer of this software module and his/her company, the subsequent
* editors and their companies, and ISO/IEC have no liability for use of this
* software module or modifications thereof in an implementation. Copyright is
* not released for non MPEG-4 Video (ISO/IEC 14496-2) Standard conforming
* products.
*
* ACTS-MoMuSys partners retain full right to use the code for his/her own
* purpose, assign or donate the code to a third party and to inhibit third
* parties from using the code for non MPEG-4 Video (ISO/IEC 14496-2) Standard
* conforming products. This copyright notice must be included in all copies or
* derivative works.
*
* Copyright (c) 1996
*
*****************************************************************************/
/***********************************************************HeaderBegin*******
*
* File: vlc_dec.c
*
* Author: Paulo Nunes (IST) - Paulo.Nunes@lx.it.pt
* Created: 1-Mar-96
*
* Description: This file contains the VLC functions needed to decode a
* bitstream.
*
* Notes:
* The functions contained in this file were adapted from
* tmndecode
* Written by Karl Olav Lillevold <kol@nta.no>,
* 1995 Telenor R&D.
* Donated to the Momusys-project as background code by
* Telenor.
*
* based on mpeg2decode, (C) 1994, MPEG Software Simulation Group
* and mpeg2play, (C) 1994 Stefan Eckart
* <stefan@lis.e-technik.tu-muenchen.de>
*
*
* Modified: 9-May-96 Paulo Nunes: Reformatted. New headers.
* 17-Jan-97 Jan De Lameillieure (HHI) : corrected in
* 01.05.97 Luis Ducla-Soares: added RvlcDecTCOEF() to allow decoding
* of Reversible VLCs.
* 09.03.98 Paulo Nunes: Cleaning.
*
***********************************************************HeaderEnd*********/
#include "mp4dec_lib.h"
#include "vlc_dec_tab.h"
#include "vlc_decode.h"
#include "bitstream.h"
#include "max_level.h"
/* ====================================================================== /
Function : DecodeUserData()
Date : 04/10/2000
History :
Modified : 04/16/2001 : removed status checking of PV_BitstreamFlushBits
This is simply a realization of the user_data() function
in the ISO/IEC 14496-2 manual.
/ ====================================================================== */
PV_STATUS DecodeUserData(BitstreamDecVideo *stream)
{
PV_STATUS status;
uint32 code;
BitstreamReadBits32HC(stream);
BitstreamShowBits32(stream, 24, &code);
while (code != 1)
{
/* Discard user data for now. 04/05/2000 */
BitstreamReadBits16(stream, 8);
BitstreamShowBits32(stream, 24, &code);
status = BitstreamCheckEndBuffer(stream);
if (status == PV_END_OF_VOP) return status; /* 03/19/2002 */
}
return PV_SUCCESS;
}
/***********************************************************CommentBegin******
*
* 3/10/00 : initial modification to the
* new PV-Decoder Lib format.
* 3/29/00 : added return code check to some functions and
* optimize the code.
*
***********************************************************CommentEnd********/
PV_STATUS PV_GetMBvectors(VideoDecData *video, uint mode)
{
PV_STATUS status;
BitstreamDecVideo *stream = video->bitstream;
int f_code_f = video->currVop->fcodeForward;
int vlc_code_mag;
MOT *mot_x = video->motX;
MOT *mot_y = video->motY;
int k, offset;
int x_pos = video->mbnum_col;
int y_pos = video->mbnum_row;
int doubleWidth = video->nMBPerRow << 1;
int pos = (x_pos + y_pos * doubleWidth) << 1;
MOT mvx = 0, mvy = 0;
if (f_code_f == 1)
{
#ifdef PV_ANNEX_IJKT_SUPPORT
if (mode == MODE_INTER4V || mode == MODE_INTER4V_Q)
#else
if (mode == MODE_INTER4V)
#endif
{
for (k = 0; k < 4; k++)
{
offset = (k & 1) + (k >> 1) * doubleWidth;
mv_prediction(video, k, &mvx, &mvy);
/* decode component x */
status = PV_VlcDecMV(stream, &vlc_code_mag);
if (status != PV_SUCCESS)
{
return status;
}
mvx += (MOT)vlc_code_mag;
mvx = (MOT)(((mvx + 32) & 0x3F) - 32);
status = PV_VlcDecMV(stream, &vlc_code_mag);
if (status != PV_SUCCESS)
{
return status;
}
mvy += (MOT)vlc_code_mag;
mvy = (MOT)(((mvy + 32) & 0x3F) - 32);
mot_x[pos+offset] = (MOT) mvx;
mot_y[pos+offset] = (MOT) mvy;
}
}
else
{
mv_prediction(video, 0, &mvx, &mvy);
/* For PVOPs, field appears only in MODE_INTER & MODE_INTER_Q */
status = PV_VlcDecMV(stream, &vlc_code_mag);
if (status != PV_SUCCESS)
{
return status;
}
mvx += (MOT)vlc_code_mag;
mvx = (MOT)(((mvx + 32) & 0x3F) - 32);
status = PV_VlcDecMV(stream, &vlc_code_mag);
if (status != PV_SUCCESS)
{
return status;
}
mvy += (MOT)vlc_code_mag;
mvy = (MOT)(((mvy + 32) & 0x3F) - 32);
mot_x[pos] = mot_x[pos+1] = (MOT) mvx;
mot_y[pos] = mot_y[pos+1] = (MOT) mvy;
pos += doubleWidth;
mot_x[pos] = mot_x[pos+1] = (MOT) mvx;
mot_y[pos] = mot_y[pos+1] = (MOT) mvy;
}
}
else
{
#ifdef PV_ANNEX_IJKT_SUPPORT
if (mode == MODE_INTER4V || mode == MODE_INTER4V_Q)
#else
if (mode == MODE_INTER4V)
#endif
{
for (k = 0; k < 4; k++)
{
offset = (k & 1) + (k >> 1) * doubleWidth;
mv_prediction(video, k, &mvx, &mvy);
status = PV_DecodeMBVec(stream, &mvx, &mvy, f_code_f);
mot_x[pos+offset] = (MOT) mvx;
mot_y[pos+offset] = (MOT) mvy;
if (status != PV_SUCCESS)
{
return status;
}
}
}
else
{
mv_prediction(video, 0, &mvx, &mvy);
/* For PVOPs, field appears only in MODE_INTER & MODE_INTER_Q */
status = PV_DecodeMBVec(stream, &mvx, &mvy, f_code_f);
mot_x[pos] = mot_x[pos+1] = (MOT) mvx;
mot_y[pos] = mot_y[pos+1] = (MOT) mvy;
pos += doubleWidth;
mot_x[pos] = mot_x[pos+1] = (MOT) mvx;
mot_y[pos] = mot_y[pos+1] = (MOT) mvy;
if (status != PV_SUCCESS)
{
return status;
}
}
}
return PV_SUCCESS;
}
/***********************************************************CommentBegin******
* 3/10/00 : initial modification to the
* new PV-Decoder Lib format.
* 3/29/00 : added return code check to some functions
* 5/10/00 : check whether the decoded vector is legal.
* 4/17/01 : use MOT type
***********************************************************CommentEnd********/
PV_STATUS PV_DecodeMBVec(BitstreamDecVideo *stream, MOT *mv_x, MOT *mv_y, int f_code_f)
{
PV_STATUS status;
int vlc_code_magx, vlc_code_magy;
int residualx = 0, residualy = 0;
/* decode component x */
status = PV_VlcDecMV(stream, &vlc_code_magx);
if (status != PV_SUCCESS)
{
return status;
}
if (vlc_code_magx)
{
residualx = (int) BitstreamReadBits16_INLINE(stream, (int)(f_code_f - 1));
}
/* decode component y */
status = PV_VlcDecMV(stream, &vlc_code_magy);
if (status != PV_SUCCESS)
{
return status;
}
if (vlc_code_magy)
{
residualy = (int) BitstreamReadBits16_INLINE(stream, (int)(f_code_f - 1));
}
if (PV_DeScaleMVD(f_code_f, residualx, vlc_code_magx, mv_x) != PV_SUCCESS)
{
return PV_FAIL;
}
if (PV_DeScaleMVD(f_code_f, residualy, vlc_code_magy, mv_y) != PV_SUCCESS)
{
return PV_FAIL;
}
return PV_SUCCESS;
}
/***********************************************************CommentBegin******
* 3/31/2000 : initial modification to the new PV-Decoder Lib format.
* 5/10/2000 : check to see if the decoded vector falls within
* the legal fcode range.
*
***********************************************************CommentEnd********/
PV_STATUS PV_DeScaleMVD(
int f_code, /* <-- MV range in 1/2 units: 1=32,2=64,...,7=2048 */
int residual, /* <-- part of the MV Diff. FLC coded */
int vlc_code_mag, /* <-- part of the MV Diff. VLC coded */
MOT *vector /* --> Obtained MV component in 1/2 units */
)
{
int half_range = (1 << (f_code + 4));
int mask = (half_range << 1) - 1;
int diff_vector;
if (vlc_code_mag == 0)
{
diff_vector = vlc_code_mag;
}
else
{
diff_vector = ((PV_ABS(vlc_code_mag) - 1) << (f_code - 1)) + residual + 1;
if (vlc_code_mag < 0)
{
diff_vector = -diff_vector;
}
}
*vector += (MOT)(diff_vector);
*vector = (MOT)((*vector + half_range) & mask) - half_range;
return PV_SUCCESS;
}
void mv_prediction(
VideoDecData *video,
int block,
MOT *mvx,
MOT *mvy
)
{
/*----------------------------------------------------------------------------
; Define all local variables
----------------------------------------------------------------------------*/
MOT *motxdata = video->motX;
MOT *motydata = video->motY;
int mbnum_col = video->mbnum_col;
int mbnum_row = video->mbnum_row;
uint8 *slice_nb = video->sliceNo;
int nMBPerRow = video->nMBPerRow;
int nMVPerRow = nMBPerRow << 1;
int mbnum = video->mbnum;
int p1x = 0, p2x = 0, p3x = 0;
int p1y = 0, p2y = 0, p3y = 0;
int rule1 = 0, rule2 = 0, rule3 = 0;
int indx;
indx = ((mbnum_col << 1) + (block & 1)) + ((mbnum_row << 1) + (block >> 1)) * nMVPerRow - 1; /* left block */
if (block & 1) /* block 1, 3 */
{
p1x = motxdata[indx];
p1y = motydata[indx];
rule1 = 1;
}
else /* block 0, 2 */
{
if (mbnum_col > 0 && slice_nb[mbnum] == slice_nb[mbnum-1])
{
p1x = motxdata[indx];
p1y = motydata[indx];
rule1 = 1;
}
}
indx = indx + 1 - nMVPerRow; /* upper_block */
if (block >> 1)
{
indx -= (block & 1);
p2x = motxdata[indx];
p2y = motydata[indx];
p3x = motxdata[indx + 1];
p3y = motydata[indx + 1];
rule2 = rule3 = 1;
}
else
{ /* block 0,1 */
if (mbnum_row)
{
if (slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow])
{
p2x = motxdata[indx];
p2y = motydata[indx];
rule2 = 1;
}
if (mbnum_col < nMBPerRow - 1 && slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow+1])
{
indx = indx + 2 - (block & 1);
p3x = motxdata[indx];
p3y = motydata[indx];
rule3 = 1;
}
}
}
if (rule1 + rule2 + rule3 > 1)
{
*mvx = (MOT)PV_MEDIAN(p1x, p2x, p3x);
*mvy = (MOT)PV_MEDIAN(p1y, p2y, p3y);
}
else if (rule1 + rule2 + rule3 == 1)
{
/* two of three are zero */
*mvx = (MOT)(p1x + p2x + p3x);
*mvy = (MOT)(p1y + p2y + p3y);
}
else
{
/* all MBs are outside the VOP */
*mvx = *mvy = 0;
}
/*----------------------------------------------------------------------------
; Return nothing or data or data pointer
----------------------------------------------------------------------------*/
return;
}
/***********************************************************CommentBegin******
*
* 3/30/2000 : initial modification to the new PV-Decoder Lib format.
* 4/16/2001 : removed checking of status for PV_BitstreamFlushBits
***********************************************************CommentEnd********/
PV_STATUS PV_VlcDecMV(BitstreamDecVideo *stream, int *mv)
{
PV_STATUS status = PV_SUCCESS;
uint code;
BitstreamShow13Bits(stream, &code);
if (code >> 12)
{
*mv = 0; /* Vector difference = 0 */
PV_BitstreamFlushBits(stream, 1);
return PV_SUCCESS;
}
if (code >= 512)
{
code = (code >> 8) - 2;
PV_BitstreamFlushBits(stream, PV_TMNMVtab0[code].len + 1);
*mv = PV_TMNMVtab0[code].val;
return status;
}
if (code >= 128)
{
code = (code >> 2) - 32;
PV_BitstreamFlushBits(stream, PV_TMNMVtab1[code].len + 1);
*mv = PV_TMNMVtab1[code].val;
return status;
}
if (code < 4)
{
*mv = -1;
return PV_FAIL;
}
code -= 4;
PV_BitstreamFlushBits(stream, PV_TMNMVtab2[code].len + 1);
*mv = PV_TMNMVtab2[code].val;
return status;
}
/***********************************************************CommentBegin******
* 3/30/2000 : initial modification to the new PV-Decoder Lib
* format and the change of error-handling method.
* 4/16/01 : removed status checking of PV_BitstreamFlushBits
***********************************************************CommentEnd********/
int PV_VlcDecMCBPC_com_intra(BitstreamDecVideo *stream)
{
uint code;
BitstreamShowBits16(stream, 9, &code);
if (code < 8)
{
return VLC_CODE_ERROR;
}
code >>= 3;
if (code >= 32)
{
PV_BitstreamFlushBits(stream, 1);
return 3;
}
PV_BitstreamFlushBits(stream, PV_MCBPCtabintra[code].len);
return PV_MCBPCtabintra[code].val;
}
/***********************************************************CommentBegin******
*
* 3/30/2000 : initial modification to the new PV-Decoder Lib
* format and the change of error-handling method.
* 4/16/2001 : removed checking of return status of PV_BitstreamFlushBits
***********************************************************CommentEnd********/
int PV_VlcDecMCBPC_com_inter(BitstreamDecVideo *stream)
{
uint code;
BitstreamShowBits16(stream, 9, &code);
if (code == 0)
{
return VLC_CODE_ERROR;
}
else if (code >= 256)
{
PV_BitstreamFlushBits(stream, 1);
return 0;
}
PV_BitstreamFlushBits(stream, PV_MCBPCtab[code].len);
return PV_MCBPCtab[code].val;
}
#ifdef PV_ANNEX_IJKT_SUPPORT
int PV_VlcDecMCBPC_com_inter_H263(BitstreamDecVideo *stream)
{
uint code;
BitstreamShow13Bits(stream, &code);
if (code < 8)
{
return VLC_CODE_ERROR;
}
else if (code >= 4096)
{
PV_BitstreamFlushBits(stream, 1);
return 0;
}
if (code >= 16)
{
PV_BitstreamFlushBits(stream, PV_MCBPCtab[code >> 4].len);
return PV_MCBPCtab[code >> 4].val;
}
else
{
PV_BitstreamFlushBits(stream, PV_MCBPCtab1[code - 8].len);
return PV_MCBPCtab1[code - 8].val;
}
}
#endif
/***********************************************************CommentBegin******
* 3/30/2000 : initial modification to the new PV-Decoder Lib
* format and the change of error-handling method.
* 4/16/2001 : removed status checking for PV_BitstreamFlushBits
***********************************************************CommentEnd********/
int PV_VlcDecCBPY(BitstreamDecVideo *stream, int intra)
{
int CBPY = 0;
uint code;
BitstreamShowBits16(stream, 6, &code);
if (code < 2)
{
return -1;
}
else if (code >= 48)
{
PV_BitstreamFlushBits(stream, 2);
CBPY = 15;
}
else
{
PV_BitstreamFlushBits(stream, PV_CBPYtab[code].len);
CBPY = PV_CBPYtab[code].val;
}
if (intra == 0) CBPY = 15 - CBPY;
CBPY = CBPY & 15;
return CBPY;
}
/***********************************************************CommentBegin******
* 3/31/2000 : initial modification to the new PV-Decoder Lib format.
*
* 8/23/2000 : optimize the function by removing unnecessary BitstreamShowBits()
* function calls.
*
* 9/6/2000 : change the API to check for end-of-buffer for proper
* termination of decoding process.
***********************************************************CommentEnd********/
PV_STATUS PV_VlcDecIntraDCPredSize(BitstreamDecVideo *stream, int compnum, uint *DC_size)
{
PV_STATUS status = PV_FAIL; /* 07/09/01 */
uint code;
*DC_size = 0;
if (compnum < 4) /* luminance block */
{
BitstreamShowBits16(stream, 11, &code);
if (code == 1)
{
*DC_size = 12;
PV_BitstreamFlushBits(stream, 11);
return PV_SUCCESS;
}
code >>= 1;
if (code == 1)
{
*DC_size = 11;
PV_BitstreamFlushBits(stream, 10);
return PV_SUCCESS;
}
code >>= 1;
if (code == 1)
{
*DC_size = 10;
PV_BitstreamFlushBits(stream, 9);
return PV_SUCCESS;
}
code >>= 1;
if (code == 1)
{
*DC_size = 9;
PV_BitstreamFlushBits(stream, 8);
return PV_SUCCESS;
}
code >>= 1;
if (code == 1)
{
*DC_size = 8;
PV_BitstreamFlushBits(stream, 7);
return PV_SUCCESS;
}
code >>= 1;
if (code == 1)
{
*DC_size = 7;
PV_BitstreamFlushBits(stream, 6);
return PV_SUCCESS;
}
code >>= 1;
if (code == 1)
{
*DC_size = 6;
PV_BitstreamFlushBits(stream, 5);
return PV_SUCCESS;
}
code >>= 1;
if (code == 1)
{
*DC_size = 5;
PV_BitstreamFlushBits(stream, 4);
return PV_SUCCESS;
}
code >>= 1;
if (code == 1)
{
*DC_size = 4;
PV_BitstreamFlushBits(stream, 3);
return PV_SUCCESS;
}
else if (code == 2)
{
*DC_size = 3;
PV_BitstreamFlushBits(stream, 3);
return PV_SUCCESS;
}
else if (code == 3)
{
*DC_size = 0;
PV_BitstreamFlushBits(stream, 3);
return PV_SUCCESS;
}
code >>= 1;
if (code == 2)
{
*DC_size = 2;
PV_BitstreamFlushBits(stream, 2);
return PV_SUCCESS;
}
else if (code == 3)
{
*DC_size = 1;
PV_BitstreamFlushBits(stream, 2);
return PV_SUCCESS;
}
}
else /* chrominance block */
{
BitstreamShow13Bits(stream, &code);
code >>= 1;
if (code == 1)
{
*DC_size = 12;
PV_BitstreamFlushBits(stream, 12);
return PV_SUCCESS;
}
code >>= 1;
if (code == 1)
{
*DC_size = 11;
PV_BitstreamFlushBits(stream, 11);
return PV_SUCCESS;
}
code >>= 1;
if (code == 1)
{
*DC_size = 10;
PV_BitstreamFlushBits(stream, 10);
return PV_SUCCESS;
}
code >>= 1;
if (code == 1)
{
*DC_size = 9;
PV_BitstreamFlushBits(stream, 9);
return PV_SUCCESS;
}
code >>= 1;
if (code == 1)
{
*DC_size = 8;
PV_BitstreamFlushBits(stream, 8);
return PV_SUCCESS;
}
code >>= 1;
if (code == 1)
{
*DC_size = 7;
PV_BitstreamFlushBits(stream, 7);
return PV_SUCCESS;
}
code >>= 1;
if (code == 1)
{
*DC_size = 6;
PV_BitstreamFlushBits(stream, 6);
return PV_SUCCESS;
}
code >>= 1;
if (code == 1)
{
*DC_size = 5;
PV_BitstreamFlushBits(stream, 5);
return PV_SUCCESS;
}
code >>= 1;
if (code == 1)
{
*DC_size = 4;
PV_BitstreamFlushBits(stream, 4);
return PV_SUCCESS;
}
code >>= 1;
if (code == 1)
{
*DC_size = 3;
PV_BitstreamFlushBits(stream, 3);
return PV_SUCCESS;
}
code >>= 1;
{
*DC_size = (int)(3 - code);
PV_BitstreamFlushBits(stream, 2);
return PV_SUCCESS;
}
}
return status;
}
/***********************************************************CommentBegin******
*
*
* 3/30/2000 : initial modification to the new PV-Decoder Lib
* format and the change of error-handling method.
*
***********************************************************CommentEnd********/
PV_STATUS VlcDecTCOEFIntra(BitstreamDecVideo *stream, Tcoef *pTcoef)
{
uint code;
const VLCtab2 *tab;
BitstreamShow13Bits(stream, &code);
/* 10/17/2000, perform a little bit better on ARM by putting the whole function in VlcDecTCOEFFIntra */
/* if(GetTcoeffIntra(code,pTcoef,&tab,stream)!=PV_SUCCESS) return status;*/
if (code >= 1024)
{
tab = &PV_DCT3Dtab3[(code >> 6) - 16];
}
else
{
if (code >= 256)
{
tab = &PV_DCT3Dtab4[(code >> 3) - 32];
}
else
{
if (code >= 16)
{
tab = &PV_DCT3Dtab5[(code>>1) - 8];
}
else
{
return PV_FAIL;
}
}
}
PV_BitstreamFlushBits(stream, tab->len + 1);
pTcoef->sign = (code >> (12 - tab->len)) & 1;
pTcoef->run = (uint) tab->run; //(tab->val >> 8) & 255;
pTcoef->level = (int) tab->level; //tab->val & 255;
pTcoef->last = (uint) tab->last; //(tab->val >> 16) & 1;
/* the following is modified for 3-mode escape -- boon */
if (tab->level != 0xFF)
{
return PV_SUCCESS;
}
//if (((tab->run<<8)|(tab->level)|(tab->last<<16)) == VLC_ESCAPE_CODE)
if (!pTcoef->sign)
{
/* first escape mode. level is offset */
BitstreamShow13Bits(stream, &code);
/* 10/17/2000, perform a little bit better on ARM by putting the whole function in VlcDecTCOEFFIntra */
/* if(GetTcoeffIntra(code,pTcoef,&tab,stream)!=PV_SUCCESS) return status;*/
if (code >= 1024)
{
tab = &PV_DCT3Dtab3[(code >> 6) - 16];
}
else
{
if (code >= 256)
{
tab = &PV_DCT3Dtab4[(code >> 3) - 32];
}
else
{
if (code >= 16)
{
tab = &PV_DCT3Dtab5[(code>>1) - 8];
}
else
{
return PV_FAIL;
}
}
}
PV_BitstreamFlushBits(stream, tab->len + 1);
/* sign bit */
pTcoef->sign = (code >> (12 - tab->len)) & 1;
pTcoef->run = (uint)tab->run; //(tab->val >> 8) & 255;
pTcoef->level = (int)tab->level; //tab->val & 255;
pTcoef->last = (uint)tab->last; //(tab->val >> 16) & 1;
/* need to add back the max level */
if ((pTcoef->last == 0 && pTcoef->run > 14) || (pTcoef->last == 1 && pTcoef->run > 20))
{
return PV_FAIL;
}
pTcoef->level = pTcoef->level + intra_max_level[pTcoef->last][pTcoef->run];
}
else
{
uint run_offset;
run_offset = BitstreamRead1Bits_INLINE(stream);
if (!run_offset)
{
/* second escape mode. run is offset */
BitstreamShow13Bits(stream, &code);
/* 10/17/2000, perform a little bit better on ARM by putting the whole function in VlcDecTCOEFFIntra */
/* if(GetTcoeffIntra(code,pTcoef,&tab,stream)!=PV_SUCCESS) return status;*/
if (code >= 1024)
{
tab = &PV_DCT3Dtab3[(code >> 6) - 16];
}
else
{
if (code >= 256)
{
tab = &PV_DCT3Dtab4[(code >> 3) - 32];
}
else
{
if (code >= 16)
{
tab = &PV_DCT3Dtab5[(code>>1) - 8];
}
else
{
return PV_FAIL;
}
}
}
PV_BitstreamFlushBits(stream, tab->len + 1);
/* sign bit */
pTcoef->sign = (code >> (12 - tab->len)) & 1;
pTcoef->run = (uint)tab->run; //(tab->val >> 8) & 255;
pTcoef->level = (int)tab->level; //tab->val & 255;
pTcoef->last = (uint)tab->last; //(tab->val >> 16) & 1;
/* need to add back the max run */
if (pTcoef->last)
{
if (pTcoef->level > 8)
{
return PV_FAIL;
}
pTcoef->run = pTcoef->run + intra_max_run1[pTcoef->level] + 1;
}
else
{
if (pTcoef->level > 27)
{
return PV_FAIL;
}
pTcoef->run = pTcoef->run + intra_max_run0[pTcoef->level] + 1;
}
}
else
{
code = BitstreamReadBits16_INLINE(stream, 8);
pTcoef->last = code >> 7;
pTcoef->run = (code >> 1) & 0x3F;
pTcoef->level = (int)(BitstreamReadBits16_INLINE(stream, 13) >> 1);
if (pTcoef->level >= 2048)
{
pTcoef->sign = 1;
pTcoef->level = 4096 - pTcoef->level;
}
else
{
pTcoef->sign = 0;
}
} /* flc */
}
return PV_SUCCESS;
} /* VlcDecTCOEFIntra */
PV_STATUS VlcDecTCOEFInter(BitstreamDecVideo *stream, Tcoef *pTcoef)
{
uint code;
const VLCtab2 *tab;
BitstreamShow13Bits(stream, &code);
/* 10/17/2000, perform a little bit better on ARM by putting the whole function in VlcDecTCOEFFInter */
/* if(GetTcoeffInter(code,pTcoef,&tab,stream)!=PV_SUCCESS) return status;*/
if (code >= 1024)
{
tab = &PV_DCT3Dtab0[(code >> 6) - 16];
}
else
{
if (code >= 256)
{
tab = &PV_DCT3Dtab1[(code >> 3) - 32];
}
else
{
if (code >= 16)
{
tab = &PV_DCT3Dtab2[(code>>1) - 8];
}
else
{
return PV_FAIL;
}
}
}
PV_BitstreamFlushBits(stream, tab->len + 1);
pTcoef->sign = (code >> (12 - tab->len)) & 1;
pTcoef->run = (uint)tab->run; //(tab->val >> 4) & 255;
pTcoef->level = (int)tab->level; //tab->val & 15;
pTcoef->last = (uint)tab->last; //(tab->val >> 12) & 1;
/* the following is modified for 3-mode escape -- boon */
if (tab->run != 0xBF)
{
return PV_SUCCESS;
}
//if (((tab->run<<4)|(tab->level)|(tab->last<<12)) == VLC_ESCAPE_CODE)
if (!pTcoef->sign)
{
/* first escape mode. level is offset */
BitstreamShow13Bits(stream, &code);
/* 10/17/2000, perform a little bit better on ARM by putting the whole function in VlcDecTCOEFFInter */
/* if(GetTcoeffInter(code,pTcoef,&tab,stream)!=PV_SUCCESS) return status;*/
if (code >= 1024)
{
tab = &PV_DCT3Dtab0[(code >> 6) - 16];
}
else
{
if (code >= 256)
{
tab = &PV_DCT3Dtab1[(code >> 3) - 32];
}
else
{
if (code >= 16)
{
tab = &PV_DCT3Dtab2[(code>>1) - 8];
}
else
{
return PV_FAIL;
}
}
}
PV_BitstreamFlushBits(stream, tab->len + 1);
pTcoef->sign = (code >> (12 - tab->len)) & 1;
pTcoef->run = (uint)tab->run; //(tab->val >> 4) & 255;
pTcoef->level = (int)tab->level; //tab->val & 15;
pTcoef->last = (uint)tab->last; //(tab->val >> 12) & 1;
/* need to add back the max level */
if ((pTcoef->last == 0 && pTcoef->run > 26) || (pTcoef->last == 1 && pTcoef->run > 40))
{
return PV_FAIL;
}
pTcoef->level = pTcoef->level + inter_max_level[pTcoef->last][pTcoef->run];
}
else
{
uint run_offset;
run_offset = BitstreamRead1Bits_INLINE(stream);
if (!run_offset)
{
/* second escape mode. run is offset */
BitstreamShow13Bits(stream, &code);
/* 10/17/2000, perform a little bit better on ARM by putting the whole function in VlcDecTCOEFFInter */
/*if(GetTcoeffInter(code,pTcoef,&tab,stream)!=PV_SUCCESS) return status;*/
if (code >= 1024)
{
tab = &PV_DCT3Dtab0[(code >> 6) - 16];
}
else
{
if (code >= 256)
{
tab = &PV_DCT3Dtab1[(code >> 3) - 32];
}
else
{
if (code >= 16)
{
tab = &PV_DCT3Dtab2[(code>>1) - 8];
}
else
{
return PV_FAIL;
}
}
}
PV_BitstreamFlushBits(stream, tab->len + 1);
pTcoef->sign = (code >> (12 - tab->len)) & 1;
pTcoef->run = (uint)tab->run; //(tab->val >> 4) & 255;
pTcoef->level = (int)tab->level; //tab->val & 15;
pTcoef->last = (uint)tab->last; //(tab->val >> 12) & 1;
/* need to add back the max run */
if (pTcoef->last)
{
if (pTcoef->level > 3)
{
return PV_FAIL;
}
pTcoef->run = pTcoef->run + inter_max_run1[pTcoef->level] + 1;
}
else
{
if (pTcoef->level > 12)
{
return PV_FAIL;
}
pTcoef->run = pTcoef->run + inter_max_run0[pTcoef->level] + 1;
}
}
else
{
code = BitstreamReadBits16_INLINE(stream, 8);
pTcoef->last = code >> 7;
pTcoef->run = (code >> 1) & 0x3F;
pTcoef->level = (int)(BitstreamReadBits16_INLINE(stream, 13) >> 1);
if (pTcoef->level >= 2048)
{
pTcoef->sign = 1;
pTcoef->level = 4096 - pTcoef->level;
}
else
{
pTcoef->sign = 0;
}
} /* flc */
}
return PV_SUCCESS;
} /* VlcDecTCOEFInter */
/*=======================================================
Function: VlcDecTCOEFShortHeader()
Date : 04/27/99
Purpose : New function used in decoding of video planes
with short header
Modified: 05/23/2000
for new decoder structure.
=========================================================*/
PV_STATUS VlcDecTCOEFShortHeader(BitstreamDecVideo *stream, Tcoef *pTcoef/*, int intra*/)
{
uint code;
const VLCtab2 *tab;
BitstreamShow13Bits(stream, &code);
/*intra = 0;*/
if (code >= 1024) tab = &PV_DCT3Dtab0[(code >> 6) - 16];
else
{
if (code >= 256) tab = &PV_DCT3Dtab1[(code >> 3) - 32];
else
{
if (code >= 16) tab = &PV_DCT3Dtab2[(code>>1) - 8];
else return PV_FAIL;
}
}
PV_BitstreamFlushBits(stream, tab->len + 1);
pTcoef->sign = (code >> (12 - tab->len)) & 1;
pTcoef->run = (uint)tab->run;//(tab->val >> 4) & 255;
pTcoef->level = (int)tab->level;//tab->val & 15;
pTcoef->last = (uint)tab->last;//(tab->val >> 12) & 1;
/* the following is modified for 3-mode escape -- boon */
if (((tab->run << 4) | (tab->level) | (tab->last << 12)) != VLC_ESCAPE_CODE) /* ESCAPE */
{
return PV_SUCCESS;
}
/* escape mode 4 - H.263 type */
pTcoef->last = pTcoef->sign; /* Last */
pTcoef->run = BitstreamReadBits16_INLINE(stream, 6); /* Run */
pTcoef->level = (int) BitstreamReadBits16_INLINE(stream, 8); /* Level */
if (pTcoef->level == 0 || pTcoef->level == 128)
{
return PV_FAIL;
}
if (pTcoef->level > 128)
{
pTcoef->sign = 1;
pTcoef->level = 256 - pTcoef->level;
}
else
{
pTcoef->sign = 0;
}
return PV_SUCCESS;
} /* VlcDecTCOEFShortHeader */
#ifdef PV_ANNEX_IJKT_SUPPORT
PV_STATUS VlcDecTCOEFShortHeader_AnnexI(BitstreamDecVideo *stream, Tcoef *pTcoef/*, int intra*/)
{
uint code;
const VLCtab2 *tab;
BitstreamShow13Bits(stream, &code);
/*intra = 0;*/
if (code >= 1024) tab = &PV_DCT3Dtab6[(code >> 6) - 16];
else
{
if (code >= 256) tab = &PV_DCT3Dtab7[(code >> 3) - 32];
else
{
if (code >= 16) tab = &PV_DCT3Dtab8[(code>>1) - 8];
else return PV_FAIL;
}
}
PV_BitstreamFlushBits(stream, tab->len + 1);
pTcoef->sign = (code >> (12 - tab->len)) & 1;
pTcoef->run = (uint)tab->run;//(tab->val >> 4) & 255;
pTcoef->level = (int)tab->level;//tab->val & 15;
pTcoef->last = (uint)tab->last;//(tab->val >> 12) & 1;
/* the following is modified for 3-mode escape -- boon */
if (((tab->run << 6) | (tab->level) | (tab->last << 12)) != VLC_ESCAPE_CODE) /* ESCAPE */
{
return PV_SUCCESS;
}
/* escape mode 4 - H.263 type */
pTcoef->last = pTcoef->sign; /* Last */
pTcoef->run = BitstreamReadBits16(stream, 6); /* Run */
pTcoef->level = (int) BitstreamReadBits16(stream, 8); /* Level */
if (pTcoef->level == 0 || pTcoef->level == 128)
{
return PV_FAIL;
}
if (pTcoef->level > 128)
{
pTcoef->sign = 1;
pTcoef->level = 256 - pTcoef->level;
}
else pTcoef->sign = 0;
return PV_SUCCESS;
} /* VlcDecTCOEFShortHeader_AnnexI */
PV_STATUS VlcDecTCOEFShortHeader_AnnexT(BitstreamDecVideo *stream, Tcoef *pTcoef/*, int intra*/)
{
uint code;
const VLCtab2 *tab;
BitstreamShow13Bits(stream, &code);
/*intra = 0;*/
if (code >= 1024) tab = &PV_DCT3Dtab0[(code >> 6) - 16];
else
{
if (code >= 256) tab = &PV_DCT3Dtab1[(code >> 3) - 32];
else
{
if (code >= 16) tab = &PV_DCT3Dtab2[(code>>1) - 8];
else return PV_FAIL;
}
}
PV_BitstreamFlushBits(stream, tab->len + 1);
pTcoef->sign = (code >> (12 - tab->len)) & 1;
pTcoef->run = (uint)tab->run;//(tab->val >> 4) & 255;
pTcoef->level = (int)tab->level;//tab->val & 15;
pTcoef->last = (uint)tab->last;//(tab->val >> 12) & 1;
/* the following is modified for 3-mode escape -- */
if (((tab->run << 4) | (tab->level) | (tab->last << 12)) != VLC_ESCAPE_CODE) /* ESCAPE */
{
return PV_SUCCESS;
}
/* escape mode 4 - H.263 type */
pTcoef->last = pTcoef->sign; /* Last */
pTcoef->run = BitstreamReadBits16(stream, 6); /* Run */
pTcoef->level = (int) BitstreamReadBits16(stream, 8); /* Level */
if (pTcoef->level == 0)
{
return PV_FAIL;
}
if (pTcoef->level >= 128)
{
pTcoef->sign = 1;
pTcoef->level = 256 - pTcoef->level;
}
else
{
pTcoef->sign = 0;
}
if (pTcoef->level == 128)
{
code = BitstreamReadBits16(stream, 11); /* ANNEX_T */
code = (code >> 6 & 0x1F) | (code << 5 & 0x7ff);
if (code > 1024)
{
pTcoef->sign = 1;
pTcoef->level = (2048 - code);
}
else
{
pTcoef->sign = 0;
pTcoef->level = code;
}
}
return PV_SUCCESS;
} /* VlcDecTCOEFShortHeader */
PV_STATUS VlcDecTCOEFShortHeader_AnnexIT(BitstreamDecVideo *stream, Tcoef *pTcoef/*, int intra*/)
{
uint code;
const VLCtab2 *tab;
BitstreamShow13Bits(stream, &code);
/*intra = 0;*/
if (code >= 1024) tab = &PV_DCT3Dtab6[(code >> 6) - 16];
else
{
if (code >= 256) tab = &PV_DCT3Dtab7[(code >> 3) - 32];
else
{
if (code >= 16) tab = &PV_DCT3Dtab8[(code>>1) - 8];
else return PV_FAIL;
}
}
PV_BitstreamFlushBits(stream, tab->len + 1);
pTcoef->sign = (code >> (12 - tab->len)) & 1;
pTcoef->run = (uint)tab->run;//(tab->val >> 4) & 255;
pTcoef->level = (int)tab->level;//tab->val & 15;
pTcoef->last = (uint)tab->last;//(tab->val >> 12) & 1;
/* the following is modified for 3-mode escape -- */
if (((tab->run << 6) | (tab->level) | (tab->last << 12)) != VLC_ESCAPE_CODE) /* ESCAPE */
{
return PV_SUCCESS;
}
/* escape mode 4 - H.263 type */
pTcoef->last = pTcoef->sign; /* Last */
pTcoef->run = BitstreamReadBits16(stream, 6); /* Run */
pTcoef->level = (int) BitstreamReadBits16(stream, 8); /* Level */
if (pTcoef->level == 0)
{
return PV_FAIL;
}
if (pTcoef->level >= 128)
{
pTcoef->sign = 1;
pTcoef->level = 256 - pTcoef->level;
}
else
{
pTcoef->sign = 0;
}
if (pTcoef->level == 128)
{
code = BitstreamReadBits16(stream, 11); /* ANNEX_T */
code = (code >> 6 & 0x1F) | (code << 5 & 0x7ff);
if (code > 1024)
{
pTcoef->sign = 1;
pTcoef->level = (2048 - code);
}
else
{
pTcoef->sign = 0;
pTcoef->level = code;
}
}
return PV_SUCCESS;
} /* VlcDecTCOEFShortHeader_AnnexI */
#endif
/***********************************************************CommentBegin******
* 3/30/2000 : initial modification to the new PV-Decoder Lib
* format and the change of error-handling method.
* The coefficient is now returned thru a pre-
* initialized parameters for speedup.
*
***********************************************************CommentEnd********/
PV_STATUS RvlcDecTCOEFInter(BitstreamDecVideo *stream, Tcoef *pTcoef)
{
uint code, mask;
const VLCtab2 *tab2;
int count, len, num[2] = {0, 0} /* 01/30/01 */;
mask = 0x4000; /* mask 100000000000000 */
BitstreamShow15Bits(stream, &code); /* 03/07/01 */
len = 1;
// 09/20/99 Escape mode
/// Bitstream Exchange
if (code < 2048)
{
PV_BitstreamFlushBits(stream, 5);
pTcoef->last = BitstreamRead1Bits_INLINE(stream);
pTcoef->run = BitstreamReadBits16_INLINE(stream, 6);
// 09/20/99 New marker bit
PV_BitstreamFlushBits(stream, 1);
// 09/20/99 The length for LEVEL used to be 7 in the old version
pTcoef->level = (int)(BitstreamReadBits16_INLINE(stream, 12) >> 1);
// 09/20/99 Another new marker bit
// PV_BitstreamFlushBitsCheck(stream, 1);
pTcoef->sign = BitstreamReadBits16_INLINE(stream, 5) & 0x1; /* fix 3/13/01 */
return PV_SUCCESS;
}
if (code & mask)
{
count = 1;
while (mask && count > 0) /* fix 3/28/01 */
{
mask = mask >> 1;
if (code & mask)
count--;
else
num[0]++; /* number of zeros in the middle */
len++;
}
}
else
{
count = 2;
while (mask && count > 0) /* fix 3/28/01 */
{
mask = mask >> 1;
if (!(code & mask))
count--;
else
num[count-1]++; /* number of ones in the middle */
len++;
}
}
code = code & 0x7fff;
code = code >> (15 - (len + 1));
/* 1/30/01, add fast decoding algorithm here */
/* code is in two forms : 0xxxx0xxx00 or 0xxx0xxx01
num[1] and num[0] x
or : 1xxxxx10 or 1xxxxx11
num[0] x */
/* len+1 is the length of the above */
if (num[1] > 10 || num[0] > 11) /* invalid RVLC code */
return PV_FAIL;
if (code&(1 << len))
tab2 = RvlcDCTtabInter + 146 + (num[0] << 1) + (code & 1);
else
tab2 = RvlcDCTtabInter + ptrRvlcTab[num[1]] + (num[0] << 1) + (code & 1);
PV_BitstreamFlushBits(stream, (int) tab2->len);
pTcoef->run = (uint)tab2->run;//(tab->val >> 8) & 255;
pTcoef->level = (int)tab2->level;//tab->val & 255;
pTcoef->last = (uint)tab2->last;//(tab->val >> 16) & 1;
pTcoef->sign = BitstreamRead1Bits_INLINE(stream);
return PV_SUCCESS;
} /* RvlcDecTCOEFInter */
PV_STATUS RvlcDecTCOEFIntra(BitstreamDecVideo *stream, Tcoef *pTcoef)
{
uint code, mask;
const VLCtab2 *tab2;
int count, len, num[2] = {0, 0} /* 01/30/01 */;
mask = 0x4000; /* mask 100000000000000 */
BitstreamShow15Bits(stream, &code);
len = 1;
// 09/20/99 Escape mode
/// Bitstream Exchange
if (code < 2048)
{
PV_BitstreamFlushBits(stream, 5);
pTcoef->last = BitstreamRead1Bits_INLINE(stream);
pTcoef->run = BitstreamReadBits16_INLINE(stream, 6);
// 09/20/99 New marker bit
PV_BitstreamFlushBits(stream, 1);
// 09/20/99 The length for LEVEL used to be 7 in the old version
pTcoef->level = (int)(BitstreamReadBits16_INLINE(stream, 12) >> 1);
// 09/20/99 Another new marker bit
// PV_BitstreamFlushBitsCheck(stream, 1);
pTcoef->sign = BitstreamReadBits16_INLINE(stream, 5) & 0x1; /* fix 03/13/01 */
return PV_SUCCESS;
}
if (code & mask)
{
count = 1;
while (mask && count > 0) /* fix 03/28/01 */
{
mask = mask >> 1;
if (code & mask)
count--;
else
num[0]++; /* number of zeros in the middle */
len++;
}
}
else
{
count = 2;
while (mask && count > 0) /* fix 03/28/01 */
{
mask = mask >> 1;
if (!(code & mask))
count--;
else
num[count-1]++; /* number of ones in the middle */
len++;
}
}
code = code & 0x7fff;
code = code >> (15 - (len + 1));
/* 1/30/01, add fast decoding algorithm here */
/* code is in two forms : 0xxxx0xxx00 or 0xxx0xxx01
num[1] and num[0] x
or : 1xxxxx10 or 1xxxxx11
num[0] x */
/* len+1 is the length of the above */
if (num[1] > 10 || num[0] > 11) /* invalid RVLC code */
return PV_FAIL;
if (code & (1 << len))
tab2 = RvlcDCTtabIntra + 146 + (num[0] << 1) + (code & 1);
else
tab2 = RvlcDCTtabIntra + ptrRvlcTab[num[1]] + (num[0] << 1) + (code & 1);
PV_BitstreamFlushBits(stream, (int) tab2->len);
pTcoef->run = (uint)tab2->run;//(tab->val >> 8) & 255;
pTcoef->level = (int)tab2->level;//tab->val & 255;
pTcoef->last = (uint)tab2->last;//(tab->val >> 16) & 1;
pTcoef->sign = BitstreamRead1Bits_INLINE(stream);
return PV_SUCCESS;
} /* RvlcDecTCOEFIntra */