crystalhd/linux_lib/libcrystalhd/libcrystalhd_parser.cpp

1375 lines
36 KiB
C++

/********************************************************************
* Copyright(c) 2006-2009 Broadcom Corporation.
*
* Name: libcrystalhd_parser.h
*
* Description: Driver Interface library Internal.
*
* AU
*
* HISTORY:
*
********************************************************************
*
* This file is part of libcrystalhd.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*******************************************************************/
#include <stdlib.h>
#include "7411d.h"
#include "libcrystalhd_if.h"
#include "libcrystalhd_priv.h"
#include "libcrystalhd_parser.h"
//Check Number of Reference
//NAL Unit
//#include "NALUnit.h"
//Advanced Profile
static const uint8_t b_asf_vc1_frame_scode[4]={0x00, 0x00, 0x01, 0x0D};
//Simple / Main Profile
//SP/MP Code-In Magic Word
static const uint8_t b_asf_vc1_sm_codein_scode[4] = {0x5a, 0x5a, 0x5a, 0x5a};
static const uint8_t b_asf_vc1_sm_codein_data_suffix[1] = {0x0D};
static const uint8_t b_asf_vc1_sm_codein_sl_suffix[1] = {0x0F};
static const uint8_t b_asf_vc1_sm_codein_pts_suffix[1] = {0xBD};
static const uint8_t b_asf_vc1_sm_seqheader_scode[4] = {0x00, 0x00, 0x01, 0x0F};
static const uint8_t b_asf_vc1_sm_picheader_scode[4] = {0x00, 0x00, 0x01, 0x0D};
static const uint8_t b_asf_vc1_sm_codein_header[16] = {0x5a, 0x5a, 0x5a, 0x5a,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x5a, 0x5a, 0x5a, 0x5a};
static const uint8_t b_asf_vc1_sm_codein_seqhdr[32] = {0x5a, 0x5a, 0x5a, 0x5a,
0x00, 0x00, 0x00, 0x20,
0x00, 0x00, 0x00, 0x07,
0x5a, 0x5a, 0x5a, 0x5a,
0x0f, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00};
static const uint8_t b_asf_vc1_sm_seqhdr[12] = {0x00, 0x00, 0x01, 0x0F,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00};
//Swap Data
uint32_t DWORD_SWAP(uint32_t x)
{
return ((uint32_t)(((x) << 24) | ((x) >> 24) | (((x) & 0xFF00) << 8) | (((x) & 0xFF0000) >> 8)));
}
uint16_t WORD_SWAP(uint16_t x)
{
return ((uint16_t)(((x) << 8) | ((x) >> 8)));
}
uint64_t ULONGLONG_SWAP(uint64_t x)
{
return ((uint64_t)(((x) << 56) | ((x) >> 56) | (((x) & 0xFF00LL) << 40) | (((x) & 0xFF000000000000LL) >> 40) | (((x) & 0xFF0000LL) << 24) | (((x) & 0xFF0000000000LL) >> 24) | (((x) & 0xFF000000LL) << 8) | (((x) & 0xFF00000000LL) >> 8)));
}
void PTS2MakerBit5Bytes(uint8_t* pMakerBit, int64_t llPTS)
{
//4 Bits: '0010'
//3 Bits: PTS[32:30]
//1 Bit: '1'
//15 Bits: PTS[29:15]
//1 Bit: '1'
//15 Bits: PTS[14:0]
//1 Bit : '1'
//0010 xxx1 xxxx xxxx xxxx xxx1 xxxx xxxx xxxx xxx1
//Swap
uint64_t ullSwap = ULONGLONG_SWAP(llPTS);
uint8_t *pPTS = (uint8_t *)(&ullSwap);
//Reserved the last 5 bytes, using the last 33 bits of PTS
//0000 000x xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx
pPTS = pPTS + 3;
//1st Byte: 0010 xxx1
*(pMakerBit) = 0x21 | ((*(pPTS) & 0x01) << 3) | ((*(pPTS + 1) & 0xC0) >> 5);
//2nd Byte: xxxx xxxx
*(pMakerBit + 1) = ((*(pPTS + 1) & 0x3F) << 2) | ((*(pPTS + 2) & 0xC0) >> 6);
//3rd Byte: xxxx xxx1
*(pMakerBit + 2) = 0x01 | ((*(pPTS + 2) & 0x3F) << 2) | ((*(pPTS + 3) & 0x80) >> 6);
//4th Byte: xxxx xxxx
*(pMakerBit + 3) = ((*(pPTS + 3) & 0x7F) << 1) | ((*(pPTS + 4) & 0x80) >> 7);
//5th Byte: xxxx xxx1
*(pMakerBit + 4) = 0x01 | ((*(pPTS + 4) & 0x7F) << 1);
}
/*
void PESHeaderPTSInsert(uint8_t *pPESHdr, uint64_t llPTS)
{
//Swap
uint64_t ullSwap = ULONGLONG_SWAP(llPTS);
uint8_t *pPTS = (uint8_t *)(&ullSwap);
//PES Header Bit[8~12] PTS 5Bytes Field
//0010 xxx1 xxxx xxxx
//xxxx xxx1 xxxx xxxx
//xxxx xxx1
}
*/
BC_STATUS DtsReleasePESConverter(HANDLE hDevice)
{
DTS_LIB_CONTEXT *Ctx = NULL;
DTS_GET_CTX(hDevice,Ctx);
if (Ctx->PESConvParams.m_pSpsPpsBuf)
free(Ctx->PESConvParams.m_pSpsPpsBuf);
Ctx->PESConvParams.m_pSpsPpsBuf = NULL;
if (Ctx->PESConvParams.pStartcodePendBuff)
free(Ctx->PESConvParams.pStartcodePendBuff);
Ctx->PESConvParams.pStartcodePendBuff = NULL;
return BC_STS_SUCCESS;
}
BC_STATUS DtsInitPESConverter(HANDLE hDevice)
{
DTS_LIB_CONTEXT *Ctx = NULL;
DTS_GET_CTX(hDevice,Ctx);
Ctx->PESConvParams.m_bIsFirstByteStreamNALU = true;
Ctx->PESConvParams.m_pSpsPpsBuf = NULL;
Ctx->PESConvParams.m_iSpsPpsLen = 0;
Ctx->PESConvParams.m_lStartCodeDataSize = 0;
Ctx->PESConvParams.pStartcodePendBuff = NULL;
Ctx->PESConvParams.lPendBufferSize = 0;
Ctx->PESConvParams.m_SymbInt.m_nSize = 0;
Ctx->PESConvParams.m_SymbInt.m_nUsed = 0;
Ctx->PESConvParams.m_SymbInt.m_pCurrent = NULL;
Ctx->PESConvParams.m_SymbInt.m_pInputBuffer = NULL;
Ctx->PESConvParams.m_SymbInt.m_pInputBufferEnd = NULL;
Ctx->PESConvParams.m_SymbInt.m_ulMask = 0;
Ctx->PESConvParams.m_SymbInt.m_ulOffset = 0;
Ctx->PESConvParams.m_SymbInt.m_ulZero = 0;
Ctx->PESConvParams.m_bAddSpsPps = true;
Ctx->PESConvParams.m_bIsAdd_SCode_CodeIn = false;
Ctx->PESConvParams.m_bRangered = false;
Ctx->PESConvParams.m_bFinterpFlag = false;
Ctx->PESConvParams.m_bMaxbFrames = false;
return BC_STS_SUCCESS;
}
BC_STATUS DtsSetVC1SH(HANDLE hDevice)
{
DTS_LIB_CONTEXT *Ctx = NULL;
int sts = 0;
DTS_GET_CTX(hDevice,Ctx);
//Send SPS and PPS
//unused uint8_t *pSrc = NULL;
//unused uint8_t *pDes = NULL;
if((Ctx->VidParams.MediaSubType == BC_MSUBTYPE_WVC1) || (Ctx->VidParams.MediaSubType == BC_MSUBTYPE_WMVA))
{
Ctx->PESConvParams.m_iSpsPpsLen = Ctx->VidParams.MetaDataSz;
sts = posix_memalign((void**)&Ctx->PESConvParams.m_pSpsPpsBuf, 8, Ctx->PESConvParams.m_iSpsPpsLen);
if(sts)
return BC_STS_INSUFF_RES;
memcpy(Ctx->PESConvParams.m_pSpsPpsBuf, Ctx->VidParams.pMetaData, Ctx->PESConvParams.m_iSpsPpsLen);
}
else
{
if (Ctx->DevId == BC_PCI_DEVID_LINK)
{
if (Ctx->PESConvParams.m_pSpsPpsBuf)
free(Ctx->PESConvParams.m_pSpsPpsBuf);
Ctx->PESConvParams.m_iSpsPpsLen = 32;
sts = posix_memalign((void**)&Ctx->PESConvParams.m_pSpsPpsBuf, 8, Ctx->PESConvParams.m_iSpsPpsLen);
if(sts)
return BC_STS_INSUFF_RES;
memcpy(Ctx->PESConvParams.m_pSpsPpsBuf, b_asf_vc1_sm_codein_seqhdr, Ctx->PESConvParams.m_iSpsPpsLen);
*((uint16_t*)(Ctx->PESConvParams.m_pSpsPpsBuf + 17)) = WORD_SWAP((uint16_t)Ctx->VidParams.WidthInPixels);
*((uint16_t*)(Ctx->PESConvParams.m_pSpsPpsBuf + 19)) = WORD_SWAP((uint16_t)Ctx->VidParams.HeightInPixels);
memcpy(Ctx->PESConvParams.m_pSpsPpsBuf + 21, Ctx->VidParams.pMetaData, 4);
}
else if (Ctx->DevId == BC_PCI_DEVID_FLEA)
{
if (Ctx->PESConvParams.m_pSpsPpsBuf)
free(Ctx->PESConvParams.m_pSpsPpsBuf);
Ctx->PESConvParams.m_iSpsPpsLen = 12;
sts = posix_memalign((void**)&Ctx->PESConvParams.m_pSpsPpsBuf, 8, Ctx->PESConvParams.m_iSpsPpsLen);
if(sts)
return BC_STS_INSUFF_RES;
memcpy(Ctx->PESConvParams.m_pSpsPpsBuf, b_asf_vc1_sm_seqhdr, Ctx->PESConvParams.m_iSpsPpsLen);
*((uint16_t*)(Ctx->PESConvParams.m_pSpsPpsBuf + 4)) = WORD_SWAP((uint16_t)Ctx->VidParams.WidthInPixels);
*((uint16_t*)(Ctx->PESConvParams.m_pSpsPpsBuf + 6)) = WORD_SWAP((uint16_t)Ctx->VidParams.HeightInPixels);
memcpy(Ctx->PESConvParams.m_pSpsPpsBuf + 8, Ctx->VidParams.pMetaData, 4);
}
}
return BC_STS_SUCCESS;
}
BC_STATUS DtsSetSpsPps(HANDLE hDevice)
{
DTS_LIB_CONTEXT *Ctx = NULL;
//Send SPS and PPS
uint8_t *pSrc = NULL;
uint8_t *pDes = NULL;
uint8_t NALtype = 0;
int iSHStart[40];
int iSHStop[40];
int iPktIdx = 0;
int i = 0;
int j = 0;
unsigned int iSize = 0;
int iStartSize = 2;
DTS_GET_CTX(hDevice,Ctx);
// if ((Ctx->VidParams.MediaSubType != BC_MSUBTYPE_AVC1) &&
// (Ctx->VidParams.MediaSubType != BC_MSUBTYPE_H264) &&
// (Ctx->VidParams.MediaSubType != BC_MSUBTYPE_DIVX) )
// return BC_STS_SUCCESS;
// MSUBTYPE_H264 does not have codec_type to generate separate SPS/PPS
if ((Ctx->VidParams.MediaSubType != BC_MSUBTYPE_AVC1) &&
(Ctx->VidParams.MediaSubType != BC_MSUBTYPE_DIVX) )
return BC_STS_SUCCESS;
int iSHSize = Ctx->VidParams.MetaDataSz;
pSrc = Ctx->VidParams.pMetaData;
if((iSHSize > 0) && (pSrc))
{
if (pSrc[0]==0x00 && pSrc[1]==0x00 && pSrc[2]==0x01)
{
iStartSize = 3;
iSHStart[iPktIdx] = 3;
for (i = 3; i < iSHSize; i ++)
{
if (pSrc[i-2]==0x00 && pSrc[i-1]==0x00 && pSrc[i]==0x01)
{
iSHStop[iPktIdx] = i - 3;
if (i < iSHSize)
{
iPktIdx++;
iSHStart[iPktIdx] = i + 1;
}
}
}
iSHStop[iPktIdx++] = i-1;
}
else if (pSrc[0]==0x00 && pSrc[1]==0x00 && pSrc[2]==0x00 && pSrc[3]==0x01)
{
iStartSize = 4;
iSHStart[iPktIdx] = 4;
for (i = 4; i < iSHSize; i ++)
{
if (pSrc[i-3] == 0x00 && pSrc[i-2]==0x00 && pSrc[i-1]==0x00 && pSrc[i]==0x01)
{
iSHStop[iPktIdx] = i - 4;
if (i < iSHSize)
{
iPktIdx++;
iSHStart[iPktIdx] = i + 1;
}
}
}
iSHStop[iPktIdx++] = i-1;
}
else
{
while (i < iSHSize)
{
iSize = (pSrc[i] << 8) + pSrc[i+1];
iSHStart[iPktIdx] = i + 2;
iSHStop[iPktIdx] = iSHStart[iPktIdx] + iSize - 1;
iPktIdx++;
i += (2 + iSize);
}
}
Ctx->PESConvParams.m_iSpsPpsLen = iSHSize + (BRCM_START_CODE_SIZE - iStartSize) * (iPktIdx);
if(Ctx->PESConvParams.m_pSpsPpsBuf)
free(Ctx->PESConvParams.m_pSpsPpsBuf);
if(!posix_memalign((void**)&Ctx->PESConvParams.m_pSpsPpsBuf, 8, Ctx->PESConvParams.m_iSpsPpsLen))
{
memset(Ctx->PESConvParams.m_pSpsPpsBuf, 0, Ctx->PESConvParams.m_iSpsPpsLen);
pDes = Ctx->PESConvParams.m_pSpsPpsBuf;
pSrc = Ctx->VidParams.pMetaData;
for(i=0;i<iPktIdx;i++)
{
// NAREN - Add only SPS and PPS from the sequence header to send to the HW
// If there is other invalid data in the sequence header do not pass it along
// Similarly if there is any other NAL unit type do not pass it along
// NAL unit type for SPS is 7 and for PPS is 8 for H.264
// NAL unit type is the first byte of the header portion and can be between 0 and 31
// For MPEG-4 part 2 In general the demuxers give all of Video Object Layer start codes in the sequence header
// Haali for example copies the entire MPEG-4 header up to the first Video Object Plane start
// We may need to handle error checking for the MPEG4 part 2 streams, but for now we just copy the entire sequence header
// and assume that demuxers do not give us any part of a VOP. Otherwise the same issue will exist for MP4p2
NALtype = Ctx->VidParams.pMetaData[iSHStart[i]] & 0x1F;
if((((NALtype == 0x7) || (NALtype == 0x8)) && (Ctx->VidParams.MediaSubType != BC_MSUBTYPE_DIVX)) ||
(Ctx->VidParams.MediaSubType == BC_MSUBTYPE_DIVX))
{
//Start Code
//Add to Pending Buffer
for(j=0; j<BRCM_START_CODE_SIZE - 1;j++)
{
pDes[j] = 0;
}
pDes[BRCM_START_CODE_SIZE - 1] = 1;
//Get Size
iSize = iSHStop[i] - iSHStart[i] + 1;
pDes = pDes + BRCM_START_CODE_SIZE;
pSrc = pSrc + iStartSize;
//Copy Sequence Header
if(iSize > (Ctx->PESConvParams.m_iSpsPpsLen - (pDes - Ctx->PESConvParams.m_pSpsPpsBuf)))
return BC_STS_ERROR;
memcpy(pDes, pSrc, iSize);
//Update
pDes += iSize;
}
pSrc += iSize;
}
}
else
return BC_STS_INSUFF_RES;
}
return BC_STS_SUCCESS;
}
BC_STATUS DtsSetPESConverter( HANDLE hDevice)
{
DTS_LIB_CONTEXT *Ctx = NULL;
DTS_GET_CTX(hDevice,Ctx);
DtsInitPESConverter(hDevice);
uint8_t* pSeqHeader = Ctx->VidParams.pMetaData;
//SoftRave (VC-1 S/M and Divx)
if ((Ctx->DevId == BC_PCI_DEVID_FLEA) &&
((Ctx->VidParams.MediaSubType == BC_MSUBTYPE_WMV3) ||
(Ctx->VidParams.MediaSubType == BC_MSUBTYPE_DIVX) ||
(Ctx->VidParams.MediaSubType == BC_MSUBTYPE_DIVX311) ))
{
Ctx->PESConvParams.m_bSoftRave = true;
}
else
{
Ctx->PESConvParams.m_bSoftRave = false;
}
if ((Ctx->VidParams.MediaSubType == BC_MSUBTYPE_AVC1) || (Ctx->VidParams.MediaSubType == BC_MSUBTYPE_H264) || (Ctx->VidParams.MediaSubType == BC_MSUBTYPE_DIVX))
{
DtsSetSpsPps(hDevice);
if (Ctx->VidParams.MediaSubType == BC_MSUBTYPE_AVC1)
Ctx->PESConvParams.m_bIsAdd_SCode_CodeIn = true;
}
if((Ctx->VidParams.MediaSubType == BC_MSUBTYPE_WVC1) || (Ctx->VidParams.MediaSubType == BC_MSUBTYPE_WMV3) || (Ctx->VidParams.MediaSubType == BC_MSUBTYPE_WMVA))
{
Ctx->PESConvParams.m_bIsAdd_SCode_CodeIn = true;
if (pSeqHeader)
{
if (Ctx->VidParams.MediaSubType == BC_MSUBTYPE_WMV3)
{
DWORD dwSH = DWORD_SWAP(*(DWORD *)pSeqHeader);
Ctx->PESConvParams.m_bRangered = (0x00000080 & dwSH) == 0x00000080;
Ctx->PESConvParams.m_bMaxbFrames = (0x00000070 & dwSH) == 0x00000070;
Ctx->PESConvParams.m_bFinterpFlag = (0x00000002 & dwSH) == 0x00000002;
}
}
DtsSetVC1SH(hDevice);
}
return BC_STS_SUCCESS;
}
BC_STATUS DtsCheckProfile(HANDLE hDevice)
{
/*
DTS_LIB_CONTEXT *Ctx = NULL;
DTS_GET_CTX(hDevice,Ctx);
uint8_t* pSequenceHeader = Ctx->VidParams.pMetaData;
LONG lSize = Ctx->VidParams.MetaDataSz;
Ctx->VidParams.NumOfRefFrames = 0;
Ctx->VidParams.LevelIDC = 0;
if (Ctx->VidParams.MediaSubType == BC_MSUBTYPE_DIVX && Ctx->DevId != BC_PCI_DEVID_FLEA)
return BC_STS_ERROR;
if((Ctx->VidParams.MediaSubType != BC_MSUBTYPE_AVC1) && (Ctx->VidParams.MediaSubType != BC_MSUBTYPE_H264))
return BC_STS_SUCCESS;
if (pSequenceHeader == NULL || lSize <= 0)
return BC_STS_SUCCESS;
//Get SPS Size
int iSPSSize = (pSequenceHeader[0] << 8) + pSequenceHeader[1];
uint8_t *pSPS = &pSequenceHeader[2];
if (iSPSSize <=0)
return BC_STS_SUCCESS;
NALUnit nalu(pSPS, iSPSSize);
if(nalu.Type() == NALUnit::NAL_Sequence_Params)
{
SeqParamSet sq;
if(sq.Parse(&nalu))
{
int cx = sq.EncodedWidth();
int cy = sq.EncodedHeight();
bool bInterlace = sq.Interlaced();
unsigned int iNumRefFrames = sq.NumRefFrames();
// In Link we allocated 12 HD buffers for VDEC processing. This implies 12 * 1920 * 1088 bytes of memory storage.
// The actual number of reference pictures allowed will be 2 less than the number of buffers allocated.
// 2 is the number of pictures for processing overhead.
// For various resolutions the amount of memory required per buffer is as follows -
// 288x352 - 172032
// 144x176 - 65536
// 1088x1920 - 3194880
// 576x720 - 688128
// 320x352 - 196608
// 160x176 - 65536
// 720x1280 - 1474560
// Use these values to determine the number of reference pictures we can support without errors in the HW
unsigned int iNumRefPicturesSupported;
// Just handle the two large cases. Assume that no clips exist with greater than 24 reference pictures
// since no valid Profile/Level exists for that case. However x264 allows crazy things to happen. So change if needed.
if(cy > 720)
iNumRefPicturesSupported = ((12 * 3194880) / 3194880) - 2;
else
iNumRefPicturesSupported = ((12 * 3194880) / 1474560) - 2;
if(iNumRefFrames > iNumRefPicturesSupported)
{
//Reject
return BC_STS_ERROR;
}
Ctx->VidParams.NumOfRefFrames = iNumRefFrames;
Ctx->VidParams.LevelIDC = sq.LevelIDC();
}
}
*/
return BC_STS_SUCCESS;
}
BOOL DtsChkAVCSps(HANDLE hDevice, uint8_t *pBuffer, uint32_t ulSize)
{
NALU_t Nalu;
int ret = 0;
uint32_t Pos = 0;
while (1)
{
ret=DtsGetNaluType(hDevice, pBuffer + Pos,ulSize - Pos,&Nalu, false);
if (ret <= 0)
{
return FALSE;
}
Pos += ret;
if (Nalu.NalUnitType == NALU_TYPE_SPS)
return TRUE;
}
return FALSE;
}
BOOL DtsCheckSpsPps(HANDLE hDevice, uint8_t *pBuffer, uint32_t ulSize)
{
DTS_LIB_CONTEXT *Ctx = NULL;
DTS_GET_CTX(hDevice,Ctx);
if((Ctx->VidParams.MediaSubType == BC_MSUBTYPE_H264) ||
(Ctx->VidParams.MediaSubType == BC_MSUBTYPE_AVC1) ||
(Ctx->VidParams.MediaSubType == BC_MSUBTYPE_DIVX) ||
(Ctx->VidParams.MediaSubType == BC_MSUBTYPE_DIVX311))
return DtsChkAVCSps(hDevice, pBuffer, ulSize);
else
return FALSE;
}
BC_STATUS DtsAddH264SCode(HANDLE hDevice, uint8_t **ppBuffer, uint32_t *pUlDataSize, uint64_t *pTimeStamp)
{
DTS_LIB_CONTEXT *Ctx = NULL;
DTS_GET_CTX(hDevice,Ctx);
uint32_t lPendActualSize = 0;
uint8_t *pPendCurrentPos = NULL;
uint8_t *pStart = NULL;
uint32_t lDataRemained = 0;
//unused uint64_t timestamp = *pTimeStamp;
uint8_t *pNALU = NULL;
uint32_t ulNalSize = 0;
int sts;
if(Ctx->PESConvParams.lPendBufferSize < (*pUlDataSize*2))
{
if (Ctx->PESConvParams.pStartcodePendBuff)
free(Ctx->PESConvParams.pStartcodePendBuff);
Ctx->PESConvParams.lPendBufferSize = *pUlDataSize * 2;
if (Ctx->PESConvParams.lPendBufferSize < 1024)
Ctx->PESConvParams.lPendBufferSize = 1024;
// minimum 8 byte aligned since posix_memalign needs to have min of size of (void *) and on 64-bit this is 8 bytes
sts = posix_memalign((void**)&Ctx->PESConvParams.pStartcodePendBuff, 8, Ctx->PESConvParams.lPendBufferSize);
if(sts != 0)
return BC_STS_INSUFF_RES;
}
//Replace Start Code
lDataRemained = *pUlDataSize;
pStart = *ppBuffer;
lPendActualSize = 0;
pPendCurrentPos = Ctx->PESConvParams.pStartcodePendBuff;
while(1)
{
if(Ctx->PESConvParams.m_lStartCodeDataSize != 0)
{
//Remained
if(Ctx->PESConvParams.m_lStartCodeDataSize >= lDataRemained)
{
//Pre-Update Size
lPendActualSize = lPendActualSize + lDataRemained;
//Check Copy Size
if(lPendActualSize > Ctx->PESConvParams.lPendBufferSize)
{
//Error
Ctx->PESConvParams.m_lStartCodeDataSize = 0;
return BC_STS_ERROR;
}
//Copy to Pend Buffer
memcpy(pPendCurrentPos, pStart, lDataRemained);
//Update Pending Buffer
pPendCurrentPos = pPendCurrentPos + lDataRemained;
//Update Source Buffer
pStart = pStart + lDataRemained;
Ctx->PESConvParams.m_lStartCodeDataSize = Ctx->PESConvParams.m_lStartCodeDataSize - lDataRemained;
lDataRemained = 0;
//Done
break;
}
else
{
//Get Start Code Position
//Pre-Update Size
lPendActualSize = lPendActualSize + Ctx->PESConvParams.m_lStartCodeDataSize;
//Check Copy Size
if(lPendActualSize > Ctx->PESConvParams.lPendBufferSize)
{
//Error
Ctx->PESConvParams.m_lStartCodeDataSize = 0;
return BC_STS_ERROR;
}
//Copy to Pend Buffer
memcpy(pPendCurrentPos, pStart, Ctx->PESConvParams.m_lStartCodeDataSize);
//Update Pending Buffer
pPendCurrentPos = pPendCurrentPos + Ctx->PESConvParams.m_lStartCodeDataSize;
//Update Source Buffer
pStart = pStart + Ctx->PESConvParams.m_lStartCodeDataSize;
lDataRemained = lDataRemained - Ctx->PESConvParams.m_lStartCodeDataSize;
Ctx->PESConvParams.m_lStartCodeDataSize = 0;
}
}
//Get Start Code
uint8_t *StartCode = pStart;
if(lDataRemained > Ctx->VidParams.StartCodeSz)
{
//Get Size
for(uint32_t i = 0;i < Ctx->VidParams.StartCodeSz;i++)
{
Ctx->PESConvParams.m_lStartCodeDataSize <<= 8;
Ctx->PESConvParams.m_lStartCodeDataSize += StartCode[i];
}
if(Ctx->PESConvParams.m_lStartCodeDataSize < 0)
{
//Error
Ctx->PESConvParams.m_lStartCodeDataSize = 0;
return BC_STS_ERROR;
}
else if(Ctx->PESConvParams.m_lStartCodeDataSize == 1)
{
//Could be Alreay a Start Code
Ctx->PESConvParams.m_lStartCodeDataSize = 0;
Ctx->PESConvParams.m_bIsAdd_SCode_CodeIn = false;
if (Ctx->PESConvParams.pStartcodePendBuff)
free(Ctx->PESConvParams.pStartcodePendBuff);
Ctx->PESConvParams.lPendBufferSize = 0;
Ctx->PESConvParams.pStartcodePendBuff = NULL;
return BC_STS_SUCCESS;
}
else if(Ctx->PESConvParams.m_lStartCodeDataSize < *pUlDataSize)
{
//Succeeded
//Check NAL Unit Type
pNALU = pStart + Ctx->VidParams.StartCodeSz;
ulNalSize = Ctx->PESConvParams.m_lStartCodeDataSize;
//BRCM Start Code
//Pre-Update Size
lPendActualSize = lPendActualSize + BRCM_START_CODE_SIZE;
//Check Copy Size
if(lPendActualSize >Ctx->PESConvParams.lPendBufferSize)
{
//Error
Ctx->PESConvParams.m_lStartCodeDataSize = 0;
return BC_STS_ERROR;
}
//Add to Pending Buffer
for(int i=0;i<BRCM_START_CODE_SIZE - 1;i++)
{
pPendCurrentPos[i] = 0;
}
pPendCurrentPos[BRCM_START_CODE_SIZE - 1] = 1;
//Update Pending Buffer
pPendCurrentPos = pPendCurrentPos + BRCM_START_CODE_SIZE;
//Update Source Buffer
pStart = pStart + Ctx->VidParams.StartCodeSz;
lDataRemained = lDataRemained - Ctx->VidParams.StartCodeSz;
}
}
else
{
//Error
return BC_STS_IO_XFR_ERROR;
}
}//While
//Use Pending Buffer Directly
*ppBuffer = Ctx->PESConvParams.pStartcodePendBuff;
*pUlDataSize = lPendActualSize;
return BC_STS_SUCCESS;
}
BC_STATUS DtsAddVC1SCode(HANDLE hDevice, uint8_t **ppBuffer, uint32_t *pUlDataSize, uint64_t *pTimeStamp)
{
uint32_t iCount = 0;
int sts = 0;
DTS_LIB_CONTEXT *Ctx = NULL;
DTS_GET_CTX(hDevice,Ctx);
uint64_t timestamp = *pTimeStamp;
//Check Start Code for AP and SP/MP
if(((*ppBuffer)[0] == 0x00) && ((*ppBuffer)[1] == 0x00) && ((*ppBuffer)[2] == 0x01) && (((*ppBuffer)[3] == 0x0F) || ((*ppBuffer)[3] == 0x0D) || ((*ppBuffer)[3] == 0xE0)))
{
Ctx->PESConvParams.m_bIsAdd_SCode_CodeIn = false;
if (Ctx->PESConvParams.pStartcodePendBuff)
free(Ctx->PESConvParams.pStartcodePendBuff);
Ctx->PESConvParams.lPendBufferSize = 0;
Ctx->PESConvParams.pStartcodePendBuff = NULL;
return BC_STS_SUCCESS;
}
if(Ctx->PESConvParams.lPendBufferSize < (*pUlDataSize*2))
{
if (Ctx->PESConvParams.pStartcodePendBuff)
free(Ctx->PESConvParams.pStartcodePendBuff);
Ctx->PESConvParams.lPendBufferSize = *pUlDataSize * 2;
if (Ctx->PESConvParams.lPendBufferSize < 1024)
Ctx->PESConvParams.lPendBufferSize = 1024;
sts = posix_memalign((void**)&Ctx->PESConvParams.pStartcodePendBuff, 8, Ctx->PESConvParams.lPendBufferSize);
if(sts)
return BC_STS_INSUFF_RES;
}
//unused uint8_t* pSequenceHeader = Ctx->VidParams.pMetaData;
//unused LONG iSHSize = Ctx->VidParams.MetaDataSz;
if((Ctx->VidParams.MediaSubType == BC_MSUBTYPE_WVC1) || (Ctx->VidParams.MediaSubType == BC_MSUBTYPE_WMVA))
{
//Copy Start Code
LONG lStartCodeSize = 4;
memcpy(Ctx->PESConvParams.pStartcodePendBuff + iCount, (uint8_t *)b_asf_vc1_frame_scode, lStartCodeSize);
iCount += lStartCodeSize;
//Copy Data
memcpy(Ctx->PESConvParams.pStartcodePendBuff + iCount, (uint8_t *)*ppBuffer, *pUlDataSize);
iCount +=*pUlDataSize;
*pTimeStamp = timestamp;
}
else
{
//SP / MP
uint8_t* pData = *ppBuffer;
uint8_t* pDst = Ctx->PESConvParams.pStartcodePendBuff;
if (Ctx->DevId == BC_PCI_DEVID_LINK)
{
LONG lCIHeaderSize = 17;
LONG lCIPacketSize = 0;
LONG lCIZeroPaddingSize = 0;
LONG lCILastDataLoc = *pUlDataSize - 1;
if ((lCIHeaderSize + *pUlDataSize) & 0x1F)
lCIPacketSize = (((lCIHeaderSize + *pUlDataSize) / 32) + 1) * 32;
else
lCIPacketSize = (lCIHeaderSize + *pUlDataSize);
//Code-In Zero Padding
lCIZeroPaddingSize = lCIPacketSize - (lCIHeaderSize + *pUlDataSize);
memcpy(pDst, b_asf_vc1_sm_codein_header, 16);
*((uint32_t *)(pDst + 4)) = DWORD_SWAP((uint32_t)lCIPacketSize);
*((uint32_t *)(pDst + 8)) = DWORD_SWAP((uint32_t)lCILastDataLoc);
memcpy(pDst + 16, (uint8_t *)b_asf_vc1_sm_codein_data_suffix, 1);
memcpy(pDst + 17, pData, *pUlDataSize);
memset(pDst + 17 + *pUlDataSize, 0, lCIZeroPaddingSize);
iCount = lCIPacketSize;
}
else if (Ctx->DevId == BC_PCI_DEVID_FLEA)
{
memcpy(pDst, b_asf_vc1_sm_picheader_scode, 4);
memcpy(pDst + 4, pData, *pUlDataSize);
iCount = *pUlDataSize + 4;
}
}
*ppBuffer = Ctx->PESConvParams.pStartcodePendBuff;
*pUlDataSize = iCount;
return BC_STS_SUCCESS;
}
BC_STATUS DtsCheckKeyFrame(HANDLE hDevice, uint8_t *pBuffer)
{
DTS_LIB_CONTEXT *Ctx = NULL;
DTS_GET_CTX(hDevice,Ctx);
//unused BC_STATUS sts = BC_STS_SUCCESS;
bool bKeyFrame = false;
int iType = 0;
if((Ctx->VidParams.MediaSubType == BC_MSUBTYPE_WVC1) || (Ctx->VidParams.MediaSubType == BC_MSUBTYPE_WMVA))
{
//Advanced Profile
//0: P Type
//1: B Type
//2: I Type
//3: BI Type
//Interlaced Check
if(!Ctx->VidParams.Progressive)
{
//Interlaced
//Skip FCM with 2 bits
//Get Type
//--xx xxxx
//--?
if((pBuffer[0] & 0x20) == 0)
{
iType = 0;
}
//--1?
else if((pBuffer[0] & 0x10) == 0)
{
iType = 1;
}
//--11 ?
else if((pBuffer[0] & 0x08) == 0)
{
iType = 2;
}
//--11 1?
else if((pBuffer[0] & 0x04) == 0)
{
iType = 3;
}
}
else
{
//Progress
//Get Type
//xxxx xxxx
//?
if((pBuffer[0] & 0x80) == 0)
{
iType = 0;
}
//1?
else if((pBuffer[0] & 0x40) == 0)
{
iType = 1;
}
//11?
else if((pBuffer[0] & 0x20) == 0)
{
iType = 2;
}
//111?
else if((pBuffer[0] & 0x10) == 0)
{
iType = 3;
}
}
//Check Key Frame
if(iType == 2)
{
bKeyFrame = true;
}
}
else
{
//SP / MP
//0: P Type
//1: B Type
//2: I Type
//3: BI Type
int iCurrentBit = 0;
//Check Finterpflag
if(Ctx->PESConvParams.m_bFinterpFlag)
{
iCurrentBit = iCurrentBit + 1;
}
//Drop 2 bits
iCurrentBit = iCurrentBit + 2;
//Check Rangered
if(Ctx->PESConvParams.m_bRangered)
{
iCurrentBit = iCurrentBit + 1;
}
//Check Bit
uint8_t bFirstCheck = 0;
uint8_t bSecondCheck = 0;
if(iCurrentBit == 2)
{
bFirstCheck = 0x20;
bSecondCheck = 0x10;
}
else if(iCurrentBit == 3)
{
bFirstCheck = 0x10;
bSecondCheck = 0x08;
}
else if(iCurrentBit == 4)
{
bFirstCheck = 0x08;
bSecondCheck = 0x04;
}
if(pBuffer[0] & bFirstCheck)
{
iType = 0;
}
else if(!Ctx->PESConvParams.m_bMaxbFrames)
{
iType = 2;
}
else if(pBuffer[0] & bSecondCheck)
{
iType = 2;
}
else
{
iType = 1;
}
//Check Key Frame
if(iType == 2)
{
bKeyFrame = true;
}
}
if (bKeyFrame)
{
Ctx->PESConvParams.m_bAddSpsPps = true;
}
return BC_STS_SUCCESS;
}
BC_STATUS DtsAddStartCode(HANDLE hDevice, uint8_t **ppBuffer, uint32_t *pUlDataSize, uint64_t * pTimeStamp)
{
DTS_LIB_CONTEXT *Ctx = NULL;
DTS_GET_CTX(hDevice,Ctx);
//unused BC_STATUS sts = BC_STS_SUCCESS;
if (!Ctx->PESConvParams.m_bIsAdd_SCode_CodeIn)
return BC_STS_SUCCESS;
if(Ctx->VidParams.MediaSubType == BC_MSUBTYPE_AVC1 || Ctx->VidParams.MediaSubType == BC_MSUBTYPE_DIVX)
return DtsAddH264SCode(hDevice, ppBuffer, pUlDataSize, pTimeStamp);
if((Ctx->VidParams.MediaSubType == BC_MSUBTYPE_WVC1) || (Ctx->VidParams.MediaSubType == BC_MSUBTYPE_WMV3) || (Ctx->VidParams.MediaSubType == BC_MSUBTYPE_WMVA) || (Ctx->VidParams.MediaSubType == BC_MSUBTYPE_VC1))
return DtsAddVC1SCode(hDevice, ppBuffer, pUlDataSize, pTimeStamp);
return BC_STS_SUCCESS;
}
int DtsFindBSStartCode (unsigned char *Buf, int ZerosInStartcode)
{
BOOL bStartCode = TRUE;
int i;
for (i = 0; i < ZerosInStartcode; i++)
if(Buf[i] != 0)
bStartCode = FALSE;
if(Buf[i] != 1)
bStartCode = FALSE;
return bStartCode;
}
int DtsGetNaluType(HANDLE hDevice, uint8_t* pInputBuf, uint32_t ulSize, NALU_t* pNalu, bool bSkipSyncMarker)
{
DTS_LIB_CONTEXT *Ctx = NULL;
int b20sInSC, b30sInSC ;
int bStartCodeFound, Rewind;
int nLeadingZero8BitsCount=0, TrailingZero8Bits=0;
//unused bool bSetIDR = true;
//unused static BOOL fOne = TRUE;
uint32_t Pos = 0;
DTS_GET_CTX(hDevice,Ctx);
if (bSkipSyncMarker)
{
pNalu->NalUnitType = (pInputBuf[0]) & 0x1f;
pNalu->Len = ulSize;
return 1;
}
while(Pos <= ulSize)
{
if( (pInputBuf[Pos++]) == 0)
continue;
else
break;
}
if(pInputBuf[Pos-1] != 1)
{
return -1;
}
if(Pos < 3)
{
return -1;
}
else if(Pos == 3)
{
pNalu->StartcodePrefixLen = 3;
nLeadingZero8BitsCount = 0;
}
else
{
nLeadingZero8BitsCount = Pos-4;
pNalu->StartcodePrefixLen = 4;
}
//the 1st byte stream NAL unit can has nLeadingZero8BitsCount, but subsequent ones are not
//allowed to contain it since these zeros(if any) are considered trailing_zero_8bits
//of the previous byte stream NAL unit.
if(!Ctx->PESConvParams.m_bIsFirstByteStreamNALU && nLeadingZero8BitsCount>0)
{
// DbgLog((LOG_TRACE, 1, TEXT("GetNaluType : ret 3\n")));
return -1;
}
Ctx->PESConvParams.m_bIsFirstByteStreamNALU = false;
bStartCodeFound = 0;
b20sInSC = 0;
b30sInSC = 0;
while( (!bStartCodeFound) && (Pos < ulSize))
{
Pos++;
if(Pos > ulSize)
{
// DbgLog((LOG_TRACE, 1, TEXT("GetNaluType : Pos > size = %d\n"),ulSize));
}
b30sInSC = DtsFindBSStartCode( (pInputBuf + Pos- 4), 3);
if(b30sInSC != 1)
b20sInSC = DtsFindBSStartCode( (pInputBuf + Pos -3), 2);
bStartCodeFound = (b20sInSC || b30sInSC);
}
Rewind = 0;
if(!bStartCodeFound)
{
// DbgLog((LOG_TRACE, 1, TEXT("GetNaluType : ret 4 Pos = %d size = %d\n"),Pos,ulSize));
//even if next start code is not found pprocess this NAL.
#if 0
return -1;
#endif
}
if(bStartCodeFound)
{
//Count the trailing_zero_8bits
//TrailingZero8Bits is present only for start code 00 00 00 01
if(b30sInSC)
{
while(pInputBuf[Pos-5-TrailingZero8Bits]==0)
TrailingZero8Bits++;
}
// Here, we have found another start code (and read length of startcode bytes more than we should
// have. Hence, go back in the file
if(b30sInSC)
Rewind = -4;
else if (b20sInSC)
Rewind = -3;
}
// Here the leading zeros(if any), Start code, the complete NALU, trailing zeros(if any)
// until the next start code .
// Total size traversed is Pos, Pos+rewind are the number of bytes excluding the next
// start code, and (Pos+rewind)-StartcodePrefixLen-LeadingZero8BitsCount-TrailingZero8Bits
// is the size of the NALU.
pNalu->Len = (Pos+Rewind)-pNalu->StartcodePrefixLen-nLeadingZero8BitsCount-TrailingZero8Bits;
pNalu->NalUnitType = (pInputBuf[nLeadingZero8BitsCount+pNalu->StartcodePrefixLen]) & 0x1f;
return (Pos+Rewind);
}
BC_STATUS DtsParseAVC(HANDLE hDevice, uint8_t* pInputBuf, ULONG ulSize, uint32_t* Offset, bool bIDR, int *pNalType)
{
NALU_t Nalu;
int ret = 0;
uint32_t Pos = 0;
bool bResult = false;
*pNalType = -1;
while (1)
{
ret=DtsGetNaluType(hDevice, pInputBuf + Pos,ulSize - Pos,&Nalu, false);
if (ret <= 0)
{
return BC_STS_ERROR;
}
Pos += ret;
switch (Nalu.NalUnitType)
{
case NALU_TYPE_SLICE:
case NALU_TYPE_IDR:
bResult = true;
break;
case NALU_TYPE_SEI:
case NALU_TYPE_PPS:
case NALU_TYPE_SPS:
if(!bIDR)
bResult = true;
break;
case NALU_TYPE_DPA:
case NALU_TYPE_DPC:
case NALU_TYPE_AUD:
case NALU_TYPE_EOSEQ:
case NALU_TYPE_EOSTREAM:
case NALU_TYPE_FILL:
default:
break;
}
if(bResult)
{
*Offset = Pos;
break;
}
}
*pNalType = Nalu.NalUnitType;
return BC_STS_SUCCESS;
}
BC_STATUS DtsFindIDR(HANDLE hDevice, uint8_t* pInputBuffer, uint32_t ulSizeInBytes, uint32_t* pOffset)
{
int nNalType = 0;
uint32_t ulPos = 0;
DtsParseAVC(hDevice, pInputBuffer, ulSizeInBytes, &ulPos, true, &nNalType);
if( (nNalType == NALU_TYPE_SLICE) | (nNalType == NALU_TYPE_IDR))
{
*pOffset = ulPos;
return BC_STS_SUCCESS;
}
return BC_STS_ERROR;
}
BC_STATUS DtsFindStartCode(HANDLE hDevice, uint8_t* pInputBuffer, uint32_t ulSizeInBytes, uint32_t* pOffset)
{
DTS_LIB_CONTEXT *Ctx = NULL;
uint32_t i=0;
uint8_t Suffix1 = 0;
uint8_t Suffix2 = 0;
*pOffset = 0;
DTS_GET_CTX(hDevice,Ctx);
if (Ctx->VidParams.MediaSubType == BC_MSUBTYPE_WVC1 || Ctx->VidParams.MediaSubType == BC_MSUBTYPE_WMVA || Ctx->VidParams.MediaSubType == BC_MSUBTYPE_VC1)
{
Suffix1 = VC1_FRM_SUFFIX;
Suffix2 = VC1_SEQ_SUFFIX;
}
else if (Ctx->VidParams.MediaSubType == BC_MSUBTYPE_MPEG2VIDEO)
{
Suffix1 = MPEG2_FRM_SUFFIX;
Suffix2 = MPEG2_SEQ_SUFFIX;
}
else if (Ctx->VidParams.MediaSubType ==BC_MSUBTYPE_WMV3)
//For VC-1 SP/MP
{
Suffix1 = VC1_SM_FRM_SUFFIX;
}
if((Ctx->VidParams.MediaSubType == BC_MSUBTYPE_H264) || (Ctx->VidParams.MediaSubType == BC_MSUBTYPE_AVC1) || (Ctx->VidParams.MediaSubType == BC_MSUBTYPE_DIVX))
{
int nNalType = 0;
uint32_t ulPos = 0;
if (DtsParseAVC(hDevice, pInputBuffer,ulSizeInBytes,&ulPos,false, &nNalType) != BC_STS_SUCCESS)
return BC_STS_ERROR;
if( (nNalType == NALU_TYPE_SEI) || (nNalType == NALU_TYPE_PPS) || (nNalType == NALU_TYPE_SPS))
{
*pOffset = ulPos;
return BC_STS_SUCCESS;
}
else if( (nNalType == NALU_TYPE_SLICE) | (nNalType == NALU_TYPE_IDR))
{
*pOffset = 0;
return BC_STS_SUCCESS;
}
return BC_STS_ERROR;
}
else if((Ctx->VidParams.MediaSubType == BC_MSUBTYPE_MPEG2VIDEO) || (Ctx->VidParams.MediaSubType == BC_MSUBTYPE_WVC1) ||
(Ctx->VidParams.MediaSubType == BC_MSUBTYPE_WMVA) || (Ctx->VidParams.MediaSubType ==BC_MSUBTYPE_WMV3) || (Ctx->VidParams.MediaSubType == BC_MSUBTYPE_VC1))
{
while(i < ulSizeInBytes)
{
if( (*(pInputBuffer +i) == Suffix1) || (*(pInputBuffer +i) == Suffix2))
{
if(i >= 3)
{
if( (*(pInputBuffer+(i-3)) == 0x00) && (*(pInputBuffer+(i-2)) == 0x00) && (*(pInputBuffer+(i-1)) == 0x01))
{
*pOffset = i-3;
return BC_STS_SUCCESS;
}
}
}
i++;
}
return BC_STS_ERROR;
}
return BC_STS_SUCCESS;
}
BOOL DtsFindPTSInfoCode(HANDLE hDevice, uint8_t* pInputBuffer, uint32_t ulSizeInBytes)
{
DTS_LIB_CONTEXT *Ctx = NULL;
DTS_GET_CTX(hDevice,Ctx);
if((Ctx->VidParams.MediaSubType != BC_MSUBTYPE_WMV3) && (Ctx->VidParams.MediaSubType != BC_MSUBTYPE_WMVA))
return FALSE;
//Move PES Header
uint32_t ulCurrent = 8;
uint8_t bPESHeaderLen = pInputBuffer[ulCurrent];
ulCurrent = ulCurrent + bPESHeaderLen + 1;
//Check PES Payload for PTS Info
if((ulSizeInBytes - ulCurrent) == 32)
{
DWORD dwFirstCode = *(DWORD *)&pInputBuffer[ulCurrent];
ulCurrent = ulCurrent + 12;
DWORD dwSecondCode = *(DWORD *)&pInputBuffer[ulCurrent];
ulCurrent = ulCurrent + 4;
if((dwFirstCode == VC1_SM_MAGIC_WORD) && (dwSecondCode == VC1_SM_MAGIC_WORD) && (pInputBuffer[ulCurrent] == VC1_SM_PTS_INFO_START_CODE))
{
return TRUE;
}
}
return FALSE;
}
BC_STATUS DtsSymbIntSiBuffer (HANDLE hDevice, uint8_t* pInputBuffer, ULONG ulSize)
{
DTS_LIB_CONTEXT *Ctx = NULL;
DTS_GET_CTX(hDevice,Ctx);
SYMBINT *pSymbint = &(Ctx->PESConvParams.m_SymbInt);
pSymbint->m_pCurrent = pSymbint->m_pInputBuffer = (uint8_t*) pInputBuffer;
pSymbint->m_nSize = ulSize;
pSymbint->m_pInputBufferEnd = pSymbint->m_pInputBuffer + ulSize;
pSymbint->m_nUsed = 1;
pSymbint->m_ulOffset = 0;
pSymbint->m_ulMask = 0x80;
return BC_STS_SUCCESS;
}
BC_STATUS DtsSymbIntSiUe (HANDLE hDevice, ULONG* pCode)
{
uint32_t ulSuffix;
int nLeadingZeros;
int nBit;
DTS_LIB_CONTEXT *Ctx = NULL;
DTS_GET_CTX(hDevice,Ctx);
SYMBINT *pSymbint = &(Ctx->PESConvParams.m_SymbInt);
nLeadingZeros = -1;
for (nBit = 0; nBit == 0; nLeadingZeros++)
{
nBit = DtsSymbIntNextBit(hDevice);
if(pSymbint->m_nUsed >= pSymbint->m_nSize)
return BC_STS_ERROR;
}
*pCode = (1 << nLeadingZeros) - 1;
ulSuffix = 0;
while (nLeadingZeros-- > 0 )
{
ulSuffix = (ulSuffix << 1) | DtsSymbIntNextBit(hDevice);
if(pSymbint->m_nUsed >= pSymbint->m_nSize)
return BC_STS_ERROR;
}
*pCode += ulSuffix;
return BC_STS_SUCCESS;
}
inline int DtsSymbIntNextBit ( HANDLE hDevice )
{
int nBit;
DTS_LIB_CONTEXT *Ctx = NULL;
DTS_GET_CTX(hDevice,Ctx);
SYMBINT *pSymbint = &(Ctx->PESConvParams.m_SymbInt);
nBit = (pSymbint->m_pCurrent[0] & pSymbint->m_ulMask) ? 1 : 0;
if ((pSymbint->m_ulMask >>= 1) == 0)
{
pSymbint->m_ulMask = 0x80;
if ( pSymbint->m_nUsed == pSymbint->m_nSize )
pSymbint->m_pCurrent = pSymbint->m_pInputBuffer;//reset look again
else
{
if ( ++pSymbint->m_pCurrent == pSymbint->m_pInputBufferEnd )
pSymbint->m_pCurrent = pSymbint->m_pInputBuffer;
pSymbint->m_nUsed++;
}
}
pSymbint->m_ulOffset++;
return nBit;
}
#if 0
void *DtsAlignedMalloc(size_t size, size_t alignment)
{
void *p1 ,*p2; // basic pointer needed for computation.
if((p1 =(void *) malloc(size + alignment + sizeof(size_t)))==NULL)
return NULL;
size_t addr = (size_t)p1 + alignment + sizeof(size_t);
p2 = (void *)(addr - (addr%alignment));
*((size_t *)p2-1) = (size_t)p1;
return p2;
}
void DtsAlignedFree(void *ptr)
{
if (ptr)
free((void *)(*((size_t *) ptr-1)));
}
#endif