/*------------------------------------------------------------------------------ -- -- -- This software is confidential and proprietary and may be used -- -- only as expressly authorized by a licensing agreement from -- -- -- -- Rockchip Products . -- -- -- -- (C) COPYRIGHT 2014 ROCKCHIP PRODUCTS -- -- ALL RIGHTS RESERVED -- -- -- -- The entire notice above must be reproduced -- -- on all copies and should not be removed. -- -- -- -------------------------------------------------------------------------------- -- -- Description : Jpeg decoder header decoding source code -- ------------------------------------------------------------------------------ -- -- -- ------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------ Table of contents 1. Include headers 2. External compiler flags 3. Module defines 4. Local function prototypes 5. Functions - JpegDecDecodeFrame - JpegDecDecodeQuantTables - JpegDecDecodeHuffmanTables ------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------ 1. Include headers ------------------------------------------------------------------------------*/ #include "jpegdechdrs.h" #include "jpegdecutils.h" #include "jpegdecmarkers.h" #include "jpegdecinternal.h" #include "jpegdecscan.h" #include "jpegdecapi.h" #include "dwl.h" #include /*------------------------------------------------------------------------------ 2. External compiler flags -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- 3. Module defines ------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------ 4. Local function prototypes ------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------ 5. Functions ------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------ Function name: JpegDecDecodeFrame Functional description: Decodes frame headers Inputs: JpegDecContainer *pDecData Pointer to JpegDecContainer structure Outputs: OK/NOK ------------------------------------------------------------------------------*/ JpegDecRet JpegDecDecodeFrameHdr(JpegDecContainer * pDecData) { RK_U32 i; RK_U32 width, height; RK_U32 tmp1, tmp2; RK_U32 Hmax = 0; RK_U32 Vmax = 0; RK_U32 size = 0; JpegDecRet retCode; retCode = JPEGDEC_OK; /* frame header length */ pDecData->frame.Lf = JpegDecGet2Bytes(&(pDecData->stream)); /* check if there is enough data */ if (((pDecData->stream.readBits / 8) + pDecData->frame.Lf) > pDecData->stream.streamLength) return (JPEGDEC_STRM_ERROR); /* Sample precision */ pDecData->frame.P = JpegDecGetByte(&(pDecData->stream)); if (pDecData->frame.P != 8) { JPEGDEC_TRACE_INTERNAL(("if ( pDecData->frame.P != 8)\n")); return (JPEGDEC_UNSUPPORTED); } /* Number of Lines */ pDecData->frame.Y = JpegDecGet2Bytes(&(pDecData->stream)); if (pDecData->frame.Y < 1) { return (JPEGDEC_UNSUPPORTED); } pDecData->frame.hwY = pDecData->frame.Y; /* round up to next multiple-of-16 */ pDecData->frame.hwY += 0xf; pDecData->frame.hwY &= ~(0xf); /* Number of samples per line */ pDecData->frame.X = JpegDecGet2Bytes(&(pDecData->stream)); if (pDecData->frame.X < 1) { return (JPEGDEC_UNSUPPORTED); } pDecData->frame.hwX = pDecData->frame.X; /* round up to next multiple-of-16 */ pDecData->frame.hwX += 0xf; pDecData->frame.hwX &= ~(0xf); /* for internal() */ pDecData->info.X = pDecData->frame.hwX; pDecData->info.Y = pDecData->frame.hwY; /* check for minimum and maximum dimensions */ if (pDecData->frame.hwX < pDecData->minSupportedWidth || pDecData->frame.hwY < pDecData->minSupportedHeight || pDecData->frame.hwX > pDecData->maxSupportedWidth || pDecData->frame.hwY > pDecData->maxSupportedHeight || (pDecData->frame.hwX * pDecData->frame.hwY) > pDecData->maxSupportedPixelAmount) { JPEGDEC_TRACE_INTERNAL(("FRAME: Unsupported size\n")); return (JPEGDEC_UNSUPPORTED); } /* Number of components */ pDecData->frame.Nf = JpegDecGetByte(&(pDecData->stream)); if ((pDecData->frame.Nf != 3) && (pDecData->frame.Nf != 1)) { JPEGDEC_TRACE_INTERNAL(("pDecData->frame.Nf != 3 && pDecData->frame.Nf != 1\n")); return (JPEGDEC_UNSUPPORTED); } /* save component specific data */ /* Nf == number of components */ for (i = 0; i < pDecData->frame.Nf; i++) { pDecData->frame.component[i].C = JpegDecGetByte(&(pDecData->stream)); if (i == 0) { /* for the first component */ /* if first component id is something else than 1 (jfif) */ pDecData->scan.index = pDecData->frame.component[i].C; } else { /* if component ids 'jumps' */ if ((pDecData->frame.component[i - 1].C + 1) != pDecData->frame.component[i].C) { JPEGDEC_TRACE_INTERNAL(("component ids 'jumps'\n")); return (JPEGDEC_UNSUPPORTED); } } tmp1 = JpegDecGetByte(&(pDecData->stream)); pDecData->frame.component[i].H = tmp1 >> 4; if (pDecData->frame.component[i].H > Hmax) { Hmax = pDecData->frame.component[i].H; } pDecData->frame.component[i].V = tmp1 & 0xF; if (pDecData->frame.component[i].V > Vmax) { Vmax = pDecData->frame.component[i].V; } pDecData->frame.component[i].Tq = JpegDecGetByte(&(pDecData->stream)); } if (pDecData->frame.Nf == 1) { Hmax = Vmax = 1; pDecData->frame.component[0].H = 1; pDecData->frame.component[0].V = 1; } else if (Hmax == 0 || Vmax == 0) { JPEGDEC_TRACE_INTERNAL(("Hmax == 0 || Vmax == 0 \n")); return (JPEGDEC_UNSUPPORTED); } /* JPEG_YCBCR411 horizontal size has to be multiple of 32 pels */ if (Hmax == 4 && (pDecData->frame.hwX & 0x1F)) { /* round up to next multiple-of-32 */ pDecData->frame.hwX += 16; pDecData->info.X = pDecData->frame.hwX; /* check for minimum and maximum dimensions */ if (pDecData->frame.hwX > pDecData->maxSupportedWidth || (pDecData->frame.hwX * pDecData->frame.hwY) > pDecData->maxSupportedPixelAmount) { JPEGDEC_TRACE_INTERNAL(("FRAME: Unsupported size\n")); return (JPEGDEC_UNSUPPORTED); } } /* set image pointers, calculate pixelPerRow for each component */ width = ((pDecData->frame.hwX + Hmax * 8 - 1) / (Hmax * 8)) * Hmax * 8; height = ((pDecData->frame.hwY + Vmax * 8 - 1) / (Vmax * 8)) * Vmax * 8; /* calculate numMcuInRow and numMcuInFrame */ ASSERT(Hmax != 0); ASSERT(Vmax != 0); pDecData->frame.numMcuInRow = width / (8 * Hmax); pDecData->frame.numMcuInFrame = pDecData->frame.numMcuInRow * (height / (8 * Vmax)); /* reset mcuNumbers */ pDecData->frame.mcuNumber = 0; pDecData->frame.row = pDecData->frame.col = 0; for (i = 0; i < pDecData->frame.Nf; i++) { ASSERT(i <= 2); tmp1 = (width * pDecData->frame.component[i].H + Hmax - 1) / Hmax; tmp2 = (height * pDecData->frame.component[i].V + Vmax - 1) / Vmax; size += tmp1 * tmp2; /* pixels per row */ pDecData->image.pixelsPerRow[i] = tmp1; pDecData->image.columns[i] = tmp2; pDecData->frame.numBlocks[i] = (((pDecData->frame.hwX * pDecData->frame.component[i].H) / Hmax + 7) >> 3) * (((pDecData->frame.hwY * pDecData->frame.component[i].V) / Vmax + 7) >> 3); if (i == 0) { pDecData->image.sizeLuma = size; } } pDecData->image.size = size; pDecData->image.sizeChroma = size - pDecData->image.sizeLuma; /* set YUV mode & calculate rlc tmp size */ retCode = JpegDecMode(pDecData); if (retCode != JPEGDEC_OK) { return (retCode); } return (JPEGDEC_OK); } /*------------------------------------------------------------------------------ Function name: JpegDecDecodeQuantTables Functional description: Decodes quantisation tables from the stream Inputs: JpegDecContainer *pDecData Pointer to JpegDecContainer structure Outputs: OK (0) NOK (-1) ------------------------------------------------------------------------------*/ JpegDecRet JpegDecDecodeQuantTables(JpegDecContainer * pDecData) { RK_U32 t, tmp, i; StreamStorage *pStream = &(pDecData->stream); pDecData->quant.Lq = JpegDecGet2Bytes(pStream); /* check if there is enough data for tables */ if (((pStream->readBits / 8) + pDecData->quant.Lq) > pStream->streamLength) return (JPEGDEC_STRM_ERROR); t = 4; while (t < pDecData->quant.Lq) { /* Tq value selects what table the components use */ /* read tables and write to decData->quant */ tmp = JpegDecGetByte(pStream); t++; /* supporting only 8 bits / sample */ if ((tmp >> 4) != 0) { return (JPEGDEC_UNSUPPORTED); } tmp &= 0xF; /* set the quantisation table pointer */ if (tmp == 0) { JPEGDEC_TRACE_INTERNAL(("qtable0\n")); pDecData->quant.table = pDecData->quant.table0; } else if (tmp == 1) { JPEGDEC_TRACE_INTERNAL(("qtable1\n")); pDecData->quant.table = pDecData->quant.table1; } else if (tmp == 2) { JPEGDEC_TRACE_INTERNAL(("qtable2\n")); pDecData->quant.table = pDecData->quant.table2; } else if (tmp == 3) { JPEGDEC_TRACE_INTERNAL(("qtable3\n")); pDecData->quant.table = pDecData->quant.table3; } else { return (JPEGDEC_UNSUPPORTED); } for (i = 0; i < 64; i++) { pDecData->quant.table[i] = JpegDecGetByte(pStream); t++; } } return (JPEGDEC_OK); } /*------------------------------------------------------------------------------ Function name: JpegDecDecodeHuffmanTables Functional description: Decodes huffman tables from the stream Inputs: DecData *JpegDecContainer Pointer to JpegDecContainer structure Outputs: OK (0) NOK (-1) ------------------------------------------------------------------------------*/ JpegDecRet JpegDecDecodeHuffmanTables(JpegDecContainer * pDecData) { RK_U32 i, len, Tc, Th, tmp; RK_S32 j; StreamStorage *pStream = &(pDecData->stream); pDecData->vlc.Lh = JpegDecGet2Bytes(pStream); /* check if there is enough data for tables */ if (((pStream->readBits / 8) + pDecData->vlc.Lh) > pStream->streamLength) return (JPEGDEC_STRM_ERROR); /* four bytes already read in */ len = 4; while (len < pDecData->vlc.Lh) { tmp = JpegDecGetByte(pStream); len++; Tc = tmp >> 4; /* Table class */ if (Tc != 0 && Tc != 1) { return (JPEGDEC_UNSUPPORTED); } Th = tmp & 0xF; /* Huffman table identifier */ /* only two tables in baseline allowed */ if ((pDecData->frame.codingType == SOF0) && (Th > 1)) { return (JPEGDEC_UNSUPPORTED); } /* four tables in progressive allowed */ if ((pDecData->frame.codingType == SOF2) && (Th > 3)) { return (JPEGDEC_UNSUPPORTED); } /* set the table pointer */ if (Tc) { /* Ac table */ switch (Th) { case 0: JPEGDEC_TRACE_INTERNAL(("ac0\n")); pDecData->vlc.table = &(pDecData->vlc.acTable0); break; case 1: JPEGDEC_TRACE_INTERNAL(("ac1\n")); pDecData->vlc.table = &(pDecData->vlc.acTable1); break; case 2: JPEGDEC_TRACE_INTERNAL(("ac2\n")); pDecData->vlc.table = &(pDecData->vlc.acTable2); break; case 3: JPEGDEC_TRACE_INTERNAL(("ac3\n")); pDecData->vlc.table = &(pDecData->vlc.acTable3); break; default: return (JPEGDEC_UNSUPPORTED); } } else { /* Dc table */ switch (Th) { case 0: JPEGDEC_TRACE_INTERNAL(("dc0\n")); pDecData->vlc.table = &(pDecData->vlc.dcTable0); break; case 1: JPEGDEC_TRACE_INTERNAL(("dc1\n")); pDecData->vlc.table = &(pDecData->vlc.dcTable1); break; case 2: JPEGDEC_TRACE_INTERNAL(("dc2\n")); pDecData->vlc.table = &(pDecData->vlc.dcTable2); break; case 3: JPEGDEC_TRACE_INTERNAL(("dc3\n")); pDecData->vlc.table = &(pDecData->vlc.dcTable3); break; default: return (JPEGDEC_UNSUPPORTED); } } tmp = 0; /* read in the values of list BITS */ for (i = 0; i < 16; i++) { tmp += pDecData->vlc.table->bits[i] = JpegDecGetByte(pStream); len++; } /* allocate memory for HUFFVALs */ if (pDecData->vlc.table->vals != NULL) { /* free previously reserved table */ DWLfree(pDecData->vlc.table->vals); } pDecData->vlc.table->vals = (RK_U32 *) DWLmalloc(sizeof(RK_U32) * tmp); /* set the table length */ pDecData->vlc.table->tableLength = tmp; /* read in the HUFFVALs */ for (i = 0; i < tmp; i++) { pDecData->vlc.table->vals[i] = JpegDecGetByte(pStream); len++; } /* first and last lengths */ for (i = 0; i < 16; i++) { if (pDecData->vlc.table->bits[i] != 0) { pDecData->vlc.table->start = i; break; } } for (j = 15; j >= 0; j--) { if (pDecData->vlc.table->bits[j] != 0) { pDecData->vlc.table->last = ((RK_U32) j + 1); break; } } } return (JPEGDEC_OK); } /*------------------------------------------------------------------------------ Function name: JpegDefaultHuffmanTables Functional description: if jpeg file not find huffman table, use it! Inputs: DecData *JpegDecContainer Pointer to JpegDecContainer structure Outputs: OK (0) NOK (-1) ------------------------------------------------------------------------------*/ JpegDecRet JpegDefaultHuffmanTables(JpegDecContainer * pDecData) { /* Set up the standard Huffman tables (cf. JPEG standard section K.3) */ /* IMPORTANT: these are only valid for 8-bit data precision! */ uint8_t ff_mjpeg_bits_dc_luminance[17] = { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; uint8_t ff_mjpeg_val_dc[12] = //luminance and chrominance all use it { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; uint8_t ff_mjpeg_bits_dc_chrominance[17] = { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; uint8_t ff_mjpeg_bits_ac_luminance[17] = { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }; uint8_t ff_mjpeg_val_ac_luminance[] = { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa }; uint8_t ff_mjpeg_bits_ac_chrominance[17] = { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }; uint8_t ff_mjpeg_val_ac_chrominance[] = { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa }; RK_U32 i, len, tmp, k; RK_S32 j; uint8_t *bitstable[4] = {ff_mjpeg_bits_dc_luminance, ff_mjpeg_bits_ac_luminance, ff_mjpeg_bits_dc_chrominance, ff_mjpeg_bits_ac_chrominance}; uint8_t *valtable[4] = {ff_mjpeg_val_dc, ff_mjpeg_val_ac_luminance, ff_mjpeg_val_dc, ff_mjpeg_val_ac_chrominance}; uint8_t *bitstmp; uint8_t *valtmp; for (k = 0; k < 4; k++) { bitstmp = bitstable[k]; valtmp = valtable[k]; if (k == 0) pDecData->vlc.table = &(pDecData->vlc.dcTable0); else if (k == 1) pDecData->vlc.table = &(pDecData->vlc.acTable0); else if (k == 2) pDecData->vlc.table = &(pDecData->vlc.dcTable1); else pDecData->vlc.table = &(pDecData->vlc.acTable1); tmp = 0; /* read in the values of list BITS */ for (i = 0; i < 16; i++) { tmp += pDecData->vlc.table->bits[i] = bitstmp[i + 1]; len++; } /* allocate memory for HUFFVALs */ if (pDecData->vlc.table->vals != NULL) { /* free previously reserved table */ DWLfree(pDecData->vlc.table->vals); } pDecData->vlc.table->vals = (RK_U32 *) DWLmalloc(sizeof(RK_U32) * tmp); /* set the table length */ pDecData->vlc.table->tableLength = tmp; /* read in the HUFFVALs */ for (i = 0; i < tmp; i++) { pDecData->vlc.table->vals[i] = valtmp[i]; len++; } /* first and last lengths */ for (i = 0; i < 16; i++) { if (pDecData->vlc.table->bits[i] != 0) { pDecData->vlc.table->start = i; break; } } for (j = 15; j >= 0; j--) { if (pDecData->vlc.table->bits[j] != 0) { pDecData->vlc.table->last = ((RK_U32) j + 1); break; } } } return (JPEGDEC_OK); } /*------------------------------------------------------------------------------ Function name: JpegDecMode Functional description: check YCBCR mode Inputs: JpegDecContainer *pDecData Pointer to JpegDecContainer structure Outputs: OK/NOK ------------------------------------------------------------------------------*/ JpegDecRet JpegDecMode(JpegDecContainer * pDecData) { /* check input format */ if (pDecData->frame.Nf == 3) { /* JPEG_YCBCR420 */ if (pDecData->frame.component[0].H == 2 && pDecData->frame.component[0].V == 2 && pDecData->frame.component[1].H == 1 && pDecData->frame.component[1].V == 1 && pDecData->frame.component[2].H == 1 && pDecData->frame.component[2].V == 1) { pDecData->info.yCbCrMode = JPEGDEC_YUV420; pDecData->info.X = pDecData->frame.hwX; pDecData->info.Y = pDecData->frame.hwY; /* calculate new output size if slice mode used */ if (pDecData->info.sliceMbSetValue) { /* Y */ pDecData->image.sizeLuma = (pDecData->info.X * (pDecData->info.sliceMbSetValue * 16)); /* CbCr */ pDecData->image.sizeChroma = pDecData->image.sizeLuma / 2; } } /* JPEG_YCBCR422 */ else if (pDecData->frame.component[0].H == 2 && pDecData->frame.component[0].V == 1 && pDecData->frame.component[1].H == 1 && pDecData->frame.component[1].V == 1 && pDecData->frame.component[2].H == 1 && pDecData->frame.component[2].V == 1) { pDecData->info.yCbCrMode = JPEGDEC_YUV422; pDecData->info.X = (pDecData->frame.hwX); pDecData->info.Y = (pDecData->frame.hwY); /* check if fill needed */ if ((pDecData->frame.Y & 0xF) && (pDecData->frame.Y & 0xF) <= 8) pDecData->info.fillBottom = 1; /* calculate new output size if slice mode used */ if (pDecData->info.sliceMbSetValue) { /* Y */ pDecData->image.sizeLuma = (pDecData->info.X * (pDecData->info.sliceMbSetValue * 16)); /* CbCr */ pDecData->image.sizeChroma = pDecData->image.sizeLuma; } } /* JPEG_YCBCR440 */ else if (pDecData->frame.component[0].H == 1 && pDecData->frame.component[0].V == 2 && pDecData->frame.component[1].H == 1 && pDecData->frame.component[1].V == 1 && pDecData->frame.component[2].H == 1 && pDecData->frame.component[2].V == 1) { pDecData->info.yCbCrMode = JPEGDEC_YUV440; pDecData->info.X = (pDecData->frame.hwX); pDecData->info.Y = (pDecData->frame.hwY); /* check if fill needed */ if ((pDecData->frame.X & 0xF) && (pDecData->frame.X & 0xF) <= 8) pDecData->info.fillRight = 1; /* calculate new output size if slice mode used */ if (pDecData->info.sliceMbSetValue) { /* Y */ pDecData->image.sizeLuma = (pDecData->info.X * (pDecData->info.sliceMbSetValue * 16)); /* CbCr */ pDecData->image.sizeChroma = pDecData->image.sizeLuma; } } /* JPEG_YCBCR444 : NOT SUPPORTED */ else if (pDecData->frame.component[0].H == 1 && pDecData->frame.component[0].V == 1 && pDecData->frame.component[1].H == 1 && pDecData->frame.component[1].V == 1 && pDecData->frame.component[2].H == 1 && pDecData->frame.component[2].V == 1) { pDecData->info.yCbCrMode = JPEGDEC_YUV444; pDecData->info.X = pDecData->frame.hwX; pDecData->info.Y = pDecData->frame.hwY; /* check if fill needed */ if ((pDecData->frame.X & 0xF) && (pDecData->frame.X & 0xF) <= 8) pDecData->info.fillRight = 1; if ((pDecData->frame.Y & 0xF) && (pDecData->frame.Y & 0xF) <= 8) pDecData->info.fillBottom = 1; /* calculate new output size if slice mode used */ if (pDecData->info.sliceMbSetValue) { /* Y */ pDecData->image.sizeLuma = (pDecData->info.X * (pDecData->info.sliceMbSetValue * 16)); /* CbCr */ pDecData->image.sizeChroma = pDecData->image.sizeLuma * 2; } } /* JPEG_YCBCR411 */ else if (pDecData->frame.component[0].H == 4 && pDecData->frame.component[0].V == 1 && pDecData->frame.component[1].H == 1 && pDecData->frame.component[1].V == 1 && pDecData->frame.component[2].H == 1 && pDecData->frame.component[2].V == 1) { pDecData->info.yCbCrMode = JPEGDEC_YUV411; pDecData->info.X = (pDecData->frame.hwX); pDecData->info.Y = (pDecData->frame.hwY); /* check if fill needed */ if ((pDecData->frame.Y & 0xF) && (pDecData->frame.Y & 0xF) <= 8) pDecData->info.fillBottom = 1; /* calculate new output size if slice mode used */ if (pDecData->info.sliceMbSetValue) { /* Y */ pDecData->image.sizeLuma = (pDecData->info.X * (pDecData->info.sliceMbSetValue * 16)); /* CbCr */ pDecData->image.sizeChroma = pDecData->image.sizeLuma / 2; } } else { return (JPEGDEC_UNSUPPORTED); } } else if (pDecData->frame.Nf == 1) { /* 4:0:0 */ if ((pDecData->frame.component[0].V == 1) || (pDecData->frame.component[0].H == 1)) { pDecData->info.yCbCrMode = JPEGDEC_YUV400; pDecData->info.X = (pDecData->frame.hwX); pDecData->info.Y = (pDecData->frame.hwY); /* check if fill needed */ if ((pDecData->frame.X & 0xF) && (pDecData->frame.X & 0xF) <= 8) pDecData->info.fillRight = 1; if ((pDecData->frame.Y & 0xF) && (pDecData->frame.Y & 0xF) <= 8) pDecData->info.fillBottom = 1; /* calculate new output size if slice mode used */ if (pDecData->info.sliceMbSetValue) { /* Y */ pDecData->image.sizeLuma = ((((pDecData->info.X + 15) / 16) * 16) * (pDecData->info.sliceMbSetValue * 16)); /* CbCr */ pDecData->image.sizeChroma = 0; } } else { return (JPEGDEC_UNSUPPORTED); } } else { return (JPEGDEC_UNSUPPORTED); } #ifdef JPEGDEC_ERROR_RESILIENCE if (pDecData->info.fillBottom) { pDecData->info.Y -= 16; pDecData->frame.hwY -= 16; } #endif /* JPEGDEC_ERROR_RESILIENCE */ /* save the original sampling format for progressive use */ pDecData->info.yCbCrModeOrig = pDecData->info.yCbCrMode; return (JPEGDEC_OK); }