/*------------------------------------------------------------------------------ -- -- -- This software is confidential and proprietary and may be used -- -- only as expressly authorized by a licensing agreement from -- -- -- -- Hantro Products Oy. -- -- -- -- (C) COPYRIGHT 2006 HANTRO PRODUCTS OY -- -- ALL RIGHTS RESERVED -- -- -- -- The entire notice above must be reproduced -- -- on all copies and should not be removed. -- -- -- -------------------------------------------------------------------------------- -- -- Description : jpeg scan decode source -- ------------------------------------------------------------------------------ -- -- Version control information, please leave untouched. -- -- $RCSfile: jpegdecscan.c,v $ -- $Revision: 1.12 $ -- $Date: 2008/10/14 12:00:55 $ -- ------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------ Table of contents 1. Include headers 2. External compiler flags 3. Module defines 4. Local function prototypes 5. Functions - JpegDecDecodeScan - JpegDecDecodeScanHeader - JpegDecDecodeBaselineScan - JpegDecDecodeProgressiveScan - JpegDecDecodeBaselineBlock ------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------ 1. Include headers ------------------------------------------------------------------------------*/ #include #include #include "jpegdecutils.h" #include "jpegdecinternal.h" #include "jpegdecmarkers.h" #include "jpegdecscan.h" #include "dwl.h" /*------------------------------------------------------------------------------ 2. External compiler flags -------------------------------------------------------------------------------- _DTRACE: define this flag to print trace information to stdout -------------------------------------------------------------------------------- 3. Module defines ------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------ 4. Local function prototypes ------------------------------------------------------------------------------*/ JpegDecRet JpegDecDecodeScanHeader(JpegDecContainer *); /*------------------------------------------------------------------------------ 5. Functions ------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------ Function name: JpegDecDecodeScan Functional description: Handles the top level control of scan decoding Inputs: JpegDecContainer *pDecData Pointer to JpegDecContainer structure Outputs: OK (0) NOK (-1) ------------------------------------------------------------------------------*/ JpegDecRet JpegDecDecodeScan(JpegDecContainer * pDecData) { JpegDecRet retCode; /* Returned code container */ retCode = JPEGDEC_ERROR; retCode = JpegDecDecodeScanHeader(pDecData); if(retCode != JPEGDEC_OK) { return (retCode); } JPEGDEC_TRACE_INTERNAL(("SCAN: Allocate residual buffer\n")); /* Allocate buffers if not done already */ if(!pDecData->info.allocated) { retCode = JpegDecAllocateResidual(pDecData); if(retCode != JPEGDEC_OK) { JPEGDEC_TRACE_INTERNAL(("SCAN: ALLOCATE ERROR\n")); return (retCode); } /* update */ pDecData->info.allocated = 1; } JPEGDEC_TRACE_INTERNAL(("SCAN: Scan rlc data\n")); JPEGDEC_TRACE_INTERNAL(("SCAN: MODE: %d\n", pDecData->frame.codingType)); return (JPEGDEC_OK); } /*------------------------------------------------------------------------------ Function name: JpegDecDecodeScanHeader Functional description: Decodes scan headers Inputs: JpegDecContainer *pDecData Pointer to JpegDecContainer structure Outputs: OK (0) NOK (-1) ------------------------------------------------------------------------------*/ JpegDecRet JpegDecDecodeScanHeader(JpegDecContainer * pDecData) { u32 i; u32 tmp; StreamStorage *pStream = &(pDecData->stream); pDecData->scan.Ls = JpegDecGet2Bytes(pStream); /* check if there is enough data */ if(((pStream->readBits / 8) + pDecData->scan.Ls) > pStream->streamLength) return (JPEGDEC_STRM_ERROR); pDecData->scan.Ns = JpegDecGetByte(pStream); pDecData->info.fillX = pDecData->info.fillY = 0; if(pDecData->scan.Ns == 1) { /* Reset to non-interleaved baseline operation type */ if(pDecData->info.operationType == JPEGDEC_BASELINE && pDecData->info.yCbCrMode != JPEGDEC_YUV400) pDecData->info.operationType = JPEGDEC_NONINTERLEAVED; tmp = JpegDecGetByte(&(pDecData->stream)); pDecData->frame.cIndex = tmp - 1; pDecData->info.componentId = pDecData->frame.cIndex; pDecData->scan.Cs[pDecData->frame.cIndex] = tmp; tmp = JpegDecGetByte(pStream); pDecData->scan.Td[pDecData->frame.cIndex] = tmp >> 4; pDecData->scan.Ta[pDecData->frame.cIndex] = tmp & 0x0F; /* check/update component info */ if(pDecData->frame.Nf == 3) { pDecData->info.fillRight = 0; pDecData->info.fillBottom = 0; pDecData->info. pfNeeded[pDecData->scan.Cs[pDecData->frame.cIndex] - 1] = 0; if(pDecData->scan.Cs[pDecData->frame.cIndex] == 2 || pDecData->scan.Cs[pDecData->frame.cIndex] == 3) { if(pDecData->info.operationType == JPEGDEC_PROGRESSIVE || pDecData->info.operationType == JPEGDEC_NONINTERLEAVED || pDecData->info.nonInterleavedScanReady) { if(pDecData->info.yCbCrModeOrig == JPEGDEC_YUV420) { pDecData->info.X = pDecData->frame.hwX >> 1; pDecData->info.Y = pDecData->frame.hwY >> 1; } else if(pDecData->info.yCbCrModeOrig == JPEGDEC_YUV422) { pDecData->info.X = pDecData->frame.hwX >> 1; } else if(pDecData->info.yCbCrModeOrig == JPEGDEC_YUV440) { pDecData->info.Y = pDecData->frame.hwY >> 1; } else { pDecData->info.yCbCrMode = 0; return (JPEGDEC_UNSUPPORTED); } } pDecData->info.yCbCrMode = 0; } else if(pDecData->scan.Cs[pDecData->frame.cIndex] == 1) /* YCbCr 4:2:0 */ { pDecData->info.X = pDecData->frame.hwX; pDecData->info.Y = pDecData->frame.hwY; if(pDecData->info.yCbCrMode == JPEGDEC_YUV420) { pDecData->info.yCbCrMode = 1; } else if(pDecData->info.yCbCrMode == JPEGDEC_YUV422) { pDecData->info.yCbCrMode = 0; if(pDecData->frame.cIndex == 0) { JPEGDEC_TRACE_INTERNAL(("SCAN: #YUV422 FLAG\n")); pDecData->info.yCbCr422 = 1; } } else if(pDecData->info.yCbCrMode == JPEGDEC_YUV444) { pDecData->info.yCbCrMode = 0; return (JPEGDEC_UNSUPPORTED); } } else { pDecData->info.yCbCrMode = 0; return (JPEGDEC_UNSUPPORTED); } if(pDecData->info.X & 0xF) { pDecData->info.X += 8; pDecData->info.fillX = 1; } else if((pDecData->scan.Cs[pDecData->frame.cIndex] == 1 || pDecData->info.yCbCrModeOrig == JPEGDEC_YUV440) && (pDecData->frame.X & 0xF) && (pDecData->frame.X & 0xF) <= 8) { pDecData->info.fillRight = 1; } if(pDecData->info.Y & 0xF) { pDecData->info.Y += 8; pDecData->info.fillY = 1; } else if((pDecData->scan.Cs[pDecData->frame.cIndex] == 1 || pDecData->info.yCbCrModeOrig == JPEGDEC_YUV422) && (pDecData->frame.Y & 0xF) && (pDecData->frame.Y & 0xF) <= 8) { pDecData->info.fillBottom = 1; } } else if(pDecData->frame.Nf == 1) { JPEGDEC_TRACE_INTERNAL(("SCAN: #YUV422 FLAG\n")); pDecData->info.yCbCr422 = 0; } /* decoding info */ if(pDecData->info.operationType == JPEGDEC_PROGRESSIVE || pDecData->info.operationType == JPEGDEC_NONINTERLEAVED) { pDecData->info.yCbCrMode = 0; } } else { for(i = 0; i < pDecData->scan.Ns; i++) { pDecData->scan.Cs[i] = JpegDecGetByte(&(pDecData->stream)); tmp = JpegDecGetByte(pStream); pDecData->scan.Td[i] = tmp >> 4; /* which DC table */ pDecData->scan.Ta[i] = tmp & 0x0F; /* which AC table */ pDecData->info.pfNeeded[i] = 1; } pDecData->info.X = pDecData->frame.hwX; pDecData->info.Y = pDecData->frame.hwY; pDecData->frame.cIndex = 0; pDecData->info.yCbCrMode = pDecData->info.yCbCrModeOrig; } pDecData->scan.Ss = JpegDecGetByte(pStream); pDecData->scan.Se = JpegDecGetByte(pStream); tmp = JpegDecGetByte(pStream); pDecData->scan.Ah = tmp >> 4; pDecData->scan.Al = tmp & 0x0F; if(pDecData->frame.codingType == SOF0) { /* baseline */ if(pDecData->scan.Ss != 0) return (JPEGDEC_UNSUPPORTED); if(pDecData->scan.Se != 63) return (JPEGDEC_UNSUPPORTED); if(pDecData->scan.Ah != 0) return (JPEGDEC_UNSUPPORTED); if(pDecData->scan.Al != 0) return (JPEGDEC_UNSUPPORTED); /* update scan decoding parameters */ /* interleaved/non-interleaved */ if(pDecData->info.operationType == JPEGDEC_BASELINE) pDecData->info.nonInterleaved = 0; else pDecData->info.nonInterleaved = 1; /* decoding info */ if((pDecData->frame.Nf == 3 && pDecData->scan.Ns == 1) || (pDecData->frame.Nf == 1 && pDecData->scan.Ns == 1)) pDecData->info.amountOfQTables = 1; else pDecData->info.amountOfQTables = 3; } if(pDecData->frame.codingType == SOF2) { /* progressive */ if(pDecData->scan.Ss == 0 && pDecData->scan.Se != 0) return (JPEGDEC_UNSUPPORTED); if(pDecData->scan.Ah < 0 || pDecData->scan.Ah > 13) return (JPEGDEC_UNSUPPORTED); if(pDecData->scan.Al < 0 || pDecData->scan.Al > 13) return (JPEGDEC_UNSUPPORTED); /* update scan decoding parameters */ /* TODO! What if 2 components, possible??? */ /* interleaved/non-interleaved */ if(pDecData->scan.Ns == 1) { pDecData->info.nonInterleaved = 1; /* component ID */ pDecData->info.componentId = pDecData->frame.cIndex; pDecData->info.amountOfQTables = 1; } else { pDecData->info.nonInterleaved = 0; /* component ID ==> set to luma ==> interleaved */ pDecData->info.componentId = 0; pDecData->info.amountOfQTables = 3; } } return (JPEGDEC_OK); }