diff options
Diffstat (limited to 'media/libstagefright/codecs/on2/h264dec/source')
79 files changed, 31385 insertions, 0 deletions
diff --git a/media/libstagefright/codecs/on2/h264dec/source/DecTestBench.c b/media/libstagefright/codecs/on2/h264dec/source/DecTestBench.c new file mode 100755 index 0000000..dcf2ef6 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/DecTestBench.c @@ -0,0 +1,761 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "H264SwDecApi.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/*------------------------------------------------------------------------------ + Module defines +------------------------------------------------------------------------------*/ + +/* CHECK_MEMORY_USAGE prints and sums the memory allocated in calls to + * H264SwDecMalloc() */ +/* #define CHECK_MEMORY_USAGE */ + +/* _NO_OUT disables output file writing */ +/* #define _NO_OUT */ + +/* Debug prints */ +#define DEBUG(argv) printf argv + +/* CVS tag name for identification */ +const char tagName[256] = "$Name: FIRST_ANDROID_COPYRIGHT $"; + +void WriteOutput(char *filename, u8 *data, u32 picSize); +u32 NextPacket(u8 **pStrm); +u32 CropPicture(u8 *pOutImage, u8 *pInImage, + u32 picWidth, u32 picHeight, CropParams *pCropParams); + +/* Global variables for stream handling */ +u8 *streamStop = NULL; +u32 packetize = 0; +u32 nalUnitStream = 0; +FILE *foutput = NULL; + +#ifdef SOC_DESIGNER + +// Initialisation function defined in InitCache.s +extern void cache_init(void); + +/*------------------------------------------------------------------------------ + + Function name: $Sub$$main + + Purpose: + This function is called at the end of the C library initialisation and + before main. Its purpose is to do any further initialisation before the + application start. + +------------------------------------------------------------------------------*/ +int $Sub$$main(char argc, char * argv[]) +{ + cache_init(); // does some extra setup work setting up caches + return $Super$$main(argc, argv); // calls the original function +} +#endif + +/*------------------------------------------------------------------------------ + + Function name: main + + Purpose: + main function of decoder testbench. Provides command line interface + with file I/O for H.264 decoder. Prints out the usage information + when executed without arguments. + +------------------------------------------------------------------------------*/ + +int main(int argc, char **argv) +{ + + u32 i, tmp; + u32 maxNumPics = 0; + u8 *byteStrmStart; + u8 *imageData; + u8 *tmpImage = NULL; + u32 strmLen; + u32 picSize; + H264SwDecInst decInst; + H264SwDecRet ret; + H264SwDecInput decInput; + H264SwDecOutput decOutput; + H264SwDecPicture decPicture; + H264SwDecInfo decInfo; + H264SwDecApiVersion decVer; + u32 picDecodeNumber; + u32 picDisplayNumber; + u32 numErrors = 0; + u32 cropDisplay = 0; + u32 disableOutputReordering = 0; + + FILE *finput; + + char outFileName[256] = ""; + + /* Print API version number */ + decVer = H264SwDecGetAPIVersion(); + DEBUG(("H.264 Decoder API v%d.%d\n", decVer.major, decVer.minor)); + + /* Print tag name if '-T' argument present */ + if ( argc > 1 && strcmp(argv[1], "-T") == 0 ) + { + DEBUG(("%s\n", tagName)); + return 0; + } + + /* Check that enough command line arguments given, if not -> print usage + * information out */ + if (argc < 2) + { + DEBUG(( + "Usage: %s [-Nn] [-Ooutfile] [-P] [-U] [-C] [-R] [-T] file.h264\n", + argv[0])); + DEBUG(("\t-Nn forces decoding to stop after n pictures\n")); +#if defined(_NO_OUT) + DEBUG(("\t-Ooutfile output writing disabled at compile time\n")); +#else + DEBUG(("\t-Ooutfile write output to \"outfile\" (default out_wxxxhyyy.yuv)\n")); + DEBUG(("\t-Onone does not write output\n")); +#endif + DEBUG(("\t-P packet-by-packet mode\n")); + DEBUG(("\t-U NAL unit stream mode\n")); + DEBUG(("\t-C display cropped image (default decoded image)\n")); + DEBUG(("\t-R disable DPB output reordering\n")); + DEBUG(("\t-T to print tag name and exit\n")); + return 0; + } + + /* read command line arguments */ + for (i = 1; i < (u32)(argc-1); i++) + { + if ( strncmp(argv[i], "-N", 2) == 0 ) + { + maxNumPics = (u32)atoi(argv[i]+2); + } + else if ( strncmp(argv[i], "-O", 2) == 0 ) + { + strcpy(outFileName, argv[i]+2); + } + else if ( strcmp(argv[i], "-P") == 0 ) + { + packetize = 1; + } + else if ( strcmp(argv[i], "-U") == 0 ) + { + nalUnitStream = 1; + } + else if ( strcmp(argv[i], "-C") == 0 ) + { + cropDisplay = 1; + } + else if ( strcmp(argv[i], "-R") == 0 ) + { + disableOutputReordering = 1; + } + } + + /* open input file for reading, file name given by user. If file open + * fails -> exit */ + finput = fopen(argv[argc-1],"rb"); + if (finput == NULL) + { + DEBUG(("UNABLE TO OPEN INPUT FILE\n")); + return -1; + } + + /* check size of the input file -> length of the stream in bytes */ + fseek(finput,0L,SEEK_END); + strmLen = (u32)ftell(finput); + rewind(finput); + + /* allocate memory for stream buffer. if unsuccessful -> exit */ + byteStrmStart = (u8 *)malloc(sizeof(u8)*strmLen); + if (byteStrmStart == NULL) + { + DEBUG(("UNABLE TO ALLOCATE MEMORY\n")); + return -1; + } + + /* read input stream from file to buffer and close input file */ + fread(byteStrmStart, sizeof(u8), strmLen, finput); + fclose(finput); + + /* initialize decoder. If unsuccessful -> exit */ + ret = H264SwDecInit(&decInst, disableOutputReordering); + if (ret != H264SWDEC_OK) + { + DEBUG(("DECODER INITIALIZATION FAILED\n")); + free(byteStrmStart); + return -1; + } + + /* initialize H264SwDecDecode() input structure */ + streamStop = byteStrmStart + strmLen; + decInput.pStream = byteStrmStart; + decInput.dataLen = strmLen; + decInput.intraConcealmentMethod = 0; + + /* get pointer to next packet and the size of packet + * (for packetize or nalUnitStream modes) */ + if ( (tmp = NextPacket(&decInput.pStream)) != 0 ) + decInput.dataLen = tmp; + + picDecodeNumber = picDisplayNumber = 1; + /* main decoding loop */ + do + { + /* Picture ID is the picture number in decoding order */ + decInput.picId = picDecodeNumber; + + /* call API function to perform decoding */ + ret = H264SwDecDecode(decInst, &decInput, &decOutput); + + switch(ret) + { + + case H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY: + /* Stream headers were successfully decoded + * -> stream information is available for query now */ + + ret = H264SwDecGetInfo(decInst, &decInfo); + if (ret != H264SWDEC_OK) + return -1; + + DEBUG(("Profile %d\n", decInfo.profile)); + + DEBUG(("Width %d Height %d\n", + decInfo.picWidth, decInfo.picHeight)); + + if (cropDisplay && decInfo.croppingFlag) + { + DEBUG(("Cropping params: (%d, %d) %dx%d\n", + decInfo.cropParams.cropLeftOffset, + decInfo.cropParams.cropTopOffset, + decInfo.cropParams.cropOutWidth, + decInfo.cropParams.cropOutHeight)); + + /* Cropped frame size in planar YUV 4:2:0 */ + picSize = decInfo.cropParams.cropOutWidth * + decInfo.cropParams.cropOutHeight; + picSize = (3 * picSize)/2; + tmpImage = malloc(picSize); + if (tmpImage == NULL) + return -1; + } + else + { + /* Decoder output frame size in planar YUV 4:2:0 */ + picSize = decInfo.picWidth * decInfo.picHeight; + picSize = (3 * picSize)/2; + } + + DEBUG(("videoRange %d, matrixCoefficients %d\n", + decInfo.videoRange, decInfo.matrixCoefficients)); + + /* update H264SwDecDecode() input structure, number of bytes + * "consumed" is computed as difference between the new stream + * pointer and old stream pointer */ + decInput.dataLen -= + (u32)(decOutput.pStrmCurrPos - decInput.pStream); + decInput.pStream = decOutput.pStrmCurrPos; + + /* If -O option not used, generate default file name */ + if (outFileName[0] == 0) + sprintf(outFileName, "out_w%dh%d.yuv", + decInfo.picWidth, decInfo.picHeight); + break; + + case H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY: + /* Picture is ready and more data remains in input buffer + * -> update H264SwDecDecode() input structure, number of bytes + * "consumed" is computed as difference between the new stream + * pointer and old stream pointer */ + decInput.dataLen -= + (u32)(decOutput.pStrmCurrPos - decInput.pStream); + decInput.pStream = decOutput.pStrmCurrPos; + /* fall through */ + + case H264SWDEC_PIC_RDY: + + /*lint -esym(644,tmpImage,picSize) variable initialized at + * H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY case */ + + if (ret == H264SWDEC_PIC_RDY) + decInput.dataLen = NextPacket(&decInput.pStream); + + /* If enough pictures decoded -> force decoding to end + * by setting that no more stream is available */ + if (maxNumPics && picDecodeNumber == maxNumPics) + decInput.dataLen = 0; + + /* Increment decoding number for every decoded picture */ + picDecodeNumber++; + + /* use function H264SwDecNextPicture() to obtain next picture + * in display order. Function is called until no more images + * are ready for display */ + while ( H264SwDecNextPicture(decInst, &decPicture, 0) == + H264SWDEC_PIC_RDY ) + { + DEBUG(("PIC %d, type %s", picDisplayNumber, + decPicture.isIdrPicture ? "IDR" : "NON-IDR")); + if (picDisplayNumber != decPicture.picId) + DEBUG((", decoded pic %d", decPicture.picId)); + if (decPicture.nbrOfErrMBs) + { + DEBUG((", concealed %d\n", decPicture.nbrOfErrMBs)); + } + else + DEBUG(("\n")); + fflush(stdout); + + numErrors += decPicture.nbrOfErrMBs; + + /* Increment display number for every displayed picture */ + picDisplayNumber++; + + /*lint -esym(644,decInfo) always initialized if pictures + * available for display */ + + /* Write output picture to file */ + imageData = (u8*)decPicture.pOutputPicture; + if (cropDisplay && decInfo.croppingFlag) + { + tmp = CropPicture(tmpImage, imageData, + decInfo.picWidth, decInfo.picHeight, + &decInfo.cropParams); + if (tmp) + return -1; + WriteOutput(outFileName, tmpImage, picSize); + } + else + { + WriteOutput(outFileName, imageData, picSize); + } + } + + break; + + case H264SWDEC_STRM_PROCESSED: + case H264SWDEC_STRM_ERR: + /* Input stream was decoded but no picture is ready + * -> Get more data */ + decInput.dataLen = NextPacket(&decInput.pStream); + break; + + default: + DEBUG(("FATAL ERROR\n")); + return -1; + + } + /* keep decoding until all data from input stream buffer consumed */ + } while (decInput.dataLen > 0); + + /* if output in display order is preferred, the decoder shall be forced + * to output pictures remaining in decoded picture buffer. Use function + * H264SwDecNextPicture() to obtain next picture in display order. Function + * is called until no more images are ready for display. Second parameter + * for the function is set to '1' to indicate that this is end of the + * stream and all pictures shall be output */ + while (H264SwDecNextPicture(decInst, &decPicture, 1) == H264SWDEC_PIC_RDY) + { + DEBUG(("PIC %d, type %s", picDisplayNumber, + decPicture.isIdrPicture ? "IDR" : "NON-IDR")); + if (picDisplayNumber != decPicture.picId) + DEBUG((", decoded pic %d", decPicture.picId)); + if (decPicture.nbrOfErrMBs) + { + DEBUG((", concealed %d\n", decPicture.nbrOfErrMBs)); + } + else + DEBUG(("\n")); + fflush(stdout); + + numErrors += decPicture.nbrOfErrMBs; + + /* Increment display number for every displayed picture */ + picDisplayNumber++; + + /* Write output picture to file */ + imageData = (u8*)decPicture.pOutputPicture; + if (cropDisplay && decInfo.croppingFlag) + { + tmp = CropPicture(tmpImage, imageData, + decInfo.picWidth, decInfo.picHeight, + &decInfo.cropParams); + if (tmp) + return -1; + WriteOutput(outFileName, tmpImage, picSize); + } + else + { + WriteOutput(outFileName, imageData, picSize); + } + } + + /* release decoder instance */ + H264SwDecRelease(decInst); + + if (foutput) + fclose(foutput); + + /* free allocated buffers */ + free(byteStrmStart); + free(tmpImage); + + DEBUG(("Output file: %s\n", outFileName)); + + DEBUG(("DECODING DONE\n")); + if (numErrors || picDecodeNumber == 1) + { + DEBUG(("ERRORS FOUND\n")); + return 1; + } + + return 0; +} + +/*------------------------------------------------------------------------------ + + Function name: WriteOutput + + Purpose: + Write picture pointed by data to file. Size of the + picture in pixels is indicated by picSize. + +------------------------------------------------------------------------------*/ +void WriteOutput(char *filename, u8 *data, u32 picSize) +{ + + /* foutput is global file pointer */ + if (foutput == NULL) + { + /* open output file for writing, can be disabled with define. + * If file open fails -> exit */ + if (strcmp(filename, "none") != 0) + { +#if !defined(_NO_OUT) + foutput = fopen(filename, "wb"); + if (foutput == NULL) + { + DEBUG(("UNABLE TO OPEN OUTPUT FILE\n")); + exit(100); + } +#endif + } + } + + if (foutput && data) + fwrite(data, 1, picSize, foutput); +} + +/*------------------------------------------------------------------------------ + + Function name: NextPacket + + Purpose: + Get the pointer to start of next packet in input stream. Uses + global variables 'packetize' and 'nalUnitStream' to determine the + decoder input stream mode and 'streamStop' to determine the end + of stream. There are three possible stream modes: + default - the whole stream at once + packetize - a single NAL-unit with start code prefix + nalUnitStream - a single NAL-unit without start code prefix + + pStrm stores pointer to the start of previous decoder input and is + replaced with pointer to the start of the next decoder input. + + Returns the packet size in bytes + +------------------------------------------------------------------------------*/ +u32 NextPacket(u8 **pStrm) +{ + + u32 index; + u32 maxIndex; + u32 zeroCount; + u8 *stream; + u8 byte; + static u32 prevIndex=0; + + /* For default stream mode all the stream is in first packet */ + if (!packetize && !nalUnitStream) + return 0; + + index = 0; + stream = *pStrm + prevIndex; + maxIndex = (u32)(streamStop - stream); + + if (maxIndex == 0) + return(0); + + /* leading zeros of first NAL unit */ + do + { + byte = stream[index++]; + } while (byte != 1 && index < maxIndex); + + /* invalid start code prefix */ + if (index == maxIndex || index < 3) + { + DEBUG(("INVALID BYTE STREAM\n")); + exit(100); + } + + /* nalUnitStream is without start code prefix */ + if (nalUnitStream) + { + stream += index; + maxIndex -= index; + index = 0; + } + + zeroCount = 0; + + /* Search stream for next start code prefix */ + /*lint -e(716) while(1) used consciously */ + while (1) + { + byte = stream[index++]; + if (!byte) + zeroCount++; + + if ( (byte == 0x01) && (zeroCount >= 2) ) + { + /* Start code prefix has two zeros + * Third zero is assumed to be leading zero of next packet + * Fourth and more zeros are assumed to be trailing zeros of this + * packet */ + if (zeroCount > 3) + { + index -= 4; + zeroCount -= 3; + } + else + { + index -= zeroCount+1; + zeroCount = 0; + } + break; + } + else if (byte) + zeroCount = 0; + + if (index == maxIndex) + { + break; + } + + } + + /* Store pointer to the beginning of the packet */ + *pStrm = stream; + prevIndex = index; + + /* nalUnitStream is without trailing zeros */ + if (nalUnitStream) + index -= zeroCount; + + return(index); + +} + +/*------------------------------------------------------------------------------ + + Function name: CropPicture + + Purpose: + Perform cropping for picture. Input picture pInImage with dimensions + picWidth x picHeight is cropped with pCropParams and the resulting + picture is stored in pOutImage. + +------------------------------------------------------------------------------*/ +u32 CropPicture(u8 *pOutImage, u8 *pInImage, + u32 picWidth, u32 picHeight, CropParams *pCropParams) +{ + + u32 i, j; + u32 outWidth, outHeight; + u8 *pOut, *pIn; + + if (pOutImage == NULL || pInImage == NULL || pCropParams == NULL || + !picWidth || !picHeight) + { + /* just to prevent lint warning, returning non-zero will result in + * return without freeing the memory */ + free(pOutImage); + return(1); + } + + if ( ((pCropParams->cropLeftOffset + pCropParams->cropOutWidth) > + picWidth ) || + ((pCropParams->cropTopOffset + pCropParams->cropOutHeight) > + picHeight ) ) + { + /* just to prevent lint warning, returning non-zero will result in + * return without freeing the memory */ + free(pOutImage); + return(1); + } + + outWidth = pCropParams->cropOutWidth; + outHeight = pCropParams->cropOutHeight; + + /* Calculate starting pointer for luma */ + pIn = pInImage + pCropParams->cropTopOffset*picWidth + + pCropParams->cropLeftOffset; + pOut = pOutImage; + + /* Copy luma pixel values */ + for (i = outHeight; i; i--) + { + for (j = outWidth; j; j--) + { + *pOut++ = *pIn++; + } + pIn += picWidth - outWidth; + } + + outWidth >>= 1; + outHeight >>= 1; + + /* Calculate starting pointer for cb */ + pIn = pInImage + picWidth*picHeight + + pCropParams->cropTopOffset*picWidth/4 + pCropParams->cropLeftOffset/2; + + /* Copy cb pixel values */ + for (i = outHeight; i; i--) + { + for (j = outWidth; j; j--) + { + *pOut++ = *pIn++; + } + pIn += picWidth/2 - outWidth; + } + + /* Calculate starting pointer for cr */ + pIn = pInImage + 5*picWidth*picHeight/4 + + pCropParams->cropTopOffset*picWidth/4 + pCropParams->cropLeftOffset/2; + + /* Copy cr pixel values */ + for (i = outHeight; i; i--) + { + for (j = outWidth; j; j--) + { + *pOut++ = *pIn++; + } + pIn += picWidth/2 - outWidth; + } + + return (0); +} + +/*------------------------------------------------------------------------------ + + Function name: H264SwDecTrace + + Purpose: + Example implementation of H264SwDecTrace function. Prototype of this + function is given in H264SwDecApi.h. This implementation appends + trace messages to file named 'dec_api.trc'. + +------------------------------------------------------------------------------*/ +void H264SwDecTrace(char *string) +{ + FILE *fp; + + fp = fopen("dec_api.trc", "at"); + + if (!fp) + return; + + fwrite(string, 1, strlen(string), fp); + fwrite("\n", 1,1, fp); + + fclose(fp); +} + +/*------------------------------------------------------------------------------ + + Function name: H264SwDecMalloc + + Purpose: + Example implementation of H264SwDecMalloc function. Prototype of this + function is given in H264SwDecApi.h. This implementation uses + library function malloc for allocation of memory. + +------------------------------------------------------------------------------*/ +void* H264SwDecMalloc(u32 size) +{ + +#if defined(CHECK_MEMORY_USAGE) + /* Note that if the decoder has to free and reallocate some of the buffers + * the total value will be invalid */ + static u32 numBytes = 0; + numBytes += size; + DEBUG(("Allocated %d bytes, total %d\n", size, numBytes)); +#endif + + return malloc(size); +} + +/*------------------------------------------------------------------------------ + + Function name: H264SwDecFree + + Purpose: + Example implementation of H264SwDecFree function. Prototype of this + function is given in H264SwDecApi.h. This implementation uses + library function free for freeing of memory. + +------------------------------------------------------------------------------*/ +void H264SwDecFree(void *ptr) +{ + free(ptr); +} + +/*------------------------------------------------------------------------------ + + Function name: H264SwDecMemcpy + + Purpose: + Example implementation of H264SwDecMemcpy function. Prototype of this + function is given in H264SwDecApi.h. This implementation uses + library function memcpy to copy src to dest. + +------------------------------------------------------------------------------*/ +void H264SwDecMemcpy(void *dest, void *src, u32 count) +{ + memcpy(dest, src, count); +} + +/*------------------------------------------------------------------------------ + + Function name: H264SwDecMemset + + Purpose: + Example implementation of H264SwDecMemset function. Prototype of this + function is given in H264SwDecApi.h. This implementation uses + library function memset to set content of memory area pointed by ptr. + +------------------------------------------------------------------------------*/ +void H264SwDecMemset(void *ptr, i32 value, u32 count) +{ + memset(ptr, value, count); +} + diff --git a/media/libstagefright/codecs/on2/h264dec/source/EvaluationTestBench.c b/media/libstagefright/codecs/on2/h264dec/source/EvaluationTestBench.c new file mode 100755 index 0000000..aadc75f --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/EvaluationTestBench.c @@ -0,0 +1,350 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "H264SwDecApi.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +void WriteOutput(FILE *fid, u8 *data, u32 picSize); + +/*------------------------------------------------------------------------------ + + Function name: main + + Purpose: + main function. Assuming that executable is named 'decoder' the usage + is as follows + + decoder inputFileName + + , where inputFileName shall be name of file containing h264 stream + data. + +------------------------------------------------------------------------------*/ +int main(int argc, char **argv) +{ + + u8 *byteStrmStart; + u8 *byteStrm; + u32 strmLen; + u32 picSize; + H264SwDecInst decInst; + H264SwDecRet ret; + H264SwDecInput decInput; + H264SwDecOutput decOutput; + H264SwDecPicture decPicture; + H264SwDecInfo decInfo; + u32 picNumber; + + FILE *finput; + FILE *foutput; + + /* Check that enough command line arguments given, if not -> print usage + * information out */ + if (argc < 2) + { + printf( "Usage: %s file.h264\n", argv[0]); + return -1; + } + + /* open output file for writing, output file named out.yuv. If file open + * fails -> exit */ + foutput = fopen("out.yuv", "wb"); + if (foutput == NULL) + { + printf("UNABLE TO OPEN OUTPUT FILE\n"); + return -1; + } + + /* open input file for reading, file name given by user. If file open + * fails -> exit */ + finput = fopen(argv[argc-1], "rb"); + if (finput == NULL) + { + printf("UNABLE TO OPEN INPUT FILE\n"); + return -1; + } + + /* check size of the input file -> length of the stream in bytes */ + fseek(finput, 0L, SEEK_END); + strmLen = (u32)ftell(finput); + rewind(finput); + + /* allocate memory for stream buffer, exit if unsuccessful */ + byteStrm = byteStrmStart = (u8 *)H264SwDecMalloc(sizeof(u8)*strmLen); + if (byteStrm == NULL) + { + printf("UNABLE TO ALLOCATE MEMORY\n"); + return -1; + } + + /* read input stream from file to buffer and close input file */ + fread(byteStrm, sizeof(u8), strmLen, finput); + fclose(finput); + + /* initialize decoder. If unsuccessful -> exit */ + ret = H264SwDecInit(&decInst, 0); + if (ret != H264SWDEC_OK) + { + printf("DECODER INITIALIZATION FAILED\n"); + return -1; + } + + /* initialize H264SwDecDecode() input structure */ + decInput.pStream = byteStrmStart; + decInput.dataLen = strmLen; + decInput.intraConcealmentMethod = 0; + + picNumber = 0; + + /* For performance measurements, read the start time (in seconds) here. + * The decoding time should be measured over several frames and after + * that average fps (frames/second) can be calculated. + * + * startTime = GetTime(); + * + * To prevent calculating file I/O latensies as a decoding time, + * comment out WriteOutput function call. Also prints to stdout might + * consume considerable amount of cycles during measurement */ + + /* main decoding loop */ + do + { + /* call API function to perform decoding */ + ret = H264SwDecDecode(decInst, &decInput, &decOutput); + + switch(ret) + { + + case H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY: + + /* picture dimensions are available for query now */ + ret = H264SwDecGetInfo(decInst, &decInfo); + if (ret != H264SWDEC_OK) + return -1; + + /* picture size in pixels */ + picSize = decInfo.picWidth * decInfo.picHeight; + /* memory needed for YCbCr 4:2:0 picture in bytes */ + picSize = (3 * picSize)/2; + /* memory needed for 16-bit RGB picture in bytes + * picSize = (decInfo.picWidth * decInfo.picHeight) * 2; */ + + printf("Width %d Height %d\n", + decInfo.picWidth, decInfo.picHeight); + + /* update H264SwDecDecode() input structure, number of bytes + * "consumed" is computed as difference between the new stream + * pointer and old stream pointer */ + decInput.dataLen -= + (u32)(decOutput.pStrmCurrPos - decInput.pStream); + decInput.pStream = decOutput.pStrmCurrPos; + break; + + case H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY: + case H264SWDEC_PIC_RDY: + + /* update H264SwDecDecode() input structure, number of bytes + * "consumed" is computed as difference between the new stream + * pointer and old stream pointer */ + decInput.dataLen -= + (u32)(decOutput.pStrmCurrPos - decInput.pStream); + decInput.pStream = decOutput.pStrmCurrPos; + + /* use function H264SwDecNextPicture() to obtain next picture + * in display order. Function is called until no more images + * are ready for display */ + while (H264SwDecNextPicture(decInst, &decPicture, 0) == + H264SWDEC_PIC_RDY) { picNumber++; + + printf("PIC %d, type %s, concealed %d\n", picNumber, + decPicture.isIdrPicture ? "IDR" : "NON-IDR", + decPicture.nbrOfErrMBs); + fflush(stdout); + + /* Do color conversion if needed to get display image + * in RGB-format + * + * YuvToRgb( decPicture.pOutputPicture, pRgbPicture ); */ + + /* write next display image to output file */ + WriteOutput(foutput, (u8*)decPicture.pOutputPicture, + picSize); + } + + break; + + case H264SWDEC_EVALUATION_LIMIT_EXCEEDED: + /* evaluation version of the decoder has limited decoding + * capabilities */ + printf("EVALUATION LIMIT REACHED\n"); + goto end; + + default: + printf("UNRECOVERABLE ERROR\n"); + return -1; + } + /* keep decoding until all data from input stream buffer consumed */ + } while (decInput.dataLen > 0); + +end: + + /* if output in display order is preferred, the decoder shall be forced + * to output pictures remaining in decoded picture buffer. Use function + * H264SwDecNextPicture() to obtain next picture in display order. Function + * is called until no more images are ready for display. Second parameter + * for the function is set to '1' to indicate that this is end of the + * stream and all pictures shall be output */ + while (H264SwDecNextPicture(decInst, &decPicture, 1) == + H264SWDEC_PIC_RDY) { + + picNumber++; + + printf("PIC %d, type %s, concealed %d\n", picNumber, + decPicture.isIdrPicture ? "IDR" : "NON-IDR", + decPicture.nbrOfErrMBs); + fflush(stdout); + + /* Do color conversion if needed to get display image + * in RGB-format + * + * YuvToRgb( decPicture.pOutputPicture, pRgbPicture ); */ + + /* write next display image to output file */ + WriteOutput(foutput, (u8*)decPicture.pOutputPicture, picSize); + } + + /* For performance measurements, read the end time (in seconds) here. + * + * endTime = GetTime(); + * + * Now the performance can be calculated as frames per second: + * fps = picNumber / (endTime - startTime); */ + + + /* release decoder instance */ + H264SwDecRelease(decInst); + + /* close output file */ + fclose(foutput); + + /* free byte stream buffer */ + free(byteStrmStart); + + return 0; + +} + +/*------------------------------------------------------------------------------ + + Function name: WriteOutput + + Purpose: + Write picture pointed by data to file pointed by fid. Size of the + picture in pixels is indicated by picSize. + +------------------------------------------------------------------------------*/ +void WriteOutput(FILE *fid, u8 *data, u32 picSize) +{ + fwrite(data, 1, picSize, fid); +} + +/*------------------------------------------------------------------------------ + + Function name: H264SwDecTrace + + Purpose: + Example implementation of H264SwDecTrace function. Prototype of this + function is given in H264SwDecApi.h. This implementation appends + trace messages to file named 'dec_api.trc'. + +------------------------------------------------------------------------------*/ +void H264SwDecTrace(char *string) +{ + FILE *fp; + + fp = fopen("dec_api.trc", "at"); + + if (!fp) + return; + + fwrite(string, 1, strlen(string), fp); + fwrite("\n", 1,1, fp); + + fclose(fp); +} + +/*------------------------------------------------------------------------------ + + Function name: H264SwDecmalloc + + Purpose: + Example implementation of H264SwDecMalloc function. Prototype of this + function is given in H264SwDecApi.h. This implementation uses + library function malloc for allocation of memory. + +------------------------------------------------------------------------------*/ +void* H264SwDecMalloc(u32 size) +{ + return malloc(size); +} + +/*------------------------------------------------------------------------------ + + Function name: H264SwDecFree + + Purpose: + Example implementation of H264SwDecFree function. Prototype of this + function is given in H264SwDecApi.h. This implementation uses + library function free for freeing of memory. + +------------------------------------------------------------------------------*/ +void H264SwDecFree(void *ptr) +{ + free(ptr); +} + +/*------------------------------------------------------------------------------ + + Function name: H264SwDecMemcpy + + Purpose: + Example implementation of H264SwDecMemcpy function. Prototype of this + function is given in H264SwDecApi.h. This implementation uses + library function memcpy to copy src to dest. + +------------------------------------------------------------------------------*/ +void H264SwDecMemcpy(void *dest, void *src, u32 count) +{ + memcpy(dest, src, count); +} + +/*------------------------------------------------------------------------------ + + Function name: H264SwDecMemset + + Purpose: + Example implementation of H264SwDecMemset function. Prototype of this + function is given in H264SwDecApi.h. This implementation uses + library function memset to set content of memory area pointed by ptr. + +------------------------------------------------------------------------------*/ +void H264SwDecMemset(void *ptr, i32 value, u32 count) +{ + memset(ptr, value, count); +} + diff --git a/media/libstagefright/codecs/on2/h264dec/source/H264SwDecApi.c b/media/libstagefright/codecs/on2/h264dec/source/H264SwDecApi.c new file mode 100644 index 0000000..2bb4c4d --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/H264SwDecApi.c @@ -0,0 +1,567 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. External compiler flags + 3. Module defines + 4. Local function prototypes + 5. Functions + H264SwDecInit + H264SwDecGetInfo + H264SwDecRelease + H264SwDecDecode + H264SwDecGetAPIVersion + H264SwDecNextPicture + +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ +#include <stdlib.h> +#include "basetype.h" +#include "h264bsd_container.h" +#include "H264SwDecApi.h" +#include "h264bsd_decoder.h" +#include "h264bsd_util.h" + +/*------------------------------------------------------------------------------ + Version Information +------------------------------------------------------------------------------*/ + +#define H264SWDEC_MAJOR_VERSION 2 +#define H264SWDEC_MINOR_VERSION 3 + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +H264DEC_TRACE Trace H264 Decoder API function calls. +H264DEC_EVALUATION Compile evaluation version, restricts number of frames + that can be decoded + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +#ifdef H264DEC_TRACE +#include <stdio.h> +#define DEC_API_TRC(str) H264SwDecTrace(str) +#else +#define DEC_API_TRC(str) +#endif + +#ifdef H264DEC_EVALUATION +#define H264DEC_EVALUATION_LIMIT 500 +#endif + +void H264SwDecTrace(char *string) { +} + +void* H264SwDecMalloc(u32 size) { + return malloc(size); +} + +void H264SwDecFree(void *ptr) { + free(ptr); +} + +void H264SwDecMemcpy(void *dest, void *src, u32 count) { + memcpy(dest, src, count); +} + +void H264SwDecMemset(void *ptr, i32 value, u32 count) { + memset(ptr, value, count); +} + + +/*------------------------------------------------------------------------------ + + Function: H264SwDecInit() + + Functional description: + Initialize decoder software. Function reserves memory for the + decoder instance and calls h264bsdInit to initialize the + instance data. + + Inputs: + noOutputReordering flag to indicate decoder that it doesn't have + to try to provide output pictures in display + order, saves memory + + Outputs: + decInst pointer to initialized instance is stored here + + Returns: + H264SWDEC_OK successfully initialized the instance + H264SWDEC_INITFAIL initialization failed + H264SWDEC_PARAM_ERR invalid parameters + H264SWDEC_MEM_FAIL memory allocation failed + +------------------------------------------------------------------------------*/ + +H264SwDecRet H264SwDecInit(H264SwDecInst *decInst, u32 noOutputReordering) +{ + u32 rv = 0; + + decContainer_t *pDecCont; + + DEC_API_TRC("H264SwDecInit#"); + + /* check that right shift on negative numbers is performed signed */ + /*lint -save -e* following check causes multiple lint messages */ + if ( ((-1)>>1) != (-1) ) + { + DEC_API_TRC("H264SwDecInit# ERROR: Right shift is not signed"); + return(H264SWDEC_INITFAIL); + } + /*lint -restore */ + + if (decInst == NULL) + { + DEC_API_TRC("H264SwDecInit# ERROR: decInst == NULL"); + return(H264SWDEC_PARAM_ERR); + } + + pDecCont = (decContainer_t *)H264SwDecMalloc(sizeof(decContainer_t)); + + if (pDecCont == NULL) + { + DEC_API_TRC("H264SwDecInit# ERROR: Memory allocation failed"); + return(H264SWDEC_MEMFAIL); + } + +#ifdef H264DEC_TRACE + sprintf(pDecCont->str, "H264SwDecInit# decInst %p noOutputReordering %d", + (void*)decInst, noOutputReordering); + DEC_API_TRC(pDecCont->str); +#endif + + rv = h264bsdInit(&pDecCont->storage, noOutputReordering); + if (rv != HANTRO_OK) + { + H264SwDecRelease(pDecCont); + return(H264SWDEC_MEMFAIL); + } + + pDecCont->decStat = INITIALIZED; + pDecCont->picNumber = 0; + +#ifdef H264DEC_TRACE + sprintf(pDecCont->str, "H264SwDecInit# OK: return %p", (void*)pDecCont); + DEC_API_TRC(pDecCont->str); +#endif + + *decInst = (decContainer_t *)pDecCont; + + return(H264SWDEC_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: H264SwDecGetInfo() + + Functional description: + This function provides read access to decoder information. This + function should not be called before H264SwDecDecode function has + indicated that headers are ready. + + Inputs: + decInst decoder instance + + Outputs: + pDecInfo pointer to info struct where data is written + + Returns: + H264SWDEC_OK success + H264SWDEC_PARAM_ERR invalid parameters + H264SWDEC_HDRS_NOT_RDY information not available yet + +------------------------------------------------------------------------------*/ + +H264SwDecRet H264SwDecGetInfo(H264SwDecInst decInst, H264SwDecInfo *pDecInfo) +{ + + storage_t *pStorage; + + DEC_API_TRC("H264SwDecGetInfo#"); + + if (decInst == NULL || pDecInfo == NULL) + { + DEC_API_TRC("H264SwDecGetInfo# ERROR: decInst or pDecInfo is NULL"); + return(H264SWDEC_PARAM_ERR); + } + + pStorage = &(((decContainer_t *)decInst)->storage); + + if (pStorage->activeSps == NULL || pStorage->activePps == NULL) + { + DEC_API_TRC("H264SwDecGetInfo# ERROR: Headers not decoded yet"); + return(H264SWDEC_HDRS_NOT_RDY); + } + +#ifdef H264DEC_TRACE + sprintf(((decContainer_t*)decInst)->str, + "H264SwDecGetInfo# decInst %p pDecInfo %p", decInst, (void*)pDecInfo); + DEC_API_TRC(((decContainer_t*)decInst)->str); +#endif + + /* h264bsdPicWidth and -Height return dimensions in macroblock units, + * picWidth and -Height in pixels */ + pDecInfo->picWidth = h264bsdPicWidth(pStorage) << 4; + pDecInfo->picHeight = h264bsdPicHeight(pStorage) << 4; + pDecInfo->videoRange = h264bsdVideoRange(pStorage); + pDecInfo->matrixCoefficients = h264bsdMatrixCoefficients(pStorage); + + h264bsdCroppingParams(pStorage, + &pDecInfo->croppingFlag, + &pDecInfo->cropParams.cropLeftOffset, + &pDecInfo->cropParams.cropOutWidth, + &pDecInfo->cropParams.cropTopOffset, + &pDecInfo->cropParams.cropOutHeight); + + /* sample aspect ratio */ + h264bsdSampleAspectRatio(pStorage, + &pDecInfo->parWidth, + &pDecInfo->parHeight); + + /* profile */ + pDecInfo->profile = h264bsdProfile(pStorage); + + DEC_API_TRC("H264SwDecGetInfo# OK"); + + return(H264SWDEC_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: H264SwDecRelease() + + Functional description: + Release the decoder instance. Function calls h264bsdShutDown to + release instance data and frees the memory allocated for the + instance. + + Inputs: + decInst Decoder instance + + Outputs: + none + + Returns: + none + +------------------------------------------------------------------------------*/ + +void H264SwDecRelease(H264SwDecInst decInst) +{ + + decContainer_t *pDecCont; + + DEC_API_TRC("H264SwDecRelease#"); + + if (decInst == NULL) + { + DEC_API_TRC("H264SwDecRelease# ERROR: decInst == NULL"); + return; + } + + pDecCont = (decContainer_t*)decInst; + +#ifdef H264DEC_TRACE + sprintf(pDecCont->str, "H264SwDecRelease# decInst %p",decInst); + DEC_API_TRC(pDecCont->str); +#endif + + h264bsdShutdown(&pDecCont->storage); + + H264SwDecFree(pDecCont); + +} + +/*------------------------------------------------------------------------------ + + Function: H264SwDecDecode + + Functional description: + Decode stream data. Calls h264bsdDecode to do the actual decoding. + + Input: + decInst decoder instance + pInput pointer to input struct + + Outputs: + pOutput pointer to output struct + + Returns: + H264SWDEC_NOT_INITIALIZED decoder instance not initialized yet + H264SWDEC_PARAM_ERR invalid parameters + + H264SWDEC_STRM_PROCESSED stream buffer decoded + H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY headers decoded, + stream buffer not finished + H264SWDEC_PIC_RDY decoding of a picture finished + H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY decoding of a picture finished, + stream buffer not finished + H264SWDEC_STRM_ERR serious error in decoding, no + valid parameter sets available + to decode picture data + H264SWDEC_EVALUATION_LIMIT_EXCEEDED this can only occur when + evaluation version is used, + max number of frames reached + +------------------------------------------------------------------------------*/ + +H264SwDecRet H264SwDecDecode(H264SwDecInst decInst, H264SwDecInput *pInput, + H264SwDecOutput *pOutput) +{ + + decContainer_t *pDecCont; + u32 strmLen; + u32 numReadBytes; + u8 *tmpStream; + u32 decResult = 0; + H264SwDecRet returnValue = H264SWDEC_STRM_PROCESSED; + + DEC_API_TRC("H264SwDecDecode#"); + + /* Check that function input parameters are valid */ + if (pInput == NULL || pOutput == NULL) + { + DEC_API_TRC("H264SwDecDecode# ERROR: pInput or pOutput is NULL"); + return(H264SWDEC_PARAM_ERR); + } + + if ((pInput->pStream == NULL) || (pInput->dataLen == 0)) + { + DEC_API_TRC("H264SwDecDecode# ERROR: Invalid input parameters"); + return(H264SWDEC_PARAM_ERR); + } + + pDecCont = (decContainer_t *)decInst; + + /* Check if decoder is in an incorrect mode */ + if (decInst == NULL || pDecCont->decStat == UNINITIALIZED) + { + DEC_API_TRC("H264SwDecDecode# ERROR: Decoder not initialized"); + return(H264SWDEC_NOT_INITIALIZED); + } + +#ifdef H264DEC_EVALUATION + if (pDecCont->picNumber >= H264DEC_EVALUATION_LIMIT) + return(H264SWDEC_EVALUATION_LIMIT_EXCEEDED); +#endif + +#ifdef H264DEC_TRACE + sprintf(pDecCont->str, "H264SwDecDecode# decInst %p pInput %p pOutput %p", + decInst, (void*)pInput, (void*)pOutput); + DEC_API_TRC(pDecCont->str); +#endif + + pOutput->pStrmCurrPos = NULL; + + numReadBytes = 0; + strmLen = pInput->dataLen; + tmpStream = pInput->pStream; + pDecCont->storage.intraConcealmentFlag = pInput->intraConcealmentMethod; + + do + { + /* Return HDRS_RDY after DPB flush caused by new SPS */ + if (pDecCont->decStat == NEW_HEADERS) + { + decResult = H264BSD_HDRS_RDY; + pDecCont->decStat = INITIALIZED; + } + else /* Continue decoding normally */ + { + decResult = h264bsdDecode(&pDecCont->storage, tmpStream, strmLen, + pInput->picId, &numReadBytes); + } + tmpStream += numReadBytes; + /* check if too many bytes are read from stream */ + if ( (i32)(strmLen - numReadBytes) >= 0 ) + strmLen -= numReadBytes; + else + strmLen = 0; + + pOutput->pStrmCurrPos = tmpStream; + + switch (decResult) + { + case H264BSD_HDRS_RDY: + + if(pDecCont->storage.dpb->flushed && + pDecCont->storage.dpb->numOut != + pDecCont->storage.dpb->outIndex) + { + /* output first all DPB stored pictures + * DPB flush caused by new SPS */ + pDecCont->storage.dpb->flushed = 0; + pDecCont->decStat = NEW_HEADERS; + returnValue = H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY; + strmLen = 0; + } + else + { + returnValue = H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY; + strmLen = 0; + } + break; + + case H264BSD_PIC_RDY: + pDecCont->picNumber++; + + if (strmLen == 0) + returnValue = H264SWDEC_PIC_RDY; + else + returnValue = H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY; + + strmLen = 0; + break; + + case H264BSD_PARAM_SET_ERROR: + if ( !h264bsdCheckValidParamSets(&pDecCont->storage) && + strmLen == 0 ) + { + returnValue = H264SWDEC_STRM_ERR; + } + break; + case H264BSD_MEMALLOC_ERROR: + { + returnValue = H264SWDEC_MEMFAIL; + strmLen = 0; + } + break; + default: + break; + } + + } while (strmLen); + +#ifdef H264DEC_TRACE + sprintf(pDecCont->str, "H264SwDecDecode# OK: DecResult %d", + returnValue); + DEC_API_TRC(pDecCont->str); +#endif + + return(returnValue); + +} + +/*------------------------------------------------------------------------------ + + Function: H264SwDecGetAPIVersion + + Functional description: + Return version information of the API + + Inputs: + none + + Outputs: + none + + Returns: + API version + +------------------------------------------------------------------------------*/ + +H264SwDecApiVersion H264SwDecGetAPIVersion() +{ + H264SwDecApiVersion ver; + + ver.major = H264SWDEC_MAJOR_VERSION; + ver.minor = H264SWDEC_MINOR_VERSION; + + return(ver); +} + +/*------------------------------------------------------------------------------ + + Function: H264SwDecNextPicture + + Functional description: + Get next picture in display order if any available. + + Input: + decInst decoder instance. + flushBuffer force output of all buffered pictures + + Output: + pOutput pointer to output structure + + Returns: + H264SWDEC_OK no pictures available for display + H264SWDEC_PIC_RDY picture available for display + H264SWDEC_PARAM_ERR invalid parameters + +------------------------------------------------------------------------------*/ + +H264SwDecRet H264SwDecNextPicture(H264SwDecInst decInst, + H264SwDecPicture *pOutput, u32 flushBuffer) +{ + + decContainer_t *pDecCont; + u32 numErrMbs, isIdrPic, picId; + u32 *pOutPic; + + DEC_API_TRC("H264SwDecNextPicture#"); + + if (decInst == NULL || pOutput == NULL) + { + DEC_API_TRC("H264SwDecNextPicture# ERROR: decInst or pOutput is NULL"); + return(H264SWDEC_PARAM_ERR); + } + + pDecCont = (decContainer_t*)decInst; + +#ifdef H264DEC_TRACE + sprintf(pDecCont->str, "H264SwDecNextPicture# decInst %p pOutput %p %s %d", + decInst, (void*)pOutput, "flushBuffer", flushBuffer); + DEC_API_TRC(pDecCont->str); +#endif + + if (flushBuffer) + h264bsdFlushBuffer(&pDecCont->storage); + + pOutPic = (u32*)h264bsdNextOutputPicture(&pDecCont->storage, &picId, + &isIdrPic, &numErrMbs); + + if (pOutPic == NULL) + { + DEC_API_TRC("H264SwDecNextPicture# OK: return H264SWDEC_OK"); + return(H264SWDEC_OK); + } + else + { + pOutput->pOutputPicture = pOutPic; + pOutput->picId = picId; + pOutput->isIdrPicture = isIdrPic; + pOutput->nbrOfErrMBs = numErrMbs; + DEC_API_TRC("H264SwDecNextPicture# OK: return H264SWDEC_PIC_RDY"); + return(H264SWDEC_PIC_RDY); + } + +} + + diff --git a/media/libstagefright/codecs/on2/h264dec/source/TestBenchMultipleInstance.c b/media/libstagefright/codecs/on2/h264dec/source/TestBenchMultipleInstance.c new file mode 100755 index 0000000..42170d3 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/TestBenchMultipleInstance.c @@ -0,0 +1,531 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* CVS tag name for identification */ +const char tagName[256] = "$Name: FIRST_ANDROID_COPYRIGHT $"; + +#include "H264SwDecApi.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define DEBUG(argv) printf argv + +/* _NO_OUT disables output file writing */ +#ifdef __arm +#define _NO_OUT +#endif + +/*------------------------------------------------------------------------------ + +------------------------------------------------------------------------------*/ +void WriteOutput(FILE *fid, u8 *data, u32 picSize); + +u32 CropPicture(u8 *pOutImage, u8 *pInImage, + u32 picWidth, u32 picHeight, CropParams *pCropParams); + +void CropWriteOutput(FILE *fid, u8 *imageData, u32 cropDisplay, + H264SwDecInfo *decInfo); + +typedef struct +{ + H264SwDecInst decInst; + H264SwDecInput decInput; + H264SwDecOutput decOutput; + H264SwDecPicture decPicture; + H264SwDecInfo decInfo; + FILE *foutput; + char outFileName[256]; + u8 *byteStrmStart; + u32 picNumber; +} Decoder; + + +/*------------------------------------------------------------------------------ + +------------------------------------------------------------------------------*/ +int main(int argc, char **argv) +{ + + i32 instCount, instRunning; + i32 i; + u32 maxNumPics; + u32 strmLen; + H264SwDecRet ret; + u32 numErrors = 0; + u32 cropDisplay = 0; + u32 disableOutputReordering = 0; + FILE *finput; + Decoder **decoder; + char outFileName[256] = "out.yuv"; + + + if ( argc > 1 && strcmp(argv[1], "-T") == 0 ) + { + fprintf(stderr, "%s\n", tagName); + return 0; + } + + if (argc < 2) + { + DEBUG(( + "Usage: %s [-Nn] [-Ooutfile] [-P] [-U] [-C] [-R] [-T] file1.264 [file2.264] .. [fileN.264]\n", + argv[0])); + DEBUG(("\t-Nn forces decoding to stop after n pictures\n")); +#if defined(_NO_OUT) + DEBUG(("\t-Ooutfile output writing disabled at compile time\n")); +#else + DEBUG(("\t-Ooutfile write output to \"outfile\" (default out.yuv)\n")); + DEBUG(("\t-Onone does not write output\n")); +#endif + DEBUG(("\t-C display cropped image (default decoded image)\n")); + DEBUG(("\t-R disable DPB output reordering\n")); + DEBUG(("\t-T to print tag name and exit\n")); + exit(100); + } + + instCount = argc - 1; + + /* read command line arguments */ + maxNumPics = 0; + for (i = 1; i < (argc-1); i++) + { + if ( strncmp(argv[i], "-N", 2) == 0 ) + { + maxNumPics = (u32)atoi(argv[i]+2); + instCount--; + } + else if ( strncmp(argv[i], "-O", 2) == 0 ) + { + strcpy(outFileName, argv[i]+2); + instCount--; + } + else if ( strcmp(argv[i], "-C") == 0 ) + { + cropDisplay = 1; + instCount--; + } + else if ( strcmp(argv[i], "-R") == 0 ) + { + disableOutputReordering = 1; + instCount--; + } + } + + if (instCount < 1) + { + DEBUG(("No input files\n")); + exit(100); + } + + /* allocate memory for multiple decoder instances + * one instance for every stream file */ + decoder = (Decoder **)malloc(sizeof(Decoder*)*(u32)instCount); + if (decoder == NULL) + { + DEBUG(("Unable to allocate memory\n")); + exit(100); + } + + /* prepare each decoder instance */ + for (i = 0; i < instCount; i++) + { + decoder[i] = (Decoder *)calloc(1, sizeof(Decoder)); + + /* open input file */ + finput = fopen(argv[argc-instCount+i],"rb"); + if (finput == NULL) + { + DEBUG(("Unable to open input file <%s>\n", argv[argc-instCount+i])); + exit(100); + } + + DEBUG(("Reading input file[%d] %s\n", i, argv[argc-instCount+i])); + + /* read input stream to buffer */ + fseek(finput,0L,SEEK_END); + strmLen = (u32)ftell(finput); + rewind(finput); + decoder[i]->byteStrmStart = (u8 *)malloc(sizeof(u8)*strmLen); + if (decoder[i]->byteStrmStart == NULL) + { + DEBUG(("Unable to allocate memory\n")); + exit(100); + } + fread(decoder[i]->byteStrmStart, sizeof(u8), strmLen, finput); + fclose(finput); + + /* open output file */ + if (strcmp(outFileName, "none") != 0) + { +#if defined(_NO_OUT) + decoder[i]->foutput = NULL; +#else + sprintf(decoder[i]->outFileName, "%s%i", outFileName, i); + decoder[i]->foutput = fopen(decoder[i]->outFileName, "wb"); + if (decoder[i]->foutput == NULL) + { + DEBUG(("Unable to open output file\n")); + exit(100); + } +#endif + } + + ret = H264SwDecInit(&(decoder[i]->decInst), disableOutputReordering); + + if (ret != H264SWDEC_OK) + { + DEBUG(("Init failed %d\n", ret)); + exit(100); + } + + decoder[i]->decInput.pStream = decoder[i]->byteStrmStart; + decoder[i]->decInput.dataLen = strmLen; + decoder[i]->decInput.intraConcealmentMethod = 0; + + } + + /* main decoding loop */ + do + { + /* decode once using each instance */ + for (i = 0; i < instCount; i++) + { + ret = H264SwDecDecode(decoder[i]->decInst, + &(decoder[i]->decInput), + &(decoder[i]->decOutput)); + + switch(ret) + { + + case H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY: + + ret = H264SwDecGetInfo(decoder[i]->decInst, + &(decoder[i]->decInfo)); + if (ret != H264SWDEC_OK) + exit(1); + + if (cropDisplay && decoder[i]->decInfo.croppingFlag) + { + DEBUG(("Decoder[%d] Cropping params: (%d, %d) %dx%d\n", + i, + decoder[i]->decInfo.cropParams.cropLeftOffset, + decoder[i]->decInfo.cropParams.cropTopOffset, + decoder[i]->decInfo.cropParams.cropOutWidth, + decoder[i]->decInfo.cropParams.cropOutHeight)); + } + + DEBUG(("Decoder[%d] Width %d Height %d\n", i, + decoder[i]->decInfo.picWidth, + decoder[i]->decInfo.picHeight)); + + DEBUG(("Decoder[%d] videoRange %d, matricCoefficients %d\n", + i, decoder[i]->decInfo.videoRange, + decoder[i]->decInfo.matrixCoefficients)); + decoder[i]->decInput.dataLen -= + (u32)(decoder[i]->decOutput.pStrmCurrPos - + decoder[i]->decInput.pStream); + decoder[i]->decInput.pStream = + decoder[i]->decOutput.pStrmCurrPos; + break; + + case H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY: + decoder[i]->decInput.dataLen -= + (u32)(decoder[i]->decOutput.pStrmCurrPos - + decoder[i]->decInput.pStream); + decoder[i]->decInput.pStream = + decoder[i]->decOutput.pStrmCurrPos; + /* fall through */ + case H264SWDEC_PIC_RDY: + if (ret == H264SWDEC_PIC_RDY) + decoder[i]->decInput.dataLen = 0; + + ret = H264SwDecGetInfo(decoder[i]->decInst, + &(decoder[i]->decInfo)); + if (ret != H264SWDEC_OK) + exit(1); + + while (H264SwDecNextPicture(decoder[i]->decInst, + &(decoder[i]->decPicture), 0) == H264SWDEC_PIC_RDY) + { + decoder[i]->picNumber++; + + numErrors += decoder[i]->decPicture.nbrOfErrMBs; + + DEBUG(("Decoder[%d] PIC %d, type %s, concealed %d\n", + i, decoder[i]->picNumber, + decoder[i]->decPicture.isIdrPicture + ? "IDR" : "NON-IDR", + decoder[i]->decPicture.nbrOfErrMBs)); + fflush(stdout); + + CropWriteOutput(decoder[i]->foutput, + (u8*)decoder[i]->decPicture.pOutputPicture, + cropDisplay, &(decoder[i]->decInfo)); + } + + if (maxNumPics && decoder[i]->picNumber == maxNumPics) + decoder[i]->decInput.dataLen = 0; + break; + + case H264SWDEC_STRM_PROCESSED: + case H264SWDEC_STRM_ERR: + case H264SWDEC_PARAM_ERR: + decoder[i]->decInput.dataLen = 0; + break; + + default: + DEBUG(("Decoder[%d] FATAL ERROR\n", i)); + exit(10); + break; + + } + } + + /* check if any of the instances is still running (=has more data) */ + instRunning = instCount; + for (i = 0; i < instCount; i++) + { + if (decoder[i]->decInput.dataLen == 0) + instRunning--; + } + + } while (instRunning); + + + /* get last frames and close each instance */ + for (i = 0; i < instCount; i++) + { + while (H264SwDecNextPicture(decoder[i]->decInst, + &(decoder[i]->decPicture), 1) == H264SWDEC_PIC_RDY) + { + decoder[i]->picNumber++; + + DEBUG(("Decoder[%d] PIC %d, type %s, concealed %d\n", + i, decoder[i]->picNumber, + decoder[i]->decPicture.isIdrPicture + ? "IDR" : "NON-IDR", + decoder[i]->decPicture.nbrOfErrMBs)); + fflush(stdout); + + CropWriteOutput(decoder[i]->foutput, + (u8*)decoder[i]->decPicture.pOutputPicture, + cropDisplay, &(decoder[i]->decInfo)); + } + + H264SwDecRelease(decoder[i]->decInst); + + if (decoder[i]->foutput) + fclose(decoder[i]->foutput); + + free(decoder[i]->byteStrmStart); + + free(decoder[i]); + } + + free(decoder); + + if (numErrors) + return 1; + else + return 0; + +} + +/*------------------------------------------------------------------------------ + +------------------------------------------------------------------------------*/ +void CropWriteOutput(FILE *foutput, u8 *imageData, u32 cropDisplay, + H264SwDecInfo *decInfo) +{ + u8 *tmpImage = NULL; + u32 tmp, picSize; + + if (cropDisplay && decInfo->croppingFlag) + { + picSize = decInfo->cropParams.cropOutWidth * + decInfo->cropParams.cropOutHeight; + picSize = (3 * picSize)/2; + tmpImage = malloc(picSize); + if (tmpImage == NULL) + exit(1); + tmp = CropPicture(tmpImage, imageData, + decInfo->picWidth, decInfo->picHeight, + &(decInfo->cropParams)); + if (tmp) + exit(1); + WriteOutput(foutput, tmpImage, picSize); + free(tmpImage); + } + else + { + picSize = decInfo->picWidth * decInfo->picHeight; + picSize = (3 * picSize)/2; + WriteOutput(foutput, imageData, picSize); + } + +} + +/*------------------------------------------------------------------------------ + +------------------------------------------------------------------------------*/ +void WriteOutput(FILE *fid, u8 *data, u32 picSize) +{ + if (fid) + fwrite(data, 1, picSize, fid); +} + +/*------------------------------------------------------------------------------ + + Function name: H264SwDecTrace + +------------------------------------------------------------------------------*/ +void H264SwDecTrace(char *string) +{ + FILE *fp; + + fp = fopen("dec_api.trc", "at"); + + if (!fp) + return; + + fwrite(string, 1, strlen(string), fp); + fwrite("\n", 1,1, fp); + + fclose(fp); +} + +/*------------------------------------------------------------------------------ + + Function name: H264SwDecmalloc + +------------------------------------------------------------------------------*/ +void* H264SwDecMalloc(u32 size) +{ + return malloc(size); +} + +/*------------------------------------------------------------------------------ + + Function name: H264SwDecFree + +------------------------------------------------------------------------------*/ +void H264SwDecFree(void *ptr) +{ + free(ptr); +} + +/*------------------------------------------------------------------------------ + + Function name: H264SwDecMemcpy + +------------------------------------------------------------------------------*/ +void H264SwDecMemcpy(void *dest, void *src, u32 count) +{ + memcpy(dest, src, count); +} + +/*------------------------------------------------------------------------------ + + Function name: H264SwDecMemset + +------------------------------------------------------------------------------*/ +void H264SwDecMemset(void *ptr, i32 value, u32 count) +{ + memset(ptr, value, count); +} + +/*------------------------------------------------------------------------------ + + Function name: CropPicture + +------------------------------------------------------------------------------*/ +u32 CropPicture(u8 *pOutImage, u8 *pInImage, + u32 picWidth, u32 picHeight, CropParams *pCropParams) +{ + + u32 i, j; + u32 outWidth, outHeight; + u8 *pOut, *pIn; + + if (pOutImage == NULL || pInImage == NULL || pCropParams == NULL || + !picWidth || !picHeight) + { + /* due to lint warning */ + free(pOutImage); + return(1); + } + + if ( ((pCropParams->cropLeftOffset + pCropParams->cropOutWidth) > + picWidth ) || + ((pCropParams->cropTopOffset + pCropParams->cropOutHeight) > + picHeight ) ) + { + /* due to lint warning */ + free(pOutImage); + return(1); + } + + outWidth = pCropParams->cropOutWidth; + outHeight = pCropParams->cropOutHeight; + + pIn = pInImage + pCropParams->cropTopOffset*picWidth + + pCropParams->cropLeftOffset; + pOut = pOutImage; + + /* luma */ + for (i = outHeight; i; i--) + { + for (j = outWidth; j; j--) + { + *pOut++ = *pIn++; + } + pIn += picWidth - outWidth; + } + + outWidth >>= 1; + outHeight >>= 1; + + pIn = pInImage + picWidth*picHeight + + pCropParams->cropTopOffset*picWidth/4 + pCropParams->cropLeftOffset/2; + + /* cb */ + for (i = outHeight; i; i--) + { + for (j = outWidth; j; j--) + { + *pOut++ = *pIn++; + } + pIn += picWidth/2 - outWidth; + } + + pIn = pInImage + 5*picWidth*picHeight/4 + + pCropParams->cropTopOffset*picWidth/4 + pCropParams->cropLeftOffset/2; + + /* cr */ + for (i = outHeight; i; i--) + { + for (j = outWidth; j; j--) + { + *pOut++ = *pIn++; + } + pIn += picWidth/2 - outWidth; + } + + return (0); + +} + diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_chroma_hor.s b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_chroma_hor.s new file mode 100755 index 0000000..634a484 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_chroma_hor.s @@ -0,0 +1,298 @@ +; Copyright (C) 2009 The Android Open Source Project +; +; Licensed under the Apache License, Version 2.0 (the "License"); +; you may not use this file except in compliance with the License. +; You may obtain a copy of the License at +; +; http://www.apache.org/licenses/LICENSE-2.0 +; +; Unless required by applicable law or agreed to in writing, software +; distributed under the License is distributed on an "AS IS" BASIS, +; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +; See the License for the specific language governing permissions and +; limitations under the License. + +;------------------------------------------------------------------------------- +;-- +;-- Abstract : ARMv6 optimized version of h264bsdInterpolateChromaHor function +;-- +;------------------------------------------------------------------------------- + + + IF :DEF: H264DEC_WINASM + ;// We dont use REQUIRE8 and PRESERVE8 for winasm + ELSE + REQUIRE8 + PRESERVE8 + ENDIF + + AREA |.text|, CODE + + +;// h264bsdInterpolateChromaHor register allocation + +ref RN 0 +ptrA RN 0 + +mb RN 1 +block RN 1 + +x0 RN 2 +count RN 2 + +y0 RN 3 +valX RN 3 + +width RN 4 + +height RN 5 +tmp7 RN 5 + +chrPW RN 6 +tmp8 RN 6 + +tmp1 RN 7 +chrPH RN 7 + +tmp2 RN 8 + +tmp3 RN 9 + +tmp4 RN 10 + +tmp5 RN 11 + +tmp6 RN 12 + +c32 RN 14 +xFrac RN 14 + +;// Function exports and imports + + IMPORT h264bsdFillBlock + + EXPORT h264bsdInterpolateChromaHor + +;// Function arguments +;// +;// u8 *ref, : 0xc4 +;// u8 *predPartChroma, : 0xc8 +;// i32 x0, : 0xcc +;// i32 y0, : 0xd0 +;// u32 width, : 0xf8 +;// u32 height, : 0xfc +;// u32 xFrac, : 0x100 +;// u32 chromaPartWidth, : 0x104 +;// u32 chromaPartHeight : 0x108 + +h264bsdInterpolateChromaHor + STMFD sp!, {r0-r11,lr} + SUB sp, sp, #0xc4 + + LDR chrPW, [sp, #0x104] ;// chromaPartWidth + LDR width, [sp, #0xf8] ;// width + CMP x0, #0 + BLT do_fill + + ADD tmp6, x0, chrPW ;// tmp6 = x0+ chromaPartWidth + ADD tmp6, tmp6, #1 ;// tmp6 = x0 + chromaPartWidth + 1 + CMP tmp6, width ;// x0+chromaPartWidth+1 > width + BHI do_fill + + CMP y0, #0 + BLT do_fill + LDR chrPH, [sp, #0x108] ;// chromaPartHeight + LDR height, [sp, #0xfc] ;// height + ADD tmp6, y0, chrPH ;// tmp6 = y0 + chromaPartHeight + CMP tmp6, height + BLS skip_fill + +do_fill + LDR chrPH, [sp, #0x108] ;// chromaPartHeight + LDR height, [sp, #0xfc] ;// height + ADD tmp8, chrPW, #1 ;// tmp8 = chromaPartWidth+1 + MOV tmp2, tmp8 ;// tmp2 = chromaPartWidth+1 + STMIA sp,{width,height,tmp8,chrPH,tmp2} + ADD block, sp, #0x1c ;// block + BL h264bsdFillBlock + + LDR x0, [sp, #0xcc] + LDR y0, [sp, #0xd0] + LDR ref, [sp, #0xc4] ;// ref + STMIA sp,{width,height,tmp8,chrPH,tmp2} + ADD block, sp, #0x1c ;// block + MLA ref, height, width, ref ;// ref += width * height; + MLA block, chrPH, tmp8, block;// block + (chromaPH)*(chromaPW+1) + BL h264bsdFillBlock + + MOV x0, #0 ;// x0 = 0 + MOV y0, #0 ;// y0 = 0 + STR x0, [sp, #0xcc] + STR y0, [sp, #0xd0] + ADD ref, sp, #0x1c ;// ref = block + STR ref, [sp, #0xc4] ;// ref + + STR chrPH, [sp, #0xfc] ;// height + STR tmp8, [sp, #0xf8] ;// width + MOV width, tmp8 + SUB chrPW, chrPW, #1 + +skip_fill + MLA tmp3, y0, width, x0 ;// tmp3 = y0*width+x0 + LDR xFrac, [sp, #0x100] ;// xFrac + ADD ptrA, ref, tmp3 ;// ptrA = ref + y0*width+x0 + RSB valX, xFrac, #8 ;// valX = 8-xFrac + + LDR mb, [sp, #0xc8] ;// predPartChroma + + + ;// pack values to count register + ;// [31:28] loop_x (chromaPartWidth-1) + ;// [27:24] loop_y (chromaPartHeight-1) + ;// [23:20] chromaPartWidth-1 + ;// [19:16] chromaPartHeight-1 + ;// [15:00] nothing + + SUB tmp2, chrPH, #1 ;// chromaPartHeight-1 + SUB tmp1, chrPW, #1 ;// chromaPartWidth-1 + ADD count, count, tmp2, LSL #16 ;// chromaPartHeight-1 + ADD count, count, tmp2, LSL #24 ;// loop_y + ADD count, count, tmp1, LSL #20 ;// chromaPartWidth-1 + AND tmp2, count, #0x00F00000 ;// loop_x + PKHBT valX, valX, xFrac, LSL #16 ;// |xFrac|valX | + MOV valX, valX, LSL #3 ;// multiply by 8 in advance + MOV c32, #32 + + + ;/////////////////////////////////////////////////////////////////////////// + ;// Cb + ;/////////////////////////////////////////////////////////////////////////// + + ;// 2x2 pels per iteration + ;// bilinear vertical interpolation + +loop1_y + ADD count, count, tmp2, LSL #8 + LDRB tmp1, [ptrA, width] + LDRB tmp2, [ptrA], #1 + +loop1_x + LDRB tmp3, [ptrA, width] + LDRB tmp4, [ptrA], #1 + + PKHBT tmp5, tmp1, tmp3, LSL #16 + PKHBT tmp6, tmp2, tmp4, LSL #16 + + LDRB tmp1, [ptrA, width] + LDRB tmp2, [ptrA], #1 + + SMLAD tmp5, tmp5, valX, c32 ;// multiply + SMLAD tmp6, tmp6, valX, c32 ;// multiply + + PKHBT tmp7, tmp3, tmp1, LSL #16 + PKHBT tmp8, tmp4, tmp2, LSL #16 + + SMLAD tmp7, tmp7, valX, c32 ;// multiply + SMLAD tmp8, tmp8, valX, c32 ;// multiply + + MOV tmp5, tmp5, LSR #6 ;// scale down + STRB tmp5, [mb,#8] ;// store row 2 col 1 + + MOV tmp6, tmp6, LSR #6 ;// scale down + STRB tmp6, [mb],#1 ;// store row 1 col 1 + + MOV tmp7, tmp7, LSR #6 ;// scale down + STRB tmp7, [mb,#8] ;// store row 2 col 2 + + MOV tmp8, tmp8, LSR #6 ;// scale down + STRB tmp8, [mb],#1 ;// store row 1 col 2 + + SUBS count, count, #2<<28 + BCS loop1_x + + AND tmp2, count, #0x00F00000 + + ADDS mb, mb, #16 + SBC mb, mb, tmp2, LSR #20 + ADD ptrA, ptrA, width, LSL #1 + SBC ptrA, ptrA, tmp2, LSR #20 + SUB ptrA, ptrA, #1 + + ADDS count, count, #0xE << 24 + BGE loop1_y + + ;/////////////////////////////////////////////////////////////////////////// + ;// Cr + ;/////////////////////////////////////////////////////////////////////////// + LDR height, [sp,#0xfc] ;// height + LDR ref, [sp, #0xc4] ;// ref + LDR tmp1, [sp, #0xd0] ;// y0 + LDR tmp2, [sp, #0xcc] ;// x0 + LDR mb, [sp, #0xc8] ;// predPartChroma + + ADD tmp1, height, tmp1 + MLA tmp3, tmp1, width, tmp2 + ADD ptrA, ref, tmp3 + ADD mb, mb, #64 + + AND count, count, #0x00FFFFFF + AND tmp1, count, #0x000F0000 + ADD count, count, tmp1, LSL #8 + AND tmp2, count, #0x00F00000 + + ;// 2x2 pels per iteration + ;// bilinear vertical interpolation +loop2_y + ADD count, count, tmp2, LSL #8 + LDRB tmp1, [ptrA, width] + LDRB tmp2, [ptrA], #1 + +loop2_x + LDRB tmp3, [ptrA, width] + LDRB tmp4, [ptrA], #1 + + PKHBT tmp5, tmp1, tmp3, LSL #16 + PKHBT tmp6, tmp2, tmp4, LSL #16 + + LDRB tmp1, [ptrA, width] + LDRB tmp2, [ptrA], #1 + + SMLAD tmp5, tmp5, valX, c32 ;// multiply + SMLAD tmp6, tmp6, valX, c32 ;// multiply + + PKHBT tmp7, tmp3, tmp1, LSL #16 + PKHBT tmp8, tmp4, tmp2, LSL #16 + + SMLAD tmp7, tmp7, valX, c32 ;// multiply + SMLAD tmp8, tmp8, valX, c32 ;// multiply + + MOV tmp5, tmp5, LSR #6 ;// scale down + STRB tmp5, [mb,#8] ;// store row 2 col 1 + + MOV tmp6, tmp6, LSR #6 ;// scale down + STRB tmp6, [mb],#1 ;// store row 1 col 1 + + MOV tmp7, tmp7, LSR #6 ;// scale down + STRB tmp7, [mb,#8] ;// store row 2 col 2 + + MOV tmp8, tmp8, LSR #6 ;// scale down + STRB tmp8, [mb],#1 ;// store row 1 col 2 + + SUBS count, count, #2<<28 + BCS loop2_x + + AND tmp2, count, #0x00F00000 + + ADDS mb, mb, #16 + SBC mb, mb, tmp2, LSR #20 + ADD ptrA, ptrA, width, LSL #1 + SBC ptrA, ptrA, tmp2, LSR #20 + SUB ptrA, ptrA, #1 + + ADDS count, count, #0xE << 24 + BGE loop2_y + + ADD sp,sp,#0xd4 + LDMFD sp!, {r4-r11,pc} + + END diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_chroma_hor_ver.s b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_chroma_hor_ver.s new file mode 100755 index 0000000..7420ad3 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_chroma_hor_ver.s @@ -0,0 +1,339 @@ +; Copyright (C) 2009 The Android Open Source Project +; +; Licensed under the Apache License, Version 2.0 (the "License"); +; you may not use this file except in compliance with the License. +; You may obtain a copy of the License at +; +; http://www.apache.org/licenses/LICENSE-2.0 +; +; Unless required by applicable law or agreed to in writing, software +; distributed under the License is distributed on an "AS IS" BASIS, +; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +; See the License for the specific language governing permissions and +; limitations under the License. + +;------------------------------------------------------------------------------- +;-- +;-- Abstract : ARMv6 optimized version of h264bsdInterpolateChromaHorVer +;-- function +;-- +;------------------------------------------------------------------------------- + + + IF :DEF: H264DEC_WINASM + ;// We dont use REQUIRE8 and PRESERVE8 for winasm + ELSE + REQUIRE8 + PRESERVE8 + ENDIF + + AREA |.text|, CODE + + +;// h264bsdInterpolateChromaHorVer register allocation + +ref RN 0 +ptrA RN 0 + +mb RN 1 +block RN 1 + +x0 RN 2 +count RN 2 + +y0 RN 3 +valY RN 3 + +width RN 4 + +tmp4 RN 5 +height RN 5 + +tmp1 RN 6 + +tmp2 RN 7 + +tmp3 RN 8 + +valX RN 9 + +tmp5 RN 10 +chrPW RN 10 + +tmp6 RN 11 +chrPH RN 11 + +xFrac RN 12 + +c32 RN 14 +yFrac RN 14 + +;// function exports and imports + + IMPORT h264bsdFillBlock + + EXPORT h264bsdInterpolateChromaHorVer + +;// Function arguments +;// +;// u8 *ref, : 0xc4 +;// u8 *predPartChroma, : 0xc8 +;// i32 x0, : 0xcc +;// i32 y0, : 0xd0 +;// u32 width, : 0xf8 +;// u32 height, : 0xfc +;// u32 xFrac, : 0x100 +;// u32 yFrac, : 0x104 +;// u32 chromaPartWidth, : 0x108 +;// u32 chromaPartHeight : 0x10c + +h264bsdInterpolateChromaHorVer + STMFD sp!, {r0-r11,lr} + SUB sp, sp, #0xc4 + + LDR chrPW, [sp, #0x108] ;// chromaPartWidth + LDR xFrac, [sp, #0x100] ;// xFrac + LDR width, [sp, #0xf8] ;// width + CMP x0, #0 + BLT do_fill + + ADD tmp1, x0, chrPW ;// tmp1 = x0+ chromaPartWidth + ADD tmp1, tmp1, #1 ;// tmp1 = x0+ chromaPartWidth+1 + CMP tmp1, width ;// x0+chromaPartWidth+1 > width + BHI do_fill + + CMP y0, #0 + BLT do_fill + LDR chrPH, [sp, #0x10c] ;// chromaPartHeight + LDR height, [sp, #0xfc] ;// height + ADD tmp1, y0, chrPH ;// tmp1 = y0 + chromaPartHeight + ADD tmp1, tmp1, #1 ;// tmp1 = y0 + chromaPartHeight + 1 + CMP tmp1, height + BLS skip_fill + +do_fill + LDR chrPH, [sp, #0x10c] ;// chromaPartHeight + LDR height, [sp, #0xfc] ;// height + ADD tmp3, chrPW, #1 ;// tmp3 = chromaPartWidth+1 + ADD tmp1, chrPW, #1 ;// tmp1 = chromaPartWidth+1 + ADD tmp2, chrPH, #1 ;// tmp2 = chromaPartHeight+1 + STMIA sp,{width,height,tmp1,tmp2,tmp3} + ADD block, sp, #0x1c ;// block + BL h264bsdFillBlock + + LDR x0, [sp, #0xcc] + LDR y0, [sp, #0xd0] + LDR ref, [sp, #0xc4] ;// ref + STMIA sp,{width,height,tmp1,tmp2,tmp3} + ADD block, sp, #0x1c ;// block + MLA ref, height, width, ref ;// ref += width * height; + MLA block, tmp2, tmp1, block;// block + (chromaPW+1)*(chromaPH+1) + BL h264bsdFillBlock + + MOV x0, #0 ;// x0 = 0 + MOV y0, #0 ;// y0 = 0 + STR x0, [sp, #0xcc] + STR y0, [sp, #0xd0] + ADD ref, sp, #0x1c ;// ref = block + STR ref, [sp, #0xc4] ;// ref + + STR tmp2, [sp, #0xfc] ;// height + STR tmp1, [sp, #0xf8] ;// width + MOV width, tmp1 + +skip_fill + MLA tmp3, y0, width, x0 ;// tmp3 = y0*width+x0 + LDR yFrac, [sp, #0x104] ;// yFrac + LDR xFrac, [sp, #0x100] + ADD ptrA, ref, tmp3 ;// ptrA = ref + y0*width+x0 + RSB valX, xFrac, #8 ;// valX = 8-xFrac + RSB valY, yFrac, #8 ;// valY = 8-yFrac + + LDR mb, [sp, #0xc8] ;// predPartChroma + + + ;// pack values to count register + ;// [31:28] loop_x (chromaPartWidth-1) + ;// [27:24] loop_y (chromaPartHeight-1) + ;// [23:20] chromaPartWidth-1 + ;// [19:16] chromaPartHeight-1 + ;// [15:00] nothing + + SUB tmp2, chrPH, #1 ;// chromaPartHeight-1 + SUB tmp1, chrPW, #1 ;// chromaPartWidth-1 + ADD count, count, tmp2, LSL #16 ;// chromaPartHeight-1 + ADD count, count, tmp2, LSL #24 ;// loop_y + ADD count, count, tmp1, LSL #20 ;// chromaPartWidth-1 + AND tmp2, count, #0x00F00000 ;// loop_x + PKHBT valY, valY, yFrac, LSL #16 ;// |yFrac|valY | + MOV c32, #32 + + + ;/////////////////////////////////////////////////////////////////////////// + ;// Cb + ;/////////////////////////////////////////////////////////////////////////// + + ;// 2x2 pels per iteration + ;// bilinear vertical and horizontal interpolation + +loop1_y + LDRB tmp1, [ptrA] + LDRB tmp3, [ptrA, width] + LDRB tmp5, [ptrA, width, LSL #1] + + PKHBT tmp1, tmp1, tmp3, LSL #16 ;// |t3|t1| + PKHBT tmp3, tmp3, tmp5, LSL #16 ;// |t5|t3| + + SMUAD tmp1, tmp1, valY ;// t1=(t1*valY + t3*yFrac) + SMUAD tmp3, tmp3, valY ;// t3=(t3*valY + t5*yFrac) + + ADD count, count, tmp2, LSL #8 +loop1_x + ;// first + LDRB tmp2, [ptrA, #1]! + LDRB tmp4, [ptrA, width] + LDRB tmp6, [ptrA, width, LSL #1] + + PKHBT tmp2, tmp2, tmp4, LSL #16 ;// |t4|t2| + PKHBT tmp4, tmp4, tmp6, LSL #16 ;// |t6|t4| + + SMUAD tmp2, tmp2, valY ;// t2=(t2*valY + t4*yFrac) + MLA tmp5, tmp1, valX, c32 ;// t5=t1*valX+32 + MLA tmp5, tmp2, xFrac, tmp5 ;// t5=t2*xFrac+t5 + + SMUAD tmp4, tmp4, valY ;// t4=(t4*valY + t6*yFrac) + MLA tmp6, tmp3, valX, c32 ;// t3=t3*valX+32 + MLA tmp6, tmp4, xFrac, tmp6 ;// t6=t4*xFrac+t6 + + MOV tmp6, tmp6, LSR #6 ;// scale down + STRB tmp6, [mb, #8] ;// store pixel + MOV tmp5, tmp5, LSR #6 ;// scale down + STRB tmp5, [mb], #1 ;// store pixel + + ;// second + LDRB tmp1, [ptrA, #1]! + LDRB tmp3, [ptrA, width] + LDRB tmp5, [ptrA, width, LSL #1] + + PKHBT tmp1, tmp1, tmp3, LSL #16 ;// |t3|t1| + PKHBT tmp3, tmp3, tmp5, LSL #16 ;// |t5|t3| + + SMUAD tmp1, tmp1, valY ;// t1=(t1*valY + t3*yFrac) + MLA tmp5, tmp1, xFrac, c32 ;// t1=t1*xFrac+32 + MLA tmp5, tmp2, valX, tmp5 ;// t5=t2*valX+t5 + + SMUAD tmp3, tmp3, valY ;// t3=(t3*valY + t5*yFrac) + MLA tmp6, tmp3, xFrac, c32 ;// t3=t3*xFrac+32 + MLA tmp6, tmp4, valX, tmp6 ;// t6=t4*valX+t6 + + MOV tmp6, tmp6, LSR #6 ;// scale down + STRB tmp6, [mb, #8] ;// store pixel + MOV tmp5, tmp5, LSR #6 ;// scale down + STRB tmp5, [mb], #1 ;// store pixel + + SUBS count, count, #2<<28 + BCS loop1_x + + AND tmp2, count, #0x00F00000 + + ADDS mb, mb, #16 + SBC mb, mb, tmp2, LSR #20 + ADD ptrA, ptrA, width, LSL #1 + SBC ptrA, ptrA, tmp2, LSR #20 + + ADDS count, count, #0xE << 24 + BGE loop1_y + + ;/////////////////////////////////////////////////////////////////////////// + ;// Cr + ;/////////////////////////////////////////////////////////////////////////// + LDR height, [sp,#0xfc] ;// height + LDR ref, [sp, #0xc4] ;// ref + LDR tmp1, [sp, #0xd0] ;// y0 + LDR tmp2, [sp, #0xcc] ;// x0 + LDR mb, [sp, #0xc8] ;// predPartChroma + + ADD tmp1, height, tmp1 + MLA tmp3, tmp1, width, tmp2 + ADD ptrA, ref, tmp3 + ADD mb, mb, #64 + + AND count, count, #0x00FFFFFF + AND tmp1, count, #0x000F0000 + ADD count, count, tmp1, LSL #8 + AND tmp2, count, #0x00F00000 + + ;// 2x2 pels per iteration + ;// bilinear vertical and horizontal interpolation +loop2_y + LDRB tmp1, [ptrA] + LDRB tmp3, [ptrA, width] + LDRB tmp5, [ptrA, width, LSL #1] + + PKHBT tmp1, tmp1, tmp3, LSL #16 ;// |t3|t1| + PKHBT tmp3, tmp3, tmp5, LSL #16 ;// |t5|t3| + + SMUAD tmp1, tmp1, valY ;// t1=(t1*valY + t3*yFrac) + SMUAD tmp3, tmp3, valY ;// t3=(t3*valY + t5*yFrac) + + ADD count, count, tmp2, LSL #8 +loop2_x + ;// first + LDRB tmp2, [ptrA, #1]! + LDRB tmp4, [ptrA, width] + LDRB tmp6, [ptrA, width, LSL #1] + + PKHBT tmp2, tmp2, tmp4, LSL #16 ;// |t4|t2| + PKHBT tmp4, tmp4, tmp6, LSL #16 ;// |t6|t4| + + SMUAD tmp2, tmp2, valY ;// t2=(t2*valY + t4*yFrac) + MLA tmp5, tmp1, valX, c32 ;// t5=t1*valX+32 + MLA tmp5, tmp2, xFrac, tmp5 ;// t5=t2*xFrac+t5 + + SMUAD tmp4, tmp4, valY ;// t4=(t4*valY + t6*yFrac) + MLA tmp6, tmp3, valX, c32 ;// t3=t3*valX+32 + MLA tmp6, tmp4, xFrac, tmp6 ;// t6=t4*xFrac+t6 + + MOV tmp6, tmp6, LSR #6 ;// scale down + STRB tmp6, [mb, #8] ;// store pixel + MOV tmp5, tmp5, LSR #6 ;// scale down + STRB tmp5, [mb], #1 ;// store pixel + + ;// second + LDRB tmp1, [ptrA, #1]! + LDRB tmp3, [ptrA, width] + LDRB tmp5, [ptrA, width, LSL #1] + + PKHBT tmp1, tmp1, tmp3, LSL #16 ;// |t3|t1| + PKHBT tmp3, tmp3, tmp5, LSL #16 ;// |t5|t3| + + SMUAD tmp1, tmp1, valY ;// t1=(t1*valY + t3*yFrac) + MLA tmp5, tmp1, xFrac, c32 ;// t1=t1*xFrac+32 + MLA tmp5, tmp2, valX, tmp5 ;// t5=t2*valX+t5 + + SMUAD tmp3, tmp3, valY ;// t3=(t3*valY + t5*yFrac) + MLA tmp6, tmp3, xFrac, c32 ;// t3=t3*xFrac+32 + MLA tmp6, tmp4, valX, tmp6 ;// t6=t4*valX+t6 + + MOV tmp6, tmp6, LSR #6 ;// scale down + STRB tmp6, [mb, #8] ;// store pixel + MOV tmp5, tmp5, LSR #6 ;// scale down + STRB tmp5, [mb], #1 ;// store pixel + + SUBS count, count, #2<<28 + BCS loop2_x + + AND tmp2, count, #0x00F00000 + + ADDS mb, mb, #16 + SBC mb, mb, tmp2, LSR #20 + ADD ptrA, ptrA, width, LSL #1 + SBC ptrA, ptrA, tmp2, LSR #20 + + ADDS count, count, #0xE << 24 + BGE loop2_y + + ADD sp,sp,#0xd4 + LDMFD sp!,{r4-r11,pc} + + END diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_chroma_ver.s b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_chroma_ver.s new file mode 100755 index 0000000..af9df1b --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_chroma_ver.s @@ -0,0 +1,288 @@ +; Copyright (C) 2009 The Android Open Source Project +; +; Licensed under the Apache License, Version 2.0 (the "License"); +; you may not use this file except in compliance with the License. +; You may obtain a copy of the License at +; +; http://www.apache.org/licenses/LICENSE-2.0 +; +; Unless required by applicable law or agreed to in writing, software +; distributed under the License is distributed on an "AS IS" BASIS, +; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +; See the License for the specific language governing permissions and +; limitations under the License. + +;------------------------------------------------------------------------------- +;-- +;-- Abstract : ARMv6 optimized version of h264bsdInterpolateChromaVer function +;-- +;------------------------------------------------------------------------------- + + + IF :DEF: H264DEC_WINASM + ;// We dont use REQUIRE8 and PRESERVE8 for winasm + ELSE + REQUIRE8 + PRESERVE8 + ENDIF + + AREA |.text|, CODE + +;// h264bsdInterpolateChromaVer register allocation + +ref RN 0 +ptrA RN 0 + +mb RN 1 +block RN 1 + +x0 RN 2 +count RN 2 + +y0 RN 3 +valY RN 3 + +width RN 4 + +height RN 5 +tmp7 RN 5 + +chrPW RN 6 +tmp8 RN 6 + +tmp1 RN 7 + +tmp2 RN 8 + +tmp3 RN 9 + +tmp4 RN 10 + +tmp5 RN 11 +chrPH RN 11 + +tmp6 RN 12 + +c32 RN 14 +yFrac RN 14 + +;// Function exports and imports + + IMPORT h264bsdFillBlock + + EXPORT h264bsdInterpolateChromaVer + +;// Function arguments +;// +;// u8 *ref, : 0xc4 +;// u8 *predPartChroma, : 0xc8 +;// i32 x0, : 0xcc +;// i32 y0, : 0xd0 +;// u32 width, : 0xf8 +;// u32 height, : 0xfc +;// u32 yFrac, : 0x100 +;// u32 chromaPartWidth, : 0x104 +;// u32 chromaPartHeight : 0x108 + +h264bsdInterpolateChromaVer + STMFD sp!, {r0-r11,lr} + SUB sp, sp, #0xc4 + + LDR chrPW, [sp, #0x104] ;// chromaPartWidth + LDR width, [sp, #0xf8] ;// width + CMP x0, #0 + BLT do_fill + + ADD tmp1, x0, chrPW ;// tmp1 = x0+ chromaPartWidth + CMP tmp1, width ;// x0+chromaPartWidth > width + BHI do_fill + + CMP y0, #0 + BLT do_fill + LDR chrPH, [sp, #0x108] ;// chromaPartHeight + LDR height, [sp, #0xfc] ;// height + ADD tmp1, y0, chrPH ;// tmp1 = y0 + chromaPartHeight + ADD tmp1, tmp1, #1 ;// tmp1 = y0 + chromaPartHeight + 1 + CMP tmp1, height + BLS skip_fill + +do_fill + LDR chrPH, [sp, #0x108] ;// chromaPartHeight + LDR height, [sp, #0xfc] ;// height + ADD tmp1, chrPH, #1 ;// tmp1 = chromaPartHeight+1 + MOV tmp2, chrPW ;// tmp2 = chromaPartWidth + STMIA sp,{width,height,chrPW,tmp1,tmp2} + ADD block, sp, #0x1c ;// block + BL h264bsdFillBlock + + LDR x0, [sp, #0xcc] + LDR y0, [sp, #0xd0] + LDR ref, [sp, #0xc4] ;// ref + STMIA sp,{width,height,chrPW,tmp1,tmp2} + ADD block, sp, #0x1c ;// block + MLA ref, height, width, ref ;// ref += width * height; + MLA block, chrPW, tmp1, block;// block + (chromaPW)*(chromaPH+1) + BL h264bsdFillBlock + + MOV x0, #0 ;// x0 = 0 + MOV y0, #0 ;// y0 = 0 + STR x0, [sp, #0xcc] + STR y0, [sp, #0xd0] + ADD ref, sp, #0x1c ;// ref = block + STR ref, [sp, #0xc4] ;// ref + + STR tmp1, [sp, #0xfc] ;// height + STR chrPW, [sp, #0xf8] ;// width + MOV width, chrPW + +skip_fill + MLA tmp3, y0, width, x0 ;// tmp3 = y0*width+x0 + LDR yFrac, [sp, #0x100] ;// yFrac + ADD ptrA, ref, tmp3 ;// ptrA = ref + y0*width+x0 + RSB valY, yFrac, #8 ;// valY = 8-yFrac + + LDR mb, [sp, #0xc8] ;// predPartChroma + + + ;// pack values to count register + ;// [31:28] loop_x (chromaPartWidth-1) + ;// [27:24] loop_y (chromaPartHeight-1) + ;// [23:20] chromaPartWidth-1 + ;// [19:16] chromaPartHeight-1 + ;// [15:00] nothing + + SUB tmp2, chrPH, #1 ;// chromaPartHeight-1 + SUB tmp1, chrPW, #1 ;// chromaPartWidth-1 + ADD count, count, tmp2, LSL #16 ;// chromaPartHeight-1 + ADD count, count, tmp2, LSL #24 ;// loop_y + ADD count, count, tmp1, LSL #20 ;// chromaPartWidth-1 + AND tmp2, count, #0x00F00000 ;// loop_x + PKHBT valY, valY, yFrac, LSL #16 ;// |yFrac|valY | + MOV valY, valY, LSL #3 ;// multiply by 8 in advance + MOV c32, #32 + + + ;/////////////////////////////////////////////////////////////////////////// + ;// Cb + ;/////////////////////////////////////////////////////////////////////////// + + ;// 2x2 pels per iteration + ;// bilinear vertical interpolation + +loop1_y + ADD count, count, tmp2, LSL #8 +loop1_x + ;// Process 2x2 block + LDRB tmp2, [ptrA,width] ;// 2 row, 1 col + LDRB tmp3, [ptrA,width, LSL #1] ;// 3 row, 1 col + LDRB tmp1, [ptrA],#1 ;// 1 row, 1 col + + LDRB tmp5, [ptrA,width] ;// 2 row, 2 col + LDRB tmp6, [ptrA,width, LSL #1] ;// 3 row, 2 col + LDRB tmp4, [ptrA],#1 ;// 1 row, 2 col + + PKHBT tmp1, tmp1, tmp2, LSL #16 ;// |B|A| + PKHBT tmp2, tmp2, tmp3, LSL #16 ;// |C|B| + PKHBT tmp4, tmp4, tmp5, LSL #16 ;// |B|A| + + SMLAD tmp7, tmp2, valY, c32 ;// multiply + PKHBT tmp5, tmp5, tmp6, LSL #16 ;// |C|B| + SMLAD tmp2, tmp1, valY, c32 ;// multiply + SMLAD tmp8, tmp5, valY, c32 ;// multiply + SMLAD tmp5, tmp4, valY, c32 ;// multiply + + MOV tmp7, tmp7, LSR #6 ;// scale down + STRB tmp7, [mb,#8] ;// store row 2 col 1 + MOV tmp2, tmp2, LSR #6 ;// scale down + STRB tmp2, [mb],#1 ;// store row 1 col 1 + + MOV tmp8, tmp8, LSR #6 ;// scale down + STRB tmp8, [mb,#8] ;// store row 2 col 2 + MOV tmp5, tmp5, LSR #6 ;// scale down + STRB tmp5, [mb],#1 ;// store row 1 col 2 + + + SUBS count, count, #2<<28 + BCS loop1_x + + AND tmp2, count, #0x00F00000 + + ADDS mb, mb, #16 + SBC mb, mb, tmp2, LSR #20 + ADD ptrA, ptrA, width, LSL #1 + SBC ptrA, ptrA, tmp2, LSR #20 + + ADDS count, count, #0xE << 24 + BGE loop1_y + + ;/////////////////////////////////////////////////////////////////////////// + ;// Cr + ;/////////////////////////////////////////////////////////////////////////// + LDR height, [sp,#0xfc] ;// height + LDR ref, [sp, #0xc4] ;// ref + LDR tmp1, [sp, #0xd0] ;// y0 + LDR tmp2, [sp, #0xcc] ;// x0 + LDR mb, [sp, #0xc8] ;// predPartChroma + + ADD tmp1, height, tmp1 + MLA tmp3, tmp1, width, tmp2 + ADD ptrA, ref, tmp3 + ADD mb, mb, #64 + + AND count, count, #0x00FFFFFF + AND tmp1, count, #0x000F0000 + ADD count, count, tmp1, LSL #8 + AND tmp2, count, #0x00F00000 + + ;// 2x2 pels per iteration + ;// bilinear vertical interpolation +loop2_y + ADD count, count, tmp2, LSL #8 +loop2_x + ;// Process 2x2 block + LDRB tmp2, [ptrA,width] ;// 2 row, 1 col + LDRB tmp3, [ptrA,width, LSL #1] ;// 3 row, 1 col + LDRB tmp1, [ptrA],#1 ;// 1 row, 1 col + + LDRB tmp5, [ptrA,width] ;// 2 row, 2 col + LDRB tmp6, [ptrA,width, LSL #1] ;// 3 row, 2 col + LDRB tmp4, [ptrA],#1 ;// 1 row, 2 col + + PKHBT tmp1, tmp1, tmp2, LSL #16 ;// |B|A| + PKHBT tmp2, tmp2, tmp3, LSL #16 ;// |C|B| + PKHBT tmp4, tmp4, tmp5, LSL #16 ;// |B|A| + + SMLAD tmp7, tmp2, valY, c32 ;// multiply + PKHBT tmp5, tmp5, tmp6, LSL #16 ;// |C|B| + SMLAD tmp2, tmp1, valY, c32 ;// multiply + SMLAD tmp8, tmp5, valY, c32 ;// multiply + SMLAD tmp5, tmp4, valY, c32 ;// multiply + + MOV tmp7, tmp7, LSR #6 ;// scale down + STRB tmp7, [mb,#8] ;// store row 2 col 1 + MOV tmp2, tmp2, LSR #6 ;// scale down + STRB tmp2, [mb],#1 ;// store row 1 col 1 + + MOV tmp8, tmp8, LSR #6 ;// scale down + STRB tmp8, [mb,#8] ;// store row 2 col 2 + MOV tmp5, tmp5, LSR #6 ;// scale down + STRB tmp5, [mb],#1 ;// store row 1 col 2 + + + SUBS count, count, #2<<28 + BCS loop2_x + + AND tmp2, count, #0x00F00000 + + ADDS mb, mb, #16 + SBC mb, mb, tmp2, LSR #20 + ADD ptrA, ptrA, width, LSL #1 + SBC ptrA, ptrA, tmp2, LSR #20 + + ADDS count, count, #0xE << 24 + BGE loop2_y + + ADD sp,sp,#0xd4 + LDMFD sp!, {r4-r11,pc} + + END diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_hor_half.s b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_hor_half.s new file mode 100755 index 0000000..93968b6 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_hor_half.s @@ -0,0 +1,251 @@ +; Copyright (C) 2009 The Android Open Source Project +; +; Licensed under the Apache License, Version 2.0 (the "License"); +; you may not use this file except in compliance with the License. +; You may obtain a copy of the License at +; +; http://www.apache.org/licenses/LICENSE-2.0 +; +; Unless required by applicable law or agreed to in writing, software +; distributed under the License is distributed on an "AS IS" BASIS, +; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +; See the License for the specific language governing permissions and +; limitations under the License. + +;------------------------------------------------------------------------------- +;-- +;-- Abstract : ARMv6 optimized version of h264bsdInterpolateHorHalf function +;-- +;------------------------------------------------------------------------------- + + + IF :DEF: H264DEC_WINASM + ;// We dont use REQUIRE8 and PRESERVE8 for winasm + ELSE + REQUIRE8 + PRESERVE8 + ENDIF + + AREA |.text|, CODE + +;// h264bsdInterpolateHorHalf register allocation + +ref RN 0 + +mb RN 1 +buff RN 1 + +count RN 2 +x0 RN 2 + +y0 RN 3 +x_2_0 RN 3 + +width RN 4 +x_3_1 RN 4 + +height RN 5 +x_6_4 RN 5 + +partW RN 6 +x_7_5 RN 6 + +partH RN 7 +tmp1 RN 7 + +tmp2 RN 8 + +tmp3 RN 9 + +tmp4 RN 10 + +mult_20_01 RN 11 +mult_20_m5 RN 12 + +plus16 RN 14 + + +;// function exports and imports + + IMPORT h264bsdFillBlock + + EXPORT h264bsdInterpolateHorHalf + +;// Horizontal filter approach +;// +;// Basic idea in horizontal filtering is to adjust coefficients +;// like below. Calculation is done with 16-bit maths. +;// +;// Reg x_2_0 x_3_1 x_6_4 x_7_5 x_2_0 +;// [ 2 0 ] [ 3 1 ] [ 6 4 ] [ 7 5 ] [ 10 8 ] ... +;// y_0 = 20 1 20 -5 -5 1 +;// y_1 = -5 20 1 1 20 -5 +;// y_2 = 1 -5 -5 20 1 20 +;// y_3 = 1 20 -5 -5 20 1 + + +h264bsdInterpolateHorHalf + STMFD sp!, {r0-r11, lr} + SUB sp, sp, #0x1e4 + + CMP x0, #0 + BLT do_fill ;// (x0 < 0) + LDR partW, [sp,#0x220] ;// partWidth + ADD tmp4, x0, partW ;// (x0+partWidth) + ADD tmp4, tmp4, #5 ;// (y0+partW+5) + LDR width, [sp,#0x218] ;// width + CMP tmp4, width + BHI do_fill ;// (x0+partW)>width + + CMP y0, #0 + BLT do_fill ;// (y0 < 0) + LDR partH, [sp,#0x224] ;// partHeight + ADD tmp2, y0, partH ;// (y0+partHeight) + LDR height, [sp,#0x21c] ;// height + CMP tmp2, height + BLS skip_fill ;// no overfill needed + + +do_fill + LDR partH, [sp,#0x224] ;// partHeight + LDR height, [sp,#0x21c] ;// height + LDR partW, [sp,#0x220] ;// partWidth + ADD tmp4, partW, #5 ;// tmp4 = partW + 5; + STMIB sp, {height, tmp4} ;// sp+4 = height, sp+8 = partWidth+5 + STR partH, [sp,#0xc] ;// sp+c = partHeight + STR tmp4, [sp,#0x10] ;// sp+10 = partWidth+5 + LDR width, [sp,#0x218] ;// width + STR width, [sp,#0] ;// sp+0 = width + ADD buff, sp, #0x28 ;// buff = p1[21*21/4+1] + BL h264bsdFillBlock + + MOV x0, #0 + STR x0,[sp,#0x1ec] ;// x0 = 0 + STR x0,[sp,#0x1f0] ;// y0 = 0 + ADD ref,sp,#0x28 ;// ref = p1 + STR tmp4, [sp,#0x218] ;// width = partWidth+5 + + +skip_fill + LDR x0 ,[sp,#0x1ec] ;// x0 + LDR y0 ,[sp,#0x1f0] ;// y0 + LDR width, [sp,#0x218] ;// width + MLA tmp2, width, y0, x0 ;// y0*width+x0 + ADD ref, ref, tmp2 ;// ref += y0*width+x0 + ADD ref, ref, #8 ;// ref = ref+8 + LDR mb, [sp, #0x1e8] ;// mb + + ;// pack values to count register + ;// [31:28] loop_x (partWidth-1) + ;// [27:24] loop_y (partHeight-1) + ;// [23:20] partWidth-1 + ;// [19:16] partHeight-1 + ;// [15:00] width + MOV count, width + SUB partW, partW, #1; + SUB partH, partH, #1; + ADD tmp2, partH, partW, LSL #4 + ADD count, count, tmp2, LSL #16 + + + LDR mult_20_01, = 0x00140001 + LDR mult_20_m5, = 0x0014FFFB + MOV plus16, #16 + AND tmp1, count, #0x000F0000 ;// partHeight-1 + AND tmp3, count, #0x00F00000 ;// partWidth-1 + ADD count, count, tmp1, LSL #8 +loop_y + LDR x_3_1, [ref, #-8] + ADD count, count, tmp3, LSL #8 + LDR x_7_5, [ref, #-4] + UXTB16 x_2_0, x_3_1 + UXTB16 x_3_1, x_3_1, ROR #8 + UXTB16 x_6_4, x_7_5 + +loop_x + UXTB16 x_7_5, x_7_5, ROR #8 + + SMLAD tmp1, x_2_0, mult_20_01, plus16 + SMLATB tmp3, x_2_0, mult_20_01, plus16 + SMLATB tmp2, x_2_0, mult_20_m5, plus16 + SMLATB tmp4, x_3_1, mult_20_01, plus16 + + SMLAD tmp1, x_3_1, mult_20_m5, tmp1 + SMLATB tmp3, x_3_1, mult_20_m5, tmp3 + SMLAD tmp2, x_3_1, mult_20_01, tmp2 + LDR x_3_1, [ref], #4 + SMLAD tmp4, x_6_4, mult_20_m5, tmp4 + + SMLABB tmp1, x_6_4, mult_20_m5, tmp1 + SMLADX tmp3, x_6_4, mult_20_m5, tmp3 + SMLADX tmp2, x_6_4, mult_20_01, tmp2 + SMLADX tmp4, x_7_5, mult_20_m5, tmp4 + + SMLABB tmp1, x_7_5, mult_20_01, tmp1 + UXTB16 x_2_0, x_3_1 + SMLABB tmp2, x_7_5, mult_20_m5, tmp2 + SMLADX tmp3, x_7_5, mult_20_01, tmp3 + SMLABB tmp4, x_2_0, mult_20_01, tmp4 + + MOV tmp2, tmp2, ASR #5 + MOV tmp1, tmp1, ASR #5 + PKHBT tmp2, tmp2, tmp4, LSL #(16-5) + PKHBT tmp1, tmp1, tmp3, LSL #(16-5) + USAT16 tmp2, #8, tmp2 + USAT16 tmp1, #8, tmp1 + + SUBS count, count, #4<<28 + ORR tmp1, tmp1, tmp2, LSL #8 + STR tmp1, [mb], #4 + BCC next_y + + UXTB16 x_3_1, x_3_1, ROR #8 + + SMLAD tmp1, x_6_4, mult_20_01, plus16 + SMLATB tmp3, x_6_4, mult_20_01, plus16 + SMLATB tmp2, x_6_4, mult_20_m5, plus16 + SMLATB tmp4, x_7_5, mult_20_01, plus16 + + SMLAD tmp1, x_7_5, mult_20_m5, tmp1 + SMLATB tmp3, x_7_5, mult_20_m5, tmp3 + SMLAD tmp2, x_7_5, mult_20_01, tmp2 + LDR x_7_5, [ref], #4 + SMLAD tmp4, x_2_0, mult_20_m5, tmp4 + + SMLABB tmp1, x_2_0, mult_20_m5, tmp1 + SMLADX tmp3, x_2_0, mult_20_m5, tmp3 + SMLADX tmp2, x_2_0, mult_20_01, tmp2 + SMLADX tmp4, x_3_1, mult_20_m5, tmp4 + + SMLABB tmp1, x_3_1, mult_20_01, tmp1 + UXTB16 x_6_4, x_7_5 + SMLABB tmp2, x_3_1, mult_20_m5, tmp2 + SMLADX tmp3, x_3_1, mult_20_01, tmp3 + SMLABB tmp4, x_6_4, mult_20_01, tmp4 + + MOV tmp2, tmp2, ASR #5 + MOV tmp1, tmp1, ASR #5 + PKHBT tmp2, tmp2, tmp4, LSL #(16-5) + PKHBT tmp1, tmp1, tmp3, LSL #(16-5) + USAT16 tmp2, #8, tmp2 + USAT16 tmp1, #8, tmp1 + + SUBS count, count, #4<<28 + ORR tmp1, tmp1, tmp2, LSL #8 + STR tmp1, [mb], #4 + BCS loop_x + +next_y + AND tmp3, count, #0x00F00000 ;// partWidth-1 + SMLABB ref, count, mult_20_01, ref ;// +width + ADDS mb, mb, #16 ;// +16, Carry=0 + SBC mb, mb, tmp3, LSR #20 ;// -(partWidth-1)-1 + SBC ref, ref, tmp3, LSR #20 ;// -(partWidth-1)-1 + ADDS count, count, #(1<<28)-(1<<24) + BGE loop_y + + ADD sp,sp,#0x1f4 + LDMFD sp!, {r4-r11, pc} + + END + diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_hor_quarter.s b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_hor_quarter.s new file mode 100755 index 0000000..de243d4 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_hor_quarter.s @@ -0,0 +1,273 @@ +; Copyright (C) 2009 The Android Open Source Project +; +; Licensed under the Apache License, Version 2.0 (the "License"); +; you may not use this file except in compliance with the License. +; You may obtain a copy of the License at +; +; http://www.apache.org/licenses/LICENSE-2.0 +; +; Unless required by applicable law or agreed to in writing, software +; distributed under the License is distributed on an "AS IS" BASIS, +; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +; See the License for the specific language governing permissions and +; limitations under the License. + +;------------------------------------------------------------------------------- +;-- +;-- Abstract : ARMv6 optimized version of h264bsdInterpolateHorQuarter function +;-- +;------------------------------------------------------------------------------- + + + IF :DEF: H264DEC_WINASM + ;// We dont use REQUIRE8 and PRESERVE8 for winasm + ELSE + REQUIRE8 + PRESERVE8 + ENDIF + + AREA |.text|, CODE + +;// h264bsdInterpolateHorQuarter register allocation + +ref RN 0 + +mb RN 1 +buff RN 1 + +count RN 2 +x0 RN 2 + +y0 RN 3 +x_2_0 RN 3 + +width RN 4 +x_3_1 RN 4 + +height RN 5 +x_6_4 RN 5 + +partW RN 6 +x_7_5 RN 6 + +partH RN 7 +tmp1 RN 7 + +tmp2 RN 8 + +tmp3 RN 9 + +tmp4 RN 10 + +mult_20_01 RN 11 + +mult_20_m5 RN 12 + +plus16 RN 14 + + +;// function exports and imports + + IMPORT h264bsdFillBlock + + EXPORT h264bsdInterpolateHorQuarter + + +;// Horizontal filter approach +;// +;// Basic idea in horizontal filtering is to adjust coefficients +;// like below. Calculation is done with 16-bit maths. +;// +;// Reg x_2_0 x_3_1 x_6_4 x_7_5 x_2_0 +;// [ 2 0 ] [ 3 1 ] [ 6 4 ] [ 7 5 ] [ 10 8 ] ... +;// y_0 = 20 1 20 -5 -5 1 +;// y_1 = -5 20 1 1 20 -5 +;// y_2 = 1 -5 -5 20 1 20 +;// y_3 = 1 20 -5 -5 20 1 + + +h264bsdInterpolateHorQuarter + STMFD sp!, {r0-r11, lr} + SUB sp, sp, #0x1e4 + + CMP x0, #0 + BLT do_fill ;// (x0 < 0) + LDR partW, [sp,#0x220] ;// partWidth + ADD tmp4, x0, partW ;// (x0+partWidth) + ADD tmp4, tmp4, #5 ;// (y0+partW+5) + LDR width, [sp,#0x218] ;// width + CMP tmp4, width + BHI do_fill ;// (x0+partW)>width + + CMP y0, #0 + BLT do_fill ;// (y0 < 0) + LDR partH, [sp,#0x224] ;// partHeight + ADD tmp2, y0, partH ;// (y0+partHeight) + LDR height, [sp,#0x21c] ;// height + CMP tmp2, height + BLS skip_fill ;// no overfill needed + + +do_fill + LDR partH, [sp,#0x224] ;// partHeight + LDR height, [sp,#0x21c] ;// height + LDR partW, [sp,#0x220] ;// partWidth + ADD tmp4, partW, #5 ;// tmp4 = partW + 5; + STMIB sp, {height, tmp4} ;// sp+4 = height, sp+8 = partWidth+5 + STR partH, [sp,#0xc] ;// sp+c = partHeight + STR tmp4, [sp,#0x10] ;// sp+10 = partWidth+5 + LDR width, [sp,#0x218] ;// width + STR width, [sp,#0] ;// sp+0 = width + ADD buff, sp, #0x28 ;// buff = p1[21*21/4+1] + BL h264bsdFillBlock + + MOV x0, #0 + STR x0,[sp,#0x1ec] ;// x0 = 0 + STR x0,[sp,#0x1f0] ;// y0 = 0 + ADD ref,sp,#0x28 ;// ref = p1 + STR tmp4, [sp,#0x218] ;// width = partWidth+5 + + +skip_fill + LDR x0 ,[sp,#0x1ec] ;// x0 + LDR y0 ,[sp,#0x1f0] ;// y0 + LDR width, [sp,#0x218] ;// width + MLA tmp2, width, y0, x0 ;// y0*width+x0 + ADD ref, ref, tmp2 ;// ref += y0*width+x0 + ADD ref, ref, #8 ;// ref = ref+8 + LDR mb, [sp, #0x1e8] ;// mb + + ;// pack values to count register + ;// [31:28] loop_x (partWidth-1) + ;// [27:24] loop_y (partHeight-1) + ;// [23:20] partWidth-1 + ;// [19:16] partHeight-1 + ;// [15:00] width + MOV count, width + SUB partW, partW, #1; + SUB partH, partH, #1; + ADD tmp2, partH, partW, LSL #4 + ADD count, count, tmp2, LSL #16 + + + LDR mult_20_01, = 0x00140001 + LDR mult_20_m5, = 0x0014FFFB + MOV plus16, #16 + AND tmp1, count, #0x000F0000 ;// partHeight-1 + AND tmp3, count, #0x00F00000 ;// partWidth-1 + ADD count, count, tmp1, LSL #8 +loop_y + LDR x_3_1, [ref, #-8] + ADD count, count, tmp3, LSL #8 + LDR x_7_5, [ref, #-4] + UXTB16 x_2_0, x_3_1 + UXTB16 x_3_1, x_3_1, ROR #8 + UXTB16 x_6_4, x_7_5 + +loop_x + UXTB16 x_7_5, x_7_5, ROR #8 + + SMLAD tmp1, x_2_0, mult_20_01, plus16 + SMLATB tmp3, x_2_0, mult_20_01, plus16 + SMLATB tmp2, x_2_0, mult_20_m5, plus16 + SMLATB tmp4, x_3_1, mult_20_01, plus16 + + SMLAD tmp1, x_3_1, mult_20_m5, tmp1 + SMLATB tmp3, x_3_1, mult_20_m5, tmp3 + SMLAD tmp2, x_3_1, mult_20_01, tmp2 + LDR x_3_1, [ref], #4 + SMLAD tmp4, x_6_4, mult_20_m5, tmp4 + + SMLABB tmp1, x_6_4, mult_20_m5, tmp1 + SMLADX tmp3, x_6_4, mult_20_m5, tmp3 + SMLADX tmp2, x_6_4, mult_20_01, tmp2 + SMLADX tmp4, x_7_5, mult_20_m5, tmp4 + + SMLABB tmp1, x_7_5, mult_20_01, tmp1 + UXTB16 x_2_0, x_3_1 + SMLABB tmp2, x_7_5, mult_20_m5, tmp2 + SMLADX tmp3, x_7_5, mult_20_01, tmp3 + SMLABB tmp4, x_2_0, mult_20_01, tmp4 + + MOV tmp2, tmp2, ASR #5 + MOV tmp1, tmp1, ASR #5 + PKHBT tmp2, tmp2, tmp4, LSL #(16-5) + PKHBT tmp1, tmp1, tmp3, LSL #(16-5) + LDR tmp4, [sp, #0x228] + USAT16 tmp2, #8, tmp2 + USAT16 tmp1, #8, tmp1 + SUB tmp4, tmp4, #10 + + SUBS count, count, #4<<28 + LDR tmp3, [ref, tmp4] + ORR tmp1, tmp1, tmp2, LSL #8 + +;// quarter pel position + LDR tmp2, = 0x80808080 + MVN tmp3, tmp3 + UHSUB8 tmp1, tmp1, tmp3 + EOR tmp1, tmp1, tmp2 + STR tmp1, [mb], #4 + + BCC next_y + + UXTB16 x_3_1, x_3_1, ROR #8 + + SMLAD tmp1, x_6_4, mult_20_01, plus16 + SMLATB tmp3, x_6_4, mult_20_01, plus16 + SMLATB tmp2, x_6_4, mult_20_m5, plus16 + SMLATB tmp4, x_7_5, mult_20_01, plus16 + + SMLAD tmp1, x_7_5, mult_20_m5, tmp1 + SMLATB tmp3, x_7_5, mult_20_m5, tmp3 + SMLAD tmp2, x_7_5, mult_20_01, tmp2 + LDR x_7_5, [ref], #4 + SMLAD tmp4, x_2_0, mult_20_m5, tmp4 + + SMLABB tmp1, x_2_0, mult_20_m5, tmp1 + SMLADX tmp3, x_2_0, mult_20_m5, tmp3 + SMLADX tmp2, x_2_0, mult_20_01, tmp2 + SMLADX tmp4, x_3_1, mult_20_m5, tmp4 + + SMLABB tmp1, x_3_1, mult_20_01, tmp1 + UXTB16 x_6_4, x_7_5 + SMLABB tmp2, x_3_1, mult_20_m5, tmp2 + SMLADX tmp3, x_3_1, mult_20_01, tmp3 + SMLABB tmp4, x_6_4, mult_20_01, tmp4 + + MOV tmp2, tmp2, ASR #5 + MOV tmp1, tmp1, ASR #5 + PKHBT tmp2, tmp2, tmp4, LSL #(16-5) + PKHBT tmp1, tmp1, tmp3, LSL #(16-5) + LDR tmp4, [sp, #0x228] + USAT16 tmp2, #8, tmp2 + USAT16 tmp1, #8, tmp1 + SUB tmp4, tmp4, #10 + + SUBS count, count, #4<<28 + LDR tmp3, [ref, tmp4] + ORR tmp1, tmp1, tmp2, LSL #8 + +;// quarter pel + LDR tmp2, = 0x80808080 + MVN tmp3, tmp3 + UHSUB8 tmp1, tmp1, tmp3 + EOR tmp1, tmp1, tmp2 + + STR tmp1, [mb], #4 + BCS loop_x + +next_y + AND tmp3, count, #0x00F00000 ;// partWidth-1 + SMLABB ref, count, mult_20_01, ref ;// +width + ADDS mb, mb, #16 ;// +16, Carry=0 + SBC mb, mb, tmp3, LSR #20 ;// -(partWidth-1)-1 + SBC ref, ref, tmp3, LSR #20 ;// -(partWidth-1)-1 + ADDS count, count, #(1<<28)-(1<<24) + BGE loop_y + + ADD sp,sp,#0x1f4 + LDMFD sp!, {r4-r11, pc} + + END + diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_hor_ver_quarter.s b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_hor_ver_quarter.s new file mode 100755 index 0000000..1c79b39 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_hor_ver_quarter.s @@ -0,0 +1,536 @@ +; Copyright (C) 2009 The Android Open Source Project +; +; Licensed under the Apache License, Version 2.0 (the "License"); +; you may not use this file except in compliance with the License. +; You may obtain a copy of the License at +; +; http://www.apache.org/licenses/LICENSE-2.0 +; +; Unless required by applicable law or agreed to in writing, software +; distributed under the License is distributed on an "AS IS" BASIS, +; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +; See the License for the specific language governing permissions and +; limitations under the License. + +;------------------------------------------------------------------------------- +;-- +;-- Abstract : ARMv6 optimized version of h264bsdInterpolateHorVerQuarter +;-- function +;-- +;------------------------------------------------------------------------------- + + + IF :DEF: H264DEC_WINASM + ;// We dont use REQUIRE8 and PRESERVE8 for winasm + ELSE + REQUIRE8 + PRESERVE8 + ENDIF + + AREA |.text|, CODE + +;// h264bsdInterpolateHorVerQuarter register allocation + +ref RN 0 + +mb RN 1 +buff RN 1 + +count RN 2 +x0 RN 2 + +y0 RN 3 +x_2_0 RN 3 +res RN 3 + +x_3_1 RN 4 +tmp1 RN 4 + +height RN 5 +x_6_4 RN 5 +tmp2 RN 5 + +partW RN 6 +x_7_5 RN 6 +tmp3 RN 6 + +partH RN 7 +tmp4 RN 7 + +tmp5 RN 8 + +tmp6 RN 9 + +tmpa RN 10 + +mult_20_01 RN 11 +tmpb RN 11 + +mult_20_m5 RN 12 +width RN 12 + +plus16 RN 14 + + +;// function exports and imports + + IMPORT h264bsdFillBlock + + EXPORT h264bsdInterpolateHorVerQuarter + +;// Horizontal filter approach +;// +;// Basic idea in horizontal filtering is to adjust coefficients +;// like below. Calculation is done with 16-bit maths. +;// +;// Reg x_2_0 x_3_1 x_6_4 x_7_5 x_2_0 +;// [ 2 0 ] [ 3 1 ] [ 6 4 ] [ 7 5 ] [ 10 8 ] ... +;// y_0 = 20 1 20 -5 -5 1 +;// y_1 = -5 20 1 1 20 -5 +;// y_2 = 1 -5 -5 20 1 20 +;// y_3 = 1 20 -5 -5 20 1 + + +h264bsdInterpolateHorVerQuarter + STMFD sp!, {r0-r11, lr} + SUB sp, sp, #0x1e4 + + CMP x0, #0 + BLT do_fill ;// (x0 < 0) + LDR partW, [sp,#0x220] ;// partWidth + LDR width, [sp,#0x218] ;// width + ADD tmpa, x0, partW ;// (x0+partWidth) + ADD tmpa, tmpa, #5 ;// (x0+partW+5) + CMP tmpa, width + BHI do_fill ;// (x0+partW)>width + + CMP y0, #0 + BLT do_fill ;// (y0 < 0) + LDR partH, [sp,#0x224] ;// partHeight + LDR height, [sp,#0x21c] ;// height + ADD tmp5, y0, partH ;// (y0+partHeight) + ADD tmp5, tmp5, #5 ;// (y0+partH+5) + CMP tmp5, height + BLS skip_fill ;// no overfill needed + + +do_fill + LDR partH, [sp,#0x224] ;// partHeight + LDR partW, [sp,#0x220] ;// partWidth + LDR height, [sp,#0x21c] ;// height + ADD tmp5, partH, #5 ;// tmp5 = partH + 5 + ADD tmpa, partW, #5 ;// tmpa = partW + 5 + STMIB sp, {height, tmpa} ;// sp+4 = height, sp+8 = partWidth+5 + LDR width, [sp,#0x218] ;// width + STR tmp5, [sp,#0xc] ;// sp+c = partHeight+5 + STR tmpa, [sp,#0x10] ;// sp+10 = partWidth+5 + STR width, [sp,#0] ;// sp+0 = width + ADD buff, sp, #0x28 ;// buff = p1[21*21/4+1] + BL h264bsdFillBlock + + MOV x0, #0 + STR x0,[sp,#0x1ec] ;// x0 = 0 + STR x0,[sp,#0x1f0] ;// y0 = 0 + ADD ref,sp,#0x28 ;// ref = p1 + STR tmpa, [sp,#0x218] ;// width = partWidth+5 + + +skip_fill + LDR x0 ,[sp,#0x1ec] ;// x0 + LDR y0 ,[sp,#0x1f0] ;// y0 + LDR width, [sp,#0x218] ;// width + LDR tmp6, [sp,#0x228] ;// horVerOffset + LDR mb, [sp, #0x1e8] ;// mb + MLA tmp5, width, y0, x0 ;// y0*width+x0 + ADD ref, ref, tmp5 ;// ref += y0*width+x0 + STR ref, [sp, #0x1e4] ;// store "ref" for vertical filtering + AND tmp6, tmp6, #2 ;// calculate ref for horizontal filter + MOV tmpa, #2 + ADD tmp6, tmpa, tmp6, LSR #1 + MLA ref, tmp6, width, ref + ADD ref, ref, #8 ;// ref = ref+8 + + ;// pack values to count register + ;// [31:28] loop_x (partWidth-1) + ;// [27:24] loop_y (partHeight-1) + ;// [23:20] partWidth-1 + ;// [19:16] partHeight-1 + ;// [15:00] width + MOV count, width + SUB partW, partW, #1; + SUB partH, partH, #1; + ADD tmp5, partH, partW, LSL #4 + ADD count, count, tmp5, LSL #16 + + + LDR mult_20_01, = 0x00140001 ;// constant multipliers + LDR mult_20_m5, = 0x0014FFFB ;// constant multipliers + MOV plus16, #16 ;// constant for add + AND tmp4, count, #0x000F0000 ;// partHeight-1 + AND tmp6, count, #0x00F00000 ;// partWidth-1 + ADD count, count, tmp4, LSL #8 ;// partH-1 to lower part of top byte + +;// HORIZONTAL PART + +loop_y_hor + LDR x_3_1, [ref, #-8] + ADD count, count, tmp6, LSL #8 ;// partW-1 to upper part of top byte + LDR x_7_5, [ref, #-4] + UXTB16 x_2_0, x_3_1 + UXTB16 x_3_1, x_3_1, ROR #8 + UXTB16 x_6_4, x_7_5 + +loop_x_hor + UXTB16 x_7_5, x_7_5, ROR #8 + + SMLAD tmp4, x_2_0, mult_20_01, plus16 + SMLATB tmp6, x_2_0, mult_20_01, plus16 + SMLATB tmp5, x_2_0, mult_20_m5, plus16 + SMLATB tmpa, x_3_1, mult_20_01, plus16 + + SMLAD tmp4, x_3_1, mult_20_m5, tmp4 + SMLATB tmp6, x_3_1, mult_20_m5, tmp6 + SMLAD tmp5, x_3_1, mult_20_01, tmp5 + LDR x_3_1, [ref], #4 + SMLAD tmpa, x_6_4, mult_20_m5, tmpa + + SMLABB tmp4, x_6_4, mult_20_m5, tmp4 + SMLADX tmp6, x_6_4, mult_20_m5, tmp6 + SMLADX tmp5, x_6_4, mult_20_01, tmp5 + SMLADX tmpa, x_7_5, mult_20_m5, tmpa + + SMLABB tmp4, x_7_5, mult_20_01, tmp4 + UXTB16 x_2_0, x_3_1 + SMLABB tmp5, x_7_5, mult_20_m5, tmp5 + SMLADX tmp6, x_7_5, mult_20_01, tmp6 + SMLABB tmpa, x_2_0, mult_20_01, tmpa + + MOV tmp5, tmp5, ASR #5 + MOV tmp4, tmp4, ASR #5 + PKHBT tmp5, tmp5, tmpa, LSL #(16-5) + PKHBT tmp4, tmp4, tmp6, LSL #(16-5) + USAT16 tmp5, #8, tmp5 + USAT16 tmp4, #8, tmp4 + + SUBS count, count, #4<<28 + ORR tmp4, tmp4, tmp5, LSL #8 + STR tmp4, [mb], #4 + BCC next_y_hor + + UXTB16 x_3_1, x_3_1, ROR #8 + + SMLAD tmp4, x_6_4, mult_20_01, plus16 + SMLATB tmp6, x_6_4, mult_20_01, plus16 + SMLATB tmp5, x_6_4, mult_20_m5, plus16 + SMLATB tmpa, x_7_5, mult_20_01, plus16 + + SMLAD tmp4, x_7_5, mult_20_m5, tmp4 + SMLATB tmp6, x_7_5, mult_20_m5, tmp6 + SMLAD tmp5, x_7_5, mult_20_01, tmp5 + LDR x_7_5, [ref], #4 + SMLAD tmpa, x_2_0, mult_20_m5, tmpa + + SMLABB tmp4, x_2_0, mult_20_m5, tmp4 + SMLADX tmp6, x_2_0, mult_20_m5, tmp6 + SMLADX tmp5, x_2_0, mult_20_01, tmp5 + SMLADX tmpa, x_3_1, mult_20_m5, tmpa + + SMLABB tmp4, x_3_1, mult_20_01, tmp4 + UXTB16 x_6_4, x_7_5 + SMLABB tmp5, x_3_1, mult_20_m5, tmp5 + SMLADX tmp6, x_3_1, mult_20_01, tmp6 + SMLABB tmpa, x_6_4, mult_20_01, tmpa + + MOV tmp5, tmp5, ASR #5 + MOV tmp4, tmp4, ASR #5 + PKHBT tmp5, tmp5, tmpa, LSL #(16-5) + PKHBT tmp4, tmp4, tmp6, LSL #(16-5) + USAT16 tmp5, #8, tmp5 + USAT16 tmp4, #8, tmp4 + + SUBS count, count, #4<<28 + ORR tmp4, tmp4, tmp5, LSL #8 + STR tmp4, [mb], #4 + BCS loop_x_hor + +next_y_hor + AND tmp6, count, #0x00F00000 ;// partWidth-1 + SMLABB ref, count, mult_20_01, ref ;// +width + ADDS mb, mb, #16 ;// +16, Carry=0 + SBC mb, mb, tmp6, LSR #20 ;// -(partWidth-1)-1 + SBC ref, ref, tmp6, LSR #20 ;// -(partWidth-1)-1 + ADDS count, count, #(1<<28)-(1<<24) ;// decrement counter (partW) + BGE loop_y_hor + + + +;// VERTICAL PART +;// +;// Approach to vertical interpolation +;// +;// Interpolation is done by using 32-bit loads and stores +;// and by using 16 bit arithmetic. 4x4 block is processed +;// in each round. +;// +;// |a_11|a_11|a_11|a_11|...|a_1n|a_1n|a_1n|a_1n| +;// |b_11|b_11|b_11|b_11|...|b_1n|b_1n|b_1n|b_1n| +;// |c_11|c_11|c_11|c_11|...|c_1n|c_1n|c_1n|c_1n| +;// |d_11|d_11|d_11|d_11|...|d_1n|d_1n|d_1n|d_1n| +;// .. +;// .. +;// |a_m1|a_m1|a_m1|a_m1|... +;// |b_m1|b_m1|b_m1|b_m1|... +;// |c_m1|c_m1|c_m1|c_m1|... +;// |d_m1|d_m1|d_m1|d_m1|... + +;// Approach to bilinear interpolation to quarter pel position. +;// 4 bytes are processed parallel +;// +;// algorithm (a+b+1)/2. Rouding upwards +1 can be achieved by +;// negating second operand to get one's complement (instead of 2's) +;// and using subtraction, EOR is used to correct sign. +;// +;// MVN b, b +;// UHSUB8 a, a, b +;// EOR a, a, 0x80808080 + + + LDR ref, [sp, #0x1e4] ;// ref + LDR tmpa, [sp, #0x228] ;// horVerOffset + LDR mb, [sp, #0x1e8] ;// mb + LDR width, [sp, #0x218] ;// width + ADD ref, ref, #2 ;// calculate correct position + AND tmpa, tmpa, #1 + ADD ref, ref, tmpa + LDR plus16, = 0x00100010 ;// +16 to lower and upperf halfwords + AND count, count, #0x00FFFFFF ;// partWidth-1 + + AND tmpa, count, #0x000F0000 ;// partHeight-1 + ADD count, count, tmpa, LSL #8 + +loop_y + ADD count, count, tmp6, LSL #8 ;// partWidth-1 + +loop_x + LDR tmp1, [ref], width ;// |a4|a3|a2|a1| + LDR tmp2, [ref], width ;// |c4|c3|c2|c1| + LDR tmp3, [ref], width ;// |g4|g3|g2|g1| + LDR tmp4, [ref], width ;// |m4|m3|m2|m1| + LDR tmp5, [ref], width ;// |r4|r3|r2|r1| + LDR tmp6, [ref], width ;// |t4|t3|t2|t1| + + ;// first four pixels + UXTB16 tmpa, tmp3 ;// |g3|g1| + UXTAB16 tmpa, tmpa, tmp4 ;// |g3+m3|g1+m1| + UXTB16 tmpb, tmp2 ;// |c3|c1| + ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M) + + UXTAB16 tmpb, tmpb, tmp5 ;// |c3+r3|c1+r1| + ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M) + UXTAB16 tmpa, tmpa, tmp1 ;// 16+20(G+M)+A + UXTAB16 tmpa, tmpa, tmp6 ;// 16+20(G+M)+A+T + + ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R) + SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R) + + USAT16 tmpb, #13, tmpa ;// saturate + LDR res, = 0x00FF00FF + UXTB16 tmpa, tmp3, ROR #8 ;// |g4|g2| + UXTAB16 tmpa, tmpa, tmp4, ROR #8 ;// |g4+m4|g2+m2| + AND res, res, tmpb, LSR #5 ;// mask and divide by 32 + + ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M) + UXTB16 tmpb, tmp2, ROR #8 ;// |c4|c2| + ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M) + UXTAB16 tmpb, tmpb, tmp5, ROR #8 ;// |c4+r4|c2+r2| + UXTAB16 tmpa, tmpa, tmp1, ROR #8 ;// 16+20(G+M)+A + UXTAB16 tmpa, tmpa, tmp6, ROR #8 ;// 16+20(G+M)+A+T + + ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R) + SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R) + + USAT16 tmpb, #13, tmpa ;// saturate + LDR tmp1, [mb] + LDR tmpa, = 0xFF00FF00 + MVN tmp1, tmp1 + AND tmpa, tmpa, tmpb, LSL #3 ;// mask and divede by 32 + ORR res, res, tmpa + + LDR tmpa, = 0x80808080 + UHSUB8 res, res, tmp1 ;// bilinear interpolation + LDR tmp1, [ref], width ;// load next row + EOR res, res, tmpa ;// correct sign + + STR res, [mb], #16 ;// next row (mb) + + + ;// tmp2 = |a4|a3|a2|a1| + ;// tmp3 = |c4|c3|c2|c1| + ;// tmp4 = |g4|g3|g2|g1| + ;// tmp5 = |m4|m3|m2|m1| + ;// tmp6 = |r4|r3|r2|r1| + ;// tmp1 = |t4|t3|t2|t1| + + ;// second four pixels + UXTB16 tmpa, tmp4 ;// |g3|g1| + UXTAB16 tmpa, tmpa, tmp5 ;// |g3+m3|g1+m1| + UXTB16 tmpb, tmp3 ;// |c3|c1| + ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M) + UXTAB16 tmpb, tmpb, tmp6 ;// |c3+r3|c1+r1| + ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M) + UXTAB16 tmpa, tmpa, tmp2 ;// 16+20(G+M)+A + UXTAB16 tmpa, tmpa, tmp1 ;// 16+20(G+M)+A+T + + ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R) + SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R) + + USAT16 tmpb, #13, tmpa ;// saturate + LDR res, = 0x00FF00FF + UXTB16 tmpa, tmp4, ROR #8 ;// |g4|g2| + UXTAB16 tmpa, tmpa, tmp5, ROR #8 ;// |g4+m4|g2+m2| + AND res, res, tmpb, LSR #5 ;// mask and divide by 32 + + ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M) + UXTB16 tmpb, tmp3, ROR #8 ;// |c4|c2| + ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M) + UXTAB16 tmpb, tmpb, tmp6, ROR #8 ;// |c4+r4|c2+r2| + UXTAB16 tmpa, tmpa, tmp2, ROR #8 ;// 16+20(G+M)+A + UXTAB16 tmpa, tmpa, tmp1, ROR #8 ;// 16+20(G+M)+A+T + + ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R) + SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R) + + USAT16 tmpb, #13, tmpa ;// saturate + LDR tmp2, [mb] + LDR tmpa, = 0xFF00FF00 + MVN tmp2, tmp2 + + AND tmpa, tmpa, tmpb, LSL #3 ;// mask and divide by 32 + ORR res, res, tmpa + LDR tmpa, = 0x80808080 + UHSUB8 res, res, tmp2 ;// bilinear interpolation + LDR tmp2, [ref], width ;// load next row + EOR res, res, tmpa ;// correct sign + STR res, [mb], #16 ;// next row + + ;// tmp3 = |a4|a3|a2|a1| + ;// tmp4 = |c4|c3|c2|c1| + ;// tmp5 = |g4|g3|g2|g1| + ;// tmp6 = |m4|m3|m2|m1| + ;// tmp1 = |r4|r3|r2|r1| + ;// tmp2 = |t4|t3|t2|t1| + + ;// third four pixels + UXTB16 tmpa, tmp5 ;// |g3|g1| + UXTAB16 tmpa, tmpa, tmp6 ;// |g3+m3|g1+m1| + UXTB16 tmpb, tmp4 ;// |c3|c1| + ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M) + UXTAB16 tmpb, tmpb, tmp1 ;// |c3+r3|c1+r1| + ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M) + UXTAB16 tmpa, tmpa, tmp3 ;// 16+20(G+M)+A + UXTAB16 tmpa, tmpa, tmp2 ;// 16+20(G+M)+A+T + + ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R) + SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R) + + USAT16 tmpb, #13, tmpa ;// saturate + LDR res, = 0x00FF00FF + UXTB16 tmpa, tmp5, ROR #8 ;// |g4|g2| + UXTAB16 tmpa, tmpa, tmp6, ROR #8 ;// |g4+m4|g2+m2| + AND res, res, tmpb, LSR #5 ;// mask and divide by 32 + + ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M) + UXTB16 tmpb, tmp4, ROR #8 ;// |c4|c2| + ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M) + UXTAB16 tmpb, tmpb, tmp1, ROR #8 ;// |c4+r4|c2+r2| + UXTAB16 tmpa, tmpa, tmp3, ROR #8 ;// 16+20(G+M)+A + UXTAB16 tmpa, tmpa, tmp2, ROR #8 ;// 16+20(G+M)+A+T + + + ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R) + SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R) + + USAT16 tmpb, #13, tmpa ;// saturate + LDR tmp3, [mb] + LDR tmpa, = 0xFF00FF00 + MVN tmp3, tmp3 + + AND tmpa, tmpa, tmpb, LSL #3 ;// mask and divide by 32 + ORR res, res, tmpa + LDR tmpa, = 0x80808080 + UHSUB8 res, res, tmp3 ;// bilinear interpolation + LDR tmp3, [ref] ;// load next row + EOR res, res, tmpa ;// correct sign + STR res, [mb], #16 ;// next row + + ;// tmp4 = |a4|a3|a2|a1| + ;// tmp5 = |c4|c3|c2|c1| + ;// tmp6 = |g4|g3|g2|g1| + ;// tmp1 = |m4|m3|m2|m1| + ;// tmp2 = |r4|r3|r2|r1| + ;// tmp3 = |t4|t3|t2|t1| + + ;// fourth four pixels + UXTB16 tmpa, tmp6 ;// |g3|g1| + UXTAB16 tmpa, tmpa, tmp1 ;// |g3+m3|g1+m1| + UXTB16 tmpb, tmp5 ;// |c3|c1| + ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M) + UXTAB16 tmpb, tmpb, tmp2 ;// |c3+r3|c1+r1| + ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M) + UXTAB16 tmpa, tmpa, tmp4 ;// 16+20(G+M)+A + UXTAB16 tmpa, tmpa, tmp3 ;// 16+20(G+M)+A+T + + ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R) + SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R) + + USAT16 tmpb, #13, tmpa ;// saturate + LDR res, = 0x00FF00FF + UXTB16 tmpa, tmp6, ROR #8 ;// |g4|g2| + UXTAB16 tmpa, tmpa, tmp1, ROR #8 ;// |g4+m4|g2+m2| + AND res, res, tmpb, LSR #5 ;// mask and divide by 32 + + ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M) + UXTB16 tmpb, tmp5, ROR #8 ;// |c4|c2| + ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M) + UXTAB16 tmpb, tmpb, tmp2, ROR #8 ;// |c4+r4|c2+r2| + UXTAB16 tmpa, tmpa, tmp4, ROR #8 ;// 16+20(G+M)+A + UXTAB16 tmpa, tmpa, tmp3, ROR #8 ;// 16+20(G+M)+A+T + + ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R) + SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R) + + USAT16 tmpb, #13, tmpa ;// saturate + LDR tmp5, [mb] + LDR tmp4, = 0xFF00FF00 + MVN tmp5, tmp5 + + AND tmpa, tmp4, tmpb, LSL #3 ;// mask and divide by 32 + ORR res, res, tmpa + LDR tmpa, = 0x80808080 + UHSUB8 res, res, tmp5 ;// bilinear interpolation + + ;// decrement loop_x counter + SUBS count, count, #4<<28 ;// decrement x loop counter + + ;// calculate "ref" address for next round + SUB ref, ref, width, LSL #3 ;// ref -= 8*width; + ADD ref, ref, #4 ;// next column (4 pixels) + + EOR res, res, tmpa ;// correct sign + STR res, [mb], #-44 + + BCS loop_x + + ADDS mb, mb, #64 ;// set Carry=0 + ADD ref, ref, width, LSL #2 ;// ref += 4*width + AND tmp6, count, #0x00F00000 ;// partWidth-1 + SBC ref, ref, tmp6, LSR #20 ;// -(partWidth-1)-1 + SBC mb, mb, tmp6, LSR #20 ;// -(partWidth-1)-1 + + ADDS count, count, #0xC << 24 ;// decrement y loop counter + BGE loop_y + + ADD sp, sp, #0x1f4 + LDMFD sp!, {r4-r11, pc} + + END diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_mid_hor.s b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_mid_hor.s new file mode 100755 index 0000000..a81aed7 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_mid_hor.s @@ -0,0 +1,163 @@ +; Copyright (C) 2009 The Android Open Source Project
+;
+; Licensed under the Apache License, Version 2.0 (the "License");
+; you may not use this file except in compliance with the License.
+; You may obtain a copy of the License at
+;
+; http://www.apache.org/licenses/LICENSE-2.0
+;
+; Unless required by applicable law or agreed to in writing, software
+; distributed under the License is distributed on an "AS IS" BASIS,
+; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+; See the License for the specific language governing permissions and
+; limitations under the License.
+
+;-------------------------------------------------------------------------------
+;--
+;-- Abstract : ARMv6 optimized version horizontal part of
+;-- h264bsdInterpolateMid functions
+;--
+;-------------------------------------------------------------------------------
+
+
+ IF :DEF: H264DEC_WINASM
+ ;// We dont use REQUIRE8 and PRESERVE8 for winasm
+ ELSE
+ REQUIRE8
+ PRESERVE8
+ ENDIF
+
+ AREA |.text|, CODE
+
+
+;// Register allocation
+
+ref RN 0 ;// pointer to current position in reference image
+mb RN 1 ;// pointer to current position in interpolated mb
+count RN 2 ;// bit-packed width and count values
+
+x_2_0 RN 4
+x_3_1 RN 5
+x_6_4 RN 6
+x_7_5 RN 7
+
+tmp1 RN 8
+tmp2 RN 9
+tmp3 RN 10
+tmp4 RN 11
+
+mult_20_01 RN 12 ;// [20, 1]
+mult_20_m5 RN 14 ;// [20, -5]
+
+
+ EXPORT h264bsdInterpolateMidHorPart
+
+;// Horizontal filter approach
+;//
+;// Basic idea in horizontal filtering is to adjust coefficients
+;// like below. Calculation is done with 16-bit maths.
+;//
+;// Reg x_2_0 x_3_1 x_6_4 x_7_5 x_2_0
+;// [ 2 0 ] [ 3 1 ] [ 6 4 ] [ 7 5 ] [ 10 8 ] ...
+;// y_0 = 20 1 20 -5 -5 1
+;// y_1 = -5 20 1 1 20 -5
+;// y_2 = 1 -5 -5 20 1 20
+;// y_3 = 1 20 -5 -5 20 1
+
+
+h264bsdInterpolateMidHorPart
+ STMFD sp!, {r4-r11, lr}
+
+ ;// pack values to count register
+ ;// [31:28] loop_x (partWidth-1)
+ ;// [27:24] loop_y (partHeight-1)
+ ;// [23:20] partWidth-1
+ ;// [19:16] partHeight-1
+ ;// [15:00] width
+
+
+ LDR mult_20_01, = 0x00140001
+ LDR mult_20_m5, = 0x0014FFFB
+ AND tmp3, count, #0x000F0000 ;// partWidth-1
+loop_y
+ LDR x_3_1, [ref, #-8]
+ ADD count, count, tmp3, LSL #12
+ LDR x_7_5, [ref, #-4]
+ UXTB16 x_2_0, x_3_1
+ UXTB16 x_3_1, x_3_1, ROR #8
+ UXTB16 x_6_4, x_7_5
+
+loop_x
+ UXTB16 x_7_5, x_7_5, ROR #8
+
+ SMUAD tmp1, x_2_0, mult_20_01
+ SMULTB tmp2, x_2_0, mult_20_m5
+ SMULTB tmp3, x_2_0, mult_20_01
+ SMULTB tmp4, x_3_1, mult_20_01
+
+ SMLAD tmp1, x_3_1, mult_20_m5, tmp1
+ SMLAD tmp2, x_3_1, mult_20_01, tmp2
+ SMLATB tmp3, x_3_1, mult_20_m5, tmp3
+ LDR x_3_1, [ref], #4
+ SMLAD tmp4, x_6_4, mult_20_m5, tmp4
+
+ SMLABB tmp1, x_6_4, mult_20_m5, tmp1
+ SMLADX tmp2, x_6_4, mult_20_01, tmp2
+ SMLADX tmp3, x_6_4, mult_20_m5, tmp3
+ SMLADX tmp4, x_7_5, mult_20_m5, tmp4
+
+ SMLABB tmp1, x_7_5, mult_20_01, tmp1
+ SMLABB tmp2, x_7_5, mult_20_m5, tmp2
+ UXTB16 x_2_0, x_3_1
+ SMLADX tmp3, x_7_5, mult_20_01, tmp3
+ SMLABB tmp4, x_2_0, mult_20_01, tmp4
+
+ SUBS count, count, #4<<28
+ STR tmp1, [mb], #4
+ STR tmp2, [mb], #4
+ STR tmp3, [mb], #4
+ STR tmp4, [mb], #4
+ BCC next_y
+
+ UXTB16 x_3_1, x_3_1, ROR #8
+
+ SMUAD tmp1, x_6_4, mult_20_01
+ SMULTB tmp2, x_6_4, mult_20_m5
+ SMULTB tmp3, x_6_4, mult_20_01
+ SMULTB tmp4, x_7_5, mult_20_01
+
+ SMLAD tmp1, x_7_5, mult_20_m5, tmp1
+ SMLAD tmp2, x_7_5, mult_20_01, tmp2
+ SMLATB tmp3, x_7_5, mult_20_m5, tmp3
+ LDR x_7_5, [ref], #4
+ SMLAD tmp4, x_2_0, mult_20_m5, tmp4
+
+ SMLABB tmp1, x_2_0, mult_20_m5, tmp1
+ SMLADX tmp2, x_2_0, mult_20_01, tmp2
+ SMLADX tmp3, x_2_0, mult_20_m5, tmp3
+ SMLADX tmp4, x_3_1, mult_20_m5, tmp4
+
+ SMLABB tmp1, x_3_1, mult_20_01, tmp1
+ SMLABB tmp2, x_3_1, mult_20_m5, tmp2
+ UXTB16 x_6_4, x_7_5
+ SMLADX tmp3, x_3_1, mult_20_01, tmp3
+ SMLABB tmp4, x_6_4, mult_20_01, tmp4
+
+ SUBS count, count, #4<<28
+ STR tmp1, [mb], #4
+ STR tmp2, [mb], #4
+ STR tmp3, [mb], #4
+ STR tmp4, [mb], #4
+ BCS loop_x
+
+next_y
+ AND tmp3, count, #0x000F0000 ;// partWidth-1
+ SMLABB ref, count, mult_20_01, ref ;// +width
+ SBC ref, ref, tmp3, LSR #16 ;// -(partWidth-1)-1
+ ADDS count, count, #(1<<28)-(1<<20)
+ BGE loop_y
+
+ LDMFD sp!, {r4-r11, pc}
+
+ END
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_ver_half.s b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_ver_half.s new file mode 100755 index 0000000..244fc6f --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_ver_half.s @@ -0,0 +1,347 @@ +; Copyright (C) 2009 The Android Open Source Project +; +; Licensed under the Apache License, Version 2.0 (the "License"); +; you may not use this file except in compliance with the License. +; You may obtain a copy of the License at +; +; http://www.apache.org/licenses/LICENSE-2.0 +; +; Unless required by applicable law or agreed to in writing, software +; distributed under the License is distributed on an "AS IS" BASIS, +; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +; See the License for the specific language governing permissions and +; limitations under the License. + +;------------------------------------------------------------------------------- +;-- +;-- Abstract : ARMv6 optimized version of h264bsdInterpolateVerHalf function +;-- +;------------------------------------------------------------------------------- + + + IF :DEF: H264DEC_WINASM + ;// We dont use REQUIRE8 and PRESERVE8 for winasm + ELSE + REQUIRE8 + PRESERVE8 + ENDIF + + AREA |.text|, CODE + +;// h264bsdInterpolateVerHalf register allocation + +ref RN 0 + +mb RN 1 +buff RN 1 + +count RN 2 +x0 RN 2 + +res RN 3 +y0 RN 3 + +tmp1 RN 4 + +tmp2 RN 5 +height RN 5 + +tmp3 RN 6 +partW RN 6 + +tmp4 RN 7 +partH RN 7 + +tmp5 RN 8 +tmp6 RN 9 + +tmpa RN 10 +tmpb RN 11 +width RN 12 + +plus16 RN 14 + + +;// function exports and imports + + IMPORT h264bsdFillBlock + + EXPORT h264bsdInterpolateVerHalf + +;// Approach to vertical interpolation +;// +;// Interpolation is done by using 32-bit loads and stores +;// and by using 16 bit arithmetic. 4x4 block is processed +;// in each round. +;// +;// |a_11|a_11|a_11|a_11|...|a_1n|a_1n|a_1n|a_1n| +;// |b_11|b_11|b_11|b_11|...|b_1n|b_1n|b_1n|b_1n| +;// |c_11|c_11|c_11|c_11|...|c_1n|c_1n|c_1n|c_1n| +;// |d_11|d_11|d_11|d_11|...|d_1n|d_1n|d_1n|d_1n| +;// .. +;// .. +;// |a_m1|a_m1|a_m1|a_m1|... +;// |b_m1|b_m1|b_m1|b_m1|... +;// |c_m1|c_m1|c_m1|c_m1|... +;// |d_m1|d_m1|d_m1|d_m1|... + +h264bsdInterpolateVerHalf + STMFD sp!, {r0-r11, lr} + SUB sp, sp, #0x1e4 + + CMP x0, #0 + BLT do_fill ;// (x0 < 0) + LDR partW, [sp,#0x220] ;// partWidth + ADD tmp5, x0, partW ;// (x0+partWidth) + LDR width, [sp,#0x218] ;// width + CMP tmp5, width + BHI do_fill ;// (x0+partW)>width + + CMP y0, #0 + BLT do_fill ;// (y0 < 0) + LDR partH, [sp,#0x224] ;// partHeight + ADD tmp6, y0, partH ;// (y0+partHeight) + ADD tmp6, tmp6, #5 ;// (y0+partH+5) + LDR height, [sp,#0x21c] ;// height + CMP tmp6, height + BLS skip_fill ;// no overfill needed + + +do_fill + LDR partH, [sp,#0x224] ;// partHeight + ADD tmp5, partH, #5 ;// r2 = partH + 5; + LDR height, [sp,#0x21c] ;// height + LDR partW, [sp,#0x220] ;// partWidth + STMIB sp, {height, partW} ;// sp+4 = height, sp+8 = partWidth + STR tmp5, [sp,#0xc] ;// sp+c partHeight+5 + STR partW, [sp,#0x10] ;// sp+10 = partWidth + LDR width, [sp,#0x218] ;// width + STR width, [sp,#0] ;// sp+0 = width + ADD buff, sp, #0x28 ;// buff = p1[21*21/4+1] + BL h264bsdFillBlock + + MOV x0, #0 + STR x0,[sp,#0x1ec] ;// x0 = 0 + STR x0,[sp,#0x1f0] ;// y0 = 0 + ADD ref,sp,#0x28 ;// ref = p1 + STR partW, [sp,#0x218] + + +skip_fill + LDR x0 ,[sp,#0x1ec] ;// x0 + LDR y0 ,[sp,#0x1f0] ;// y0 + LDR width, [sp,#0x218] ;// width + MLA tmp6, width, y0, x0 ;// y0*width+x0 + ADD ref, ref, tmp6 ;// ref += y0*width+x0 + LDR mb, [sp, #0x1e8] ;// mb + + ADD count, partW, partH, LSL #16 ;// |partH|partW| + LDR tmp5, = 0x00010001 + SSUB16 count, count, tmp5; ;// |partH-1|partW-1| + LDR plus16, = 0x00100010 + + AND tmp1, count, #0x000000FF ;// partWidth + + +loop_y + ADD count, count, tmp1, LSL #24 ;// partWidth-1 to top byte + +loop_x + LDR tmp1, [ref], width ;// |a4|a3|a2|a1| + LDR tmp2, [ref], width ;// |c4|c3|c2|c1| + LDR tmp3, [ref], width ;// |g4|g3|g2|g1| + LDR tmp4, [ref], width ;// |m4|m3|m2|m1| + LDR tmp5, [ref], width ;// |r4|r3|r2|r1| + LDR tmp6, [ref], width ;// |t4|t3|t2|t1| + + ;// first four pixels + UXTB16 tmpa, tmp3 ;// |g3|g1| + UXTAB16 tmpa, tmpa, tmp4 ;// |g3+m3|g1+m1| + UXTB16 tmpb, tmp2 ;// |c3|c1| + ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M) + + UXTAB16 tmpb, tmpb, tmp5 ;// |c3+r3|c1+r1| + ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M) + UXTAB16 tmpa, tmpa, tmp1 ;// 16+20(G+M)+A + UXTAB16 tmpa, tmpa, tmp6 ;// 16+20(G+M)+A+T + + ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R) + SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R) + + USAT16 tmpb, #13, tmpa ;// saturate + LDR res, = 0x00FF00FF + UXTB16 tmpa, tmp3, ROR #8 ;// |g4|g2| + UXTAB16 tmpa, tmpa, tmp4, ROR #8 ;// |g4+m4|g2+m2| + AND res, res, tmpb, LSR #5 ;// mask and divide by 32 + + ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M) + UXTB16 tmpb, tmp2, ROR #8 ;// |c4|c2| + ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M) + UXTAB16 tmpb, tmpb, tmp5, ROR #8 ;// |c4+r4|c2+r2| + UXTAB16 tmpa, tmpa, tmp1, ROR #8 ;// 16+20(G+M)+A + UXTAB16 tmpa, tmpa, tmp6, ROR #8 ;// 16+20(G+M)+A+T + + ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R) + SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R) + + USAT16 tmpb, #13, tmpa ;// saturate + LDR tmp1, [ref], width + LDR tmpa, = 0xFF00FF00 + + AND tmpa, tmpa, tmpb, LSL #3 ;// mask and divede by 32 + ORR res, res, tmpa + STR res, [mb], #16 ;// next row (mb) + + ;// tmp2 = |a4|a3|a2|a1| + ;// tmp3 = |c4|c3|c2|c1| + ;// tmp4 = |g4|g3|g2|g1| + ;// tmp5 = |m4|m3|m2|m1| + ;// tmp6 = |r4|r3|r2|r1| + ;// tmp1 = |t4|t3|t2|t1| + + ;// second four pixels + UXTB16 tmpa, tmp4 ;// |g3|g1| + UXTAB16 tmpa, tmpa, tmp5 ;// |g3+m3|g1+m1| + UXTB16 tmpb, tmp3 ;// |c3|c1| + ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M) + UXTAB16 tmpb, tmpb, tmp6 ;// |c3+r3|c1+r1| + ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M) + UXTAB16 tmpa, tmpa, tmp2 ;// 16+20(G+M)+A + UXTAB16 tmpa, tmpa, tmp1 ;// 16+20(G+M)+A+T + + ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R) + SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R) + + USAT16 tmpb, #13, tmpa ;// saturate + LDR res, = 0x00FF00FF + UXTB16 tmpa, tmp4, ROR #8 ;// |g4|g2| + UXTAB16 tmpa, tmpa, tmp5, ROR #8 ;// |g4+m4|g2+m2| + AND res, res, tmpb, LSR #5 ;// mask and divide by 32 + + ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M) + UXTB16 tmpb, tmp3, ROR #8 ;// |c4|c2| + ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M) + UXTAB16 tmpb, tmpb, tmp6, ROR #8 ;// |c4+r4|c2+r2| + UXTAB16 tmpa, tmpa, tmp2, ROR #8 ;// 16+20(G+M)+A + UXTAB16 tmpa, tmpa, tmp1, ROR #8 ;// 16+20(G+M)+A+T + + ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R) + SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R) + + USAT16 tmpb, #13, tmpa ;// saturate + LDR tmp2, [ref], width + LDR tmpa, = 0xFF00FF00 + + AND tmpa, tmpa, tmpb, LSL #3 ;// mask and divide by 32 + ORR res, res, tmpa + STR res, [mb], #16 ;// next row + + ;// tmp3 = |a4|a3|a2|a1| + ;// tmp4 = |c4|c3|c2|c1| + ;// tmp5 = |g4|g3|g2|g1| + ;// tmp6 = |m4|m3|m2|m1| + ;// tmp1 = |r4|r3|r2|r1| + ;// tmp2 = |t4|t3|t2|t1| + + ;// third four pixels + UXTB16 tmpa, tmp5 ;// |g3|g1| + UXTAB16 tmpa, tmpa, tmp6 ;// |g3+m3|g1+m1| + UXTB16 tmpb, tmp4 ;// |c3|c1| + ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M) + UXTAB16 tmpb, tmpb, tmp1 ;// |c3+r3|c1+r1| + ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M) + UXTAB16 tmpa, tmpa, tmp3 ;// 16+20(G+M)+A + UXTAB16 tmpa, tmpa, tmp2 ;// 16+20(G+M)+A+T + + ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R) + SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R) + + USAT16 tmpb, #13, tmpa ;// saturate + LDR res, = 0x00FF00FF + UXTB16 tmpa, tmp5, ROR #8 ;// |g4|g2| + UXTAB16 tmpa, tmpa, tmp6, ROR #8 ;// |g4+m4|g2+m2| + AND res, res, tmpb, LSR #5 ;// mask and divide by 32 + + ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M) + UXTB16 tmpb, tmp4, ROR #8 ;// |c4|c2| + ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M) + UXTAB16 tmpb, tmpb, tmp1, ROR #8 ;// |c4+r4|c2+r2| + UXTAB16 tmpa, tmpa, tmp3, ROR #8 ;// 16+20(G+M)+A + UXTAB16 tmpa, tmpa, tmp2, ROR #8 ;// 16+20(G+M)+A+T + + + ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R) + SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R) + + USAT16 tmpb, #13, tmpa ;// saturate + LDR tmp3, [ref] + LDR tmpa, = 0xFF00FF00 + + ;// decrement loop_x counter + SUBS count, count, #4<<24 ;// (partWidth-1) -= 4; + + AND tmpa, tmpa, tmpb, LSL #3 ;// mask and divide by 32 + ORR res, res, tmpa + STR res, [mb], #16 ;// next row + + ;// tmp4 = |a4|a3|a2|a1| + ;// tmp5 = |c4|c3|c2|c1| + ;// tmp6 = |g4|g3|g2|g1| + ;// tmp1 = |m4|m3|m2|m1| + ;// tmp2 = |r4|r3|r2|r1| + ;// tmp3 = |t4|t3|t2|t1| + + ;// fourth four pixels + UXTB16 tmpa, tmp6 ;// |g3|g1| + UXTAB16 tmpa, tmpa, tmp1 ;// |g3+m3|g1+m1| + UXTB16 tmpb, tmp5 ;// |c3|c1| + ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M) + UXTAB16 tmpb, tmpb, tmp2 ;// |c3+r3|c1+r1| + ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M) + UXTAB16 tmpa, tmpa, tmp4 ;// 16+20(G+M)+A + UXTAB16 tmpa, tmpa, tmp3 ;// 16+20(G+M)+A+T + + ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R) + SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R) + + USAT16 tmpb, #13, tmpa ;// saturate + LDR res, = 0x00FF00FF + UXTB16 tmpa, tmp6, ROR #8 ;// |g4|g2| + UXTAB16 tmpa, tmpa, tmp1, ROR #8 ;// |g4+m4|g2+m2| + AND res, res, tmpb, LSR #5 ;// mask and divide by 32 + + ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M) + UXTB16 tmpb, tmp5, ROR #8 ;// |c4|c2| + ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M) + UXTAB16 tmpb, tmpb, tmp2, ROR #8 ;// |c4+r4|c2+r2| + UXTAB16 tmpa, tmpa, tmp4, ROR #8 ;// 16+20(G+M)+A + UXTAB16 tmpa, tmpa, tmp3, ROR #8 ;// 16+20(G+M)+A+T + + ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R) + SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R) + + USAT16 tmpb, #13, tmpa ;// saturate + LDR tmp4, = 0xFF00FF00 + + ;// calculate "ref" address for next round + SUB ref, ref, width, LSL #3 ;// ref -= 8*width; + ADD ref, ref, #4; ;// next column (4 pixels) + AND tmpa, tmp4, tmpb, LSL #3 ;// mask and divide by 32 + ORR res, res, tmpa + STR res, [mb], #-44 + + BCS loop_x + + ADDS count, count, #252<<16 ;// (partHeight-1) -= 4; + ADD ref, ref, width, LSL #2 ;// ref += 4*width + AND tmp1, count, #0x000000FF ;// partWidth-1 + ADD tmp2, tmp1, #1 ;// partWidth + SUB ref, ref, tmp2 ;// ref -= partWidth + ADD mb, mb, #64; + SUB mb, mb, tmp2; ;// mb -= partWidth + BGE loop_y + + ADD sp,sp,#0x1f4 + LDMFD sp!, {r4-r11, pc} + + END diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_ver_quarter.s b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_ver_quarter.s new file mode 100755 index 0000000..5266c85 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_ver_quarter.s @@ -0,0 +1,374 @@ +; Copyright (C) 2009 The Android Open Source Project +; +; Licensed under the Apache License, Version 2.0 (the "License"); +; you may not use this file except in compliance with the License. +; You may obtain a copy of the License at +; +; http://www.apache.org/licenses/LICENSE-2.0 +; +; Unless required by applicable law or agreed to in writing, software +; distributed under the License is distributed on an "AS IS" BASIS, +; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +; See the License for the specific language governing permissions and +; limitations under the License. + +;------------------------------------------------------------------------------- +;-- +;-- Abstract : ARMv6 optimized version of h264bsdInterpolateVerQuarter function +;-- +;------------------------------------------------------------------------------- + + IF :DEF: H264DEC_WINASM + ;// We dont use REQUIRE8 and PRESERVE8 for winasm + ELSE + REQUIRE8 + PRESERVE8 + ENDIF + + AREA |.text|, CODE + +;// h264bsdInterpolateVerQuarter register allocation + +ref RN 0 + +mb RN 1 +buff RN 1 + +count RN 2 +x0 RN 2 + +res RN 3 +y0 RN 3 + +tmp1 RN 4 + +tmp2 RN 5 +height RN 5 + +tmp3 RN 6 +partW RN 6 + +tmp4 RN 7 +partH RN 7 + +tmp5 RN 8 +tmp6 RN 9 + +tmpa RN 10 +tmpb RN 11 +width RN 12 + +plus16 RN 14 + + +;// function exports and imports + + IMPORT h264bsdFillBlock + + EXPORT h264bsdInterpolateVerQuarter + +;// Approach to vertical interpolation +;// +;// Interpolation is done by using 32-bit loads and stores +;// and by using 16 bit arithmetic. 4x4 block is processed +;// in each round. +;// +;// |a_11|a_11|a_11|a_11|...|a_1n|a_1n|a_1n|a_1n| +;// |b_11|b_11|b_11|b_11|...|b_1n|b_1n|b_1n|b_1n| +;// |c_11|c_11|c_11|c_11|...|c_1n|c_1n|c_1n|c_1n| +;// |d_11|d_11|d_11|d_11|...|d_1n|d_1n|d_1n|d_1n| +;// .. +;// .. +;// |a_m1|a_m1|a_m1|a_m1|... +;// |b_m1|b_m1|b_m1|b_m1|... +;// |c_m1|c_m1|c_m1|c_m1|... +;// |d_m1|d_m1|d_m1|d_m1|... + +h264bsdInterpolateVerQuarter + STMFD sp!, {r0-r11, lr} + SUB sp, sp, #0x1e4 + + CMP x0, #0 + BLT do_fill ;// (x0 < 0) + LDR partW, [sp,#0x220] ;// partWidth + ADD tmp5, x0, partW ;// (x0+partWidth) + LDR width, [sp,#0x218] ;// width + CMP tmp5, width + BHI do_fill ;// (x0+partW)>width + + CMP y0, #0 + BLT do_fill ;// (y0 < 0) + LDR partH, [sp,#0x224] ;// partHeight + ADD tmp6, y0, partH ;// (y0+partHeight) + ADD tmp6, tmp6, #5 ;// (y0+partH+5) + LDR height, [sp,#0x21c] ;// height + CMP tmp6, height + BLS skip_fill ;// no overfill needed + + +do_fill + LDR partH, [sp,#0x224] ;// partHeight + ADD tmp5, partH, #5 ;// r2 = partH + 5; + LDR height, [sp,#0x21c] ;// height + LDR partW, [sp,#0x220] ;// partWidth + STMIB sp, {height, partW} ;// sp+4 = height, sp+8 = partWidth + STR tmp5, [sp,#0xc] ;// sp+c partHeight+5 + STR partW, [sp,#0x10] ;// sp+10 = partWidth + LDR width, [sp,#0x218] ;// width + STR width, [sp,#0] ;// sp+0 = width + ADD buff, sp, #0x28 ;// buff = p1[21*21/4+1] + BL h264bsdFillBlock + + MOV x0, #0 + STR x0,[sp,#0x1ec] ;// x0 = 0 + STR x0,[sp,#0x1f0] ;// y0 = 0 + ADD ref,sp,#0x28 ;// ref = p1 + STR partW, [sp,#0x218] + + +skip_fill + LDR x0 ,[sp,#0x1ec] ;// x0 + LDR y0 ,[sp,#0x1f0] ;// y0 + LDR width, [sp,#0x218] ;// width + MLA tmp6, width, y0, x0 ;// y0*width+x0 + ADD ref, ref, tmp6 ;// ref += y0*width+x0 + LDR mb, [sp, #0x1e8] ;// mb + + ADD count, partW, partH, LSL #8 ;// |xx|xx|partH|partW| + LDR tmp5, = 0x00010100 + RSB count, tmp5, count, LSL #8 ;// |xx|partH-1|partW-1|xx| + LDR tmp2, [sp, #0x228] ;// verOffset + ADD count, count, tmp2 ;// |xx|partH-1|partW-1|verOffset| + LDR plus16, = 0x00100010 + + AND tmp1, count, #0x0000FF00 ;// partWidth + + +loop_y + ADD count, count, tmp1, LSL #16 ;// partWidth-1 to top byte + +loop_x + LDR tmp1, [ref], width ;// |a4|a3|a2|a1| + LDR tmp2, [ref], width ;// |c4|c3|c2|c1| + LDR tmp3, [ref], width ;// |g4|g3|g2|g1| + LDR tmp4, [ref], width ;// |m4|m3|m2|m1| + LDR tmp5, [ref], width ;// |r4|r3|r2|r1| + LDR tmp6, [ref], width ;// |t4|t3|t2|t1| + + ;// first four pixels + UXTB16 tmpa, tmp3 ;// |g3|g1| + UXTAB16 tmpa, tmpa, tmp4 ;// |g3+m3|g1+m1| + UXTB16 tmpb, tmp2 ;// |c3|c1| + ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M) + + UXTAB16 tmpb, tmpb, tmp5 ;// |c3+r3|c1+r1| + ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M) + UXTAB16 tmpa, tmpa, tmp1 ;// 16+20(G+M)+A + UXTAB16 tmpa, tmpa, tmp6 ;// 16+20(G+M)+A+T + + ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R) + SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R) + + USAT16 tmpb, #13, tmpa ;// saturate + LDR res, = 0x00FF00FF + UXTB16 tmpa, tmp3, ROR #8 ;// |g4|g2| + UXTAB16 tmpa, tmpa, tmp4, ROR #8 ;// |g4+m4|g2+m2| + AND res, res, tmpb, LSR #5 ;// mask and divide by 32 + + ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M) + UXTB16 tmpb, tmp2, ROR #8 ;// |c4|c2| + ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M) + UXTAB16 tmpb, tmpb, tmp5, ROR #8 ;// |c4+r4|c2+r2| + UXTAB16 tmpa, tmpa, tmp1, ROR #8 ;// 16+20(G+M)+A + UXTAB16 tmpa, tmpa, tmp6, ROR #8 ;// 16+20(G+M)+A+T + + ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R) + SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R) + + USAT16 tmpb, #13, tmpa ;// saturate + MOVS tmp1, count, LSL #31 ;// update flags (verOffset) + LDR tmpa, = 0xFF00FF00 + MVNEQ tmp1, tmp3 ;// select verOffset=0 + MVNNE tmp1, tmp4 ;// select verOffset=1 + AND tmpa, tmpa, tmpb, LSL #3 ;// mask and divede by 32 + ORR res, res, tmpa + + LDR tmpa, = 0x80808080 + UHSUB8 res, res, tmp1 ;// bilinear interpolation + LDR tmp1, [ref], width ;// load next row + EOR res, res, tmpa ;// correct sign + + STR res, [mb], #16 ;// next row (mb) + + + ;// tmp2 = |a4|a3|a2|a1| + ;// tmp3 = |c4|c3|c2|c1| + ;// tmp4 = |g4|g3|g2|g1| + ;// tmp5 = |m4|m3|m2|m1| + ;// tmp6 = |r4|r3|r2|r1| + ;// tmp1 = |t4|t3|t2|t1| + + ;// second four pixels + UXTB16 tmpa, tmp4 ;// |g3|g1| + UXTAB16 tmpa, tmpa, tmp5 ;// |g3+m3|g1+m1| + UXTB16 tmpb, tmp3 ;// |c3|c1| + ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M) + UXTAB16 tmpb, tmpb, tmp6 ;// |c3+r3|c1+r1| + ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M) + UXTAB16 tmpa, tmpa, tmp2 ;// 16+20(G+M)+A + UXTAB16 tmpa, tmpa, tmp1 ;// 16+20(G+M)+A+T + + ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R) + SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R) + + USAT16 tmpb, #13, tmpa ;// saturate + LDR res, = 0x00FF00FF + UXTB16 tmpa, tmp4, ROR #8 ;// |g4|g2| + UXTAB16 tmpa, tmpa, tmp5, ROR #8 ;// |g4+m4|g2+m2| + AND res, res, tmpb, LSR #5 ;// mask and divide by 32 + + ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M) + UXTB16 tmpb, tmp3, ROR #8 ;// |c4|c2| + ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M) + UXTAB16 tmpb, tmpb, tmp6, ROR #8 ;// |c4+r4|c2+r2| + UXTAB16 tmpa, tmpa, tmp2, ROR #8 ;// 16+20(G+M)+A + UXTAB16 tmpa, tmpa, tmp1, ROR #8 ;// 16+20(G+M)+A+T + + ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R) + SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R) + + USAT16 tmpb, #13, tmpa ;// saturate + LDR tmpa, = 0xFF00FF00 + MVNEQ tmp2, tmp4 ;// select verOffset=0 + MVNNE tmp2, tmp5 ;// select verOffset=1 + + AND tmpa, tmpa, tmpb, LSL #3 ;// mask and divide by 32 + ORR res, res, tmpa + LDR tmpa, = 0x80808080 + UHSUB8 res, res, tmp2 ;// bilinear interpolation + LDR tmp2, [ref], width ;// load next row + EOR res, res, tmpa ;// correct sign + STR res, [mb], #16 ;// next row + + ;// tmp3 = |a4|a3|a2|a1| + ;// tmp4 = |c4|c3|c2|c1| + ;// tmp5 = |g4|g3|g2|g1| + ;// tmp6 = |m4|m3|m2|m1| + ;// tmp1 = |r4|r3|r2|r1| + ;// tmp2 = |t4|t3|t2|t1| + + ;// third four pixels + UXTB16 tmpa, tmp5 ;// |g3|g1| + UXTAB16 tmpa, tmpa, tmp6 ;// |g3+m3|g1+m1| + UXTB16 tmpb, tmp4 ;// |c3|c1| + ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M) + UXTAB16 tmpb, tmpb, tmp1 ;// |c3+r3|c1+r1| + ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M) + UXTAB16 tmpa, tmpa, tmp3 ;// 16+20(G+M)+A + UXTAB16 tmpa, tmpa, tmp2 ;// 16+20(G+M)+A+T + + ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R) + SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R) + + USAT16 tmpb, #13, tmpa ;// saturate + LDR res, = 0x00FF00FF + UXTB16 tmpa, tmp5, ROR #8 ;// |g4|g2| + UXTAB16 tmpa, tmpa, tmp6, ROR #8 ;// |g4+m4|g2+m2| + AND res, res, tmpb, LSR #5 ;// mask and divide by 32 + + ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M) + UXTB16 tmpb, tmp4, ROR #8 ;// |c4|c2| + ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M) + UXTAB16 tmpb, tmpb, tmp1, ROR #8 ;// |c4+r4|c2+r2| + UXTAB16 tmpa, tmpa, tmp3, ROR #8 ;// 16+20(G+M)+A + UXTAB16 tmpa, tmpa, tmp2, ROR #8 ;// 16+20(G+M)+A+T + + + ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R) + SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R) + + USAT16 tmpb, #13, tmpa ;// saturate + LDR tmpa, = 0xFF00FF00 + MVNEQ tmp3, tmp5 ;// select verOffset=0 + MVNNE tmp3, tmp6 ;// select verOffset=1 + + AND tmpa, tmpa, tmpb, LSL #3 ;// mask and divide by 32 + ORR res, res, tmpa + LDR tmpa, = 0x80808080 + UHSUB8 res, res, tmp3 ;// bilinear interpolation + LDR tmp3, [ref] ;// load next row + EOR res, res, tmpa ;// correct sign + STR res, [mb], #16 ;// next row + + ;// tmp4 = |a4|a3|a2|a1| + ;// tmp5 = |c4|c3|c2|c1| + ;// tmp6 = |g4|g3|g2|g1| + ;// tmp1 = |m4|m3|m2|m1| + ;// tmp2 = |r4|r3|r2|r1| + ;// tmp3 = |t4|t3|t2|t1| + + ;// fourth four pixels + UXTB16 tmpa, tmp6 ;// |g3|g1| + UXTAB16 tmpa, tmpa, tmp1 ;// |g3+m3|g1+m1| + UXTB16 tmpb, tmp5 ;// |c3|c1| + ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M) + UXTAB16 tmpb, tmpb, tmp2 ;// |c3+r3|c1+r1| + ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M) + UXTAB16 tmpa, tmpa, tmp4 ;// 16+20(G+M)+A + UXTAB16 tmpa, tmpa, tmp3 ;// 16+20(G+M)+A+T + + ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R) + SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R) + + USAT16 tmpb, #13, tmpa ;// saturate + LDR res, = 0x00FF00FF + UXTB16 tmpa, tmp6, ROR #8 ;// |g4|g2| + UXTAB16 tmpa, tmpa, tmp1, ROR #8 ;// |g4+m4|g2+m2| + AND res, res, tmpb, LSR #5 ;// mask and divide by 32 + + ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M) + UXTB16 tmpb, tmp5, ROR #8 ;// |c4|c2| + ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M) + UXTAB16 tmpb, tmpb, tmp2, ROR #8 ;// |c4+r4|c2+r2| + UXTAB16 tmpa, tmpa, tmp4, ROR #8 ;// 16+20(G+M)+A + UXTAB16 tmpa, tmpa, tmp3, ROR #8 ;// 16+20(G+M)+A+T + + ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R) + SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R) + + USAT16 tmpb, #13, tmpa ;// saturate + LDR tmp4, = 0xFF00FF00 + MVNEQ tmp5, tmp6 ;// select verOffset=0 + MVNNE tmp5, tmp1 ;// select verOffset=1 + + AND tmpa, tmp4, tmpb, LSL #3 ;// mask and divide by 32 + ORR res, res, tmpa + LDR tmpa, = 0x80808080 + UHSUB8 res, res, tmp5 ;// bilinear interpolation + + ;// decrement loop_x counter + SUBS count, count, #4<<24 ;// (partWidth-1) -= 4; + + ;// calculate "ref" address for next round + SUB ref, ref, width, LSL #3 ;// ref -= 8*width; + ADD ref, ref, #4; ;// next column (4 pixels) + + EOR res, res, tmpa ;// correct sign + STR res, [mb], #-44 + + BCS loop_x + + ADDS count, count, #252<<16 ;// (partHeight-1) -= 4; + ADD ref, ref, width, LSL #2 ;// ref += 4*width + AND tmp1, count, #0x0000FF00 ;// partWidth-1 + MOV tmp2, #1 + ADD tmp2, tmp2, tmp1, LSR #8 ;// partWidth + SUB ref, ref, tmp2 ;// ref -= partWidth + ADD mb, mb, #64; + SUB mb, mb, tmp2; ;// mb -= partWidth + BGE loop_y + + ADD sp,sp,#0x1f4 + LDMFD sp!, {r4-r11, pc} + + END diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/win_asm.bat b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/win_asm.bat new file mode 100644 index 0000000..1b8d88c --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/win_asm.bat @@ -0,0 +1,15 @@ +echo off +set ASMFLAGS= -checkreglist -CPU ARM1136 -PreDefine "H264DEC_WINASM SETL {TRUE}" +set ASM="D:\Program Files\Microsoft Visual Studio 8\VC\ce\bin\x86_arm\armasm" +echo on + +%ASM% %ASMFLAGS% h264bsd_interpolate_chroma_ver.s +%ASM% %ASMFLAGS% h264bsd_interpolate_chroma_hor.s +%ASM% %ASMFLAGS% h264bsd_interpolate_hor_half.s +%ASM% %ASMFLAGS% h264bsd_interpolate_hor_quarter.s +%ASM% %ASMFLAGS% h264bsd_interpolate_hor_ver_quarter.s +%ASM% %ASMFLAGS% h264bsd_interpolate_ver_half.s +%ASM% %ASMFLAGS% h264bsd_interpolate_ver_quarter.s + +rem %ASM% %ASMFLAGS% h264bsd_interpolate_chroma_hor_ver.s +rem %ASM% %ASMFLAGS% h264bsd_interpolate_mid_hor.s diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm/h264bsdClearMbLayer.s b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm/h264bsdClearMbLayer.s new file mode 100644 index 0000000..db11654 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm/h264bsdClearMbLayer.s @@ -0,0 +1,66 @@ +; +; Copyright (C) 2009 The Android Open Source Project +; +; Licensed under the Apache License, Version 2.0 (the "License"); +; you may not use this file except in compliance with the License. +; You may obtain a copy of the License at +; +; http://www.apache.org/licenses/LICENSE-2.0 +; +; Unless required by applicable law or agreed to in writing, software +; distributed under the License is distributed on an "AS IS" BASIS, +; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +; See the License for the specific language governing permissions and +; limitations under the License. +; + + REQUIRE8 + PRESERVE8 + + AREA |.text|, CODE + + EXPORT h264bsdClearMbLayer + +; Input / output registers +pMbLayer RN 0 +size RN 1 +pTmp RN 2 +step RN 3 + +; -- NEON registers -- + +qZero QN Q0.U8 + +;/*------------------------------------------------------------------------------ +; +; Function: h264bsdClearMbLayer +; +; Functional description: +; +; Inputs: +; +; Outputs: +; +; Returns: +; +;------------------------------------------------------------------------------*/ + +h264bsdClearMbLayer + + VMOV qZero, #0 + ADD pTmp, pMbLayer, #16 + MOV step, #32 + SUBS size, size, #64 + +loop + VST1 qZero, [pMbLayer], step + SUBS size, size, #64 + VST1 qZero, [pTmp], step + VST1 qZero, [pMbLayer], step + VST1 qZero, [pTmp], step + BCS loop + + BX lr + END + + diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm/h264bsdCountLeadingZeros.s b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm/h264bsdCountLeadingZeros.s new file mode 100644 index 0000000..c7bd73e --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm/h264bsdCountLeadingZeros.s @@ -0,0 +1,49 @@ +; +; Copyright (C) 2009 The Android Open Source Project +; +; Licensed under the Apache License, Version 2.0 (the "License"); +; you may not use this file except in compliance with the License. +; You may obtain a copy of the License at +; +; http://www.apache.org/licenses/LICENSE-2.0 +; +; Unless required by applicable law or agreed to in writing, software +; distributed under the License is distributed on an "AS IS" BASIS, +; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +; See the License for the specific language governing permissions and +; limitations under the License. +; + + REQUIRE8 + PRESERVE8 + + AREA |.text|, CODE + + EXPORT h264bsdCountLeadingZeros + +; Input / output registers +value RN 0 + +; -- NEON registers -- + +;/*------------------------------------------------------------------------------ +; +; Function: h264bsdCountLeadingZeros +; +; Functional description: +; +; Inputs: +; +; Outputs: +; +; Returns: +; +;------------------------------------------------------------------------------*/ + +h264bsdCountLeadingZeros + + CLZ value, value + BX lr + END + + diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm/h264bsdFillRow7.s b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm/h264bsdFillRow7.s new file mode 100644 index 0000000..5bfac92 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm/h264bsdFillRow7.s @@ -0,0 +1,180 @@ +; +; Copyright (C) 2009 The Android Open Source Project +; +; Licensed under the Apache License, Version 2.0 (the "License"); +; you may not use this file except in compliance with the License. +; You may obtain a copy of the License at +; +; http://www.apache.org/licenses/LICENSE-2.0 +; +; Unless required by applicable law or agreed to in writing, software +; distributed under the License is distributed on an "AS IS" BASIS, +; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +; See the License for the specific language governing permissions and +; limitations under the License. +; + + REQUIRE8 + PRESERVE8 + + AREA |.text|, CODE + + EXPORT h264bsdFillRow7 + +; Input / output registers + +ref RN 0 +fill RN 1 +left RN 2 +tmp2 RN 2 +center RN 3 +right RN 4 +tmp1 RN 5 + +; -- NEON registers -- + +qTmp0 QN Q0.U8 +qTmp1 QN Q1.U8 +dTmp0 DN D0.U8 +dTmp1 DN D1.U8 +dTmp2 DN D2.U8 +dTmp3 DN D3.U8 + + +;/*------------------------------------------------------------------------------ +; +; Function: h264bsdFillRow7 +; +; Functional description: +; +; Inputs: +; +; Outputs: +; +; Returns: +; +;------------------------------------------------------------------------------*/ + +h264bsdFillRow7 + PUSH {r4-r6,lr} + CMP left, #0 + LDR right, [sp,#0x10] + BEQ switch_center + LDRB tmp1, [ref,#0] + +loop_left + SUBS left, left, #1 + STRB tmp1, [fill], #1 + BNE loop_left + +switch_center + ASR tmp2,center,#2 + CMP tmp2,#9 + ADDCC pc,pc,tmp2,LSL #2 + B loop_center + B loop_center + B case_1 + B case_2 + B case_3 + B case_4 + B case_5 + B case_6 + B case_7 + B case_8 +;case_8 +; LDR tmp2, [ref], #4 +; SUB center, center, #4 +; STR tmp2, [fill], #4 +;case_7 +; LDR tmp2, [ref], #4 +; SUB center, center, #4 +; STR tmp2, [fill], #4 +;case_6 +; LDR tmp2, [ref], #4 +; SUB center, center, #4 +; STR tmp2, [fill],#4 +;case_5 +; LDR tmp2, [ref], #4 +; SUB center, center, #4 +; STR tmp2, [fill],#4 +;case_4 +; LDR tmp2, [ref],#4 +; SUB center, center, #4 +; STR tmp2, [fill], #4 +;case_3 +; LDR tmp2, [ref],#4 +; SUB center, center, #4 +; STR tmp2, [fill], #4 +;case_2 +; LDR tmp2, [ref],#4 +; SUB center, center, #4 +; STR tmp2, [fill], #4 +;case_1 +; LDR tmp2, [ref],#4 +; SUB center, center, #4 +; STR tmp2, [fill], #4 + +case_8 + VLD1 {qTmp0, qTmp1}, [ref]! + SUB center, center, #32 + VST1 qTmp0, [fill]! + VST1 qTmp1, [fill]! + B loop_center +case_7 + VLD1 {dTmp0,dTmp1,dTmp2}, [ref]! + SUB center, center, #28 + LDR tmp2, [ref], #4 + VST1 {dTmp0,dTmp1,dTmp2}, [fill]! + STR tmp2, [fill],#4 + B loop_center +case_6 + VLD1 {dTmp0,dTmp1,dTmp2}, [ref]! + SUB center, center, #24 + VST1 {dTmp0,dTmp1,dTmp2}, [fill]! + B loop_center +case_5 + VLD1 qTmp0, [ref]! + SUB center, center, #20 + LDR tmp2, [ref], #4 + VST1 qTmp0, [fill]! + STR tmp2, [fill],#4 + B loop_center +case_4 + VLD1 qTmp0, [ref]! + SUB center, center, #16 + VST1 qTmp0, [fill]! + B loop_center +case_3 + VLD1 dTmp0, [ref]! + SUB center, center, #12 + LDR tmp2, [ref], #4 + VST1 dTmp0, [fill]! + STR tmp2, [fill],#4 + B loop_center +case_2 + LDR tmp2, [ref],#4 + SUB center, center, #4 + STR tmp2, [fill], #4 +case_1 + LDR tmp2, [ref],#4 + SUB center, center, #4 + STR tmp2, [fill], #4 + +loop_center + CMP center, #0 + LDRBNE tmp2, [ref], #1 + SUBNE center, center, #1 + STRBNE tmp2, [fill], #1 + BNE loop_center + CMP right,#0 + POPEQ {r4-r6,pc} + LDRB tmp2, [ref,#-1] + +loop_right + STRB tmp2, [fill], #1 + SUBS right, right, #1 + BNE loop_right + + POP {r4-r6,pc} + END + diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm/h264bsdFlushBits.s b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm/h264bsdFlushBits.s new file mode 100644 index 0000000..21335b8 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm/h264bsdFlushBits.s @@ -0,0 +1,82 @@ +; +; Copyright (C) 2009 The Android Open Source Project +; +; Licensed under the Apache License, Version 2.0 (the "License"); +; you may not use this file except in compliance with the License. +; You may obtain a copy of the License at +; +; http://www.apache.org/licenses/LICENSE-2.0 +; +; Unless required by applicable law or agreed to in writing, software +; distributed under the License is distributed on an "AS IS" BASIS, +; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +; See the License for the specific language governing permissions and +; limitations under the License. +; + + REQUIRE8 + PRESERVE8 + + AREA |.text|, CODE + + EXPORT h264bsdFlushBits + +; Input / output registers +pStrmData RN 0 +numBits RN 1 +readBits RN 2 +strmBuffSize RN 3 +pStrmBuffStart RN 1 +pStrmCurrPos RN 2 +bitPosInWord RN 1 + +; -- NEON registers -- + + + +;/*------------------------------------------------------------------------------ +; +; Function: h264bsdFlushBits +; +; Functional description: +; +; Inputs: +; +; Outputs: +; +; Returns: +; +;------------------------------------------------------------------------------*/ + +h264bsdFlushBits +;// PUSH {r4-r6,lr} + + LDR readBits, [pStrmData, #0x10] + LDR strmBuffSize, [pStrmData, #0xC] + + ADD readBits, readBits, numBits + AND bitPosInWord, readBits, #7 + + STR readBits, [pStrmData, #0x10] + STR bitPosInWord, [pStrmData, #0x8] + + LDR pStrmBuffStart, [pStrmData, #0x0] + + CMP readBits, strmBuffSize, LSL #3 + + BHI end_of_stream + + ADD pStrmCurrPos, pStrmBuffStart, readBits, LSR #3 + STR pStrmCurrPos, [pStrmData, #0x4] + MOV r0, #0 + BX lr +;// POP {r4-r6,pc} + +end_of_stream + MVN r0, #0 + BX lr +;// POP {r4-r6,pc} + + END + + diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm/h264bsdWriteMacroblock.s b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm/h264bsdWriteMacroblock.s new file mode 100644 index 0000000..38a0781 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm/h264bsdWriteMacroblock.s @@ -0,0 +1,152 @@ +; +; Copyright (C) 2009 The Android Open Source Project +; +; Licensed under the Apache License, Version 2.0 (the "License"); +; you may not use this file except in compliance with the License. +; You may obtain a copy of the License at +; +; http://www.apache.org/licenses/LICENSE-2.0 +; +; Unless required by applicable law or agreed to in writing, software +; distributed under the License is distributed on an "AS IS" BASIS, +; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +; See the License for the specific language governing permissions and +; limitations under the License. +; + + REQUIRE8 + PRESERVE8 + + AREA |.text|, CODE + + EXPORT h264bsdWriteMacroblock + +; Input / output registers +image RN 0 +data RN 1 +width RN 2 +luma RN 3 +cb RN 4 +cr RN 5 +cwidth RN 6 + +; -- NEON registers -- + +qRow0 QN Q0.U8 +qRow1 QN Q1.U8 +qRow2 QN Q2.U8 +qRow3 QN Q3.U8 +qRow4 QN Q4.U8 +qRow5 QN Q5.U8 +qRow6 QN Q6.U8 +qRow7 QN Q7.U8 +qRow8 QN Q8.U8 +qRow9 QN Q9.U8 +qRow10 QN Q10.U8 +qRow11 QN Q11.U8 +qRow12 QN Q12.U8 +qRow13 QN Q13.U8 +qRow14 QN Q14.U8 +qRow15 QN Q15.U8 + +dRow0 DN D0.U8 +dRow1 DN D1.U8 +dRow2 DN D2.U8 +dRow3 DN D3.U8 +dRow4 DN D4.U8 +dRow5 DN D5.U8 +dRow6 DN D6.U8 +dRow7 DN D7.U8 +dRow8 DN D8.U8 +dRow9 DN D9.U8 +dRow10 DN D10.U8 +dRow11 DN D11.U8 +dRow12 DN D12.U8 +dRow13 DN D13.U8 +dRow14 DN D14.U8 +dRow15 DN D15.U8 + +;/*------------------------------------------------------------------------------ +; +; Function: h264bsdWriteMacroblock +; +; Functional description: +; Write one macroblock into the image. Both luma and chroma +; components will be written at the same time. +; +; Inputs: +; data pointer to macroblock data to be written, 256 values for +; luma followed by 64 values for both chroma components +; +; Outputs: +; image pointer to the image where the macroblock will be written +; +; Returns: +; none +; +;------------------------------------------------------------------------------*/ + +h264bsdWriteMacroblock + PUSH {r4-r6,lr} + VPUSH {q4-q7} + + LDR width, [image, #4] + LDR luma, [image, #0xC] + LDR cb, [image, #0x10] + LDR cr, [image, #0x14] + + +; Write luma + VLD1 {qRow0, qRow1}, [data]! + LSL width, width, #4 + VLD1 {qRow2, qRow3}, [data]! + LSR cwidth, width, #1 + VST1 {qRow0}, [luma@128], width + VLD1 {qRow4, qRow5}, [data]! + VST1 {qRow1}, [luma@128], width + VLD1 {qRow6, qRow7}, [data]! + VST1 {qRow2}, [luma@128], width + VLD1 {qRow8, qRow9}, [data]! + VST1 {qRow3}, [luma@128], width + VLD1 {qRow10, qRow11}, [data]! + VST1 {qRow4}, [luma@128], width + VLD1 {qRow12, qRow13}, [data]! + VST1 {qRow5}, [luma@128], width + VLD1 {qRow14, qRow15}, [data]! + VST1 {qRow6}, [luma@128], width + + VLD1 {qRow0, qRow1}, [data]! ;cb rows 0,1,2,3 + VST1 {qRow7}, [luma@128], width + VLD1 {qRow2, qRow3}, [data]! ;cb rows 4,5,6,7 + VST1 {qRow8}, [luma@128], width + VLD1 {qRow4, qRow5}, [data]! ;cr rows 0,1,2,3 + VST1 {qRow9}, [luma@128], width + VLD1 {qRow6, qRow7}, [data]! ;cr rows 4,5,6,7 + VST1 {qRow10}, [luma@128], width + VST1 {dRow0}, [cb@64], cwidth + VST1 {dRow8}, [cr@64], cwidth + VST1 {qRow11}, [luma@128], width + VST1 {dRow1}, [cb@64], cwidth + VST1 {dRow9}, [cr@64], cwidth + VST1 {qRow12}, [luma@128], width + VST1 {dRow2}, [cb@64], cwidth + VST1 {dRow10}, [cr@64], cwidth + VST1 {qRow13}, [luma@128], width + VST1 {dRow3}, [cb@64], cwidth + VST1 {dRow11}, [cr@64], cwidth + VST1 {qRow14}, [luma@128], width + VST1 {dRow4}, [cb@64], cwidth + VST1 {dRow12}, [cr@64], cwidth + VST1 {qRow15}, [luma] + VST1 {dRow5}, [cb@64], cwidth + VST1 {dRow13}, [cr@64], cwidth + VST1 {dRow6}, [cb@64], cwidth + VST1 {dRow14}, [cr@64], cwidth + VST1 {dRow7}, [cb@64] + VST1 {dRow15}, [cr@64] + + VPOP {q4-q7} + POP {r4-r6,pc} + END + + diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/asm_common.S b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/asm_common.S new file mode 100644 index 0000000..f39f5c4 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/asm_common.S @@ -0,0 +1,41 @@ +@ +@ Copyright (C) 2009 The Android Open Source Project +@ +@ Licensed under the Apache License, Version 2.0 (the "License"); +@ you may not use this file except in compliance with the License. +@ You may obtain a copy of the License at +@ +@ http://www.apache.org/licenses/LICENSE-2.0 +@ +@ Unless required by applicable law or agreed to in writing, software +@ distributed under the License is distributed on an "AS IS" BASIS, +@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@ See the License for the specific language governing permissions and +@ limitations under the License. +@ + + + + + .macro REQUIRE8 + .eabi_attribute 24, 1 + .endm + + .macro PRESERVE8 + .eabi_attribute 25, 1 + .endm + + + .macro function name, export=0 +.if \export + .global \name +.endif + .type \name, %function + .func \name +\name: + .endm + + .macro endfunction + .endfunc + .endm + diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdClearMbLayer.S b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdClearMbLayer.S new file mode 100644 index 0000000..c8a940e --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdClearMbLayer.S @@ -0,0 +1,68 @@ +@ +@ Copyright (C) 2009 The Android Open Source Project +@ +@ Licensed under the Apache License, Version 2.0 (the "License"); +@ you may not use this file except in compliance with the License. +@ You may obtain a copy of the License at +@ +@ http://www.apache.org/licenses/LICENSE-2.0 +@ +@ Unless required by applicable law or agreed to in writing, software +@ distributed under the License is distributed on an "AS IS" BASIS, +@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@ See the License for the specific language governing permissions and +@ limitations under the License. +@ + +#include "asm_common.S" + + preserve8 + + .fpu neon + .text + +/* Input / output registers */ +#define pMbLayer r0 +#define size r1 +#define pTmp r2 +#define step r3 + +/* -- NEON registers -- */ + +#define qZero Q0.U8 + +/*------------------------------------------------------------------------------ + + Function: h264bsdClearMbLayer + + Functional description: + + Inputs: + + Outputs: + + Returns: + +------------------------------------------------------------------------------*/ + +function h264bsdClearMbLayer, export=1 + + VMOV qZero, #0 + ADD pTmp, pMbLayer, #16 + MOV step, #32 + SUBS size, size, #64 + +loop: + VST1 {qZero}, [pMbLayer], step + SUBS size, size, #64 + VST1 {qZero}, [pTmp], step + VST1 {qZero}, [pMbLayer], step + VST1 {qZero}, [pTmp], step + BCS loop + + BX lr + +endfunction + + + diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdCountLeadingZeros.S b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdCountLeadingZeros.S new file mode 100644 index 0000000..05253d0 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdCountLeadingZeros.S @@ -0,0 +1,48 @@ +@ +@ Copyright (C) 2009 The Android Open Source Project +@ +@ Licensed under the Apache License, Version 2.0 (the "License"); +@ you may not use this file except in compliance with the License. +@ You may obtain a copy of the License at +@ +@ http://www.apache.org/licenses/LICENSE-2.0 +@ +@ Unless required by applicable law or agreed to in writing, software +@ distributed under the License is distributed on an "AS IS" BASIS, +@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@ See the License for the specific language governing permissions and +@ limitations under the License. +@ +#include "asm_common.S" + + preserve8 + .arm + .text + + +/* Input / output registers */ +#define value r0 + +/* -- NEON registers -- */ + +/*------------------------------------------------------------------------------ + + Function: h264bsdCountLeadingZeros + + Functional description: + + Inputs: + + Outputs: + + Returns: + +------------------------------------------------------------------------------*/ + +function h264bsdCountLeadingZeros, export=1 + + CLZ value, value + BX lr + +endfunction + diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdFillRow7.S b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdFillRow7.S new file mode 100644 index 0000000..6955b9a --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdFillRow7.S @@ -0,0 +1,143 @@ +@ +@ Copyright (C) 2009 The Android Open Source Project +@ +@ Licensed under the Apache License, Version 2.0 (the "License"); +@ you may not use this file except in compliance with the License. +@ You may obtain a copy of the License at +@ +@ http://www.apache.org/licenses/LICENSE-2.0 +@ +@ Unless required by applicable law or agreed to in writing, software +@ distributed under the License is distributed on an "AS IS" BASIS, +@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@ See the License for the specific language governing permissions and +@ limitations under the License. +@ + +#include "asm_common.S" + + preserve8 + + .fpu neon + .text + +/* Input / output registers */ + +#define ref r0 +#define fill r1 +#define left r2 +#define tmp2 r2 +#define center r3 +#define right r4 +#define tmp1 r5 + +/* -- NEON registers -- */ + +#define qTmp0 Q0.U8 +#define qTmp1 Q1.U8 +#define dTmp0 D0.U8 +#define dTmp1 D1.U8 +#define dTmp2 D2.U8 +#define dTmp3 D3.U8 + +/* +void h264bsdFillRow7(const u8 * ref, u8 * fill, i32 left, i32 center, + i32 right); +*/ + +function h264bsdFillRow7, export=1 + + PUSH {r4-r6,lr} + CMP left, #0 + LDR right, [sp,#0x10] + BEQ switch_center + LDRB tmp1, [ref,#0] + +loop_left: + SUBS left, left, #1 + STRB tmp1, [fill], #1 + BNE loop_left + +switch_center: + ASR tmp2,center,#2 + CMP tmp2,#9 + ADDCC pc,pc,tmp2,LSL #2 + B loop_center + B loop_center + B case_1 + B case_2 + B case_3 + B case_4 + B case_5 + B case_6 + B case_7 + B case_8 + +case_8: + VLD1 {qTmp0, qTmp1}, [ref]! + SUB center, center, #32 + VST1 {qTmp0}, [fill]! + VST1 {qTmp1}, [fill]! + B loop_center +case_7: + VLD1 {dTmp0,dTmp1,dTmp2}, [ref]! + SUB center, center, #28 + LDR tmp2, [ref], #4 + VST1 {dTmp0,dTmp1,dTmp2}, [fill]! + STR tmp2, [fill],#4 + B loop_center +case_6: + VLD1 {dTmp0,dTmp1,dTmp2}, [ref]! + SUB center, center, #24 + VST1 {dTmp0,dTmp1,dTmp2}, [fill]! + B loop_center +case_5: + VLD1 {qTmp0}, [ref]! + SUB center, center, #20 + LDR tmp2, [ref], #4 + VST1 {qTmp0}, [fill]! + STR tmp2, [fill],#4 + B loop_center +case_4: + VLD1 {qTmp0}, [ref]! + SUB center, center, #16 + VST1 {qTmp0}, [fill]! + B loop_center +case_3: + VLD1 {dTmp0}, [ref]! + SUB center, center, #12 + LDR tmp2, [ref], #4 + VST1 dTmp0, [fill]! + STR tmp2, [fill],#4 + B loop_center +case_2: + LDR tmp2, [ref],#4 + SUB center, center, #4 + STR tmp2, [fill], #4 +case_1: + LDR tmp2, [ref],#4 + SUB center, center, #4 + STR tmp2, [fill], #4 + +loop_center: + CMP center, #0 + BEQ jump + LDRB tmp2, [ref], #1 + SUB center, center, #1 + STRB tmp2, [fill], #1 + BNE loop_center +jump: + CMP right,#0 + POPEQ {r4-r6,pc} + LDRB tmp2, [ref,#-1] + +loop_right: + STRB tmp2, [fill], #1 + SUBS right, right, #1 + BNE loop_right + + POP {r4-r6,pc} + +endfunction + + diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdFlushBits.S b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdFlushBits.S new file mode 100644 index 0000000..b3f3191 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdFlushBits.S @@ -0,0 +1,78 @@ +@ +@ Copyright (C) 2009 The Android Open Source Project +@ +@ Licensed under the Apache License, Version 2.0 (the "License"); +@ you may not use this file except in compliance with the License. +@ You may obtain a copy of the License at +@ +@ http://www.apache.org/licenses/LICENSE-2.0 +@ +@ Unless required by applicable law or agreed to in writing, software +@ distributed under the License is distributed on an "AS IS" BASIS, +@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@ See the License for the specific language governing permissions and +@ limitations under the License. +@ + +#include "asm_common.S" + + preserve8 + + .arm + .text + +/* Input / output registers */ +#define pStrmData r0 +#define numBits r1 +#define readBits r2 +#define strmBuffSize r3 +#define pStrmBuffStart r1 +#define pStrmCurrPos r2 +#define bitPosInWord r1 + +/* Input / output registers */ + + + +/*------------------------------------------------------------------------------ + + Function: h264bsdFlushBits + + Functional description: + + Inputs: + + Outputs: + + Returns: + +------------------------------------------------------------------------------*/ +function h264bsdFlushBits, export=1 + + LDR readBits, [pStrmData, #0x10] + LDR strmBuffSize, [pStrmData, #0xC] + + ADD readBits, readBits, numBits + AND bitPosInWord, readBits, #7 + + STR readBits, [pStrmData, #0x10] + STR bitPosInWord, [pStrmData, #0x8] + + LDR pStrmBuffStart, [pStrmData, #0x0] + + CMP readBits, strmBuffSize, LSL #3 + + BHI end_of_stream + + ADD pStrmCurrPos, pStrmBuffStart, readBits, LSR #3 + STR pStrmCurrPos, [pStrmData, #0x4] + MOV r0, #0 + BX lr + +end_of_stream: + MVN r0, #0 + BX lr + +endfunction + + diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdWriteMacroblock.S b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdWriteMacroblock.S new file mode 100644 index 0000000..495d560 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdWriteMacroblock.S @@ -0,0 +1,157 @@ +@ +@ Copyright (C) 2009 The Android Open Source Project +@ +@ Licensed under the Apache License, Version 2.0 (the "License"); +@ you may not use this file except in compliance with the License. +@ You may obtain a copy of the License at +@ +@ http://www.apache.org/licenses/LICENSE-2.0 +@ +@ Unless required by applicable law or agreed to in writing, software +@ distributed under the License is distributed on an "AS IS" BASIS, +@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@ See the License for the specific language governing permissions and +@ limitations under the License. +@ + +#include "asm_common.S" + + require8 + preserve8 + + .arm + .fpu neon + .text + +/* Input / output registers */ +#define image r0 +#define data r1 +#define width r2 +#define luma r3 +#define cb r4 +#define cr r5 +#define cwidth r6 + +/* -- NEON registers -- */ + +#define qRow0 Q0.U8 +#define qRow1 Q1.U8 +#define qRow2 Q2.U8 +#define qRow3 Q3.U8 +#define qRow4 Q4.U8 +#define qRow5 Q5.U8 +#define qRow6 Q6.U8 +#define qRow7 Q7.U8 +#define qRow8 Q8.U8 +#define qRow9 Q9.U8 +#define qRow10 Q10.U8 +#define qRow11 Q11.U8 +#define qRow12 Q12.U8 +#define qRow13 Q13.U8 +#define qRow14 Q14.U8 +#define qRow15 Q15.U8 + +#define dRow0 D0.U8 +#define dRow1 D1.U8 +#define dRow2 D2.U8 +#define dRow3 D3.U8 +#define dRow4 D4.U8 +#define dRow5 D5.U8 +#define dRow6 D6.U8 +#define dRow7 D7.U8 +#define dRow8 D8.U8 +#define dRow9 D9.U8 +#define dRow10 D10.U8 +#define dRow11 D11.U8 +#define dRow12 D12.U8 +#define dRow13 D13.U8 +#define dRow14 D14.U8 +#define dRow15 D15.U8 + +/*------------------------------------------------------------------------------ + + Function: h264bsdWriteMacroblock + + Functional description: + Write one macroblock into the image. Both luma and chroma + components will be written at the same time. + + Inputs: + data pointer to macroblock data to be written, 256 values for + luma followed by 64 values for both chroma components + + Outputs: + image pointer to the image where the macroblock will be written + + Returns: + none + +------------------------------------------------------------------------------*/ + +function h264bsdWriteMacroblock, export=1 + PUSH {r4-r6,lr} + VPUSH {q4-q7} + + LDR width, [image, #4] + LDR luma, [image, #0xC] + LDR cb, [image, #0x10] + LDR cr, [image, #0x14] + + +@ Write luma + VLD1 {qRow0, qRow1}, [data]! + LSL width, width, #4 + VLD1 {qRow2, qRow3}, [data]! + LSR cwidth, width, #1 + VST1 {qRow0}, [luma,:128], width + VLD1 {qRow4, qRow5}, [data]! + VST1 {qRow1}, [luma,:128], width + VLD1 {qRow6, qRow7}, [data]! + VST1 {qRow2}, [luma,:128], width + VLD1 {qRow8, qRow9}, [data]! + VST1 {qRow3}, [luma,:128], width + VLD1 {qRow10, qRow11}, [data]! + VST1 {qRow4}, [luma,:128], width + VLD1 {qRow12, qRow13}, [data]! + VST1 {qRow5}, [luma,:128], width + VLD1 {qRow14, qRow15}, [data]! + VST1 {qRow6}, [luma,:128], width + + VLD1 {qRow0, qRow1}, [data]! ;//cb rows 0,1,2,3 + VST1 {qRow7}, [luma,:128], width + VLD1 {qRow2, qRow3}, [data]! ;//cb rows 4,5,6,7 + VST1 {qRow8}, [luma,:128], width + VLD1 {qRow4, qRow5}, [data]! ;//cr rows 0,1,2,3 + VST1 {qRow9}, [luma,:128], width + VLD1 {qRow6, qRow7}, [data]! ;//cr rows 4,5,6,7 + VST1 {qRow10}, [luma,:128], width + VST1 {dRow0}, [cb,:64], cwidth + VST1 {dRow8}, [cr,:64], cwidth + VST1 {qRow11}, [luma,:128], width + VST1 {dRow1}, [cb,:64], cwidth + VST1 {dRow9}, [cr,:64], cwidth + VST1 {qRow12}, [luma,:128], width + VST1 {dRow2}, [cb,:64], cwidth + VST1 {dRow10}, [cr,:64], cwidth + VST1 {qRow13}, [luma,:128], width + VST1 {dRow3}, [cb,:64], cwidth + VST1 {dRow11}, [cr,:64], cwidth + VST1 {qRow14}, [luma,:128], width + VST1 {dRow4}, [cb,:64], cwidth + VST1 {dRow12}, [cr,:64], cwidth + VST1 {qRow15}, [luma] + VST1 {dRow5}, [cb,:64], cwidth + VST1 {dRow13}, [cr,:64], cwidth + VST1 {dRow6}, [cb,:64], cwidth + VST1 {dRow14}, [cr,:64], cwidth + VST1 {dRow7}, [cb,:64] + VST1 {dRow15}, [cr,:64] + + VPOP {q4-q7} + POP {r4-r6,pc} +@ BX lr + + .endfunc + + + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_byte_stream.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_byte_stream.c new file mode 100755 index 0000000..db77f8c --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_byte_stream.c @@ -0,0 +1,237 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. External compiler flags + 3. Module defines + 4. Local function prototypes + 5. Functions + ExtractNalUnit + +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "h264bsd_byte_stream.h" +#include "h264bsd_util.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +#define BYTE_STREAM_ERROR 0xFFFFFFFF + +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + + Function name: ExtractNalUnit + + Functional description: + Extracts one NAL unit from the byte stream buffer. Removes + emulation prevention bytes if present. The original stream buffer + is used directly and is therefore modified if emulation prevention + bytes are present in the stream. + + Stream buffer is assumed to contain either exactly one NAL unit + and nothing else, or one or more NAL units embedded in byte + stream format described in the Annex B of the standard. Function + detects which one is used based on the first bytes in the buffer. + + Inputs: + pByteStream pointer to byte stream buffer + len length of the stream buffer (in bytes) + + Outputs: + pStrmData stream information is stored here + readBytes number of bytes "consumed" from the stream buffer + + Returns: + HANTRO_OK success + HANTRO_NOK error in byte stream + +------------------------------------------------------------------------------*/ + +u32 h264bsdExtractNalUnit(u8 *pByteStream, u32 len, strmData_t *pStrmData, + u32 *readBytes) +{ + +/* Variables */ + + u32 i, tmp; + u32 byteCount,initByteCount; + u32 zeroCount; + u8 byte; + u32 hasEmulation = HANTRO_FALSE; + u32 invalidStream = HANTRO_FALSE; + u8 *readPtr, *writePtr; + +/* Code */ + + ASSERT(pByteStream); + ASSERT(len); + ASSERT(len < BYTE_STREAM_ERROR); + ASSERT(pStrmData); + + /* byte stream format if starts with 0x000001 or 0x000000 */ + if (len > 3 && pByteStream[0] == 0x00 && pByteStream[1] == 0x00 && + (pByteStream[2]&0xFE) == 0x00) + { + /* search for NAL unit start point, i.e. point after first start code + * prefix in the stream */ + zeroCount = byteCount = 2; + readPtr = pByteStream + 2; + /*lint -e(716) while(1) used consciously */ + while (1) + { + byte = *readPtr++; + byteCount++; + + if (byteCount == len) + { + /* no start code prefix found -> error */ + *readBytes = len; + return(HANTRO_NOK); + } + + if (!byte) + zeroCount++; + else if ((byte == 0x01) && (zeroCount >= 2)) + break; + else + zeroCount = 0; + } + + initByteCount = byteCount; + + /* determine size of the NAL unit. Search for next start code prefix + * or end of stream and ignore possible trailing zero bytes */ + zeroCount = 0; + /*lint -e(716) while(1) used consciously */ + while (1) + { + byte = *readPtr++; + byteCount++; + if (!byte) + zeroCount++; + + if ( (byte == 0x03) && (zeroCount == 2) ) + { + hasEmulation = HANTRO_TRUE; + } + + if ( (byte == 0x01) && (zeroCount >= 2 ) ) + { + pStrmData->strmBuffSize = + byteCount - initByteCount - zeroCount - 1; + zeroCount -= MIN(zeroCount, 3); + break; + } + else if (byte) + { + if (zeroCount >= 3) + invalidStream = HANTRO_TRUE; + zeroCount = 0; + } + + if (byteCount == len) + { + pStrmData->strmBuffSize = byteCount - initByteCount - zeroCount; + break; + } + + } + } + /* separate NAL units as input -> just set stream params */ + else + { + initByteCount = 0; + zeroCount = 0; + pStrmData->strmBuffSize = len; + hasEmulation = HANTRO_TRUE; + } + + pStrmData->pStrmBuffStart = pByteStream + initByteCount; + pStrmData->pStrmCurrPos = pStrmData->pStrmBuffStart; + pStrmData->bitPosInWord = 0; + pStrmData->strmBuffReadBits = 0; + + /* return number of bytes "consumed" */ + *readBytes = pStrmData->strmBuffSize + initByteCount + zeroCount; + + if (invalidStream) + { + return(HANTRO_NOK); + } + + /* remove emulation prevention bytes before rbsp processing */ + if (hasEmulation) + { + tmp = pStrmData->strmBuffSize; + readPtr = writePtr = pStrmData->pStrmBuffStart; + zeroCount = 0; + for (i = tmp; i--;) + { + if ((zeroCount == 2) && (*readPtr == 0x03)) + { + /* emulation prevention byte shall be followed by one of the + * following bytes: 0x00, 0x01, 0x02, 0x03. This implies that + * emulation prevention 0x03 byte shall not be the last byte + * of the stream. */ + if ( (i == 0) || (*(readPtr+1) > 0x03) ) + return(HANTRO_NOK); + + /* do not write emulation prevention byte */ + readPtr++; + zeroCount = 0; + } + else + { + /* NAL unit shall not contain byte sequences 0x000000, + * 0x000001 or 0x000002 */ + if ( (zeroCount == 2) && (*readPtr <= 0x02) ) + return(HANTRO_NOK); + + if (*readPtr == 0) + zeroCount++; + else + zeroCount = 0; + + *writePtr++ = *readPtr++; + } + } + + /* (readPtr - writePtr) indicates number of "removed" emulation + * prevention bytes -> subtract from stream buffer size */ + pStrmData->strmBuffSize -= (u32)(readPtr - writePtr); + } + + return(HANTRO_OK); + +} + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_byte_stream.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_byte_stream.h new file mode 100755 index 0000000..36aec76 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_byte_stream.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. Module defines + 3. Data types + 4. Function prototypes + +------------------------------------------------------------------------------*/ + +#ifndef H264SWDEC_BYTE_STREAM_H +#define H264SWDEC_BYTE_STREAM_H + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "basetype.h" +#include "h264bsd_stream.h" + +/*------------------------------------------------------------------------------ + 2. Module defines +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 3. Data types +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ + +u32 h264bsdExtractNalUnit(u8 *pByteStream, u32 len, strmData_t *pStrmData, + u32 *readBytes); + +#endif /* #ifdef H264SWDEC_BYTE_STREAM_H */ + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_cavlc.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_cavlc.c new file mode 100755 index 0000000..91d78bd --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_cavlc.c @@ -0,0 +1,916 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. External compiler flags + 3. Module defines + 4. Local function prototypes + 5. Functions + DecodeCoeffToken + DecodeLevelPrefix + DecodeTotalZeros + DecodeRunBefore + DecodeResidualBlockCavlc + +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "h264bsd_cavlc.h" +#include "h264bsd_util.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +/* Following descriptions use term "information field" to represent combination + * of certain decoded symbol value and the length of the corresponding variable + * length code word. For example, total_zeros information field consists of + * 4 bits symbol value (bits [4,7]) along with four bits to represent length + * of the VLC code word (bits [0,3]) */ + +/* macro to obtain length of the coeff token information field, bits [0,4] */ +#define LENGTH_TC(vlc) ((vlc) & 0x1F) +/* macro to obtain length of the other information fields, bits [0,3] */ +#define LENGTH(vlc) ((vlc) & 0xF) +/* macro to obtain code word from the information fields, bits [4,7] */ +#define INFO(vlc) (((vlc) >> 4) & 0xF) /* 4 MSB bits contain information */ +/* macro to obtain trailing ones from the coeff token information word, + * bits [5,10] */ +#define TRAILING_ONES(coeffToken) ((coeffToken>>5) & 0x3F) +/* macro to obtain total coeff from the coeff token information word, + * bits [11,15] */ +#define TOTAL_COEFF(coeffToken) (((coeffToken) >> 11) & 0x1F) + +#define VLC_NOT_FOUND 0xFFFFFFFEU + +/* VLC tables for coeff_token. Because of long codes (max. 16 bits) some of the + * tables have been splitted into multiple separate tables. Each array/table + * element has the following structure: + * [5 bits for tot.coeff.] [6 bits for tr.ones] [5 bits for VLC length] + * If there is a 0x0000 value, it means that there is not corresponding VLC + * codeword for that index. */ + +/* VLC lengths up to 6 bits, 0 <= nC < 2 */ +static const u16 coeffToken0_0[32] = { + 0x0000,0x0000,0x0000,0x2066,0x1026,0x0806,0x1865,0x1865, + 0x1043,0x1043,0x1043,0x1043,0x1043,0x1043,0x1043,0x1043, + 0x0822,0x0822,0x0822,0x0822,0x0822,0x0822,0x0822,0x0822, + 0x0822,0x0822,0x0822,0x0822,0x0822,0x0822,0x0822,0x0822}; + +/* VLC lengths up to 10 bits, 0 <= nC < 2 */ +static const u16 coeffToken0_1[48] = { + 0x0000,0x0000,0x0000,0x0000,0x406a,0x304a,0x282a,0x200a, + 0x3869,0x3869,0x2849,0x2849,0x2029,0x2029,0x1809,0x1809, + 0x3068,0x3068,0x3068,0x3068,0x2048,0x2048,0x2048,0x2048, + 0x1828,0x1828,0x1828,0x1828,0x1008,0x1008,0x1008,0x1008, + 0x2867,0x2867,0x2867,0x2867,0x2867,0x2867,0x2867,0x2867, + 0x1847,0x1847,0x1847,0x1847,0x1847,0x1847,0x1847,0x1847}; + +/* VLC lengths up to 14 bits, 0 <= nC < 2 */ +static const u16 coeffToken0_2[56] = { + 0x606e,0x584e,0x502e,0x500e,0x586e,0x504e,0x482e,0x480e, + 0x400d,0x400d,0x484d,0x484d,0x402d,0x402d,0x380d,0x380d, + 0x506d,0x506d,0x404d,0x404d,0x382d,0x382d,0x300d,0x300d, + 0x486b,0x486b,0x486b,0x486b,0x486b,0x486b,0x486b,0x486b, + 0x384b,0x384b,0x384b,0x384b,0x384b,0x384b,0x384b,0x384b, + 0x302b,0x302b,0x302b,0x302b,0x302b,0x302b,0x302b,0x302b, + 0x280b,0x280b,0x280b,0x280b,0x280b,0x280b,0x280b,0x280b}; + +/* VLC lengths up to 16 bits, 0 <= nC < 2 */ +static const u16 coeffToken0_3[32] = { + 0x0000,0x0000,0x682f,0x682f,0x8010,0x8050,0x8030,0x7810, + 0x8070,0x7850,0x7830,0x7010,0x7870,0x7050,0x7030,0x6810, + 0x706f,0x706f,0x684f,0x684f,0x602f,0x602f,0x600f,0x600f, + 0x686f,0x686f,0x604f,0x604f,0x582f,0x582f,0x580f,0x580f}; + +/* VLC lengths up to 6 bits, 2 <= nC < 4 */ +static const u16 coeffToken2_0[32] = { + 0x0000,0x0000,0x0000,0x0000,0x3866,0x2046,0x2026,0x1006, + 0x3066,0x1846,0x1826,0x0806,0x2865,0x2865,0x1025,0x1025, + 0x2064,0x2064,0x2064,0x2064,0x1864,0x1864,0x1864,0x1864, + 0x1043,0x1043,0x1043,0x1043,0x1043,0x1043,0x1043,0x1043}; + +/* VLC lengths up to 9 bits, 2 <= nC < 4 */ +static const u16 coeffToken2_1[32] = { + 0x0000,0x0000,0x0000,0x0000,0x4869,0x3849,0x3829,0x3009, + 0x2808,0x2808,0x3048,0x3048,0x3028,0x3028,0x2008,0x2008, + 0x4067,0x4067,0x4067,0x4067,0x2847,0x2847,0x2847,0x2847, + 0x2827,0x2827,0x2827,0x2827,0x1807,0x1807,0x1807,0x1807}; + +/* VLC lengths up to 14 bits, 2 <= nC < 4 */ +static const u16 coeffToken2_2[128] = { + 0x0000,0x0000,0x786d,0x786d,0x806e,0x804e,0x802e,0x800e, + 0x782e,0x780e,0x784e,0x702e,0x704d,0x704d,0x700d,0x700d, + 0x706d,0x706d,0x684d,0x684d,0x682d,0x682d,0x680d,0x680d, + 0x686d,0x686d,0x604d,0x604d,0x602d,0x602d,0x600d,0x600d, + 0x580c,0x580c,0x580c,0x580c,0x584c,0x584c,0x584c,0x584c, + 0x582c,0x582c,0x582c,0x582c,0x500c,0x500c,0x500c,0x500c, + 0x606c,0x606c,0x606c,0x606c,0x504c,0x504c,0x504c,0x504c, + 0x502c,0x502c,0x502c,0x502c,0x480c,0x480c,0x480c,0x480c, + 0x586b,0x586b,0x586b,0x586b,0x586b,0x586b,0x586b,0x586b, + 0x484b,0x484b,0x484b,0x484b,0x484b,0x484b,0x484b,0x484b, + 0x482b,0x482b,0x482b,0x482b,0x482b,0x482b,0x482b,0x482b, + 0x400b,0x400b,0x400b,0x400b,0x400b,0x400b,0x400b,0x400b, + 0x506b,0x506b,0x506b,0x506b,0x506b,0x506b,0x506b,0x506b, + 0x404b,0x404b,0x404b,0x404b,0x404b,0x404b,0x404b,0x404b, + 0x402b,0x402b,0x402b,0x402b,0x402b,0x402b,0x402b,0x402b, + 0x380b,0x380b,0x380b,0x380b,0x380b,0x380b,0x380b,0x380b}; + +/* VLC lengths up to 6 bits, 4 <= nC < 8 */ +static const u16 coeffToken4_0[64] = { + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x1806,0x3846,0x3826,0x1006,0x4866,0x3046,0x3026,0x0806, + 0x2825,0x2825,0x2845,0x2845,0x2025,0x2025,0x2045,0x2045, + 0x1825,0x1825,0x4065,0x4065,0x1845,0x1845,0x1025,0x1025, + 0x3864,0x3864,0x3864,0x3864,0x3064,0x3064,0x3064,0x3064, + 0x2864,0x2864,0x2864,0x2864,0x2064,0x2064,0x2064,0x2064, + 0x1864,0x1864,0x1864,0x1864,0x1044,0x1044,0x1044,0x1044, + 0x0824,0x0824,0x0824,0x0824,0x0004,0x0004,0x0004,0x0004}; + +/* VLC lengths up to 10 bits, 4 <= nC < 8 */ +static const u16 coeffToken4_1[128] = { + 0x0000,0x800a,0x806a,0x804a,0x802a,0x780a,0x786a,0x784a, + 0x782a,0x700a,0x706a,0x704a,0x702a,0x680a,0x6829,0x6829, + 0x6009,0x6009,0x6849,0x6849,0x6029,0x6029,0x5809,0x5809, + 0x6869,0x6869,0x6049,0x6049,0x5829,0x5829,0x5009,0x5009, + 0x6068,0x6068,0x6068,0x6068,0x5848,0x5848,0x5848,0x5848, + 0x5028,0x5028,0x5028,0x5028,0x4808,0x4808,0x4808,0x4808, + 0x5868,0x5868,0x5868,0x5868,0x5048,0x5048,0x5048,0x5048, + 0x4828,0x4828,0x4828,0x4828,0x4008,0x4008,0x4008,0x4008, + 0x3807,0x3807,0x3807,0x3807,0x3807,0x3807,0x3807,0x3807, + 0x3007,0x3007,0x3007,0x3007,0x3007,0x3007,0x3007,0x3007, + 0x4847,0x4847,0x4847,0x4847,0x4847,0x4847,0x4847,0x4847, + 0x2807,0x2807,0x2807,0x2807,0x2807,0x2807,0x2807,0x2807, + 0x5067,0x5067,0x5067,0x5067,0x5067,0x5067,0x5067,0x5067, + 0x4047,0x4047,0x4047,0x4047,0x4047,0x4047,0x4047,0x4047, + 0x4027,0x4027,0x4027,0x4027,0x4027,0x4027,0x4027,0x4027, + 0x2007,0x2007,0x2007,0x2007,0x2007,0x2007,0x2007,0x2007}; + +/* fixed 6 bit length VLC, nC <= 8 */ +static const u16 coeffToken8[64] = { + 0x0806,0x0826,0x0000,0x0006,0x1006,0x1026,0x1046,0x0000, + 0x1806,0x1826,0x1846,0x1866,0x2006,0x2026,0x2046,0x2066, + 0x2806,0x2826,0x2846,0x2866,0x3006,0x3026,0x3046,0x3066, + 0x3806,0x3826,0x3846,0x3866,0x4006,0x4026,0x4046,0x4066, + 0x4806,0x4826,0x4846,0x4866,0x5006,0x5026,0x5046,0x5066, + 0x5806,0x5826,0x5846,0x5866,0x6006,0x6026,0x6046,0x6066, + 0x6806,0x6826,0x6846,0x6866,0x7006,0x7026,0x7046,0x7066, + 0x7806,0x7826,0x7846,0x7866,0x8006,0x8026,0x8046,0x8066}; + +/* VLC lengths up to 3 bits, nC == -1 */ +static const u16 coeffTokenMinus1_0[8] = { + 0x0000,0x1043,0x0002,0x0002,0x0821,0x0821,0x0821,0x0821}; + +/* VLC lengths up to 8 bits, nC == -1 */ +static const u16 coeffTokenMinus1_1[32] = { + 0x2067,0x2067,0x2048,0x2028,0x1847,0x1847,0x1827,0x1827, + 0x2006,0x2006,0x2006,0x2006,0x1806,0x1806,0x1806,0x1806, + 0x1006,0x1006,0x1006,0x1006,0x1866,0x1866,0x1866,0x1866, + 0x1026,0x1026,0x1026,0x1026,0x0806,0x0806,0x0806,0x0806}; + +/* VLC tables for total_zeros. One table containing longer code, totalZeros_1, + * has been broken into two separate tables. Table elements have the + * following structure: + * [4 bits for info] [4 bits for VLC length] */ + +/* VLC lengths up to 5 bits */ +static const u8 totalZeros_1_0[32] = { + 0x00,0x00,0x65,0x55,0x44,0x44,0x34,0x34, + 0x23,0x23,0x23,0x23,0x13,0x13,0x13,0x13, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01}; + +/* VLC lengths up to 9 bits */ +static const u8 totalZeros_1_1[32] = { + 0x00,0xf9,0xe9,0xd9,0xc8,0xc8,0xb8,0xb8, + 0xa7,0xa7,0xa7,0xa7,0x97,0x97,0x97,0x97, + 0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86, + 0x76,0x76,0x76,0x76,0x76,0x76,0x76,0x76}; + +static const u8 totalZeros_2[64] = { + 0xe6,0xd6,0xc6,0xb6,0xa5,0xa5,0x95,0x95, + 0x84,0x84,0x84,0x84,0x74,0x74,0x74,0x74, + 0x64,0x64,0x64,0x64,0x54,0x54,0x54,0x54, + 0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43, + 0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33, + 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03}; + +static const u8 totalZeros_3[64] = { + 0xd6,0xb6,0xc5,0xc5,0xa5,0xa5,0x95,0x95, + 0x84,0x84,0x84,0x84,0x54,0x54,0x54,0x54, + 0x44,0x44,0x44,0x44,0x04,0x04,0x04,0x04, + 0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73, + 0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63, + 0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33, + 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13}; + +static const u8 totalZeros_4[32] = { + 0xc5,0xb5,0xa5,0x05,0x94,0x94,0x74,0x74, + 0x34,0x34,0x24,0x24,0x83,0x83,0x83,0x83, + 0x63,0x63,0x63,0x63,0x53,0x53,0x53,0x53, + 0x43,0x43,0x43,0x43,0x13,0x13,0x13,0x13}; + +static const u8 totalZeros_5[32] = { + 0xb5,0x95,0xa4,0xa4,0x84,0x84,0x24,0x24, + 0x14,0x14,0x04,0x04,0x73,0x73,0x73,0x73, + 0x63,0x63,0x63,0x63,0x53,0x53,0x53,0x53, + 0x43,0x43,0x43,0x43,0x33,0x33,0x33,0x33}; + +static const u8 totalZeros_6[64] = { + 0xa6,0x06,0x15,0x15,0x84,0x84,0x84,0x84, + 0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93, + 0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73, + 0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63, + 0x53,0x53,0x53,0x53,0x53,0x53,0x53,0x53, + 0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43, + 0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33, + 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23}; + +static const u8 totalZeros_7[64] = { + 0x96,0x06,0x15,0x15,0x74,0x74,0x74,0x74, + 0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83, + 0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63, + 0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43, + 0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33, + 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23, + 0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52, + 0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52}; + +static const u8 totalZeros_8[64] = { + 0x86,0x06,0x25,0x25,0x14,0x14,0x14,0x14, + 0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73, + 0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63, + 0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33, + 0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52, + 0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52, + 0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42, + 0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42}; + +static const u8 totalZeros_9[64] = { + 0x16,0x06,0x75,0x75,0x24,0x24,0x24,0x24, + 0x53,0x53,0x53,0x53,0x53,0x53,0x53,0x53, + 0x62,0x62,0x62,0x62,0x62,0x62,0x62,0x62, + 0x62,0x62,0x62,0x62,0x62,0x62,0x62,0x62, + 0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42, + 0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42, + 0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x32, + 0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x32}; + +static const u8 totalZeros_10[32] = { + 0x15,0x05,0x64,0x64,0x23,0x23,0x23,0x23, + 0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52, + 0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42, + 0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x32}; + +static const u8 totalZeros_11[16] = { + 0x04,0x14,0x23,0x23,0x33,0x33,0x53,0x53, + 0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41}; + +static const u8 totalZeros_12[16] = { + 0x04,0x14,0x43,0x43,0x22,0x22,0x22,0x22, + 0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31}; + +static const u8 totalZeros_13[8] = {0x03,0x13,0x32,0x32,0x21,0x21,0x21,0x21}; + +static const u8 totalZeros_14[4] = {0x02,0x12,0x21,0x21}; + +/* VLC tables for run_before. Table elements have the following structure: + * [4 bits for info] [4bits for VLC length] + */ + +static const u8 runBefore_6[8] = {0x13,0x23,0x43,0x33,0x63,0x53,0x02,0x02}; + +static const u8 runBefore_5[8] = {0x53,0x43,0x33,0x23,0x12,0x12,0x02,0x02}; + +static const u8 runBefore_4[8] = {0x43,0x33,0x22,0x22,0x12,0x12,0x02,0x02}; + +static const u8 runBefore_3[4] = {0x32,0x22,0x12,0x02}; + +static const u8 runBefore_2[4] = {0x22,0x12,0x01,0x01}; + +static const u8 runBefore_1[2] = {0x11,0x01}; + +/* following four macros are used to handle stream buffer "cache" in the CAVLC + * decoding function */ + +/* macro to initialize stream buffer cache, fills the buffer (32 bits) */ +#define BUFFER_INIT(value, bits) \ +{ \ + bits = 32; \ + value = h264bsdShowBits32(pStrmData); \ +} + +/* macro to read numBits bits from the buffer, bits will be written to + * outVal. Refills the buffer if not enough bits left */ +#define BUFFER_SHOW(value, bits, outVal, numBits) \ +{ \ + if (bits < (numBits)) \ + { \ + if(h264bsdFlushBits(pStrmData,32-bits) == END_OF_STREAM) \ + return(HANTRO_NOK); \ + value = h264bsdShowBits32(pStrmData); \ + bits = 32; \ + } \ + (outVal) = value >> (32 - (numBits)); \ +} + +/* macro to flush numBits bits from the buffer */ +#define BUFFER_FLUSH(value, bits, numBits) \ +{ \ + value <<= (numBits); \ + bits -= (numBits); \ +} + +/* macro to read and flush numBits bits from the buffer, bits will be written + * to outVal. Refills the buffer if not enough bits left */ +#define BUFFER_GET(value, bits, outVal, numBits) \ +{ \ + if (bits < (numBits)) \ + { \ + if(h264bsdFlushBits(pStrmData,32-bits) == END_OF_STREAM) \ + return(HANTRO_NOK); \ + value = h264bsdShowBits32(pStrmData); \ + bits = 32; \ + } \ + (outVal) = value >> (32 - (numBits)); \ + value <<= (numBits); \ + bits -= (numBits); \ +} + +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ + +static u32 DecodeCoeffToken(u32 bits, u32 nc); + +static u32 DecodeLevelPrefix(u32 bits); + +static u32 DecodeTotalZeros(u32 bits, u32 totalCoeff, u32 isChromaDC); + +static u32 DecodeRunBefore(u32 bits,u32 zerosLeft); + +/*------------------------------------------------------------------------------ + + Function: DecodeCoeffToken + + Functional description: + Function to decode coeff_token information field from the stream. + + Inputs: + u32 bits next 16 stream bits + u32 nc nC, see standard for details + + Outputs: + u32 information field (11 bits for value, 5 bits for length) + +------------------------------------------------------------------------------*/ + +u32 DecodeCoeffToken(u32 bits, u32 nc) +{ + +/* Variables */ + + u32 value; + +/* Code */ + + /* standard defines that nc for decoding of chroma dc coefficients is -1, + * represented by u32 here -> -1 maps to 2^32 - 1 */ + ASSERT(nc <= 16 || nc == (u32)(-1)); + + if (nc < 2) + { + if (bits >= 0x8000) + { + value = 0x0001; + } + else if (bits >= 0x0C00) + value = coeffToken0_0[bits >> 10]; + else if (bits >= 0x0100) + value = coeffToken0_1[bits >> 6]; + else if (bits >= 0x0020) + value = coeffToken0_2[(bits>>2)-8]; + else + value = coeffToken0_3[bits]; + } + else if (nc < 4) + { + if (bits >= 0x8000) + { + value = bits & 0x4000 ? 0x0002 : 0x0822; + } + else if (bits >= 0x1000) + value = coeffToken2_0[bits >> 10]; + else if (bits >= 0x0200) + value = coeffToken2_1[bits >> 7]; + else + value = coeffToken2_2[bits>>2]; + } + else if (nc < 8) + { + value = coeffToken4_0[bits >> 10]; + if (!value) + value = coeffToken4_1[bits>>6]; + } + else if (nc <= 16) + { + value = coeffToken8[bits>>10]; + } + else + { + value = coeffTokenMinus1_0[bits >> 13]; + if (!value) + value = coeffTokenMinus1_1[bits>>8]; + } + + return(value); + +} + +/*------------------------------------------------------------------------------ + + Function: DecodeLevelPrefix + + Functional description: + Function to decode level_prefix information field from the stream + + Inputs: + u32 bits next 16 stream bits + + Outputs: + u32 level_prefix information field or VLC_NOT_FOUND + +------------------------------------------------------------------------------*/ + +u32 DecodeLevelPrefix(u32 bits) +{ + +/* Variables */ + + u32 numZeros; + +/* Code */ + + if (bits >= 0x8000) + numZeros = 0; + else if (bits >= 0x4000) + numZeros = 1; + else if (bits >= 0x2000) + numZeros = 2; + else if (bits >= 0x1000) + numZeros = 3; + else if (bits >= 0x0800) + numZeros = 4; + else if (bits >= 0x0400) + numZeros = 5; + else if (bits >= 0x0200) + numZeros = 6; + else if (bits >= 0x0100) + numZeros = 7; + else if (bits >= 0x0080) + numZeros = 8; + else if (bits >= 0x0040) + numZeros = 9; + else if (bits >= 0x0020) + numZeros = 10; + else if (bits >= 0x0010) + numZeros = 11; + else if (bits >= 0x0008) + numZeros = 12; + else if (bits >= 0x0004) + numZeros = 13; + else if (bits >= 0x0002) + numZeros = 14; + else if (bits >= 0x0001) + numZeros = 15; + else /* more than 15 zeros encountered which is an error */ + return(VLC_NOT_FOUND); + + return(numZeros); + +} + +/*------------------------------------------------------------------------------ + + Function: DecodeTotalZeros + + Functional description: + Function to decode total_zeros information field from the stream + + Inputs: + u32 bits next 9 stream bits + u32 totalCoeff total number of coefficients for the block + being decoded + u32 isChromaDC flag to indicate chroma DC block + + Outputs: + u32 information field (4 bits value, 4 bits length) + +------------------------------------------------------------------------------*/ + +u32 DecodeTotalZeros(u32 bits, u32 totalCoeff, u32 isChromaDC) +{ + +/* Variables */ + + u32 value = 0x0; + +/* Code */ + + ASSERT(totalCoeff); + + if (!isChromaDC) + { + ASSERT(totalCoeff < 16); + switch (totalCoeff) + { + case 1: + value = totalZeros_1_0[bits >> 4]; + if (!value) + value = totalZeros_1_1[bits]; + break; + + case 2: + value = totalZeros_2[bits >> 3]; + break; + + case 3: + value = totalZeros_3[bits >> 3]; + break; + + case 4: + value = totalZeros_4[bits >> 4]; + break; + + case 5: + value = totalZeros_5[bits >> 4]; + break; + + case 6: + value = totalZeros_6[bits >> 3]; + break; + + case 7: + value = totalZeros_7[bits >> 3]; + break; + + case 8: + value = totalZeros_8[bits >> 3]; + break; + + case 9: + value = totalZeros_9[bits >> 3]; + break; + + case 10: + value = totalZeros_10[bits >> 4]; + break; + + case 11: + value = totalZeros_11[bits >> 5]; + break; + + case 12: + value = totalZeros_12[bits >> 5]; + break; + + case 13: + value = totalZeros_13[bits >> 6]; + break; + + case 14: + value = totalZeros_14[bits >> 7]; + break; + + default: /* case 15 */ + value = (bits >> 8) ? 0x11 : 0x01; + break; + } + } + else + { + ASSERT(totalCoeff < 4); + bits >>= 6; + if (bits > 3) + value = 0x01; + else + { + if (totalCoeff == 3) + value = 0x11; + else if (bits > 1) + { + value = 0x12; + } + else if (totalCoeff == 2) + value = 0x22; + else if (bits) + value = 0x23; + else + value = 0x33; + } + } + + return(value); + +} + +/*------------------------------------------------------------------------------ + + Function: DecodeRunBefore + + Functional description: + Function to decode run_before information field from the stream + + Inputs: + u32 bits next 11 stream bits + u32 zerosLeft number of zeros left for the current block + + Outputs: + u32 information field (4 bits value, 4 bits length) + +------------------------------------------------------------------------------*/ + +u32 DecodeRunBefore(u32 bits, u32 zerosLeft) +{ + +/* Variables */ + + u32 value = 0x0; + +/* Code */ + + switch (zerosLeft) + { + case 1: + value = runBefore_1[bits>>10]; + break; + + case 2: + value = runBefore_2[bits>>9]; + break; + + case 3: + value = runBefore_3[bits>>9]; + break; + + case 4: + value = runBefore_4[bits>>8]; + break; + + case 5: + value = runBefore_5[bits>>8]; + break; + + case 6: + value = runBefore_6[bits>>8]; + break; + + default: + if (bits >= 0x100) + value = ((7-(bits>>8))<<4)+0x3; + else if (bits >= 0x80) + value = 0x74; + else if (bits >= 0x40) + value = 0x85; + else if (bits >= 0x20) + value = 0x96; + else if (bits >= 0x10) + value = 0xa7; + else if (bits >= 0x8) + value = 0xb8; + else if (bits >= 0x4) + value = 0xc9; + else if (bits >= 0x2) + value = 0xdA; + else if (bits) + value = 0xeB; + if (INFO(value) > zerosLeft) + value = 0; + break; + } + + return(value); + +} + +/*------------------------------------------------------------------------------ + + Function: DecodeResidualBlockCavlc + + Functional description: + Function to decode one CAVLC coded block. This corresponds to + syntax elements residual_block_cavlc() in the standard. + + Inputs: + pStrmData pointer to stream data structure + nc nC value + maxNumCoeff maximum number of residual coefficients + + Outputs: + coeffLevel stores decoded coefficient levels + + Returns: + numCoeffs on bits [4,11] if successful + coeffMap on bits [16,31] if successful, this is bit map + where each bit indicates if the corresponding + coefficient was zero (0) or non-zero (1) + HANTRO_NOK end of stream or error in stream + +------------------------------------------------------------------------------*/ + +u32 h264bsdDecodeResidualBlockCavlc( + strmData_t *pStrmData, + i32 *coeffLevel, + i32 nc, + u32 maxNumCoeff) +{ + +/* Variables */ + + u32 i, tmp, totalCoeff, trailingOnes, suffixLength, levelPrefix; + u32 levelSuffix, zerosLeft, bit; + i32 level[16]; + u32 run[16]; + /* stream "cache" */ + u32 bufferValue; + u32 bufferBits; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(coeffLevel); + ASSERT(nc > -2); + ASSERT(maxNumCoeff == 4 || maxNumCoeff == 15 || maxNumCoeff == 16); + ASSERT(VLC_NOT_FOUND != END_OF_STREAM); + + /* assume that coeffLevel array has been "cleaned" by caller */ + + BUFFER_INIT(bufferValue, bufferBits); + + /*lint -e774 disable lint warning on always false comparison */ + BUFFER_SHOW(bufferValue, bufferBits, bit, 16); + /*lint +e774 */ + tmp = DecodeCoeffToken(bit, (u32)nc); + if (!tmp) + return(HANTRO_NOK); + BUFFER_FLUSH(bufferValue, bufferBits, LENGTH_TC(tmp)); + + totalCoeff = TOTAL_COEFF(tmp); + if (totalCoeff > maxNumCoeff) + return(HANTRO_NOK); + trailingOnes = TRAILING_ONES(tmp); + + if (totalCoeff != 0) + { + i = 0; + /* nonzero coefficients: +/- 1 */ + if (trailingOnes) + { + BUFFER_GET(bufferValue, bufferBits, bit, trailingOnes); + tmp = 1 << (trailingOnes - 1); + for (; tmp; i++) + { + level[i] = bit & tmp ? -1 : 1; + tmp >>= 1; + } + } + + /* other levels */ + if (totalCoeff > 10 && trailingOnes < 3) + suffixLength = 1; + else + suffixLength = 0; + + for (; i < totalCoeff; i++) + { + BUFFER_SHOW(bufferValue, bufferBits, bit, 16); + levelPrefix = DecodeLevelPrefix(bit); + if (levelPrefix == VLC_NOT_FOUND) + return(HANTRO_NOK); + BUFFER_FLUSH(bufferValue, bufferBits, levelPrefix+1); + + if (levelPrefix < 14) + tmp = suffixLength; + else if (levelPrefix == 14) + { + tmp = suffixLength ? suffixLength : 4; + } + else + { + /* setting suffixLength to 1 here corresponds to adding 15 + * to levelCode value if levelPrefix == 15 and + * suffixLength == 0 */ + if (!suffixLength) + suffixLength = 1; + tmp = 12; + } + + if (suffixLength) + levelPrefix <<= suffixLength; + + if (tmp) + { + BUFFER_GET(bufferValue, bufferBits, levelSuffix, tmp); + levelPrefix += levelSuffix; + } + + tmp = levelPrefix; + + if (i == trailingOnes && trailingOnes < 3) + tmp += 2; + + level[i] = (tmp+2)>>1; + + if (suffixLength == 0) + suffixLength = 1; + + if ((level[i] > (3 << (suffixLength - 1))) && suffixLength < 6) + suffixLength++; + + if (tmp & 0x1) + level[i] = -level[i]; + } + + /* zero runs */ + if (totalCoeff < maxNumCoeff) + { + BUFFER_SHOW(bufferValue, bufferBits, bit,9); + zerosLeft = DecodeTotalZeros(bit, totalCoeff, + (u32)(maxNumCoeff == 4)); + if (!zerosLeft) + return(HANTRO_NOK); + BUFFER_FLUSH(bufferValue, bufferBits, LENGTH(zerosLeft)); + zerosLeft = INFO(zerosLeft); + } + else + zerosLeft = 0; + + for (i = 0; i < totalCoeff - 1; i++) + { + if (zerosLeft > 0) + { + BUFFER_SHOW(bufferValue, bufferBits, bit,11); + tmp = DecodeRunBefore(bit, zerosLeft); + if (!tmp) + return(HANTRO_NOK); + BUFFER_FLUSH(bufferValue, bufferBits, LENGTH(tmp)); + run[i] = INFO(tmp); + zerosLeft -= run[i]++; + } + else + { + run[i] = 1; + } + } + + /* combining level and run, levelSuffix variable used to hold coeffMap, + * i.e. bit map indicating which coefficients had non-zero value. */ + + /*lint -esym(771,level,run) level and run are always initialized */ + tmp = zerosLeft; + coeffLevel[tmp] = level[totalCoeff-1]; + levelSuffix = 1 << tmp; + for (i = totalCoeff-1; i--;) + { + tmp += run[i]; + levelSuffix |= 1 << tmp; + coeffLevel[tmp] = level[i]; + } + + } + else + levelSuffix = 0; + + if (h264bsdFlushBits(pStrmData, 32-bufferBits) != HANTRO_OK) + return(HANTRO_NOK); + + return((totalCoeff << 4) | (levelSuffix << 16)); +} + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_cavlc.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_cavlc.h new file mode 100755 index 0000000..80353d3 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_cavlc.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. Module defines + 3. Data types + 4. Function prototypes + +------------------------------------------------------------------------------*/ + +#ifndef H264SWDEC_CAVLC_H +#define H264SWDEC_CAVLC_H + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "basetype.h" +#include "h264bsd_stream.h" + +/*------------------------------------------------------------------------------ + 2. Module defines +------------------------------------------------------------------------------*/ + + +/*------------------------------------------------------------------------------ + 3. Data types +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ + +u32 h264bsdDecodeResidualBlockCavlc( + strmData_t *pStrmData, + i32 *coeffLevel, + i32 nc, + u32 maxNumCoeff); + +#endif /* #ifdef H264SWDEC_CAVLC_H */ + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_cfg.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_cfg.h new file mode 100755 index 0000000..2baba5a --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_cfg.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. Module defines + 3. Data types + 4. Function prototypes + +------------------------------------------------------------------------------*/ + +#ifndef H264SWDEC_CFG_H +#define H264SWDEC_CFG_H + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "basetype.h" + +/*------------------------------------------------------------------------------ + 2. Module defines +------------------------------------------------------------------------------*/ + +#define MAX_NUM_REF_PICS 16 +#define MAX_NUM_SLICE_GROUPS 8 +#define MAX_NUM_SEQ_PARAM_SETS 32 +#define MAX_NUM_PIC_PARAM_SETS 256 + +/*------------------------------------------------------------------------------ + 3. Data types +------------------------------------------------------------------------------*/ + + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ + +#endif /* #ifdef H264SWDEC_CFG_H */ + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_conceal.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_conceal.c new file mode 100755 index 0000000..493fb9e --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_conceal.c @@ -0,0 +1,626 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. External compiler flags + 3. Module defines + 4. Local function prototypes + 5. Functions + h264bsdConceal + ConcealMb + Transform + +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "h264bsd_conceal.h" +#include "h264bsd_util.h" +#include "h264bsd_reconstruct.h" +#include "h264bsd_dpb.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +/*lint -e702 disable lint warning on right shift of signed quantity */ + +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ + +static u32 ConcealMb(mbStorage_t *pMb, image_t *currImage, u32 row, u32 col, + u32 sliceType, u8 *data); + +static void Transform(i32 *data); + +/*------------------------------------------------------------------------------ + + Function name: h264bsdConceal + + Functional description: + Perform error concealment for a picture. Two types of concealment + is performed based on sliceType: + 1) copy from previous picture for P-slices. + 2) concealment from neighbour pixels for I-slices + + I-type concealment is based on ideas presented by Jarno Tulkki. + The concealment algorithm determines frequency domain coefficients + from the neighbour pixels, applies integer transform (the same + transform used in the residual processing) and uses the results as + pixel values for concealed macroblocks. Transform produces 4x4 + array and one pixel value has to be used for 4x4 luma blocks and + 2x2 chroma blocks. + + Similar concealment is performed for whole picture (the choise + of the type is based on last successfully decoded slice header of + the picture but it is handled by the calling function). It is + acknowledged that this may result in wrong type of concealment + when a picture contains both types of slices. However, + determination of slice type macroblock-by-macroblock cannot + be done due to the fact that it is impossible to know to which + slice each corrupted (not successfully decoded) macroblock + belongs. + + The error concealment is started by searching the first propoerly + decoded macroblock and concealing the row containing the macroblock + in question. After that all macroblocks above the row in question + are concealed. Finally concealment of rows below is performed. + The order of concealment for 4x4 picture where macroblock 9 is the + first properly decoded one is as follows (properly decoded + macroblocks marked with 'x', numbers indicating the order of + concealment): + + 4 6 8 10 + 3 5 7 9 + 1 x x 2 + 11 12 13 14 + + If all macroblocks of the picture are lost, the concealment is + copy of previous picture for P-type and setting the image to + constant gray (pixel value 128) for I-type. + + Concealment sets quantization parameter of the concealed + macroblocks to value 40 and macroblock type to intra to enable + deblocking filter to smooth the edges of the concealed areas. + + Inputs: + pStorage pointer to storage structure + currImage pointer to current image structure + sliceType type of the slice + + Outputs: + currImage concealed macroblocks will be written here + + Returns: + HANTRO_OK + +------------------------------------------------------------------------------*/ + +u32 h264bsdConceal(storage_t *pStorage, image_t *currImage, u32 sliceType) +{ + +/* Variables */ + + u32 i, j; + u32 row, col; + u32 width, height; + u8 *refData; + mbStorage_t *mb; + +/* Code */ + + ASSERT(pStorage); + ASSERT(currImage); + + DEBUG(("Concealing %s slice\n", IS_I_SLICE(sliceType) ? + "intra" : "inter")); + + width = currImage->width; + height = currImage->height; + refData = NULL; + /* use reference picture with smallest available index */ + if (IS_P_SLICE(sliceType) || (pStorage->intraConcealmentFlag != 0)) + { + i = 0; + do + { + refData = h264bsdGetRefPicData(pStorage->dpb, i); + i++; + if (i >= 16) + break; + } while (refData == NULL); + } + + i = row = col = 0; + /* find first properly decoded macroblock -> start point for concealment */ + while (i < pStorage->picSizeInMbs && !pStorage->mb[i].decoded) + { + i++; + col++; + if (col == width) + { + row++; + col = 0; + } + } + + /* whole picture lost -> copy previous or set grey */ + if (i == pStorage->picSizeInMbs) + { + if ( (IS_I_SLICE(sliceType) && (pStorage->intraConcealmentFlag == 0)) || + refData == NULL) + H264SwDecMemset(currImage->data, 128, width*height*384); + else + H264SwDecMemcpy(currImage->data, refData, width*height*384); + + pStorage->numConcealedMbs = pStorage->picSizeInMbs; + + /* no filtering if whole picture concealed */ + for (i = 0; i < pStorage->picSizeInMbs; i++) + pStorage->mb[i].disableDeblockingFilterIdc = 1; + + return(HANTRO_OK); + } + + /* start from the row containing the first correct macroblock, conceal the + * row in question, all rows above that row and then continue downwards */ + mb = pStorage->mb + row * width; + for (j = col; j--;) + { + ConcealMb(mb+j, currImage, row, j, sliceType, refData); + mb[j].decoded = 1; + pStorage->numConcealedMbs++; + } + for (j = col + 1; j < width; j++) + { + if (!mb[j].decoded) + { + ConcealMb(mb+j, currImage, row, j, sliceType, refData); + mb[j].decoded = 1; + pStorage->numConcealedMbs++; + } + } + /* if previous row(s) could not be concealed -> conceal them now */ + if (row) + { + for (j = 0; j < width; j++) + { + i = row - 1; + mb = pStorage->mb + i*width + j; + do + { + ConcealMb(mb, currImage, i, j, sliceType, refData); + mb->decoded = 1; + pStorage->numConcealedMbs++; + mb -= width; + } while(i--); + } + } + + /* process rows below the one containing the first correct macroblock */ + for (i = row + 1; i < height; i++) + { + mb = pStorage->mb + i * width; + + for (j = 0; j < width; j++) + { + if (!mb[j].decoded) + { + ConcealMb(mb+j, currImage, i, j, sliceType, refData); + mb[j].decoded = 1; + pStorage->numConcealedMbs++; + } + } + } + + return(HANTRO_OK); +} + +/*------------------------------------------------------------------------------ + + Function name: ConcealMb + + Functional description: + Perform error concealment for one macroblock, location of the + macroblock in the picture indicated by row and col + +------------------------------------------------------------------------------*/ + +u32 ConcealMb(mbStorage_t *pMb, image_t *currImage, u32 row, u32 col, + u32 sliceType, u8 *refData) +{ + +/* Variables */ + + u32 i, j, comp; + u32 hor, ver; + u32 mbNum; + u32 width, height; + u8 *mbPos; + u8 data[384]; + u8 *pData; + i32 tmp; + i32 firstPhase[16]; + i32 *pTmp; + /* neighbours above, below, left and right */ + i32 a[4], b[4], l[4], r[4]; + u32 A, B, L, R; +#ifdef H264DEC_OMXDL + u8 fillBuff[32*21 + 15 + 32]; + u8 *pFill; +#endif +/* Code */ + + ASSERT(pMb); + ASSERT(!pMb->decoded); + ASSERT(currImage); + ASSERT(col < currImage->width); + ASSERT(row < currImage->height); + +#ifdef H264DEC_OMXDL + pFill = ALIGN(fillBuff, 16); +#endif + width = currImage->width; + height = currImage->height; + mbNum = row * width + col; + + h264bsdSetCurrImageMbPointers(currImage, mbNum); + + mbPos = currImage->data + row * 16 * width * 16 + col * 16; + A = B = L = R = HANTRO_FALSE; + + /* set qpY to 40 to enable some filtering in deblocking (stetson value) */ + pMb->qpY = 40; + pMb->disableDeblockingFilterIdc = 0; + /* mbType set to intra to perform filtering despite the values of other + * boundary strength determination fields */ + pMb->mbType = I_4x4; + pMb->filterOffsetA = 0; + pMb->filterOffsetB = 0; + pMb->chromaQpIndexOffset = 0; + + if (IS_I_SLICE(sliceType)) + H264SwDecMemset(data, 0, sizeof(data)); + else + { + mv_t mv = {0,0}; + image_t refImage; + refImage.width = width; + refImage.height = height; + refImage.data = refData; + if (refImage.data) + { +#ifndef H264DEC_OMXDL + h264bsdPredictSamples(data, &mv, &refImage, col*16, row*16, + 0, 0, 16, 16); +#else + h264bsdPredictSamples(data, &mv, &refImage, + ((row*16) + ((col*16)<<16)), + 0x00001010, pFill); +#endif + h264bsdWriteMacroblock(currImage, data); + + return(HANTRO_OK); + } + else + H264SwDecMemset(data, 0, sizeof(data)); + } + + H264SwDecMemset(firstPhase, 0, sizeof(firstPhase)); + + /* counter for number of neighbours used */ + j = 0; + hor = ver = 0; + if (row && (pMb-width)->decoded) + { + A = HANTRO_TRUE; + pData = mbPos - width*16; + a[0] = *pData++; a[0] += *pData++; a[0] += *pData++; a[0] += *pData++; + a[1] = *pData++; a[1] += *pData++; a[1] += *pData++; a[1] += *pData++; + a[2] = *pData++; a[2] += *pData++; a[2] += *pData++; a[2] += *pData++; + a[3] = *pData++; a[3] += *pData++; a[3] += *pData++; a[3] += *pData++; + j++; + hor++; + firstPhase[0] += a[0] + a[1] + a[2] + a[3]; + firstPhase[1] += a[0] + a[1] - a[2] - a[3]; + } + if ((row != height - 1) && (pMb+width)->decoded) + { + B = HANTRO_TRUE; + pData = mbPos + 16*width*16; + b[0] = *pData++; b[0] += *pData++; b[0] += *pData++; b[0] += *pData++; + b[1] = *pData++; b[1] += *pData++; b[1] += *pData++; b[1] += *pData++; + b[2] = *pData++; b[2] += *pData++; b[2] += *pData++; b[2] += *pData++; + b[3] = *pData++; b[3] += *pData++; b[3] += *pData++; b[3] += *pData++; + j++; + hor++; + firstPhase[0] += b[0] + b[1] + b[2] + b[3]; + firstPhase[1] += b[0] + b[1] - b[2] - b[3]; + } + if (col && (pMb-1)->decoded) + { + L = HANTRO_TRUE; + pData = mbPos - 1; + l[0] = pData[0]; l[0] += pData[16*width]; + l[0] += pData[32*width]; l[0] += pData[48*width]; + pData += 64*width; + l[1] = pData[0]; l[1] += pData[16*width]; + l[1] += pData[32*width]; l[1] += pData[48*width]; + pData += 64*width; + l[2] = pData[0]; l[2] += pData[16*width]; + l[2] += pData[32*width]; l[2] += pData[48*width]; + pData += 64*width; + l[3] = pData[0]; l[3] += pData[16*width]; + l[3] += pData[32*width]; l[3] += pData[48*width]; + j++; + ver++; + firstPhase[0] += l[0] + l[1] + l[2] + l[3]; + firstPhase[4] += l[0] + l[1] - l[2] - l[3]; + } + if ((col != width - 1) && (pMb+1)->decoded) + { + R = HANTRO_TRUE; + pData = mbPos + 16; + r[0] = pData[0]; r[0] += pData[16*width]; + r[0] += pData[32*width]; r[0] += pData[48*width]; + pData += 64*width; + r[1] = pData[0]; r[1] += pData[16*width]; + r[1] += pData[32*width]; r[1] += pData[48*width]; + pData += 64*width; + r[2] = pData[0]; r[2] += pData[16*width]; + r[2] += pData[32*width]; r[2] += pData[48*width]; + pData += 64*width; + r[3] = pData[0]; r[3] += pData[16*width]; + r[3] += pData[32*width]; r[3] += pData[48*width]; + j++; + ver++; + firstPhase[0] += r[0] + r[1] + r[2] + r[3]; + firstPhase[4] += r[0] + r[1] - r[2] - r[3]; + } + + /* at least one properly decoded neighbour available */ + ASSERT(j); + + /*lint -esym(644,l,r,a,b) variable initialized above */ + if (!hor && L && R) + firstPhase[1] = (l[0]+l[1]+l[2]+l[3]-r[0]-r[1]-r[2]-r[3]) >> 5; + else if (hor) + firstPhase[1] >>= (3+hor); + + if (!ver && A && B) + firstPhase[4] = (a[0]+a[1]+a[2]+a[3]-b[0]-b[1]-b[2]-b[3]) >> 5; + else if (ver) + firstPhase[4] >>= (3+ver); + + switch (j) + { + case 1: + firstPhase[0] >>= 4; + break; + + case 2: + firstPhase[0] >>= 5; + break; + + case 3: + /* approximate (firstPhase[0]*4/3)>>6 */ + firstPhase[0] = (21 * firstPhase[0]) >> 10; + break; + + default: /* 4 */ + firstPhase[0] >>= 6; + break; + + } + + + Transform(firstPhase); + + for (i = 0, pData = data, pTmp = firstPhase; i < 256;) + { + tmp = pTmp[(i & 0xF)>>2]; + /*lint -e734 CLIP1 macro results in value that fits into 8 bits */ + *pData++ = CLIP1(tmp); + /*lint +e734 */ + + i++; + if (!(i & 0x3F)) + pTmp += 4; + } + + /* chroma components */ + mbPos = currImage->data + width * height * 256 + + row * 8 * width * 8 + col * 8; + for (comp = 0; comp < 2; comp++) + { + + H264SwDecMemset(firstPhase, 0, sizeof(firstPhase)); + + /* counter for number of neighbours used */ + j = 0; + hor = ver = 0; + if (A) + { + pData = mbPos - width*8; + a[0] = *pData++; a[0] += *pData++; + a[1] = *pData++; a[1] += *pData++; + a[2] = *pData++; a[2] += *pData++; + a[3] = *pData++; a[3] += *pData++; + j++; + hor++; + firstPhase[0] += a[0] + a[1] + a[2] + a[3]; + firstPhase[1] += a[0] + a[1] - a[2] - a[3]; + } + if (B) + { + pData = mbPos + 8*width*8; + b[0] = *pData++; b[0] += *pData++; + b[1] = *pData++; b[1] += *pData++; + b[2] = *pData++; b[2] += *pData++; + b[3] = *pData++; b[3] += *pData++; + j++; + hor++; + firstPhase[0] += b[0] + b[1] + b[2] + b[3]; + firstPhase[1] += b[0] + b[1] - b[2] - b[3]; + } + if (L) + { + pData = mbPos - 1; + l[0] = pData[0]; l[0] += pData[8*width]; + pData += 16*width; + l[1] = pData[0]; l[1] += pData[8*width]; + pData += 16*width; + l[2] = pData[0]; l[2] += pData[8*width]; + pData += 16*width; + l[3] = pData[0]; l[3] += pData[8*width]; + j++; + ver++; + firstPhase[0] += l[0] + l[1] + l[2] + l[3]; + firstPhase[4] += l[0] + l[1] - l[2] - l[3]; + } + if (R) + { + pData = mbPos + 8; + r[0] = pData[0]; r[0] += pData[8*width]; + pData += 16*width; + r[1] = pData[0]; r[1] += pData[8*width]; + pData += 16*width; + r[2] = pData[0]; r[2] += pData[8*width]; + pData += 16*width; + r[3] = pData[0]; r[3] += pData[8*width]; + j++; + ver++; + firstPhase[0] += r[0] + r[1] + r[2] + r[3]; + firstPhase[4] += r[0] + r[1] - r[2] - r[3]; + } + if (!hor && L && R) + firstPhase[1] = (l[0]+l[1]+l[2]+l[3]-r[0]-r[1]-r[2]-r[3]) >> 4; + else if (hor) + firstPhase[1] >>= (2+hor); + + if (!ver && A && B) + firstPhase[4] = (a[0]+a[1]+a[2]+a[3]-b[0]-b[1]-b[2]-b[3]) >> 4; + else if (ver) + firstPhase[4] >>= (2+ver); + + switch (j) + { + case 1: + firstPhase[0] >>= 3; + break; + + case 2: + firstPhase[0] >>= 4; + break; + + case 3: + /* approximate (firstPhase[0]*4/3)>>5 */ + firstPhase[0] = (21 * firstPhase[0]) >> 9; + break; + + default: /* 4 */ + firstPhase[0] >>= 5; + break; + + } + + Transform(firstPhase); + + pData = data + 256 + comp*64; + for (i = 0, pTmp = firstPhase; i < 64;) + { + tmp = pTmp[(i & 0x7)>>1]; + /*lint -e734 CLIP1 macro results in value that fits into 8 bits */ + *pData++ = CLIP1(tmp); + /*lint +e734 */ + + i++; + if (!(i & 0xF)) + pTmp += 4; + } + + /* increment pointers for cr */ + mbPos += width * height * 64; + } + + h264bsdWriteMacroblock(currImage, data); + + return(HANTRO_OK); + +} + + +/*------------------------------------------------------------------------------ + + Function name: Transform + + Functional description: + Simplified transform, assuming that only dc component and lowest + horizontal and lowest vertical component may be non-zero + +------------------------------------------------------------------------------*/ + +void Transform(i32 *data) +{ + + u32 col; + i32 tmp0, tmp1; + + if (!data[1] && !data[4]) + { + data[1] = data[2] = data[3] = data[4] = data[5] = + data[6] = data[7] = data[8] = data[9] = data[10] = + data[11] = data[12] = data[13] = data[14] = data[15] = data[0]; + return; + } + /* first horizontal transform for rows 0 and 1 */ + tmp0 = data[0]; + tmp1 = data[1]; + data[0] = tmp0 + tmp1; + data[1] = tmp0 + (tmp1>>1); + data[2] = tmp0 - (tmp1>>1); + data[3] = tmp0 - tmp1; + + tmp0 = data[4]; + data[5] = tmp0; + data[6] = tmp0; + data[7] = tmp0; + + /* then vertical transform */ + for (col = 4; col--; data++) + { + tmp0 = data[0]; + tmp1 = data[4]; + data[0] = tmp0 + tmp1; + data[4] = tmp0 + (tmp1>>1); + data[8] = tmp0 - (tmp1>>1); + data[12] = tmp0 - tmp1; + } + +} +/*lint +e702 */ + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_conceal.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_conceal.h new file mode 100755 index 0000000..3134670 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_conceal.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. Module defines + 3. Data types + 4. Function prototypes + +------------------------------------------------------------------------------*/ + +#ifndef H264SWDEC_CONCEAL_H +#define H264SWDEC_CONCEAL_H + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "basetype.h" +#include "h264bsd_slice_header.h" +#include "h264bsd_storage.h" + +/*------------------------------------------------------------------------------ + 2. Module defines +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 3. Data types +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ + +u32 h264bsdConceal(storage_t *pStorage, image_t *currImage, u32 sliceType); + +#endif /* #ifdef H264SWDEC_CONCEAL_H */ + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_container.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_container.h new file mode 100755 index 0000000..99b74a0 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_container.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. Module defines + 3. Data types + 4. Function prototypes + +------------------------------------------------------------------------------*/ + +#ifndef H264SWDEC_CONTAINER_H +#define H264SWDEC_CONTAINER_H + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "basetype.h" +#include "h264bsd_storage.h" + +/*------------------------------------------------------------------------------ + 2. Module defines +------------------------------------------------------------------------------*/ + +/* String length for tracing */ +#define H264DEC_TRACE_STR_LEN 100 + +/*------------------------------------------------------------------------------ + 3. Data types +------------------------------------------------------------------------------*/ + +typedef struct +{ + enum { + UNINITIALIZED, + INITIALIZED, + NEW_HEADERS + } decStat; + + u32 picNumber; + storage_t storage; +#ifdef H264DEC_TRACE + char str[H264DEC_TRACE_STR_LEN]; +#endif +} decContainer_t; + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ + +#endif /* #ifdef H264SWDEC_DECCONTAINER_H */ + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_deblocking.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_deblocking.c new file mode 100755 index 0000000..f8c1f76 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_deblocking.c @@ -0,0 +1,2417 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. External compiler flags + 3. Module defines + 4. Local function prototypes + 5. Functions + h264bsdFilterPicture + FilterVerLumaEdge + FilterHorLumaEdge + FilterHorLuma + FilterVerChromaEdge + FilterHorChromaEdge + FilterHorChroma + InnerBoundaryStrength + EdgeBoundaryStrength + GetBoundaryStrengths + IsSliceBoundaryOnLeft + IsSliceBoundaryOnTop + GetMbFilteringFlags + GetLumaEdgeThresholds + GetChromaEdgeThresholds + FilterLuma + FilterChroma + +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "basetype.h" +#include "h264bsd_util.h" +#include "h264bsd_macroblock_layer.h" +#include "h264bsd_deblocking.h" +#include "h264bsd_dpb.h" + +#ifdef H264DEC_OMXDL +#include "omxtypes.h" +#include "omxVC.h" +#include "armVC.h" +#endif /* H264DEC_OMXDL */ + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +/* Switch off the following Lint messages for this file: + * Info 701: Shift left of signed quantity (int) + * Info 702: Shift right of signed quantity (int) + */ +/*lint -e701 -e702 */ + +/* array of alpha values, from the standard */ +static const u8 alphas[52] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,5,6,7,8,9,10, + 12,13,15,17,20,22,25,28,32,36,40,45,50,56,63,71,80,90,101,113,127,144,162, + 182,203,226,255,255}; + +/* array of beta values, from the standard */ +static const u8 betas[52] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,3,3,3,3,4,4, + 4,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,16,16,17,17,18,18}; + + + +#ifndef H264DEC_OMXDL +/* array of tc0 values, from the standard, each triplet corresponds to a + * column in the table. Indexing goes as tc0[indexA][bS-1] */ +static const u8 tc0[52][3] = { + {0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0}, + {0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0}, + {0,0,0},{0,0,1},{0,0,1},{0,0,1},{0,0,1},{0,1,1},{0,1,1},{1,1,1}, + {1,1,1},{1,1,1},{1,1,1},{1,1,2},{1,1,2},{1,1,2},{1,1,2},{1,2,3}, + {1,2,3},{2,2,3},{2,2,4},{2,3,4},{2,3,4},{3,3,5},{3,4,6},{3,4,6}, + {4,5,7},{4,5,8},{4,6,9},{5,7,10},{6,8,11},{6,8,13},{7,10,14},{8,11,16}, + {9,12,18},{10,13,20},{11,15,23},{13,17,25} +}; +#else +/* array of tc0 values, from the standard, each triplet corresponds to a + * column in the table. Indexing goes as tc0[indexA][bS] */ +static const u8 tc0[52][5] = { + {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, {0, 0, 0, 1, 0}, {0, 0, 0, 1, 0}, {0, 0, 0, 1, 0}, + {0, 0, 0, 1, 0}, {0, 0, 1, 1, 0}, {0, 0, 1, 1, 0}, {0, 1, 1, 1, 0}, + {0, 1, 1, 1, 0}, {0, 1, 1, 1, 0}, {0, 1, 1, 1, 0}, {0, 1, 1, 2, 0}, + {0, 1, 1, 2, 0}, {0, 1, 1, 2, 0}, {0, 1, 1, 2, 0}, {0, 1, 2, 3, 0}, + {0, 1, 2, 3, 0}, {0, 2, 2, 3, 0}, {0, 2, 2, 4, 0}, {0, 2, 3, 4, 0}, + {0, 2, 3, 4, 0}, {0, 3, 3, 5, 0}, {0, 3, 4, 6, 0}, {0, 3, 4, 6, 0}, + {0, 4, 5, 7, 0}, {0, 4, 5, 8, 0}, {0, 4, 6, 9, 0}, {0, 5, 7, 10, 0}, + {0, 6, 8, 11, 0}, {0, 6, 8, 13, 0}, {0, 7, 10, 14, 0}, + {0, 8, 11, 16, 0}, {0, 9, 12, 18, 0}, {0, 10, 13, 20, 0}, + {0, 11, 15, 23, 0}, {0, 13, 17, 25, 0} +}; +#endif + + +#ifndef H264DEC_OMXDL +/* mapping of raster scan block index to 4x4 block index */ +static const u32 mb4x4Index[16] = + {0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15}; + +typedef struct { + const u8 *tc0; + u32 alpha; + u32 beta; +} edgeThreshold_t; + +typedef struct { + u32 top; + u32 left; +} bS_t; + +enum { TOP = 0, LEFT = 1, INNER = 2 }; +#endif /* H264DEC_OMXDL */ + +#define FILTER_LEFT_EDGE 0x04 +#define FILTER_TOP_EDGE 0x02 +#define FILTER_INNER_EDGE 0x01 + + +/* clipping table defined in intra_prediction.c */ +extern const u8 h264bsdClip[]; + +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ + +static u32 InnerBoundaryStrength(mbStorage_t *mb1, u32 i1, u32 i2); + +#ifndef H264DEC_OMXDL +static u32 EdgeBoundaryStrength(mbStorage_t *mb1, mbStorage_t *mb2, + u32 i1, u32 i2); +#else +static u32 InnerBoundaryStrength2(mbStorage_t *mb1, u32 i1, u32 i2); +static u32 EdgeBoundaryStrengthLeft(mbStorage_t *mb1, mbStorage_t *mb2); +static u32 EdgeBoundaryStrengthTop(mbStorage_t *mb1, mbStorage_t *mb2); +#endif + +static u32 IsSliceBoundaryOnLeft(mbStorage_t *mb); + +static u32 IsSliceBoundaryOnTop(mbStorage_t *mb); + +static u32 GetMbFilteringFlags(mbStorage_t *mb); + +#ifndef H264DEC_OMXDL + +static u32 GetBoundaryStrengths(mbStorage_t *mb, bS_t *bs, u32 flags); + +static void FilterLuma(u8 *data, bS_t *bS, edgeThreshold_t *thresholds, + u32 imageWidth); + +static void FilterChroma(u8 *cb, u8 *cr, bS_t *bS, edgeThreshold_t *thresholds, + u32 imageWidth); + +static void FilterVerLumaEdge( u8 *data, u32 bS, edgeThreshold_t *thresholds, + u32 imageWidth); +static void FilterHorLumaEdge( u8 *data, u32 bS, edgeThreshold_t *thresholds, + i32 imageWidth); +static void FilterHorLuma( u8 *data, u32 bS, edgeThreshold_t *thresholds, + i32 imageWidth); + +static void FilterVerChromaEdge( u8 *data, u32 bS, edgeThreshold_t *thresholds, + u32 imageWidth); +static void FilterHorChromaEdge( u8 *data, u32 bS, edgeThreshold_t *thresholds, + i32 imageWidth); +static void FilterHorChroma( u8 *data, u32 bS, edgeThreshold_t *thresholds, + i32 imageWidth); + +static void GetLumaEdgeThresholds( + edgeThreshold_t *thresholds, + mbStorage_t *mb, + u32 filteringFlags); + +static void GetChromaEdgeThresholds( + edgeThreshold_t *thresholds, + mbStorage_t *mb, + u32 filteringFlags, + i32 chromaQpIndexOffset); + +#else /* H264DEC_OMXDL */ + +static u32 GetBoundaryStrengths(mbStorage_t *mb, u8 (*bs)[16], u32 flags); + +static void GetLumaEdgeThresholds( + mbStorage_t *mb, + u8 (*alpha)[2], + u8 (*beta)[2], + u8 (*threshold)[16], + u8 (*bs)[16], + u32 filteringFlags ); + +static void GetChromaEdgeThresholds( + mbStorage_t *mb, + u8 (*alpha)[2], + u8 (*beta)[2], + u8 (*threshold)[8], + u8 (*bs)[16], + u32 filteringFlags, + i32 chromaQpIndexOffset); + +#endif /* H264DEC_OMXDL */ + +/*------------------------------------------------------------------------------ + + Function: IsSliceBoundaryOnLeft + + Functional description: + Function to determine if there is a slice boundary on the left side + of a macroblock. + +------------------------------------------------------------------------------*/ +u32 IsSliceBoundaryOnLeft(mbStorage_t *mb) +{ + +/* Variables */ + +/* Code */ + + ASSERT(mb && mb->mbA); + + if (mb->sliceId != mb->mbA->sliceId) + return(HANTRO_TRUE); + else + return(HANTRO_FALSE); + +} + +/*------------------------------------------------------------------------------ + + Function: IsSliceBoundaryOnTop + + Functional description: + Function to determine if there is a slice boundary above the + current macroblock. + +------------------------------------------------------------------------------*/ +u32 IsSliceBoundaryOnTop(mbStorage_t *mb) +{ + +/* Variables */ + +/* Code */ + + ASSERT(mb && mb->mbB); + + if (mb->sliceId != mb->mbB->sliceId) + return(HANTRO_TRUE); + else + return(HANTRO_FALSE); + +} + +/*------------------------------------------------------------------------------ + + Function: GetMbFilteringFlags + + Functional description: + Function to determine which edges of a macroblock has to be + filtered. Output is a bit-wise OR of FILTER_LEFT_EDGE, + FILTER_TOP_EDGE and FILTER_INNER_EDGE, depending on which edges + shall be filtered. + +------------------------------------------------------------------------------*/ +u32 GetMbFilteringFlags(mbStorage_t *mb) +{ + +/* Variables */ + + u32 flags = 0; + +/* Code */ + + ASSERT(mb); + + /* nothing will be filtered if disableDeblockingFilterIdc == 1 */ + if (mb->disableDeblockingFilterIdc != 1) + { + flags |= FILTER_INNER_EDGE; + + /* filterLeftMbEdgeFlag, left mb is MB_A */ + if (mb->mbA && + ((mb->disableDeblockingFilterIdc != 2) || + !IsSliceBoundaryOnLeft(mb))) + flags |= FILTER_LEFT_EDGE; + + /* filterTopMbEdgeFlag */ + if (mb->mbB && + ((mb->disableDeblockingFilterIdc != 2) || + !IsSliceBoundaryOnTop(mb))) + flags |= FILTER_TOP_EDGE; + } + + return(flags); + +} + +/*------------------------------------------------------------------------------ + + Function: InnerBoundaryStrength + + Functional description: + Function to calculate boundary strength value bs for an inner + edge of a macroblock. Macroblock type is checked before this is + called -> no intra mb condition here. + +------------------------------------------------------------------------------*/ +u32 InnerBoundaryStrength(mbStorage_t *mb1, u32 ind1, u32 ind2) +{ + i32 tmp1, tmp2; + i32 mv1, mv2, mv3, mv4; + + tmp1 = mb1->totalCoeff[ind1]; + tmp2 = mb1->totalCoeff[ind2]; + mv1 = mb1->mv[ind1].hor; + mv2 = mb1->mv[ind2].hor; + mv3 = mb1->mv[ind1].ver; + mv4 = mb1->mv[ind2].ver; + + if (tmp1 || tmp2) + { + return 2; + } + else if ( (ABS(mv1 - mv2) >= 4) || (ABS(mv3 - mv4) >= 4) || + (mb1->refAddr[ind1 >> 2] != mb1->refAddr[ind2 >> 2]) ) + { + return 1; + } + else + return 0; +} + +/*------------------------------------------------------------------------------ + + Function: InnerBoundaryStrength2 + + Functional description: + Function to calculate boundary strength value bs for an inner + edge of a macroblock. The function is the same as + InnerBoundaryStrength but without checking totalCoeff. + +------------------------------------------------------------------------------*/ +u32 InnerBoundaryStrength2(mbStorage_t *mb1, u32 ind1, u32 ind2) +{ + i32 tmp1, tmp2, tmp3, tmp4; + + tmp1 = mb1->mv[ind1].hor; + tmp2 = mb1->mv[ind2].hor; + tmp3 = mb1->mv[ind1].ver; + tmp4 = mb1->mv[ind2].ver; + + if ( (ABS(tmp1 - tmp2) >= 4) || (ABS(tmp3 - tmp4) >= 4) || + (mb1->refAddr[ind1 >> 2] != mb1->refAddr[ind2 >> 2])) + { + return 1; + } + else + return 0; +} +#ifndef H264DEC_OMXDL +/*------------------------------------------------------------------------------ + + Function: EdgeBoundaryStrength + + Functional description: + Function to calculate boundary strength value bs for left- or + top-most edge of a macroblock. Macroblock types are checked + before this is called -> no intra mb conditions here. + +------------------------------------------------------------------------------*/ +u32 EdgeBoundaryStrength(mbStorage_t *mb1, mbStorage_t *mb2, + u32 ind1, u32 ind2) +{ + + if (mb1->totalCoeff[ind1] || mb2->totalCoeff[ind2]) + { + return 2; + } + else if ((mb1->refAddr[ind1 >> 2] != mb2->refAddr[ind2 >> 2]) || + (ABS(mb1->mv[ind1].hor - mb2->mv[ind2].hor) >= 4) || + (ABS(mb1->mv[ind1].ver - mb2->mv[ind2].ver) >= 4)) + { + return 1; + } + else + return 0; +} + +#else /* H264DEC_OMXDL */ + +/*------------------------------------------------------------------------------ + + Function: EdgeBoundaryStrengthTop + + Functional description: + Function to calculate boundary strength value bs for + top-most edge of a macroblock. Macroblock types are checked + before this is called -> no intra mb conditions here. + +------------------------------------------------------------------------------*/ +u32 EdgeBoundaryStrengthTop(mbStorage_t *mb1, mbStorage_t *mb2) +{ + u32 topBs = 0; + u32 tmp1, tmp2, tmp3, tmp4; + + tmp1 = mb1->totalCoeff[0]; + tmp2 = mb2->totalCoeff[10]; + tmp3 = mb1->totalCoeff[1]; + tmp4 = mb2->totalCoeff[11]; + if (tmp1 || tmp2) + { + topBs = 2<<0; + } + else if ((ABS(mb1->mv[0].hor - mb2->mv[10].hor) >= 4) || + (ABS(mb1->mv[0].ver - mb2->mv[10].ver) >= 4) || + (mb1->refAddr[0] != mb2->refAddr[10 >> 2])) + { + topBs = 1<<0; + } + tmp1 = mb1->totalCoeff[4]; + tmp2 = mb2->totalCoeff[14]; + if (tmp3 || tmp4) + { + topBs += 2<<8; + } + else if ((ABS(mb1->mv[1].hor - mb2->mv[11].hor) >= 4) || + (ABS(mb1->mv[1].ver - mb2->mv[11].ver) >= 4) || + (mb1->refAddr[0] != mb2->refAddr[11 >> 2])) + { + topBs += 1<<8; + } + tmp3 = mb1->totalCoeff[5]; + tmp4 = mb2->totalCoeff[15]; + if (tmp1 || tmp2) + { + topBs += 2<<16; + } + else if ((ABS(mb1->mv[4].hor - mb2->mv[14].hor) >= 4) || + (ABS(mb1->mv[4].ver - mb2->mv[14].ver) >= 4) || + (mb1->refAddr[4 >> 2] != mb2->refAddr[14 >> 2])) + { + topBs += 1<<16; + } + if (tmp3 || tmp4) + { + topBs += 2<<24; + } + else if ((ABS(mb1->mv[5].hor - mb2->mv[15].hor) >= 4) || + (ABS(mb1->mv[5].ver - mb2->mv[15].ver) >= 4) || + (mb1->refAddr[5 >> 2] != mb2->refAddr[15 >> 2])) + { + topBs += 1<<24; + } + + return topBs; +} + +/*------------------------------------------------------------------------------ + + Function: EdgeBoundaryStrengthLeft + + Functional description: + Function to calculate boundary strength value bs for left- + edge of a macroblock. Macroblock types are checked + before this is called -> no intra mb conditions here. + +------------------------------------------------------------------------------*/ +u32 EdgeBoundaryStrengthLeft(mbStorage_t *mb1, mbStorage_t *mb2) +{ + u32 leftBs = 0; + u32 tmp1, tmp2, tmp3, tmp4; + + tmp1 = mb1->totalCoeff[0]; + tmp2 = mb2->totalCoeff[5]; + tmp3 = mb1->totalCoeff[2]; + tmp4 = mb2->totalCoeff[7]; + + if (tmp1 || tmp2) + { + leftBs = 2<<0; + } + else if ((ABS(mb1->mv[0].hor - mb2->mv[5].hor) >= 4) || + (ABS(mb1->mv[0].ver - mb2->mv[5].ver) >= 4) || + (mb1->refAddr[0] != mb2->refAddr[5 >> 2])) + { + leftBs = 1<<0; + } + tmp1 = mb1->totalCoeff[8]; + tmp2 = mb2->totalCoeff[13]; + if (tmp3 || tmp4) + { + leftBs += 2<<8; + } + else if ((ABS(mb1->mv[2].hor - mb2->mv[7].hor) >= 4) || + (ABS(mb1->mv[2].ver - mb2->mv[7].ver) >= 4) || + (mb1->refAddr[0] != mb2->refAddr[7 >> 2])) + { + leftBs += 1<<8; + } + tmp3 = mb1->totalCoeff[10]; + tmp4 = mb2->totalCoeff[15]; + if (tmp1 || tmp2) + { + leftBs += 2<<16; + } + else if ((ABS(mb1->mv[8].hor - mb2->mv[13].hor) >= 4) || + (ABS(mb1->mv[8].ver - mb2->mv[13].ver) >= 4) || + (mb1->refAddr[8 >> 2] != mb2->refAddr[13 >> 2])) + { + leftBs += 1<<16; + } + if (tmp3 || tmp4) + { + leftBs += 2<<24; + } + else if ((ABS(mb1->mv[10].hor - mb2->mv[15].hor) >= 4) || + (ABS(mb1->mv[10].ver - mb2->mv[15].ver) >= 4) || + (mb1->refAddr[10 >> 2] != mb2->refAddr[15 >> 2])) + { + leftBs += 1<<24; + } + + return leftBs; +} +#endif /* H264DEC_OMXDL */ +/*------------------------------------------------------------------------------ + + Function: h264bsdFilterPicture + + Functional description: + Perform deblocking filtering for a picture. Filter does not copy + the original picture anywhere but filtering is performed directly + on the original image. Parameters controlling the filtering process + are computed based on information in macroblock structures of the + filtered macroblock, macroblock above and macroblock on the left of + the filtered one. + + Inputs: + image pointer to image to be filtered + mb pointer to macroblock data structure of the top-left + macroblock of the picture + + Outputs: + image filtered image stored here + + Returns: + none + +------------------------------------------------------------------------------*/ +#ifndef H264DEC_OMXDL +void h264bsdFilterPicture( + image_t *image, + mbStorage_t *mb) +{ + +/* Variables */ + + u32 flags; + u32 picSizeInMbs, mbRow, mbCol; + u32 picWidthInMbs; + u8 *data; + mbStorage_t *pMb; + bS_t bS[16]; + edgeThreshold_t thresholds[3]; + +/* Code */ + + ASSERT(image); + ASSERT(mb); + ASSERT(image->data); + ASSERT(image->width); + ASSERT(image->height); + + picWidthInMbs = image->width; + data = image->data; + picSizeInMbs = picWidthInMbs * image->height; + + pMb = mb; + + for (mbRow = 0, mbCol = 0; mbRow < image->height; pMb++) + { + flags = GetMbFilteringFlags(pMb); + + if (flags) + { + /* GetBoundaryStrengths function returns non-zero value if any of + * the bS values for the macroblock being processed was non-zero */ + if (GetBoundaryStrengths(pMb, bS, flags)) + { + /* luma */ + GetLumaEdgeThresholds(thresholds, pMb, flags); + data = image->data + mbRow * picWidthInMbs * 256 + mbCol * 16; + + FilterLuma((u8*)data, bS, thresholds, picWidthInMbs*16); + + /* chroma */ + GetChromaEdgeThresholds(thresholds, pMb, flags, + pMb->chromaQpIndexOffset); + data = image->data + picSizeInMbs * 256 + + mbRow * picWidthInMbs * 64 + mbCol * 8; + + FilterChroma((u8*)data, data + 64*picSizeInMbs, bS, + thresholds, picWidthInMbs*8); + + } + } + + mbCol++; + if (mbCol == picWidthInMbs) + { + mbCol = 0; + mbRow++; + } + } + +} + +/*------------------------------------------------------------------------------ + + Function: FilterVerLumaEdge + + Functional description: + Filter one vertical 4-pixel luma edge. + +------------------------------------------------------------------------------*/ +void FilterVerLumaEdge( + u8 *data, + u32 bS, + edgeThreshold_t *thresholds, + u32 imageWidth) +{ + +/* Variables */ + + i32 delta, tc, tmp; + u32 i; + u8 p0, q0, p1, q1, p2, q2; + u32 tmpFlag; + const u8 *clp = h264bsdClip + 512; + +/* Code */ + + ASSERT(data); + ASSERT(bS && bS <= 4); + ASSERT(thresholds); + + if (bS < 4) + { + tc = thresholds->tc0[bS-1]; + tmp = tc; + for (i = 4; i; i--, data += imageWidth) + { + p1 = data[-2]; p0 = data[-1]; + q0 = data[0]; q1 = data[1]; + if ( ((unsigned)ABS(p0-q0) < thresholds->alpha) && + ((unsigned)ABS(p1-p0) < thresholds->beta) && + ((unsigned)ABS(q1-q0) < thresholds->beta) ) + { + p2 = data[-3]; + q2 = data[2]; + + if ((unsigned)ABS(p2-p0) < thresholds->beta) + { + data[-2] = (u8)(p1 + CLIP3(-tc,tc, + (p2 + ((p0 + q0 + 1) >> 1) - (p1 << 1)) >> 1)); + tmp++; + } + + if ((unsigned)ABS(q2-q0) < thresholds->beta) + { + data[1] = (u8)(q1 + CLIP3(-tc,tc, + (q2 + ((p0 + q0 + 1) >> 1) - (q1 << 1)) >> 1)); + tmp++; + } + + delta = CLIP3(-tmp, tmp, ((((q0 - p0) << 2) + + (p1 - q1) + 4) >> 3)); + + p0 = clp[p0 + delta]; + q0 = clp[q0 - delta]; + tmp = tc; + data[-1] = p0; + data[ 0] = q0; + } + } + } + else + { + for (i = 4; i; i--, data += imageWidth) + { + p1 = data[-2]; p0 = data[-1]; + q0 = data[0]; q1 = data[1]; + if ( ((unsigned)ABS(p0-q0) < thresholds->alpha) && + ((unsigned)ABS(p1-p0) < thresholds->beta) && + ((unsigned)ABS(q1-q0) < thresholds->beta) ) + { + tmpFlag = + ((unsigned)ABS(p0-q0) < ((thresholds->alpha >> 2) +2)) ? + HANTRO_TRUE : HANTRO_FALSE; + + p2 = data[-3]; + q2 = data[2]; + + if (tmpFlag && (unsigned)ABS(p2-p0) < thresholds->beta) + { + tmp = p1 + p0 + q0; + data[-1] = (u8)((p2 + 2 * tmp + q1 + 4) >> 3); + data[-2] = (u8)((p2 + tmp + 2) >> 2); + data[-3] = (u8)((2 * data[-4] + 3 * p2 + tmp + 4) >> 3); + } + else + data[-1] = (2 * p1 + p0 + q1 + 2) >> 2; + + if (tmpFlag && (unsigned)ABS(q2-q0) < thresholds->beta) + { + tmp = p0 + q0 + q1; + data[0] = (u8)((p1 + 2 * tmp + q2 + 4) >> 3); + data[1] = (u8)((tmp + q2 + 2) >> 2); + data[2] = (u8)((2 * data[3] + 3 * q2 + tmp + 4) >> 3); + } + else + data[0] = (u8)((2 * q1 + q0 + p1 + 2) >> 2); + } + } + } + +} + +/*------------------------------------------------------------------------------ + + Function: FilterHorLumaEdge + + Functional description: + Filter one horizontal 4-pixel luma edge + +------------------------------------------------------------------------------*/ +void FilterHorLumaEdge( + u8 *data, + u32 bS, + edgeThreshold_t *thresholds, + i32 imageWidth) +{ + +/* Variables */ + + i32 delta, tc, tmp; + u32 i; + u8 p0, q0, p1, q1, p2, q2; + const u8 *clp = h264bsdClip + 512; + +/* Code */ + + ASSERT(data); + ASSERT(bS < 4); + ASSERT(thresholds); + + tc = thresholds->tc0[bS-1]; + tmp = tc; + for (i = 4; i; i--, data++) + { + p1 = data[-imageWidth*2]; p0 = data[-imageWidth]; + q0 = data[0]; q1 = data[imageWidth]; + if ( ((unsigned)ABS(p0-q0) < thresholds->alpha) && + ((unsigned)ABS(p1-p0) < thresholds->beta) && + ((unsigned)ABS(q1-q0) < thresholds->beta) ) + { + p2 = data[-imageWidth*3]; + + if ((unsigned)ABS(p2-p0) < thresholds->beta) + { + data[-imageWidth*2] = (u8)(p1 + CLIP3(-tc,tc, + (p2 + ((p0 + q0 + 1) >> 1) - (p1 << 1)) >> 1)); + tmp++; + } + + q2 = data[imageWidth*2]; + + if ((unsigned)ABS(q2-q0) < thresholds->beta) + { + data[imageWidth] = (u8)(q1 + CLIP3(-tc,tc, + (q2 + ((p0 + q0 + 1) >> 1) - (q1 << 1)) >> 1)); + tmp++; + } + + delta = CLIP3(-tmp, tmp, ((((q0 - p0) << 2) + + (p1 - q1) + 4) >> 3)); + + p0 = clp[p0 + delta]; + q0 = clp[q0 - delta]; + tmp = tc; + data[-imageWidth] = p0; + data[ 0] = q0; + } + } +} + +/*------------------------------------------------------------------------------ + + Function: FilterHorLuma + + Functional description: + Filter all four successive horizontal 4-pixel luma edges. This can + be done when bS is equal to all four edges. + +------------------------------------------------------------------------------*/ +void FilterHorLuma( + u8 *data, + u32 bS, + edgeThreshold_t *thresholds, + i32 imageWidth) +{ + +/* Variables */ + + i32 delta, tc, tmp; + u32 i; + u8 p0, q0, p1, q1, p2, q2; + u32 tmpFlag; + const u8 *clp = h264bsdClip + 512; + +/* Code */ + + ASSERT(data); + ASSERT(bS <= 4); + ASSERT(thresholds); + + if (bS < 4) + { + tc = thresholds->tc0[bS-1]; + tmp = tc; + for (i = 16; i; i--, data++) + { + p1 = data[-imageWidth*2]; p0 = data[-imageWidth]; + q0 = data[0]; q1 = data[imageWidth]; + if ( ((unsigned)ABS(p0-q0) < thresholds->alpha) && + ((unsigned)ABS(p1-p0) < thresholds->beta) && + ((unsigned)ABS(q1-q0) < thresholds->beta) ) + { + p2 = data[-imageWidth*3]; + + if ((unsigned)ABS(p2-p0) < thresholds->beta) + { + data[-imageWidth*2] = (u8)(p1 + CLIP3(-tc,tc, + (p2 + ((p0 + q0 + 1) >> 1) - (p1 << 1)) >> 1)); + tmp++; + } + + q2 = data[imageWidth*2]; + + if ((unsigned)ABS(q2-q0) < thresholds->beta) + { + data[imageWidth] = (u8)(q1 + CLIP3(-tc,tc, + (q2 + ((p0 + q0 + 1) >> 1) - (q1 << 1)) >> 1)); + tmp++; + } + + delta = CLIP3(-tmp, tmp, ((((q0 - p0) << 2) + + (p1 - q1) + 4) >> 3)); + + p0 = clp[p0 + delta]; + q0 = clp[q0 - delta]; + tmp = tc; + data[-imageWidth] = p0; + data[ 0] = q0; + } + } + } + else + { + for (i = 16; i; i--, data++) + { + p1 = data[-imageWidth*2]; p0 = data[-imageWidth]; + q0 = data[0]; q1 = data[imageWidth]; + if ( ((unsigned)ABS(p0-q0) < thresholds->alpha) && + ((unsigned)ABS(p1-p0) < thresholds->beta) && + ((unsigned)ABS(q1-q0) < thresholds->beta) ) + { + tmpFlag = ((unsigned)ABS(p0-q0) < ((thresholds->alpha >> 2) +2)) + ? HANTRO_TRUE : HANTRO_FALSE; + + p2 = data[-imageWidth*3]; + q2 = data[imageWidth*2]; + + if (tmpFlag && (unsigned)ABS(p2-p0) < thresholds->beta) + { + tmp = p1 + p0 + q0; + data[-imageWidth] = (u8)((p2 + 2 * tmp + q1 + 4) >> 3); + data[-imageWidth*2] = (u8)((p2 + tmp + 2) >> 2); + data[-imageWidth*3] = (u8)((2 * data[-imageWidth*4] + + 3 * p2 + tmp + 4) >> 3); + } + else + data[-imageWidth] = (u8)((2 * p1 + p0 + q1 + 2) >> 2); + + if (tmpFlag && (unsigned)ABS(q2-q0) < thresholds->beta) + { + tmp = p0 + q0 + q1; + data[ 0] = (u8)((p1 + 2 * tmp + q2 + 4) >> 3); + data[imageWidth] = (u8)((tmp + q2 + 2) >> 2); + data[imageWidth*2] = (u8)((2 * data[imageWidth*3] + + 3 * q2 + tmp + 4) >> 3); + } + else + data[0] = (2 * q1 + q0 + p1 + 2) >> 2; + } + } + } + +} + +/*------------------------------------------------------------------------------ + + Function: FilterVerChromaEdge + + Functional description: + Filter one vertical 2-pixel chroma edge + +------------------------------------------------------------------------------*/ +void FilterVerChromaEdge( + u8 *data, + u32 bS, + edgeThreshold_t *thresholds, + u32 width) +{ + +/* Variables */ + + i32 delta, tc; + u8 p0, q0, p1, q1; + const u8 *clp = h264bsdClip + 512; + +/* Code */ + + ASSERT(data); + ASSERT(bS <= 4); + ASSERT(thresholds); + + p1 = data[-2]; p0 = data[-1]; + q0 = data[0]; q1 = data[1]; + if ( ((unsigned)ABS(p0-q0) < thresholds->alpha) && + ((unsigned)ABS(p1-p0) < thresholds->beta) && + ((unsigned)ABS(q1-q0) < thresholds->beta) ) + { + if (bS < 4) + { + tc = thresholds->tc0[bS-1] + 1; + delta = CLIP3(-tc, tc, ((((q0 - p0) << 2) + + (p1 - q1) + 4) >> 3)); + p0 = clp[p0 + delta]; + q0 = clp[q0 - delta]; + data[-1] = p0; + data[ 0] = q0; + } + else + { + data[-1] = (2 * p1 + p0 + q1 + 2) >> 2; + data[ 0] = (2 * q1 + q0 + p1 + 2) >> 2; + } + } + data += width; + p1 = data[-2]; p0 = data[-1]; + q0 = data[0]; q1 = data[1]; + if ( ((unsigned)ABS(p0-q0) < thresholds->alpha) && + ((unsigned)ABS(p1-p0) < thresholds->beta) && + ((unsigned)ABS(q1-q0) < thresholds->beta) ) + { + if (bS < 4) + { + tc = thresholds->tc0[bS-1] + 1; + delta = CLIP3(-tc, tc, ((((q0 - p0) << 2) + + (p1 - q1) + 4) >> 3)); + p0 = clp[p0 + delta]; + q0 = clp[q0 - delta]; + data[-1] = p0; + data[ 0] = q0; + } + else + { + data[-1] = (2 * p1 + p0 + q1 + 2) >> 2; + data[ 0] = (2 * q1 + q0 + p1 + 2) >> 2; + } + } + +} + +/*------------------------------------------------------------------------------ + + Function: FilterHorChromaEdge + + Functional description: + Filter one horizontal 2-pixel chroma edge + +------------------------------------------------------------------------------*/ +void FilterHorChromaEdge( + u8 *data, + u32 bS, + edgeThreshold_t *thresholds, + i32 width) +{ + +/* Variables */ + + i32 delta, tc; + u32 i; + u8 p0, q0, p1, q1; + const u8 *clp = h264bsdClip + 512; + +/* Code */ + + ASSERT(data); + ASSERT(bS < 4); + ASSERT(thresholds); + + tc = thresholds->tc0[bS-1] + 1; + for (i = 2; i; i--, data++) + { + p1 = data[-width*2]; p0 = data[-width]; + q0 = data[0]; q1 = data[width]; + if ( ((unsigned)ABS(p0-q0) < thresholds->alpha) && + ((unsigned)ABS(p1-p0) < thresholds->beta) && + ((unsigned)ABS(q1-q0) < thresholds->beta) ) + { + delta = CLIP3(-tc, tc, ((((q0 - p0) << 2) + + (p1 - q1) + 4) >> 3)); + p0 = clp[p0 + delta]; + q0 = clp[q0 - delta]; + data[-width] = p0; + data[ 0] = q0; + } + } +} + +/*------------------------------------------------------------------------------ + + Function: FilterHorChroma + + Functional description: + Filter all four successive horizontal 2-pixel chroma edges. This + can be done if bS is equal for all four edges. + +------------------------------------------------------------------------------*/ +void FilterHorChroma( + u8 *data, + u32 bS, + edgeThreshold_t *thresholds, + i32 width) +{ + +/* Variables */ + + i32 delta, tc; + u32 i; + u8 p0, q0, p1, q1; + const u8 *clp = h264bsdClip + 512; + +/* Code */ + + ASSERT(data); + ASSERT(bS <= 4); + ASSERT(thresholds); + + if (bS < 4) + { + tc = thresholds->tc0[bS-1] + 1; + for (i = 8; i; i--, data++) + { + p1 = data[-width*2]; p0 = data[-width]; + q0 = data[0]; q1 = data[width]; + if ( ((unsigned)ABS(p0-q0) < thresholds->alpha) && + ((unsigned)ABS(p1-p0) < thresholds->beta) && + ((unsigned)ABS(q1-q0) < thresholds->beta) ) + { + delta = CLIP3(-tc, tc, ((((q0 - p0) << 2) + + (p1 - q1) + 4) >> 3)); + p0 = clp[p0 + delta]; + q0 = clp[q0 - delta]; + data[-width] = p0; + data[ 0] = q0; + } + } + } + else + { + for (i = 8; i; i--, data++) + { + p1 = data[-width*2]; p0 = data[-width]; + q0 = data[0]; q1 = data[width]; + if ( ((unsigned)ABS(p0-q0) < thresholds->alpha) && + ((unsigned)ABS(p1-p0) < thresholds->beta) && + ((unsigned)ABS(q1-q0) < thresholds->beta) ) + { + data[-width] = (2 * p1 + p0 + q1 + 2) >> 2; + data[ 0] = (2 * q1 + q0 + p1 + 2) >> 2; + } + } + } + +} + + +/*------------------------------------------------------------------------------ + + Function: GetBoundaryStrengths + + Functional description: + Function to calculate boundary strengths for all edges of a + macroblock. Function returns HANTRO_TRUE if any of the bS values for + the macroblock had non-zero value, HANTRO_FALSE otherwise. + +------------------------------------------------------------------------------*/ +u32 GetBoundaryStrengths(mbStorage_t *mb, bS_t *bS, u32 flags) +{ + +/* Variables */ + + /* this flag is set HANTRO_TRUE as soon as any boundary strength value is + * non-zero */ + u32 nonZeroBs = HANTRO_FALSE; + +/* Code */ + + ASSERT(mb); + ASSERT(bS); + ASSERT(flags); + + /* top edges */ + if (flags & FILTER_TOP_EDGE) + { + if (IS_INTRA_MB(*mb) || IS_INTRA_MB(*mb->mbB)) + { + bS[0].top = bS[1].top = bS[2].top = bS[3].top = 4; + nonZeroBs = HANTRO_TRUE; + } + else + { + bS[0].top = EdgeBoundaryStrength(mb, mb->mbB, 0, 10); + bS[1].top = EdgeBoundaryStrength(mb, mb->mbB, 1, 11); + bS[2].top = EdgeBoundaryStrength(mb, mb->mbB, 4, 14); + bS[3].top = EdgeBoundaryStrength(mb, mb->mbB, 5, 15); + if (bS[0].top || bS[1].top || bS[2].top || bS[3].top) + nonZeroBs = HANTRO_TRUE; + } + } + else + { + bS[0].top = bS[1].top = bS[2].top = bS[3].top = 0; + } + + /* left edges */ + if (flags & FILTER_LEFT_EDGE) + { + if (IS_INTRA_MB(*mb) || IS_INTRA_MB(*mb->mbA)) + { + bS[0].left = bS[4].left = bS[8].left = bS[12].left = 4; + nonZeroBs = HANTRO_TRUE; + } + else + { + bS[0].left = EdgeBoundaryStrength(mb, mb->mbA, 0, 5); + bS[4].left = EdgeBoundaryStrength(mb, mb->mbA, 2, 7); + bS[8].left = EdgeBoundaryStrength(mb, mb->mbA, 8, 13); + bS[12].left = EdgeBoundaryStrength(mb, mb->mbA, 10, 15); + if (!nonZeroBs && + (bS[0].left || bS[4].left || bS[8].left || bS[12].left)) + nonZeroBs = HANTRO_TRUE; + } + } + else + { + bS[0].left = bS[4].left = bS[8].left = bS[12].left = 0; + } + + /* inner edges */ + if (IS_INTRA_MB(*mb)) + { + bS[4].top = bS[5].top = bS[6].top = bS[7].top = + bS[8].top = bS[9].top = bS[10].top = bS[11].top = + bS[12].top = bS[13].top = bS[14].top = bS[15].top = 3; + + bS[1].left = bS[2].left = bS[3].left = + bS[5].left = bS[6].left = bS[7].left = + bS[9].left = bS[10].left = bS[11].left = + bS[13].left = bS[14].left = bS[15].left = 3; + nonZeroBs = HANTRO_TRUE; + } + else + { + /* 16x16 inter mb -> ref addresses or motion vectors cannot differ, + * only check if either of the blocks contain coefficients */ + if (h264bsdNumMbPart(mb->mbType) == 1) + { + bS[4].top = mb->totalCoeff[2] || mb->totalCoeff[0] ? 2 : 0; + bS[5].top = mb->totalCoeff[3] || mb->totalCoeff[1] ? 2 : 0; + bS[6].top = mb->totalCoeff[6] || mb->totalCoeff[4] ? 2 : 0; + bS[7].top = mb->totalCoeff[7] || mb->totalCoeff[5] ? 2 : 0; + bS[8].top = mb->totalCoeff[8] || mb->totalCoeff[2] ? 2 : 0; + bS[9].top = mb->totalCoeff[9] || mb->totalCoeff[3] ? 2 : 0; + bS[10].top = mb->totalCoeff[12] || mb->totalCoeff[6] ? 2 : 0; + bS[11].top = mb->totalCoeff[13] || mb->totalCoeff[7] ? 2 : 0; + bS[12].top = mb->totalCoeff[10] || mb->totalCoeff[8] ? 2 : 0; + bS[13].top = mb->totalCoeff[11] || mb->totalCoeff[9] ? 2 : 0; + bS[14].top = mb->totalCoeff[14] || mb->totalCoeff[12] ? 2 : 0; + bS[15].top = mb->totalCoeff[15] || mb->totalCoeff[13] ? 2 : 0; + + bS[1].left = mb->totalCoeff[1] || mb->totalCoeff[0] ? 2 : 0; + bS[2].left = mb->totalCoeff[4] || mb->totalCoeff[1] ? 2 : 0; + bS[3].left = mb->totalCoeff[5] || mb->totalCoeff[4] ? 2 : 0; + bS[5].left = mb->totalCoeff[3] || mb->totalCoeff[2] ? 2 : 0; + bS[6].left = mb->totalCoeff[6] || mb->totalCoeff[3] ? 2 : 0; + bS[7].left = mb->totalCoeff[7] || mb->totalCoeff[6] ? 2 : 0; + bS[9].left = mb->totalCoeff[9] || mb->totalCoeff[8] ? 2 : 0; + bS[10].left = mb->totalCoeff[12] || mb->totalCoeff[9] ? 2 : 0; + bS[11].left = mb->totalCoeff[13] || mb->totalCoeff[12] ? 2 : 0; + bS[13].left = mb->totalCoeff[11] || mb->totalCoeff[10] ? 2 : 0; + bS[14].left = mb->totalCoeff[14] || mb->totalCoeff[11] ? 2 : 0; + bS[15].left = mb->totalCoeff[15] || mb->totalCoeff[14] ? 2 : 0; + } + /* 16x8 inter mb -> ref addresses and motion vectors can be different + * only for the middle horizontal edge, for the other top edges it is + * enough to check whether the blocks contain coefficients or not. The + * same applies to all internal left edges. */ + else if (mb->mbType == P_L0_L0_16x8) + { + bS[4].top = mb->totalCoeff[2] || mb->totalCoeff[0] ? 2 : 0; + bS[5].top = mb->totalCoeff[3] || mb->totalCoeff[1] ? 2 : 0; + bS[6].top = mb->totalCoeff[6] || mb->totalCoeff[4] ? 2 : 0; + bS[7].top = mb->totalCoeff[7] || mb->totalCoeff[5] ? 2 : 0; + bS[12].top = mb->totalCoeff[10] || mb->totalCoeff[8] ? 2 : 0; + bS[13].top = mb->totalCoeff[11] || mb->totalCoeff[9] ? 2 : 0; + bS[14].top = mb->totalCoeff[14] || mb->totalCoeff[12] ? 2 : 0; + bS[15].top = mb->totalCoeff[15] || mb->totalCoeff[13] ? 2 : 0; + bS[8].top = InnerBoundaryStrength(mb, 8, 2); + bS[9].top = InnerBoundaryStrength(mb, 9, 3); + bS[10].top = InnerBoundaryStrength(mb, 12, 6); + bS[11].top = InnerBoundaryStrength(mb, 13, 7); + + bS[1].left = mb->totalCoeff[1] || mb->totalCoeff[0] ? 2 : 0; + bS[2].left = mb->totalCoeff[4] || mb->totalCoeff[1] ? 2 : 0; + bS[3].left = mb->totalCoeff[5] || mb->totalCoeff[4] ? 2 : 0; + bS[5].left = mb->totalCoeff[3] || mb->totalCoeff[2] ? 2 : 0; + bS[6].left = mb->totalCoeff[6] || mb->totalCoeff[3] ? 2 : 0; + bS[7].left = mb->totalCoeff[7] || mb->totalCoeff[6] ? 2 : 0; + bS[9].left = mb->totalCoeff[9] || mb->totalCoeff[8] ? 2 : 0; + bS[10].left = mb->totalCoeff[12] || mb->totalCoeff[9] ? 2 : 0; + bS[11].left = mb->totalCoeff[13] || mb->totalCoeff[12] ? 2 : 0; + bS[13].left = mb->totalCoeff[11] || mb->totalCoeff[10] ? 2 : 0; + bS[14].left = mb->totalCoeff[14] || mb->totalCoeff[11] ? 2 : 0; + bS[15].left = mb->totalCoeff[15] || mb->totalCoeff[14] ? 2 : 0; + } + /* 8x16 inter mb -> ref addresses and motion vectors can be different + * only for the middle vertical edge, for the other left edges it is + * enough to check whether the blocks contain coefficients or not. The + * same applies to all internal top edges. */ + else if (mb->mbType == P_L0_L0_8x16) + { + bS[4].top = mb->totalCoeff[2] || mb->totalCoeff[0] ? 2 : 0; + bS[5].top = mb->totalCoeff[3] || mb->totalCoeff[1] ? 2 : 0; + bS[6].top = mb->totalCoeff[6] || mb->totalCoeff[4] ? 2 : 0; + bS[7].top = mb->totalCoeff[7] || mb->totalCoeff[5] ? 2 : 0; + bS[8].top = mb->totalCoeff[8] || mb->totalCoeff[2] ? 2 : 0; + bS[9].top = mb->totalCoeff[9] || mb->totalCoeff[3] ? 2 : 0; + bS[10].top = mb->totalCoeff[12] || mb->totalCoeff[6] ? 2 : 0; + bS[11].top = mb->totalCoeff[13] || mb->totalCoeff[7] ? 2 : 0; + bS[12].top = mb->totalCoeff[10] || mb->totalCoeff[8] ? 2 : 0; + bS[13].top = mb->totalCoeff[11] || mb->totalCoeff[9] ? 2 : 0; + bS[14].top = mb->totalCoeff[14] || mb->totalCoeff[12] ? 2 : 0; + bS[15].top = mb->totalCoeff[15] || mb->totalCoeff[13] ? 2 : 0; + + bS[1].left = mb->totalCoeff[1] || mb->totalCoeff[0] ? 2 : 0; + bS[3].left = mb->totalCoeff[5] || mb->totalCoeff[4] ? 2 : 0; + bS[5].left = mb->totalCoeff[3] || mb->totalCoeff[2] ? 2 : 0; + bS[7].left = mb->totalCoeff[7] || mb->totalCoeff[6] ? 2 : 0; + bS[9].left = mb->totalCoeff[9] || mb->totalCoeff[8] ? 2 : 0; + bS[11].left = mb->totalCoeff[13] || mb->totalCoeff[12] ? 2 : 0; + bS[13].left = mb->totalCoeff[11] || mb->totalCoeff[10] ? 2 : 0; + bS[15].left = mb->totalCoeff[15] || mb->totalCoeff[14] ? 2 : 0; + bS[2].left = InnerBoundaryStrength(mb, 4, 1); + bS[6].left = InnerBoundaryStrength(mb, 6, 3); + bS[10].left = InnerBoundaryStrength(mb, 12, 9); + bS[14].left = InnerBoundaryStrength(mb, 14, 11); + } + else + { + bS[4].top = + InnerBoundaryStrength(mb, mb4x4Index[4], mb4x4Index[0]); + bS[5].top = + InnerBoundaryStrength(mb, mb4x4Index[5], mb4x4Index[1]); + bS[6].top = + InnerBoundaryStrength(mb, mb4x4Index[6], mb4x4Index[2]); + bS[7].top = + InnerBoundaryStrength(mb, mb4x4Index[7], mb4x4Index[3]); + bS[8].top = + InnerBoundaryStrength(mb, mb4x4Index[8], mb4x4Index[4]); + bS[9].top = + InnerBoundaryStrength(mb, mb4x4Index[9], mb4x4Index[5]); + bS[10].top = + InnerBoundaryStrength(mb, mb4x4Index[10], mb4x4Index[6]); + bS[11].top = + InnerBoundaryStrength(mb, mb4x4Index[11], mb4x4Index[7]); + bS[12].top = + InnerBoundaryStrength(mb, mb4x4Index[12], mb4x4Index[8]); + bS[13].top = + InnerBoundaryStrength(mb, mb4x4Index[13], mb4x4Index[9]); + bS[14].top = + InnerBoundaryStrength(mb, mb4x4Index[14], mb4x4Index[10]); + bS[15].top = + InnerBoundaryStrength(mb, mb4x4Index[15], mb4x4Index[11]); + + bS[1].left = + InnerBoundaryStrength(mb, mb4x4Index[1], mb4x4Index[0]); + bS[2].left = + InnerBoundaryStrength(mb, mb4x4Index[2], mb4x4Index[1]); + bS[3].left = + InnerBoundaryStrength(mb, mb4x4Index[3], mb4x4Index[2]); + bS[5].left = + InnerBoundaryStrength(mb, mb4x4Index[5], mb4x4Index[4]); + bS[6].left = + InnerBoundaryStrength(mb, mb4x4Index[6], mb4x4Index[5]); + bS[7].left = + InnerBoundaryStrength(mb, mb4x4Index[7], mb4x4Index[6]); + bS[9].left = + InnerBoundaryStrength(mb, mb4x4Index[9], mb4x4Index[8]); + bS[10].left = + InnerBoundaryStrength(mb, mb4x4Index[10], mb4x4Index[9]); + bS[11].left = + InnerBoundaryStrength(mb, mb4x4Index[11], mb4x4Index[10]); + bS[13].left = + InnerBoundaryStrength(mb, mb4x4Index[13], mb4x4Index[12]); + bS[14].left = + InnerBoundaryStrength(mb, mb4x4Index[14], mb4x4Index[13]); + bS[15].left = + InnerBoundaryStrength(mb, mb4x4Index[15], mb4x4Index[14]); + } + if (!nonZeroBs && + (bS[4].top || bS[5].top || bS[6].top || bS[7].top || + bS[8].top || bS[9].top || bS[10].top || bS[11].top || + bS[12].top || bS[13].top || bS[14].top || bS[15].top || + bS[1].left || bS[2].left || bS[3].left || + bS[5].left || bS[6].left || bS[7].left || + bS[9].left || bS[10].left || bS[11].left || + bS[13].left || bS[14].left || bS[15].left)) + nonZeroBs = HANTRO_TRUE; + } + + return(nonZeroBs); + +} + +/*------------------------------------------------------------------------------ + + Function: GetLumaEdgeThresholds + + Functional description: + Compute alpha, beta and tc0 thresholds for inner, left and top + luma edges of a macroblock. + +------------------------------------------------------------------------------*/ +void GetLumaEdgeThresholds( + edgeThreshold_t *thresholds, + mbStorage_t *mb, + u32 filteringFlags) +{ + +/* Variables */ + + u32 indexA, indexB; + u32 qpAv, qp, qpTmp; + +/* Code */ + + ASSERT(thresholds); + ASSERT(mb); + + qp = mb->qpY; + + indexA = (u32)CLIP3(0, 51, (i32)qp + mb->filterOffsetA); + indexB = (u32)CLIP3(0, 51, (i32)qp + mb->filterOffsetB); + + thresholds[INNER].alpha = alphas[indexA]; + thresholds[INNER].beta = betas[indexB]; + thresholds[INNER].tc0 = tc0[indexA]; + + if (filteringFlags & FILTER_TOP_EDGE) + { + qpTmp = mb->mbB->qpY; + if (qpTmp != qp) + { + qpAv = (qp + qpTmp + 1) >> 1; + + indexA = (u32)CLIP3(0, 51, (i32)qpAv + mb->filterOffsetA); + indexB = (u32)CLIP3(0, 51, (i32)qpAv + mb->filterOffsetB); + + thresholds[TOP].alpha = alphas[indexA]; + thresholds[TOP].beta = betas[indexB]; + thresholds[TOP].tc0 = tc0[indexA]; + } + else + { + thresholds[TOP].alpha = thresholds[INNER].alpha; + thresholds[TOP].beta = thresholds[INNER].beta; + thresholds[TOP].tc0 = thresholds[INNER].tc0; + } + } + if (filteringFlags & FILTER_LEFT_EDGE) + { + qpTmp = mb->mbA->qpY; + if (qpTmp != qp) + { + qpAv = (qp + qpTmp + 1) >> 1; + + indexA = (u32)CLIP3(0, 51, (i32)qpAv + mb->filterOffsetA); + indexB = (u32)CLIP3(0, 51, (i32)qpAv + mb->filterOffsetB); + + thresholds[LEFT].alpha = alphas[indexA]; + thresholds[LEFT].beta = betas[indexB]; + thresholds[LEFT].tc0 = tc0[indexA]; + } + else + { + thresholds[LEFT].alpha = thresholds[INNER].alpha; + thresholds[LEFT].beta = thresholds[INNER].beta; + thresholds[LEFT].tc0 = thresholds[INNER].tc0; + } + } + +} + +/*------------------------------------------------------------------------------ + + Function: GetChromaEdgeThresholds + + Functional description: + Compute alpha, beta and tc0 thresholds for inner, left and top + chroma edges of a macroblock. + +------------------------------------------------------------------------------*/ +void GetChromaEdgeThresholds( + edgeThreshold_t *thresholds, + mbStorage_t *mb, + u32 filteringFlags, + i32 chromaQpIndexOffset) +{ + +/* Variables */ + + u32 indexA, indexB; + u32 qpAv, qp, qpTmp; + +/* Code */ + + ASSERT(thresholds); + ASSERT(mb); + + qp = mb->qpY; + qp = h264bsdQpC[CLIP3(0, 51, (i32)qp + chromaQpIndexOffset)]; + + indexA = (u32)CLIP3(0, 51, (i32)qp + mb->filterOffsetA); + indexB = (u32)CLIP3(0, 51, (i32)qp + mb->filterOffsetB); + + thresholds[INNER].alpha = alphas[indexA]; + thresholds[INNER].beta = betas[indexB]; + thresholds[INNER].tc0 = tc0[indexA]; + + if (filteringFlags & FILTER_TOP_EDGE) + { + qpTmp = mb->mbB->qpY; + if (qpTmp != mb->qpY) + { + qpTmp = h264bsdQpC[CLIP3(0, 51, (i32)qpTmp + chromaQpIndexOffset)]; + qpAv = (qp + qpTmp + 1) >> 1; + + indexA = (u32)CLIP3(0, 51, (i32)qpAv + mb->filterOffsetA); + indexB = (u32)CLIP3(0, 51, (i32)qpAv + mb->filterOffsetB); + + thresholds[TOP].alpha = alphas[indexA]; + thresholds[TOP].beta = betas[indexB]; + thresholds[TOP].tc0 = tc0[indexA]; + } + else + { + thresholds[TOP].alpha = thresholds[INNER].alpha; + thresholds[TOP].beta = thresholds[INNER].beta; + thresholds[TOP].tc0 = thresholds[INNER].tc0; + } + } + if (filteringFlags & FILTER_LEFT_EDGE) + { + qpTmp = mb->mbA->qpY; + if (qpTmp != mb->qpY) + { + qpTmp = h264bsdQpC[CLIP3(0, 51, (i32)qpTmp + chromaQpIndexOffset)]; + qpAv = (qp + qpTmp + 1) >> 1; + + indexA = (u32)CLIP3(0, 51, (i32)qpAv + mb->filterOffsetA); + indexB = (u32)CLIP3(0, 51, (i32)qpAv + mb->filterOffsetB); + + thresholds[LEFT].alpha = alphas[indexA]; + thresholds[LEFT].beta = betas[indexB]; + thresholds[LEFT].tc0 = tc0[indexA]; + } + else + { + thresholds[LEFT].alpha = thresholds[INNER].alpha; + thresholds[LEFT].beta = thresholds[INNER].beta; + thresholds[LEFT].tc0 = thresholds[INNER].tc0; + } + } + +} + +/*------------------------------------------------------------------------------ + + Function: FilterLuma + + Functional description: + Function to filter all luma edges of a macroblock + +------------------------------------------------------------------------------*/ +void FilterLuma( + u8 *data, + bS_t *bS, + edgeThreshold_t *thresholds, + u32 width) +{ + +/* Variables */ + + u32 vblock; + bS_t *tmp; + u8 *ptr; + u32 offset; + +/* Code */ + + ASSERT(data); + ASSERT(bS); + ASSERT(thresholds); + + ptr = data; + tmp = bS; + + offset = TOP; + + /* loop block rows, perform filtering for all vertical edges of the block + * row first, then filter each horizontal edge of the row */ + for (vblock = 4; vblock--;) + { + /* only perform filtering if bS is non-zero, first of the four + * FilterVerLumaEdge handles the left edge of the macroblock, others + * filter inner edges */ + if (tmp[0].left) + FilterVerLumaEdge(ptr, tmp[0].left, thresholds + LEFT, width); + if (tmp[1].left) + FilterVerLumaEdge(ptr+4, tmp[1].left, thresholds + INNER, width); + if (tmp[2].left) + FilterVerLumaEdge(ptr+8, tmp[2].left, thresholds + INNER, width); + if (tmp[3].left) + FilterVerLumaEdge(ptr+12, tmp[3].left, thresholds + INNER, width); + + /* if bS is equal for all horizontal edges of the row -> perform + * filtering with FilterHorLuma, otherwise use FilterHorLumaEdge for + * each edge separately. offset variable indicates top macroblock edge + * on the first loop round, inner edge for the other rounds */ + if (tmp[0].top == tmp[1].top && tmp[1].top == tmp[2].top && + tmp[2].top == tmp[3].top) + { + if(tmp[0].top) + FilterHorLuma(ptr, tmp[0].top, thresholds + offset, (i32)width); + } + else + { + if(tmp[0].top) + FilterHorLumaEdge(ptr, tmp[0].top, thresholds+offset, + (i32)width); + if(tmp[1].top) + FilterHorLumaEdge(ptr+4, tmp[1].top, thresholds+offset, + (i32)width); + if(tmp[2].top) + FilterHorLumaEdge(ptr+8, tmp[2].top, thresholds+offset, + (i32)width); + if(tmp[3].top) + FilterHorLumaEdge(ptr+12, tmp[3].top, thresholds+offset, + (i32)width); + } + + /* four pixel rows ahead, i.e. next row of 4x4-blocks */ + ptr += width*4; + tmp += 4; + offset = INNER; + } +} + +/*------------------------------------------------------------------------------ + + Function: FilterChroma + + Functional description: + Function to filter all chroma edges of a macroblock + +------------------------------------------------------------------------------*/ +void FilterChroma( + u8 *dataCb, + u8 *dataCr, + bS_t *bS, + edgeThreshold_t *thresholds, + u32 width) +{ + +/* Variables */ + + u32 vblock; + bS_t *tmp; + u32 offset; + +/* Code */ + + ASSERT(dataCb); + ASSERT(dataCr); + ASSERT(bS); + ASSERT(thresholds); + + tmp = bS; + offset = TOP; + + /* loop block rows, perform filtering for all vertical edges of the block + * row first, then filter each horizontal edge of the row */ + for (vblock = 0; vblock < 2; vblock++) + { + /* only perform filtering if bS is non-zero, first two of the four + * FilterVerChromaEdge calls handle the left edge of the macroblock, + * others filter the inner edge. Note that as chroma uses bS values + * determined for luma edges, each bS is used only for 2 pixels of + * a 4-pixel edge */ + if (tmp[0].left) + { + FilterVerChromaEdge(dataCb, tmp[0].left, thresholds + LEFT, width); + FilterVerChromaEdge(dataCr, tmp[0].left, thresholds + LEFT, width); + } + if (tmp[4].left) + { + FilterVerChromaEdge(dataCb+2*width, tmp[4].left, thresholds + LEFT, + width); + FilterVerChromaEdge(dataCr+2*width, tmp[4].left, thresholds + LEFT, + width); + } + if (tmp[2].left) + { + FilterVerChromaEdge(dataCb+4, tmp[2].left, thresholds + INNER, + width); + FilterVerChromaEdge(dataCr+4, tmp[2].left, thresholds + INNER, + width); + } + if (tmp[6].left) + { + FilterVerChromaEdge(dataCb+2*width+4, tmp[6].left, + thresholds + INNER, width); + FilterVerChromaEdge(dataCr+2*width+4, tmp[6].left, + thresholds + INNER, width); + } + + /* if bS is equal for all horizontal edges of the row -> perform + * filtering with FilterHorChroma, otherwise use FilterHorChromaEdge + * for each edge separately. offset variable indicates top macroblock + * edge on the first loop round, inner edge for the second */ + if (tmp[0].top == tmp[1].top && tmp[1].top == tmp[2].top && + tmp[2].top == tmp[3].top) + { + if(tmp[0].top) + { + FilterHorChroma(dataCb, tmp[0].top, thresholds+offset, + (i32)width); + FilterHorChroma(dataCr, tmp[0].top, thresholds+offset, + (i32)width); + } + } + else + { + if (tmp[0].top) + { + FilterHorChromaEdge(dataCb, tmp[0].top, thresholds+offset, + (i32)width); + FilterHorChromaEdge(dataCr, tmp[0].top, thresholds+offset, + (i32)width); + } + if (tmp[1].top) + { + FilterHorChromaEdge(dataCb+2, tmp[1].top, thresholds+offset, + (i32)width); + FilterHorChromaEdge(dataCr+2, tmp[1].top, thresholds+offset, + (i32)width); + } + if (tmp[2].top) + { + FilterHorChromaEdge(dataCb+4, tmp[2].top, thresholds+offset, + (i32)width); + FilterHorChromaEdge(dataCr+4, tmp[2].top, thresholds+offset, + (i32)width); + } + if (tmp[3].top) + { + FilterHorChromaEdge(dataCb+6, tmp[3].top, thresholds+offset, + (i32)width); + FilterHorChromaEdge(dataCr+6, tmp[3].top, thresholds+offset, + (i32)width); + } + } + + tmp += 8; + dataCb += width*4; + dataCr += width*4; + offset = INNER; + } +} + +#else /* H264DEC_OMXDL */ + +/*------------------------------------------------------------------------------ + + Function: h264bsdFilterPicture + + Functional description: + Perform deblocking filtering for a picture. Filter does not copy + the original picture anywhere but filtering is performed directly + on the original image. Parameters controlling the filtering process + are computed based on information in macroblock structures of the + filtered macroblock, macroblock above and macroblock on the left of + the filtered one. + + Inputs: + image pointer to image to be filtered + mb pointer to macroblock data structure of the top-left + macroblock of the picture + + Outputs: + image filtered image stored here + + Returns: + none + +------------------------------------------------------------------------------*/ + +/*lint --e{550} Symbol not accessed */ +void h264bsdFilterPicture( + image_t *image, + mbStorage_t *mb) +{ + +/* Variables */ + + u32 flags; + u32 picSizeInMbs, mbRow, mbCol; + u32 picWidthInMbs; + u8 *data; + mbStorage_t *pMb; + u8 bS[2][16]; + u8 thresholdLuma[2][16]; + u8 thresholdChroma[2][8]; + u8 alpha[2][2]; + u8 beta[2][2]; + OMXResult res; + +/* Code */ + + ASSERT(image); + ASSERT(mb); + ASSERT(image->data); + ASSERT(image->width); + ASSERT(image->height); + + picWidthInMbs = image->width; + data = image->data; + picSizeInMbs = picWidthInMbs * image->height; + + pMb = mb; + + for (mbRow = 0, mbCol = 0; mbRow < image->height; pMb++) + { + flags = GetMbFilteringFlags(pMb); + + if (flags) + { + /* GetBoundaryStrengths function returns non-zero value if any of + * the bS values for the macroblock being processed was non-zero */ + if (GetBoundaryStrengths(pMb, bS, flags)) + { + + /* Luma */ + GetLumaEdgeThresholds(pMb,alpha,beta,thresholdLuma,bS,flags); + data = image->data + mbRow * picWidthInMbs * 256 + mbCol * 16; + + res = omxVCM4P10_FilterDeblockingLuma_VerEdge_I( data, + (OMX_S32)(picWidthInMbs*16), + (const OMX_U8*)alpha, + (const OMX_U8*)beta, + (const OMX_U8*)thresholdLuma, + (const OMX_U8*)bS ); + + res = omxVCM4P10_FilterDeblockingLuma_HorEdge_I( data, + (OMX_S32)(picWidthInMbs*16), + (const OMX_U8*)alpha+2, + (const OMX_U8*)beta+2, + (const OMX_U8*)thresholdLuma+16, + (const OMX_U8*)bS+16 ); + /* Cb */ + GetChromaEdgeThresholds(pMb, alpha, beta, thresholdChroma, + bS, flags, pMb->chromaQpIndexOffset); + data = image->data + picSizeInMbs * 256 + + mbRow * picWidthInMbs * 64 + mbCol * 8; + + res = omxVCM4P10_FilterDeblockingChroma_VerEdge_I( data, + (OMX_S32)(picWidthInMbs*8), + (const OMX_U8*)alpha, + (const OMX_U8*)beta, + (const OMX_U8*)thresholdChroma, + (const OMX_U8*)bS ); + res = omxVCM4P10_FilterDeblockingChroma_HorEdge_I( data, + (OMX_S32)(picWidthInMbs*8), + (const OMX_U8*)alpha+2, + (const OMX_U8*)beta+2, + (const OMX_U8*)thresholdChroma+8, + (const OMX_U8*)bS+16 ); + /* Cr */ + data += (picSizeInMbs * 64); + res = omxVCM4P10_FilterDeblockingChroma_VerEdge_I( data, + (OMX_S32)(picWidthInMbs*8), + (const OMX_U8*)alpha, + (const OMX_U8*)beta, + (const OMX_U8*)thresholdChroma, + (const OMX_U8*)bS ); + res = omxVCM4P10_FilterDeblockingChroma_HorEdge_I( data, + (OMX_S32)(picWidthInMbs*8), + (const OMX_U8*)alpha+2, + (const OMX_U8*)beta+2, + (const OMX_U8*)thresholdChroma+8, + (const OMX_U8*)bS+16 ); + } + } + + mbCol++; + if (mbCol == picWidthInMbs) + { + mbCol = 0; + mbRow++; + } + } + +} + +/*------------------------------------------------------------------------------ + + Function: GetBoundaryStrengths + + Functional description: + Function to calculate boundary strengths for all edges of a + macroblock. Function returns HANTRO_TRUE if any of the bS values for + the macroblock had non-zero value, HANTRO_FALSE otherwise. + +------------------------------------------------------------------------------*/ +u32 GetBoundaryStrengths(mbStorage_t *mb, u8 (*bS)[16], u32 flags) +{ + +/* Variables */ + + /* this flag is set HANTRO_TRUE as soon as any boundary strength value is + * non-zero */ + u32 nonZeroBs = HANTRO_FALSE; + u32 *pTmp; + u32 tmp1, tmp2, isIntraMb; + +/* Code */ + + ASSERT(mb); + ASSERT(bS); + ASSERT(flags); + + isIntraMb = IS_INTRA_MB(*mb); + + /* top edges */ + pTmp = (u32*)&bS[1][0]; + if (flags & FILTER_TOP_EDGE) + { + if (isIntraMb || IS_INTRA_MB(*mb->mbB)) + { + *pTmp = 0x04040404; + nonZeroBs = HANTRO_TRUE; + } + else + { + *pTmp = EdgeBoundaryStrengthTop(mb, mb->mbB); + if (*pTmp) + nonZeroBs = HANTRO_TRUE; + } + } + else + { + *pTmp = 0; + } + + /* left edges */ + pTmp = (u32*)&bS[0][0]; + if (flags & FILTER_LEFT_EDGE) + { + if (isIntraMb || IS_INTRA_MB(*mb->mbA)) + { + /*bS[0][0] = bS[0][1] = bS[0][2] = bS[0][3] = 4;*/ + *pTmp = 0x04040404; + nonZeroBs = HANTRO_TRUE; + } + else + { + *pTmp = EdgeBoundaryStrengthLeft(mb, mb->mbA); + if (!nonZeroBs && *pTmp) + nonZeroBs = HANTRO_TRUE; + } + } + else + { + *pTmp = 0; + } + + /* inner edges */ + if (isIntraMb) + { + pTmp++; + *pTmp++ = 0x03030303; + *pTmp++ = 0x03030303; + *pTmp++ = 0x03030303; + pTmp++; + *pTmp++ = 0x03030303; + *pTmp++ = 0x03030303; + *pTmp = 0x03030303; + + nonZeroBs = HANTRO_TRUE; + } + else + { + pTmp = (u32*)mb->totalCoeff; + + /* 16x16 inter mb -> ref addresses or motion vectors cannot differ, + * only check if either of the blocks contain coefficients */ + if (h264bsdNumMbPart(mb->mbType) == 1) + { + tmp1 = *pTmp++; + tmp2 = *pTmp++; + bS[1][4] = (tmp1 & 0x00FF00FF) ? 2 : 0; /* [2] || [0] */ + bS[1][5] = (tmp1 & 0xFF00FF00) ? 2 : 0; /* [3] || [1] */ + bS[0][4] = (tmp1 & 0x0000FFFF) ? 2 : 0; /* [1] || [0] */ + bS[0][5] = (tmp1 & 0xFFFF0000) ? 2 : 0; /* [3] || [2] */ + + tmp1 = *pTmp++; + bS[1][6] = (tmp2 & 0x00FF00FF) ? 2 : 0; /* [6] || [4] */ + bS[1][7] = (tmp2 & 0xFF00FF00) ? 2 : 0; /* [7] || [5] */ + bS[0][12] = (tmp2 & 0x0000FFFF) ? 2 : 0; /* [5] || [4] */ + bS[0][13] = (tmp2 & 0xFFFF0000) ? 2 : 0; /* [7] || [6] */ + tmp2 = *pTmp; + bS[1][12] = (tmp1 & 0x00FF00FF) ? 2 : 0; /* [10] || [8] */ + bS[1][13] = (tmp1 & 0xFF00FF00) ? 2 : 0; /* [11] || [9] */ + bS[0][6] = (tmp1 & 0x0000FFFF) ? 2 : 0; /* [9] || [8] */ + bS[0][7] = (tmp1 & 0xFFFF0000) ? 2 : 0; /* [11] || [10] */ + + bS[1][14] = (tmp2 & 0x00FF00FF) ? 2 : 0; /* [14] || [12] */ + bS[1][15] = (tmp2 & 0xFF00FF00) ? 2 : 0; /* [15] || [13] */ + bS[0][14] = (tmp2 & 0x0000FFFF) ? 2 : 0; /* [13] || [12] */ + bS[0][15] = (tmp2 & 0xFFFF0000) ? 2 : 0; /* [15] || [14] */ + + { + u32 tmp3, tmp4; + + tmp1 = mb->totalCoeff[8]; + tmp2 = mb->totalCoeff[2]; + tmp3 = mb->totalCoeff[9]; + tmp4 = mb->totalCoeff[3]; + + bS[1][8] = tmp1 || tmp2 ? 2 : 0; + tmp1 = mb->totalCoeff[12]; + tmp2 = mb->totalCoeff[6]; + bS[1][9] = tmp3 || tmp4 ? 2 : 0; + tmp3 = mb->totalCoeff[13]; + tmp4 = mb->totalCoeff[7]; + bS[1][10] = tmp1 || tmp2 ? 2 : 0; + tmp1 = mb->totalCoeff[4]; + tmp2 = mb->totalCoeff[1]; + bS[1][11] = tmp3 || tmp4 ? 2 : 0; + tmp3 = mb->totalCoeff[6]; + tmp4 = mb->totalCoeff[3]; + bS[0][8] = tmp1 || tmp2 ? 2 : 0; + tmp1 = mb->totalCoeff[12]; + tmp2 = mb->totalCoeff[9]; + bS[0][9] = tmp3 || tmp4 ? 2 : 0; + tmp3 = mb->totalCoeff[14]; + tmp4 = mb->totalCoeff[11]; + bS[0][10] = tmp1 || tmp2 ? 2 : 0; + bS[0][11] = tmp3 || tmp4 ? 2 : 0; + } + } + + /* 16x8 inter mb -> ref addresses and motion vectors can be different + * only for the middle horizontal edge, for the other top edges it is + * enough to check whether the blocks contain coefficients or not. The + * same applies to all internal left edges. */ + else if (mb->mbType == P_L0_L0_16x8) + { + tmp1 = *pTmp++; + tmp2 = *pTmp++; + bS[1][4] = (tmp1 & 0x00FF00FF) ? 2 : 0; /* [2] || [0] */ + bS[1][5] = (tmp1 & 0xFF00FF00) ? 2 : 0; /* [3] || [1] */ + bS[0][4] = (tmp1 & 0x0000FFFF) ? 2 : 0; /* [1] || [0] */ + bS[0][5] = (tmp1 & 0xFFFF0000) ? 2 : 0; /* [3] || [2] */ + tmp1 = *pTmp++; + bS[1][6] = (tmp2 & 0x00FF00FF) ? 2 : 0; /* [6] || [4] */ + bS[1][7] = (tmp2 & 0xFF00FF00) ? 2 : 0; /* [7] || [5] */ + bS[0][12] = (tmp2 & 0x0000FFFF) ? 2 : 0; /* [5] || [4] */ + bS[0][13] = (tmp2 & 0xFFFF0000) ? 2 : 0; /* [7] || [6] */ + tmp2 = *pTmp; + bS[1][12] = (tmp1 & 0x00FF00FF) ? 2 : 0; /* [10] || [8] */ + bS[1][13] = (tmp1 & 0xFF00FF00) ? 2 : 0; /* [11] || [9] */ + bS[0][6] = (tmp1 & 0x0000FFFF) ? 2 : 0; /* [9] || [8] */ + bS[0][7] = (tmp1 & 0xFFFF0000) ? 2 : 0; /* [11] || [10] */ + + bS[1][14] = (tmp2 & 0x00FF00FF) ? 2 : 0; /* [14] || [12] */ + bS[1][15] = (tmp2 & 0xFF00FF00) ? 2 : 0; /* [15] || [13] */ + bS[0][14] = (tmp2 & 0x0000FFFF) ? 2 : 0; /* [13] || [12] */ + bS[0][15] = (tmp2 & 0xFFFF0000) ? 2 : 0; /* [15] || [14] */ + + bS[1][8] = (u8)InnerBoundaryStrength(mb, 8, 2); + bS[1][9] = (u8)InnerBoundaryStrength(mb, 9, 3); + bS[1][10] = (u8)InnerBoundaryStrength(mb, 12, 6); + bS[1][11] = (u8)InnerBoundaryStrength(mb, 13, 7); + + { + u32 tmp3, tmp4; + + tmp1 = mb->totalCoeff[4]; + tmp2 = mb->totalCoeff[1]; + tmp3 = mb->totalCoeff[6]; + tmp4 = mb->totalCoeff[3]; + bS[0][8] = tmp1 || tmp2 ? 2 : 0; + tmp1 = mb->totalCoeff[12]; + tmp2 = mb->totalCoeff[9]; + bS[0][9] = tmp3 || tmp4 ? 2 : 0; + tmp3 = mb->totalCoeff[14]; + tmp4 = mb->totalCoeff[11]; + bS[0][10] = tmp1 || tmp2 ? 2 : 0; + bS[0][11] = tmp3 || tmp4 ? 2 : 0; + } + } + /* 8x16 inter mb -> ref addresses and motion vectors can be different + * only for the middle vertical edge, for the other left edges it is + * enough to check whether the blocks contain coefficients or not. The + * same applies to all internal top edges. */ + else if (mb->mbType == P_L0_L0_8x16) + { + tmp1 = *pTmp++; + tmp2 = *pTmp++; + bS[1][4] = (tmp1 & 0x00FF00FF) ? 2 : 0; /* [2] || [0] */ + bS[1][5] = (tmp1 & 0xFF00FF00) ? 2 : 0; /* [3] || [1] */ + bS[0][4] = (tmp1 & 0x0000FFFF) ? 2 : 0; /* [1] || [0] */ + bS[0][5] = (tmp1 & 0xFFFF0000) ? 2 : 0; /* [3] || [2] */ + tmp1 = *pTmp++; + bS[1][6] = (tmp2 & 0x00FF00FF) ? 2 : 0; /* [6] || [4] */ + bS[1][7] = (tmp2 & 0xFF00FF00) ? 2 : 0; /* [7] || [5] */ + bS[0][12] = (tmp2 & 0x0000FFFF) ? 2 : 0; /* [5] || [4] */ + bS[0][13] = (tmp2 & 0xFFFF0000) ? 2 : 0; /* [7] || [6] */ + tmp2 = *pTmp; + bS[1][12] = (tmp1 & 0x00FF00FF) ? 2 : 0; /* [10] || [8] */ + bS[1][13] = (tmp1 & 0xFF00FF00) ? 2 : 0; /* [11] || [9] */ + bS[0][6] = (tmp1 & 0x0000FFFF) ? 2 : 0; /* [9] || [8] */ + bS[0][7] = (tmp1 & 0xFFFF0000) ? 2 : 0; /* [11] || [10] */ + + bS[1][14] = (tmp2 & 0x00FF00FF) ? 2 : 0; /* [14] || [12] */ + bS[1][15] = (tmp2 & 0xFF00FF00) ? 2 : 0; /* [15] || [13] */ + bS[0][14] = (tmp2 & 0x0000FFFF) ? 2 : 0; /* [13] || [12] */ + bS[0][15] = (tmp2 & 0xFFFF0000) ? 2 : 0; /* [15] || [14] */ + + bS[0][8] = (u8)InnerBoundaryStrength(mb, 4, 1); + bS[0][9] = (u8)InnerBoundaryStrength(mb, 6, 3); + bS[0][10] = (u8)InnerBoundaryStrength(mb, 12, 9); + bS[0][11] = (u8)InnerBoundaryStrength(mb, 14, 11); + + { + u32 tmp3, tmp4; + + tmp1 = mb->totalCoeff[8]; + tmp2 = mb->totalCoeff[2]; + tmp3 = mb->totalCoeff[9]; + tmp4 = mb->totalCoeff[3]; + bS[1][8] = tmp1 || tmp2 ? 2 : 0; + tmp1 = mb->totalCoeff[12]; + tmp2 = mb->totalCoeff[6]; + bS[1][9] = tmp3 || tmp4 ? 2 : 0; + tmp3 = mb->totalCoeff[13]; + tmp4 = mb->totalCoeff[7]; + bS[1][10] = tmp1 || tmp2 ? 2 : 0; + bS[1][11] = tmp3 || tmp4 ? 2 : 0; + } + } + else + { + tmp1 = *pTmp++; + bS[1][4] = (tmp1 & 0x00FF00FF) ? 2 : (u8)InnerBoundaryStrength2(mb, 2, 0); + bS[1][5] = (tmp1 & 0xFF00FF00) ? 2 : (u8)InnerBoundaryStrength2(mb, 3, 1); + bS[0][4] = (tmp1 & 0x0000FFFF) ? 2 : (u8)InnerBoundaryStrength2(mb, 1, 0); + bS[0][5] = (tmp1 & 0xFFFF0000) ? 2 : (u8)InnerBoundaryStrength2(mb, 3, 2); + tmp1 = *pTmp++; + bS[1][6] = (tmp1 & 0x00FF00FF) ? 2 : (u8)InnerBoundaryStrength2(mb, 6, 4); + bS[1][7] = (tmp1 & 0xFF00FF00) ? 2 : (u8)InnerBoundaryStrength2(mb, 7, 5); + bS[0][12] = (tmp1 & 0x0000FFFF) ? 2 : (u8)InnerBoundaryStrength2(mb, 5, 4); + bS[0][13] = (tmp1 & 0xFFFF0000) ? 2 : (u8)InnerBoundaryStrength2(mb, 7, 6); + tmp1 = *pTmp++; + bS[1][12] = (tmp1 & 0x00FF00FF) ? 2 : (u8)InnerBoundaryStrength2(mb, 10, 8); + bS[1][13] = (tmp1 & 0xFF00FF00) ? 2 : (u8)InnerBoundaryStrength2(mb, 11, 9); + bS[0][6] = (tmp1 & 0x0000FFFF) ? 2 : (u8)InnerBoundaryStrength2(mb, 9, 8); + bS[0][7] = (tmp1 & 0xFFFF0000) ? 2 : (u8)InnerBoundaryStrength2(mb, 11, 10); + tmp1 = *pTmp; + bS[1][14] = (tmp1 & 0x00FF00FF) ? 2 : (u8)InnerBoundaryStrength2(mb, 14, 12); + bS[1][15] = (tmp1 & 0xFF00FF00) ? 2 : (u8)InnerBoundaryStrength2(mb, 15, 13); + bS[0][14] = (tmp1 & 0x0000FFFF) ? 2 : (u8)InnerBoundaryStrength2(mb, 13, 12); + bS[0][15] = (tmp1 & 0xFFFF0000) ? 2 : (u8)InnerBoundaryStrength2(mb, 15, 14); + + bS[1][8] = (u8)InnerBoundaryStrength(mb, 8, 2); + bS[1][9] = (u8)InnerBoundaryStrength(mb, 9, 3); + bS[1][10] = (u8)InnerBoundaryStrength(mb, 12, 6); + bS[1][11] = (u8)InnerBoundaryStrength(mb, 13, 7); + + bS[0][8] = (u8)InnerBoundaryStrength(mb, 4, 1); + bS[0][9] = (u8)InnerBoundaryStrength(mb, 6, 3); + bS[0][10] = (u8)InnerBoundaryStrength(mb, 12, 9); + bS[0][11] = (u8)InnerBoundaryStrength(mb, 14, 11); + } + pTmp = (u32*)&bS[0][0]; + if (!nonZeroBs && (pTmp[1] || pTmp[2] || pTmp[3] || + pTmp[5] || pTmp[6] || pTmp[7]) ) + { + nonZeroBs = HANTRO_TRUE; + } + } + + return(nonZeroBs); + +} + +/*------------------------------------------------------------------------------ + + Function: GetLumaEdgeThresholds + + Functional description: + Compute alpha, beta and tc0 thresholds for inner, left and top + luma edges of a macroblock. + +------------------------------------------------------------------------------*/ +void GetLumaEdgeThresholds( + mbStorage_t *mb, + u8 (*alpha)[2], + u8 (*beta)[2], + u8 (*threshold)[16], + u8 (*bs)[16], + u32 filteringFlags ) +{ + +/* Variables */ + + u32 indexA, indexB; + u32 qpAv, qp, qpTmp; + u32 i; + +/* Code */ + + ASSERT(threshold); + ASSERT(bs); + ASSERT(beta); + ASSERT(alpha); + ASSERT(mb); + + qp = mb->qpY; + + indexA = (u32)CLIP3(0, 51, (i32)qp + mb->filterOffsetA); + indexB = (u32)CLIP3(0, 51, (i32)qp + mb->filterOffsetB); + + /* Internal edge values */ + alpha[0][1] = alphas[indexA]; + alpha[1][1] = alphas[indexA]; + alpha[1][0] = alphas[indexA]; + alpha[0][0] = alphas[indexA]; + beta[0][1] = betas[indexB]; + beta[1][1] = betas[indexB]; + beta[1][0] = betas[indexB]; + beta[0][0] = betas[indexB]; + + /* vertical scan order */ + for (i = 0; i < 2; i++) + { + u32 t1, t2; + + t1 = bs[i][0]; + t2 = bs[i][1]; + threshold[i][0] = (t1) ? tc0[indexA][t1] : 0; + t1 = bs[i][2]; + threshold[i][1] = (t2) ? tc0[indexA][t2] : 0; + t2 = bs[i][3]; + threshold[i][2] = (t1) ? tc0[indexA][t1] : 0; + t1 = bs[i][4]; + threshold[i][3] = (t2) ? tc0[indexA][t2] : 0; + t2 = bs[i][5]; + threshold[i][4] = (t1) ? tc0[indexA][t1] : 0; + t1 = bs[i][6]; + threshold[i][5] = (t2) ? tc0[indexA][t2] : 0; + t2 = bs[i][7]; + threshold[i][6] = (t1) ? tc0[indexA][t1] : 0; + t1 = bs[i][8]; + threshold[i][7] = (t2) ? tc0[indexA][t2] : 0; + t2 = bs[i][9]; + threshold[i][8] = (t1) ? tc0[indexA][t1] : 0; + t1 = bs[i][10]; + threshold[i][9] = (t2) ? tc0[indexA][t2] : 0; + t2 = bs[i][11]; + threshold[i][10] = (t1) ? tc0[indexA][t1] : 0; + t1 = bs[i][12]; + threshold[i][11] = (t2) ? tc0[indexA][t2] : 0; + t2 = bs[i][13]; + threshold[i][12] = (t1) ? tc0[indexA][t1] : 0; + t1 = bs[i][14]; + threshold[i][13] = (t2) ? tc0[indexA][t2] : 0; + t2 = bs[i][15]; + threshold[i][14] = (t1) ? tc0[indexA][t1] : 0; + threshold[i][15] = (t2) ? tc0[indexA][t2] : 0; + } + + if (filteringFlags & FILTER_TOP_EDGE) + { + qpTmp = mb->mbB->qpY; + if (qpTmp != qp) + { + u32 t1, t2, t3, t4; + qpAv = (qp + qpTmp + 1) >> 1; + + indexA = (u32)CLIP3(0, 51, (i32)qpAv + mb->filterOffsetA); + indexB = (u32)CLIP3(0, 51, (i32)qpAv + mb->filterOffsetB); + + alpha[1][0] = alphas[indexA]; + beta[1][0] = betas[indexB]; + t1 = bs[1][0]; + t2 = bs[1][1]; + t3 = bs[1][2]; + t4 = bs[1][3]; + threshold[1][0] = (t1 && (t1 < 4)) ? tc0[indexA][t1] : 0; + threshold[1][1] = (t2 && (t2 < 4)) ? tc0[indexA][t2] : 0; + threshold[1][2] = (t3 && (t3 < 4)) ? tc0[indexA][t3] : 0; + threshold[1][3] = (t4 && (t4 < 4)) ? tc0[indexA][t4] : 0; + } + } + if (filteringFlags & FILTER_LEFT_EDGE) + { + qpTmp = mb->mbA->qpY; + if (qpTmp != qp) + { + qpAv = (qp + qpTmp + 1) >> 1; + + indexA = (u32)CLIP3(0, 51, (i32)qpAv + mb->filterOffsetA); + indexB = (u32)CLIP3(0, 51, (i32)qpAv + mb->filterOffsetB); + + alpha[0][0] = alphas[indexA]; + beta[0][0] = betas[indexB]; + threshold[0][0] = (bs[0][0] && (bs[0][0] < 4)) ? tc0[indexA][bs[0][0]] : 0; + threshold[0][1] = (bs[0][1] && (bs[0][1] < 4)) ? tc0[indexA][bs[0][1]] : 0; + threshold[0][2] = (bs[0][2] && (bs[0][2] < 4)) ? tc0[indexA][bs[0][2]] : 0; + threshold[0][3] = (bs[0][3] && (bs[0][3] < 4)) ? tc0[indexA][bs[0][3]] : 0; + } + } + +} + +/*------------------------------------------------------------------------------ + + Function: GetChromaEdgeThresholds + + Functional description: + Compute alpha, beta and tc0 thresholds for inner, left and top + chroma edges of a macroblock. + +------------------------------------------------------------------------------*/ +void GetChromaEdgeThresholds( + mbStorage_t *mb, + u8 (*alpha)[2], + u8 (*beta)[2], + u8 (*threshold)[8], + u8 (*bs)[16], + u32 filteringFlags, + i32 chromaQpIndexOffset) +{ + +/* Variables */ + + u32 indexA, indexB; + u32 qpAv, qp, qpTmp; + u32 i; + +/* Code */ + + ASSERT(threshold); + ASSERT(bs); + ASSERT(beta); + ASSERT(alpha); + ASSERT(mb); + ASSERT(mb); + + qp = mb->qpY; + qp = h264bsdQpC[CLIP3(0, 51, (i32)qp + chromaQpIndexOffset)]; + + indexA = (u32)CLIP3(0, 51, (i32)qp + mb->filterOffsetA); + indexB = (u32)CLIP3(0, 51, (i32)qp + mb->filterOffsetB); + + alpha[0][1] = alphas[indexA]; + alpha[1][1] = alphas[indexA]; + alpha[1][0] = alphas[indexA]; + alpha[0][0] = alphas[indexA]; + beta[0][1] = betas[indexB]; + beta[1][1] = betas[indexB]; + beta[1][0] = betas[indexB]; + beta[0][0] = betas[indexB]; + + for (i = 0; i < 2; i++) + { + u32 t1, t2; + + t1 = bs[i][0]; + t2 = bs[i][1]; + threshold[i][0] = (t1) ? tc0[indexA][t1] : 0; + t1 = bs[i][2]; + threshold[i][1] = (t2) ? tc0[indexA][t2] : 0; + t2 = bs[i][3]; + threshold[i][2] = (t1) ? tc0[indexA][t1] : 0; + t1 = bs[i][8]; + threshold[i][3] = (t2) ? tc0[indexA][t2] : 0; + t2 = bs[i][9]; + threshold[i][4] = (t1) ? tc0[indexA][t1] : 0; + t1 = bs[i][10]; + threshold[i][5] = (t2) ? tc0[indexA][t2] : 0; + t2 = bs[i][11]; + threshold[i][6] = (t1) ? tc0[indexA][t1] : 0; + threshold[i][7] = (t2) ? tc0[indexA][t2] : 0; + } + + if (filteringFlags & FILTER_TOP_EDGE) + { + qpTmp = mb->mbB->qpY; + if (qpTmp != mb->qpY) + { + u32 t1, t2, t3, t4; + qpTmp = h264bsdQpC[CLIP3(0, 51, (i32)qpTmp + chromaQpIndexOffset)]; + qpAv = (qp + qpTmp + 1) >> 1; + + indexA = (u32)CLIP3(0, 51, (i32)qpAv + mb->filterOffsetA); + indexB = (u32)CLIP3(0, 51, (i32)qpAv + mb->filterOffsetB); + + alpha[1][0] = alphas[indexA]; + beta[1][0] = betas[indexB]; + + t1 = bs[1][0]; + t2 = bs[1][1]; + t3 = bs[1][2]; + t4 = bs[1][3]; + threshold[1][0] = (t1) ? tc0[indexA][t1] : 0; + threshold[1][1] = (t2) ? tc0[indexA][t2] : 0; + threshold[1][2] = (t3) ? tc0[indexA][t3] : 0; + threshold[1][3] = (t4) ? tc0[indexA][t4] : 0; + } + } + if (filteringFlags & FILTER_LEFT_EDGE) + { + qpTmp = mb->mbA->qpY; + if (qpTmp != mb->qpY) + { + + qpTmp = h264bsdQpC[CLIP3(0, 51, (i32)qpTmp + chromaQpIndexOffset)]; + qpAv = (qp + qpTmp + 1) >> 1; + + indexA = (u32)CLIP3(0, 51, (i32)qpAv + mb->filterOffsetA); + indexB = (u32)CLIP3(0, 51, (i32)qpAv + mb->filterOffsetB); + + alpha[0][0] = alphas[indexA]; + beta[0][0] = betas[indexB]; + threshold[0][0] = (bs[0][0]) ? tc0[indexA][bs[0][0]] : 0; + threshold[0][1] = (bs[0][1]) ? tc0[indexA][bs[0][1]] : 0; + threshold[0][2] = (bs[0][2]) ? tc0[indexA][bs[0][2]] : 0; + threshold[0][3] = (bs[0][3]) ? tc0[indexA][bs[0][3]] : 0; + } + } + +} + +#endif /* H264DEC_OMXDL */ + +/*lint +e701 +e702 */ + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_deblocking.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_deblocking.h new file mode 100755 index 0000000..2571dda --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_deblocking.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. Module defines + 3. Data types + 4. Function prototypes + +------------------------------------------------------------------------------*/ + +#ifndef H264SWDEC_DEBLOCKING_H +#define H264SWDEC_DEBLOCKING_H + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "basetype.h" +#include "h264bsd_image.h" +#include "h264bsd_macroblock_layer.h" + +/*------------------------------------------------------------------------------ + 2. Module defines +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 3. Data types +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ + +void h264bsdFilterPicture( + image_t *image, + mbStorage_t *mb); + +#endif /* #ifdef H264SWDEC_DEBLOCKING_H */ + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_decoder.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_decoder.c new file mode 100644 index 0000000..a816871 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_decoder.c @@ -0,0 +1,961 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. External compiler flags + 3. Module defines + 4. Local function prototypes + 5. Functions + h264bsdInit + h264bsdDecode + h264bsdShutdown + h264bsdCurrentImage + h264bsdNextOutputPicture + h264bsdPicWidth + h264bsdPicHeight + h264bsdFlushBuffer + h264bsdCheckValidParamSets + h264bsdVideoRange + h264bsdMatrixCoefficients + h264bsdCroppingParams + +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "h264bsd_decoder.h" +#include "h264bsd_nal_unit.h" +#include "h264bsd_byte_stream.h" +#include "h264bsd_seq_param_set.h" +#include "h264bsd_pic_param_set.h" +#include "h264bsd_slice_header.h" +#include "h264bsd_slice_data.h" +#include "h264bsd_neighbour.h" +#include "h264bsd_util.h" +#include "h264bsd_dpb.h" +#include "h264bsd_deblocking.h" +#include "h264bsd_conceal.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + + Function name: h264bsdInit + + Functional description: + Initialize the decoder. + + Inputs: + noOutputReordering flag to indicate the decoder that it does not + have to perform reordering of display images. + + Outputs: + pStorage pointer to initialized storage structure + + Returns: + none + +------------------------------------------------------------------------------*/ + +u32 h264bsdInit(storage_t *pStorage, u32 noOutputReordering) +{ + +/* Variables */ + u32 size; +/* Code */ + + ASSERT(pStorage); + + h264bsdInitStorage(pStorage); + + /* allocate mbLayer to be next multiple of 64 to enable use of + * specific NEON optimized "memset" for clearing the structure */ + size = (sizeof(macroblockLayer_t) + 63) & ~0x3F; + + pStorage->mbLayer = (macroblockLayer_t*)H264SwDecMalloc(size); + if (!pStorage->mbLayer) + return HANTRO_NOK; + + if (noOutputReordering) + pStorage->noReordering = HANTRO_TRUE; + + return HANTRO_OK; +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdDecode + + Functional description: + Decode a NAL unit. This function calls other modules to perform + tasks like + * extract and decode NAL unit from the byte stream + * decode parameter sets + * decode slice header and slice data + * conceal errors in the picture + * perform deblocking filtering + + This function contains top level control logic of the decoder. + + Inputs: + pStorage pointer to storage data structure + byteStrm pointer to stream buffer given by application + len length of the buffer in bytes + picId identifier for a picture, assigned by the + application + + Outputs: + readBytes number of bytes read from the stream is stored + here + + Returns: + H264BSD_RDY decoding finished, nothing special + H264BSD_PIC_RDY decoding of a picture finished + H264BSD_HDRS_RDY param sets activated, information like + picture dimensions etc can be read + H264BSD_ERROR error in decoding + H264BSD_PARAM_SET_ERROR serius error in decoding, failed to + activate param sets + +------------------------------------------------------------------------------*/ + +u32 h264bsdDecode(storage_t *pStorage, u8 *byteStrm, u32 len, u32 picId, + u32 *readBytes) +{ + +/* Variables */ + + u32 tmp, ppsId, spsId; + i32 picOrderCnt; + nalUnit_t nalUnit; + seqParamSet_t seqParamSet; + picParamSet_t picParamSet; + strmData_t strm; + u32 accessUnitBoundaryFlag = HANTRO_FALSE; + u32 picReady = HANTRO_FALSE; + +/* Code */ + + ASSERT(pStorage); + ASSERT(byteStrm); + ASSERT(len); + ASSERT(readBytes); + + /* if previous buffer was not finished and same pointer given -> skip NAL + * unit extraction */ + if (pStorage->prevBufNotFinished && byteStrm == pStorage->prevBufPointer) + { + strm = pStorage->strm[0]; + strm.pStrmCurrPos = strm.pStrmBuffStart; + strm.strmBuffReadBits = strm.bitPosInWord = 0; + *readBytes = pStorage->prevBytesConsumed; + } + else + { + tmp = h264bsdExtractNalUnit(byteStrm, len, &strm, readBytes); + if (tmp != HANTRO_OK) + { + EPRINT("BYTE_STREAM"); + return(H264BSD_ERROR); + } + /* store stream */ + pStorage->strm[0] = strm; + pStorage->prevBytesConsumed = *readBytes; + pStorage->prevBufPointer = byteStrm; + } + pStorage->prevBufNotFinished = HANTRO_FALSE; + + tmp = h264bsdDecodeNalUnit(&strm, &nalUnit); + if (tmp != HANTRO_OK) + { + EPRINT("NAL_UNIT"); + return(H264BSD_ERROR); + } + + /* Discard unspecified, reserved, SPS extension and auxiliary picture slices */ + if(nalUnit.nalUnitType == 0 || nalUnit.nalUnitType >= 13) + { + DEBUG(("DISCARDED NAL (UNSPECIFIED, REGISTERED, SPS ext or AUX slice)\n")); + return(H264BSD_RDY); + } + + tmp = h264bsdCheckAccessUnitBoundary( + &strm, + &nalUnit, + pStorage, + &accessUnitBoundaryFlag); + if (tmp != HANTRO_OK) + { + EPRINT("ACCESS UNIT BOUNDARY CHECK"); + if (tmp == PARAM_SET_ERROR) + return(H264BSD_PARAM_SET_ERROR); + else + return(H264BSD_ERROR); + } + + if ( accessUnitBoundaryFlag ) + { + DEBUG(("Access unit boundary\n")); + /* conceal if picture started and param sets activated */ + if (pStorage->picStarted && pStorage->activeSps != NULL) + { + DEBUG(("CONCEALING...")); + + /* return error if second phase of + * initialization is not completed */ + if (pStorage->pendingActivation) + { + EPRINT("Pending activation not completed"); + return (H264BSD_ERROR); + } + + if (!pStorage->validSliceInAccessUnit) + { + pStorage->currImage->data = + h264bsdAllocateDpbImage(pStorage->dpb); + h264bsdInitRefPicList(pStorage->dpb); + tmp = h264bsdConceal(pStorage, pStorage->currImage, P_SLICE); + } + else + tmp = h264bsdConceal(pStorage, pStorage->currImage, + pStorage->sliceHeader->sliceType); + + picReady = HANTRO_TRUE; + + /* current NAL unit should be decoded on next activation -> set + * readBytes to 0 */ + *readBytes = 0; + pStorage->prevBufNotFinished = HANTRO_TRUE; + DEBUG(("...DONE\n")); + } + else + { + pStorage->validSliceInAccessUnit = HANTRO_FALSE; + } + pStorage->skipRedundantSlices = HANTRO_FALSE; + } + + if (!picReady) + { + switch (nalUnit.nalUnitType) + { + case NAL_SEQ_PARAM_SET: + DEBUG(("SEQ PARAM SET\n")); + tmp = h264bsdDecodeSeqParamSet(&strm, &seqParamSet); + if (tmp != HANTRO_OK) + { + EPRINT("SEQ_PARAM_SET"); + FREE(seqParamSet.offsetForRefFrame); + FREE(seqParamSet.vuiParameters); + return(H264BSD_ERROR); + } + tmp = h264bsdStoreSeqParamSet(pStorage, &seqParamSet); + break; + + case NAL_PIC_PARAM_SET: + DEBUG(("PIC PARAM SET\n")); + tmp = h264bsdDecodePicParamSet(&strm, &picParamSet); + if (tmp != HANTRO_OK) + { + EPRINT("PIC_PARAM_SET"); + FREE(picParamSet.runLength); + FREE(picParamSet.topLeft); + FREE(picParamSet.bottomRight); + FREE(picParamSet.sliceGroupId); + return(H264BSD_ERROR); + } + tmp = h264bsdStorePicParamSet(pStorage, &picParamSet); + break; + + case NAL_CODED_SLICE_IDR: + DEBUG(("IDR ")); + /* fall through */ + case NAL_CODED_SLICE: + DEBUG(("SLICE HEADER\n")); + + /* picture successfully finished and still decoding same old + * access unit -> no need to decode redundant slices */ + if (pStorage->skipRedundantSlices) + return(H264BSD_RDY); + + pStorage->picStarted = HANTRO_TRUE; + + if (h264bsdIsStartOfPicture(pStorage)) + { + pStorage->numConcealedMbs = 0; + pStorage->currentPicId = picId; + + tmp = h264bsdCheckPpsId(&strm, &ppsId); + ASSERT(tmp == HANTRO_OK); + /* store old activeSpsId and return headers ready + * indication if activeSps changes */ + spsId = pStorage->activeSpsId; + tmp = h264bsdActivateParamSets(pStorage, ppsId, + IS_IDR_NAL_UNIT(&nalUnit) ? + HANTRO_TRUE : HANTRO_FALSE); + if (tmp != HANTRO_OK) + { + EPRINT("Param set activation"); + pStorage->activePpsId = MAX_NUM_PIC_PARAM_SETS; + pStorage->activePps = NULL; + pStorage->activeSpsId = MAX_NUM_SEQ_PARAM_SETS; + pStorage->activeSps = NULL; + pStorage->pendingActivation = HANTRO_FALSE; + + if(tmp == MEMORY_ALLOCATION_ERROR) + { + return H264BSD_MEMALLOC_ERROR; + } + else + return(H264BSD_PARAM_SET_ERROR); + } + + if (spsId != pStorage->activeSpsId) + { + seqParamSet_t *oldSPS = NULL; + seqParamSet_t *newSPS = pStorage->activeSps; + u32 noOutputOfPriorPicsFlag = 1; + + if(pStorage->oldSpsId < MAX_NUM_SEQ_PARAM_SETS) + { + oldSPS = pStorage->sps[pStorage->oldSpsId]; + } + + *readBytes = 0; + pStorage->prevBufNotFinished = HANTRO_TRUE; + + + if(nalUnit.nalUnitType == NAL_CODED_SLICE_IDR) + { + tmp = + h264bsdCheckPriorPicsFlag(&noOutputOfPriorPicsFlag, + &strm, newSPS, + pStorage->activePps, + nalUnit.nalUnitType); + } + else + { + tmp = HANTRO_NOK; + } + + if((tmp != HANTRO_OK) || + (noOutputOfPriorPicsFlag != 0) || + (pStorage->dpb->noReordering) || + (oldSPS == NULL) || + (oldSPS->picWidthInMbs != newSPS->picWidthInMbs) || + (oldSPS->picHeightInMbs != newSPS->picHeightInMbs) || + (oldSPS->maxDpbSize != newSPS->maxDpbSize)) + { + pStorage->dpb->flushed = 0; + } + else + { + h264bsdFlushDpb(pStorage->dpb); + } + + pStorage->oldSpsId = pStorage->activeSpsId; + + return(H264BSD_HDRS_RDY); + } + } + + /* return error if second phase of + * initialization is not completed */ + if (pStorage->pendingActivation) + { + EPRINT("Pending activation not completed"); + return (H264BSD_ERROR); + } + tmp = h264bsdDecodeSliceHeader(&strm, pStorage->sliceHeader + 1, + pStorage->activeSps, pStorage->activePps, &nalUnit); + if (tmp != HANTRO_OK) + { + EPRINT("SLICE_HEADER"); + return(H264BSD_ERROR); + } + if (h264bsdIsStartOfPicture(pStorage)) + { + if (!IS_IDR_NAL_UNIT(&nalUnit)) + { + tmp = h264bsdCheckGapsInFrameNum(pStorage->dpb, + pStorage->sliceHeader[1].frameNum, + nalUnit.nalRefIdc != 0 ? + HANTRO_TRUE : HANTRO_FALSE, + pStorage->activeSps-> + gapsInFrameNumValueAllowedFlag); + if (tmp != HANTRO_OK) + { + EPRINT("Gaps in frame num"); + return(H264BSD_ERROR); + } + } + pStorage->currImage->data = + h264bsdAllocateDpbImage(pStorage->dpb); + } + + /* store slice header to storage if successfully decoded */ + pStorage->sliceHeader[0] = pStorage->sliceHeader[1]; + pStorage->validSliceInAccessUnit = HANTRO_TRUE; + pStorage->prevNalUnit[0] = nalUnit; + + h264bsdComputeSliceGroupMap(pStorage, + pStorage->sliceHeader->sliceGroupChangeCycle); + + h264bsdInitRefPicList(pStorage->dpb); + tmp = h264bsdReorderRefPicList(pStorage->dpb, + &pStorage->sliceHeader->refPicListReordering, + pStorage->sliceHeader->frameNum, + pStorage->sliceHeader->numRefIdxL0Active); + if (tmp != HANTRO_OK) + { + EPRINT("Reordering"); + return(H264BSD_ERROR); + } + + DEBUG(("SLICE DATA, FIRST %d\n", + pStorage->sliceHeader->firstMbInSlice)); + tmp = h264bsdDecodeSliceData(&strm, pStorage, + pStorage->currImage, pStorage->sliceHeader); + if (tmp != HANTRO_OK) + { + EPRINT("SLICE_DATA"); + h264bsdMarkSliceCorrupted(pStorage, + pStorage->sliceHeader->firstMbInSlice); + return(H264BSD_ERROR); + } + + if (h264bsdIsEndOfPicture(pStorage)) + { + picReady = HANTRO_TRUE; + pStorage->skipRedundantSlices = HANTRO_TRUE; + } + break; + + case NAL_SEI: + DEBUG(("SEI MESSAGE, NOT DECODED")); + break; + + default: + DEBUG(("NOT IMPLEMENTED YET %d\n",nalUnit.nalUnitType)); + } + } + + if (picReady) + { + h264bsdFilterPicture(pStorage->currImage, pStorage->mb); + + h264bsdResetStorage(pStorage); + + picOrderCnt = h264bsdDecodePicOrderCnt(pStorage->poc, + pStorage->activeSps, pStorage->sliceHeader, pStorage->prevNalUnit); + + if (pStorage->validSliceInAccessUnit) + { + if (pStorage->prevNalUnit->nalRefIdc) + { + tmp = h264bsdMarkDecRefPic(pStorage->dpb, + &pStorage->sliceHeader->decRefPicMarking, + pStorage->currImage, pStorage->sliceHeader->frameNum, + picOrderCnt, + IS_IDR_NAL_UNIT(pStorage->prevNalUnit) ? + HANTRO_TRUE : HANTRO_FALSE, + pStorage->currentPicId, pStorage->numConcealedMbs); + } + /* non-reference picture, just store for possible display + * reordering */ + else + { + tmp = h264bsdMarkDecRefPic(pStorage->dpb, NULL, + pStorage->currImage, pStorage->sliceHeader->frameNum, + picOrderCnt, + IS_IDR_NAL_UNIT(pStorage->prevNalUnit) ? + HANTRO_TRUE : HANTRO_FALSE, + pStorage->currentPicId, pStorage->numConcealedMbs); + } + } + + pStorage->picStarted = HANTRO_FALSE; + pStorage->validSliceInAccessUnit = HANTRO_FALSE; + + return(H264BSD_PIC_RDY); + } + else + return(H264BSD_RDY); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdShutdown + + Functional description: + Shutdown a decoder instance. Function frees all the memories + allocated for the decoder instance. + + Inputs: + pStorage pointer to storage data structure + + Returns: + none + + +------------------------------------------------------------------------------*/ + +void h264bsdShutdown(storage_t *pStorage) +{ + +/* Variables */ + + u32 i; + +/* Code */ + + ASSERT(pStorage); + + for (i = 0; i < MAX_NUM_SEQ_PARAM_SETS; i++) + { + if (pStorage->sps[i]) + { + FREE(pStorage->sps[i]->offsetForRefFrame); + FREE(pStorage->sps[i]->vuiParameters); + FREE(pStorage->sps[i]); + } + } + + for (i = 0; i < MAX_NUM_PIC_PARAM_SETS; i++) + { + if (pStorage->pps[i]) + { + FREE(pStorage->pps[i]->runLength); + FREE(pStorage->pps[i]->topLeft); + FREE(pStorage->pps[i]->bottomRight); + FREE(pStorage->pps[i]->sliceGroupId); + FREE(pStorage->pps[i]); + } + } + + FREE(pStorage->mbLayer); + FREE(pStorage->mb); + FREE(pStorage->sliceGroupMap); + + h264bsdFreeDpb(pStorage->dpb); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdNextOutputPicture + + Functional description: + Get next output picture in display order. + + Inputs: + pStorage pointer to storage data structure + + Outputs: + picId identifier of the picture will be stored here + isIdrPic IDR flag of the picture will be stored here + numErrMbs number of concealed macroblocks in the picture + will be stored here + + Returns: + pointer to the picture data + NULL if no pictures available for display + +------------------------------------------------------------------------------*/ + +u8* h264bsdNextOutputPicture(storage_t *pStorage, u32 *picId, u32 *isIdrPic, + u32 *numErrMbs) +{ + +/* Variables */ + + dpbOutPicture_t *pOut; + +/* Code */ + + ASSERT(pStorage); + + pOut = h264bsdDpbOutputPicture(pStorage->dpb); + + if (pOut != NULL) + { + *picId = pOut->picId; + *isIdrPic = pOut->isIdr; + *numErrMbs = pOut->numErrMbs; + return (pOut->data); + } + else + return(NULL); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdPicWidth + + Functional description: + Get width of the picture in macroblocks + + Inputs: + pStorage pointer to storage data structure + + Outputs: + none + + Returns: + picture width + 0 if parameters sets not yet activated + +------------------------------------------------------------------------------*/ + +u32 h264bsdPicWidth(storage_t *pStorage) +{ + +/* Variables */ + +/* Code */ + + ASSERT(pStorage); + + if (pStorage->activeSps) + return(pStorage->activeSps->picWidthInMbs); + else + return(0); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdPicHeight + + Functional description: + Get height of the picture in macroblocks + + Inputs: + pStorage pointer to storage data structure + + Outputs: + none + + Returns: + picture width + 0 if parameters sets not yet activated + +------------------------------------------------------------------------------*/ + +u32 h264bsdPicHeight(storage_t *pStorage) +{ + +/* Variables */ + +/* Code */ + + ASSERT(pStorage); + + if (pStorage->activeSps) + return(pStorage->activeSps->picHeightInMbs); + else + return(0); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdFlushBuffer + + Functional description: + Flush the decoded picture buffer, see dpb.c for details + + Inputs: + pStorage pointer to storage data structure + +------------------------------------------------------------------------------*/ + +void h264bsdFlushBuffer(storage_t *pStorage) +{ + +/* Variables */ + +/* Code */ + + ASSERT(pStorage); + + h264bsdFlushDpb(pStorage->dpb); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdCheckValidParamSets + + Functional description: + Check if any valid parameter set combinations (SPS/PPS) exists. + + Inputs: + pStorage pointer to storage structure + + Returns: + 1 at least one valid SPS/PPS combination found + 0 no valid param set combinations found + + +------------------------------------------------------------------------------*/ + +u32 h264bsdCheckValidParamSets(storage_t *pStorage) +{ + +/* Variables */ + +/* Code */ + + ASSERT(pStorage); + + return(h264bsdValidParamSets(pStorage) == HANTRO_OK ? 1 : 0); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdVideoRange + + Functional description: + Get value of video_full_range_flag received in the VUI data. + + Inputs: + pStorage pointer to storage structure + + Returns: + 1 video_full_range_flag received and value is 1 + 0 otherwise + +------------------------------------------------------------------------------*/ + +u32 h264bsdVideoRange(storage_t *pStorage) +{ + +/* Variables */ + +/* Code */ + + ASSERT(pStorage); + + if (pStorage->activeSps && pStorage->activeSps->vuiParametersPresentFlag && + pStorage->activeSps->vuiParameters && + pStorage->activeSps->vuiParameters->videoSignalTypePresentFlag && + pStorage->activeSps->vuiParameters->videoFullRangeFlag) + return(1); + else /* default value of video_full_range_flag is 0 */ + return(0); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdMatrixCoefficients + + Functional description: + Get value of matrix_coefficients received in the VUI data + + Inputs: + pStorage pointer to storage structure + + Outputs: + value of matrix_coefficients if received + 2 otherwise (this is the default value) + +------------------------------------------------------------------------------*/ + +u32 h264bsdMatrixCoefficients(storage_t *pStorage) +{ + +/* Variables */ + +/* Code */ + + ASSERT(pStorage); + + if (pStorage->activeSps && pStorage->activeSps->vuiParametersPresentFlag && + pStorage->activeSps->vuiParameters && + pStorage->activeSps->vuiParameters->videoSignalTypePresentFlag && + pStorage->activeSps->vuiParameters->colourDescriptionPresentFlag) + return(pStorage->activeSps->vuiParameters->matrixCoefficients); + else /* default unspecified */ + return(2); + +} + +/*------------------------------------------------------------------------------ + + Function: hh264bsdCroppingParams + + Functional description: + Get cropping parameters of the active SPS + + Inputs: + pStorage pointer to storage structure + + Outputs: + croppingFlag flag indicating if cropping params present is + stored here + leftOffset cropping left offset in pixels is stored here + width width of the image after cropping is stored here + topOffset cropping top offset in pixels is stored here + height height of the image after cropping is stored here + + Returns: + none + +------------------------------------------------------------------------------*/ + +void h264bsdCroppingParams(storage_t *pStorage, u32 *croppingFlag, + u32 *leftOffset, u32 *width, u32 *topOffset, u32 *height) +{ + +/* Variables */ + +/* Code */ + + ASSERT(pStorage); + + if (pStorage->activeSps && pStorage->activeSps->frameCroppingFlag) + { + *croppingFlag = 1; + *leftOffset = 2 * pStorage->activeSps->frameCropLeftOffset; + *width = 16 * pStorage->activeSps->picWidthInMbs - + 2 * (pStorage->activeSps->frameCropLeftOffset + + pStorage->activeSps->frameCropRightOffset); + *topOffset = 2 * pStorage->activeSps->frameCropTopOffset; + *height = 16 * pStorage->activeSps->picHeightInMbs - + 2 * (pStorage->activeSps->frameCropTopOffset + + pStorage->activeSps->frameCropBottomOffset); + } + else + { + *croppingFlag = 0; + *leftOffset = 0; + *width = 0; + *topOffset = 0; + *height = 0; + } + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdSampleAspectRatio + + Functional description: + Get aspect ratio received in the VUI data + + Inputs: + pStorage pointer to storage structure + + Outputs: + sarWidth sample aspect ratio height + sarHeight sample aspect ratio width + +------------------------------------------------------------------------------*/ + +void h264bsdSampleAspectRatio(storage_t *pStorage, u32 *sarWidth, u32 *sarHeight) +{ + +/* Variables */ + u32 w = 1; + u32 h = 1; +/* Code */ + + ASSERT(pStorage); + + + if (pStorage->activeSps && + pStorage->activeSps->vuiParametersPresentFlag && + pStorage->activeSps->vuiParameters && + pStorage->activeSps->vuiParameters->aspectRatioPresentFlag ) + { + switch (pStorage->activeSps->vuiParameters->aspectRatioIdc) + { + case ASPECT_RATIO_UNSPECIFIED: w = 0; h = 0; break; + case ASPECT_RATIO_1_1: w = 1; h = 1; break; + case ASPECT_RATIO_12_11: w = 12; h = 11; break; + case ASPECT_RATIO_10_11: w = 10; h = 11; break; + case ASPECT_RATIO_16_11: w = 16; h = 11; break; + case ASPECT_RATIO_40_33: w = 40; h = 33; break; + case ASPECT_RATIO_24_11: w = 24; h = 11; break; + case ASPECT_RATIO_20_11: w = 20; h = 11; break; + case ASPECT_RATIO_32_11: w = 32; h = 11; break; + case ASPECT_RATIO_80_33: w = 80; h = 33; break; + case ASPECT_RATIO_18_11: w = 18; h = 11; break; + case ASPECT_RATIO_15_11: w = 15; h = 11; break; + case ASPECT_RATIO_64_33: w = 64; h = 33; break; + case ASPECT_RATIO_160_99: w = 160; h = 99; break; + case ASPECT_RATIO_EXTENDED_SAR: + w = pStorage->activeSps->vuiParameters->sarWidth; + h = pStorage->activeSps->vuiParameters->sarHeight; + if ((w == 0) || (h == 0)) + w = h = 0; + break; + default: + w = 0; + h = 0; + break; + } + } + + /* set aspect ratio*/ + *sarWidth = w; + *sarHeight = h; + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdProfile + + Functional description: + Get profile information from active SPS + + Inputs: + pStorage pointer to storage structure + + Outputs: + profile current profile + +------------------------------------------------------------------------------*/ +u32 h264bsdProfile(storage_t *pStorage) +{ + if (pStorage->activeSps) + return pStorage->activeSps->profileIdc; + else + return 0; +} + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_decoder.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_decoder.h new file mode 100644 index 0000000..8336523 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_decoder.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. Module defines + 3. Data types + 4. Function prototypes + +------------------------------------------------------------------------------*/ + +#ifndef H264SWDEC_DECODER_H +#define H264SWDEC_DECODER_H + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "basetype.h" +#include "h264bsd_storage.h" + +/*------------------------------------------------------------------------------ + 2. Module defines +------------------------------------------------------------------------------*/ + +/* enumerated return values of the functions */ +enum { + H264BSD_RDY, + H264BSD_PIC_RDY, + H264BSD_HDRS_RDY, + H264BSD_ERROR, + H264BSD_PARAM_SET_ERROR, + H264BSD_MEMALLOC_ERROR +}; + +/*------------------------------------------------------------------------------ + 3. Data types +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ + +u32 h264bsdInit(storage_t *pStorage, u32 noOutputReordering); +u32 h264bsdDecode(storage_t *pStorage, u8 *byteStrm, u32 len, u32 picId, + u32 *readBytes); +void h264bsdShutdown(storage_t *pStorage); + +u8* h264bsdNextOutputPicture(storage_t *pStorage, u32 *picId, u32 *isIdrPic, + u32 *numErrMbs); + +u32 h264bsdPicWidth(storage_t *pStorage); +u32 h264bsdPicHeight(storage_t *pStorage); +u32 h264bsdVideoRange(storage_t *pStorage); +u32 h264bsdMatrixCoefficients(storage_t *pStorage); +void h264bsdCroppingParams(storage_t *pStorage, u32 *croppingFlag, + u32 *left, u32 *width, u32 *top, u32 *height); +void h264bsdSampleAspectRatio(storage_t *pStorage, + u32 *sarWidth, u32 *sarHeight); +u32 h264bsdCheckValidParamSets(storage_t *pStorage); + +void h264bsdFlushBuffer(storage_t *pStorage); + +u32 h264bsdProfile(storage_t *pStorage); + +#endif /* #ifdef H264SWDEC_DECODER_H */ + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_dpb.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_dpb.c new file mode 100755 index 0000000..9517d0a --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_dpb.c @@ -0,0 +1,1584 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. External compiler flags + 3. Module defines + 4. Local function prototypes + 5. Functions + ComparePictures + h264bsdReorderRefPicList + Mmcop1 + Mmcop2 + Mmcop3 + Mmcop4 + Mmcop5 + Mmcop6 + h264bsdMarkDecRefPic + h264bsdGetRefPicData + h264bsdAllocateDpbImage + SlidingWindowRefPicMarking + h264bsdInitDpb + h264bsdResetDpb + h264bsdInitRefPicList + FindDpbPic + SetPicNums + h264bsdCheckGapsInFrameNum + FindSmallestPicOrderCnt + OutputPicture + h264bsdDpbOutputPicture + h264bsdFlushDpb + h264bsdFreeDpb + +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "h264bsd_cfg.h" +#include "h264bsd_dpb.h" +#include "h264bsd_slice_header.h" +#include "h264bsd_image.h" +#include "h264bsd_util.h" +#include "basetype.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +/* macros to determine picture status. Note that IS_SHORT_TERM macro returns + * true also for non-existing pictures because non-existing pictures are + * regarded short term pictures according to H.264 standard */ +#define IS_REFERENCE(a) ((a).status) +#define IS_EXISTING(a) ((a).status > NON_EXISTING) +#define IS_SHORT_TERM(a) \ + ((a).status == NON_EXISTING || (a).status == SHORT_TERM) +#define IS_LONG_TERM(a) ((a).status == LONG_TERM) + +/* macro to set a picture unused for reference */ +#define SET_UNUSED(a) (a).status = UNUSED; + +#define MAX_NUM_REF_IDX_L0_ACTIVE 16 + +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ + +static i32 ComparePictures(const void *ptr1, const void *ptr2); + +static u32 Mmcop1(dpbStorage_t *dpb, u32 currPicNum, u32 differenceOfPicNums); + +static u32 Mmcop2(dpbStorage_t *dpb, u32 longTermPicNum); + +static u32 Mmcop3(dpbStorage_t *dpb, u32 currPicNum, u32 differenceOfPicNums, + u32 longTermFrameIdx); + +static u32 Mmcop4(dpbStorage_t *dpb, u32 maxLongTermFrameIdx); + +static u32 Mmcop5(dpbStorage_t *dpb); + +static u32 Mmcop6(dpbStorage_t *dpb, u32 frameNum, i32 picOrderCnt, + u32 longTermFrameIdx); + +static u32 SlidingWindowRefPicMarking(dpbStorage_t *dpb); + +static i32 FindDpbPic(dpbStorage_t *dpb, i32 picNum, u32 isShortTerm); + +static void SetPicNums(dpbStorage_t *dpb, u32 currFrameNum); + +static dpbPicture_t* FindSmallestPicOrderCnt(dpbStorage_t *dpb); + +static u32 OutputPicture(dpbStorage_t *dpb); + +static void ShellSort(dpbPicture_t *pPic, u32 num); + +/*------------------------------------------------------------------------------ + + Function: ComparePictures + + Functional description: + Function to compare dpb pictures, used by the ShellSort() function. + Order of the pictures after sorting shall be as follows: + 1) short term reference pictures starting with the largest + picNum + 2) long term reference pictures starting with the smallest + longTermPicNum + 3) pictures unused for reference but needed for display + 4) other pictures + + Returns: + -1 pic 1 is greater than pic 2 + 0 equal from comparison point of view + 1 pic 2 is greater then pic 1 + +------------------------------------------------------------------------------*/ + +static i32 ComparePictures(const void *ptr1, const void *ptr2) +{ + +/* Variables */ + + dpbPicture_t *pic1, *pic2; + +/* Code */ + + ASSERT(ptr1); + ASSERT(ptr2); + + pic1 = (dpbPicture_t*)ptr1; + pic2 = (dpbPicture_t*)ptr2; + + /* both are non-reference pictures, check if needed for display */ + if (!IS_REFERENCE(*pic1) && !IS_REFERENCE(*pic2)) + { + if (pic1->toBeDisplayed && !pic2->toBeDisplayed) + return(-1); + else if (!pic1->toBeDisplayed && pic2->toBeDisplayed) + return(1); + else + return(0); + } + /* only pic 1 needed for reference -> greater */ + else if (!IS_REFERENCE(*pic2)) + return(-1); + /* only pic 2 needed for reference -> greater */ + else if (!IS_REFERENCE(*pic1)) + return(1); + /* both are short term reference pictures -> check picNum */ + else if (IS_SHORT_TERM(*pic1) && IS_SHORT_TERM(*pic2)) + { + if (pic1->picNum > pic2->picNum) + return(-1); + else if (pic1->picNum < pic2->picNum) + return(1); + else + return(0); + } + /* only pic 1 is short term -> greater */ + else if (IS_SHORT_TERM(*pic1)) + return(-1); + /* only pic 2 is short term -> greater */ + else if (IS_SHORT_TERM(*pic2)) + return(1); + /* both are long term reference pictures -> check picNum (contains the + * longTermPicNum */ + else + { + if (pic1->picNum > pic2->picNum) + return(1); + else if (pic1->picNum < pic2->picNum) + return(-1); + else + return(0); + } +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdReorderRefPicList + + Functional description: + Function to perform reference picture list reordering based on + reordering commands received in the slice header. See details + of the process in the H.264 standard. + + Inputs: + dpb pointer to dpb storage structure + order pointer to reordering commands + currFrameNum current frame number + numRefIdxActive number of active reference indices for current + picture + + Outputs: + dpb 'list' field of the structure reordered + + Returns: + HANTRO_OK success + HANTRO_NOK if non-existing pictures referred to in the + reordering commands + +------------------------------------------------------------------------------*/ + +u32 h264bsdReorderRefPicList( + dpbStorage_t *dpb, + refPicListReordering_t *order, + u32 currFrameNum, + u32 numRefIdxActive) +{ + +/* Variables */ + + u32 i, j, k, picNumPred, refIdx; + i32 picNum, picNumNoWrap, index; + u32 isShortTerm; + +/* Code */ + + ASSERT(order); + ASSERT(currFrameNum <= dpb->maxFrameNum); + ASSERT(numRefIdxActive <= MAX_NUM_REF_IDX_L0_ACTIVE); + + /* set dpb picture numbers for sorting */ + SetPicNums(dpb, currFrameNum); + + if (!order->refPicListReorderingFlagL0) + return(HANTRO_OK); + + refIdx = 0; + picNumPred = currFrameNum; + + i = 0; + while (order->command[i].reorderingOfPicNumsIdc < 3) + { + /* short term */ + if (order->command[i].reorderingOfPicNumsIdc < 2) + { + if (order->command[i].reorderingOfPicNumsIdc == 0) + { + picNumNoWrap = + (i32)picNumPred - (i32)order->command[i].absDiffPicNum; + if (picNumNoWrap < 0) + picNumNoWrap += (i32)dpb->maxFrameNum; + } + else + { + picNumNoWrap = + (i32)(picNumPred + order->command[i].absDiffPicNum); + if (picNumNoWrap >= (i32)dpb->maxFrameNum) + picNumNoWrap -= (i32)dpb->maxFrameNum; + } + picNumPred = (u32)picNumNoWrap; + picNum = picNumNoWrap; + if ((u32)picNumNoWrap > currFrameNum) + picNum -= (i32)dpb->maxFrameNum; + isShortTerm = HANTRO_TRUE; + } + /* long term */ + else + { + picNum = (i32)order->command[i].longTermPicNum; + isShortTerm = HANTRO_FALSE; + + } + /* find corresponding picture from dpb */ + index = FindDpbPic(dpb, picNum, isShortTerm); + if (index < 0 || !IS_EXISTING(dpb->buffer[index])) + return(HANTRO_NOK); + + /* shift pictures */ + for (j = numRefIdxActive; j > refIdx; j--) + dpb->list[j] = dpb->list[j-1]; + /* put picture into the list */ + dpb->list[refIdx++] = &dpb->buffer[index]; + /* remove later references to the same picture */ + for (j = k = refIdx; j <= numRefIdxActive; j++) + if(dpb->list[j] != &dpb->buffer[index]) + dpb->list[k++] = dpb->list[j]; + + i++; + } + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: Mmcop1 + + Functional description: + Function to mark a short-term reference picture unused for + reference, memory_management_control_operation equal to 1 + + Returns: + HANTRO_OK success + HANTRO_NOK failure, picture does not exist in the buffer + +------------------------------------------------------------------------------*/ + +static u32 Mmcop1(dpbStorage_t *dpb, u32 currPicNum, u32 differenceOfPicNums) +{ + +/* Variables */ + + i32 index, picNum; + +/* Code */ + + ASSERT(currPicNum < dpb->maxFrameNum); + + picNum = (i32)currPicNum - (i32)differenceOfPicNums; + + index = FindDpbPic(dpb, picNum, HANTRO_TRUE); + if (index < 0) + return(HANTRO_NOK); + + SET_UNUSED(dpb->buffer[index]); + dpb->numRefFrames--; + if (!dpb->buffer[index].toBeDisplayed) + dpb->fullness--; + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: Mmcop2 + + Functional description: + Function to mark a long-term reference picture unused for + reference, memory_management_control_operation equal to 2 + + Returns: + HANTRO_OK success + HANTRO_NOK failure, picture does not exist in the buffer + +------------------------------------------------------------------------------*/ + +static u32 Mmcop2(dpbStorage_t *dpb, u32 longTermPicNum) +{ + +/* Variables */ + + i32 index; + +/* Code */ + + index = FindDpbPic(dpb, (i32)longTermPicNum, HANTRO_FALSE); + if (index < 0) + return(HANTRO_NOK); + + SET_UNUSED(dpb->buffer[index]); + dpb->numRefFrames--; + if (!dpb->buffer[index].toBeDisplayed) + dpb->fullness--; + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: Mmcop3 + + Functional description: + Function to assing a longTermFrameIdx to a short-term reference + frame (i.e. to change it to a long-term reference picture), + memory_management_control_operation equal to 3 + + Returns: + HANTRO_OK success + HANTRO_NOK failure, short-term picture does not exist in the + buffer or is a non-existing picture, or invalid + longTermFrameIdx given + +------------------------------------------------------------------------------*/ + +static u32 Mmcop3(dpbStorage_t *dpb, u32 currPicNum, u32 differenceOfPicNums, + u32 longTermFrameIdx) +{ + +/* Variables */ + + i32 index, picNum; + u32 i; + +/* Code */ + + ASSERT(dpb); + ASSERT(currPicNum < dpb->maxFrameNum); + + if ( (dpb->maxLongTermFrameIdx == NO_LONG_TERM_FRAME_INDICES) || + (longTermFrameIdx > dpb->maxLongTermFrameIdx) ) + return(HANTRO_NOK); + + /* check if a long term picture with the same longTermFrameIdx already + * exist and remove it if necessary */ + for (i = 0; i < dpb->maxRefFrames; i++) + if (IS_LONG_TERM(dpb->buffer[i]) && + (u32)dpb->buffer[i].picNum == longTermFrameIdx) + { + SET_UNUSED(dpb->buffer[i]); + dpb->numRefFrames--; + if (!dpb->buffer[i].toBeDisplayed) + dpb->fullness--; + break; + } + + picNum = (i32)currPicNum - (i32)differenceOfPicNums; + + index = FindDpbPic(dpb, picNum, HANTRO_TRUE); + if (index < 0) + return(HANTRO_NOK); + if (!IS_EXISTING(dpb->buffer[index])) + return(HANTRO_NOK); + + dpb->buffer[index].status = LONG_TERM; + dpb->buffer[index].picNum = (i32)longTermFrameIdx; + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: Mmcop4 + + Functional description: + Function to set maxLongTermFrameIdx, + memory_management_control_operation equal to 4 + + Returns: + HANTRO_OK success + +------------------------------------------------------------------------------*/ + +static u32 Mmcop4(dpbStorage_t *dpb, u32 maxLongTermFrameIdx) +{ + +/* Variables */ + + u32 i; + +/* Code */ + + dpb->maxLongTermFrameIdx = maxLongTermFrameIdx; + + for (i = 0; i < dpb->maxRefFrames; i++) + if (IS_LONG_TERM(dpb->buffer[i]) && + ( ((u32)dpb->buffer[i].picNum > maxLongTermFrameIdx) || + (dpb->maxLongTermFrameIdx == NO_LONG_TERM_FRAME_INDICES) ) ) + { + SET_UNUSED(dpb->buffer[i]); + dpb->numRefFrames--; + if (!dpb->buffer[i].toBeDisplayed) + dpb->fullness--; + } + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: Mmcop5 + + Functional description: + Function to mark all reference pictures unused for reference and + set maxLongTermFrameIdx to NO_LONG_TERM_FRAME_INDICES, + memory_management_control_operation equal to 5. Function flushes + the buffer and places all pictures that are needed for display into + the output buffer. + + Returns: + HANTRO_OK success + +------------------------------------------------------------------------------*/ + +static u32 Mmcop5(dpbStorage_t *dpb) +{ + +/* Variables */ + + u32 i; + +/* Code */ + + for (i = 0; i < 16; i++) + { + if (IS_REFERENCE(dpb->buffer[i])) + { + SET_UNUSED(dpb->buffer[i]); + if (!dpb->buffer[i].toBeDisplayed) + dpb->fullness--; + } + } + + /* output all pictures */ + while (OutputPicture(dpb) == HANTRO_OK) + ; + dpb->numRefFrames = 0; + dpb->maxLongTermFrameIdx = NO_LONG_TERM_FRAME_INDICES; + dpb->prevRefFrameNum = 0; + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: Mmcop6 + + Functional description: + Function to assign longTermFrameIdx to the current picture, + memory_management_control_operation equal to 6 + + Returns: + HANTRO_OK success + HANTRO_NOK invalid longTermFrameIdx or no room for current + picture in the buffer + +------------------------------------------------------------------------------*/ + +static u32 Mmcop6(dpbStorage_t *dpb, u32 frameNum, i32 picOrderCnt, + u32 longTermFrameIdx) +{ + +/* Variables */ + + u32 i; + +/* Code */ + + ASSERT(frameNum < dpb->maxFrameNum); + + if ( (dpb->maxLongTermFrameIdx == NO_LONG_TERM_FRAME_INDICES) || + (longTermFrameIdx > dpb->maxLongTermFrameIdx) ) + return(HANTRO_NOK); + + /* check if a long term picture with the same longTermFrameIdx already + * exist and remove it if necessary */ + for (i = 0; i < dpb->maxRefFrames; i++) + if (IS_LONG_TERM(dpb->buffer[i]) && + (u32)dpb->buffer[i].picNum == longTermFrameIdx) + { + SET_UNUSED(dpb->buffer[i]); + dpb->numRefFrames--; + if (!dpb->buffer[i].toBeDisplayed) + dpb->fullness--; + break; + } + + if (dpb->numRefFrames < dpb->maxRefFrames) + { + dpb->currentOut->frameNum = frameNum; + dpb->currentOut->picNum = (i32)longTermFrameIdx; + dpb->currentOut->picOrderCnt = picOrderCnt; + dpb->currentOut->status = LONG_TERM; + if (dpb->noReordering) + dpb->currentOut->toBeDisplayed = HANTRO_FALSE; + else + dpb->currentOut->toBeDisplayed = HANTRO_TRUE; + dpb->numRefFrames++; + dpb->fullness++; + return(HANTRO_OK); + } + /* if there is no room, return an error */ + else + return(HANTRO_NOK); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdMarkDecRefPic + + Functional description: + Function to perform reference picture marking process. This + function should be called both for reference and non-reference + pictures. Non-reference pictures shall have mark pointer set to + NULL. + + Inputs: + dpb pointer to the DPB data structure + mark pointer to reference picture marking commands + image pointer to current picture to be placed in the buffer + frameNum frame number of the current picture + picOrderCnt picture order count for the current picture + isIdr flag to indicate if the current picture is an + IDR picture + currentPicId identifier for the current picture, from the + application, stored along with the picture + numErrMbs number of concealed macroblocks in the current + picture, stored along with the picture + + Outputs: + dpb 'buffer' modified, possible output frames placed into + 'outBuf' + + Returns: + HANTRO_OK success + HANTRO_NOK failure + +------------------------------------------------------------------------------*/ + +u32 h264bsdMarkDecRefPic( + dpbStorage_t *dpb, + decRefPicMarking_t *mark, + image_t *image, + u32 frameNum, + i32 picOrderCnt, + u32 isIdr, + u32 currentPicId, + u32 numErrMbs) +{ + +/* Variables */ + + u32 i, status; + u32 markedAsLongTerm; + u32 toBeDisplayed; + +/* Code */ + + ASSERT(dpb); + ASSERT(mark || !isIdr); + ASSERT(!isIdr || (frameNum == 0 && picOrderCnt == 0)); + ASSERT(frameNum < dpb->maxFrameNum); + + if (image->data != dpb->currentOut->data) + { + EPRINT("TRYING TO MARK NON-ALLOCATED IMAGE"); + return(HANTRO_NOK); + } + + dpb->lastContainsMmco5 = HANTRO_FALSE; + status = HANTRO_OK; + + toBeDisplayed = dpb->noReordering ? HANTRO_FALSE : HANTRO_TRUE; + + /* non-reference picture, stored for display reordering purposes */ + if (mark == NULL) + { + dpb->currentOut->status = UNUSED; + dpb->currentOut->frameNum = frameNum; + dpb->currentOut->picNum = (i32)frameNum; + dpb->currentOut->picOrderCnt = picOrderCnt; + dpb->currentOut->toBeDisplayed = toBeDisplayed; + if (!dpb->noReordering) + dpb->fullness++; + } + /* IDR picture */ + else if (isIdr) + { + + /* h264bsdCheckGapsInFrameNum not called for IDR pictures -> have to + * reset numOut and outIndex here */ + dpb->numOut = dpb->outIndex = 0; + + /* flush the buffer */ + Mmcop5(dpb); + /* if noOutputOfPriorPicsFlag was set -> the pictures preceding the + * IDR picture shall not be output -> set output buffer empty */ + if (mark->noOutputOfPriorPicsFlag || dpb->noReordering) + { + dpb->numOut = 0; + dpb->outIndex = 0; + } + + if (mark->longTermReferenceFlag) + { + dpb->currentOut->status = LONG_TERM; + dpb->maxLongTermFrameIdx = 0; + } + else + { + dpb->currentOut->status = SHORT_TERM; + dpb->maxLongTermFrameIdx = NO_LONG_TERM_FRAME_INDICES; + } + dpb->currentOut->frameNum = 0; + dpb->currentOut->picNum = 0; + dpb->currentOut->picOrderCnt = 0; + dpb->currentOut->toBeDisplayed = toBeDisplayed; + dpb->fullness = 1; + dpb->numRefFrames = 1; + } + /* reference picture */ + else + { + markedAsLongTerm = HANTRO_FALSE; + if (mark->adaptiveRefPicMarkingModeFlag) + { + i = 0; + while (mark->operation[i].memoryManagementControlOperation) + { + switch (mark->operation[i].memoryManagementControlOperation) + { + case 1: + status = Mmcop1( + dpb, + frameNum, + mark->operation[i].differenceOfPicNums); + break; + + case 2: + status = Mmcop2(dpb, mark->operation[i].longTermPicNum); + break; + + case 3: + status = Mmcop3( + dpb, + frameNum, + mark->operation[i].differenceOfPicNums, + mark->operation[i].longTermFrameIdx); + break; + + case 4: + status = Mmcop4( + dpb, + mark->operation[i].maxLongTermFrameIdx); + break; + + case 5: + status = Mmcop5(dpb); + dpb->lastContainsMmco5 = HANTRO_TRUE; + frameNum = 0; + break; + + case 6: + status = Mmcop6( + dpb, + frameNum, + picOrderCnt, + mark->operation[i].longTermFrameIdx); + if (status == HANTRO_OK) + markedAsLongTerm = HANTRO_TRUE; + break; + + default: /* invalid memory management control operation */ + status = HANTRO_NOK; + break; + } + if (status != HANTRO_OK) + { + break; + } + i++; + } + } + else + { + status = SlidingWindowRefPicMarking(dpb); + } + /* if current picture was not marked as long-term reference by + * memory management control operation 6 -> mark current as short + * term and insert it into dpb (if there is room) */ + if (!markedAsLongTerm) + { + if (dpb->numRefFrames < dpb->maxRefFrames) + { + dpb->currentOut->frameNum = frameNum; + dpb->currentOut->picNum = (i32)frameNum; + dpb->currentOut->picOrderCnt = picOrderCnt; + dpb->currentOut->status = SHORT_TERM; + dpb->currentOut->toBeDisplayed = toBeDisplayed; + dpb->fullness++; + dpb->numRefFrames++; + } + /* no room */ + else + { + status = HANTRO_NOK; + } + } + } + + dpb->currentOut->isIdr = isIdr; + dpb->currentOut->picId = currentPicId; + dpb->currentOut->numErrMbs = numErrMbs; + + /* dpb was initialized to not to reorder the pictures -> output current + * picture immediately */ + if (dpb->noReordering) + { + ASSERT(dpb->numOut == 0); + ASSERT(dpb->outIndex == 0); + dpb->outBuf[dpb->numOut].data = dpb->currentOut->data; + dpb->outBuf[dpb->numOut].isIdr = dpb->currentOut->isIdr; + dpb->outBuf[dpb->numOut].picId = dpb->currentOut->picId; + dpb->outBuf[dpb->numOut].numErrMbs = dpb->currentOut->numErrMbs; + dpb->numOut++; + } + else + { + /* output pictures if buffer full */ + while (dpb->fullness > dpb->dpbSize) + { + i = OutputPicture(dpb); + ASSERT(i == HANTRO_OK); + } + } + + /* sort dpb */ + ShellSort(dpb->buffer, dpb->dpbSize+1); + + return(status); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdGetRefPicData + + Functional description: + Function to get reference picture data from the reference picture + list + + Returns: + pointer to desired reference picture data + NULL if invalid index or non-existing picture referred + +------------------------------------------------------------------------------*/ + +u8* h264bsdGetRefPicData(dpbStorage_t *dpb, u32 index) +{ + +/* Variables */ + +/* Code */ + + if(index > 16 || dpb->list[index] == NULL) + return(NULL); + else if(!IS_EXISTING(*dpb->list[index])) + return(NULL); + else + return(dpb->list[index]->data); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdAllocateDpbImage + + Functional description: + function to allocate memory for a image. This function does not + really allocate any memory but reserves one of the buffer + positions for decoding of current picture + + Returns: + pointer to memory area for the image + + +------------------------------------------------------------------------------*/ + +u8* h264bsdAllocateDpbImage(dpbStorage_t *dpb) +{ + +/* Variables */ + +/* Code */ + + ASSERT( !dpb->buffer[dpb->dpbSize].toBeDisplayed && + !IS_REFERENCE(dpb->buffer[dpb->dpbSize]) ); + ASSERT(dpb->fullness <= dpb->dpbSize); + + dpb->currentOut = dpb->buffer + dpb->dpbSize; + + return(dpb->currentOut->data); + +} + +/*------------------------------------------------------------------------------ + + Function: SlidingWindowRefPicMarking + + Functional description: + Function to perform sliding window refence picture marking process. + + Outputs: + HANTRO_OK success + HANTRO_NOK failure, no short-term reference frame found that + could be marked unused + + +------------------------------------------------------------------------------*/ + +static u32 SlidingWindowRefPicMarking(dpbStorage_t *dpb) +{ + +/* Variables */ + + i32 index, picNum; + u32 i; + +/* Code */ + + if (dpb->numRefFrames < dpb->maxRefFrames) + { + return(HANTRO_OK); + } + else + { + index = -1; + picNum = 0; + /* find the oldest short term picture */ + for (i = 0; i < dpb->numRefFrames; i++) + if (IS_SHORT_TERM(dpb->buffer[i])) + if (dpb->buffer[i].picNum < picNum || index == -1) + { + index = (i32)i; + picNum = dpb->buffer[i].picNum; + } + if (index >= 0) + { + SET_UNUSED(dpb->buffer[index]); + dpb->numRefFrames--; + if (!dpb->buffer[index].toBeDisplayed) + dpb->fullness--; + + return(HANTRO_OK); + } + } + + return(HANTRO_NOK); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdInitDpb + + Functional description: + Function to initialize DPB. Reserves memories for the buffer, + reference picture list and output buffer. dpbSize indicates + the maximum DPB size indicated by the levelIdc in the stream. + If noReordering flag is FALSE the DPB stores dpbSize pictures + for display reordering purposes. On the other hand, if the + flag is TRUE the DPB only stores maxRefFrames reference pictures + and outputs all the pictures immediately. + + Inputs: + picSizeInMbs picture size in macroblocks + dpbSize size of the DPB (number of pictures) + maxRefFrames max number of reference frames + maxFrameNum max frame number + noReordering flag to indicate that DPB does not have to + prepare to reorder frames for display + + Outputs: + dpb pointer to dpb data storage + + Returns: + HANTRO_OK success + MEMORY_ALLOCATION_ERROR if memory allocation failed + +------------------------------------------------------------------------------*/ + +u32 h264bsdInitDpb( + dpbStorage_t *dpb, + u32 picSizeInMbs, + u32 dpbSize, + u32 maxRefFrames, + u32 maxFrameNum, + u32 noReordering) +{ + +/* Variables */ + + u32 i; + +/* Code */ + + ASSERT(picSizeInMbs); + ASSERT(maxRefFrames <= MAX_NUM_REF_PICS); + ASSERT(maxRefFrames <= dpbSize); + ASSERT(maxFrameNum); + ASSERT(dpbSize); + + dpb->maxLongTermFrameIdx = NO_LONG_TERM_FRAME_INDICES; + dpb->maxRefFrames = MAX(maxRefFrames, 1); + if (noReordering) + dpb->dpbSize = dpb->maxRefFrames; + else + dpb->dpbSize = dpbSize; + dpb->maxFrameNum = maxFrameNum; + dpb->noReordering = noReordering; + dpb->fullness = 0; + dpb->numRefFrames = 0; + dpb->prevRefFrameNum = 0; + + ALLOCATE(dpb->buffer, MAX_NUM_REF_IDX_L0_ACTIVE + 1, dpbPicture_t); + if (dpb->buffer == NULL) + return(MEMORY_ALLOCATION_ERROR); + H264SwDecMemset(dpb->buffer, 0, + (MAX_NUM_REF_IDX_L0_ACTIVE + 1)*sizeof(dpbPicture_t)); + for (i = 0; i < dpb->dpbSize + 1; i++) + { + /* Allocate needed amount of memory, which is: + * image size + 32 + 15, where 32 cames from the fact that in ARM OpenMax + * DL implementation Functions may read beyond the end of an array, + * by a maximum of 32 bytes. And +15 cames for the need to align memory + * to 16-byte boundary */ + ALLOCATE(dpb->buffer[i].pAllocatedData, (picSizeInMbs*384 + 32+15), u8); + if (dpb->buffer[i].pAllocatedData == NULL) + return(MEMORY_ALLOCATION_ERROR); + + dpb->buffer[i].data = ALIGN(dpb->buffer[i].pAllocatedData, 16); + } + + ALLOCATE(dpb->list, MAX_NUM_REF_IDX_L0_ACTIVE + 1, dpbPicture_t*); + ALLOCATE(dpb->outBuf, dpb->dpbSize+1, dpbOutPicture_t); + + if (dpb->list == NULL || dpb->outBuf == NULL) + return(MEMORY_ALLOCATION_ERROR); + + H264SwDecMemset(dpb->list, 0, + ((MAX_NUM_REF_IDX_L0_ACTIVE + 1) * sizeof(dpbPicture_t*)) ); + + dpb->numOut = dpb->outIndex = 0; + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdResetDpb + + Functional description: + Function to reset DPB. This function should be called when an IDR + slice (other than the first) activates new sequence parameter set. + Function calls h264bsdFreeDpb to free old allocated memories and + h264bsdInitDpb to re-initialize the DPB. Same inputs, outputs and + returns as for h264bsdInitDpb. + +------------------------------------------------------------------------------*/ + +u32 h264bsdResetDpb( + dpbStorage_t *dpb, + u32 picSizeInMbs, + u32 dpbSize, + u32 maxRefFrames, + u32 maxFrameNum, + u32 noReordering) +{ + +/* Code */ + + ASSERT(picSizeInMbs); + ASSERT(maxRefFrames <= MAX_NUM_REF_PICS); + ASSERT(maxRefFrames <= dpbSize); + ASSERT(maxFrameNum); + ASSERT(dpbSize); + + h264bsdFreeDpb(dpb); + + return h264bsdInitDpb(dpb, picSizeInMbs, dpbSize, maxRefFrames, + maxFrameNum, noReordering); +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdInitRefPicList + + Functional description: + Function to initialize reference picture list. Function just + sets pointers in the list according to pictures in the buffer. + The buffer is assumed to contain pictures sorted according to + what the H.264 standard says about initial reference picture list. + + Inputs: + dpb pointer to dpb data structure + + Outputs: + dpb 'list' field initialized + + Returns: + none + +------------------------------------------------------------------------------*/ + +void h264bsdInitRefPicList(dpbStorage_t *dpb) +{ + +/* Variables */ + + u32 i; + +/* Code */ + + for (i = 0; i < dpb->numRefFrames; i++) + dpb->list[i] = &dpb->buffer[i]; + +} + +/*------------------------------------------------------------------------------ + + Function: FindDpbPic + + Functional description: + Function to find a reference picture from the buffer. The picture + to be found is identified by picNum and isShortTerm flag. + + Returns: + index of the picture in the buffer + -1 if the specified picture was not found in the buffer + +------------------------------------------------------------------------------*/ + +static i32 FindDpbPic(dpbStorage_t *dpb, i32 picNum, u32 isShortTerm) +{ + +/* Variables */ + + u32 i = 0; + u32 found = HANTRO_FALSE; + +/* Code */ + + if (isShortTerm) + { + while (i < dpb->maxRefFrames && !found) + { + if (IS_SHORT_TERM(dpb->buffer[i]) && + dpb->buffer[i].picNum == picNum) + found = HANTRO_TRUE; + else + i++; + } + } + else + { + ASSERT(picNum >= 0); + while (i < dpb->maxRefFrames && !found) + { + if (IS_LONG_TERM(dpb->buffer[i]) && + dpb->buffer[i].picNum == picNum) + found = HANTRO_TRUE; + else + i++; + } + } + + if (found) + return((i32)i); + else + return(-1); + +} + +/*------------------------------------------------------------------------------ + + Function: SetPicNums + + Functional description: + Function to set picNum values for short-term pictures in the + buffer. Numbering of pictures is based on frame numbers and as + frame numbers are modulo maxFrameNum -> frame numbers of older + pictures in the buffer may be bigger than the currFrameNum. + picNums will be set so that current frame has the largest picNum + and all the short-term frames in the buffer will get smaller picNum + representing their "distance" from the current frame. This + function kind of maps the modulo arithmetic back to normal. + +------------------------------------------------------------------------------*/ + +static void SetPicNums(dpbStorage_t *dpb, u32 currFrameNum) +{ + +/* Variables */ + + u32 i; + i32 frameNumWrap; + +/* Code */ + + ASSERT(dpb); + ASSERT(currFrameNum < dpb->maxFrameNum); + + for (i = 0; i < dpb->numRefFrames; i++) + if (IS_SHORT_TERM(dpb->buffer[i])) + { + if (dpb->buffer[i].frameNum > currFrameNum) + frameNumWrap = + (i32)dpb->buffer[i].frameNum - (i32)dpb->maxFrameNum; + else + frameNumWrap = (i32)dpb->buffer[i].frameNum; + dpb->buffer[i].picNum = frameNumWrap; + } + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdCheckGapsInFrameNum + + Functional description: + Function to check gaps in frame_num and generate non-existing + (short term) reference pictures if necessary. This function should + be called only for non-IDR pictures. + + Inputs: + dpb pointer to dpb data structure + frameNum frame number of the current picture + isRefPic flag to indicate if current picture is a reference or + non-reference picture + gapsAllowed Flag which indicates active SPS stance on whether + to allow gaps + + Outputs: + dpb 'buffer' possibly modified by inserting non-existing + pictures with sliding window marking process + + Returns: + HANTRO_OK success + HANTRO_NOK error in sliding window reference picture marking or + frameNum equal to previous reference frame used for + a reference picture + +------------------------------------------------------------------------------*/ + +u32 h264bsdCheckGapsInFrameNum(dpbStorage_t *dpb, u32 frameNum, u32 isRefPic, + u32 gapsAllowed) +{ + +/* Variables */ + + u32 unUsedShortTermFrameNum; + u8 *tmp; + +/* Code */ + + ASSERT(dpb); + ASSERT(dpb->fullness <= dpb->dpbSize); + ASSERT(frameNum < dpb->maxFrameNum); + + dpb->numOut = 0; + dpb->outIndex = 0; + + if(!gapsAllowed) + return(HANTRO_OK); + + if ( (frameNum != dpb->prevRefFrameNum) && + (frameNum != ((dpb->prevRefFrameNum + 1) % dpb->maxFrameNum))) + { + + unUsedShortTermFrameNum = (dpb->prevRefFrameNum + 1) % dpb->maxFrameNum; + + /* store data pointer of last buffer position to be used as next + * "allocated" data pointer if last buffer position after this process + * contains data pointer located in outBuf (buffer placed in the output + * shall not be overwritten by the current picture) */ + tmp = dpb->buffer[dpb->dpbSize].data; + do + { + SetPicNums(dpb, unUsedShortTermFrameNum); + + if (SlidingWindowRefPicMarking(dpb) != HANTRO_OK) + { + return(HANTRO_NOK); + } + + /* output pictures if buffer full */ + while (dpb->fullness >= dpb->dpbSize) + { +#ifdef _ASSERT_USED + ASSERT(!dpb->noReordering); + ASSERT(OutputPicture(dpb) == HANTRO_OK); +#else + OutputPicture(dpb); +#endif + } + + /* add to end of list */ + ASSERT( !dpb->buffer[dpb->dpbSize].toBeDisplayed && + !IS_REFERENCE(dpb->buffer[dpb->dpbSize]) ); + dpb->buffer[dpb->dpbSize].status = NON_EXISTING; + dpb->buffer[dpb->dpbSize].frameNum = unUsedShortTermFrameNum; + dpb->buffer[dpb->dpbSize].picNum = (i32)unUsedShortTermFrameNum; + dpb->buffer[dpb->dpbSize].picOrderCnt = 0; + dpb->buffer[dpb->dpbSize].toBeDisplayed = HANTRO_FALSE; + dpb->fullness++; + dpb->numRefFrames++; + + /* sort the buffer */ + ShellSort(dpb->buffer, dpb->dpbSize+1); + + unUsedShortTermFrameNum = (unUsedShortTermFrameNum + 1) % + dpb->maxFrameNum; + + } while (unUsedShortTermFrameNum != frameNum); + + /* pictures placed in output buffer -> check that 'data' in + * buffer position dpbSize is not in the output buffer (this will be + * "allocated" by h264bsdAllocateDpbImage). If it is -> exchange data + * pointer with the one stored in the beginning */ + if (dpb->numOut) + { + u32 i; + + for (i = 0; i < dpb->numOut; i++) + { + if (dpb->outBuf[i].data == dpb->buffer[dpb->dpbSize].data) + { + /* find buffer position containing data pointer stored in + * tmp */ + for (i = 0; i < dpb->dpbSize; i++) + { + if (dpb->buffer[i].data == tmp) + { + dpb->buffer[i].data = + dpb->buffer[dpb->dpbSize].data; + dpb->buffer[dpb->dpbSize].data = tmp; + break; + } + } + ASSERT(i < dpb->dpbSize); + break; + } + } + } + } + /* frameNum for reference pictures shall not be the same as for previous + * reference picture, otherwise accesses to pictures in the buffer cannot + * be solved unambiguously */ + else if (isRefPic && frameNum == dpb->prevRefFrameNum) + { + return(HANTRO_NOK); + } + + /* save current frame_num in prevRefFrameNum. For non-reference frame + * prevFrameNum is set to frame number of last non-existing frame above */ + if (isRefPic) + dpb->prevRefFrameNum = frameNum; + else if (frameNum != dpb->prevRefFrameNum) + { + dpb->prevRefFrameNum = + (frameNum + dpb->maxFrameNum - 1) % dpb->maxFrameNum; + } + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: FindSmallestPicOrderCnt + + Functional description: + Function to find picture with smallest picture order count. This + will be the next picture in display order. + + Returns: + pointer to the picture, NULL if no pictures to be displayed + +------------------------------------------------------------------------------*/ + +dpbPicture_t* FindSmallestPicOrderCnt(dpbStorage_t *dpb) +{ + +/* Variables */ + + u32 i; + i32 picOrderCnt; + dpbPicture_t *tmp; + +/* Code */ + + ASSERT(dpb); + + picOrderCnt = 0x7FFFFFFF; + tmp = NULL; + + for (i = 0; i <= dpb->dpbSize; i++) + { + if (dpb->buffer[i].toBeDisplayed && + (dpb->buffer[i].picOrderCnt < picOrderCnt)) + { + tmp = dpb->buffer + i; + picOrderCnt = dpb->buffer[i].picOrderCnt; + } + } + + return(tmp); + +} + +/*------------------------------------------------------------------------------ + + Function: OutputPicture + + Functional description: + Function to put next display order picture into the output buffer. + + Returns: + HANTRO_OK success + HANTRO_NOK no pictures to display + +------------------------------------------------------------------------------*/ + +u32 OutputPicture(dpbStorage_t *dpb) +{ + +/* Variables */ + + dpbPicture_t *tmp; + +/* Code */ + + ASSERT(dpb); + + if (dpb->noReordering) + return(HANTRO_NOK); + + tmp = FindSmallestPicOrderCnt(dpb); + + /* no pictures to be displayed */ + if (tmp == NULL) + return(HANTRO_NOK); + + dpb->outBuf[dpb->numOut].data = tmp->data; + dpb->outBuf[dpb->numOut].isIdr = tmp->isIdr; + dpb->outBuf[dpb->numOut].picId = tmp->picId; + dpb->outBuf[dpb->numOut].numErrMbs = tmp->numErrMbs; + dpb->numOut++; + + tmp->toBeDisplayed = HANTRO_FALSE; + if (!IS_REFERENCE(*tmp)) + { + dpb->fullness--; + } + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdDpbOutputPicture + + Functional description: + Function to get next display order picture from the output buffer. + + Return: + pointer to output picture structure, NULL if no pictures to + display + +------------------------------------------------------------------------------*/ + +dpbOutPicture_t* h264bsdDpbOutputPicture(dpbStorage_t *dpb) +{ + +/* Variables */ + +/* Code */ + + ASSERT(dpb); + + if (dpb->outIndex < dpb->numOut) + return(dpb->outBuf + dpb->outIndex++); + else + return(NULL); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdFlushDpb + + Functional description: + Function to flush the DPB. Function puts all pictures needed for + display into the output buffer. This function shall be called in + the end of the stream to obtain pictures buffered for display + re-ordering purposes. + +------------------------------------------------------------------------------*/ + +void h264bsdFlushDpb(dpbStorage_t *dpb) +{ + + /* don't do anything if buffer not reserved */ + if (dpb->buffer) + { + dpb->flushed = 1; + /* output all pictures */ + while (OutputPicture(dpb) == HANTRO_OK) + ; + } + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdFreeDpb + + Functional description: + Function to free memories reserved for the DPB. + +------------------------------------------------------------------------------*/ + +void h264bsdFreeDpb(dpbStorage_t *dpb) +{ + +/* Variables */ + + u32 i; + +/* Code */ + + ASSERT(dpb); + + if (dpb->buffer) + { + for (i = 0; i < dpb->dpbSize+1; i++) + { + FREE(dpb->buffer[i].pAllocatedData); + } + } + FREE(dpb->buffer); + FREE(dpb->list); + FREE(dpb->outBuf); + +} + +/*------------------------------------------------------------------------------ + + Function: ShellSort + + Functional description: + Sort pictures in the buffer. Function implements Shell's method, + i.e. diminishing increment sort. See e.g. "Numerical Recipes in C" + for more information. + +------------------------------------------------------------------------------*/ + +static void ShellSort(dpbPicture_t *pPic, u32 num) +{ + + u32 i, j; + u32 step; + dpbPicture_t tmpPic; + + step = 7; + + while (step) + { + for (i = step; i < num; i++) + { + tmpPic = pPic[i]; + j = i; + while (j >= step && ComparePictures(pPic + j - step, &tmpPic) > 0) + { + pPic[j] = pPic[j-step]; + j -= step; + } + pPic[j] = tmpPic; + } + step >>= 1; + } + +} + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_dpb.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_dpb.h new file mode 100755 index 0000000..0e25084 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_dpb.h @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. Module defines + 3. Data types + 4. Function prototypes + +------------------------------------------------------------------------------*/ + +#ifndef H264SWDEC_DPB_H +#define H264SWDEC_DPB_H + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "basetype.h" +#include "h264bsd_slice_header.h" +#include "h264bsd_image.h" + +/*------------------------------------------------------------------------------ + 2. Module defines +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 3. Data types +------------------------------------------------------------------------------*/ + +/* enumeration to represent status of buffered image */ +typedef enum { + UNUSED = 0, + NON_EXISTING, + SHORT_TERM, + LONG_TERM +} dpbPictureStatus_e; + +/* structure to represent a buffered picture */ +typedef struct { + u8 *data; /* 16-byte aligned pointer of pAllocatedData */ + u8 *pAllocatedData; /* allocated picture pointer; (size + 15) bytes */ + i32 picNum; + u32 frameNum; + i32 picOrderCnt; + dpbPictureStatus_e status; + u32 toBeDisplayed; + u32 picId; + u32 numErrMbs; + u32 isIdr; +} dpbPicture_t; + +/* structure to represent display image output from the buffer */ +typedef struct { + u8 *data; + u32 picId; + u32 numErrMbs; + u32 isIdr; +} dpbOutPicture_t; + +/* structure to represent DPB */ +typedef struct { + dpbPicture_t *buffer; + dpbPicture_t **list; + dpbPicture_t *currentOut; + dpbOutPicture_t *outBuf; + u32 numOut; + u32 outIndex; + u32 maxRefFrames; + u32 dpbSize; + u32 maxFrameNum; + u32 maxLongTermFrameIdx; + u32 numRefFrames; + u32 fullness; + u32 prevRefFrameNum; + u32 lastContainsMmco5; + u32 noReordering; + u32 flushed; +} dpbStorage_t; + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ + +u32 h264bsdInitDpb( + dpbStorage_t *dpb, + u32 picSizeInMbs, + u32 dpbSize, + u32 numRefFrames, + u32 maxFrameNum, + u32 noReordering); + +u32 h264bsdResetDpb( + dpbStorage_t *dpb, + u32 picSizeInMbs, + u32 dpbSize, + u32 numRefFrames, + u32 maxFrameNum, + u32 noReordering); + +void h264bsdInitRefPicList(dpbStorage_t *dpb); + +u8* h264bsdAllocateDpbImage(dpbStorage_t *dpb); + +u8* h264bsdGetRefPicData(dpbStorage_t *dpb, u32 index); + +u32 h264bsdReorderRefPicList( + dpbStorage_t *dpb, + refPicListReordering_t *order, + u32 currFrameNum, + u32 numRefIdxActive); + +u32 h264bsdMarkDecRefPic( + dpbStorage_t *dpb, + decRefPicMarking_t *mark, + image_t *image, + u32 frameNum, + i32 picOrderCnt, + u32 isIdr, + u32 picId, + u32 numErrMbs); + +u32 h264bsdCheckGapsInFrameNum(dpbStorage_t *dpb, u32 frameNum, u32 isRefPic, + u32 gapsAllowed); + +dpbOutPicture_t* h264bsdDpbOutputPicture(dpbStorage_t *dpb); + +void h264bsdFlushDpb(dpbStorage_t *dpb); + +void h264bsdFreeDpb(dpbStorage_t *dpb); + +#endif /* #ifdef H264SWDEC_DPB_H */ + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_image.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_image.c new file mode 100755 index 0000000..7b92870 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_image.c @@ -0,0 +1,345 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. External compiler flags + 3. Module defines + 4. Local function prototypes + 5. Functions + h264bsdWriteMacroblock + h264bsdWriteOutputBlocks + +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "h264bsd_image.h" +#include "h264bsd_util.h" +#include "h264bsd_neighbour.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +/* x- and y-coordinates for each block, defined in h264bsd_intra_prediction.c */ +extern const u32 h264bsdBlockX[]; +extern const u32 h264bsdBlockY[]; + +/* clipping table, defined in h264bsd_intra_prediction.c */ +extern const u8 h264bsdClip[]; + +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ + + + +/*------------------------------------------------------------------------------ + + Function: h264bsdWriteMacroblock + + Functional description: + Write one macroblock into the image. Both luma and chroma + components will be written at the same time. + + Inputs: + data pointer to macroblock data to be written, 256 values for + luma followed by 64 values for both chroma components + + Outputs: + image pointer to the image where the macroblock will be written + + Returns: + none + +------------------------------------------------------------------------------*/ +#ifndef H264DEC_NEON +void h264bsdWriteMacroblock(image_t *image, u8 *data) +{ + +/* Variables */ + + u32 i; + u32 width; + u32 *lum, *cb, *cr; + u32 *ptr; + u32 tmp1, tmp2; + +/* Code */ + + ASSERT(image); + ASSERT(data); + ASSERT(!((u32)data&0x3)); + + width = image->width; + + /*lint -save -e826 lum, cb and cr used to copy 4 bytes at the time, disable + * "area too small" info message */ + lum = (u32*)image->luma; + cb = (u32*)image->cb; + cr = (u32*)image->cr; + ASSERT(!((u32)lum&0x3)); + ASSERT(!((u32)cb&0x3)); + ASSERT(!((u32)cr&0x3)); + + ptr = (u32*)data; + + width *= 4; + for (i = 16; i ; i--) + { + tmp1 = *ptr++; + tmp2 = *ptr++; + *lum++ = tmp1; + *lum++ = tmp2; + tmp1 = *ptr++; + tmp2 = *ptr++; + *lum++ = tmp1; + *lum++ = tmp2; + lum += width-4; + } + + width >>= 1; + for (i = 8; i ; i--) + { + tmp1 = *ptr++; + tmp2 = *ptr++; + *cb++ = tmp1; + *cb++ = tmp2; + cb += width-2; + } + + for (i = 8; i ; i--) + { + tmp1 = *ptr++; + tmp2 = *ptr++; + *cr++ = tmp1; + *cr++ = tmp2; + cr += width-2; + } + +} +#endif +#ifndef H264DEC_OMXDL +/*------------------------------------------------------------------------------ + + Function: h264bsdWriteOutputBlocks + + Functional description: + Write one macroblock into the image. Prediction for the macroblock + and the residual are given separately and will be combined while + writing the data to the image + + Inputs: + data pointer to macroblock prediction data, 256 values for + luma followed by 64 values for both chroma components + mbNum number of the macroblock + residual pointer to residual data, 16 16-element arrays for luma + followed by 4 16-element arrays for both chroma + components + + Outputs: + image pointer to the image where the data will be written + + Returns: + none + +------------------------------------------------------------------------------*/ + +void h264bsdWriteOutputBlocks(image_t *image, u32 mbNum, u8 *data, + i32 residual[][16]) +{ + +/* Variables */ + + u32 i; + u32 picWidth, picSize; + u8 *lum, *cb, *cr; + u8 *imageBlock; + u8 *tmp; + u32 row, col; + u32 block; + u32 x, y; + i32 *pRes; + i32 tmp1, tmp2, tmp3, tmp4; + const u8 *clp = h264bsdClip + 512; + +/* Code */ + + ASSERT(image); + ASSERT(data); + ASSERT(mbNum < image->width * image->height); + ASSERT(!((u32)data&0x3)); + + /* Image size in macroblocks */ + picWidth = image->width; + picSize = picWidth * image->height; + row = mbNum / picWidth; + col = mbNum % picWidth; + + /* Output macroblock position in output picture */ + lum = (image->data + row * picWidth * 256 + col * 16); + cb = (image->data + picSize * 256 + row * picWidth * 64 + col * 8); + cr = (cb + picSize * 64); + + picWidth *= 16; + + for (block = 0; block < 16; block++) + { + x = h264bsdBlockX[block]; + y = h264bsdBlockY[block]; + + pRes = residual[block]; + + ASSERT(pRes); + + tmp = data + y*16 + x; + imageBlock = lum + y*picWidth + x; + + ASSERT(!((u32)tmp&0x3)); + ASSERT(!((u32)imageBlock&0x3)); + + if (IS_RESIDUAL_EMPTY(pRes)) + { + /*lint -e826 */ + i32 *in32 = (i32*)tmp; + i32 *out32 = (i32*)imageBlock; + + /* Residual is zero => copy prediction block to output */ + tmp1 = *in32; in32 += 4; + tmp2 = *in32; in32 += 4; + *out32 = tmp1; out32 += picWidth/4; + *out32 = tmp2; out32 += picWidth/4; + tmp1 = *in32; in32 += 4; + tmp2 = *in32; + *out32 = tmp1; out32 += picWidth/4; + *out32 = tmp2; + } + else + { + + RANGE_CHECK_ARRAY(pRes, -512, 511, 16); + + /* Calculate image = prediction + residual + * Process four pixels in a loop */ + for (i = 4; i; i--) + { + tmp1 = tmp[0]; + tmp2 = *pRes++; + tmp3 = tmp[1]; + tmp1 = clp[tmp1 + tmp2]; + tmp4 = *pRes++; + imageBlock[0] = (u8)tmp1; + tmp3 = clp[tmp3 + tmp4]; + tmp1 = tmp[2]; + tmp2 = *pRes++; + imageBlock[1] = (u8)tmp3; + tmp1 = clp[tmp1 + tmp2]; + tmp3 = tmp[3]; + tmp4 = *pRes++; + imageBlock[2] = (u8)tmp1; + tmp3 = clp[tmp3 + tmp4]; + tmp += 16; + imageBlock[3] = (u8)tmp3; + imageBlock += picWidth; + } + } + + } + + picWidth /= 2; + + for (block = 16; block <= 23; block++) + { + x = h264bsdBlockX[block & 0x3]; + y = h264bsdBlockY[block & 0x3]; + + pRes = residual[block]; + + ASSERT(pRes); + + tmp = data + 256; + imageBlock = cb; + + if (block >= 20) + { + imageBlock = cr; + tmp += 64; + } + + tmp += y*8 + x; + imageBlock += y*picWidth + x; + + ASSERT(!((u32)tmp&0x3)); + ASSERT(!((u32)imageBlock&0x3)); + + if (IS_RESIDUAL_EMPTY(pRes)) + { + /*lint -e826 */ + i32 *in32 = (i32*)tmp; + i32 *out32 = (i32*)imageBlock; + + /* Residual is zero => copy prediction block to output */ + tmp1 = *in32; in32 += 2; + tmp2 = *in32; in32 += 2; + *out32 = tmp1; out32 += picWidth/4; + *out32 = tmp2; out32 += picWidth/4; + tmp1 = *in32; in32 += 2; + tmp2 = *in32; + *out32 = tmp1; out32 += picWidth/4; + *out32 = tmp2; + } + else + { + + RANGE_CHECK_ARRAY(pRes, -512, 511, 16); + + for (i = 4; i; i--) + { + tmp1 = tmp[0]; + tmp2 = *pRes++; + tmp3 = tmp[1]; + tmp1 = clp[tmp1 + tmp2]; + tmp4 = *pRes++; + imageBlock[0] = (u8)tmp1; + tmp3 = clp[tmp3 + tmp4]; + tmp1 = tmp[2]; + tmp2 = *pRes++; + imageBlock[1] = (u8)tmp3; + tmp1 = clp[tmp1 + tmp2]; + tmp3 = tmp[3]; + tmp4 = *pRes++; + imageBlock[2] = (u8)tmp1; + tmp3 = clp[tmp3 + tmp4]; + tmp += 8; + imageBlock[3] = (u8)tmp3; + imageBlock += picWidth; + } + } + } + +} +#endif /* H264DEC_OMXDL */ + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_image.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_image.h new file mode 100755 index 0000000..ed7c18c --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_image.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. Module defines + 3. Data types + 4. Function prototypes + +------------------------------------------------------------------------------*/ + +#ifndef H264SWDEC_IMAGE_H +#define H264SWDEC_IMAGE_H + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "basetype.h" + +/*------------------------------------------------------------------------------ + 2. Module defines +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 3. Data types +------------------------------------------------------------------------------*/ + +typedef struct +{ + u8 *data; + u32 width; + u32 height; + /* current MB's components */ + u8 *luma; + u8 *cb; + u8 *cr; +} image_t; + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ + +void h264bsdWriteMacroblock(image_t *image, u8 *data); + +#ifndef H264DEC_OMXDL +void h264bsdWriteOutputBlocks(image_t *image, u32 mbNum, u8 *data, + i32 residual[][16]); +#endif + +#endif /* #ifdef H264SWDEC_IMAGE_H */ + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_inter_prediction.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_inter_prediction.c new file mode 100755 index 0000000..2a81c4a --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_inter_prediction.c @@ -0,0 +1,1027 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. External compiler flags + 3. Module defines + 4. Local function prototypes + 5. Functions + h264bsdInterPrediction + MvPrediction16x16 + MvPrediction16x8 + MvPrediction8x16 + MvPrediction8x8 + MvPrediction + MedianFilter + GetInterNeighbour + GetPredictionMv + +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "h264bsd_inter_prediction.h" +#include "h264bsd_neighbour.h" +#include "h264bsd_util.h" +#include "h264bsd_reconstruct.h" +#include "h264bsd_dpb.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +typedef struct +{ + u32 available; + u32 refIndex; + mv_t mv; +} interNeighbour_t; + +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ + +static u32 MvPrediction16x16(mbStorage_t *pMb, mbPred_t *mbPred, + dpbStorage_t *dpb); +static u32 MvPrediction16x8(mbStorage_t *pMb, mbPred_t *mbPred, + dpbStorage_t *dpb); +static u32 MvPrediction8x16(mbStorage_t *pMb, mbPred_t *mbPred, + dpbStorage_t *dpb); +static u32 MvPrediction8x8(mbStorage_t *pMb, subMbPred_t *subMbPred, + dpbStorage_t *dpb); +static u32 MvPrediction(mbStorage_t *pMb, subMbPred_t *subMbPred, + u32 mbPartIdx, u32 subMbPartIdx); +static i32 MedianFilter(i32 a, i32 b, i32 c); + +static void GetInterNeighbour(u32 sliceId, mbStorage_t *nMb, + interNeighbour_t *n, u32 index); +static void GetPredictionMv(mv_t *mv, interNeighbour_t *a, u32 refIndex); + +static const neighbour_t N_A_SUB_PART[4][4][4] = { + { { {MB_A,5}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} }, + { {MB_A,5}, {MB_A,7}, {MB_NA,0}, {MB_NA,0} }, + { {MB_A,5}, {MB_CURR,0}, {MB_NA,0}, {MB_NA,0} }, + { {MB_A,5}, {MB_CURR,0}, {MB_A,7}, {MB_CURR,2} } }, + + { { {MB_CURR,1}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} }, + { {MB_CURR,1}, {MB_CURR,3}, {MB_NA,0}, {MB_NA,0} }, + { {MB_CURR,1}, {MB_CURR,4}, {MB_NA,0}, {MB_NA,0} }, + { {MB_CURR,1}, {MB_CURR,4}, {MB_CURR,3}, {MB_CURR,6} } }, + + { { {MB_A,13}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} }, + { {MB_A,13}, {MB_A,15}, {MB_NA,0}, {MB_NA,0} }, + { {MB_A,13}, {MB_CURR,8}, {MB_NA,0}, {MB_NA,0} }, + { {MB_A,13}, {MB_CURR,8}, {MB_A,15}, {MB_CURR,10} } }, + + { { {MB_CURR,9}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} }, + { {MB_CURR,9}, {MB_CURR,11}, {MB_NA,0}, {MB_NA,0} }, + { {MB_CURR,9}, {MB_CURR,12}, {MB_NA,0}, {MB_NA,0} }, + { {MB_CURR,9}, {MB_CURR,12}, {MB_CURR,11}, {MB_CURR,14} } } }; + +static const neighbour_t N_B_SUB_PART[4][4][4] = { + { { {MB_B,10}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} }, + { {MB_B,10}, {MB_CURR,0}, {MB_NA,0}, {MB_NA,0} }, + { {MB_B,10}, {MB_B,11}, {MB_NA,0}, {MB_NA,0} }, + { {MB_B,10}, {MB_B,11}, {MB_CURR,0}, {MB_CURR,1} } }, + + { { {MB_B,14}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} }, + { {MB_B,14}, {MB_CURR,4}, {MB_NA,0}, {MB_NA,0} }, + { {MB_B,14}, {MB_B,15}, {MB_NA,0}, {MB_NA,0} }, + { {MB_B,14}, {MB_B,15}, {MB_CURR,4}, {MB_CURR,5} } }, + + { { {MB_CURR,2}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} }, + { {MB_CURR,2}, {MB_CURR,8}, {MB_NA,0}, {MB_NA,0} }, + { {MB_CURR,2}, {MB_CURR,3}, {MB_NA,0}, {MB_NA,0} }, + { {MB_CURR,2}, {MB_CURR,3}, {MB_CURR,8}, {MB_CURR,9} } }, + + { { {MB_CURR,6}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} }, + { {MB_CURR,6}, {MB_CURR,12}, {MB_NA,0}, {MB_NA,0} }, + { {MB_CURR,6}, {MB_CURR,7}, {MB_NA,0}, {MB_NA,0} }, + { {MB_CURR,6}, {MB_CURR,7}, {MB_CURR,12}, {MB_CURR,13} } } }; + +static const neighbour_t N_C_SUB_PART[4][4][4] = { + { { {MB_B,14}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} }, + { {MB_B,14}, {MB_NA,4}, {MB_NA,0}, {MB_NA,0} }, + { {MB_B,11}, {MB_B,14}, {MB_NA,0}, {MB_NA,0} }, + { {MB_B,11}, {MB_B,14}, {MB_CURR,1}, {MB_NA,4} } }, + + { { {MB_C,10}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} }, + { {MB_C,10}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} }, + { {MB_B,15}, {MB_C,10}, {MB_NA,0}, {MB_NA,0} }, + { {MB_B,15}, {MB_C,10}, {MB_CURR,5}, {MB_NA,0} } }, + + { { {MB_CURR,6}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} }, + { {MB_CURR,6}, {MB_NA,12}, {MB_NA,0}, {MB_NA,0} }, + { {MB_CURR,3}, {MB_CURR,6}, {MB_NA,0}, {MB_NA,0} }, + { {MB_CURR,3}, {MB_CURR,6}, {MB_CURR,9}, {MB_NA,12} } }, + + { { {MB_NA,2}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} }, + { {MB_NA,2}, {MB_NA,8}, {MB_NA,0}, {MB_NA,0} }, + { {MB_CURR,7}, {MB_NA,2}, {MB_NA,0}, {MB_NA,0} }, + { {MB_CURR,7}, {MB_NA,2}, {MB_CURR,13}, {MB_NA,8} } } }; + +static const neighbour_t N_D_SUB_PART[4][4][4] = { + { { {MB_D,15}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} }, + { {MB_D,15}, {MB_A,5}, {MB_NA,0}, {MB_NA,0} }, + { {MB_D,15}, {MB_B,10}, {MB_NA,0}, {MB_NA,0} }, + { {MB_D,15}, {MB_B,10}, {MB_A,5}, {MB_CURR,0} } }, + + { { {MB_B,11}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} }, + { {MB_B,11}, {MB_CURR,1}, {MB_NA,0}, {MB_NA,0} }, + { {MB_B,11}, {MB_B,14}, {MB_NA,0}, {MB_NA,0} }, + { {MB_B,11}, {MB_B,14}, {MB_CURR,1}, {MB_CURR,4} } }, + + { { {MB_A,7}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} }, + { {MB_A,7}, {MB_A,13}, {MB_NA,0}, {MB_NA,0} }, + { {MB_A,7}, {MB_CURR,2}, {MB_NA,0}, {MB_NA,0} }, + { {MB_A,7}, {MB_CURR,2}, {MB_A,13}, {MB_CURR,8} } }, + + { { {MB_CURR,3}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} }, + { {MB_CURR,3}, {MB_CURR,9}, {MB_NA,0}, {MB_NA,0} }, + { {MB_CURR,3}, {MB_CURR,6}, {MB_NA,0}, {MB_NA,0} }, + { {MB_CURR,3}, {MB_CURR,6}, {MB_CURR,9}, {MB_CURR,12} } } }; + + +#ifdef H264DEC_OMXDL + +/*------------------------------------------------------------------------------ + + Function: h264bsdInterPrediction + + Functional description: + Processes one inter macroblock. Performs motion vector prediction + and reconstructs prediction macroblock. Writes the final macroblock + (prediction + residual) into the output image (currImage) + + Inputs: + pMb pointer to macroblock specific information + pMbLayer pointer to current macroblock data from stream + dpb pointer to decoded picture buffer + mbNum current macroblock number + currImage pointer to output image + data pointer where predicted macroblock will be stored + + Outputs: + pMb structure is updated with current macroblock + currImage current macroblock is written into image + data prediction is stored here + + Returns: + HANTRO_OK success + HANTRO_NOK error in motion vector prediction + +------------------------------------------------------------------------------*/ +u32 h264bsdInterPrediction(mbStorage_t *pMb, macroblockLayer_t *pMbLayer, + dpbStorage_t *dpb, u32 mbNum, image_t *currImage, u8 *data) +{ + +/* Variables */ + + u32 i; + u32 x, y; + u32 colAndRow; + subMbPartMode_e subPartMode; + image_t refImage; + u8 fillBuff[32*21 + 15 + 32]; + u8 *pFill; + u32 tmp; +/* Code */ + + ASSERT(pMb); + ASSERT(h264bsdMbPartPredMode(pMb->mbType) == PRED_MODE_INTER); + ASSERT(pMbLayer); + + /* 16-byte alignment */ + pFill = ALIGN(fillBuff, 16); + + /* set row bits 15:0 */ + colAndRow = mbNum / currImage->width; + /*set col to bits 31:16 */ + colAndRow += (mbNum - colAndRow * currImage->width) << 16; + colAndRow <<= 4; + + refImage.width = currImage->width; + refImage.height = currImage->height; + + switch (pMb->mbType) + { + case P_Skip: + case P_L0_16x16: + if (MvPrediction16x16(pMb, &pMbLayer->mbPred, dpb) != HANTRO_OK) + return(HANTRO_NOK); + refImage.data = pMb->refAddr[0]; + tmp = (0<<24) + (0<<16) + (16<<8) + 16; + h264bsdPredictSamples(data, pMb->mv, &refImage, + colAndRow, tmp, pFill); + break; + + case P_L0_L0_16x8: + if ( MvPrediction16x8(pMb, &pMbLayer->mbPred, dpb) != HANTRO_OK) + return(HANTRO_NOK); + refImage.data = pMb->refAddr[0]; + tmp = (0<<24) + (0<<16) + (16<<8) + 8; + h264bsdPredictSamples(data, pMb->mv, &refImage, + colAndRow, tmp, pFill); + + refImage.data = pMb->refAddr[2]; + tmp = (0<<24) + (8<<16) + (16<<8) + 8; + h264bsdPredictSamples(data, pMb->mv+8, &refImage, + colAndRow, tmp, pFill); + break; + + case P_L0_L0_8x16: + if ( MvPrediction8x16(pMb, &pMbLayer->mbPred, dpb) != HANTRO_OK) + return(HANTRO_NOK); + refImage.data = pMb->refAddr[0]; + tmp = (0<<24) + (0<<16) + (8<<8) + 16; + h264bsdPredictSamples(data, pMb->mv, &refImage, + colAndRow, tmp, pFill); + refImage.data = pMb->refAddr[1]; + tmp = (8<<24) + (0<<16) + (8<<8) + 16; + h264bsdPredictSamples(data, pMb->mv+4, &refImage, + colAndRow, tmp, pFill); + break; + + default: /* P_8x8 and P_8x8ref0 */ + if ( MvPrediction8x8(pMb, &pMbLayer->subMbPred, dpb) != HANTRO_OK) + return(HANTRO_NOK); + for (i = 0; i < 4; i++) + { + refImage.data = pMb->refAddr[i]; + subPartMode = + h264bsdSubMbPartMode(pMbLayer->subMbPred.subMbType[i]); + x = i & 0x1 ? 8 : 0; + y = i < 2 ? 0 : 8; + switch (subPartMode) + { + case MB_SP_8x8: + tmp = (x<<24) + (y<<16) + (8<<8) + 8; + h264bsdPredictSamples(data, pMb->mv+4*i, &refImage, + colAndRow, tmp, pFill); + break; + + case MB_SP_8x4: + tmp = (x<<24) + (y<<16) + (8<<8) + 4; + h264bsdPredictSamples(data, pMb->mv+4*i, &refImage, + colAndRow, tmp, pFill); + tmp = (x<<24) + ((y+4)<<16) + (8<<8) + 4; + h264bsdPredictSamples(data, pMb->mv+4*i+2, &refImage, + colAndRow, tmp, pFill); + break; + + case MB_SP_4x8: + tmp = (x<<24) + (y<<16) + (4<<8) + 8; + h264bsdPredictSamples(data, pMb->mv+4*i, &refImage, + colAndRow, tmp, pFill); + tmp = ((x+4)<<24) + (y<<16) + (4<<8) + 8; + h264bsdPredictSamples(data, pMb->mv+4*i+1, &refImage, + colAndRow, tmp, pFill); + break; + + default: + tmp = (x<<24) + (y<<16) + (4<<8) + 4; + h264bsdPredictSamples(data, pMb->mv+4*i, &refImage, + colAndRow, tmp, pFill); + tmp = ((x+4)<<24) + (y<<16) + (4<<8) + 4; + h264bsdPredictSamples(data, pMb->mv+4*i+1, &refImage, + colAndRow, tmp, pFill); + tmp = (x<<24) + ((y+4)<<16) + (4<<8) + 4; + h264bsdPredictSamples(data, pMb->mv+4*i+2, &refImage, + colAndRow, tmp, pFill); + tmp = ((x+4)<<24) + ((y+4)<<16) + (4<<8) + 4; + h264bsdPredictSamples(data, pMb->mv+4*i+3, &refImage, + colAndRow, tmp, pFill); + break; + } + } + break; + } + + /* if decoded flag > 1 -> mb has already been successfully decoded and + * written to output -> do not write again */ + if (pMb->decoded > 1) + return HANTRO_OK; + + return(HANTRO_OK); +} + +#else /* H264DEC_OMXDL */ + +/*------------------------------------------------------------------------------ + + Function: h264bsdInterPrediction + + Functional description: + Processes one inter macroblock. Performs motion vector prediction + and reconstructs prediction macroblock. Writes the final macroblock + (prediction + residual) into the output image (currImage) + + Inputs: + pMb pointer to macroblock specific information + pMbLayer pointer to current macroblock data from stream + dpb pointer to decoded picture buffer + mbNum current macroblock number + currImage pointer to output image + data pointer where predicted macroblock will be stored + + Outputs: + pMb structure is updated with current macroblock + currImage current macroblock is written into image + data prediction is stored here + + Returns: + HANTRO_OK success + HANTRO_NOK error in motion vector prediction + +------------------------------------------------------------------------------*/ +u32 h264bsdInterPrediction(mbStorage_t *pMb, macroblockLayer_t *pMbLayer, + dpbStorage_t *dpb, u32 mbNum, image_t *currImage, u8 *data) +{ + +/* Variables */ + + u32 i; + u32 x, y; + u32 row, col; + subMbPartMode_e subPartMode; + image_t refImage; + +/* Code */ + + ASSERT(pMb); + ASSERT(h264bsdMbPartPredMode(pMb->mbType) == PRED_MODE_INTER); + ASSERT(pMbLayer); + + row = mbNum / currImage->width; + col = mbNum - row * currImage->width; + row *= 16; + col *= 16; + + refImage.width = currImage->width; + refImage.height = currImage->height; + + switch (pMb->mbType) + { + case P_Skip: + case P_L0_16x16: + if (MvPrediction16x16(pMb, &pMbLayer->mbPred, dpb) != HANTRO_OK) + return(HANTRO_NOK); + refImage.data = pMb->refAddr[0]; + h264bsdPredictSamples(data, pMb->mv, &refImage, col, row, 0, 0, + 16, 16); + break; + + case P_L0_L0_16x8: + if ( MvPrediction16x8(pMb, &pMbLayer->mbPred, dpb) != HANTRO_OK) + return(HANTRO_NOK); + refImage.data = pMb->refAddr[0]; + h264bsdPredictSamples(data, pMb->mv, &refImage, col, row, 0, 0, + 16, 8); + refImage.data = pMb->refAddr[2]; + h264bsdPredictSamples(data, pMb->mv+8, &refImage, col, row, 0, 8, + 16, 8); + break; + + case P_L0_L0_8x16: + if ( MvPrediction8x16(pMb, &pMbLayer->mbPred, dpb) != HANTRO_OK) + return(HANTRO_NOK); + refImage.data = pMb->refAddr[0]; + h264bsdPredictSamples(data, pMb->mv, &refImage, col, row, 0, 0, + 8, 16); + refImage.data = pMb->refAddr[1]; + h264bsdPredictSamples(data, pMb->mv+4, &refImage, col, row, 8, 0, + 8, 16); + break; + + default: /* P_8x8 and P_8x8ref0 */ + if ( MvPrediction8x8(pMb, &pMbLayer->subMbPred, dpb) != HANTRO_OK) + return(HANTRO_NOK); + for (i = 0; i < 4; i++) + { + refImage.data = pMb->refAddr[i]; + subPartMode = + h264bsdSubMbPartMode(pMbLayer->subMbPred.subMbType[i]); + x = i & 0x1 ? 8 : 0; + y = i < 2 ? 0 : 8; + switch (subPartMode) + { + case MB_SP_8x8: + h264bsdPredictSamples(data, pMb->mv+4*i, &refImage, + col, row, x, y, 8, 8); + break; + + case MB_SP_8x4: + h264bsdPredictSamples(data, pMb->mv+4*i, &refImage, + col, row, x, y, 8, 4); + h264bsdPredictSamples(data, pMb->mv+4*i+2, &refImage, + col, row, x, y+4, 8, 4); + break; + + case MB_SP_4x8: + h264bsdPredictSamples(data, pMb->mv+4*i, &refImage, + col, row, x, y, 4, 8); + h264bsdPredictSamples(data, pMb->mv+4*i+1, &refImage, + col, row, x+4, y, 4, 8); + break; + + default: + h264bsdPredictSamples(data, pMb->mv+4*i, &refImage, + col, row, x, y, 4, 4); + h264bsdPredictSamples(data, pMb->mv+4*i+1, &refImage, + col, row, x+4, y, 4, 4); + h264bsdPredictSamples(data, pMb->mv+4*i+2, &refImage, + col, row, x, y+4, 4, 4); + h264bsdPredictSamples(data, pMb->mv+4*i+3, &refImage, + col, row, x+4, y+4, 4, 4); + break; + } + } + break; + } + + /* if decoded flag > 1 -> mb has already been successfully decoded and + * written to output -> do not write again */ + if (pMb->decoded > 1) + return HANTRO_OK; + + if (pMb->mbType != P_Skip) + { + h264bsdWriteOutputBlocks(currImage, mbNum, data, + pMbLayer->residual.level); + } + else + { + h264bsdWriteMacroblock(currImage, data); + } + + return(HANTRO_OK); +} +#endif /* H264DEC_OMXDL */ + +/*------------------------------------------------------------------------------ + + Function: MvPrediction16x16 + + Functional description: + Motion vector prediction for 16x16 partition mode + +------------------------------------------------------------------------------*/ + +u32 MvPrediction16x16(mbStorage_t *pMb, mbPred_t *mbPred, dpbStorage_t *dpb) +{ + +/* Variables */ + + mv_t mv; + mv_t mvPred; + interNeighbour_t a[3]; /* A, B, C */ + u32 refIndex; + u8 *tmp; + u32 *tmpMv1, *tmpMv2; + +/* Code */ + + refIndex = mbPred->refIdxL0[0]; + + GetInterNeighbour(pMb->sliceId, pMb->mbA, a, 5); + GetInterNeighbour(pMb->sliceId, pMb->mbB, a+1, 10); + /*lint --e(740) Unusual pointer cast (incompatible indirect types) */ + tmpMv1 = (u32*)(&a[0].mv); /* we test just that both MVs are zero */ + /*lint --e(740) */ + tmpMv2 = (u32*)(&a[1].mv); /* i.e. a[0].mv.hor == 0 && a[0].mv.ver == 0 */ + if (pMb->mbType == P_Skip && + (!a[0].available || !a[1].available || + ( a[0].refIndex == 0 && ((u32)(*tmpMv1) == 0) ) || + ( a[1].refIndex == 0 && ((u32)(*tmpMv2) == 0) ))) + { + mv.hor = mv.ver = 0; + } + else + { + mv = mbPred->mvdL0[0]; + GetInterNeighbour(pMb->sliceId, pMb->mbC, a+2, 10); + if (!a[2].available) + { + GetInterNeighbour(pMb->sliceId, pMb->mbD, a+2, 15); + } + + GetPredictionMv(&mvPred, a, refIndex); + + mv.hor += mvPred.hor; + mv.ver += mvPred.ver; + + /* horizontal motion vector range [-2048, 2047.75] */ + if ((u32)(i32)(mv.hor+8192) >= (16384)) + return(HANTRO_NOK); + + /* vertical motion vector range [-512, 511.75] + * (smaller for low levels) */ + if ((u32)(i32)(mv.ver+2048) >= (4096)) + return(HANTRO_NOK); + } + + tmp = h264bsdGetRefPicData(dpb, refIndex); + if (tmp == NULL) + return(HANTRO_NOK); + + pMb->mv[0] = pMb->mv[1] = pMb->mv[2] = pMb->mv[3] = + pMb->mv[4] = pMb->mv[5] = pMb->mv[6] = pMb->mv[7] = + pMb->mv[8] = pMb->mv[9] = pMb->mv[10] = pMb->mv[11] = + pMb->mv[12] = pMb->mv[13] = pMb->mv[14] = pMb->mv[15] = mv; + + pMb->refPic[0] = refIndex; + pMb->refPic[1] = refIndex; + pMb->refPic[2] = refIndex; + pMb->refPic[3] = refIndex; + pMb->refAddr[0] = tmp; + pMb->refAddr[1] = tmp; + pMb->refAddr[2] = tmp; + pMb->refAddr[3] = tmp; + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: MvPrediction16x8 + + Functional description: + Motion vector prediction for 16x8 partition mode + +------------------------------------------------------------------------------*/ + +u32 MvPrediction16x8(mbStorage_t *pMb, mbPred_t *mbPred, dpbStorage_t *dpb) +{ + +/* Variables */ + + mv_t mv; + mv_t mvPred; + interNeighbour_t a[3]; /* A, B, C */ + u32 refIndex; + u8 *tmp; + +/* Code */ + + mv = mbPred->mvdL0[0]; + refIndex = mbPred->refIdxL0[0]; + + GetInterNeighbour(pMb->sliceId, pMb->mbB, a+1, 10); + + if (a[1].refIndex == refIndex) + mvPred = a[1].mv; + else + { + GetInterNeighbour(pMb->sliceId, pMb->mbA, a, 5); + GetInterNeighbour(pMb->sliceId, pMb->mbC, a+2, 10); + if (!a[2].available) + { + GetInterNeighbour(pMb->sliceId, pMb->mbD, a+2, 15); + } + + GetPredictionMv(&mvPred, a, refIndex); + + } + mv.hor += mvPred.hor; + mv.ver += mvPred.ver; + + /* horizontal motion vector range [-2048, 2047.75] */ + if ((u32)(i32)(mv.hor+8192) >= (16384)) + return(HANTRO_NOK); + + /* vertical motion vector range [-512, 511.75] (smaller for low levels) */ + if ((u32)(i32)(mv.ver+2048) >= (4096)) + return(HANTRO_NOK); + + tmp = h264bsdGetRefPicData(dpb, refIndex); + if (tmp == NULL) + return(HANTRO_NOK); + + pMb->mv[0] = pMb->mv[1] = pMb->mv[2] = pMb->mv[3] = + pMb->mv[4] = pMb->mv[5] = pMb->mv[6] = pMb->mv[7] = mv; + pMb->refPic[0] = refIndex; + pMb->refPic[1] = refIndex; + pMb->refAddr[0] = tmp; + pMb->refAddr[1] = tmp; + + mv = mbPred->mvdL0[1]; + refIndex = mbPred->refIdxL0[1]; + + GetInterNeighbour(pMb->sliceId, pMb->mbA, a, 13); + if (a[0].refIndex == refIndex) + mvPred = a[0].mv; + else + { + a[1].available = HANTRO_TRUE; + a[1].refIndex = pMb->refPic[0]; + a[1].mv = pMb->mv[0]; + + /* c is not available */ + GetInterNeighbour(pMb->sliceId, pMb->mbA, a+2, 7); + + GetPredictionMv(&mvPred, a, refIndex); + + } + mv.hor += mvPred.hor; + mv.ver += mvPred.ver; + + /* horizontal motion vector range [-2048, 2047.75] */ + if ((u32)(i32)(mv.hor+8192) >= (16384)) + return(HANTRO_NOK); + + /* vertical motion vector range [-512, 511.75] (smaller for low levels) */ + if ((u32)(i32)(mv.ver+2048) >= (4096)) + return(HANTRO_NOK); + + tmp = h264bsdGetRefPicData(dpb, refIndex); + if (tmp == NULL) + return(HANTRO_NOK); + + pMb->mv[8] = pMb->mv[9] = pMb->mv[10] = pMb->mv[11] = + pMb->mv[12] = pMb->mv[13] = pMb->mv[14] = pMb->mv[15] = mv; + pMb->refPic[2] = refIndex; + pMb->refPic[3] = refIndex; + pMb->refAddr[2] = tmp; + pMb->refAddr[3] = tmp; + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: MvPrediction8x16 + + Functional description: + Motion vector prediction for 8x16 partition mode + +------------------------------------------------------------------------------*/ + +u32 MvPrediction8x16(mbStorage_t *pMb, mbPred_t *mbPred, dpbStorage_t *dpb) +{ + +/* Variables */ + + mv_t mv; + mv_t mvPred; + interNeighbour_t a[3]; /* A, B, C */ + u32 refIndex; + u8 *tmp; + +/* Code */ + + mv = mbPred->mvdL0[0]; + refIndex = mbPred->refIdxL0[0]; + + GetInterNeighbour(pMb->sliceId, pMb->mbA, a, 5); + + if (a[0].refIndex == refIndex) + mvPred = a[0].mv; + else + { + GetInterNeighbour(pMb->sliceId, pMb->mbB, a+1, 10); + GetInterNeighbour(pMb->sliceId, pMb->mbB, a+2, 14); + if (!a[2].available) + { + GetInterNeighbour(pMb->sliceId, pMb->mbD, a+2, 15); + } + + GetPredictionMv(&mvPred, a, refIndex); + + } + mv.hor += mvPred.hor; + mv.ver += mvPred.ver; + + /* horizontal motion vector range [-2048, 2047.75] */ + if ((u32)(i32)(mv.hor+8192) >= (16384)) + return(HANTRO_NOK); + + /* vertical motion vector range [-512, 511.75] (smaller for low levels) */ + if ((u32)(i32)(mv.ver+2048) >= (4096)) + return(HANTRO_NOK); + + tmp = h264bsdGetRefPicData(dpb, refIndex); + if (tmp == NULL) + return(HANTRO_NOK); + + pMb->mv[0] = pMb->mv[1] = pMb->mv[2] = pMb->mv[3] = + pMb->mv[8] = pMb->mv[9] = pMb->mv[10] = pMb->mv[11] = mv; + pMb->refPic[0] = refIndex; + pMb->refPic[2] = refIndex; + pMb->refAddr[0] = tmp; + pMb->refAddr[2] = tmp; + + mv = mbPred->mvdL0[1]; + refIndex = mbPred->refIdxL0[1]; + + GetInterNeighbour(pMb->sliceId, pMb->mbC, a+2, 10); + if (!a[2].available) + { + GetInterNeighbour(pMb->sliceId, pMb->mbB, a+2, 11); + } + if (a[2].refIndex == refIndex) + mvPred = a[2].mv; + else + { + a[0].available = HANTRO_TRUE; + a[0].refIndex = pMb->refPic[0]; + a[0].mv = pMb->mv[0]; + + GetInterNeighbour(pMb->sliceId, pMb->mbB, a+1, 14); + + GetPredictionMv(&mvPred, a, refIndex); + + } + mv.hor += mvPred.hor; + mv.ver += mvPred.ver; + + /* horizontal motion vector range [-2048, 2047.75] */ + if ((u32)(i32)(mv.hor+8192) >= (16384)) + return(HANTRO_NOK); + + /* vertical motion vector range [-512, 511.75] (smaller for low levels) */ + if ((u32)(i32)(mv.ver+2048) >= (4096)) + return(HANTRO_NOK); + + tmp = h264bsdGetRefPicData(dpb, refIndex); + if (tmp == NULL) + return(HANTRO_NOK); + + pMb->mv[4] = pMb->mv[5] = pMb->mv[6] = pMb->mv[7] = + pMb->mv[12] = pMb->mv[13] = pMb->mv[14] = pMb->mv[15] = mv; + pMb->refPic[1] = refIndex; + pMb->refPic[3] = refIndex; + pMb->refAddr[1] = tmp; + pMb->refAddr[3] = tmp; + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: MvPrediction8x8 + + Functional description: + Motion vector prediction for 8x8 partition mode + +------------------------------------------------------------------------------*/ + +u32 MvPrediction8x8(mbStorage_t *pMb, subMbPred_t *subMbPred, dpbStorage_t *dpb) +{ + +/* Variables */ + + u32 i, j; + u32 numSubMbPart; + +/* Code */ + + for (i = 0; i < 4; i++) + { + numSubMbPart = h264bsdNumSubMbPart(subMbPred->subMbType[i]); + pMb->refPic[i] = subMbPred->refIdxL0[i]; + pMb->refAddr[i] = h264bsdGetRefPicData(dpb, subMbPred->refIdxL0[i]); + if (pMb->refAddr[i] == NULL) + return(HANTRO_NOK); + for (j = 0; j < numSubMbPart; j++) + { + if (MvPrediction(pMb, subMbPred, i, j) != HANTRO_OK) + return(HANTRO_NOK); + } + } + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: MvPrediction + + Functional description: + Perform motion vector prediction for sub-partition + +------------------------------------------------------------------------------*/ + +u32 MvPrediction(mbStorage_t *pMb, subMbPred_t *subMbPred, u32 mbPartIdx, + u32 subMbPartIdx) +{ + +/* Variables */ + + mv_t mv, mvPred; + u32 refIndex; + subMbPartMode_e subMbPartMode; + const neighbour_t *n; + mbStorage_t *nMb; + interNeighbour_t a[3]; /* A, B, C */ + +/* Code */ + + mv = subMbPred->mvdL0[mbPartIdx][subMbPartIdx]; + subMbPartMode = h264bsdSubMbPartMode(subMbPred->subMbType[mbPartIdx]); + refIndex = subMbPred->refIdxL0[mbPartIdx]; + + n = N_A_SUB_PART[mbPartIdx][subMbPartMode]+subMbPartIdx; + nMb = h264bsdGetNeighbourMb(pMb, n->mb); + GetInterNeighbour(pMb->sliceId, nMb, a, n->index); + + n = N_B_SUB_PART[mbPartIdx][subMbPartMode]+subMbPartIdx; + nMb = h264bsdGetNeighbourMb(pMb, n->mb); + GetInterNeighbour(pMb->sliceId, nMb, a+1, n->index); + + n = N_C_SUB_PART[mbPartIdx][subMbPartMode]+subMbPartIdx; + nMb = h264bsdGetNeighbourMb(pMb, n->mb); + GetInterNeighbour(pMb->sliceId, nMb, a+2, n->index); + + if (!a[2].available) + { + n = N_D_SUB_PART[mbPartIdx][subMbPartMode]+subMbPartIdx; + nMb = h264bsdGetNeighbourMb(pMb, n->mb); + GetInterNeighbour(pMb->sliceId, nMb, a+2, n->index); + } + + GetPredictionMv(&mvPred, a, refIndex); + + mv.hor += mvPred.hor; + mv.ver += mvPred.ver; + + /* horizontal motion vector range [-2048, 2047.75] */ + if (((u32)(i32)(mv.hor+8192) >= (16384))) + return(HANTRO_NOK); + + /* vertical motion vector range [-512, 511.75] (smaller for low levels) */ + if (((u32)(i32)(mv.ver+2048) >= (4096))) + return(HANTRO_NOK); + + switch (subMbPartMode) + { + case MB_SP_8x8: + pMb->mv[4*mbPartIdx] = mv; + pMb->mv[4*mbPartIdx + 1] = mv; + pMb->mv[4*mbPartIdx + 2] = mv; + pMb->mv[4*mbPartIdx + 3] = mv; + break; + + case MB_SP_8x4: + pMb->mv[4*mbPartIdx + 2*subMbPartIdx] = mv; + pMb->mv[4*mbPartIdx + 2*subMbPartIdx + 1] = mv; + break; + + case MB_SP_4x8: + pMb->mv[4*mbPartIdx + subMbPartIdx] = mv; + pMb->mv[4*mbPartIdx + subMbPartIdx + 2] = mv; + break; + + case MB_SP_4x4: + pMb->mv[4*mbPartIdx + subMbPartIdx] = mv; + break; + } + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: MedianFilter + + Functional description: + Median filtering for motion vector prediction + +------------------------------------------------------------------------------*/ + +i32 MedianFilter(i32 a, i32 b, i32 c) +{ + +/* Variables */ + + i32 max,min,med; + +/* Code */ + + max = min = med = a; + if (b > max) + { + max = b; + } + else if (b < min) + { + min = b; + } + if (c > max) + { + med = max; + } + else if (c < min) + { + med = min; + } + else + { + med = c; + } + + return(med); +} + +/*------------------------------------------------------------------------------ + + Function: GetInterNeighbour + + Functional description: + Get availability, reference index and motion vector of a neighbour + +------------------------------------------------------------------------------*/ + +void GetInterNeighbour(u32 sliceId, mbStorage_t *nMb, + interNeighbour_t *n, u32 index) +{ + + n->available = HANTRO_FALSE; + n->refIndex = 0xFFFFFFFF; + n->mv.hor = n->mv.ver = 0; + + if (nMb && (sliceId == nMb->sliceId)) + { + u32 tmp; + mv_t tmpMv; + + tmp = nMb->mbType; + n->available = HANTRO_TRUE; + /* MbPartPredMode "inlined" */ + if (tmp <= P_8x8ref0) + { + tmpMv = nMb->mv[index]; + tmp = nMb->refPic[index>>2]; + n->refIndex = tmp; + n->mv = tmpMv; + } + } + +} + +/*------------------------------------------------------------------------------ + + Function: GetPredictionMv + + Functional description: + Compute motion vector predictor based on neighbours A, B and C + +------------------------------------------------------------------------------*/ + +void GetPredictionMv(mv_t *mv, interNeighbour_t *a, u32 refIndex) +{ + + if ( a[1].available || a[2].available || !a[0].available) + { + u32 isA, isB, isC; + isA = (a[0].refIndex == refIndex) ? HANTRO_TRUE : HANTRO_FALSE; + isB = (a[1].refIndex == refIndex) ? HANTRO_TRUE : HANTRO_FALSE; + isC = (a[2].refIndex == refIndex) ? HANTRO_TRUE : HANTRO_FALSE; + + if (((u32)isA+(u32)isB+(u32)isC) != 1) + { + mv->hor = (i16)MedianFilter(a[0].mv.hor, a[1].mv.hor, a[2].mv.hor); + mv->ver = (i16)MedianFilter(a[0].mv.ver, a[1].mv.ver, a[2].mv.ver); + } + else if (isA) + *mv = a[0].mv; + else if (isB) + *mv = a[1].mv; + else + *mv = a[2].mv; + } + else + { + *mv = a[0].mv; + } + +} + + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_inter_prediction.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_inter_prediction.h new file mode 100755 index 0000000..94dee25 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_inter_prediction.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. Module defines + 3. Data types + 4. Function prototypes + +------------------------------------------------------------------------------*/ + +#ifndef H264SWDEC_INTER_PREDICTION_H +#define H264SWDEC_INTER_PREDICTION_H + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "basetype.h" +#include "h264bsd_image.h" +#include "h264bsd_macroblock_layer.h" +#include "h264bsd_dpb.h" + +/*------------------------------------------------------------------------------ + 2. Module defines +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 3. Data types +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ + +u32 h264bsdInterPrediction(mbStorage_t *pMb, macroblockLayer_t *pMbLayer, + dpbStorage_t *dpb, u32 mbNum, image_t *image, u8 *data); + +#endif /* #ifdef H264SWDEC_INTER_PREDICTION_H */ + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_intra_prediction.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_intra_prediction.c new file mode 100755 index 0000000..15eabfb --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_intra_prediction.c @@ -0,0 +1,1937 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. External compiler flags + 3. Module defines + 4. Local function prototypes + 5. Functions + h264bsdIntraPrediction + h264bsdGetNeighbourPels + h264bsdIntra16x16Prediction + h264bsdIntra4x4Prediction + h264bsdIntraChromaPrediction + h264bsdAddResidual + Intra16x16VerticalPrediction + Intra16x16HorizontalPrediction + Intra16x16DcPrediction + Intra16x16PlanePrediction + IntraChromaDcPrediction + IntraChromaHorizontalPrediction + IntraChromaVerticalPrediction + IntraChromaPlanePrediction + Get4x4NeighbourPels + Write4x4To16x16 + Intra4x4VerticalPrediction + Intra4x4HorizontalPrediction + Intra4x4DcPrediction + Intra4x4DiagonalDownLeftPrediction + Intra4x4DiagonalDownRightPrediction + Intra4x4VerticalRightPrediction + Intra4x4HorizontalDownPrediction + Intra4x4VerticalLeftPrediction + Intra4x4HorizontalUpPrediction + DetermineIntra4x4PredMode + +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "h264bsd_intra_prediction.h" +#include "h264bsd_util.h" +#include "h264bsd_macroblock_layer.h" +#include "h264bsd_neighbour.h" +#include "h264bsd_image.h" + +#ifdef H264DEC_OMXDL +#include "omxtypes.h" +#include "omxVC.h" +#endif /* H264DEC_OMXDL */ + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +/* Switch off the following Lint messages for this file: + * Info 702: Shift right of signed quantity (int) + */ +/*lint -e702 */ + + +/* x- and y-coordinates for each block */ +const u32 h264bsdBlockX[16] = + { 0, 4, 0, 4, 8, 12, 8, 12, 0, 4, 0, 4, 8, 12, 8, 12 }; +const u32 h264bsdBlockY[16] = + { 0, 0, 4, 4, 0, 0, 4, 4, 8, 8, 12, 12, 8, 8, 12, 12 }; + +const u8 h264bsdClip[1280] = +{ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, + 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, + 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, + 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63, + 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, + 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95, + 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111, + 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, + 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, + 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, + 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, + 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, + 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, + 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, + 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, + 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255 +}; + +#ifndef H264DEC_OMXDL +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ +static void Get4x4NeighbourPels(u8 *a, u8 *l, u8 *data, u8 *above, u8 *left, + u32 blockNum); +static void Intra16x16VerticalPrediction(u8 *data, u8 *above); +static void Intra16x16HorizontalPrediction(u8 *data, u8 *left); +static void Intra16x16DcPrediction(u8 *data, u8 *above, u8 *left, + u32 A, u32 B); +static void Intra16x16PlanePrediction(u8 *data, u8 *above, u8 *left); +static void IntraChromaDcPrediction(u8 *data, u8 *above, u8 *left, + u32 A, u32 B); +static void IntraChromaHorizontalPrediction(u8 *data, u8 *left); +static void IntraChromaVerticalPrediction(u8 *data, u8 *above); +static void IntraChromaPlanePrediction(u8 *data, u8 *above, u8 *left); + +static void Intra4x4VerticalPrediction(u8 *data, u8 *above); +static void Intra4x4HorizontalPrediction(u8 *data, u8 *left); +static void Intra4x4DcPrediction(u8 *data, u8 *above, u8 *left, u32 A, u32 B); +static void Intra4x4DiagonalDownLeftPrediction(u8 *data, u8 *above); +static void Intra4x4DiagonalDownRightPrediction(u8 *data, u8 *above, u8 *left); +static void Intra4x4VerticalRightPrediction(u8 *data, u8 *above, u8 *left); +static void Intra4x4HorizontalDownPrediction(u8 *data, u8 *above, u8 *left); +static void Intra4x4VerticalLeftPrediction(u8 *data, u8 *above); +static void Intra4x4HorizontalUpPrediction(u8 *data, u8 *left); +void h264bsdAddResidual(u8 *data, i32 *residual, u32 blockNum); + +static void Write4x4To16x16(u8 *data, u8 *data4x4, u32 blockNum); +#endif /* H264DEC_OMXDL */ + +static u32 DetermineIntra4x4PredMode(macroblockLayer_t *pMbLayer, + u32 available, neighbour_t *nA, neighbour_t *nB, u32 index, + mbStorage_t *nMbA, mbStorage_t *nMbB); + + +#ifdef H264DEC_OMXDL + +/*------------------------------------------------------------------------------ + + Function: h264bsdIntra16x16Prediction + + Functional description: + Perform intra 16x16 prediction mode for luma pixels and add + residual into prediction. The resulting luma pixels are + stored in macroblock array 'data'. + +------------------------------------------------------------------------------*/ +u32 h264bsdIntra16x16Prediction(mbStorage_t *pMb, u8 *data, u8 *ptr, + u32 width, u32 constrainedIntraPred) +{ + +/* Variables */ + + u32 availableA, availableB, availableD; + OMXResult omxRes; + +/* Code */ + ASSERT(pMb); + ASSERT(data); + ASSERT(ptr); + ASSERT(h264bsdPredModeIntra16x16(pMb->mbType) < 4); + + availableA = h264bsdIsNeighbourAvailable(pMb, pMb->mbA); + if (availableA && constrainedIntraPred && + (h264bsdMbPartPredMode(pMb->mbA->mbType) == PRED_MODE_INTER)) + availableA = HANTRO_FALSE; + availableB = h264bsdIsNeighbourAvailable(pMb, pMb->mbB); + if (availableB && constrainedIntraPred && + (h264bsdMbPartPredMode(pMb->mbB->mbType) == PRED_MODE_INTER)) + availableB = HANTRO_FALSE; + availableD = h264bsdIsNeighbourAvailable(pMb, pMb->mbD); + if (availableD && constrainedIntraPred && + (h264bsdMbPartPredMode(pMb->mbD->mbType) == PRED_MODE_INTER)) + availableD = HANTRO_FALSE; + + omxRes = omxVCM4P10_PredictIntra_16x16( (ptr-1), + (ptr - width), + (ptr - width-1), + data, + (i32)width, + 16, + (OMXVCM4P10Intra16x16PredMode) + h264bsdPredModeIntra16x16(pMb->mbType), + (i32)(availableB + (availableA<<1) + + (availableD<<5)) ); + if (omxRes != OMX_Sts_NoErr) + return HANTRO_NOK; + else + return(HANTRO_OK); +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdIntra4x4Prediction + + Functional description: + Perform intra 4x4 prediction for luma pixels and add residual + into prediction. The resulting luma pixels are stored in + macroblock array 'data'. The intra 4x4 prediction mode for each + block is stored in 'pMb' structure. + +------------------------------------------------------------------------------*/ +u32 h264bsdIntra4x4Prediction(mbStorage_t *pMb, u8 *data, + macroblockLayer_t *mbLayer, + u8 *ptr, u32 width, + u32 constrainedIntraPred, u32 block) +{ + +/* Variables */ + u32 mode; + neighbour_t neighbour, neighbourB; + mbStorage_t *nMb, *nMb2; + u32 availableA, availableB, availableC, availableD; + + OMXResult omxRes; + u32 x, y; + u8 *l, *a, *al; +/* Code */ + ASSERT(pMb); + ASSERT(data); + ASSERT(mbLayer); + ASSERT(ptr); + ASSERT(pMb->intra4x4PredMode[block] < 9); + + neighbour = *h264bsdNeighbour4x4BlockA(block); + nMb = h264bsdGetNeighbourMb(pMb, neighbour.mb); + availableA = h264bsdIsNeighbourAvailable(pMb, nMb); + if (availableA && constrainedIntraPred && + ( h264bsdMbPartPredMode(nMb->mbType) == PRED_MODE_INTER) ) + { + availableA = HANTRO_FALSE; + } + + neighbourB = *h264bsdNeighbour4x4BlockB(block); + nMb2 = h264bsdGetNeighbourMb(pMb, neighbourB.mb); + availableB = h264bsdIsNeighbourAvailable(pMb, nMb2); + if (availableB && constrainedIntraPred && + ( h264bsdMbPartPredMode(nMb2->mbType) == PRED_MODE_INTER) ) + { + availableB = HANTRO_FALSE; + } + + mode = DetermineIntra4x4PredMode(mbLayer, + (u32)(availableA && availableB), + &neighbour, &neighbourB, block, nMb, nMb2); + pMb->intra4x4PredMode[block] = (u8)mode; + + neighbour = *h264bsdNeighbour4x4BlockC(block); + nMb = h264bsdGetNeighbourMb(pMb, neighbour.mb); + availableC = h264bsdIsNeighbourAvailable(pMb, nMb); + if (availableC && constrainedIntraPred && + ( h264bsdMbPartPredMode(nMb->mbType) == PRED_MODE_INTER) ) + { + availableC = HANTRO_FALSE; + } + + neighbour = *h264bsdNeighbour4x4BlockD(block); + nMb = h264bsdGetNeighbourMb(pMb, neighbour.mb); + availableD = h264bsdIsNeighbourAvailable(pMb, nMb); + if (availableD && constrainedIntraPred && + ( h264bsdMbPartPredMode(nMb->mbType) == PRED_MODE_INTER) ) + { + availableD = HANTRO_FALSE; + } + + x = h264bsdBlockX[block]; + y = h264bsdBlockY[block]; + + if (y == 0) + a = ptr - width + x; + else + a = data-16; + + if (x == 0) + l = ptr + y * width -1; + else + { + l = data-1; + width = 16; + } + + if (x == 0) + al = l-width; + else + al = a-1; + + omxRes = omxVCM4P10_PredictIntra_4x4( l, + a, + al, + data, + (i32)width, + 16, + (OMXVCM4P10Intra4x4PredMode)mode, + (i32)(availableB + + (availableA<<1) + + (availableD<<5) + + (availableC<<6)) ); + if (omxRes != OMX_Sts_NoErr) + return HANTRO_NOK; + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdIntraChromaPrediction + + Functional description: + Perform intra prediction for chroma pixels and add residual + into prediction. The resulting chroma pixels are stored in 'data'. + +------------------------------------------------------------------------------*/ +u32 h264bsdIntraChromaPrediction(mbStorage_t *pMb, u8 *data, image_t *image, + u32 predMode, u32 constrainedIntraPred) +{ + +/* Variables */ + + u32 availableA, availableB, availableD; + OMXResult omxRes; + u8 *ptr; + u32 width; + +/* Code */ + ASSERT(pMb); + ASSERT(data); + ASSERT(image); + ASSERT(predMode < 4); + + availableA = h264bsdIsNeighbourAvailable(pMb, pMb->mbA); + if (availableA && constrainedIntraPred && + (h264bsdMbPartPredMode(pMb->mbA->mbType) == PRED_MODE_INTER)) + availableA = HANTRO_FALSE; + availableB = h264bsdIsNeighbourAvailable(pMb, pMb->mbB); + if (availableB && constrainedIntraPred && + (h264bsdMbPartPredMode(pMb->mbB->mbType) == PRED_MODE_INTER)) + availableB = HANTRO_FALSE; + availableD = h264bsdIsNeighbourAvailable(pMb, pMb->mbD); + if (availableD && constrainedIntraPred && + (h264bsdMbPartPredMode(pMb->mbD->mbType) == PRED_MODE_INTER)) + availableD = HANTRO_FALSE; + + ptr = image->cb; + width = image->width*8; + + omxRes = omxVCM4P10_PredictIntraChroma_8x8( (ptr-1), + (ptr - width), + (ptr - width -1), + data, + (i32)width, + 8, + (OMXVCM4P10IntraChromaPredMode) + predMode, + (i32)(availableB + + (availableA<<1) + + (availableD<<5)) ); + if (omxRes != OMX_Sts_NoErr) + return HANTRO_NOK; + + /* advance pointers */ + data += 64; + ptr = image->cr; + + omxRes = omxVCM4P10_PredictIntraChroma_8x8( (ptr-1), + (ptr - width), + (ptr - width -1), + data, + (i32)width, + 8, + (OMXVCM4P10IntraChromaPredMode) + predMode, + (i32)(availableB + + (availableA<<1) + + (availableD<<5)) ); + if (omxRes != OMX_Sts_NoErr) + return HANTRO_NOK; + + return(HANTRO_OK); + +} + + +#else /* H264DEC_OMXDL */ + + +/*------------------------------------------------------------------------------ + + Function: h264bsdIntraPrediction + + Functional description: + Processes one intra macroblock. Performs intra prediction using + specified prediction mode. Writes the final macroblock + (prediction + residual) into the output image (image) + + Inputs: + pMb pointer to macroblock specific information + mbLayer pointer to current macroblock data from stream + image pointer to output image + mbNum current macroblock number + constrainedIntraPred flag specifying if neighbouring inter + macroblocks are used in intra prediction + data pointer where output macroblock will be stored + + Outputs: + pMb structure is updated with current macroblock + image current macroblock is written into image + data current macroblock is stored here + + Returns: + HANTRO_OK success + HANTRO_NOK error in intra prediction + +------------------------------------------------------------------------------*/ +u32 h264bsdIntraPrediction(mbStorage_t *pMb, macroblockLayer_t *mbLayer, + image_t *image, u32 mbNum, u32 constrainedIntraPred, u8 *data) +{ + +/* Variables */ + + /* pelAbove and pelLeft contain samples above and left to the current + * macroblock. Above array contains also sample above-left to the current + * mb as well as 4 samples above-right to the current mb (latter only for + * luma) */ + /* lumD + lumB + lumC + cbD + cbB + crD + crB */ + u8 pelAbove[1 + 16 + 4 + 1 + 8 + 1 + 8]; + /* lumA + cbA + crA */ + u8 pelLeft[16 + 8 + 8]; + u32 tmp; + +/* Code */ + + ASSERT(pMb); + ASSERT(image); + ASSERT(mbNum < image->width * image->height); + ASSERT(h264bsdMbPartPredMode(pMb->mbType) != PRED_MODE_INTER); + + h264bsdGetNeighbourPels(image, pelAbove, pelLeft, mbNum); + + if (h264bsdMbPartPredMode(pMb->mbType) == PRED_MODE_INTRA16x16) + { + tmp = h264bsdIntra16x16Prediction(pMb, data, mbLayer->residual.level, + pelAbove, pelLeft, constrainedIntraPred); + if (tmp != HANTRO_OK) + return(tmp); + } + else + { + tmp = h264bsdIntra4x4Prediction(pMb, data, mbLayer, + pelAbove, pelLeft, constrainedIntraPred); + if (tmp != HANTRO_OK) + return(tmp); + } + + tmp = h264bsdIntraChromaPrediction(pMb, data + 256, + mbLayer->residual.level+16, pelAbove + 21, pelLeft + 16, + mbLayer->mbPred.intraChromaPredMode, constrainedIntraPred); + if (tmp != HANTRO_OK) + return(tmp); + + /* if decoded flag > 1 -> mb has already been successfully decoded and + * written to output -> do not write again */ + if (pMb->decoded > 1) + return HANTRO_OK; + + h264bsdWriteMacroblock(image, data); + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdGetNeighbourPels + + Functional description: + Get pixel values from neighbouring macroblocks into 'above' + and 'left' arrays. + +------------------------------------------------------------------------------*/ + +void h264bsdGetNeighbourPels(image_t *image, u8 *above, u8 *left, u32 mbNum) +{ + +/* Variables */ + + u32 i; + u32 width, picSize; + u8 *ptr, *tmp; + u32 row, col; + +/* Code */ + + ASSERT(image); + ASSERT(above); + ASSERT(left); + ASSERT(mbNum < image->width * image->height); + + if (!mbNum) + return; + + width = image->width; + picSize = width * image->height; + row = mbNum / width; + col = mbNum - row * width; + + width *= 16; + ptr = image->data + row * 16 * width + col * 16; + + /* note that luma samples above-right to current macroblock do not make + * sense when current mb is the right-most mb in a row. Same applies to + * sample above-left if col is zero. However, usage of pels in prediction + * is controlled by neighbour availability information in actual prediction + * process */ + if (row) + { + tmp = ptr - (width + 1); + for (i = 21; i--;) + *above++ = *tmp++; + } + + if (col) + { + ptr--; + for (i = 16; i--; ptr+=width) + *left++ = *ptr; + } + + width >>= 1; + ptr = image->data + picSize * 256 + row * 8 * width + col * 8; + + if (row) + { + tmp = ptr - (width + 1); + for (i = 9; i--;) + *above++ = *tmp++; + tmp += (picSize * 64) - 9; + for (i = 9; i--;) + *above++ = *tmp++; + } + + if (col) + { + ptr--; + for (i = 8; i--; ptr+=width) + *left++ = *ptr; + ptr += (picSize * 64) - 8 * width; + for (i = 8; i--; ptr+=width) + *left++ = *ptr; + } +} + +/*------------------------------------------------------------------------------ + + Function: Intra16x16Prediction + + Functional description: + Perform intra 16x16 prediction mode for luma pixels and add + residual into prediction. The resulting luma pixels are + stored in macroblock array 'data'. + +------------------------------------------------------------------------------*/ + +u32 h264bsdIntra16x16Prediction(mbStorage_t *pMb, u8 *data, i32 residual[][16], + u8 *above, u8 *left, u32 constrainedIntraPred) +{ + +/* Variables */ + + u32 i; + u32 availableA, availableB, availableD; + +/* Code */ + + ASSERT(data); + ASSERT(residual); + ASSERT(above); + ASSERT(left); + ASSERT(h264bsdPredModeIntra16x16(pMb->mbType) < 4); + + availableA = h264bsdIsNeighbourAvailable(pMb, pMb->mbA); + if (availableA && constrainedIntraPred && + (h264bsdMbPartPredMode(pMb->mbA->mbType) == PRED_MODE_INTER)) + availableA = HANTRO_FALSE; + availableB = h264bsdIsNeighbourAvailable(pMb, pMb->mbB); + if (availableB && constrainedIntraPred && + (h264bsdMbPartPredMode(pMb->mbB->mbType) == PRED_MODE_INTER)) + availableB = HANTRO_FALSE; + availableD = h264bsdIsNeighbourAvailable(pMb, pMb->mbD); + if (availableD && constrainedIntraPred && + (h264bsdMbPartPredMode(pMb->mbD->mbType) == PRED_MODE_INTER)) + availableD = HANTRO_FALSE; + + switch(h264bsdPredModeIntra16x16(pMb->mbType)) + { + case 0: /* Intra_16x16_Vertical */ + if (!availableB) + return(HANTRO_NOK); + Intra16x16VerticalPrediction(data, above+1); + break; + + case 1: /* Intra_16x16_Horizontal */ + if (!availableA) + return(HANTRO_NOK); + Intra16x16HorizontalPrediction(data, left); + break; + + case 2: /* Intra_16x16_DC */ + Intra16x16DcPrediction(data, above+1, left, availableA, availableB); + break; + + default: /* case 3: Intra_16x16_Plane */ + if (!availableA || !availableB || !availableD) + return(HANTRO_NOK); + Intra16x16PlanePrediction(data, above+1, left); + break; + } + /* add residual */ + for (i = 0; i < 16; i++) + h264bsdAddResidual(data, residual[i], i); + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: Intra4x4Prediction + + Functional description: + Perform intra 4x4 prediction for luma pixels and add residual + into prediction. The resulting luma pixels are stored in + macroblock array 'data'. The intra 4x4 prediction mode for each + block is stored in 'pMb' structure. + +------------------------------------------------------------------------------*/ + +u32 h264bsdIntra4x4Prediction(mbStorage_t *pMb, u8 *data, + macroblockLayer_t *mbLayer, u8 *above, + u8 *left, u32 constrainedIntraPred) +{ + +/* Variables */ + + u32 block; + u32 mode; + neighbour_t neighbour, neighbourB; + mbStorage_t *nMb, *nMb2; + u8 a[1 + 4 + 4], l[1 + 4]; + u32 data4x4[4]; + u32 availableA, availableB, availableC, availableD; + +/* Code */ + + ASSERT(data); + ASSERT(mbLayer); + ASSERT(above); + ASSERT(left); + + for (block = 0; block < 16; block++) + { + + ASSERT(pMb->intra4x4PredMode[block] < 9); + + neighbour = *h264bsdNeighbour4x4BlockA(block); + nMb = h264bsdGetNeighbourMb(pMb, neighbour.mb); + availableA = h264bsdIsNeighbourAvailable(pMb, nMb); + if (availableA && constrainedIntraPred && + ( h264bsdMbPartPredMode(nMb->mbType) == PRED_MODE_INTER) ) + { + availableA = HANTRO_FALSE; + } + + neighbourB = *h264bsdNeighbour4x4BlockB(block); + nMb2 = h264bsdGetNeighbourMb(pMb, neighbourB.mb); + availableB = h264bsdIsNeighbourAvailable(pMb, nMb2); + if (availableB && constrainedIntraPred && + ( h264bsdMbPartPredMode(nMb2->mbType) == PRED_MODE_INTER) ) + { + availableB = HANTRO_FALSE; + } + + mode = DetermineIntra4x4PredMode(mbLayer, + (u32)(availableA && availableB), + &neighbour, &neighbourB, block, nMb, nMb2); + pMb->intra4x4PredMode[block] = (u8)mode; + + neighbour = *h264bsdNeighbour4x4BlockC(block); + nMb = h264bsdGetNeighbourMb(pMb, neighbour.mb); + availableC = h264bsdIsNeighbourAvailable(pMb, nMb); + if (availableC && constrainedIntraPred && + ( h264bsdMbPartPredMode(nMb->mbType) == PRED_MODE_INTER) ) + { + availableC = HANTRO_FALSE; + } + + neighbour = *h264bsdNeighbour4x4BlockD(block); + nMb = h264bsdGetNeighbourMb(pMb, neighbour.mb); + availableD = h264bsdIsNeighbourAvailable(pMb, nMb); + if (availableD && constrainedIntraPred && + ( h264bsdMbPartPredMode(nMb->mbType) == PRED_MODE_INTER) ) + { + availableD = HANTRO_FALSE; + } + + Get4x4NeighbourPels(a, l, data, above, left, block); + + switch(mode) + { + case 0: /* Intra_4x4_Vertical */ + if (!availableB) + return(HANTRO_NOK); + Intra4x4VerticalPrediction((u8*)data4x4, a + 1); + break; + case 1: /* Intra_4x4_Horizontal */ + if (!availableA) + return(HANTRO_NOK); + Intra4x4HorizontalPrediction((u8*)data4x4, l + 1); + break; + case 2: /* Intra_4x4_DC */ + Intra4x4DcPrediction((u8*)data4x4, a + 1, l + 1, + availableA, availableB); + break; + case 3: /* Intra_4x4_Diagonal_Down_Left */ + if (!availableB) + return(HANTRO_NOK); + if (!availableC) + { + a[5] = a[6] = a[7] = a[8] = a[4]; + } + Intra4x4DiagonalDownLeftPrediction((u8*)data4x4, a + 1); + break; + case 4: /* Intra_4x4_Diagonal_Down_Right */ + if (!availableA || !availableB || !availableD) + return(HANTRO_NOK); + Intra4x4DiagonalDownRightPrediction((u8*)data4x4, a + 1, l + 1); + break; + case 5: /* Intra_4x4_Vertical_Right */ + if (!availableA || !availableB || !availableD) + return(HANTRO_NOK); + Intra4x4VerticalRightPrediction((u8*)data4x4, a + 1, l + 1); + break; + case 6: /* Intra_4x4_Horizontal_Down */ + if (!availableA || !availableB || !availableD) + return(HANTRO_NOK); + Intra4x4HorizontalDownPrediction((u8*)data4x4, a + 1, l + 1); + break; + case 7: /* Intra_4x4_Vertical_Left */ + if (!availableB) + return(HANTRO_NOK); + if (!availableC) + { + a[5] = a[6] = a[7] = a[8] = a[4]; + } + Intra4x4VerticalLeftPrediction((u8*)data4x4, a + 1); + break; + default: /* case 8 Intra_4x4_Horizontal_Up */ + if (!availableA) + return(HANTRO_NOK); + Intra4x4HorizontalUpPrediction((u8*)data4x4, l + 1); + break; + } + + Write4x4To16x16(data, (u8*)data4x4, block); + h264bsdAddResidual(data, mbLayer->residual.level[block], block); + } + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: IntraChromaPrediction + + Functional description: + Perform intra prediction for chroma pixels and add residual + into prediction. The resulting chroma pixels are stored in 'data'. + +------------------------------------------------------------------------------*/ + +u32 h264bsdIntraChromaPrediction(mbStorage_t *pMb, u8 *data, i32 residual[][16], + u8 *above, u8 *left, u32 predMode, u32 constrainedIntraPred) +{ + +/* Variables */ + + u32 i, comp, block; + u32 availableA, availableB, availableD; + +/* Code */ + + ASSERT(data); + ASSERT(residual); + ASSERT(above); + ASSERT(left); + ASSERT(predMode < 4); + + availableA = h264bsdIsNeighbourAvailable(pMb, pMb->mbA); + if (availableA && constrainedIntraPred && + (h264bsdMbPartPredMode(pMb->mbA->mbType) == PRED_MODE_INTER)) + availableA = HANTRO_FALSE; + availableB = h264bsdIsNeighbourAvailable(pMb, pMb->mbB); + if (availableB && constrainedIntraPred && + (h264bsdMbPartPredMode(pMb->mbB->mbType) == PRED_MODE_INTER)) + availableB = HANTRO_FALSE; + availableD = h264bsdIsNeighbourAvailable(pMb, pMb->mbD); + if (availableD && constrainedIntraPred && + (h264bsdMbPartPredMode(pMb->mbD->mbType) == PRED_MODE_INTER)) + availableD = HANTRO_FALSE; + + for (comp = 0, block = 16; comp < 2; comp++) + { + switch(predMode) + { + case 0: /* Intra_Chroma_DC */ + IntraChromaDcPrediction(data, above+1, left, availableA, + availableB); + break; + + case 1: /* Intra_Chroma_Horizontal */ + if (!availableA) + return(HANTRO_NOK); + IntraChromaHorizontalPrediction(data, left); + break; + + case 2: /* Intra_Chroma_Vertical */ + if (!availableB) + return(HANTRO_NOK); + IntraChromaVerticalPrediction(data, above+1); + + break; + + default: /* case 3: Intra_Chroma_Plane */ + if (!availableA || !availableB || !availableD) + return(HANTRO_NOK); + IntraChromaPlanePrediction(data, above+1, left); + break; + } + for (i = 0; i < 4; i++, block++) + h264bsdAddResidual(data, residual[i], block); + + /* advance pointers */ + data += 64; + above += 9; + left += 8; + residual += 4; + } + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdAddResidual + + Functional description: + Add residual of a block into prediction in macroblock array 'data'. + The result (residual + prediction) is stored in 'data'. + +------------------------------------------------------------------------------*/ +#ifndef H264DEC_OMXDL +void h264bsdAddResidual(u8 *data, i32 *residual, u32 blockNum) +{ + +/* Variables */ + + u32 i; + u32 x, y; + u32 width; + i32 tmp1, tmp2, tmp3, tmp4; + u8 *tmp; + const u8 *clp = h264bsdClip + 512; + +/* Code */ + + ASSERT(data); + ASSERT(residual); + ASSERT(blockNum < 16 + 4 + 4); + + if (IS_RESIDUAL_EMPTY(residual)) + return; + + RANGE_CHECK_ARRAY(residual, -512, 511, 16); + + if (blockNum < 16) + { + width = 16; + x = h264bsdBlockX[blockNum]; + y = h264bsdBlockY[blockNum]; + } + else + { + width = 8; + x = h264bsdBlockX[blockNum & 0x3]; + y = h264bsdBlockY[blockNum & 0x3]; + } + + tmp = data + y*width + x; + for (i = 4; i; i--) + { + tmp1 = *residual++; + tmp2 = tmp[0]; + tmp3 = *residual++; + tmp4 = tmp[1]; + + tmp[0] = clp[tmp1 + tmp2]; + + tmp1 = *residual++; + tmp2 = tmp[2]; + + tmp[1] = clp[tmp3 + tmp4]; + + tmp3 = *residual++; + tmp4 = tmp[3]; + + tmp1 = clp[tmp1 + tmp2]; + tmp3 = clp[tmp3 + tmp4]; + tmp[2] = (u8)tmp1; + tmp[3] = (u8)tmp3; + + tmp += width; + } + +} +#endif +/*------------------------------------------------------------------------------ + + Function: Intra16x16VerticalPrediction + + Functional description: + Perform intra 16x16 vertical prediction mode. + +------------------------------------------------------------------------------*/ + +void Intra16x16VerticalPrediction(u8 *data, u8 *above) +{ + +/* Variables */ + + u32 i, j; + +/* Code */ + + ASSERT(data); + ASSERT(above); + + for (i = 0; i < 16; i++) + { + for (j = 0; j < 16; j++) + { + *data++ = above[j]; + } + } + +} + +/*------------------------------------------------------------------------------ + + Function: Intra16x16HorizontalPrediction + + Functional description: + Perform intra 16x16 horizontal prediction mode. + +------------------------------------------------------------------------------*/ + +void Intra16x16HorizontalPrediction(u8 *data, u8 *left) +{ + +/* Variables */ + + u32 i, j; + +/* Code */ + + ASSERT(data); + ASSERT(left); + + for (i = 0; i < 16; i++) + { + for (j = 0; j < 16; j++) + { + *data++ = left[i]; + } + } + +} + +/*------------------------------------------------------------------------------ + + Function: Intra16x16DcPrediction + + Functional description: + Perform intra 16x16 DC prediction mode. + +------------------------------------------------------------------------------*/ + +void Intra16x16DcPrediction(u8 *data, u8 *above, u8 *left, u32 availableA, + u32 availableB) +{ + +/* Variables */ + + u32 i, tmp; + +/* Code */ + + ASSERT(data); + ASSERT(above); + ASSERT(left); + + if (availableA && availableB) + { + for (i = 0, tmp = 0; i < 16; i++) + tmp += above[i] + left[i]; + tmp = (tmp + 16) >> 5; + } + else if (availableA) + { + for (i = 0, tmp = 0; i < 16; i++) + tmp += left[i]; + tmp = (tmp + 8) >> 4; + } + else if (availableB) + { + for (i = 0, tmp = 0; i < 16; i++) + tmp += above[i]; + tmp = (tmp + 8) >> 4; + } + /* neither A nor B available */ + else + { + tmp = 128; + } + for (i = 0; i < 256; i++) + data[i] = (u8)tmp; + +} + +/*------------------------------------------------------------------------------ + + Function: Intra16x16PlanePrediction + + Functional description: + Perform intra 16x16 plane prediction mode. + +------------------------------------------------------------------------------*/ + +void Intra16x16PlanePrediction(u8 *data, u8 *above, u8 *left) +{ + +/* Variables */ + + u32 i, j; + i32 a, b, c; + i32 tmp; + +/* Code */ + + ASSERT(data); + ASSERT(above); + ASSERT(left); + + a = 16 * (above[15] + left[15]); + + for (i = 0, b = 0; i < 8; i++) + b += ((i32)i + 1) * (above[8+i] - above[6-i]); + b = (5 * b + 32) >> 6; + + for (i = 0, c = 0; i < 7; i++) + c += ((i32)i + 1) * (left[8+i] - left[6-i]); + /* p[-1,-1] has to be accessed through above pointer */ + c += ((i32)i + 1) * (left[8+i] - above[-1]); + c = (5 * c + 32) >> 6; + + for (i = 0; i < 16; i++) + { + for (j = 0; j < 16; j++) + { + tmp = (a + b * ((i32)j - 7) + c * ((i32)i - 7) + 16) >> 5; + data[i*16+j] = (u8)CLIP1(tmp); + } + } + +} + +/*------------------------------------------------------------------------------ + + Function: IntraChromaDcPrediction + + Functional description: + Perform intra chroma DC prediction mode. + +------------------------------------------------------------------------------*/ + +void IntraChromaDcPrediction(u8 *data, u8 *above, u8 *left, u32 availableA, + u32 availableB) +{ + +/* Variables */ + + u32 i; + u32 tmp1, tmp2; + +/* Code */ + + ASSERT(data); + ASSERT(above); + ASSERT(left); + + /* y = 0..3 */ + if (availableA && availableB) + { + tmp1 = above[0] + above[1] + above[2] + above[3] + + left[0] + left[1] + left[2] + left[3]; + tmp1 = (tmp1 + 4) >> 3; + tmp2 = (above[4] + above[5] + above[6] + above[7] + 2) >> 2; + } + else if (availableB) + { + tmp1 = (above[0] + above[1] + above[2] + above[3] + 2) >> 2; + tmp2 = (above[4] + above[5] + above[6] + above[7] + 2) >> 2; + } + else if (availableA) + { + tmp1 = (left[0] + left[1] + left[2] + left[3] + 2) >> 2; + tmp2 = tmp1; + } + /* neither A nor B available */ + else + { + tmp1 = tmp2 = 128; + } + + ASSERT(tmp1 < 256 && tmp2 < 256); + for (i = 4; i--;) + { + *data++ = (u8)tmp1; + *data++ = (u8)tmp1; + *data++ = (u8)tmp1; + *data++ = (u8)tmp1; + *data++ = (u8)tmp2; + *data++ = (u8)tmp2; + *data++ = (u8)tmp2; + *data++ = (u8)tmp2; + } + + /* y = 4...7 */ + if (availableA) + { + tmp1 = (left[4] + left[5] + left[6] + left[7] + 2) >> 2; + if (availableB) + { + tmp2 = above[4] + above[5] + above[6] + above[7] + + left[4] + left[5] + left[6] + left[7]; + tmp2 = (tmp2 + 4) >> 3; + } + else + tmp2 = tmp1; + } + else if (availableB) + { + tmp1 = (above[0] + above[1] + above[2] + above[3] + 2) >> 2; + tmp2 = (above[4] + above[5] + above[6] + above[7] + 2) >> 2; + } + else + { + tmp1 = tmp2 = 128; + } + + ASSERT(tmp1 < 256 && tmp2 < 256); + for (i = 4; i--;) + { + *data++ = (u8)tmp1; + *data++ = (u8)tmp1; + *data++ = (u8)tmp1; + *data++ = (u8)tmp1; + *data++ = (u8)tmp2; + *data++ = (u8)tmp2; + *data++ = (u8)tmp2; + *data++ = (u8)tmp2; + } +} + +/*------------------------------------------------------------------------------ + + Function: IntraChromaHorizontalPrediction + + Functional description: + Perform intra chroma horizontal prediction mode. + +------------------------------------------------------------------------------*/ + +void IntraChromaHorizontalPrediction(u8 *data, u8 *left) +{ + +/* Variables */ + + u32 i; + +/* Code */ + + ASSERT(data); + ASSERT(left); + + for (i = 8; i--;) + { + *data++ = *left; + *data++ = *left; + *data++ = *left; + *data++ = *left; + *data++ = *left; + *data++ = *left; + *data++ = *left; + *data++ = *left++; + } + +} + +/*------------------------------------------------------------------------------ + + Function: IntraChromaVerticalPrediction + + Functional description: + Perform intra chroma vertical prediction mode. + +------------------------------------------------------------------------------*/ + +void IntraChromaVerticalPrediction(u8 *data, u8 *above) +{ + +/* Variables */ + + u32 i; + +/* Code */ + + ASSERT(data); + ASSERT(above); + + for (i = 8; i--;data++/*above-=8*/) + { + data[0] = *above; + data[8] = *above; + data[16] = *above; + data[24] = *above; + data[32] = *above; + data[40] = *above; + data[48] = *above; + data[56] = *above++; + } + +} + +/*------------------------------------------------------------------------------ + + Function: IntraChromaPlanePrediction + + Functional description: + Perform intra chroma plane prediction mode. + +------------------------------------------------------------------------------*/ + +void IntraChromaPlanePrediction(u8 *data, u8 *above, u8 *left) +{ + +/* Variables */ + + u32 i; + i32 a, b, c; + i32 tmp; + const u8 *clp = h264bsdClip + 512; + +/* Code */ + + ASSERT(data); + ASSERT(above); + ASSERT(left); + + a = 16 * (above[7] + left[7]); + + b = (above[4] - above[2]) + 2 * (above[5] - above[1]) + + 3 * (above[6] - above[0]) + 4 * (above[7] - above[-1]); + b = (17 * b + 16) >> 5; + + /* p[-1,-1] has to be accessed through above pointer */ + c = (left[4] - left[2]) + 2 * (left[5] - left[1]) + + 3 * (left[6] - left[0]) + 4 * (left[7] - above[-1]); + c = (17 * c + 16) >> 5; + + /*a += 16;*/ + a = a - 3 * c + 16; + for (i = 8; i--; a += c) + { + tmp = (a - 3 * b); + *data++ = clp[tmp>>5]; + tmp += b; + *data++ = clp[tmp>>5]; + tmp += b; + *data++ = clp[tmp>>5]; + tmp += b; + *data++ = clp[tmp>>5]; + tmp += b; + *data++ = clp[tmp>>5]; + tmp += b; + *data++ = clp[tmp>>5]; + tmp += b; + *data++ = clp[tmp>>5]; + tmp += b; + *data++ = clp[tmp>>5]; + } + +} + +/*------------------------------------------------------------------------------ + + Function: Get4x4NeighbourPels + + Functional description: + Get neighbouring pixels of a 4x4 block into 'a' and 'l'. + +------------------------------------------------------------------------------*/ + +void Get4x4NeighbourPels(u8 *a, u8 *l, u8 *data, u8 *above, u8 *left, + u32 blockNum) +{ + +/* Variables */ + + u32 x, y; + u8 t1, t2; + +/* Code */ + + ASSERT(a); + ASSERT(l); + ASSERT(data); + ASSERT(above); + ASSERT(left); + ASSERT(blockNum < 16); + + x = h264bsdBlockX[blockNum]; + y = h264bsdBlockY[blockNum]; + + /* A and D */ + if (x == 0) + { + t1 = left[y ]; + t2 = left[y + 1]; + l[1] = t1; + l[2] = t2; + t1 = left[y + 2]; + t2 = left[y + 3]; + l[3] = t1; + l[4] = t2; + } + else + { + t1 = data[y * 16 + x - 1 ]; + t2 = data[y * 16 + x - 1 + 16]; + l[1] = t1; + l[2] = t2; + t1 = data[y * 16 + x - 1 + 32]; + t2 = data[y * 16 + x - 1 + 48]; + l[3] = t1; + l[4] = t2; + } + + /* B, C and D */ + if (y == 0) + { + t1 = above[x ]; + t2 = above[x ]; + l[0] = t1; + a[0] = t2; + t1 = above[x + 1]; + t2 = above[x + 2]; + a[1] = t1; + a[2] = t2; + t1 = above[x + 3]; + t2 = above[x + 4]; + a[3] = t1; + a[4] = t2; + t1 = above[x + 5]; + t2 = above[x + 6]; + a[5] = t1; + a[6] = t2; + t1 = above[x + 7]; + t2 = above[x + 8]; + a[7] = t1; + a[8] = t2; + } + else + { + t1 = data[(y - 1) * 16 + x ]; + t2 = data[(y - 1) * 16 + x + 1]; + a[1] = t1; + a[2] = t2; + t1 = data[(y - 1) * 16 + x + 2]; + t2 = data[(y - 1) * 16 + x + 3]; + a[3] = t1; + a[4] = t2; + t1 = data[(y - 1) * 16 + x + 4]; + t2 = data[(y - 1) * 16 + x + 5]; + a[5] = t1; + a[6] = t2; + t1 = data[(y - 1) * 16 + x + 6]; + t2 = data[(y - 1) * 16 + x + 7]; + a[7] = t1; + a[8] = t2; + + if (x == 0) + l[0] = a[0] = left[y-1]; + else + l[0] = a[0] = data[(y - 1) * 16 + x - 1]; + } +} + + +/*------------------------------------------------------------------------------ + + Function: Intra4x4VerticalPrediction + + Functional description: + Perform intra 4x4 vertical prediction mode. + +------------------------------------------------------------------------------*/ + +void Intra4x4VerticalPrediction(u8 *data, u8 *above) +{ + +/* Variables */ + + u8 t1, t2; + +/* Code */ + + ASSERT(data); + ASSERT(above); + + t1 = above[0]; + t2 = above[1]; + data[0] = data[4] = data[8] = data[12] = t1; + data[1] = data[5] = data[9] = data[13] = t2; + t1 = above[2]; + t2 = above[3]; + data[2] = data[6] = data[10] = data[14] = t1; + data[3] = data[7] = data[11] = data[15] = t2; + +} + +/*------------------------------------------------------------------------------ + + Function: Intra4x4HorizontalPrediction + + Functional description: + Perform intra 4x4 horizontal prediction mode. + +------------------------------------------------------------------------------*/ + +void Intra4x4HorizontalPrediction(u8 *data, u8 *left) +{ + +/* Variables */ + + u8 t1, t2; + +/* Code */ + + ASSERT(data); + ASSERT(left); + + t1 = left[0]; + t2 = left[1]; + data[0] = data[1] = data[2] = data[3] = t1; + data[4] = data[5] = data[6] = data[7] = t2; + t1 = left[2]; + t2 = left[3]; + data[8] = data[9] = data[10] = data[11] = t1; + data[12] = data[13] = data[14] = data[15] = t2; + +} + +/*------------------------------------------------------------------------------ + + Function: Intra4x4DcPrediction + + Functional description: + Perform intra 4x4 DC prediction mode. + +------------------------------------------------------------------------------*/ + +void Intra4x4DcPrediction(u8 *data, u8 *above, u8 *left, u32 availableA, + u32 availableB) +{ + +/* Variables */ + + u32 tmp; + u8 t1, t2, t3, t4; + +/* Code */ + + ASSERT(data); + ASSERT(above); + ASSERT(left); + + if (availableA && availableB) + { + t1 = above[0]; t2 = above[1]; t3 = above[2]; t4 = above[3]; + tmp = t1 + t2 + t3 + t4; + t1 = left[0]; t2 = left[1]; t3 = left[2]; t4 = left[3]; + tmp += t1 + t2 + t3 + t4; + tmp = (tmp + 4) >> 3; + } + else if (availableA) + { + t1 = left[0]; t2 = left[1]; t3 = left[2]; t4 = left[3]; + tmp = (t1 + t2 + t3 + t4 + 2) >> 2; + } + else if (availableB) + { + t1 = above[0]; t2 = above[1]; t3 = above[2]; t4 = above[3]; + tmp = (t1 + t2 + t3 + t4 + 2) >> 2; + } + else + { + tmp = 128; + } + + ASSERT(tmp < 256); + data[0] = data[1] = data[2] = data[3] = + data[4] = data[5] = data[6] = data[7] = + data[8] = data[9] = data[10] = data[11] = + data[12] = data[13] = data[14] = data[15] = (u8)tmp; + +} + +/*------------------------------------------------------------------------------ + + Function: Intra4x4DiagonalDownLeftPrediction + + Functional description: + Perform intra 4x4 diagonal down-left prediction mode. + +------------------------------------------------------------------------------*/ + +void Intra4x4DiagonalDownLeftPrediction(u8 *data, u8 *above) +{ + +/* Variables */ + +/* Code */ + + ASSERT(data); + ASSERT(above); + + data[ 0] = (above[0] + 2 * above[1] + above[2] + 2) >> 2; + data[ 1] = (above[1] + 2 * above[2] + above[3] + 2) >> 2; + data[ 4] = (above[1] + 2 * above[2] + above[3] + 2) >> 2; + data[ 2] = (above[2] + 2 * above[3] + above[4] + 2) >> 2; + data[ 5] = (above[2] + 2 * above[3] + above[4] + 2) >> 2; + data[ 8] = (above[2] + 2 * above[3] + above[4] + 2) >> 2; + data[ 3] = (above[3] + 2 * above[4] + above[5] + 2) >> 2; + data[ 6] = (above[3] + 2 * above[4] + above[5] + 2) >> 2; + data[ 9] = (above[3] + 2 * above[4] + above[5] + 2) >> 2; + data[12] = (above[3] + 2 * above[4] + above[5] + 2) >> 2; + data[ 7] = (above[4] + 2 * above[5] + above[6] + 2) >> 2; + data[10] = (above[4] + 2 * above[5] + above[6] + 2) >> 2; + data[13] = (above[4] + 2 * above[5] + above[6] + 2) >> 2; + data[11] = (above[5] + 2 * above[6] + above[7] + 2) >> 2; + data[14] = (above[5] + 2 * above[6] + above[7] + 2) >> 2; + data[15] = (above[6] + 3 * above[7] + 2) >> 2; + +} + +/*------------------------------------------------------------------------------ + + Function: Intra4x4DiagonalDownRightPrediction + + Functional description: + Perform intra 4x4 diagonal down-right prediction mode. + +------------------------------------------------------------------------------*/ + +void Intra4x4DiagonalDownRightPrediction(u8 *data, u8 *above, u8 *left) +{ + +/* Variables */ + +/* Code */ + + ASSERT(data); + ASSERT(above); + ASSERT(left); + + data[ 0] = (above[0] + 2 * above[-1] + left[0] + 2) >> 2; + data[ 5] = (above[0] + 2 * above[-1] + left[0] + 2) >> 2; + data[10] = (above[0] + 2 * above[-1] + left[0] + 2) >> 2; + data[15] = (above[0] + 2 * above[-1] + left[0] + 2) >> 2; + data[ 1] = (above[-1] + 2 * above[0] + above[1] + 2) >> 2; + data[ 6] = (above[-1] + 2 * above[0] + above[1] + 2) >> 2; + data[11] = (above[-1] + 2 * above[0] + above[1] + 2) >> 2; + data[ 2] = (above[0] + 2 * above[1] + above[2] + 2) >> 2; + data[ 7] = (above[0] + 2 * above[1] + above[2] + 2) >> 2; + data[ 3] = (above[1] + 2 * above[2] + above[3] + 2) >> 2; + data[ 4] = (left[-1] + 2 * left[0] + left[1] + 2) >> 2; + data[ 9] = (left[-1] + 2 * left[0] + left[1] + 2) >> 2; + data[14] = (left[-1] + 2 * left[0] + left[1] + 2) >> 2; + data[ 8] = (left[0] + 2 * left[1] + left[2] + 2) >> 2; + data[13] = (left[0] + 2 * left[1] + left[2] + 2) >> 2; + data[12] = (left[1] + 2 * left[2] + left[3] + 2) >> 2; +} + +/*------------------------------------------------------------------------------ + + Function: Intra4x4VerticalRightPrediction + + Functional description: + Perform intra 4x4 vertical right prediction mode. + +------------------------------------------------------------------------------*/ + +void Intra4x4VerticalRightPrediction(u8 *data, u8 *above, u8 *left) +{ + +/* Variables */ + +/* Code */ + + ASSERT(data); + ASSERT(above); + ASSERT(left); + + data[ 0] = (above[-1] + above[0] + 1) >> 1; + data[ 9] = (above[-1] + above[0] + 1) >> 1; + data[ 5] = (above[-1] + 2 * above[0] + above[1] + 2) >> 2; + data[14] = (above[-1] + 2 * above[0] + above[1] + 2) >> 2; + data[ 4] = (above[0] + 2 * above[-1] + left[0] + 2) >> 2; + data[13] = (above[0] + 2 * above[-1] + left[0] + 2) >> 2; + data[ 1] = (above[0] + above[1] + 1) >> 1; + data[10] = (above[0] + above[1] + 1) >> 1; + data[ 6] = (above[0] + 2 * above[1] + above[2] + 2) >> 2; + data[15] = (above[0] + 2 * above[1] + above[2] + 2) >> 2; + data[ 2] = (above[1] + above[2] + 1) >> 1; + data[11] = (above[1] + above[2] + 1) >> 1; + data[ 7] = (above[1] + 2 * above[2] + above[3] + 2) >> 2; + data[ 3] = (above[2] + above[3] + 1) >> 1; + data[ 8] = (left[1] + 2 * left[0] + left[-1] + 2) >> 2; + data[12] = (left[2] + 2 * left[1] + left[0] + 2) >> 2; + +} + +/*------------------------------------------------------------------------------ + + Function: Intra4x4HorizontalDownPrediction + + Functional description: + Perform intra 4x4 horizontal down prediction mode. + +------------------------------------------------------------------------------*/ + +void Intra4x4HorizontalDownPrediction(u8 *data, u8 *above, u8 *left) +{ + +/* Variables */ + +/* Code */ + + ASSERT(data); + ASSERT(above); + ASSERT(left); + + data[ 0] = (left[-1] + left[0] + 1) >> 1; + data[ 6] = (left[-1] + left[0] + 1) >> 1; + data[ 5] = (left[-1] + 2 * left[0] + left[1] + 2) >> 2; + data[11] = (left[-1] + 2 * left[0] + left[1] + 2) >> 2; + data[ 4] = (left[0] + left[1] + 1) >> 1; + data[10] = (left[0] + left[1] + 1) >> 1; + data[ 9] = (left[0] + 2 * left[1] + left[2] + 2) >> 2; + data[15] = (left[0] + 2 * left[1] + left[2] + 2) >> 2; + data[ 8] = (left[1] + left[2] + 1) >> 1; + data[14] = (left[1] + left[2] + 1) >> 1; + data[13] = (left[1] + 2 * left[2] + left[3] + 2) >> 2; + data[12] = (left[2] + left[3] + 1) >> 1; + data[ 1] = (above[0] + 2 * above[-1] + left[0] + 2) >> 2; + data[ 7] = (above[0] + 2 * above[-1] + left[0] + 2) >> 2; + data[ 2] = (above[1] + 2 * above[0] + above[-1] + 2) >> 2; + data[ 3] = (above[2] + 2 * above[1] + above[0] + 2) >> 2; +} + +/*------------------------------------------------------------------------------ + + Function: Intra4x4VerticalLeftPrediction + + Functional description: + Perform intra 4x4 vertical left prediction mode. + +------------------------------------------------------------------------------*/ + +void Intra4x4VerticalLeftPrediction(u8 *data, u8 *above) +{ + +/* Variables */ + +/* Code */ + + ASSERT(data); + ASSERT(above); + + data[ 0] = (above[0] + above[1] + 1) >> 1; + data[ 1] = (above[1] + above[2] + 1) >> 1; + data[ 2] = (above[2] + above[3] + 1) >> 1; + data[ 3] = (above[3] + above[4] + 1) >> 1; + data[ 4] = (above[0] + 2 * above[1] + above[2] + 2) >> 2; + data[ 5] = (above[1] + 2 * above[2] + above[3] + 2) >> 2; + data[ 6] = (above[2] + 2 * above[3] + above[4] + 2) >> 2; + data[ 7] = (above[3] + 2 * above[4] + above[5] + 2) >> 2; + data[ 8] = (above[1] + above[2] + 1) >> 1; + data[ 9] = (above[2] + above[3] + 1) >> 1; + data[10] = (above[3] + above[4] + 1) >> 1; + data[11] = (above[4] + above[5] + 1) >> 1; + data[12] = (above[1] + 2 * above[2] + above[3] + 2) >> 2; + data[13] = (above[2] + 2 * above[3] + above[4] + 2) >> 2; + data[14] = (above[3] + 2 * above[4] + above[5] + 2) >> 2; + data[15] = (above[4] + 2 * above[5] + above[6] + 2) >> 2; + +} + +/*------------------------------------------------------------------------------ + + Function: Intra4x4HorizontalUpPrediction + + Functional description: + Perform intra 4x4 horizontal up prediction mode. + +------------------------------------------------------------------------------*/ + +void Intra4x4HorizontalUpPrediction(u8 *data, u8 *left) +{ + +/* Variables */ + +/* Code */ + + ASSERT(data); + ASSERT(left); + + data[ 0] = (left[0] + left[1] + 1) >> 1; + data[ 1] = (left[0] + 2 * left[1] + left[2] + 2) >> 2; + data[ 2] = (left[1] + left[2] + 1) >> 1; + data[ 3] = (left[1] + 2 * left[2] + left[3] + 2) >> 2; + data[ 4] = (left[1] + left[2] + 1) >> 1; + data[ 5] = (left[1] + 2 * left[2] + left[3] + 2) >> 2; + data[ 6] = (left[2] + left[3] + 1) >> 1; + data[ 7] = (left[2] + 3 * left[3] + 2) >> 2; + data[ 8] = (left[2] + left[3] + 1) >> 1; + data[ 9] = (left[2] + 3 * left[3] + 2) >> 2; + data[10] = left[3]; + data[11] = left[3]; + data[12] = left[3]; + data[13] = left[3]; + data[14] = left[3]; + data[15] = left[3]; + +} + +#endif /* H264DEC_OMXDL */ + +/*------------------------------------------------------------------------------ + + Function: Write4x4To16x16 + + Functional description: + Write a 4x4 block (data4x4) into correct position + in 16x16 macroblock (data). + +------------------------------------------------------------------------------*/ + +void Write4x4To16x16(u8 *data, u8 *data4x4, u32 blockNum) +{ + +/* Variables */ + + u32 x, y; + u32 *in32, *out32; + +/* Code */ + + ASSERT(data); + ASSERT(data4x4); + ASSERT(blockNum < 16); + + x = h264bsdBlockX[blockNum]; + y = h264bsdBlockY[blockNum]; + + data += y*16+x; + + ASSERT(((u32)data&0x3) == 0); + + /*lint --e(826) */ + out32 = (u32 *)data; + /*lint --e(826) */ + in32 = (u32 *)data4x4; + + out32[0] = *in32++; + out32[4] = *in32++; + out32[8] = *in32++; + out32[12] = *in32++; +} + +/*------------------------------------------------------------------------------ + + Function: DetermineIntra4x4PredMode + + Functional description: + Returns the intra 4x4 prediction mode of a block based on the + neighbouring macroblocks and information parsed from stream. + +------------------------------------------------------------------------------*/ + +u32 DetermineIntra4x4PredMode(macroblockLayer_t *pMbLayer, + u32 available, neighbour_t *nA, neighbour_t *nB, u32 index, + mbStorage_t *nMbA, mbStorage_t *nMbB) +{ + +/* Variables */ + + u32 mode1, mode2; + mbStorage_t *pMb; + +/* Code */ + + ASSERT(pMbLayer); + + /* dc only prediction? */ + if (!available) + mode1 = 2; + else + { + pMb = nMbA; + if (h264bsdMbPartPredMode(pMb->mbType) == PRED_MODE_INTRA4x4) + { + mode1 = pMb->intra4x4PredMode[nA->index]; + } + else + mode1 = 2; + + pMb = nMbB; + if (h264bsdMbPartPredMode(pMb->mbType) == PRED_MODE_INTRA4x4) + { + mode2 = pMb->intra4x4PredMode[nB->index]; + } + else + mode2 = 2; + + mode1 = MIN(mode1, mode2); + } + + if (!pMbLayer->mbPred.prevIntra4x4PredModeFlag[index]) + { + if (pMbLayer->mbPred.remIntra4x4PredMode[index] < mode1) + { + mode1 = pMbLayer->mbPred.remIntra4x4PredMode[index]; + } + else + { + mode1 = pMbLayer->mbPred.remIntra4x4PredMode[index] + 1; + } + } + + return(mode1); +} + + +/*lint +e702 */ + + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_intra_prediction.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_intra_prediction.h new file mode 100755 index 0000000..4652bd5 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_intra_prediction.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. Module defines + 3. Data types + 4. Function prototypes + +------------------------------------------------------------------------------*/ + +#ifndef H264SWDEC_INTRA_PREDICTION_H +#define H264SWDEC_INTRA_PREDICTION_H + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "basetype.h" +#include "h264bsd_image.h" +#include "h264bsd_macroblock_layer.h" + +/*------------------------------------------------------------------------------ + 2. Module defines +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 3. Data types +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ +#ifndef H264DEC_OMXDL +u32 h264bsdIntraPrediction(mbStorage_t *pMb, macroblockLayer_t *mbLayer, + image_t *image, u32 mbNum, u32 constrainedIntraPred, u8 *data); + +u32 h264bsdIntra4x4Prediction(mbStorage_t *pMb, u8 *data, + macroblockLayer_t *mbLayer, + u8 *above, u8 *left, u32 constrainedIntraPred); +u32 h264bsdIntra16x16Prediction(mbStorage_t *pMb, u8 *data, i32 residual[][16], + u8 *above, u8 *left, u32 constrainedIntraPred); + +u32 h264bsdIntraChromaPrediction(mbStorage_t *pMb, u8 *data, i32 residual[][16], + u8 *above, u8 *left, u32 predMode, u32 constrainedIntraPred); + +void h264bsdGetNeighbourPels(image_t *image, u8 *above, u8 *left, u32 mbNum); + +#else + +u32 h264bsdIntra4x4Prediction(mbStorage_t *pMb, u8 *data, + macroblockLayer_t *mbLayer, + u8 *pImage, u32 width, + u32 constrainedIntraPred, u32 block); + +u32 h264bsdIntra16x16Prediction(mbStorage_t *pMb, u8 *data, u8 *pImage, + u32 width, u32 constrainedIntraPred); + +u32 h264bsdIntraChromaPrediction(mbStorage_t *pMb, u8 *data, image_t *image, + u32 predMode, u32 constrainedIntraPred); + +#endif + +#endif /* #ifdef H264SWDEC_INTRA_PREDICTION_H */ + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_macroblock_layer.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_macroblock_layer.c new file mode 100755 index 0000000..2b3e7f0 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_macroblock_layer.c @@ -0,0 +1,1446 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. External compiler flags + 3. Module defines + 4. Local function prototypes + 5. Functions + h264bsdDecodeMacroblockLayer + h264bsdMbPartPredMode + h264bsdNumMbPart + h264bsdNumSubMbPart + DecodeMbPred + DecodeSubMbPred + DecodeResidual + DetermineNc + CbpIntra16x16 + h264bsdPredModeIntra16x16 + h264bsdDecodeMacroblock + ProcessResidual + h264bsdSubMbPartMode + +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "h264bsd_macroblock_layer.h" +#include "h264bsd_slice_header.h" +#include "h264bsd_util.h" +#include "h264bsd_vlc.h" +#include "h264bsd_cavlc.h" +#include "h264bsd_nal_unit.h" +#include "h264bsd_neighbour.h" +#include "h264bsd_transform.h" +#include "h264bsd_intra_prediction.h" +#include "h264bsd_inter_prediction.h" + +#ifdef H264DEC_OMXDL +#include "omxtypes.h" +#include "omxVC.h" +#include "armVC.h" +#endif /* H264DEC_OMXDL */ + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ +#ifdef H264DEC_OMXDL +static const u32 chromaIndex[8] = { 256, 260, 288, 292, 320, 324, 352, 356 }; +static const u32 lumaIndex[16] = { 0, 4, 64, 68, + 8, 12, 72, 76, + 128, 132, 192, 196, + 136, 140, 200, 204 }; +#endif +/* mapping of dc coefficients array to luma blocks */ +static const u32 dcCoeffIndex[16] = + {0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15}; + +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ + +static u32 DecodeMbPred(strmData_t *pStrmData, mbPred_t *pMbPred, + mbType_e mbType, u32 numRefIdxActive); +static u32 DecodeSubMbPred(strmData_t *pStrmData, subMbPred_t *pSubMbPred, + mbType_e mbType, u32 numRefIdxActive); +static u32 DecodeResidual(strmData_t *pStrmData, residual_t *pResidual, + mbStorage_t *pMb, mbType_e mbType, u32 codedBlockPattern); + +#ifdef H264DEC_OMXDL +static u32 DetermineNc(mbStorage_t *pMb, u32 blockIndex, u8 *pTotalCoeff); +#else +static u32 DetermineNc(mbStorage_t *pMb, u32 blockIndex, i16 *pTotalCoeff); +#endif + +static u32 CbpIntra16x16(mbType_e mbType); +#ifdef H264DEC_OMXDL +static u32 ProcessIntra4x4Residual(mbStorage_t *pMb, u8 *data, u32 constrainedIntraPred, + macroblockLayer_t *mbLayer, const u8 **pSrc, image_t *image); +static u32 ProcessChromaResidual(mbStorage_t *pMb, u8 *data, const u8 **pSrc ); +static u32 ProcessIntra16x16Residual(mbStorage_t *pMb, u8 *data, u32 constrainedIntraPred, + u32 intraChromaPredMode, const u8 **pSrc, image_t *image); + + +#else +static u32 ProcessResidual(mbStorage_t *pMb, i32 residualLevel[][16], u32 *); +#endif + +/*------------------------------------------------------------------------------ + + Function name: h264bsdDecodeMacroblockLayer + + Functional description: + Parse macroblock specific information from bit stream. + + Inputs: + pStrmData pointer to stream data structure + pMb pointer to macroblock storage structure + sliceType type of the current slice + numRefIdxActive maximum reference index + + Outputs: + pMbLayer stores the macroblock data parsed from stream + + Returns: + HANTRO_OK success + HANTRO_NOK end of stream or error in stream + +------------------------------------------------------------------------------*/ + +u32 h264bsdDecodeMacroblockLayer(strmData_t *pStrmData, + macroblockLayer_t *pMbLayer, mbStorage_t *pMb, u32 sliceType, + u32 numRefIdxActive) +{ + +/* Variables */ + + u32 tmp, i, value; + i32 itmp; + mbPartPredMode_e partMode; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pMbLayer); + +#ifdef H264DEC_NEON + h264bsdClearMbLayer(pMbLayer, ((sizeof(macroblockLayer_t) + 63) & ~0x3F)); +#else + H264SwDecMemset(pMbLayer, 0, sizeof(macroblockLayer_t)); +#endif + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); + + if (IS_I_SLICE(sliceType)) + { + if ((value + 6) > 31 || tmp != HANTRO_OK) + return(HANTRO_NOK); + pMbLayer->mbType = (mbType_e)(value + 6); + } + else + { + if ((value + 1) > 31 || tmp != HANTRO_OK) + return(HANTRO_NOK); + pMbLayer->mbType = (mbType_e)(value + 1); + } + + if (pMbLayer->mbType == I_PCM) + { + i32 *level; + while( !h264bsdIsByteAligned(pStrmData) ) + { + /* pcm_alignment_zero_bit */ + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp) + return(HANTRO_NOK); + } + + level = pMbLayer->residual.level[0]; + for (i = 0; i < 384; i++) + { + value = h264bsdGetBits(pStrmData, 8); + if (value == END_OF_STREAM) + return(HANTRO_NOK); + *level++ = (i32)value; + } + } + else + { + partMode = h264bsdMbPartPredMode(pMbLayer->mbType); + if ( (partMode == PRED_MODE_INTER) && + (h264bsdNumMbPart(pMbLayer->mbType) == 4) ) + { + tmp = DecodeSubMbPred(pStrmData, &pMbLayer->subMbPred, + pMbLayer->mbType, numRefIdxActive); + } + else + { + tmp = DecodeMbPred(pStrmData, &pMbLayer->mbPred, + pMbLayer->mbType, numRefIdxActive); + } + if (tmp != HANTRO_OK) + return(tmp); + + if (partMode != PRED_MODE_INTRA16x16) + { + tmp = h264bsdDecodeExpGolombMapped(pStrmData, &value, + (u32)(partMode == PRED_MODE_INTRA4x4)); + if (tmp != HANTRO_OK) + return(tmp); + pMbLayer->codedBlockPattern = value; + } + else + { + pMbLayer->codedBlockPattern = CbpIntra16x16(pMbLayer->mbType); + } + + if ( pMbLayer->codedBlockPattern || + (partMode == PRED_MODE_INTRA16x16) ) + { + tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp); + if (tmp != HANTRO_OK || (itmp < -26) || (itmp > 25) ) + return(HANTRO_NOK); + pMbLayer->mbQpDelta = itmp; + + tmp = DecodeResidual(pStrmData, &pMbLayer->residual, pMb, + pMbLayer->mbType, pMbLayer->codedBlockPattern); + + pStrmData->strmBuffReadBits = + (u32)(pStrmData->pStrmCurrPos - pStrmData->pStrmBuffStart) * 8 + + pStrmData->bitPosInWord; + + if (tmp != HANTRO_OK) + return(tmp); + } + } + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdMbPartPredMode + + Functional description: + Returns the prediction mode of a macroblock type + +------------------------------------------------------------------------------*/ + +mbPartPredMode_e h264bsdMbPartPredMode(mbType_e mbType) +{ + +/* Variables */ + + +/* Code */ + + ASSERT(mbType <= 31); + + if ((mbType <= P_8x8ref0)) + return(PRED_MODE_INTER); + else if (mbType == I_4x4) + return(PRED_MODE_INTRA4x4); + else + return(PRED_MODE_INTRA16x16); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdNumMbPart + + Functional description: + Returns the amount of macroblock partitions in a macroblock type + +------------------------------------------------------------------------------*/ + +u32 h264bsdNumMbPart(mbType_e mbType) +{ + +/* Variables */ + + +/* Code */ + + ASSERT(h264bsdMbPartPredMode(mbType) == PRED_MODE_INTER); + + switch (mbType) + { + case P_L0_16x16: + case P_Skip: + return(1); + + case P_L0_L0_16x8: + case P_L0_L0_8x16: + return(2); + + /* P_8x8 or P_8x8ref0 */ + default: + return(4); + } + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdNumSubMbPart + + Functional description: + Returns the amount of sub-partitions in a sub-macroblock type + +------------------------------------------------------------------------------*/ + +u32 h264bsdNumSubMbPart(subMbType_e subMbType) +{ + +/* Variables */ + + +/* Code */ + + ASSERT(subMbType <= P_L0_4x4); + + switch (subMbType) + { + case P_L0_8x8: + return(1); + + case P_L0_8x4: + case P_L0_4x8: + return(2); + + /* P_L0_4x4 */ + default: + return(4); + } + +} + +/*------------------------------------------------------------------------------ + + Function: DecodeMbPred + + Functional description: + Parse macroblock prediction information from bit stream and store + in 'pMbPred'. + +------------------------------------------------------------------------------*/ + +u32 DecodeMbPred(strmData_t *pStrmData, mbPred_t *pMbPred, mbType_e mbType, + u32 numRefIdxActive) +{ + +/* Variables */ + + u32 tmp, i, j, value; + i32 itmp; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pMbPred); + + switch (h264bsdMbPartPredMode(mbType)) + { + case PRED_MODE_INTER: /* PRED_MODE_INTER */ + if (numRefIdxActive > 1) + { + for (i = h264bsdNumMbPart(mbType), j = 0; i--; j++) + { + tmp = h264bsdDecodeExpGolombTruncated(pStrmData, &value, + (u32)(numRefIdxActive > 2)); + if (tmp != HANTRO_OK || value >= numRefIdxActive) + return(HANTRO_NOK); + + pMbPred->refIdxL0[j] = value; + } + } + + for (i = h264bsdNumMbPart(mbType), j = 0; i--; j++) + { + tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp); + if (tmp != HANTRO_OK) + return(tmp); + pMbPred->mvdL0[j].hor = (i16)itmp; + + tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp); + if (tmp != HANTRO_OK) + return(tmp); + pMbPred->mvdL0[j].ver = (i16)itmp; + } + break; + + case PRED_MODE_INTRA4x4: + for (itmp = 0, i = 0; itmp < 2; itmp++) + { + value = h264bsdShowBits32(pStrmData); + tmp = 0; + for (j = 8; j--; i++) + { + pMbPred->prevIntra4x4PredModeFlag[i] = + value & 0x80000000 ? HANTRO_TRUE : HANTRO_FALSE; + value <<= 1; + if (!pMbPred->prevIntra4x4PredModeFlag[i]) + { + pMbPred->remIntra4x4PredMode[i] = value>>29; + value <<= 3; + tmp++; + } + } + if (h264bsdFlushBits(pStrmData, 8 + 3*tmp) == END_OF_STREAM) + return(HANTRO_NOK); + } + /* fall-through */ + + case PRED_MODE_INTRA16x16: + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); + if (tmp != HANTRO_OK || value > 3) + return(HANTRO_NOK); + pMbPred->intraChromaPredMode = value; + break; + } + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: DecodeSubMbPred + + Functional description: + Parse sub-macroblock prediction information from bit stream and + store in 'pMbPred'. + +------------------------------------------------------------------------------*/ + +u32 DecodeSubMbPred(strmData_t *pStrmData, subMbPred_t *pSubMbPred, + mbType_e mbType, u32 numRefIdxActive) +{ + +/* Variables */ + + u32 tmp, i, j, value; + i32 itmp; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pSubMbPred); + ASSERT(h264bsdMbPartPredMode(mbType) == PRED_MODE_INTER); + + for (i = 0; i < 4; i++) + { + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); + if (tmp != HANTRO_OK || value > 3) + return(HANTRO_NOK); + pSubMbPred->subMbType[i] = (subMbType_e)value; + } + + if ( (numRefIdxActive > 1) && (mbType != P_8x8ref0) ) + { + for (i = 0; i < 4; i++) + { + tmp = h264bsdDecodeExpGolombTruncated(pStrmData, &value, + (u32)(numRefIdxActive > 2)); + if (tmp != HANTRO_OK || value >= numRefIdxActive) + return(HANTRO_NOK); + pSubMbPred->refIdxL0[i] = value; + } + } + + for (i = 0; i < 4; i++) + { + j = 0; + for (value = h264bsdNumSubMbPart(pSubMbPred->subMbType[i]); + value--; j++) + { + tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp); + if (tmp != HANTRO_OK) + return(tmp); + pSubMbPred->mvdL0[i][j].hor = (i16)itmp; + + tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp); + if (tmp != HANTRO_OK) + return(tmp); + pSubMbPred->mvdL0[i][j].ver = (i16)itmp; + } + } + + return(HANTRO_OK); + +} + +#ifdef H264DEC_OMXDL +/*------------------------------------------------------------------------------ + + Function: DecodeResidual + + Functional description: + Parse residual information from bit stream and store in 'pResidual'. + +------------------------------------------------------------------------------*/ + +u32 DecodeResidual(strmData_t *pStrmData, residual_t *pResidual, + mbStorage_t *pMb, mbType_e mbType, u32 codedBlockPattern) +{ + +/* Variables */ + + u32 i, j; + u32 blockCoded; + u32 blockIndex; + u32 is16x16; + OMX_INT nc; + OMXResult omxRes; + OMX_U8 *pPosCoefBuf; + + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pResidual); + + pPosCoefBuf = pResidual->posCoefBuf; + + /* luma DC is at index 24 */ + if (h264bsdMbPartPredMode(mbType) == PRED_MODE_INTRA16x16) + { + nc = (OMX_INT)DetermineNc(pMb, 0, pResidual->totalCoeff); +#ifndef H264DEC_NEON + omxRes = omxVCM4P10_DecodeCoeffsToPairCAVLC( + (const OMX_U8 **) (&pStrmData->pStrmCurrPos), + (OMX_S32*) (&pStrmData->bitPosInWord), + &pResidual->totalCoeff[24], + &pPosCoefBuf, + nc, + 16); +#else + omxRes = armVCM4P10_DecodeCoeffsToPair( + (const OMX_U8 **) (&pStrmData->pStrmCurrPos), + (OMX_S32*) (&pStrmData->bitPosInWord), + &pResidual->totalCoeff[24], + &pPosCoefBuf, + nc, + 16); +#endif + if (omxRes != OMX_Sts_NoErr) + return(HANTRO_NOK); + is16x16 = HANTRO_TRUE; + } + else + is16x16 = HANTRO_FALSE; + + for (i = 4, blockIndex = 0; i--;) + { + /* luma cbp in bits 0-3 */ + blockCoded = codedBlockPattern & 0x1; + codedBlockPattern >>= 1; + if (blockCoded) + { + for (j = 4; j--; blockIndex++) + { + nc = (OMX_INT)DetermineNc(pMb,blockIndex,pResidual->totalCoeff); + if (is16x16) + { +#ifndef H264DEC_NEON + omxRes = omxVCM4P10_DecodeCoeffsToPairCAVLC( + (const OMX_U8 **) (&pStrmData->pStrmCurrPos), + (OMX_S32*) (&pStrmData->bitPosInWord), + &pResidual->totalCoeff[blockIndex], + &pPosCoefBuf, + nc, + 15); +#else + omxRes = armVCM4P10_DecodeCoeffsToPair( + (const OMX_U8 **) (&pStrmData->pStrmCurrPos), + (OMX_S32*) (&pStrmData->bitPosInWord), + &pResidual->totalCoeff[blockIndex], + &pPosCoefBuf, + nc, + 15); +#endif + } + else + { +#ifndef H264DEC_NEON + omxRes = omxVCM4P10_DecodeCoeffsToPairCAVLC( + (const OMX_U8 **) (&pStrmData->pStrmCurrPos), + (OMX_S32*) (&pStrmData->bitPosInWord), + &pResidual->totalCoeff[blockIndex], + &pPosCoefBuf, + nc, + 16); +#else + omxRes = armVCM4P10_DecodeCoeffsToPair( + (const OMX_U8 **) (&pStrmData->pStrmCurrPos), + (OMX_S32*) (&pStrmData->bitPosInWord), + &pResidual->totalCoeff[blockIndex], + &pPosCoefBuf, + nc, + 16); +#endif + } + if (omxRes != OMX_Sts_NoErr) + return(HANTRO_NOK); + } + } + else + blockIndex += 4; + } + + /* chroma DC block are at indices 25 and 26 */ + blockCoded = codedBlockPattern & 0x3; + if (blockCoded) + { +#ifndef H264DEC_NEON + omxRes = omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC( + (const OMX_U8**) (&pStrmData->pStrmCurrPos), + (OMX_S32*) (&pStrmData->bitPosInWord), + &pResidual->totalCoeff[25], + &pPosCoefBuf); +#else + omxRes = armVCM4P10_DecodeCoeffsToPair( + (const OMX_U8**) (&pStrmData->pStrmCurrPos), + (OMX_S32*) (&pStrmData->bitPosInWord), + &pResidual->totalCoeff[25], + &pPosCoefBuf, + 17, + 4); +#endif + if (omxRes != OMX_Sts_NoErr) + return(HANTRO_NOK); +#ifndef H264DEC_NEON + omxRes = omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC( + (const OMX_U8**) (&pStrmData->pStrmCurrPos), + (OMX_S32*) (&pStrmData->bitPosInWord), + &pResidual->totalCoeff[26], + &pPosCoefBuf); +#else + omxRes = armVCM4P10_DecodeCoeffsToPair( + (const OMX_U8**) (&pStrmData->pStrmCurrPos), + (OMX_S32*) (&pStrmData->bitPosInWord), + &pResidual->totalCoeff[26], + &pPosCoefBuf, + 17, + 4); +#endif + if (omxRes != OMX_Sts_NoErr) + return(HANTRO_NOK); + } + + /* chroma AC */ + blockCoded = codedBlockPattern & 0x2; + if (blockCoded) + { + for (i = 8; i--;blockIndex++) + { + nc = (OMX_INT)DetermineNc(pMb, blockIndex, pResidual->totalCoeff); +#ifndef H264DEC_NEON + omxRes = omxVCM4P10_DecodeCoeffsToPairCAVLC( + (const OMX_U8 **) (&pStrmData->pStrmCurrPos), + (OMX_S32*) (&pStrmData->bitPosInWord), + &pResidual->totalCoeff[blockIndex], + &pPosCoefBuf, + nc, + 15); +#else + omxRes = armVCM4P10_DecodeCoeffsToPair( + (const OMX_U8 **) (&pStrmData->pStrmCurrPos), + (OMX_S32*) (&pStrmData->bitPosInWord), + &pResidual->totalCoeff[blockIndex], + &pPosCoefBuf, + nc, + 15); +#endif + if (omxRes != OMX_Sts_NoErr) + return(HANTRO_NOK); + } + } + + return(HANTRO_OK); + +} + +#else +/*------------------------------------------------------------------------------ + + Function: DecodeResidual + + Functional description: + Parse residual information from bit stream and store in 'pResidual'. + +------------------------------------------------------------------------------*/ + +u32 DecodeResidual(strmData_t *pStrmData, residual_t *pResidual, + mbStorage_t *pMb, mbType_e mbType, u32 codedBlockPattern) +{ + +/* Variables */ + + u32 i, j, tmp; + i32 nc; + u32 blockCoded; + u32 blockIndex; + u32 is16x16; + i32 (*level)[16]; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pResidual); + + level = pResidual->level; + + /* luma DC is at index 24 */ + if (h264bsdMbPartPredMode(mbType) == PRED_MODE_INTRA16x16) + { + nc = (i32)DetermineNc(pMb, 0, pResidual->totalCoeff); + tmp = h264bsdDecodeResidualBlockCavlc(pStrmData, level[24], nc, 16); + if ((tmp & 0xF) != HANTRO_OK) + return(tmp); + pResidual->totalCoeff[24] = (tmp >> 4) & 0xFF; + is16x16 = HANTRO_TRUE; + } + else + is16x16 = HANTRO_FALSE; + + for (i = 4, blockIndex = 0; i--;) + { + /* luma cbp in bits 0-3 */ + blockCoded = codedBlockPattern & 0x1; + codedBlockPattern >>= 1; + if (blockCoded) + { + for (j = 4; j--; blockIndex++) + { + nc = (i32)DetermineNc(pMb, blockIndex, pResidual->totalCoeff); + if (is16x16) + { + tmp = h264bsdDecodeResidualBlockCavlc(pStrmData, + level[blockIndex] + 1, nc, 15); + pResidual->coeffMap[blockIndex] = tmp >> 15; + } + else + { + tmp = h264bsdDecodeResidualBlockCavlc(pStrmData, + level[blockIndex], nc, 16); + pResidual->coeffMap[blockIndex] = tmp >> 16; + } + if ((tmp & 0xF) != HANTRO_OK) + return(tmp); + pResidual->totalCoeff[blockIndex] = (tmp >> 4) & 0xFF; + } + } + else + blockIndex += 4; + } + + /* chroma DC block are at indices 25 and 26 */ + blockCoded = codedBlockPattern & 0x3; + if (blockCoded) + { + tmp = h264bsdDecodeResidualBlockCavlc(pStrmData, level[25], -1, 4); + if ((tmp & 0xF) != HANTRO_OK) + return(tmp); + pResidual->totalCoeff[25] = (tmp >> 4) & 0xFF; + tmp = h264bsdDecodeResidualBlockCavlc(pStrmData, level[25]+4, -1, 4); + if ((tmp & 0xF) != HANTRO_OK) + return(tmp); + pResidual->totalCoeff[26] = (tmp >> 4) & 0xFF; + } + + /* chroma AC */ + blockCoded = codedBlockPattern & 0x2; + if (blockCoded) + { + for (i = 8; i--;blockIndex++) + { + nc = (i32)DetermineNc(pMb, blockIndex, pResidual->totalCoeff); + tmp = h264bsdDecodeResidualBlockCavlc(pStrmData, + level[blockIndex] + 1, nc, 15); + if ((tmp & 0xF) != HANTRO_OK) + return(tmp); + pResidual->totalCoeff[blockIndex] = (tmp >> 4) & 0xFF; + pResidual->coeffMap[blockIndex] = (tmp >> 15); + } + } + + return(HANTRO_OK); + +} +#endif + +/*------------------------------------------------------------------------------ + + Function: DetermineNc + + Functional description: + Returns the nC of a block. + +------------------------------------------------------------------------------*/ +#ifdef H264DEC_OMXDL +u32 DetermineNc(mbStorage_t *pMb, u32 blockIndex, u8 *pTotalCoeff) +#else +u32 DetermineNc(mbStorage_t *pMb, u32 blockIndex, i16 *pTotalCoeff) +#endif +{ +/*lint -e702 */ +/* Variables */ + + u32 tmp; + i32 n; + const neighbour_t *neighbourA, *neighbourB; + u8 neighbourAindex, neighbourBindex; + +/* Code */ + + ASSERT(blockIndex < 24); + + /* if neighbour block belongs to current macroblock totalCoeff array + * mbStorage has not been set/updated yet -> use pTotalCoeff */ + neighbourA = h264bsdNeighbour4x4BlockA(blockIndex); + neighbourB = h264bsdNeighbour4x4BlockB(blockIndex); + neighbourAindex = neighbourA->index; + neighbourBindex = neighbourB->index; + if (neighbourA->mb == MB_CURR && neighbourB->mb == MB_CURR) + { + n = (pTotalCoeff[neighbourAindex] + + pTotalCoeff[neighbourBindex] + 1)>>1; + } + else if (neighbourA->mb == MB_CURR) + { + n = pTotalCoeff[neighbourAindex]; + if (h264bsdIsNeighbourAvailable(pMb, pMb->mbB)) + { + n = (n + pMb->mbB->totalCoeff[neighbourBindex] + 1) >> 1; + } + } + else if (neighbourB->mb == MB_CURR) + { + n = pTotalCoeff[neighbourBindex]; + if (h264bsdIsNeighbourAvailable(pMb, pMb->mbA)) + { + n = (n + pMb->mbA->totalCoeff[neighbourAindex] + 1) >> 1; + } + } + else + { + n = tmp = 0; + if (h264bsdIsNeighbourAvailable(pMb, pMb->mbA)) + { + n = pMb->mbA->totalCoeff[neighbourAindex]; + tmp = 1; + } + if (h264bsdIsNeighbourAvailable(pMb, pMb->mbB)) + { + if (tmp) + n = (n + pMb->mbB->totalCoeff[neighbourBindex] + 1) >> 1; + else + n = pMb->mbB->totalCoeff[neighbourBindex]; + } + } + return((u32)n); +/*lint +e702 */ +} + +/*------------------------------------------------------------------------------ + + Function: CbpIntra16x16 + + Functional description: + Returns the coded block pattern for intra 16x16 macroblock. + +------------------------------------------------------------------------------*/ + +u32 CbpIntra16x16(mbType_e mbType) +{ + +/* Variables */ + + u32 cbp; + u32 tmp; + +/* Code */ + + ASSERT(mbType >= I_16x16_0_0_0 && mbType <= I_16x16_3_2_1); + + if (mbType >= I_16x16_0_0_1) + cbp = 15; + else + cbp = 0; + + /* tmp is 0 for I_16x16_0_0_0 mb type */ + /* ignore lint warning on arithmetic on enum's */ + tmp = /*lint -e(656)*/(mbType - I_16x16_0_0_0) >> 2; + if (tmp > 2) + tmp -= 3; + + cbp += tmp << 4; + + return(cbp); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdPredModeIntra16x16 + + Functional description: + Returns the prediction mode for intra 16x16 macroblock. + +------------------------------------------------------------------------------*/ + +u32 h264bsdPredModeIntra16x16(mbType_e mbType) +{ + +/* Variables */ + + u32 tmp; + +/* Code */ + + ASSERT(mbType >= I_16x16_0_0_0 && mbType <= I_16x16_3_2_1); + + /* tmp is 0 for I_16x16_0_0_0 mb type */ + /* ignore lint warning on arithmetic on enum's */ + tmp = /*lint -e(656)*/(mbType - I_16x16_0_0_0); + + return(tmp & 0x3); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdDecodeMacroblock + + Functional description: + Decode one macroblock and write into output image. + + Inputs: + pMb pointer to macroblock specific information + mbLayer pointer to current macroblock data from stream + currImage pointer to output image + dpb pointer to decoded picture buffer + qpY pointer to slice QP + mbNum current macroblock number + constrainedIntraPred flag specifying if neighbouring inter + macroblocks are used in intra prediction + + Outputs: + pMb structure is updated with current macroblock + currImage decoded macroblock is written into output image + + Returns: + HANTRO_OK success + HANTRO_NOK error in macroblock decoding + +------------------------------------------------------------------------------*/ + +u32 h264bsdDecodeMacroblock(mbStorage_t *pMb, macroblockLayer_t *pMbLayer, + image_t *currImage, dpbStorage_t *dpb, i32 *qpY, u32 mbNum, + u32 constrainedIntraPredFlag, u8* data) +{ + +/* Variables */ + + u32 i, tmp; + mbType_e mbType; +#ifdef H264DEC_OMXDL + const u8 *pSrc; +#endif +/* Code */ + + ASSERT(pMb); + ASSERT(pMbLayer); + ASSERT(currImage); + ASSERT(qpY && *qpY < 52); + ASSERT(mbNum < currImage->width*currImage->height); + + mbType = pMbLayer->mbType; + pMb->mbType = mbType; + + pMb->decoded++; + + h264bsdSetCurrImageMbPointers(currImage, mbNum); + + if (mbType == I_PCM) + { + u8 *pData = (u8*)data; +#ifdef H264DEC_OMXDL + u8 *tot = pMb->totalCoeff; +#else + i16 *tot = pMb->totalCoeff; +#endif + i32 *lev = pMbLayer->residual.level[0]; + + pMb->qpY = 0; + + /* if decoded flag > 1 -> mb has already been successfully decoded and + * written to output -> do not write again */ + if (pMb->decoded > 1) + { + for (i = 24; i--;) + *tot++ = 16; + return HANTRO_OK; + } + + for (i = 24; i--;) + { + *tot++ = 16; + for (tmp = 16; tmp--;) + *pData++ = (u8)(*lev++); + } + h264bsdWriteMacroblock(currImage, (u8*)data); + + return(HANTRO_OK); + } + else + { +#ifdef H264DEC_OMXDL + if (h264bsdMbPartPredMode(mbType) == PRED_MODE_INTER) + { + tmp = h264bsdInterPrediction(pMb, pMbLayer, dpb, mbNum, + currImage, (u8*)data); + if (tmp != HANTRO_OK) return (tmp); + } +#endif + if (mbType != P_Skip) + { + H264SwDecMemcpy(pMb->totalCoeff, + pMbLayer->residual.totalCoeff, + 27*sizeof(*pMb->totalCoeff)); + + /* update qpY */ + if (pMbLayer->mbQpDelta) + { + *qpY = *qpY + pMbLayer->mbQpDelta; + if (*qpY < 0) *qpY += 52; + else if (*qpY >= 52) *qpY -= 52; + } + pMb->qpY = (u32)*qpY; + +#ifdef H264DEC_OMXDL + pSrc = pMbLayer->residual.posCoefBuf; + + if (h264bsdMbPartPredMode(mbType) == PRED_MODE_INTER) + { + OMXResult res; + u8 *p; + u8 *totalCoeff = pMb->totalCoeff; + + for (i = 0; i < 16; i++, totalCoeff++) + { + p = data + lumaIndex[i]; + if (*totalCoeff) + { + res = omxVCM4P10_DequantTransformResidualFromPairAndAdd( + &pSrc, p, 0, p, 16, 16, *qpY, *totalCoeff); + if (res != OMX_Sts_NoErr) + return (HANTRO_NOK); + } + } + + } + else if (h264bsdMbPartPredMode(mbType) == PRED_MODE_INTRA4x4) + { + tmp = ProcessIntra4x4Residual(pMb, + data, + constrainedIntraPredFlag, + pMbLayer, + &pSrc, + currImage); + if (tmp != HANTRO_OK) + return (tmp); + } + else if (h264bsdMbPartPredMode(mbType) == PRED_MODE_INTRA16x16) + { + tmp = ProcessIntra16x16Residual(pMb, + data, + constrainedIntraPredFlag, + pMbLayer->mbPred.intraChromaPredMode, + &pSrc, + currImage); + if (tmp != HANTRO_OK) + return (tmp); + } + + tmp = ProcessChromaResidual(pMb, data, &pSrc); + +#else + tmp = ProcessResidual(pMb, pMbLayer->residual.level, + pMbLayer->residual.coeffMap); +#endif + if (tmp != HANTRO_OK) + return (tmp); + } + else + { + H264SwDecMemset(pMb->totalCoeff, 0, 27*sizeof(*pMb->totalCoeff)); + pMb->qpY = (u32)*qpY; + } +#ifdef H264DEC_OMXDL + /* if decoded flag > 1 -> mb has already been successfully decoded and + * written to output -> do not write again */ + if (pMb->decoded > 1) + return HANTRO_OK; + + h264bsdWriteMacroblock(currImage, data); +#else + if (h264bsdMbPartPredMode(mbType) != PRED_MODE_INTER) + { + tmp = h264bsdIntraPrediction(pMb, pMbLayer, currImage, mbNum, + constrainedIntraPredFlag, (u8*)data); + if (tmp != HANTRO_OK) return (tmp); + } + else + { + tmp = h264bsdInterPrediction(pMb, pMbLayer, dpb, mbNum, + currImage, (u8*)data); + if (tmp != HANTRO_OK) return (tmp); + } +#endif + } + + return HANTRO_OK; +} + + +#ifdef H264DEC_OMXDL + +/*------------------------------------------------------------------------------ + + Function: ProcessChromaResidual + + Functional description: + Process the residual data of chroma with + inverse quantization and inverse transform. + +------------------------------------------------------------------------------*/ +u32 ProcessChromaResidual(mbStorage_t *pMb, u8 *data, const u8 **pSrc ) +{ + u32 i; + u32 chromaQp; + i16 *pDc; + i16 dc[4 + 4] = {0,0,0,0,0,0,0,0}; + u8 *totalCoeff; + OMXResult result; + u8 *p; + + /* chroma DC processing. First chroma dc block is block with index 25 */ + chromaQp = + h264bsdQpC[CLIP3(0, 51, (i32)pMb->qpY + pMb->chromaQpIndexOffset)]; + + if (pMb->totalCoeff[25]) + { + pDc = dc; + result = omxVCM4P10_TransformDequantChromaDCFromPair( + pSrc, + pDc, + (i32)chromaQp); + if (result != OMX_Sts_NoErr) + return (HANTRO_NOK); + } + if (pMb->totalCoeff[26]) + { + pDc = dc+4; + result = omxVCM4P10_TransformDequantChromaDCFromPair( + pSrc, + pDc, + (i32)chromaQp); + if (result != OMX_Sts_NoErr) + return (HANTRO_NOK); + } + + pDc = dc; + totalCoeff = pMb->totalCoeff + 16; + for (i = 0; i < 8; i++, pDc++, totalCoeff++) + { + /* chroma prediction */ + if (*totalCoeff || *pDc) + { + p = data + chromaIndex[i]; + result = omxVCM4P10_DequantTransformResidualFromPairAndAdd( + pSrc, + p, + pDc, + p, + 8, + 8, + (i32)chromaQp, + *totalCoeff); + if (result != OMX_Sts_NoErr) + return (HANTRO_NOK); + } + } + + return(HANTRO_OK); +} + +/*------------------------------------------------------------------------------ + + Function: ProcessIntra16x16Residual + + Functional description: + Process the residual data of luma with + inverse quantization and inverse transform. + +------------------------------------------------------------------------------*/ +u32 ProcessIntra16x16Residual(mbStorage_t *pMb, + u8 *data, + u32 constrainedIntraPred, + u32 intraChromaPredMode, + const u8** pSrc, + image_t *image) +{ + u32 i; + i16 *pDc; + i16 dc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + u8 *totalCoeff; + OMXResult result; + u8 *p; + + totalCoeff = pMb->totalCoeff; + + if (totalCoeff[24]) + { + pDc = dc; + result = omxVCM4P10_TransformDequantLumaDCFromPair( + pSrc, + pDc, + (i32)pMb->qpY); + if (result != OMX_Sts_NoErr) + return (HANTRO_NOK); + } + /* Intra 16x16 pred */ + if (h264bsdIntra16x16Prediction(pMb, data, image->luma, + image->width*16, constrainedIntraPred) != HANTRO_OK) + return(HANTRO_NOK); + for (i = 0; i < 16; i++, totalCoeff++) + { + p = data + lumaIndex[i]; + pDc = &dc[dcCoeffIndex[i]]; + if (*totalCoeff || *pDc) + { + result = omxVCM4P10_DequantTransformResidualFromPairAndAdd( + pSrc, + p, + pDc, + p, + 16, + 16, + (i32)pMb->qpY, + *totalCoeff); + if (result != OMX_Sts_NoErr) + return (HANTRO_NOK); + } + } + + if (h264bsdIntraChromaPrediction(pMb, data + 256, + image, + intraChromaPredMode, + constrainedIntraPred) != HANTRO_OK) + return(HANTRO_NOK); + + return HANTRO_OK; +} + +/*------------------------------------------------------------------------------ + + Function: ProcessIntra4x4Residual + + Functional description: + Process the residual data of luma with + inverse quantization and inverse transform. + +------------------------------------------------------------------------------*/ +u32 ProcessIntra4x4Residual(mbStorage_t *pMb, + u8 *data, + u32 constrainedIntraPred, + macroblockLayer_t *mbLayer, + const u8 **pSrc, + image_t *image) +{ + u32 i; + u8 *totalCoeff; + OMXResult result; + u8 *p; + + totalCoeff = pMb->totalCoeff; + + for (i = 0; i < 16; i++, totalCoeff++) + { + p = data + lumaIndex[i]; + if (h264bsdIntra4x4Prediction(pMb, p, mbLayer, image->luma, + image->width*16, constrainedIntraPred, i) != HANTRO_OK) + return(HANTRO_NOK); + + if (*totalCoeff) + { + result = omxVCM4P10_DequantTransformResidualFromPairAndAdd( + pSrc, + p, + NULL, + p, + 16, + 16, + (i32)pMb->qpY, + *totalCoeff); + if (result != OMX_Sts_NoErr) + return (HANTRO_NOK); + } + } + + if (h264bsdIntraChromaPrediction(pMb, data + 256, + image, + mbLayer->mbPred.intraChromaPredMode, + constrainedIntraPred) != HANTRO_OK) + return(HANTRO_NOK); + + return HANTRO_OK; +} + +#else /* H264DEC_OMXDL */ + +/*------------------------------------------------------------------------------ + + Function: ProcessResidual + + Functional description: + Process the residual data of one macroblock with + inverse quantization and inverse transform. + +------------------------------------------------------------------------------*/ + +u32 ProcessResidual(mbStorage_t *pMb, i32 residualLevel[][16], u32 *coeffMap) +{ + +/* Variables */ + + u32 i; + u32 chromaQp; + i32 (*blockData)[16]; + i32 (*blockDc)[16]; + i16 *totalCoeff; + i32 *chromaDc; + const u32 *dcCoeffIdx; + +/* Code */ + + ASSERT(pMb); + ASSERT(residualLevel); + + /* set pointers to DC coefficient blocks */ + blockDc = residualLevel + 24; + + blockData = residualLevel; + totalCoeff = pMb->totalCoeff; + if (h264bsdMbPartPredMode(pMb->mbType) == PRED_MODE_INTRA16x16) + { + if (totalCoeff[24]) + { + h264bsdProcessLumaDc(*blockDc, pMb->qpY); + } + dcCoeffIdx = dcCoeffIndex; + + for (i = 16; i--; blockData++, totalCoeff++, coeffMap++) + { + /* set dc coefficient of luma block */ + (*blockData)[0] = (*blockDc)[*dcCoeffIdx++]; + if ((*blockData)[0] || *totalCoeff) + { + if (h264bsdProcessBlock(*blockData, pMb->qpY, 1, *coeffMap) != + HANTRO_OK) + return(HANTRO_NOK); + } + else + MARK_RESIDUAL_EMPTY(*blockData); + } + } + else + { + for (i = 16; i--; blockData++, totalCoeff++, coeffMap++) + { + if (*totalCoeff) + { + if (h264bsdProcessBlock(*blockData, pMb->qpY, 0, *coeffMap) != + HANTRO_OK) + return(HANTRO_NOK); + } + else + MARK_RESIDUAL_EMPTY(*blockData); + } + } + + /* chroma DC processing. First chroma dc block is block with index 25 */ + chromaQp = + h264bsdQpC[CLIP3(0, 51, (i32)pMb->qpY + pMb->chromaQpIndexOffset)]; + if (pMb->totalCoeff[25] || pMb->totalCoeff[26]) + h264bsdProcessChromaDc(residualLevel[25], chromaQp); + chromaDc = residualLevel[25]; + for (i = 8; i--; blockData++, totalCoeff++, coeffMap++) + { + /* set dc coefficient of chroma block */ + (*blockData)[0] = *chromaDc++; + if ((*blockData)[0] || *totalCoeff) + { + if (h264bsdProcessBlock(*blockData, chromaQp, 1,*coeffMap) != + HANTRO_OK) + return(HANTRO_NOK); + } + else + MARK_RESIDUAL_EMPTY(*blockData); + } + + return(HANTRO_OK); +} +#endif /* H264DEC_OMXDL */ + +/*------------------------------------------------------------------------------ + + Function: h264bsdSubMbPartMode + + Functional description: + Returns the macroblock's sub-partition mode. + +------------------------------------------------------------------------------*/ + +subMbPartMode_e h264bsdSubMbPartMode(subMbType_e subMbType) +{ + +/* Variables */ + + +/* Code */ + + ASSERT(subMbType < 4); + + return((subMbPartMode_e)subMbType); + +} + + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_macroblock_layer.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_macroblock_layer.h new file mode 100755 index 0000000..32bc340 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_macroblock_layer.h @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. Module defines + 3. Data types + 4. Function prototypes + +------------------------------------------------------------------------------*/ + +#ifndef H264SWDEC_MACROBLOCK_LAYER_H +#define H264SWDEC_MACROBLOCK_LAYER_H + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "basetype.h" +#include "h264bsd_stream.h" +#include "h264bsd_image.h" +#include "h264bsd_dpb.h" + +/*------------------------------------------------------------------------------ + 2. Module defines +------------------------------------------------------------------------------*/ + +/* Macro to determine if a mb is an intra mb */ +#define IS_INTRA_MB(a) ((a).mbType > 5) + +/* Macro to determine if a mb is an I_PCM mb */ +#define IS_I_PCM_MB(a) ((a).mbType == 31) + +typedef enum { + P_Skip = 0, + P_L0_16x16 = 1, + P_L0_L0_16x8 = 2, + P_L0_L0_8x16 = 3, + P_8x8 = 4, + P_8x8ref0 = 5, + I_4x4 = 6, + I_16x16_0_0_0 = 7, + I_16x16_1_0_0 = 8, + I_16x16_2_0_0 = 9, + I_16x16_3_0_0 = 10, + I_16x16_0_1_0 = 11, + I_16x16_1_1_0 = 12, + I_16x16_2_1_0 = 13, + I_16x16_3_1_0 = 14, + I_16x16_0_2_0 = 15, + I_16x16_1_2_0 = 16, + I_16x16_2_2_0 = 17, + I_16x16_3_2_0 = 18, + I_16x16_0_0_1 = 19, + I_16x16_1_0_1 = 20, + I_16x16_2_0_1 = 21, + I_16x16_3_0_1 = 22, + I_16x16_0_1_1 = 23, + I_16x16_1_1_1 = 24, + I_16x16_2_1_1 = 25, + I_16x16_3_1_1 = 26, + I_16x16_0_2_1 = 27, + I_16x16_1_2_1 = 28, + I_16x16_2_2_1 = 29, + I_16x16_3_2_1 = 30, + I_PCM = 31 +} mbType_e; + +typedef enum { + P_L0_8x8 = 0, + P_L0_8x4 = 1, + P_L0_4x8 = 2, + P_L0_4x4 = 3 +} subMbType_e; + +typedef enum { + MB_P_16x16 = 0, + MB_P_16x8, + MB_P_8x16, + MB_P_8x8 +} mbPartMode_e; + +typedef enum { + MB_SP_8x8 = 0, + MB_SP_8x4, + MB_SP_4x8, + MB_SP_4x4 +} subMbPartMode_e; + +typedef enum { + PRED_MODE_INTRA4x4 = 0, + PRED_MODE_INTRA16x16 , + PRED_MODE_INTER +} mbPartPredMode_e; + +/*------------------------------------------------------------------------------ + 3. Data types +------------------------------------------------------------------------------*/ + +typedef struct +{ + /* MvPrediction16x16 assumes that MVs are 16bits */ + i16 hor; + i16 ver; +} mv_t; + +typedef struct +{ + u32 prevIntra4x4PredModeFlag[16]; + u32 remIntra4x4PredMode[16]; + u32 intraChromaPredMode; + u32 refIdxL0[4]; + mv_t mvdL0[4]; +} mbPred_t; + +typedef struct +{ + subMbType_e subMbType[4]; + u32 refIdxL0[4]; + mv_t mvdL0[4][4]; +} subMbPred_t; + +typedef struct +{ +#ifdef H264DEC_OMXDL + u8 posCoefBuf[27*16*3]; + u8 totalCoeff[27]; +#else + i16 totalCoeff[27]; +#endif + i32 level[26][16]; + u32 coeffMap[24]; +} residual_t; + +typedef struct +{ + mbType_e mbType; + u32 codedBlockPattern; + i32 mbQpDelta; + mbPred_t mbPred; + subMbPred_t subMbPred; + residual_t residual; +} macroblockLayer_t; + +typedef struct mbStorage +{ + mbType_e mbType; + u32 sliceId; + u32 disableDeblockingFilterIdc; + i32 filterOffsetA; + i32 filterOffsetB; + u32 qpY; + i32 chromaQpIndexOffset; +#ifdef H264DEC_OMXDL + u8 totalCoeff[27]; +#else + i16 totalCoeff[27]; +#endif + u8 intra4x4PredMode[16]; + u32 refPic[4]; + u8* refAddr[4]; + mv_t mv[16]; + u32 decoded; + struct mbStorage *mbA; + struct mbStorage *mbB; + struct mbStorage *mbC; + struct mbStorage *mbD; +} mbStorage_t; + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ + +u32 h264bsdDecodeMacroblockLayer(strmData_t *pStrmData, + macroblockLayer_t *pMbLayer, mbStorage_t *pMb, u32 sliceType, + u32 numRefIdxActive); + +u32 h264bsdNumMbPart(mbType_e mbType); +u32 h264bsdNumSubMbPart(subMbType_e subMbType); + +subMbPartMode_e h264bsdSubMbPartMode(subMbType_e subMbType); + +u32 h264bsdDecodeMacroblock(mbStorage_t *pMb, macroblockLayer_t *pMbLayer, + image_t *currImage, dpbStorage_t *dpb, i32 *qpY, u32 mbNum, + u32 constrainedIntraPredFlag, u8* data); + +u32 h264bsdPredModeIntra16x16(mbType_e mbType); + +mbPartPredMode_e h264bsdMbPartPredMode(mbType_e mbType); +#ifdef H264DEC_NEON +u32 h264bsdClearMbLayer(macroblockLayer_t *pMbLayer, u32 size); +#endif + +#endif /* #ifdef H264SWDEC_MACROBLOCK_LAYER_H */ + + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_nal_unit.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_nal_unit.c new file mode 100755 index 0000000..e44c43a --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_nal_unit.c @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. External compiler flags + 3. Module defines + 4. Local function prototypes + 5. Functions + h264bsdDecodeNalUnit + +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "h264bsd_nal_unit.h" +#include "h264bsd_util.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + + Function name: h264bsdDecodeNalUnit + + Functional description: + Decode NAL unit header information + + Inputs: + pStrmData pointer to stream data structure + + Outputs: + pNalUnit NAL unit header information is stored here + + Returns: + HANTRO_OK success + HANTRO_NOK invalid NAL unit header information + +------------------------------------------------------------------------------*/ + +u32 h264bsdDecodeNalUnit(strmData_t *pStrmData, nalUnit_t *pNalUnit) +{ + +/* Variables */ + + u32 tmp; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pNalUnit); + ASSERT(pStrmData->bitPosInWord == 0); + + /* forbidden_zero_bit (not checked to be zero, errors ignored) */ + tmp = h264bsdGetBits(pStrmData, 1); + /* Assuming that NAL unit starts from byte boundary > don't have to check + * following 7 bits for END_OF_STREAM */ + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + + tmp = h264bsdGetBits(pStrmData, 2); + pNalUnit->nalRefIdc = tmp; + + tmp = h264bsdGetBits(pStrmData, 5); + pNalUnit->nalUnitType = (nalUnitType_e)tmp; + + /* data partitioning NAL units not supported */ + if ( (tmp == 2) || (tmp == 3) || (tmp == 4) ) + { + return(HANTRO_NOK); + } + + /* nal_ref_idc shall not be zero for these nal_unit_types */ + if ( ( (tmp == NAL_SEQ_PARAM_SET) || (tmp == NAL_PIC_PARAM_SET) || + (tmp == NAL_CODED_SLICE_IDR) ) && (pNalUnit->nalRefIdc == 0) ) + { + return(HANTRO_NOK); + } + /* nal_ref_idc shall be zero for these nal_unit_types */ + else if ( ( (tmp == NAL_SEI) || (tmp == NAL_ACCESS_UNIT_DELIMITER) || + (tmp == NAL_END_OF_SEQUENCE) || (tmp == NAL_END_OF_STREAM) || + (tmp == NAL_FILLER_DATA) ) && (pNalUnit->nalRefIdc != 0) ) + { + return(HANTRO_NOK); + } + + return(HANTRO_OK); + +} + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_nal_unit.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_nal_unit.h new file mode 100755 index 0000000..38957bf --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_nal_unit.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. Module defines + 3. Data types + 4. Function prototypes + +------------------------------------------------------------------------------*/ + +#ifndef H264SWDEC_NAL_UNIT_H +#define H264SWDEC_NAL_UNIT_H + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "basetype.h" +#include "h264bsd_stream.h" + +/*------------------------------------------------------------------------------ + 2. Module defines +------------------------------------------------------------------------------*/ + +/* macro to determine if NAL unit pointed by pNalUnit contains an IDR slice */ +#define IS_IDR_NAL_UNIT(pNalUnit) \ + ((pNalUnit)->nalUnitType == NAL_CODED_SLICE_IDR) + +/*------------------------------------------------------------------------------ + 3. Data types +------------------------------------------------------------------------------*/ + +typedef enum { + NAL_CODED_SLICE = 1, + NAL_CODED_SLICE_IDR = 5, + NAL_SEI = 6, + NAL_SEQ_PARAM_SET = 7, + NAL_PIC_PARAM_SET = 8, + NAL_ACCESS_UNIT_DELIMITER = 9, + NAL_END_OF_SEQUENCE = 10, + NAL_END_OF_STREAM = 11, + NAL_FILLER_DATA = 12, + NAL_MAX_TYPE_VALUE = 31 +} nalUnitType_e; + +typedef struct +{ + nalUnitType_e nalUnitType; + u32 nalRefIdc; +} nalUnit_t; + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ + +u32 h264bsdDecodeNalUnit(strmData_t *pStrmData, nalUnit_t *pNalUnit); + +#endif /* #ifdef H264SWDEC_NAL_UNIT_H */ + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_neighbour.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_neighbour.c new file mode 100755 index 0000000..ce5eeff --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_neighbour.c @@ -0,0 +1,382 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. External compiler flags + 3. Module defines + 4. Local function prototypes + 5. Functions + h264bsdInitMbNeighbours + h264bsdGetNeighbourMb + h264bsdNeighbour4x4BlockA + h264bsdNeighbour4x4BlockB + h264bsdNeighbour4x4BlockC + h264bsdNeighbour4x4BlockD + +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "h264bsd_neighbour.h" +#include "h264bsd_util.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +/* Following four tables indicate neighbours of each block of a macroblock. + * First 16 values are for luma blocks, next 4 values for Cb and last 4 + * values for Cr. Elements of the table indicate to which macroblock the + * neighbour block belongs and the index of the neighbour block in question. + * Indexing of the blocks goes as follows + * + * Y Cb Cr + * 0 1 4 5 16 17 20 21 + * 2 3 6 7 18 19 22 23 + * 8 9 12 13 + * 10 11 14 15 + */ + +/* left neighbour for each block */ +static const neighbour_t N_A_4x4B[24] = { + {MB_A,5}, {MB_CURR,0}, {MB_A,7}, {MB_CURR,2}, + {MB_CURR,1}, {MB_CURR,4}, {MB_CURR,3}, {MB_CURR,6}, + {MB_A,13}, {MB_CURR,8}, {MB_A,15}, {MB_CURR,10}, + {MB_CURR,9}, {MB_CURR,12},{MB_CURR,11},{MB_CURR,14}, + {MB_A,17}, {MB_CURR,16},{MB_A,19}, {MB_CURR,18}, + {MB_A,21}, {MB_CURR,20},{MB_A,23}, {MB_CURR,22} }; + +/* above neighbour for each block */ +static const neighbour_t N_B_4x4B[24] = { + {MB_B,10}, {MB_B,11}, {MB_CURR,0}, {MB_CURR,1}, + {MB_B,14}, {MB_B,15}, {MB_CURR,4}, {MB_CURR,5}, + {MB_CURR,2}, {MB_CURR,3}, {MB_CURR,8}, {MB_CURR,9}, + {MB_CURR,6}, {MB_CURR,7}, {MB_CURR,12},{MB_CURR,13}, + {MB_B,18}, {MB_B,19}, {MB_CURR,16},{MB_CURR,17}, + {MB_B,22}, {MB_B,23}, {MB_CURR,20},{MB_CURR,21} }; + +/* above-right neighbour for each block */ +static const neighbour_t N_C_4x4B[24] = { + {MB_B,11}, {MB_B,14}, {MB_CURR,1}, {MB_NA,4}, + {MB_B,15}, {MB_C,10}, {MB_CURR,5}, {MB_NA,0}, + {MB_CURR,3}, {MB_CURR,6}, {MB_CURR,9}, {MB_NA,12}, + {MB_CURR,7}, {MB_NA,2}, {MB_CURR,13},{MB_NA,8}, + {MB_B,19}, {MB_C,18}, {MB_CURR,17},{MB_NA,16}, + {MB_B,23}, {MB_C,22}, {MB_CURR,21},{MB_NA,20} }; + +/* above-left neighbour for each block */ +static const neighbour_t N_D_4x4B[24] = { + {MB_D,15}, {MB_B,10}, {MB_A,5}, {MB_CURR,0}, + {MB_B,11}, {MB_B,14}, {MB_CURR,1}, {MB_CURR,4}, + {MB_A,7}, {MB_CURR,2}, {MB_A,13}, {MB_CURR,8}, + {MB_CURR,3}, {MB_CURR,6}, {MB_CURR,9}, {MB_CURR,12}, + {MB_D,19}, {MB_B,18}, {MB_A,17}, {MB_CURR,16}, + {MB_D,23}, {MB_B,22}, {MB_A,21}, {MB_CURR,20} }; + +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + + Function: h264bsdInitMbNeighbours + + Functional description: + Initialize macroblock neighbours. Function sets neighbour + macroblock pointers in macroblock structures to point to + macroblocks on the left, above, above-right and above-left. + Pointers are set NULL if the neighbour does not fit into the + picture. + + Inputs: + picWidth width of the picture in macroblocks + picSizeInMbs no need to clarify + + Outputs: + pMbStorage neighbour pointers of each mbStorage structure + stored here + + Returns: + none + +------------------------------------------------------------------------------*/ + +void h264bsdInitMbNeighbours(mbStorage_t *pMbStorage, u32 picWidth, + u32 picSizeInMbs) +{ + +/* Variables */ + + u32 i, row, col; + +/* Code */ + + ASSERT(pMbStorage); + ASSERT(picWidth); + ASSERT(picWidth <= picSizeInMbs); + ASSERT(((picSizeInMbs / picWidth) * picWidth) == picSizeInMbs); + + row = col = 0; + + for (i = 0; i < picSizeInMbs; i++) + { + + if (col) + pMbStorage[i].mbA = pMbStorage + i - 1; + else + pMbStorage[i].mbA = NULL; + + if (row) + pMbStorage[i].mbB = pMbStorage + i - picWidth; + else + pMbStorage[i].mbB = NULL; + + if (row && (col < picWidth - 1)) + pMbStorage[i].mbC = pMbStorage + i - (picWidth - 1); + else + pMbStorage[i].mbC = NULL; + + if (row && col) + pMbStorage[i].mbD = pMbStorage + i - (picWidth + 1); + else + pMbStorage[i].mbD = NULL; + + col++; + if (col == picWidth) + { + col = 0; + row++; + } + } + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdGetNeighbourMb + + Functional description: + Get pointer to neighbour macroblock. + + Inputs: + pMb pointer to macroblock structure of the macroblock + whose neighbour is wanted + neighbour indicates which neighbour is wanted + + Outputs: + none + + Returns: + pointer to neighbour macroblock + NULL if not available + +------------------------------------------------------------------------------*/ + +mbStorage_t* h264bsdGetNeighbourMb(mbStorage_t *pMb, neighbourMb_e neighbour) +{ + +/* Variables */ + + +/* Code */ + + ASSERT((neighbour <= MB_CURR) || (neighbour == MB_NA)); + + if (neighbour == MB_A) + return(pMb->mbA); + else if (neighbour == MB_B) + return(pMb->mbB); + else if (neighbour == MB_C) + return(pMb->mbC); + else if (neighbour == MB_D) + return(pMb->mbD); + else if (neighbour == MB_CURR) + return(pMb); + else + return(NULL); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdNeighbour4x4BlockA + + Functional description: + Get left neighbour of the block. Function returns pointer to + the table defined in the beginning of the file. + + Inputs: + blockIndex indicates the block whose neighbours are wanted + + Outputs: + + Returns: + pointer to neighbour structure + +------------------------------------------------------------------------------*/ + +const neighbour_t* h264bsdNeighbour4x4BlockA(u32 blockIndex) +{ + +/* Variables */ + +/* Code */ + + ASSERT(blockIndex < 24); + + return(N_A_4x4B+blockIndex); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdNeighbour4x4BlockB + + Functional description: + Get above neighbour of the block. Function returns pointer to + the table defined in the beginning of the file. + + Inputs: + blockIndex indicates the block whose neighbours are wanted + + Outputs: + + Returns: + pointer to neighbour structure + +------------------------------------------------------------------------------*/ + +const neighbour_t* h264bsdNeighbour4x4BlockB(u32 blockIndex) +{ + +/* Variables */ + +/* Code */ + + ASSERT(blockIndex < 24); + + return(N_B_4x4B+blockIndex); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdNeighbour4x4BlockC + + Functional description: + Get above-right neighbour of the block. Function returns pointer + to the table defined in the beginning of the file. + + Inputs: + blockIndex indicates the block whose neighbours are wanted + + Outputs: + + Returns: + pointer to neighbour structure + +------------------------------------------------------------------------------*/ + +const neighbour_t* h264bsdNeighbour4x4BlockC(u32 blockIndex) +{ + +/* Variables */ + +/* Code */ + + ASSERT(blockIndex < 24); + + return(N_C_4x4B+blockIndex); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdNeighbour4x4BlockD + + Functional description: + Get above-left neighbour of the block. Function returns pointer to + the table defined in the beginning of the file. + + Inputs: + blockIndex indicates the block whose neighbours are wanted + + Outputs: + + Returns: + pointer to neighbour structure + +------------------------------------------------------------------------------*/ + +const neighbour_t* h264bsdNeighbour4x4BlockD(u32 blockIndex) +{ + +/* Variables */ + +/* Code */ + + ASSERT(blockIndex < 24); + + return(N_D_4x4B+blockIndex); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdIsNeighbourAvailable + + Functional description: + Check if neighbour macroblock is available. Neighbour macroblock + is considered available if it is within the picture and belongs + to the same slice as the current macroblock. + + Inputs: + pMb pointer to the current macroblock + pNeighbour pointer to the neighbour macroblock + + Outputs: + none + + Returns: + TRUE neighbour is available + FALSE neighbour is not available + +------------------------------------------------------------------------------*/ + +u32 h264bsdIsNeighbourAvailable(mbStorage_t *pMb, mbStorage_t *pNeighbour) +{ + +/* Variables */ + +/* Code */ + + if ( (pNeighbour == NULL) || (pMb->sliceId != pNeighbour->sliceId) ) + return(HANTRO_FALSE); + else + return(HANTRO_TRUE); + +} + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_neighbour.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_neighbour.h new file mode 100755 index 0000000..fce0ad1 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_neighbour.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. Module defines + 3. Data types + 4. Function prototypes + +------------------------------------------------------------------------------*/ + +#ifndef H264SWDEC_NEIGHBOUR_H +#define H264SWDEC_NEIGHBOUR_H + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "basetype.h" +#include "h264bsd_macroblock_layer.h" + +/*------------------------------------------------------------------------------ + 2. Module defines +------------------------------------------------------------------------------*/ + +typedef enum { + MB_A = 0, + MB_B, + MB_C, + MB_D, + MB_CURR, + MB_NA = 0xFF +} neighbourMb_e; + +/*------------------------------------------------------------------------------ + 3. Data types +------------------------------------------------------------------------------*/ + +typedef struct +{ + neighbourMb_e mb; + u8 index; +} neighbour_t; + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ + +void h264bsdInitMbNeighbours(mbStorage_t *pMbStorage, u32 picWidth, + u32 picSizeInMbs); + +mbStorage_t* h264bsdGetNeighbourMb(mbStorage_t *pMb, neighbourMb_e neighbour); + +u32 h264bsdIsNeighbourAvailable(mbStorage_t *pMb, mbStorage_t *pNeighbour); + +const neighbour_t* h264bsdNeighbour4x4BlockA(u32 blockIndex); +const neighbour_t* h264bsdNeighbour4x4BlockB(u32 blockIndex); +const neighbour_t* h264bsdNeighbour4x4BlockC(u32 blockIndex); +const neighbour_t* h264bsdNeighbour4x4BlockD(u32 blockIndex); + +#endif /* #ifdef H264SWDEC_NEIGHBOUR_H */ + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_pic_order_cnt.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_pic_order_cnt.c new file mode 100755 index 0000000..fb23352 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_pic_order_cnt.c @@ -0,0 +1,347 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. External compiler flags + 3. Module defines + 4. Local function prototypes + 5. Functions + h264bsdDecodePicOrderCnt + +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "h264bsd_util.h" +#include "h264bsd_pic_order_cnt.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + + Function: h264bsdDecodePicOrderCnt + + Functional description: + Compute picture order count for a picture. Function implements + computation of all POC types (0, 1 and 2), type is obtained from + sps. See standard for description of the POC types and how POC is + computed for each type. + + Function returns the minimum of top field and bottom field pic + order counts. + + Inputs: + poc pointer to previous results + sps pointer to sequence parameter set + slicHeader pointer to current slice header, frame number and + other params needed for POC computation + pNalUnit pointer to current NAL unit structrue, function needs + to know if this is an IDR picture and also if this is + a reference picture + + Outputs: + poc results stored here for computation of next POC + + Returns: + picture order count + +------------------------------------------------------------------------------*/ + +i32 h264bsdDecodePicOrderCnt(pocStorage_t *poc, seqParamSet_t *sps, + sliceHeader_t *pSliceHeader, nalUnit_t *pNalUnit) +{ + +/* Variables */ + + u32 i; + i32 picOrderCnt; + u32 frameNumOffset, absFrameNum, picOrderCntCycleCnt; + u32 frameNumInPicOrderCntCycle; + i32 expectedDeltaPicOrderCntCycle; + u32 containsMmco5; + +/* Code */ + + ASSERT(poc); + ASSERT(sps); + ASSERT(pSliceHeader); + ASSERT(pNalUnit); + ASSERT(sps->picOrderCntType <= 2); + +#if 0 + /* JanSa: I don't think this is necessary, don't see any reason to + * increment prevFrameNum one by one instead of one big increment. + * However, standard specifies that this should be done -> if someone + * figures out any case when the outcome would be different for step by + * step increment, this part of the code should be enabled */ + + /* if there was a gap in frame numbering and picOrderCntType is 1 or 2 -> + * "compute" pic order counts for non-existing frames. These are not + * actually computed, but process needs to be done to update the + * prevFrameNum and prevFrameNumOffset */ + if ( sps->picOrderCntType > 0 && + pSliceHeader->frameNum != poc->prevFrameNum && + pSliceHeader->frameNum != ((poc->prevFrameNum + 1) % sps->maxFrameNum)) + { + + /* use variable i for unUsedShortTermFrameNum */ + i = (poc->prevFrameNum + 1) % sps->maxFrameNum; + + do + { + if (poc->prevFrameNum > i) + frameNumOffset = poc->prevFrameNumOffset + sps->maxFrameNum; + else + frameNumOffset = poc->prevFrameNumOffset; + + poc->prevFrameNumOffset = frameNumOffset; + poc->prevFrameNum = i; + + i = (i + 1) % sps->maxFrameNum; + + } while (i != pSliceHeader->frameNum); + } +#endif + + /* check if current slice includes mmco equal to 5 */ + containsMmco5 = HANTRO_FALSE; + if (pSliceHeader->decRefPicMarking.adaptiveRefPicMarkingModeFlag) + { + i = 0; + while (pSliceHeader->decRefPicMarking.operation[i]. + memoryManagementControlOperation) + { + if (pSliceHeader->decRefPicMarking.operation[i]. + memoryManagementControlOperation == 5) + { + containsMmco5 = HANTRO_TRUE; + break; + } + i++; + } + } + switch (sps->picOrderCntType) + { + + case 0: + /* set prevPicOrderCnt values for IDR frame */ + if (IS_IDR_NAL_UNIT(pNalUnit)) + { + poc->prevPicOrderCntMsb = 0; + poc->prevPicOrderCntLsb = 0; + } + + /* compute picOrderCntMsb (stored in picOrderCnt variable) */ + if ( (pSliceHeader->picOrderCntLsb < poc->prevPicOrderCntLsb) && + ((poc->prevPicOrderCntLsb - pSliceHeader->picOrderCntLsb) >= + sps->maxPicOrderCntLsb/2) ) + { + picOrderCnt = poc->prevPicOrderCntMsb + + (i32)sps->maxPicOrderCntLsb; + } + else if ((pSliceHeader->picOrderCntLsb > poc->prevPicOrderCntLsb) && + ((pSliceHeader->picOrderCntLsb - poc->prevPicOrderCntLsb) > + sps->maxPicOrderCntLsb/2) ) + { + picOrderCnt = poc->prevPicOrderCntMsb - + (i32)sps->maxPicOrderCntLsb; + } + else + picOrderCnt = poc->prevPicOrderCntMsb; + + /* standard specifies that prevPicOrderCntMsb is from previous + * rererence frame -> replace old value only if current frame is + * rererence frame */ + if (pNalUnit->nalRefIdc) + poc->prevPicOrderCntMsb = picOrderCnt; + + /* compute top field order cnt (stored in picOrderCnt) */ + picOrderCnt += (i32)pSliceHeader->picOrderCntLsb; + + /* if delta for bottom field is negative -> bottom will be the + * minimum pic order count */ + if (pSliceHeader->deltaPicOrderCntBottom < 0) + picOrderCnt += pSliceHeader->deltaPicOrderCntBottom; + + /* standard specifies that prevPicOrderCntLsb is from previous + * rererence frame -> replace old value only if current frame is + * rererence frame */ + if (pNalUnit->nalRefIdc) + { + /* if current frame contains mmco5 -> modify values to be + * stored */ + if (containsMmco5) + { + poc->prevPicOrderCntMsb = 0; + /* prevPicOrderCntLsb should be the top field picOrderCnt + * if previous frame included mmco5. Top field picOrderCnt + * for frames containing mmco5 is obtained by subtracting + * the picOrderCnt from original top field order count -> + * value is zero if top field was the minimum, i.e. delta + * for bottom was positive, otherwise value is + * -deltaPicOrderCntBottom */ + if (pSliceHeader->deltaPicOrderCntBottom < 0) + poc->prevPicOrderCntLsb = + (u32)(-pSliceHeader->deltaPicOrderCntBottom); + else + poc->prevPicOrderCntLsb = 0; + picOrderCnt = 0; + } + else + { + poc->prevPicOrderCntLsb = pSliceHeader->picOrderCntLsb; + } + } + + break; + + case 1: + + /* step 1 (in the description in the standard) */ + if (IS_IDR_NAL_UNIT(pNalUnit)) + frameNumOffset = 0; + else if (poc->prevFrameNum > pSliceHeader->frameNum) + frameNumOffset = poc->prevFrameNumOffset + sps->maxFrameNum; + else + frameNumOffset = poc->prevFrameNumOffset; + + /* step 2 */ + if (sps->numRefFramesInPicOrderCntCycle) + absFrameNum = frameNumOffset + pSliceHeader->frameNum; + else + absFrameNum = 0; + + if (pNalUnit->nalRefIdc == 0 && absFrameNum > 0) + absFrameNum -= 1; + + /* step 3 */ + if (absFrameNum > 0) + { + picOrderCntCycleCnt = + (absFrameNum - 1)/sps->numRefFramesInPicOrderCntCycle; + frameNumInPicOrderCntCycle = + (absFrameNum - 1)%sps->numRefFramesInPicOrderCntCycle; + } + + /* step 4 */ + expectedDeltaPicOrderCntCycle = 0; + for (i = 0; i < sps->numRefFramesInPicOrderCntCycle; i++) + expectedDeltaPicOrderCntCycle += sps->offsetForRefFrame[i]; + + /* step 5 (picOrderCnt used to store expectedPicOrderCnt) */ + /*lint -esym(644,picOrderCntCycleCnt) always initialized */ + /*lint -esym(644,frameNumInPicOrderCntCycle) always initialized */ + if (absFrameNum > 0) + { + picOrderCnt = + (i32)picOrderCntCycleCnt * expectedDeltaPicOrderCntCycle; + for (i = 0; i <= frameNumInPicOrderCntCycle; i++) + picOrderCnt += sps->offsetForRefFrame[i]; + } + else + picOrderCnt = 0; + + if (pNalUnit->nalRefIdc == 0) + picOrderCnt += sps->offsetForNonRefPic; + + /* step 6 (picOrderCnt is top field order cnt if delta for bottom + * is positive, otherwise it is bottom field order cnt) */ + picOrderCnt += pSliceHeader->deltaPicOrderCnt[0]; + + if ( (sps->offsetForTopToBottomField + + pSliceHeader->deltaPicOrderCnt[1]) < 0 ) + { + picOrderCnt += sps->offsetForTopToBottomField + + pSliceHeader->deltaPicOrderCnt[1]; + } + + /* if current picture contains mmco5 -> set prevFrameNumOffset and + * prevFrameNum to 0 for computation of picOrderCnt of next + * frame, otherwise store frameNum and frameNumOffset to poc + * structure */ + if (!containsMmco5) + { + poc->prevFrameNumOffset = frameNumOffset; + poc->prevFrameNum = pSliceHeader->frameNum; + } + else + { + poc->prevFrameNumOffset = 0; + poc->prevFrameNum = 0; + picOrderCnt = 0; + } + break; + + default: /* case 2 */ + /* derive frameNumOffset */ + if (IS_IDR_NAL_UNIT(pNalUnit)) + frameNumOffset = 0; + else if (poc->prevFrameNum > pSliceHeader->frameNum) + frameNumOffset = poc->prevFrameNumOffset + sps->maxFrameNum; + else + frameNumOffset = poc->prevFrameNumOffset; + + /* derive picOrderCnt (type 2 has same value for top and bottom + * field order cnts) */ + if (IS_IDR_NAL_UNIT(pNalUnit)) + picOrderCnt = 0; + else if (pNalUnit->nalRefIdc == 0) + picOrderCnt = + 2 * (i32)(frameNumOffset + pSliceHeader->frameNum) - 1; + else + picOrderCnt = + 2 * (i32)(frameNumOffset + pSliceHeader->frameNum); + + /* if current picture contains mmco5 -> set prevFrameNumOffset and + * prevFrameNum to 0 for computation of picOrderCnt of next + * frame, otherwise store frameNum and frameNumOffset to poc + * structure */ + if (!containsMmco5) + { + poc->prevFrameNumOffset = frameNumOffset; + poc->prevFrameNum = pSliceHeader->frameNum; + } + else + { + poc->prevFrameNumOffset = 0; + poc->prevFrameNum = 0; + picOrderCnt = 0; + } + break; + + } + + /*lint -esym(644,picOrderCnt) always initialized */ + return(picOrderCnt); + +} + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_pic_order_cnt.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_pic_order_cnt.h new file mode 100755 index 0000000..19741eb --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_pic_order_cnt.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. Module defines + 3. Data types + 4. Function prototypes + +------------------------------------------------------------------------------*/ + +#ifndef H264SWDEC_PIC_ORDER_CNT_H +#define H264SWDEC_PIC_ORDER_CNT_H + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "basetype.h" +#include "h264bsd_seq_param_set.h" +#include "h264bsd_slice_header.h" +#include "h264bsd_nal_unit.h" + +/*------------------------------------------------------------------------------ + 2. Module defines +------------------------------------------------------------------------------*/ + + +/*------------------------------------------------------------------------------ + 3. Data types +------------------------------------------------------------------------------*/ + +/* structure to store information computed for previous picture, needed for + * POC computation of a picture. Two first fields for POC type 0, last two + * for types 1 and 2 */ +typedef struct +{ + u32 prevPicOrderCntLsb; + i32 prevPicOrderCntMsb; + u32 prevFrameNum; + u32 prevFrameNumOffset; +} pocStorage_t; + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ + +i32 h264bsdDecodePicOrderCnt(pocStorage_t *poc, seqParamSet_t *sps, + sliceHeader_t *sliceHeader, nalUnit_t *pNalUnit); + +#endif /* #ifdef H264SWDEC_PIC_ORDER_CNT_H */ + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_pic_param_set.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_pic_param_set.c new file mode 100755 index 0000000..e04dea4 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_pic_param_set.c @@ -0,0 +1,335 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. External compiler flags + 3. Module defines + 4. Local function prototypes + 5. Functions + h264bsdDecodePicParamSet + +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "h264bsd_pic_param_set.h" +#include "h264bsd_util.h" +#include "h264bsd_vlc.h" +#include "h264bsd_cfg.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +/* lookup table for ceil(log2(numSliceGroups)), i.e. number of bits needed to + * represent range [0, numSliceGroups) + * + * NOTE: if MAX_NUM_SLICE_GROUPS is higher than 8 this table has to be resized + * accordingly */ +static const u32 CeilLog2NumSliceGroups[8] = {1, 1, 2, 2, 3, 3, 3, 3}; + +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + + Function name: h264bsdDecodePicParamSet + + Functional description: + Decode picture parameter set information from the stream. + + Function allocates memory for + - run lengths if slice group map type is 0 + - top-left and bottom-right arrays if map type is 2 + - for slice group ids if map type is 6 + + Validity of some of the slice group mapping information depends + on the image dimensions which are not known here. Therefore the + validity has to be checked afterwards, currently in the parameter + set activation phase. + + Inputs: + pStrmData pointer to stream data structure + + Outputs: + pPicParamSet decoded information is stored here + + Returns: + HANTRO_OK success + HANTRO_NOK failure, invalid information or end of stream + MEMORY_ALLOCATION_ERROR for memory allocation failure + + +------------------------------------------------------------------------------*/ + +u32 h264bsdDecodePicParamSet(strmData_t *pStrmData, picParamSet_t *pPicParamSet) +{ + +/* Variables */ + + u32 tmp, i, value; + i32 itmp; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pPicParamSet); + + + H264SwDecMemset(pPicParamSet, 0, sizeof(picParamSet_t)); + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pPicParamSet->picParameterSetId); + if (tmp != HANTRO_OK) + return(tmp); + if (pPicParamSet->picParameterSetId >= MAX_NUM_PIC_PARAM_SETS) + { + EPRINT("pic_parameter_set_id"); + return(HANTRO_NOK); + } + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pPicParamSet->seqParameterSetId); + if (tmp != HANTRO_OK) + return(tmp); + if (pPicParamSet->seqParameterSetId >= MAX_NUM_SEQ_PARAM_SETS) + { + EPRINT("seq_param_set_id"); + return(HANTRO_NOK); + } + + /* entropy_coding_mode_flag, shall be 0 for baseline profile */ + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp) + { + EPRINT("entropy_coding_mode_flag"); + return(HANTRO_NOK); + } + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pPicParamSet->picOrderPresentFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; + + /* num_slice_groups_minus1 */ + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + pPicParamSet->numSliceGroups = value + 1; + if (pPicParamSet->numSliceGroups > MAX_NUM_SLICE_GROUPS) + { + EPRINT("num_slice_groups_minus1"); + return(HANTRO_NOK); + } + + /* decode slice group mapping information if more than one slice groups */ + if (pPicParamSet->numSliceGroups > 1) + { + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pPicParamSet->sliceGroupMapType); + if (tmp != HANTRO_OK) + return(tmp); + if (pPicParamSet->sliceGroupMapType > 6) + { + EPRINT("slice_group_map_type"); + return(HANTRO_NOK); + } + + if (pPicParamSet->sliceGroupMapType == 0) + { + ALLOCATE(pPicParamSet->runLength, + pPicParamSet->numSliceGroups, u32); + if (pPicParamSet->runLength == NULL) + return(MEMORY_ALLOCATION_ERROR); + for (i = 0; i < pPicParamSet->numSliceGroups; i++) + { + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + pPicParamSet->runLength[i] = value+1; + /* param values checked in CheckPps() */ + } + } + else if (pPicParamSet->sliceGroupMapType == 2) + { + ALLOCATE(pPicParamSet->topLeft, + pPicParamSet->numSliceGroups - 1, u32); + ALLOCATE(pPicParamSet->bottomRight, + pPicParamSet->numSliceGroups - 1, u32); + if (pPicParamSet->topLeft == NULL || + pPicParamSet->bottomRight == NULL) + return(MEMORY_ALLOCATION_ERROR); + for (i = 0; i < pPicParamSet->numSliceGroups - 1; i++) + { + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + pPicParamSet->topLeft[i] = value; + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + pPicParamSet->bottomRight[i] = value; + /* param values checked in CheckPps() */ + } + } + else if ( (pPicParamSet->sliceGroupMapType == 3) || + (pPicParamSet->sliceGroupMapType == 4) || + (pPicParamSet->sliceGroupMapType == 5) ) + { + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pPicParamSet->sliceGroupChangeDirectionFlag = + (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + pPicParamSet->sliceGroupChangeRate = value + 1; + /* param value checked in CheckPps() */ + } + else if (pPicParamSet->sliceGroupMapType == 6) + { + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + pPicParamSet->picSizeInMapUnits = value + 1; + + ALLOCATE(pPicParamSet->sliceGroupId, + pPicParamSet->picSizeInMapUnits, u32); + if (pPicParamSet->sliceGroupId == NULL) + return(MEMORY_ALLOCATION_ERROR); + + /* determine number of bits needed to represent range + * [0, numSliceGroups) */ + tmp = CeilLog2NumSliceGroups[pPicParamSet->numSliceGroups-1]; + + for (i = 0; i < pPicParamSet->picSizeInMapUnits; i++) + { + pPicParamSet->sliceGroupId[i] = h264bsdGetBits(pStrmData, tmp); + if ( pPicParamSet->sliceGroupId[i] >= + pPicParamSet->numSliceGroups ) + { + EPRINT("slice_group_id"); + return(HANTRO_NOK); + } + } + } + } + + /* num_ref_idx_l0_active_minus1 */ + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + if (value > 31) + { + EPRINT("num_ref_idx_l0_active_minus1"); + return(HANTRO_NOK); + } + pPicParamSet->numRefIdxL0Active = value + 1; + + /* num_ref_idx_l1_active_minus1 */ + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + if (value > 31) + { + EPRINT("num_ref_idx_l1_active_minus1"); + return(HANTRO_NOK); + } + + /* weighted_pred_flag, this shall be 0 for baseline profile */ + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp) + { + EPRINT("weighted_pred_flag"); + return(HANTRO_NOK); + } + + /* weighted_bipred_idc */ + tmp = h264bsdGetBits(pStrmData, 2); + if (tmp > 2) + { + EPRINT("weighted_bipred_idc"); + return(HANTRO_NOK); + } + + /* pic_init_qp_minus26 */ + tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp); + if (tmp != HANTRO_OK) + return(tmp); + if ((itmp < -26) || (itmp > 25)) + { + EPRINT("pic_init_qp_minus26"); + return(HANTRO_NOK); + } + pPicParamSet->picInitQp = (u32)(itmp + 26); + + /* pic_init_qs_minus26 */ + tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp); + if (tmp != HANTRO_OK) + return(tmp); + if ((itmp < -26) || (itmp > 25)) + { + EPRINT("pic_init_qs_minus26"); + return(HANTRO_NOK); + } + + tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp); + if (tmp != HANTRO_OK) + return(tmp); + if ((itmp < -12) || (itmp > 12)) + { + EPRINT("chroma_qp_index_offset"); + return(HANTRO_NOK); + } + pPicParamSet->chromaQpIndexOffset = itmp; + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pPicParamSet->deblockingFilterControlPresentFlag = + (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pPicParamSet->constrainedIntraPredFlag = (tmp == 1) ? + HANTRO_TRUE : HANTRO_FALSE; + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pPicParamSet->redundantPicCntPresentFlag = (tmp == 1) ? + HANTRO_TRUE : HANTRO_FALSE; + + tmp = h264bsdRbspTrailingBits(pStrmData); + + /* ignore possible errors in trailing bits of parameters sets */ + return(HANTRO_OK); + +} + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_pic_param_set.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_pic_param_set.h new file mode 100755 index 0000000..6328638 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_pic_param_set.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. Module defines + 3. Data types + 4. Function prototypes + +------------------------------------------------------------------------------*/ + +#ifndef H264SWDEC_PIC_PARAM_SET_H +#define H264SWDEC_PIC_PARAM_SET_H + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "basetype.h" +#include "h264bsd_stream.h" + +/*------------------------------------------------------------------------------ + 2. Module defines +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 3. Data types +------------------------------------------------------------------------------*/ + +/* data structure to store PPS information decoded from the stream */ +typedef struct +{ + u32 picParameterSetId; + u32 seqParameterSetId; + u32 picOrderPresentFlag; + u32 numSliceGroups; + u32 sliceGroupMapType; + u32 *runLength; + u32 *topLeft; + u32 *bottomRight; + u32 sliceGroupChangeDirectionFlag; + u32 sliceGroupChangeRate; + u32 picSizeInMapUnits; + u32 *sliceGroupId; + u32 numRefIdxL0Active; + u32 picInitQp; + i32 chromaQpIndexOffset; + u32 deblockingFilterControlPresentFlag; + u32 constrainedIntraPredFlag; + u32 redundantPicCntPresentFlag; +} picParamSet_t; + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ + +u32 h264bsdDecodePicParamSet(strmData_t *pStrmData, + picParamSet_t *pPicParamSet); + +#endif /* #ifdef H264SWDEC_PIC_PARAM_SET_H */ + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_reconstruct.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_reconstruct.c new file mode 100755 index 0000000..c948776 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_reconstruct.c @@ -0,0 +1,2315 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. External compiler flags + 3. Module defines + 4. Local function prototypes + 5. Functions + +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "basetype.h" +#include "h264bsd_reconstruct.h" +#include "h264bsd_macroblock_layer.h" +#include "h264bsd_image.h" +#include "h264bsd_util.h" + +#ifdef H264DEC_OMXDL +#include "omxtypes.h" +#include "omxVC.h" +#include "armVC.h" +#endif /* H264DEC_OMXDL */ + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +/* Switch off the following Lint messages for this file: + * Info 701: Shift left of signed quantity (int) + * Info 702: Shift right of signed quantity (int) + */ +/*lint -e701 -e702 */ + +/* Luma fractional-sample positions + * + * G a b c H + * d e f g + * h i j k m + * n p q r + * M s N + * + * G, H, M and N are integer sample positions + * a-s are fractional samples that need to be interpolated. + */ +#ifndef H264DEC_OMXDL +static const u32 lumaFracPos[4][4] = { + /* G d h n a e i p b f j q c g k r */ + {0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11}, {12, 13, 14, 15}}; +#endif /* H264DEC_OMXDL */ + +/* clipping table, defined in h264bsd_intra_prediction.c */ +extern const u8 h264bsdClip[]; + +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ + +#ifndef H264DEC_OMXDL + +/*------------------------------------------------------------------------------ + + Function: h264bsdInterpolateChromaHor + + Functional description: + This function performs chroma interpolation in horizontal direction. + Overfilling is done only if needed. Reference image (pRef) is + read at correct position and the predicted part is written to + macroblock's chrominance (predPartChroma) + Inputs: + pRef pointer to reference frame Cb top-left corner + x0 integer x-coordinate for prediction + y0 integer y-coordinate for prediction + width width of the reference frame chrominance in pixels + height height of the reference frame chrominance in pixels + xFrac horizontal fraction for prediction in 1/8 pixels + chromaPartWidth width of the predicted part in pixels + chromaPartHeight height of the predicted part in pixels + Outputs: + predPartChroma pointer where predicted part is written + +------------------------------------------------------------------------------*/ +#ifndef H264DEC_ARM11 +void h264bsdInterpolateChromaHor( + u8 *pRef, + u8 *predPartChroma, + i32 x0, + i32 y0, + u32 width, + u32 height, + u32 xFrac, + u32 chromaPartWidth, + u32 chromaPartHeight) +{ + +/* Variables */ + + u32 x, y, tmp1, tmp2, tmp3, tmp4, c, val; + u8 *ptrA, *cbr; + u32 comp; + u8 block[9*8*2]; + +/* Code */ + + ASSERT(predPartChroma); + ASSERT(chromaPartWidth); + ASSERT(chromaPartHeight); + ASSERT(xFrac < 8); + ASSERT(pRef); + + if ((x0 < 0) || ((u32)x0+chromaPartWidth+1 > width) || + (y0 < 0) || ((u32)y0+chromaPartHeight > height)) + { + h264bsdFillBlock(pRef, block, x0, y0, width, height, + chromaPartWidth + 1, chromaPartHeight, chromaPartWidth + 1); + pRef += width * height; + h264bsdFillBlock(pRef, block + (chromaPartWidth+1)*chromaPartHeight, + x0, y0, width, height, chromaPartWidth + 1, + chromaPartHeight, chromaPartWidth + 1); + + pRef = block; + x0 = 0; + y0 = 0; + width = chromaPartWidth+1; + height = chromaPartHeight; + } + + val = 8 - xFrac; + + for (comp = 0; comp <= 1; comp++) + { + + ptrA = pRef + (comp * height + (u32)y0) * width + x0; + cbr = predPartChroma + comp * 8 * 8; + + /* 2x2 pels per iteration + * bilinear horizontal interpolation */ + for (y = (chromaPartHeight >> 1); y; y--) + { + for (x = (chromaPartWidth >> 1); x; x--) + { + tmp1 = ptrA[width]; + tmp2 = *ptrA++; + tmp3 = ptrA[width]; + tmp4 = *ptrA++; + c = ((val * tmp1 + xFrac * tmp3) << 3) + 32; + c >>= 6; + cbr[8] = (u8)c; + c = ((val * tmp2 + xFrac * tmp4) << 3) + 32; + c >>= 6; + *cbr++ = (u8)c; + tmp1 = ptrA[width]; + tmp2 = *ptrA; + c = ((val * tmp3 + xFrac * tmp1) << 3) + 32; + c >>= 6; + cbr[8] = (u8)c; + c = ((val * tmp4 + xFrac * tmp2) << 3) + 32; + c >>= 6; + *cbr++ = (u8)c; + } + cbr += 2*8 - chromaPartWidth; + ptrA += 2*width - chromaPartWidth; + } + } + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdInterpolateChromaVer + + Functional description: + This function performs chroma interpolation in vertical direction. + Overfilling is done only if needed. Reference image (pRef) is + read at correct position and the predicted part is written to + macroblock's chrominance (predPartChroma) + +------------------------------------------------------------------------------*/ + +void h264bsdInterpolateChromaVer( + u8 *pRef, + u8 *predPartChroma, + i32 x0, + i32 y0, + u32 width, + u32 height, + u32 yFrac, + u32 chromaPartWidth, + u32 chromaPartHeight) +{ + +/* Variables */ + + u32 x, y, tmp1, tmp2, tmp3, c, val; + u8 *ptrA, *cbr; + u32 comp; + u8 block[9*8*2]; + +/* Code */ + + ASSERT(predPartChroma); + ASSERT(chromaPartWidth); + ASSERT(chromaPartHeight); + ASSERT(yFrac < 8); + ASSERT(pRef); + + if ((x0 < 0) || ((u32)x0+chromaPartWidth > width) || + (y0 < 0) || ((u32)y0+chromaPartHeight+1 > height)) + { + h264bsdFillBlock(pRef, block, x0, y0, width, height, chromaPartWidth, + chromaPartHeight + 1, chromaPartWidth); + pRef += width * height; + h264bsdFillBlock(pRef, block + chromaPartWidth*(chromaPartHeight+1), + x0, y0, width, height, chromaPartWidth, + chromaPartHeight + 1, chromaPartWidth); + + pRef = block; + x0 = 0; + y0 = 0; + width = chromaPartWidth; + height = chromaPartHeight+1; + } + + val = 8 - yFrac; + + for (comp = 0; comp <= 1; comp++) + { + + ptrA = pRef + (comp * height + (u32)y0) * width + x0; + cbr = predPartChroma + comp * 8 * 8; + + /* 2x2 pels per iteration + * bilinear vertical interpolation */ + for (y = (chromaPartHeight >> 1); y; y--) + { + for (x = (chromaPartWidth >> 1); x; x--) + { + tmp3 = ptrA[width*2]; + tmp2 = ptrA[width]; + tmp1 = *ptrA++; + c = ((val * tmp2 + yFrac * tmp3) << 3) + 32; + c >>= 6; + cbr[8] = (u8)c; + c = ((val * tmp1 + yFrac * tmp2) << 3) + 32; + c >>= 6; + *cbr++ = (u8)c; + tmp3 = ptrA[width*2]; + tmp2 = ptrA[width]; + tmp1 = *ptrA++; + c = ((val * tmp2 + yFrac * tmp3) << 3) + 32; + c >>= 6; + cbr[8] = (u8)c; + c = ((val * tmp1 + yFrac * tmp2) << 3) + 32; + c >>= 6; + *cbr++ = (u8)c; + } + cbr += 2*8 - chromaPartWidth; + ptrA += 2*width - chromaPartWidth; + } + } + +} +#endif +/*------------------------------------------------------------------------------ + + Function: h264bsdInterpolateChromaHorVer + + Functional description: + This function performs chroma interpolation in horizontal and + vertical direction. Overfilling is done only if needed. Reference + image (ref) is read at correct position and the predicted part + is written to macroblock's chrominance (predPartChroma) + +------------------------------------------------------------------------------*/ + +void h264bsdInterpolateChromaHorVer( + u8 *ref, + u8 *predPartChroma, + i32 x0, + i32 y0, + u32 width, + u32 height, + u32 xFrac, + u32 yFrac, + u32 chromaPartWidth, + u32 chromaPartHeight) +{ + u8 block[9*9*2]; + u32 x, y, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, valX, valY, plus32 = 32; + u32 comp; + u8 *ptrA, *cbr; + +/* Code */ + + ASSERT(predPartChroma); + ASSERT(chromaPartWidth); + ASSERT(chromaPartHeight); + ASSERT(xFrac < 8); + ASSERT(yFrac < 8); + ASSERT(ref); + + if ((x0 < 0) || ((u32)x0+chromaPartWidth+1 > width) || + (y0 < 0) || ((u32)y0+chromaPartHeight+1 > height)) + { + h264bsdFillBlock(ref, block, x0, y0, width, height, + chromaPartWidth + 1, chromaPartHeight + 1, chromaPartWidth + 1); + ref += width * height; + h264bsdFillBlock(ref, block + (chromaPartWidth+1)*(chromaPartHeight+1), + x0, y0, width, height, chromaPartWidth + 1, + chromaPartHeight + 1, chromaPartWidth + 1); + + ref = block; + x0 = 0; + y0 = 0; + width = chromaPartWidth+1; + height = chromaPartHeight+1; + } + + valX = 8 - xFrac; + valY = 8 - yFrac; + + for (comp = 0; comp <= 1; comp++) + { + + ptrA = ref + (comp * height + (u32)y0) * width + x0; + cbr = predPartChroma + comp * 8 * 8; + + /* 2x2 pels per iteration + * bilinear vertical and horizontal interpolation */ + for (y = (chromaPartHeight >> 1); y; y--) + { + tmp1 = *ptrA; + tmp3 = ptrA[width]; + tmp5 = ptrA[width*2]; + tmp1 *= valY; + tmp1 += tmp3 * yFrac; + tmp3 *= valY; + tmp3 += tmp5 * yFrac; + for (x = (chromaPartWidth >> 1); x; x--) + { + tmp2 = *++ptrA; + tmp4 = ptrA[width]; + tmp6 = ptrA[width*2]; + tmp2 *= valY; + tmp2 += tmp4 * yFrac; + tmp4 *= valY; + tmp4 += tmp6 * yFrac; + tmp1 = tmp1 * valX + plus32; + tmp3 = tmp3 * valX + plus32; + tmp1 += tmp2 * xFrac; + tmp1 >>= 6; + tmp3 += tmp4 * xFrac; + tmp3 >>= 6; + cbr[8] = (u8)tmp3; + *cbr++ = (u8)tmp1; + + tmp1 = *++ptrA; + tmp3 = ptrA[width]; + tmp5 = ptrA[width*2]; + tmp1 *= valY; + tmp1 += tmp3 * yFrac; + tmp3 *= valY; + tmp3 += tmp5 * yFrac; + tmp2 = tmp2 * valX + plus32; + tmp4 = tmp4 * valX + plus32; + tmp2 += tmp1 * xFrac; + tmp2 >>= 6; + tmp4 += tmp3 * xFrac; + tmp4 >>= 6; + cbr[8] = (u8)tmp4; + *cbr++ = (u8)tmp2; + } + cbr += 2*8 - chromaPartWidth; + ptrA += 2*width - chromaPartWidth; + } + } + +} + +/*------------------------------------------------------------------------------ + + Function: PredictChroma + + Functional description: + Top level chroma prediction function that calls the appropriate + interpolation function. The output is written to macroblock array. + +------------------------------------------------------------------------------*/ + +static void PredictChroma( + u8 *mbPartChroma, + u32 xAL, + u32 yAL, + u32 partWidth, + u32 partHeight, + mv_t *mv, + image_t *refPic) +{ + +/* Variables */ + + u32 xFrac, yFrac, width, height, chromaPartWidth, chromaPartHeight; + i32 xInt, yInt; + u8 *ref; + +/* Code */ + + ASSERT(mv); + ASSERT(refPic); + ASSERT(refPic->data); + ASSERT(refPic->width); + ASSERT(refPic->height); + + width = 8 * refPic->width; + height = 8 * refPic->height; + + xInt = (xAL >> 1) + (mv->hor >> 3); + yInt = (yAL >> 1) + (mv->ver >> 3); + xFrac = mv->hor & 0x7; + yFrac = mv->ver & 0x7; + + chromaPartWidth = partWidth >> 1; + chromaPartHeight = partHeight >> 1; + ref = refPic->data + 256 * refPic->width * refPic->height; + + if (xFrac && yFrac) + { + h264bsdInterpolateChromaHorVer(ref, mbPartChroma, xInt, yInt, width, + height, xFrac, yFrac, chromaPartWidth, chromaPartHeight); + } + else if (xFrac) + { + h264bsdInterpolateChromaHor(ref, mbPartChroma, xInt, yInt, width, + height, xFrac, chromaPartWidth, chromaPartHeight); + } + else if (yFrac) + { + h264bsdInterpolateChromaVer(ref, mbPartChroma, xInt, yInt, width, + height, yFrac, chromaPartWidth, chromaPartHeight); + } + else + { + h264bsdFillBlock(ref, mbPartChroma, xInt, yInt, width, height, + chromaPartWidth, chromaPartHeight, 8); + ref += width * height; + h264bsdFillBlock(ref, mbPartChroma + 8*8, xInt, yInt, width, height, + chromaPartWidth, chromaPartHeight, 8); + } + +} + + +/*------------------------------------------------------------------------------ + + Function: h264bsdInterpolateVerHalf + + Functional description: + Function to perform vertical interpolation of pixel position 'h' + for a block. Overfilling is done only if needed. Reference + image (ref) is read at correct position and the predicted part + is written to macroblock array (mb) + +------------------------------------------------------------------------------*/ +#ifndef H264DEC_ARM11 +void h264bsdInterpolateVerHalf( + u8 *ref, + u8 *mb, + i32 x0, + i32 y0, + u32 width, + u32 height, + u32 partWidth, + u32 partHeight) +{ + u32 p1[21*21/4+1]; + u32 i, j; + i32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + u8 *ptrC, *ptrV; + const u8 *clp = h264bsdClip + 512; + + /* Code */ + + ASSERT(ref); + ASSERT(mb); + + if ((x0 < 0) || ((u32)x0+partWidth > width) || + (y0 < 0) || ((u32)y0+partHeight+5 > height)) + { + h264bsdFillBlock(ref, (u8*)p1, x0, y0, width, height, + partWidth, partHeight+5, partWidth); + + x0 = 0; + y0 = 0; + ref = (u8*)p1; + width = partWidth; + } + + ref += (u32)y0 * width + (u32)x0; + + ptrC = ref + width; + ptrV = ptrC + 5*width; + + /* 4 pixels per iteration, interpolate using 5 vertical samples */ + for (i = (partHeight >> 2); i; i--) + { + /* h1 = (16 + A + 16(G+M) + 4(G+M) - 4(C+R) - (C+R) + T) >> 5 */ + for (j = partWidth; j; j--) + { + tmp4 = ptrV[-(i32)width*2]; + tmp5 = ptrV[-(i32)width]; + tmp1 = ptrV[width]; + tmp2 = ptrV[width*2]; + tmp6 = *ptrV++; + + tmp7 = tmp4 + tmp1; + tmp2 -= (tmp7 << 2); + tmp2 -= tmp7; + tmp2 += 16; + tmp7 = tmp5 + tmp6; + tmp3 = ptrC[width*2]; + tmp2 += (tmp7 << 4); + tmp2 += (tmp7 << 2); + tmp2 += tmp3; + tmp2 = clp[tmp2>>5]; + tmp1 += 16; + mb[48] = (u8)tmp2; + + tmp7 = tmp3 + tmp6; + tmp1 -= (tmp7 << 2); + tmp1 -= tmp7; + tmp7 = tmp4 + tmp5; + tmp2 = ptrC[width]; + tmp1 += (tmp7 << 4); + tmp1 += (tmp7 << 2); + tmp1 += tmp2; + tmp1 = clp[tmp1>>5]; + tmp6 += 16; + mb[32] = (u8)tmp1; + + tmp7 = tmp2 + tmp5; + tmp6 -= (tmp7 << 2); + tmp6 -= tmp7; + tmp7 = tmp4 + tmp3; + tmp1 = *ptrC; + tmp6 += (tmp7 << 4); + tmp6 += (tmp7 << 2); + tmp6 += tmp1; + tmp6 = clp[tmp6>>5]; + tmp5 += 16; + mb[16] = (u8)tmp6; + + tmp1 += tmp4; + tmp5 -= (tmp1 << 2); + tmp5 -= tmp1; + tmp3 += tmp2; + tmp6 = ptrC[-(i32)width]; + tmp5 += (tmp3 << 4); + tmp5 += (tmp3 << 2); + tmp5 += tmp6; + tmp5 = clp[tmp5>>5]; + *mb++ = (u8)tmp5; + ptrC++; + } + ptrC += 4*width - partWidth; + ptrV += 4*width - partWidth; + mb += 4*16 - partWidth; + } + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdInterpolateVerQuarter + + Functional description: + Function to perform vertical interpolation of pixel position 'd' + or 'n' for a block. Overfilling is done only if needed. Reference + image (ref) is read at correct position and the predicted part + is written to macroblock array (mb) + +------------------------------------------------------------------------------*/ + +void h264bsdInterpolateVerQuarter( + u8 *ref, + u8 *mb, + i32 x0, + i32 y0, + u32 width, + u32 height, + u32 partWidth, + u32 partHeight, + u32 verOffset) /* 0 for pixel d, 1 for pixel n */ +{ + u32 p1[21*21/4+1]; + u32 i, j; + i32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + u8 *ptrC, *ptrV, *ptrInt; + const u8 *clp = h264bsdClip + 512; + + /* Code */ + + ASSERT(ref); + ASSERT(mb); + + if ((x0 < 0) || ((u32)x0+partWidth > width) || + (y0 < 0) || ((u32)y0+partHeight+5 > height)) + { + h264bsdFillBlock(ref, (u8*)p1, x0, y0, width, height, + partWidth, partHeight+5, partWidth); + + x0 = 0; + y0 = 0; + ref = (u8*)p1; + width = partWidth; + } + + ref += (u32)y0 * width + (u32)x0; + + ptrC = ref + width; + ptrV = ptrC + 5*width; + + /* Pointer to integer sample position, either M or R */ + ptrInt = ptrC + (2+verOffset)*width; + + /* 4 pixels per iteration + * interpolate using 5 vertical samples and average between + * interpolated value and integer sample value */ + for (i = (partHeight >> 2); i; i--) + { + /* h1 = (16 + A + 16(G+M) + 4(G+M) - 4(C+R) - (C+R) + T) >> 5 */ + for (j = partWidth; j; j--) + { + tmp4 = ptrV[-(i32)width*2]; + tmp5 = ptrV[-(i32)width]; + tmp1 = ptrV[width]; + tmp2 = ptrV[width*2]; + tmp6 = *ptrV++; + + tmp7 = tmp4 + tmp1; + tmp2 -= (tmp7 << 2); + tmp2 -= tmp7; + tmp2 += 16; + tmp7 = tmp5 + tmp6; + tmp3 = ptrC[width*2]; + tmp2 += (tmp7 << 4); + tmp2 += (tmp7 << 2); + tmp2 += tmp3; + tmp2 = clp[tmp2>>5]; + tmp7 = ptrInt[width*2]; + tmp1 += 16; + tmp2++; + mb[48] = (u8)((tmp2 + tmp7) >> 1); + + tmp7 = tmp3 + tmp6; + tmp1 -= (tmp7 << 2); + tmp1 -= tmp7; + tmp7 = tmp4 + tmp5; + tmp2 = ptrC[width]; + tmp1 += (tmp7 << 4); + tmp1 += (tmp7 << 2); + tmp1 += tmp2; + tmp1 = clp[tmp1>>5]; + tmp7 = ptrInt[width]; + tmp6 += 16; + tmp1++; + mb[32] = (u8)((tmp1 + tmp7) >> 1); + + tmp7 = tmp2 + tmp5; + tmp6 -= (tmp7 << 2); + tmp6 -= tmp7; + tmp7 = tmp4 + tmp3; + tmp1 = *ptrC; + tmp6 += (tmp7 << 4); + tmp6 += (tmp7 << 2); + tmp6 += tmp1; + tmp6 = clp[tmp6>>5]; + tmp7 = *ptrInt; + tmp5 += 16; + tmp6++; + mb[16] = (u8)((tmp6 + tmp7) >> 1); + + tmp1 += tmp4; + tmp5 -= (tmp1 << 2); + tmp5 -= tmp1; + tmp3 += tmp2; + tmp6 = ptrC[-(i32)width]; + tmp5 += (tmp3 << 4); + tmp5 += (tmp3 << 2); + tmp5 += tmp6; + tmp5 = clp[tmp5>>5]; + tmp7 = ptrInt[-(i32)width]; + tmp5++; + *mb++ = (u8)((tmp5 + tmp7) >> 1); + ptrC++; + ptrInt++; + } + ptrC += 4*width - partWidth; + ptrV += 4*width - partWidth; + ptrInt += 4*width - partWidth; + mb += 4*16 - partWidth; + } + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdInterpolateHorHalf + + Functional description: + Function to perform horizontal interpolation of pixel position 'b' + for a block. Overfilling is done only if needed. Reference + image (ref) is read at correct position and the predicted part + is written to macroblock array (mb) + +------------------------------------------------------------------------------*/ + +void h264bsdInterpolateHorHalf( + u8 *ref, + u8 *mb, + i32 x0, + i32 y0, + u32 width, + u32 height, + u32 partWidth, + u32 partHeight) +{ + u32 p1[21*21/4+1]; + u8 *ptrJ; + u32 x, y; + i32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + const u8 *clp = h264bsdClip + 512; + + /* Code */ + + ASSERT(ref); + ASSERT(mb); + ASSERT((partWidth&0x3) == 0); + ASSERT((partHeight&0x3) == 0); + + if ((x0 < 0) || ((u32)x0+partWidth+5 > width) || + (y0 < 0) || ((u32)y0+partHeight > height)) + { + h264bsdFillBlock(ref, (u8*)p1, x0, y0, width, height, + partWidth+5, partHeight, partWidth+5); + + x0 = 0; + y0 = 0; + ref = (u8*)p1; + width = partWidth + 5; + } + + ref += (u32)y0 * width + (u32)x0; + + ptrJ = ref + 5; + + for (y = partHeight; y; y--) + { + tmp6 = *(ptrJ - 5); + tmp5 = *(ptrJ - 4); + tmp4 = *(ptrJ - 3); + tmp3 = *(ptrJ - 2); + tmp2 = *(ptrJ - 1); + + /* calculate 4 pels per iteration */ + for (x = (partWidth >> 2); x; x--) + { + /* First pixel */ + tmp6 += 16; + tmp7 = tmp3 + tmp4; + tmp6 += (tmp7 << 4); + tmp6 += (tmp7 << 2); + tmp7 = tmp2 + tmp5; + tmp1 = *ptrJ++; + tmp6 -= (tmp7 << 2); + tmp6 -= tmp7; + tmp6 += tmp1; + tmp6 = clp[tmp6>>5]; + /* Second pixel */ + tmp5 += 16; + tmp7 = tmp2 + tmp3; + *mb++ = (u8)tmp6; + tmp5 += (tmp7 << 4); + tmp5 += (tmp7 << 2); + tmp7 = tmp1 + tmp4; + tmp6 = *ptrJ++; + tmp5 -= (tmp7 << 2); + tmp5 -= tmp7; + tmp5 += tmp6; + tmp5 = clp[tmp5>>5]; + /* Third pixel */ + tmp4 += 16; + tmp7 = tmp1 + tmp2; + *mb++ = (u8)tmp5; + tmp4 += (tmp7 << 4); + tmp4 += (tmp7 << 2); + tmp7 = tmp6 + tmp3; + tmp5 = *ptrJ++; + tmp4 -= (tmp7 << 2); + tmp4 -= tmp7; + tmp4 += tmp5; + tmp4 = clp[tmp4>>5]; + /* Fourth pixel */ + tmp3 += 16; + tmp7 = tmp6 + tmp1; + *mb++ = (u8)tmp4; + tmp3 += (tmp7 << 4); + tmp3 += (tmp7 << 2); + tmp7 = tmp5 + tmp2; + tmp4 = *ptrJ++; + tmp3 -= (tmp7 << 2); + tmp3 -= tmp7; + tmp3 += tmp4; + tmp3 = clp[tmp3>>5]; + tmp7 = tmp4; + tmp4 = tmp6; + tmp6 = tmp2; + tmp2 = tmp7; + *mb++ = (u8)tmp3; + tmp3 = tmp5; + tmp5 = tmp1; + } + ptrJ += width - partWidth; + mb += 16 - partWidth; + } + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdInterpolateHorQuarter + + Functional description: + Function to perform horizontal interpolation of pixel position 'a' + or 'c' for a block. Overfilling is done only if needed. Reference + image (ref) is read at correct position and the predicted part + is written to macroblock array (mb) + +------------------------------------------------------------------------------*/ + +void h264bsdInterpolateHorQuarter( + u8 *ref, + u8 *mb, + i32 x0, + i32 y0, + u32 width, + u32 height, + u32 partWidth, + u32 partHeight, + u32 horOffset) /* 0 for pixel a, 1 for pixel c */ +{ + u32 p1[21*21/4+1]; + u8 *ptrJ; + u32 x, y; + i32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + const u8 *clp = h264bsdClip + 512; + + /* Code */ + + ASSERT(ref); + ASSERT(mb); + + if ((x0 < 0) || ((u32)x0+partWidth+5 > width) || + (y0 < 0) || ((u32)y0+partHeight > height)) + { + h264bsdFillBlock(ref, (u8*)p1, x0, y0, width, height, + partWidth+5, partHeight, partWidth+5); + + x0 = 0; + y0 = 0; + ref = (u8*)p1; + width = partWidth + 5; + } + + ref += (u32)y0 * width + (u32)x0; + + ptrJ = ref + 5; + + for (y = partHeight; y; y--) + { + tmp6 = *(ptrJ - 5); + tmp5 = *(ptrJ - 4); + tmp4 = *(ptrJ - 3); + tmp3 = *(ptrJ - 2); + tmp2 = *(ptrJ - 1); + + /* calculate 4 pels per iteration */ + for (x = (partWidth >> 2); x; x--) + { + /* First pixel */ + tmp6 += 16; + tmp7 = tmp3 + tmp4; + tmp6 += (tmp7 << 4); + tmp6 += (tmp7 << 2); + tmp7 = tmp2 + tmp5; + tmp1 = *ptrJ++; + tmp6 -= (tmp7 << 2); + tmp6 -= tmp7; + tmp6 += tmp1; + tmp6 = clp[tmp6>>5]; + tmp5 += 16; + if (!horOffset) + tmp6 += tmp4; + else + tmp6 += tmp3; + *mb++ = (u8)((tmp6 + 1) >> 1); + /* Second pixel */ + tmp7 = tmp2 + tmp3; + tmp5 += (tmp7 << 4); + tmp5 += (tmp7 << 2); + tmp7 = tmp1 + tmp4; + tmp6 = *ptrJ++; + tmp5 -= (tmp7 << 2); + tmp5 -= tmp7; + tmp5 += tmp6; + tmp5 = clp[tmp5>>5]; + tmp4 += 16; + if (!horOffset) + tmp5 += tmp3; + else + tmp5 += tmp2; + *mb++ = (u8)((tmp5 + 1) >> 1); + /* Third pixel */ + tmp7 = tmp1 + tmp2; + tmp4 += (tmp7 << 4); + tmp4 += (tmp7 << 2); + tmp7 = tmp6 + tmp3; + tmp5 = *ptrJ++; + tmp4 -= (tmp7 << 2); + tmp4 -= tmp7; + tmp4 += tmp5; + tmp4 = clp[tmp4>>5]; + tmp3 += 16; + if (!horOffset) + tmp4 += tmp2; + else + tmp4 += tmp1; + *mb++ = (u8)((tmp4 + 1) >> 1); + /* Fourth pixel */ + tmp7 = tmp6 + tmp1; + tmp3 += (tmp7 << 4); + tmp3 += (tmp7 << 2); + tmp7 = tmp5 + tmp2; + tmp4 = *ptrJ++; + tmp3 -= (tmp7 << 2); + tmp3 -= tmp7; + tmp3 += tmp4; + tmp3 = clp[tmp3>>5]; + if (!horOffset) + tmp3 += tmp1; + else + tmp3 += tmp6; + *mb++ = (u8)((tmp3 + 1) >> 1); + tmp3 = tmp5; + tmp5 = tmp1; + tmp7 = tmp4; + tmp4 = tmp6; + tmp6 = tmp2; + tmp2 = tmp7; + } + ptrJ += width - partWidth; + mb += 16 - partWidth; + } + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdInterpolateHorVerQuarter + + Functional description: + Function to perform horizontal and vertical interpolation of pixel + position 'e', 'g', 'p' or 'r' for a block. Overfilling is done only + if needed. Reference image (ref) is read at correct position and + the predicted part is written to macroblock array (mb) + +------------------------------------------------------------------------------*/ + +void h264bsdInterpolateHorVerQuarter( + u8 *ref, + u8 *mb, + i32 x0, + i32 y0, + u32 width, + u32 height, + u32 partWidth, + u32 partHeight, + u32 horVerOffset) /* 0 for pixel e, 1 for pixel g, + 2 for pixel p, 3 for pixel r */ +{ + u32 p1[21*21/4+1]; + u8 *ptrC, *ptrJ, *ptrV; + u32 x, y; + i32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + const u8 *clp = h264bsdClip + 512; + + /* Code */ + + ASSERT(ref); + ASSERT(mb); + + if ((x0 < 0) || ((u32)x0+partWidth+5 > width) || + (y0 < 0) || ((u32)y0+partHeight+5 > height)) + { + h264bsdFillBlock(ref, (u8*)p1, x0, y0, width, height, + partWidth+5, partHeight+5, partWidth+5); + + x0 = 0; + y0 = 0; + ref = (u8*)p1; + width = partWidth+5; + } + + /* Ref points to G + (-2, -2) */ + ref += (u32)y0 * width + (u32)x0; + + /* ptrJ points to either J or Q, depending on vertical offset */ + ptrJ = ref + (((horVerOffset & 0x2) >> 1) + 2) * width + 5; + + /* ptrC points to either C or D, depending on horizontal offset */ + ptrC = ref + width + 2 + (horVerOffset & 0x1); + + for (y = partHeight; y; y--) + { + tmp6 = *(ptrJ - 5); + tmp5 = *(ptrJ - 4); + tmp4 = *(ptrJ - 3); + tmp3 = *(ptrJ - 2); + tmp2 = *(ptrJ - 1); + + /* Horizontal interpolation, calculate 4 pels per iteration */ + for (x = (partWidth >> 2); x; x--) + { + /* First pixel */ + tmp6 += 16; + tmp7 = tmp3 + tmp4; + tmp6 += (tmp7 << 4); + tmp6 += (tmp7 << 2); + tmp7 = tmp2 + tmp5; + tmp1 = *ptrJ++; + tmp6 -= (tmp7 << 2); + tmp6 -= tmp7; + tmp6 += tmp1; + tmp6 = clp[tmp6>>5]; + /* Second pixel */ + tmp5 += 16; + tmp7 = tmp2 + tmp3; + *mb++ = (u8)tmp6; + tmp5 += (tmp7 << 4); + tmp5 += (tmp7 << 2); + tmp7 = tmp1 + tmp4; + tmp6 = *ptrJ++; + tmp5 -= (tmp7 << 2); + tmp5 -= tmp7; + tmp5 += tmp6; + tmp5 = clp[tmp5>>5]; + /* Third pixel */ + tmp4 += 16; + tmp7 = tmp1 + tmp2; + *mb++ = (u8)tmp5; + tmp4 += (tmp7 << 4); + tmp4 += (tmp7 << 2); + tmp7 = tmp6 + tmp3; + tmp5 = *ptrJ++; + tmp4 -= (tmp7 << 2); + tmp4 -= tmp7; + tmp4 += tmp5; + tmp4 = clp[tmp4>>5]; + /* Fourth pixel */ + tmp3 += 16; + tmp7 = tmp6 + tmp1; + *mb++ = (u8)tmp4; + tmp3 += (tmp7 << 4); + tmp3 += (tmp7 << 2); + tmp7 = tmp5 + tmp2; + tmp4 = *ptrJ++; + tmp3 -= (tmp7 << 2); + tmp3 -= tmp7; + tmp3 += tmp4; + tmp3 = clp[tmp3>>5]; + tmp7 = tmp4; + tmp4 = tmp6; + tmp6 = tmp2; + tmp2 = tmp7; + *mb++ = (u8)tmp3; + tmp3 = tmp5; + tmp5 = tmp1; + } + ptrJ += width - partWidth; + mb += 16 - partWidth; + } + + mb -= 16*partHeight; + ptrV = ptrC + 5*width; + + for (y = (partHeight >> 2); y; y--) + { + /* Vertical interpolation and averaging, 4 pels per iteration */ + for (x = partWidth; x; x--) + { + tmp4 = ptrV[-(i32)width*2]; + tmp5 = ptrV[-(i32)width]; + tmp1 = ptrV[width]; + tmp2 = ptrV[width*2]; + tmp6 = *ptrV++; + + tmp7 = tmp4 + tmp1; + tmp2 -= (tmp7 << 2); + tmp2 -= tmp7; + tmp2 += 16; + tmp7 = tmp5 + tmp6; + tmp3 = ptrC[width*2]; + tmp2 += (tmp7 << 4); + tmp2 += (tmp7 << 2); + tmp2 += tmp3; + tmp7 = clp[tmp2>>5]; + tmp2 = mb[48]; + tmp1 += 16; + tmp7++; + mb[48] = (u8)((tmp2 + tmp7) >> 1); + + tmp7 = tmp3 + tmp6; + tmp1 -= (tmp7 << 2); + tmp1 -= tmp7; + tmp7 = tmp4 + tmp5; + tmp2 = ptrC[width]; + tmp1 += (tmp7 << 4); + tmp1 += (tmp7 << 2); + tmp1 += tmp2; + tmp7 = clp[tmp1>>5]; + tmp1 = mb[32]; + tmp6 += 16; + tmp7++; + mb[32] = (u8)((tmp1 + tmp7) >> 1); + + tmp1 = *ptrC; + tmp7 = tmp2 + tmp5; + tmp6 -= (tmp7 << 2); + tmp6 -= tmp7; + tmp7 = tmp4 + tmp3; + tmp6 += (tmp7 << 4); + tmp6 += (tmp7 << 2); + tmp6 += tmp1; + tmp7 = clp[tmp6>>5]; + tmp6 = mb[16]; + tmp5 += 16; + tmp7++; + mb[16] = (u8)((tmp6 + tmp7) >> 1); + + tmp6 = ptrC[-(i32)width]; + tmp1 += tmp4; + tmp5 -= (tmp1 << 2); + tmp5 -= tmp1; + tmp3 += tmp2; + tmp5 += (tmp3 << 4); + tmp5 += (tmp3 << 2); + tmp5 += tmp6; + tmp7 = clp[tmp5>>5]; + tmp5 = *mb; + tmp7++; + *mb++ = (u8)((tmp5 + tmp7) >> 1); + ptrC++; + + } + ptrC += 4*width - partWidth; + ptrV += 4*width - partWidth; + mb += 4*16 - partWidth; + } + +} +#endif + +/*------------------------------------------------------------------------------ + + Function: h264bsdInterpolateMidHalf + + Functional description: + Function to perform horizontal and vertical interpolation of pixel + position 'j' for a block. Overfilling is done only if needed. + Reference image (ref) is read at correct position and the predicted + part is written to macroblock array (mb) + +------------------------------------------------------------------------------*/ + +void h264bsdInterpolateMidHalf( + u8 *ref, + u8 *mb, + i32 x0, + i32 y0, + u32 width, + u32 height, + u32 partWidth, + u32 partHeight) +{ + u32 p1[21*21/4+1]; + u32 x, y; + i32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + i32 *ptrC, *ptrV, *b1; + u8 *ptrJ; + i32 table[21*16]; + const u8 *clp = h264bsdClip + 512; + + /* Code */ + + ASSERT(ref); + ASSERT(mb); + + if ((x0 < 0) || ((u32)x0+partWidth+5 > width) || + (y0 < 0) || ((u32)y0+partHeight+5 > height)) + { + h264bsdFillBlock(ref, (u8*)p1, x0, y0, width, height, + partWidth+5, partHeight+5, partWidth+5); + + x0 = 0; + y0 = 0; + ref = (u8*)p1; + width = partWidth+5; + } + + ref += (u32)y0 * width + (u32)x0; + + b1 = table; + ptrJ = ref + 5; + + /* First step: calculate intermediate values for + * horizontal interpolation */ + for (y = partHeight + 5; y; y--) + { + tmp6 = *(ptrJ - 5); + tmp5 = *(ptrJ - 4); + tmp4 = *(ptrJ - 3); + tmp3 = *(ptrJ - 2); + tmp2 = *(ptrJ - 1); + + /* 4 pels per iteration */ + for (x = (partWidth >> 2); x; x--) + { + /* First pixel */ + tmp7 = tmp3 + tmp4; + tmp6 += (tmp7 << 4); + tmp6 += (tmp7 << 2); + tmp7 = tmp2 + tmp5; + tmp1 = *ptrJ++; + tmp6 -= (tmp7 << 2); + tmp6 -= tmp7; + tmp6 += tmp1; + *b1++ = tmp6; + /* Second pixel */ + tmp7 = tmp2 + tmp3; + tmp5 += (tmp7 << 4); + tmp5 += (tmp7 << 2); + tmp7 = tmp1 + tmp4; + tmp6 = *ptrJ++; + tmp5 -= (tmp7 << 2); + tmp5 -= tmp7; + tmp5 += tmp6; + *b1++ = tmp5; + /* Third pixel */ + tmp7 = tmp1 + tmp2; + tmp4 += (tmp7 << 4); + tmp4 += (tmp7 << 2); + tmp7 = tmp6 + tmp3; + tmp5 = *ptrJ++; + tmp4 -= (tmp7 << 2); + tmp4 -= tmp7; + tmp4 += tmp5; + *b1++ = tmp4; + /* Fourth pixel */ + tmp7 = tmp6 + tmp1; + tmp3 += (tmp7 << 4); + tmp3 += (tmp7 << 2); + tmp7 = tmp5 + tmp2; + tmp4 = *ptrJ++; + tmp3 -= (tmp7 << 2); + tmp3 -= tmp7; + tmp3 += tmp4; + *b1++ = tmp3; + tmp7 = tmp4; + tmp4 = tmp6; + tmp6 = tmp2; + tmp2 = tmp7; + tmp3 = tmp5; + tmp5 = tmp1; + } + ptrJ += width - partWidth; + } + + /* Second step: calculate vertical interpolation */ + ptrC = table + partWidth; + ptrV = ptrC + 5*partWidth; + for (y = (partHeight >> 2); y; y--) + { + /* 4 pels per iteration */ + for (x = partWidth; x; x--) + { + tmp4 = ptrV[-(i32)partWidth*2]; + tmp5 = ptrV[-(i32)partWidth]; + tmp1 = ptrV[partWidth]; + tmp2 = ptrV[partWidth*2]; + tmp6 = *ptrV++; + + tmp7 = tmp4 + tmp1; + tmp2 -= (tmp7 << 2); + tmp2 -= tmp7; + tmp2 += 512; + tmp7 = tmp5 + tmp6; + tmp3 = ptrC[partWidth*2]; + tmp2 += (tmp7 << 4); + tmp2 += (tmp7 << 2); + tmp2 += tmp3; + tmp7 = clp[tmp2>>10]; + tmp1 += 512; + mb[48] = (u8)tmp7; + + tmp7 = tmp3 + tmp6; + tmp1 -= (tmp7 << 2); + tmp1 -= tmp7; + tmp7 = tmp4 + tmp5; + tmp2 = ptrC[partWidth]; + tmp1 += (tmp7 << 4); + tmp1 += (tmp7 << 2); + tmp1 += tmp2; + tmp7 = clp[tmp1>>10]; + tmp6 += 512; + mb[32] = (u8)tmp7; + + tmp1 = *ptrC; + tmp7 = tmp2 + tmp5; + tmp6 -= (tmp7 << 2); + tmp6 -= tmp7; + tmp7 = tmp4 + tmp3; + tmp6 += (tmp7 << 4); + tmp6 += (tmp7 << 2); + tmp6 += tmp1; + tmp7 = clp[tmp6>>10]; + tmp5 += 512; + mb[16] = (u8)tmp7; + + tmp6 = ptrC[-(i32)partWidth]; + tmp1 += tmp4; + tmp5 -= (tmp1 << 2); + tmp5 -= tmp1; + tmp3 += tmp2; + tmp5 += (tmp3 << 4); + tmp5 += (tmp3 << 2); + tmp5 += tmp6; + tmp7 = clp[tmp5>>10]; + *mb++ = (u8)tmp7; + ptrC++; + } + mb += 4*16 - partWidth; + ptrC += 3*partWidth; + ptrV += 3*partWidth; + } + +} + + +/*------------------------------------------------------------------------------ + + Function: h264bsdInterpolateMidVerQuarter + + Functional description: + Function to perform horizontal and vertical interpolation of pixel + position 'f' or 'q' for a block. Overfilling is done only if needed. + Reference image (ref) is read at correct position and the predicted + part is written to macroblock array (mb) + +------------------------------------------------------------------------------*/ + +void h264bsdInterpolateMidVerQuarter( + u8 *ref, + u8 *mb, + i32 x0, + i32 y0, + u32 width, + u32 height, + u32 partWidth, + u32 partHeight, + u32 verOffset) /* 0 for pixel f, 1 for pixel q */ +{ + u32 p1[21*21/4+1]; + u32 x, y; + i32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + i32 *ptrC, *ptrV, *ptrInt, *b1; + u8 *ptrJ; + i32 table[21*16]; + const u8 *clp = h264bsdClip + 512; + + /* Code */ + + ASSERT(ref); + ASSERT(mb); + + if ((x0 < 0) || ((u32)x0+partWidth+5 > width) || + (y0 < 0) || ((u32)y0+partHeight+5 > height)) + { + h264bsdFillBlock(ref, (u8*)p1, x0, y0, width, height, + partWidth+5, partHeight+5, partWidth+5); + + x0 = 0; + y0 = 0; + ref = (u8*)p1; + width = partWidth+5; + } + + ref += (u32)y0 * width + (u32)x0; + + b1 = table; + ptrJ = ref + 5; + + /* First step: calculate intermediate values for + * horizontal interpolation */ + for (y = partHeight + 5; y; y--) + { + tmp6 = *(ptrJ - 5); + tmp5 = *(ptrJ - 4); + tmp4 = *(ptrJ - 3); + tmp3 = *(ptrJ - 2); + tmp2 = *(ptrJ - 1); + for (x = (partWidth >> 2); x; x--) + { + /* First pixel */ + tmp7 = tmp3 + tmp4; + tmp6 += (tmp7 << 4); + tmp6 += (tmp7 << 2); + tmp7 = tmp2 + tmp5; + tmp1 = *ptrJ++; + tmp6 -= (tmp7 << 2); + tmp6 -= tmp7; + tmp6 += tmp1; + *b1++ = tmp6; + /* Second pixel */ + tmp7 = tmp2 + tmp3; + tmp5 += (tmp7 << 4); + tmp5 += (tmp7 << 2); + tmp7 = tmp1 + tmp4; + tmp6 = *ptrJ++; + tmp5 -= (tmp7 << 2); + tmp5 -= tmp7; + tmp5 += tmp6; + *b1++ = tmp5; + /* Third pixel */ + tmp7 = tmp1 + tmp2; + tmp4 += (tmp7 << 4); + tmp4 += (tmp7 << 2); + tmp7 = tmp6 + tmp3; + tmp5 = *ptrJ++; + tmp4 -= (tmp7 << 2); + tmp4 -= tmp7; + tmp4 += tmp5; + *b1++ = tmp4; + /* Fourth pixel */ + tmp7 = tmp6 + tmp1; + tmp3 += (tmp7 << 4); + tmp3 += (tmp7 << 2); + tmp7 = tmp5 + tmp2; + tmp4 = *ptrJ++; + tmp3 -= (tmp7 << 2); + tmp3 -= tmp7; + tmp3 += tmp4; + *b1++ = tmp3; + tmp7 = tmp4; + tmp4 = tmp6; + tmp6 = tmp2; + tmp2 = tmp7; + tmp3 = tmp5; + tmp5 = tmp1; + } + ptrJ += width - partWidth; + } + + /* Second step: calculate vertical interpolation and average */ + ptrC = table + partWidth; + ptrV = ptrC + 5*partWidth; + /* Pointer to integer sample position, either M or R */ + ptrInt = ptrC + (2+verOffset)*partWidth; + for (y = (partHeight >> 2); y; y--) + { + for (x = partWidth; x; x--) + { + tmp4 = ptrV[-(i32)partWidth*2]; + tmp5 = ptrV[-(i32)partWidth]; + tmp1 = ptrV[partWidth]; + tmp2 = ptrV[partWidth*2]; + tmp6 = *ptrV++; + + tmp7 = tmp4 + tmp1; + tmp2 -= (tmp7 << 2); + tmp2 -= tmp7; + tmp2 += 512; + tmp7 = tmp5 + tmp6; + tmp3 = ptrC[partWidth*2]; + tmp2 += (tmp7 << 4); + tmp2 += (tmp7 << 2); + tmp7 = ptrInt[partWidth*2]; + tmp2 += tmp3; + tmp2 = clp[tmp2>>10]; + tmp7 += 16; + tmp7 = clp[tmp7>>5]; + tmp1 += 512; + tmp2++; + mb[48] = (u8)((tmp7 + tmp2) >> 1); + + tmp7 = tmp3 + tmp6; + tmp1 -= (tmp7 << 2); + tmp1 -= tmp7; + tmp7 = tmp4 + tmp5; + tmp2 = ptrC[partWidth]; + tmp1 += (tmp7 << 4); + tmp1 += (tmp7 << 2); + tmp7 = ptrInt[partWidth]; + tmp1 += tmp2; + tmp1 = clp[tmp1>>10]; + tmp7 += 16; + tmp7 = clp[tmp7>>5]; + tmp6 += 512; + tmp1++; + mb[32] = (u8)((tmp7 + tmp1) >> 1); + + tmp1 = *ptrC; + tmp7 = tmp2 + tmp5; + tmp6 -= (tmp7 << 2); + tmp6 -= tmp7; + tmp7 = tmp4 + tmp3; + tmp6 += (tmp7 << 4); + tmp6 += (tmp7 << 2); + tmp7 = *ptrInt; + tmp6 += tmp1; + tmp6 = clp[tmp6>>10]; + tmp7 += 16; + tmp7 = clp[tmp7>>5]; + tmp5 += 512; + tmp6++; + mb[16] = (u8)((tmp7 + tmp6) >> 1); + + tmp6 = ptrC[-(i32)partWidth]; + tmp1 += tmp4; + tmp5 -= (tmp1 << 2); + tmp5 -= tmp1; + tmp3 += tmp2; + tmp5 += (tmp3 << 4); + tmp5 += (tmp3 << 2); + tmp7 = ptrInt[-(i32)partWidth]; + tmp5 += tmp6; + tmp5 = clp[tmp5>>10]; + tmp7 += 16; + tmp7 = clp[tmp7>>5]; + tmp5++; + *mb++ = (u8)((tmp7 + tmp5) >> 1); + ptrC++; + ptrInt++; + } + mb += 4*16 - partWidth; + ptrC += 3*partWidth; + ptrV += 3*partWidth; + ptrInt += 3*partWidth; + } + +} + + +/*------------------------------------------------------------------------------ + + Function: h264bsdInterpolateMidHorQuarter + + Functional description: + Function to perform horizontal and vertical interpolation of pixel + position 'i' or 'k' for a block. Overfilling is done only if needed. + Reference image (ref) is read at correct position and the predicted + part is written to macroblock array (mb) + +------------------------------------------------------------------------------*/ + +void h264bsdInterpolateMidHorQuarter( + u8 *ref, + u8 *mb, + i32 x0, + i32 y0, + u32 width, + u32 height, + u32 partWidth, + u32 partHeight, + u32 horOffset) /* 0 for pixel i, 1 for pixel k */ +{ + u32 p1[21*21/4+1]; + u32 x, y; + i32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + i32 *ptrJ, *ptrInt, *h1; + u8 *ptrC, *ptrV; + i32 table[21*16]; + i32 tableWidth = (i32)partWidth+5; + const u8 *clp = h264bsdClip + 512; + + /* Code */ + + ASSERT(ref); + ASSERT(mb); + + if ((x0 < 0) || ((u32)x0+partWidth+5 > width) || + (y0 < 0) || ((u32)y0+partHeight+5 > height)) + { + h264bsdFillBlock(ref, (u8*)p1, x0, y0, width, height, + partWidth+5, partHeight+5, partWidth+5); + + x0 = 0; + y0 = 0; + ref = (u8*)p1; + width = partWidth+5; + } + + ref += (u32)y0 * width + (u32)x0; + + h1 = table + tableWidth; + ptrC = ref + width; + ptrV = ptrC + 5*width; + + /* First step: calculate intermediate values for + * vertical interpolation */ + for (y = (partHeight >> 2); y; y--) + { + for (x = (u32)tableWidth; x; x--) + { + tmp4 = ptrV[-(i32)width*2]; + tmp5 = ptrV[-(i32)width]; + tmp1 = ptrV[width]; + tmp2 = ptrV[width*2]; + tmp6 = *ptrV++; + + tmp7 = tmp4 + tmp1; + tmp2 -= (tmp7 << 2); + tmp2 -= tmp7; + tmp7 = tmp5 + tmp6; + tmp3 = ptrC[width*2]; + tmp2 += (tmp7 << 4); + tmp2 += (tmp7 << 2); + tmp2 += tmp3; + h1[tableWidth*2] = tmp2; + + tmp7 = tmp3 + tmp6; + tmp1 -= (tmp7 << 2); + tmp1 -= tmp7; + tmp7 = tmp4 + tmp5; + tmp2 = ptrC[width]; + tmp1 += (tmp7 << 4); + tmp1 += (tmp7 << 2); + tmp1 += tmp2; + h1[tableWidth] = tmp1; + + tmp1 = *ptrC; + tmp7 = tmp2 + tmp5; + tmp6 -= (tmp7 << 2); + tmp6 -= tmp7; + tmp7 = tmp4 + tmp3; + tmp6 += (tmp7 << 4); + tmp6 += (tmp7 << 2); + tmp6 += tmp1; + *h1 = tmp6; + + tmp6 = ptrC[-(i32)width]; + tmp1 += tmp4; + tmp5 -= (tmp1 << 2); + tmp5 -= tmp1; + tmp3 += tmp2; + tmp5 += (tmp3 << 4); + tmp5 += (tmp3 << 2); + tmp5 += tmp6; + h1[-tableWidth] = tmp5; + h1++; + ptrC++; + } + ptrC += 4*width - partWidth - 5; + ptrV += 4*width - partWidth - 5; + h1 += 3*tableWidth; + } + + /* Second step: calculate horizontal interpolation and average */ + ptrJ = table + 5; + /* Pointer to integer sample position, either G or H */ + ptrInt = table + 2 + horOffset; + for (y = partHeight; y; y--) + { + tmp6 = *(ptrJ - 5); + tmp5 = *(ptrJ - 4); + tmp4 = *(ptrJ - 3); + tmp3 = *(ptrJ - 2); + tmp2 = *(ptrJ - 1); + for (x = (partWidth>>2); x; x--) + { + /* First pixel */ + tmp6 += 512; + tmp7 = tmp3 + tmp4; + tmp6 += (tmp7 << 4); + tmp6 += (tmp7 << 2); + tmp7 = tmp2 + tmp5; + tmp1 = *ptrJ++; + tmp6 -= (tmp7 << 2); + tmp6 -= tmp7; + tmp7 = *ptrInt++; + tmp6 += tmp1; + tmp6 = clp[tmp6 >> 10]; + tmp7 += 16; + tmp7 = clp[tmp7 >> 5]; + tmp5 += 512; + tmp6++; + *mb++ = (u8)((tmp6 + tmp7) >> 1); + /* Second pixel */ + tmp7 = tmp2 + tmp3; + tmp5 += (tmp7 << 4); + tmp5 += (tmp7 << 2); + tmp7 = tmp1 + tmp4; + tmp6 = *ptrJ++; + tmp5 -= (tmp7 << 2); + tmp5 -= tmp7; + tmp7 = *ptrInt++; + tmp5 += tmp6; + tmp5 = clp[tmp5 >> 10]; + tmp7 += 16; + tmp7 = clp[tmp7 >> 5]; + tmp4 += 512; + tmp5++; + *mb++ = (u8)((tmp5 + tmp7) >> 1); + /* Third pixel */ + tmp7 = tmp1 + tmp2; + tmp4 += (tmp7 << 4); + tmp4 += (tmp7 << 2); + tmp7 = tmp6 + tmp3; + tmp5 = *ptrJ++; + tmp4 -= (tmp7 << 2); + tmp4 -= tmp7; + tmp7 = *ptrInt++; + tmp4 += tmp5; + tmp4 = clp[tmp4 >> 10]; + tmp7 += 16; + tmp7 = clp[tmp7 >> 5]; + tmp3 += 512; + tmp4++; + *mb++ = (u8)((tmp4 + tmp7) >> 1); + /* Fourth pixel */ + tmp7 = tmp6 + tmp1; + tmp3 += (tmp7 << 4); + tmp3 += (tmp7 << 2); + tmp7 = tmp5 + tmp2; + tmp4 = *ptrJ++; + tmp3 -= (tmp7 << 2); + tmp3 -= tmp7; + tmp7 = *ptrInt++; + tmp3 += tmp4; + tmp3 = clp[tmp3 >> 10]; + tmp7 += 16; + tmp7 = clp[tmp7 >> 5]; + tmp3++; + *mb++ = (u8)((tmp3 + tmp7) >> 1); + tmp3 = tmp5; + tmp5 = tmp1; + tmp7 = tmp4; + tmp4 = tmp6; + tmp6 = tmp2; + tmp2 = tmp7; + } + ptrJ += 5; + ptrInt += 5; + mb += 16 - partWidth; + } + +} + + +/*------------------------------------------------------------------------------ + + Function: h264bsdPredictSamples + + Functional description: + This function reconstructs a prediction for a macroblock partition. + The prediction is either copied or interpolated using the reference + frame and the motion vector. Both luminance and chrominance parts are + predicted. The prediction is stored in given macroblock array (data). + Inputs: + data pointer to macroblock array (384 bytes) for output + mv pointer to motion vector used for prediction + refPic pointer to reference picture structure + xA x-coordinate for current macroblock + yA y-coordinate for current macroblock + partX x-offset for partition in macroblock + partY y-offset for partition in macroblock + partWidth width of partition + partHeight height of partition + Outputs: + data macroblock array (16x16+8x8+8x8) where predicted + partition is stored at correct position + +------------------------------------------------------------------------------*/ + +void h264bsdPredictSamples( + u8 *data, + mv_t *mv, + image_t *refPic, + u32 xA, + u32 yA, + u32 partX, + u32 partY, + u32 partWidth, + u32 partHeight) + +{ + +/* Variables */ + + u32 xFrac, yFrac, width, height; + i32 xInt, yInt; + u8 *lumaPartData; + +/* Code */ + + ASSERT(data); + ASSERT(mv); + ASSERT(partWidth); + ASSERT(partHeight); + ASSERT(refPic); + ASSERT(refPic->data); + ASSERT(refPic->width); + ASSERT(refPic->height); + + /* luma */ + lumaPartData = data + 16*partY + partX; + + xFrac = mv->hor & 0x3; + yFrac = mv->ver & 0x3; + + width = 16 * refPic->width; + height = 16 * refPic->height; + + xInt = (i32)xA + (i32)partX + (mv->hor >> 2); + yInt = (i32)yA + (i32)partY + (mv->ver >> 2); + + ASSERT(lumaFracPos[xFrac][yFrac] < 16); + + switch (lumaFracPos[xFrac][yFrac]) + { + case 0: /* G */ + h264bsdFillBlock(refPic->data, lumaPartData, + xInt,yInt,width,height,partWidth,partHeight,16); + break; + case 1: /* d */ + h264bsdInterpolateVerQuarter(refPic->data, lumaPartData, + xInt, yInt-2, width, height, partWidth, partHeight, 0); + break; + case 2: /* h */ + h264bsdInterpolateVerHalf(refPic->data, lumaPartData, + xInt, yInt-2, width, height, partWidth, partHeight); + break; + case 3: /* n */ + h264bsdInterpolateVerQuarter(refPic->data, lumaPartData, + xInt, yInt-2, width, height, partWidth, partHeight, 1); + break; + case 4: /* a */ + h264bsdInterpolateHorQuarter(refPic->data, lumaPartData, + xInt-2, yInt, width, height, partWidth, partHeight, 0); + break; + case 5: /* e */ + h264bsdInterpolateHorVerQuarter(refPic->data, lumaPartData, + xInt-2, yInt-2, width, height, partWidth, partHeight, 0); + break; + case 6: /* i */ + h264bsdInterpolateMidHorQuarter(refPic->data, lumaPartData, + xInt-2, yInt-2, width, height, partWidth, partHeight, 0); + break; + case 7: /* p */ + h264bsdInterpolateHorVerQuarter(refPic->data, lumaPartData, + xInt-2, yInt-2, width, height, partWidth, partHeight, 2); + break; + case 8: /* b */ + h264bsdInterpolateHorHalf(refPic->data, lumaPartData, + xInt-2, yInt, width, height, partWidth, partHeight); + break; + case 9: /* f */ + h264bsdInterpolateMidVerQuarter(refPic->data, lumaPartData, + xInt-2, yInt-2, width, height, partWidth, partHeight, 0); + break; + case 10: /* j */ + h264bsdInterpolateMidHalf(refPic->data, lumaPartData, + xInt-2, yInt-2, width, height, partWidth, partHeight); + break; + case 11: /* q */ + h264bsdInterpolateMidVerQuarter(refPic->data, lumaPartData, + xInt-2, yInt-2, width, height, partWidth, partHeight, 1); + break; + case 12: /* c */ + h264bsdInterpolateHorQuarter(refPic->data, lumaPartData, + xInt-2, yInt, width, height, partWidth, partHeight, 1); + break; + case 13: /* g */ + h264bsdInterpolateHorVerQuarter(refPic->data, lumaPartData, + xInt-2, yInt-2, width, height, partWidth, partHeight, 1); + break; + case 14: /* k */ + h264bsdInterpolateMidHorQuarter(refPic->data, lumaPartData, + xInt-2, yInt-2, width, height, partWidth, partHeight, 1); + break; + default: /* case 15, r */ + h264bsdInterpolateHorVerQuarter(refPic->data, lumaPartData, + xInt-2, yInt-2, width, height, partWidth, partHeight, 3); + break; + } + + /* chroma */ + PredictChroma( + data + 16*16 + (partY>>1)*8 + (partX>>1), + xA + partX, + yA + partY, + partWidth, + partHeight, + mv, + refPic); + +} + +#else /* H264DEC_OMXDL */ +/*------------------------------------------------------------------------------ + + Function: h264bsdPredictSamples + + Functional description: + This function reconstructs a prediction for a macroblock partition. + The prediction is either copied or interpolated using the reference + frame and the motion vector. Both luminance and chrominance parts are + predicted. The prediction is stored in given macroblock array (data). + Inputs: + data pointer to macroblock array (384 bytes) for output + mv pointer to motion vector used for prediction + refPic pointer to reference picture structure + xA x-coordinate for current macroblock + yA y-coordinate for current macroblock + partX x-offset for partition in macroblock + partY y-offset for partition in macroblock + partWidth width of partition + partHeight height of partition + Outputs: + data macroblock array (16x16+8x8+8x8) where predicted + partition is stored at correct position + +------------------------------------------------------------------------------*/ + +/*lint -e{550} Symbol 'res' not accessed */ +void h264bsdPredictSamples( + u8 *data, + mv_t *mv, + image_t *refPic, + u32 colAndRow, + u32 part, + u8 *pFill) + +{ + +/* Variables */ + + u32 xFrac, yFrac; + u32 width, height; + i32 xInt, yInt, x0, y0; + u8 *partData, *ref; + OMXSize roi; + u32 fillWidth; + u32 fillHeight; + OMXResult res; + u32 xA, yA; + u32 partX, partY; + u32 partWidth, partHeight; + +/* Code */ + + ASSERT(data); + ASSERT(mv); + ASSERT(refPic); + ASSERT(refPic->data); + ASSERT(refPic->width); + ASSERT(refPic->height); + + xA = (colAndRow & 0xFFFF0000) >> 16; + yA = (colAndRow & 0x0000FFFF); + + partX = (part & 0xFF000000) >> 24; + partY = (part & 0x00FF0000) >> 16; + partWidth = (part & 0x0000FF00) >> 8; + partHeight = (part & 0x000000FF); + + ASSERT(partWidth); + ASSERT(partHeight); + + /* luma */ + partData = data + 16*partY + partX; + + xFrac = mv->hor & 0x3; + yFrac = mv->ver & 0x3; + + width = 16 * refPic->width; + height = 16 * refPic->height; + + xInt = (i32)xA + (i32)partX + (mv->hor >> 2); + yInt = (i32)yA + (i32)partY + (mv->ver >> 2); + + x0 = (xFrac) ? xInt-2 : xInt; + y0 = (yFrac) ? yInt-2 : yInt; + + if (xFrac) + { + if (partWidth == 16) + fillWidth = 32; + else + fillWidth = 16; + } + else + fillWidth = (partWidth*2); + if (yFrac) + fillHeight = partHeight+5; + else + fillHeight = partHeight; + + + if ((x0 < 0) || ((u32)x0+fillWidth > width) || + (y0 < 0) || ((u32)y0+fillHeight > height)) + { + h264bsdFillBlock(refPic->data, (u8*)pFill, x0, y0, width, height, + fillWidth, fillHeight, fillWidth); + + x0 = 0; + y0 = 0; + ref = pFill; + width = fillWidth; + if (yFrac) + ref += 2*width; + if (xFrac) + ref += 2; + } + else + { + /*lint --e(737) Loss of sign */ + ref = refPic->data + yInt*width + xInt; + } + /* Luma interpolation */ + roi.width = (i32)partWidth; + roi.height = (i32)partHeight; + + res = omxVCM4P10_InterpolateLuma(ref, (i32)width, partData, 16, + (i32)xFrac, (i32)yFrac, roi); + ASSERT(res == 0); + + /* Chroma */ + width = 8 * refPic->width; + height = 8 * refPic->height; + + x0 = ((xA + partX) >> 1) + (mv->hor >> 3); + y0 = ((yA + partY) >> 1) + (mv->ver >> 3); + xFrac = mv->hor & 0x7; + yFrac = mv->ver & 0x7; + + ref = refPic->data + 256 * refPic->width * refPic->height; + + roi.width = (i32)(partWidth >> 1); + fillWidth = ((partWidth >> 1) + 8) & ~0x7; + roi.height = (i32)(partHeight >> 1); + fillHeight = (partHeight >> 1) + 1; + + if ((x0 < 0) || ((u32)x0+fillWidth > width) || + (y0 < 0) || ((u32)y0+fillHeight > height)) + { + h264bsdFillBlock(ref, pFill, x0, y0, width, height, + fillWidth, fillHeight, fillWidth); + ref += width * height; + h264bsdFillBlock(ref, pFill + fillWidth*fillHeight, + x0, y0, width, height, fillWidth, + fillHeight, fillWidth); + + ref = pFill; + x0 = 0; + y0 = 0; + width = fillWidth; + height = fillHeight; + } + + partData = data + 16*16 + (partY>>1)*8 + (partX>>1); + + /* Chroma interpolation */ + /*lint --e(737) Loss of sign */ + ref += y0 * width + x0; + res = armVCM4P10_Interpolate_Chroma(ref, width, partData, 8, + (u32)roi.width, (u32)roi.height, xFrac, yFrac); + ASSERT(res == 0); + partData += 8 * 8; + ref += height * width; + res = armVCM4P10_Interpolate_Chroma(ref, width, partData, 8, + (u32)roi.width, (u32)roi.height, xFrac, yFrac); + ASSERT(res == 0); + +} + +#endif /* H264DEC_OMXDL */ + + +/*------------------------------------------------------------------------------ + + Function: FillRow1 + + Functional description: + This function gets a row of reference pels in a 'normal' case when no + overfilling is necessary. + +------------------------------------------------------------------------------*/ + +static void FillRow1( + u8 *ref, + u8 *fill, + i32 left, + i32 center, + i32 right) +{ + + ASSERT(ref); + ASSERT(fill); + + H264SwDecMemcpy(fill, ref, (u32)center); + + /*lint -e(715) */ +} + + +/*------------------------------------------------------------------------------ + + Function: h264bsdFillRow7 + + Functional description: + This function gets a row of reference pels when horizontal coordinate + is partly negative or partly greater than reference picture width + (overfilling some pels on left and/or right edge). + Inputs: + ref pointer to reference samples + left amount of pixels to overfill on left-edge + center amount of pixels to copy + right amount of pixels to overfill on right-edge + Outputs: + fill pointer where samples are stored + +------------------------------------------------------------------------------*/ +#ifndef H264DEC_NEON +void h264bsdFillRow7( + u8 *ref, + u8 *fill, + i32 left, + i32 center, + i32 right) +{ + u8 tmp; + + ASSERT(ref); + ASSERT(fill); + + if (left) + tmp = *ref; + + for ( ; left; left--) + /*lint -esym(644,tmp) tmp is initialized if used */ + *fill++ = tmp; + + for ( ; center; center--) + *fill++ = *ref++; + + if (right) + tmp = ref[-1]; + + for ( ; right; right--) + /*lint -esym(644,tmp) tmp is initialized if used */ + *fill++ = tmp; +} +#endif +/*------------------------------------------------------------------------------ + + Function: h264bsdFillBlock + + Functional description: + This function gets a block of reference pels. It determines whether + overfilling is needed or not and repeatedly calls an appropriate + function (by using a function pointer) that fills one row the block. + Inputs: + ref pointer to reference frame + x0 x-coordinate for block + y0 y-coordinate for block + width width of reference frame + height height of reference frame + blockWidth width of block + blockHeight height of block + fillScanLength length of a line in output array (pixels) + Outputs: + fill pointer to array where output block is written + +------------------------------------------------------------------------------*/ + +void h264bsdFillBlock( + u8 *ref, + u8 *fill, + i32 x0, + i32 y0, + u32 width, + u32 height, + u32 blockWidth, + u32 blockHeight, + u32 fillScanLength) + +{ + +/* Variables */ + + i32 xstop, ystop; + void (*fp)(u8*, u8*, i32, i32, i32); + i32 left, x, right; + i32 top, y, bottom; + +/* Code */ + + ASSERT(ref); + ASSERT(fill); + ASSERT(width); + ASSERT(height); + ASSERT(fill); + ASSERT(blockWidth); + ASSERT(blockHeight); + + xstop = x0 + (i32)blockWidth; + ystop = y0 + (i32)blockHeight; + + /* Choose correct function whether overfilling on left-edge or right-edge + * is needed or not */ + if (x0 >= 0 && xstop <= (i32)width) + fp = FillRow1; + else + fp = h264bsdFillRow7; + + if (ystop < 0) + y0 = -(i32)blockHeight; + + if (xstop < 0) + x0 = -(i32)blockWidth; + + if (y0 > (i32)height) + y0 = (i32)height; + + if (x0 > (i32)width) + x0 = (i32)width; + + xstop = x0 + (i32)blockWidth; + ystop = y0 + (i32)blockHeight; + + if (x0 > 0) + ref += x0; + + if (y0 > 0) + ref += y0 * (i32)width; + + left = x0 < 0 ? -x0 : 0; + right = xstop > (i32)width ? xstop - (i32)width : 0; + x = (i32)blockWidth - left - right; + + top = y0 < 0 ? -y0 : 0; + bottom = ystop > (i32)height ? ystop - (i32)height : 0; + y = (i32)blockHeight - top - bottom; + + /* Top-overfilling */ + for ( ; top; top-- ) + { + (*fp)(ref, fill, left, x, right); + fill += fillScanLength; + } + + /* Lines inside reference image */ + for ( ; y; y-- ) + { + (*fp)(ref, fill, left, x, right); + ref += width; + fill += fillScanLength; + } + + ref -= width; + + /* Bottom-overfilling */ + for ( ; bottom; bottom-- ) + { + (*fp)(ref, fill, left, x, right); + fill += fillScanLength; + } +} + +/*lint +e701 +e702 */ + + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_reconstruct.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_reconstruct.h new file mode 100755 index 0000000..5a1a140 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_reconstruct.h @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. Module defines + 3. Data types + 4. Function prototypes + +------------------------------------------------------------------------------*/ + +#ifndef H264SWDEC_RECONSTRUCT_H +#define H264SWDEC_RECONSTRUCT_H + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "basetype.h" +#include "h264bsd_macroblock_layer.h" +#include "h264bsd_image.h" + +/*------------------------------------------------------------------------------ + 2. Module defines +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 3. Data types +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ +#ifndef H264DEC_OMXDL +void h264bsdPredictSamples( + u8 *data, + mv_t *mv, + image_t *refPic, + u32 xA, + u32 yA, + u32 partX, + u32 partY, + u32 partWidth, + u32 partHeight); +#else +void h264bsdPredictSamples( + u8 *data, + mv_t *mv, + image_t *refPic, + u32 colAndRow,/* packaged data | column | row |*/ + u32 part, /* packaged data |partX|partY|partWidth|partHeight|*/ + u8 *pFill); +#endif + +void h264bsdFillBlock( + u8 * ref, + u8 * fill, + i32 x0, + i32 y0, + u32 width, + u32 height, + u32 blockWidth, + u32 blockHeight, + u32 fillScanLength); + +void h264bsdInterpolateChromaHor( + u8 *pRef, + u8 *predPartChroma, + i32 x0, + i32 y0, + u32 width, + u32 height, + u32 xFrac, + u32 chromaPartWidth, + u32 chromaPartHeight); + +void h264bsdInterpolateChromaVer( + u8 *pRef, + u8 *predPartChroma, + i32 x0, + i32 y0, + u32 width, + u32 height, + u32 yFrac, + u32 chromaPartWidth, + u32 chromaPartHeight); + +void h264bsdInterpolateChromaHorVer( + u8 *ref, + u8 *predPartChroma, + i32 x0, + i32 y0, + u32 width, + u32 height, + u32 xFrac, + u32 yFrac, + u32 chromaPartWidth, + u32 chromaPartHeight); + +void h264bsdInterpolateVerHalf( + u8 *ref, + u8 *mb, + i32 x0, + i32 y0, + u32 width, + u32 height, + u32 partWidth, + u32 partHeight); + +void h264bsdInterpolateVerQuarter( + u8 *ref, + u8 *mb, + i32 x0, + i32 y0, + u32 width, + u32 height, + u32 partWidth, + u32 partHeight, + u32 verOffset); + +void h264bsdInterpolateHorHalf( + u8 *ref, + u8 *mb, + i32 x0, + i32 y0, + u32 width, + u32 height, + u32 partWidth, + u32 partHeight); + +void h264bsdInterpolateHorQuarter( + u8 *ref, + u8 *mb, + i32 x0, + i32 y0, + u32 width, + u32 height, + u32 partWidth, + u32 partHeight, + u32 horOffset); + +void h264bsdInterpolateHorVerQuarter( + u8 *ref, + u8 *mb, + i32 x0, + i32 y0, + u32 width, + u32 height, + u32 partWidth, + u32 partHeight, + u32 horVerOffset); + +void h264bsdInterpolateMidHalf( + u8 *ref, + u8 *mb, + i32 x0, + i32 y0, + u32 width, + u32 height, + u32 partWidth, + u32 partHeight); + +void h264bsdInterpolateMidVerQuarter( + u8 *ref, + u8 *mb, + i32 x0, + i32 y0, + u32 width, + u32 height, + u32 partWidth, + u32 partHeight, + u32 verOffset); + +void h264bsdInterpolateMidHorQuarter( + u8 *ref, + u8 *mb, + i32 x0, + i32 y0, + u32 width, + u32 height, + u32 partWidth, + u32 partHeight, + u32 horOffset); + + +void h264bsdFillRow7( + u8 *ref, + u8 *fill, + i32 left, + i32 center, + i32 right); + +#endif /* #ifdef H264SWDEC_RECONSTRUCT_H */ + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_sei.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_sei.c new file mode 100755 index 0000000..0756c47 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_sei.c @@ -0,0 +1,1692 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. External compiler flags + 3. Module defines + 4. Local function prototypes + 5. Functions + h264bsdDecodeSeiMessage + DecodeBufferingPeriod + DecodePictureTiming + DecodePanScanRectangle + DecodeFillerPayload + DecodeUserDataRegisteredITuTT35 + DecodeUserDataUnregistered + DecodeRecoveryPoint + DecodeDecRefPicMarkingRepetition + DecodeSparePic + DecodeSceneInfo + DecodeSubSeqInfo + DecodeSubSeqLayerCharacteristics + DecodeSubSeqCharacteristics + DecodeFullFrameFreeze + DecodeFullFrameSnapshot + DecodeProgressiveRefinementSegmentStart + DecodeProgressiveRefinementSegmentEnd + DecodeMotionConstrainedSliceGroupSet + DecodeReservedSeiMessage + +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "h264bsd_sei.h" +#include "basetype.h" +#include "h264bsd_util.h" +#include "h264bsd_stream.h" +#include "h264bsd_vlc.h" +#include "h264bsd_seq_param_set.h" +#include "h264bsd_slice_header.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +static const u32 numClockTS[9] = {1,1,1,2,2,3,3,2,3}; +static const u32 ceilLog2NumSliceGroups[9] = {0,1,1,2,2,3,3,3,3}; + +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ + +static u32 DecodeBufferingPeriod( + strmData_t *pStrmData, + seiBufferingPeriod_t *pBufferingPeriod, + u32 cpbCnt, + u32 initialCpbRemovalDelayLength, + u32 nalHrdBpPresentFlag, + u32 vclHrdBpPresentFlag); + +static u32 DecodePictureTiming( + strmData_t *pStrmData, + seiPicTiming_t *pPicTiming, + u32 cpbRemovalDelayLength, + u32 dpbOutputDelayLength, + u32 timeOffsetLength, + u32 cpbDpbDelaysPresentFlag, + u32 picStructPresentFlag); + +static u32 DecodePanScanRectangle( + strmData_t *pStrmData, + seiPanScanRect_t *pPanScanRectangle); + +static u32 DecodeFillerPayload(strmData_t *pStrmData, u32 payloadSize); + +static u32 DecodeUserDataRegisteredITuTT35( + strmData_t *pStrmData, + seiUserDataRegisteredItuTT35_t *pUserDataRegisteredItuTT35, + u32 payloadSize); + +static u32 DecodeUserDataUnregistered( + strmData_t *pStrmData, + seiUserDataUnregistered_t *pUserDataUnregistered, + u32 payloadSize); + +static u32 DecodeRecoveryPoint( + strmData_t *pStrmData, + seiRecoveryPoint_t *pRecoveryPoint); + +static u32 DecodeDecRefPicMarkingRepetition( + strmData_t *pStrmData, + seiDecRefPicMarkingRepetition_t *pDecRefPicMarkingRepetition, + u32 numRefFrames); + +static u32 DecodeSparePic( + strmData_t *pStrmData, + seiSparePic_t *pSparePic, + u32 picSizeInMapUnits); + +static u32 DecodeSceneInfo( + strmData_t *pStrmData, + seiSceneInfo_t *pSceneInfo); + +static u32 DecodeSubSeqInfo( + strmData_t *pStrmData, + seiSubSeqInfo_t *pSubSeqInfo); + +static u32 DecodeSubSeqLayerCharacteristics( + strmData_t *pStrmData, + seiSubSeqLayerCharacteristics_t *pSubSeqLayerCharacteristics); + +static u32 DecodeSubSeqCharacteristics( + strmData_t *pStrmData, + seiSubSeqCharacteristics_t *pSubSeqCharacteristics); + +static u32 DecodeFullFrameFreeze( + strmData_t *pStrmData, + seiFullFrameFreeze_t *pFullFrameFreeze); + +static u32 DecodeFullFrameSnapshot( + strmData_t *pStrmData, + seiFullFrameSnapshot_t *pFullFrameSnapshot); + +static u32 DecodeProgressiveRefinementSegmentStart( + strmData_t *pStrmData, + seiProgressiveRefinementSegmentStart_t *pProgressiveRefinementSegmentStart); + +static u32 DecodeProgressiveRefinementSegmentEnd( + strmData_t *pStrmData, + seiProgressiveRefinementSegmentEnd_t *pProgressiveRefinementSegmentEnd); + +static u32 DecodeMotionConstrainedSliceGroupSet( + strmData_t *pStrmData, + seiMotionConstrainedSliceGroupSet_t *pMotionConstrainedSliceGroupSet, + u32 numSliceGroups); + +static u32 DecodeReservedSeiMessage( + strmData_t *pStrmData, + seiReservedSeiMessage_t *pReservedSeiMessage, + u32 payloadSize); + +/*------------------------------------------------------------------------------ + + Function: h264bsdDecodeSeiMessage + + Functional description: + <++> + Inputs: + <++> + Outputs: + <++> + +------------------------------------------------------------------------------*/ + +u32 h264bsdDecodeSeiMessage( + strmData_t *pStrmData, + seqParamSet_t *pSeqParamSet, + seiMessage_t *pSeiMessage, + u32 numSliceGroups) +{ + +/* Variables */ + + u32 tmp, payloadType, payloadSize, status; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pSeiMessage); + + + H264SwDecMemset(pSeiMessage, 0, sizeof(seiMessage_t)); + + do + { + payloadType = 0; + while((tmp = h264bsdGetBits(pStrmData, 8)) == 0xFF) + { + payloadType += 255; + } + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + payloadType += tmp; + + payloadSize = 0; + while((tmp = h264bsdGetBits(pStrmData, 8)) == 0xFF) + { + payloadSize += 255; + } + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + payloadSize += tmp; + + pSeiMessage->payloadType = payloadType; + + switch (payloadType) + { + case 0: + ASSERT(pSeqParamSet); + status = DecodeBufferingPeriod( + pStrmData, + &pSeiMessage->bufferingPeriod, + pSeqParamSet->vuiParameters->vclHrdParameters.cpbCnt, + pSeqParamSet->vuiParameters->vclHrdParameters. + initialCpbRemovalDelayLength, + pSeqParamSet->vuiParameters->nalHrdParametersPresentFlag, + pSeqParamSet->vuiParameters->vclHrdParametersPresentFlag); + break; + + case 1: + ASSERT(pSeqParamSet->vuiParametersPresentFlag); + status = DecodePictureTiming( + pStrmData, + &pSeiMessage->picTiming, + pSeqParamSet->vuiParameters->vclHrdParameters. + cpbRemovalDelayLength, + pSeqParamSet->vuiParameters->vclHrdParameters. + dpbOutputDelayLength, + pSeqParamSet->vuiParameters->vclHrdParameters. + timeOffsetLength, + pSeqParamSet->vuiParameters->nalHrdParametersPresentFlag || + pSeqParamSet->vuiParameters->vclHrdParametersPresentFlag ? + HANTRO_TRUE : HANTRO_FALSE, + pSeqParamSet->vuiParameters->picStructPresentFlag); + break; + + case 2: + status = DecodePanScanRectangle( + pStrmData, + &pSeiMessage->panScanRect); + break; + + case 3: + status = DecodeFillerPayload(pStrmData, payloadSize); + break; + + case 4: + status = DecodeUserDataRegisteredITuTT35( + pStrmData, + &pSeiMessage->userDataRegisteredItuTT35, + payloadSize); + break; + + case 5: + status = DecodeUserDataUnregistered( + pStrmData, + &pSeiMessage->userDataUnregistered, + payloadSize); + break; + + case 6: + status = DecodeRecoveryPoint( + pStrmData, + &pSeiMessage->recoveryPoint); + break; + + case 7: + status = DecodeDecRefPicMarkingRepetition( + pStrmData, + &pSeiMessage->decRefPicMarkingRepetition, + pSeqParamSet->numRefFrames); + break; + + case 8: + ASSERT(pSeqParamSet); + status = DecodeSparePic( + pStrmData, + &pSeiMessage->sparePic, + pSeqParamSet->picWidthInMbs * pSeqParamSet->picHeightInMbs); + break; + + case 9: + status = DecodeSceneInfo( + pStrmData, + &pSeiMessage->sceneInfo); + break; + + case 10: + status = DecodeSubSeqInfo( + pStrmData, + &pSeiMessage->subSeqInfo); + break; + + case 11: + status = DecodeSubSeqLayerCharacteristics( + pStrmData, + &pSeiMessage->subSeqLayerCharacteristics); + break; + + case 12: + status = DecodeSubSeqCharacteristics( + pStrmData, + &pSeiMessage->subSeqCharacteristics); + break; + + case 13: + status = DecodeFullFrameFreeze( + pStrmData, + &pSeiMessage->fullFrameFreeze); + break; + + case 14: /* This SEI does not contain data, what to do ??? */ + status = HANTRO_OK; + break; + + case 15: + status = DecodeFullFrameSnapshot( + pStrmData, + &pSeiMessage->fullFrameSnapshot); + break; + + case 16: + status = DecodeProgressiveRefinementSegmentStart( + pStrmData, + &pSeiMessage->progressiveRefinementSegmentStart); + break; + + case 17: + status = DecodeProgressiveRefinementSegmentEnd( + pStrmData, + &pSeiMessage->progressiveRefinementSegmentEnd); + break; + + case 18: + ASSERT(numSliceGroups); + status = DecodeMotionConstrainedSliceGroupSet( + pStrmData, + &pSeiMessage->motionConstrainedSliceGroupSet, + numSliceGroups); + break; + + default: + status = DecodeReservedSeiMessage( + pStrmData, + &pSeiMessage->reservedSeiMessage, + payloadSize); + break; + } + + if (status != HANTRO_OK) + return(status); + + while (!h264bsdIsByteAligned(pStrmData)) + { + if (h264bsdGetBits(pStrmData, 1) != 1) + return(HANTRO_NOK); + while (!h264bsdIsByteAligned(pStrmData)) + { + if (h264bsdGetBits(pStrmData, 1) != 0) + return(HANTRO_NOK); + } + } + } while (h264bsdMoreRbspData(pStrmData)); + + return(h264bsdRbspTrailingBits(pStrmData)); + +} + +/*------------------------------------------------------------------------------ + + Function: DecodeBufferingPeriod + + Functional description: + <++> + Inputs: + <++> + Outputs: + <++> + +------------------------------------------------------------------------------*/ + +static u32 DecodeBufferingPeriod( + strmData_t *pStrmData, + seiBufferingPeriod_t *pBufferingPeriod, + u32 cpbCnt, + u32 initialCpbRemovalDelayLength, + u32 nalHrdBpPresentFlag, + u32 vclHrdBpPresentFlag) +{ + +/* Variables */ + + u32 tmp, i; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pBufferingPeriod); + ASSERT(cpbCnt); + ASSERT(initialCpbRemovalDelayLength); + + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pBufferingPeriod->seqParameterSetId); + if (tmp != HANTRO_OK) + return(tmp); + if (pBufferingPeriod->seqParameterSetId > 31) + return(HANTRO_NOK); + + if (nalHrdBpPresentFlag) + { + for (i = 0; i < cpbCnt; i++) + { + tmp = h264bsdGetBits(pStrmData, initialCpbRemovalDelayLength); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + if (tmp == 0) + return(HANTRO_NOK); + pBufferingPeriod->initialCpbRemovalDelay[i] = tmp; + + tmp = h264bsdGetBits(pStrmData, initialCpbRemovalDelayLength); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pBufferingPeriod->initialCpbRemovalDelayOffset[i] = tmp; + } + } + + if (vclHrdBpPresentFlag) + { + for (i = 0; i < cpbCnt; i++) + { + tmp = h264bsdGetBits(pStrmData, initialCpbRemovalDelayLength); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pBufferingPeriod->initialCpbRemovalDelay[i] = tmp; + + tmp = h264bsdGetBits(pStrmData, initialCpbRemovalDelayLength); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pBufferingPeriod->initialCpbRemovalDelayOffset[i] = tmp; + } + } + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: DecodePictureTiming + + Functional description: + <++> + Inputs: + <++> + Outputs: + <++> + +------------------------------------------------------------------------------*/ + +static u32 DecodePictureTiming( + strmData_t *pStrmData, + seiPicTiming_t *pPicTiming, + u32 cpbRemovalDelayLength, + u32 dpbOutputDelayLength, + u32 timeOffsetLength, + u32 cpbDpbDelaysPresentFlag, + u32 picStructPresentFlag) +{ + +/* Variables */ + + u32 tmp, i; + i32 itmp; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pPicTiming); + + + if (cpbDpbDelaysPresentFlag) + { + tmp = h264bsdGetBits(pStrmData, cpbRemovalDelayLength); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pPicTiming->cpbRemovalDelay = tmp; + + tmp = h264bsdGetBits(pStrmData, dpbOutputDelayLength); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pPicTiming->dpbOutputDelay = tmp; + } + + if (picStructPresentFlag) + { + tmp = h264bsdGetBits(pStrmData, 4); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + if (tmp > 8) + return(HANTRO_NOK); + pPicTiming->picStruct = tmp; + + for (i = 0; i < numClockTS[pPicTiming->picStruct]; i++) + { + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pPicTiming->clockTimeStampFlag[i] = tmp == 1 ? + HANTRO_TRUE : HANTRO_FALSE; + + if (pPicTiming->clockTimeStampFlag[i]) + { + tmp = h264bsdGetBits(pStrmData, 2); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pPicTiming->ctType[i] = tmp; + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pPicTiming->nuitFieldBasedFlag[i] = tmp == 1 ? + HANTRO_TRUE : HANTRO_FALSE; + + tmp = h264bsdGetBits(pStrmData, 5); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + if (tmp > 6) + return(HANTRO_NOK); + pPicTiming->countingType[i] = tmp; + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pPicTiming->fullTimeStampFlag[i] = tmp == 1 ? + HANTRO_TRUE : HANTRO_FALSE; + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pPicTiming->discontinuityFlag[i] = tmp == 1 ? + HANTRO_TRUE : HANTRO_FALSE; + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pPicTiming->cntDroppedFlag[i] = tmp == 1 ? + HANTRO_TRUE : HANTRO_FALSE; + + tmp = h264bsdGetBits(pStrmData, 8); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pPicTiming->nFrames[i] = tmp; + + if (pPicTiming->fullTimeStampFlag[i]) + { + tmp = h264bsdGetBits(pStrmData, 6); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + if (tmp > 59) + return(HANTRO_NOK); + pPicTiming->secondsValue[i] = tmp; + + tmp = h264bsdGetBits(pStrmData, 6); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + if (tmp > 59) + return(HANTRO_NOK); + pPicTiming->minutesValue[i] = tmp; + + tmp = h264bsdGetBits(pStrmData, 5); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + if (tmp > 23) + return(HANTRO_NOK); + pPicTiming->hoursValue[i] = tmp; + } + else + { + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pPicTiming->secondsFlag[i] = tmp == 1 ? + HANTRO_TRUE : HANTRO_FALSE; + + if (pPicTiming->secondsFlag[i]) + { + tmp = h264bsdGetBits(pStrmData, 6); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + if (tmp > 59) + return(HANTRO_NOK); + pPicTiming->secondsValue[i] = tmp; + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pPicTiming->minutesFlag[i] = tmp == 1 ? + HANTRO_TRUE : HANTRO_FALSE; + + if (pPicTiming->minutesFlag[i]) + { + tmp = h264bsdGetBits(pStrmData, 6); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + if (tmp > 59) + return(HANTRO_NOK); + pPicTiming->minutesValue[i] = tmp; + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pPicTiming->hoursFlag[i] = tmp == 1 ? + HANTRO_TRUE : HANTRO_FALSE; + + if (pPicTiming->hoursFlag[i]) + { + tmp = h264bsdGetBits(pStrmData, 5); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + if (tmp > 23) + return(HANTRO_NOK); + pPicTiming->hoursValue[i] = tmp; + } + } + } + } + if (timeOffsetLength) + { + tmp = h264bsdGetBits(pStrmData, timeOffsetLength); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + itmp = (i32)tmp; + /* following "converts" timeOffsetLength-bit signed + * integer into i32 */ + /*lint -save -e701 -e702 */ + itmp <<= (32 - timeOffsetLength); + itmp >>= (32 - timeOffsetLength); + /*lint -restore */ + pPicTiming->timeOffset[i] = itmp; + } + else + pPicTiming->timeOffset[i] = 0; + } + } + } + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: DecodePanScanRectangle + + Functional description: + <++> + Inputs: + <++> + Outputs: + <++> + +------------------------------------------------------------------------------*/ + +static u32 DecodePanScanRectangle( + strmData_t *pStrmData, + seiPanScanRect_t *pPanScanRectangle) +{ + +/* Variables */ + + u32 tmp, i; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pPanScanRectangle); + + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pPanScanRectangle->panScanRectId); + if (tmp != HANTRO_OK) + return(tmp); + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pPanScanRectangle->panScanRectCancelFlag = tmp == 1 ? + HANTRO_TRUE : HANTRO_FALSE; + + if (!pPanScanRectangle->panScanRectCancelFlag) + { + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pPanScanRectangle->panScanCnt); + if (tmp != HANTRO_OK) + return(tmp); + if (pPanScanRectangle->panScanCnt > 2) + return(HANTRO_NOK); + pPanScanRectangle->panScanCnt++; + + for (i = 0; i < pPanScanRectangle->panScanCnt; i++) + { + tmp = h264bsdDecodeExpGolombSigned(pStrmData, + &pPanScanRectangle->panScanRectLeftOffset[i]); + if (tmp != HANTRO_OK) + return(tmp); + + tmp = h264bsdDecodeExpGolombSigned(pStrmData, + &pPanScanRectangle->panScanRectRightOffset[i]); + if (tmp != HANTRO_OK) + return(tmp); + + tmp = h264bsdDecodeExpGolombSigned(pStrmData, + &pPanScanRectangle->panScanRectTopOffset[i]); + if (tmp != HANTRO_OK) + return(tmp); + + tmp = h264bsdDecodeExpGolombSigned(pStrmData, + &pPanScanRectangle->panScanRectBottomOffset[i]); + if (tmp != HANTRO_OK) + return(tmp); + } + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pPanScanRectangle->panScanRectRepetitionPeriod); + if (tmp != HANTRO_OK) + return(tmp); + if (pPanScanRectangle->panScanRectRepetitionPeriod > 16384) + return(HANTRO_NOK); + if (pPanScanRectangle->panScanCnt > 1 && + pPanScanRectangle->panScanRectRepetitionPeriod > 1) + return(HANTRO_NOK); + } + + return(HANTRO_OK); +} + +/*------------------------------------------------------------------------------ + + Function: DecodeFillerPayload + + Functional description: + <++> + Inputs: + <++> + Outputs: + <++> + +------------------------------------------------------------------------------*/ + +static u32 DecodeFillerPayload(strmData_t *pStrmData, u32 payloadSize) +{ + +/* Variables */ + +/* Code */ + + ASSERT(pStrmData); + + + if (payloadSize) + if (h264bsdFlushBits(pStrmData, 8 * payloadSize) == END_OF_STREAM) + return(HANTRO_NOK); + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: DecodeUserDataRegisteredITuTT35 + + Functional description: + <++> + Inputs: + <++> + Outputs: + <++> + +------------------------------------------------------------------------------*/ + +static u32 DecodeUserDataRegisteredITuTT35( + strmData_t *pStrmData, + seiUserDataRegisteredItuTT35_t *pUserDataRegisteredItuTT35, + u32 payloadSize) +{ + +/* Variables */ + + u32 tmp, i, j; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pUserDataRegisteredItuTT35); + ASSERT(payloadSize); + + tmp = h264bsdGetBits(pStrmData, 8); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pUserDataRegisteredItuTT35->ituTT35CountryCode = tmp; + + if (pUserDataRegisteredItuTT35->ituTT35CountryCode != 0xFF) + i = 1; + else + { + tmp = h264bsdGetBits(pStrmData, 8); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pUserDataRegisteredItuTT35->ituTT35CountryCodeExtensionByte = tmp; + i = 2; + } + + /* where corresponding FREE() ??? */ + ALLOCATE(pUserDataRegisteredItuTT35->ituTT35PayloadByte,payloadSize-i,u8); + pUserDataRegisteredItuTT35->numPayloadBytes = payloadSize - i; + if (pUserDataRegisteredItuTT35->ituTT35PayloadByte == NULL) + return(MEMORY_ALLOCATION_ERROR); + + j = 0; + do + { + tmp = h264bsdGetBits(pStrmData, 8); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pUserDataRegisteredItuTT35->ituTT35PayloadByte[j] = (u8)tmp; + i++; + j++; + } while (i < payloadSize); + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: DecodeUserDataUnregistered + + Functional description: + <++> + Inputs: + <++> + Outputs: + <++> + +------------------------------------------------------------------------------*/ + +static u32 DecodeUserDataUnregistered( + strmData_t *pStrmData, + seiUserDataUnregistered_t *pUserDataUnregistered, + u32 payloadSize) +{ + +/* Variables */ + + u32 i, tmp; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pUserDataUnregistered); + + + for (i = 0; i < 4; i++) + { + pUserDataUnregistered->uuidIsoIec11578[i] = h264bsdShowBits32(pStrmData); + if (h264bsdFlushBits(pStrmData,32) == END_OF_STREAM) + return(HANTRO_NOK); + } + + /* where corresponding FREE() ??? */ + ALLOCATE(pUserDataUnregistered->userDataPayloadByte, payloadSize - 16, u8); + if (pUserDataUnregistered->userDataPayloadByte == NULL) + return(MEMORY_ALLOCATION_ERROR); + + pUserDataUnregistered->numPayloadBytes = payloadSize - 16; + + for (i = 0; i < payloadSize - 16; i++) + { + tmp = h264bsdGetBits(pStrmData, 8); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pUserDataUnregistered->userDataPayloadByte[i] = (u8)tmp; + } + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: DecodeRecoveryPoint + + Functional description: + <++> + Inputs: + <++> + Outputs: + <++> + +------------------------------------------------------------------------------*/ + +static u32 DecodeRecoveryPoint( + strmData_t *pStrmData, + seiRecoveryPoint_t *pRecoveryPoint) +{ + +/* Variables */ + + u32 tmp; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pRecoveryPoint); + + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pRecoveryPoint->recoveryFrameCnt); + if (tmp != HANTRO_OK) + return(tmp); + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pRecoveryPoint->exactMatchFlag = tmp == 1 ? HANTRO_TRUE : HANTRO_FALSE; + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pRecoveryPoint->brokenLinkFlag = tmp == 1 ? HANTRO_TRUE : HANTRO_FALSE; + + tmp = h264bsdGetBits(pStrmData, 2); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + if (tmp > 2) + return(HANTRO_NOK); + pRecoveryPoint->changingSliceGroupIdc = tmp; + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: DecodeDecRefPicMarkingRepetition + + Functional description: + <++> + Inputs: + <++> + Outputs: + <++> + +------------------------------------------------------------------------------*/ + +static u32 DecodeDecRefPicMarkingRepetition( + strmData_t *pStrmData, + seiDecRefPicMarkingRepetition_t *pDecRefPicMarkingRepetition, + u32 numRefFrames) +{ + +/* Variables */ + + u32 tmp; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pDecRefPicMarkingRepetition); + + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pDecRefPicMarkingRepetition->originalIdrFlag = tmp == 1 ? HANTRO_TRUE : HANTRO_FALSE; + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pDecRefPicMarkingRepetition->originalFrameNum); + if (tmp != HANTRO_OK) + return(tmp); + + /* frame_mbs_only_flag assumed always true so some field related syntax + * elements are skipped, see H.264 standard */ + tmp = h264bsdDecRefPicMarking(pStrmData, + &pDecRefPicMarkingRepetition->decRefPicMarking, NAL_SEI, numRefFrames); + + return(tmp); + +} + +/*------------------------------------------------------------------------------ + + Function: DecodeSparePic + + Functional description: + <++> + Inputs: + <++> + Outputs: + <++> + +------------------------------------------------------------------------------*/ + +static u32 DecodeSparePic( + strmData_t *pStrmData, + seiSparePic_t *pSparePic, + u32 picSizeInMapUnits) +{ + +/* Variables */ + + u32 tmp, i, j, mapUnitCnt; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pSparePic); + + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pSparePic->targetFrameNum); + if (tmp != HANTRO_OK) + return(tmp); + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pSparePic->spareFieldFlag = tmp == 1 ? HANTRO_TRUE : HANTRO_FALSE; + /* do not accept fields */ + if (pSparePic->spareFieldFlag) + return(HANTRO_NOK); + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pSparePic->numSparePics); + if (tmp != HANTRO_OK) + return(tmp); + pSparePic->numSparePics++; + if (pSparePic->numSparePics > MAX_NUM_SPARE_PICS) + return(HANTRO_NOK); + + for (i = 0; i < pSparePic->numSparePics; i++) + { + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pSparePic->deltaSpareFrameNum[i]); + if (tmp != HANTRO_OK) + return(tmp); + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pSparePic->spareAreaIdc[i]); + if (tmp != HANTRO_OK) + return(tmp); + if (pSparePic->spareAreaIdc[i] > 2) + return(HANTRO_NOK); + + if (pSparePic->spareAreaIdc[i] == 1) + { + /* where corresponding FREE() ??? */ + ALLOCATE(pSparePic->spareUnitFlag[i], picSizeInMapUnits, u32); + if (pSparePic->spareUnitFlag[i] == NULL) + return(MEMORY_ALLOCATION_ERROR); + pSparePic->zeroRunLength[i] = NULL; + + for (j = 0; j < picSizeInMapUnits; j++) + { + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pSparePic->spareUnitFlag[i][j] = tmp == 1 ? + HANTRO_TRUE : HANTRO_FALSE; + } + } + else if (pSparePic->spareAreaIdc[i] == 2) + { + /* where corresponding FREE() ??? */ + ALLOCATE(pSparePic->zeroRunLength[i], picSizeInMapUnits, u32); + if (pSparePic->zeroRunLength[i] == NULL) + return(MEMORY_ALLOCATION_ERROR); + pSparePic->spareUnitFlag[i] = NULL; + + for (j = 0, mapUnitCnt = 0; mapUnitCnt < picSizeInMapUnits; j++) + { + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pSparePic->zeroRunLength[i][j]); + if (tmp != HANTRO_OK) + return(tmp); + mapUnitCnt += pSparePic->zeroRunLength[i][j] + 1; + } + } + } + + /* set rest to null */ + for (i = pSparePic->numSparePics; i < MAX_NUM_SPARE_PICS; i++) + { + pSparePic->spareUnitFlag[i] = NULL; + pSparePic->zeroRunLength[i] = NULL; + } + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: DecodeSceneInfo + + Functional description: + <++> + Inputs: + <++> + Outputs: + <++> + +------------------------------------------------------------------------------*/ + +static u32 DecodeSceneInfo( + strmData_t *pStrmData, + seiSceneInfo_t *pSceneInfo) +{ + +/* Variables */ + + u32 tmp; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pSceneInfo); + + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pSceneInfo->sceneInfoPresentFlag = tmp == 1 ? HANTRO_TRUE : HANTRO_FALSE; + + if (pSceneInfo->sceneInfoPresentFlag) + { + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pSceneInfo->sceneId); + if (tmp != HANTRO_OK) + return(tmp); + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pSceneInfo->sceneTransitionType); + if (tmp != HANTRO_OK) + return(tmp); + if (pSceneInfo->sceneTransitionType > 6) + return(HANTRO_NOK); + + if (pSceneInfo->sceneTransitionType) + { + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pSceneInfo->secondSceneId); + if (tmp != HANTRO_OK) + return(tmp); + } + + } + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: DecodeSubSeqInfo + + Functional description: + <++> + Inputs: + <++> + Outputs: + <++> + +-----------------------------------------------------------------------------*/ + +static u32 DecodeSubSeqInfo( + strmData_t *pStrmData, + seiSubSeqInfo_t *pSubSeqInfo) +{ + +/* Variables */ + + u32 tmp; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pSubSeqInfo); + + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pSubSeqInfo->subSeqLayerNum); + if (tmp != HANTRO_OK) + return(tmp); + if (pSubSeqInfo->subSeqLayerNum > 255) + return(HANTRO_NOK); + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pSubSeqInfo->subSeqId); + if (tmp != HANTRO_OK) + return(tmp); + if (pSubSeqInfo->subSeqId > 65535) + return(HANTRO_NOK); + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pSubSeqInfo->firstRefPicFlag = tmp == 1 ? HANTRO_TRUE : HANTRO_FALSE; + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pSubSeqInfo->leadingNonRefPicFlag = tmp == 1 ? HANTRO_TRUE : HANTRO_FALSE; + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pSubSeqInfo->lastPicFlag = tmp == 1 ? HANTRO_TRUE : HANTRO_FALSE; + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pSubSeqInfo->subSeqFrameNumFlag = tmp == 1 ? HANTRO_TRUE : HANTRO_FALSE; + + if (pSubSeqInfo->subSeqFrameNumFlag) + { + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pSubSeqInfo->subSeqFrameNum); + if (tmp != HANTRO_OK) + return(tmp); + } + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: DecodeSubSeqLayerCharacteristics + + Functional description: + <++> + Inputs: + <++> + Outputs: + <++> + +------------------------------------------------------------------------------*/ + +static u32 DecodeSubSeqLayerCharacteristics( + strmData_t *pStrmData, + seiSubSeqLayerCharacteristics_t *pSubSeqLayerCharacteristics) +{ + +/* Variables */ + + u32 tmp, i; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pSubSeqLayerCharacteristics); + + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pSubSeqLayerCharacteristics->numSubSeqLayers); + if (tmp != HANTRO_OK) + return(tmp); + pSubSeqLayerCharacteristics->numSubSeqLayers++; + if (pSubSeqLayerCharacteristics->numSubSeqLayers > MAX_NUM_SUB_SEQ_LAYERS) + return(HANTRO_NOK); + + for (i = 0; i < pSubSeqLayerCharacteristics->numSubSeqLayers; i++) + { + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pSubSeqLayerCharacteristics->accurateStatisticsFlag[i] = + tmp == 1 ? HANTRO_TRUE : HANTRO_FALSE; + + tmp = h264bsdGetBits(pStrmData, 16); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pSubSeqLayerCharacteristics->averageBitRate[i] = tmp; + + tmp = h264bsdGetBits(pStrmData, 16); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pSubSeqLayerCharacteristics->averageFrameRate[i] = tmp; + } + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: DecodeSubSeqCharacteristics + + Functional description: + <++> + Inputs: + <++> + Outputs: + <++> + +------------------------------------------------------------------------------*/ + +static u32 DecodeSubSeqCharacteristics( + strmData_t *pStrmData, + seiSubSeqCharacteristics_t *pSubSeqCharacteristics) +{ + +/* Variables */ + + u32 tmp, i; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pSubSeqCharacteristics); + + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pSubSeqCharacteristics->subSeqLayerNum); + if (tmp != HANTRO_OK) + return(tmp); + if (pSubSeqCharacteristics->subSeqLayerNum > MAX_NUM_SUB_SEQ_LAYERS-1) + return(HANTRO_NOK); + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pSubSeqCharacteristics->subSeqId); + if (tmp != HANTRO_OK) + return(tmp); + if (pSubSeqCharacteristics->subSeqId > 65535) + return(HANTRO_NOK); + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pSubSeqCharacteristics->durationFlag = tmp == 1 ? + HANTRO_TRUE : HANTRO_FALSE; + + if (pSubSeqCharacteristics->durationFlag) + { + pSubSeqCharacteristics->subSeqDuration = h264bsdShowBits32(pStrmData); + if (h264bsdFlushBits(pStrmData,32) == END_OF_STREAM) + return(HANTRO_NOK); + } + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pSubSeqCharacteristics->averageRateFlag = tmp == 1 ? + HANTRO_TRUE : HANTRO_FALSE; + + if (pSubSeqCharacteristics->averageRateFlag) + { + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pSubSeqCharacteristics->accurateStatisticsFlag = + tmp == 1 ? HANTRO_TRUE : HANTRO_FALSE; + + tmp = h264bsdGetBits(pStrmData, 16); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pSubSeqCharacteristics->averageBitRate = tmp; + + tmp = h264bsdGetBits(pStrmData, 16); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pSubSeqCharacteristics->averageFrameRate = tmp; + } + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pSubSeqCharacteristics->numReferencedSubseqs); + if (tmp != HANTRO_OK) + return(tmp); + if (pSubSeqCharacteristics->numReferencedSubseqs > MAX_NUM_SUB_SEQ_LAYERS-1) + return(HANTRO_NOK); + + for (i = 0; i < pSubSeqCharacteristics->numReferencedSubseqs; i++) + { + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pSubSeqCharacteristics->refSubSeqLayerNum[i]); + if (tmp != HANTRO_OK) + return(tmp); + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pSubSeqCharacteristics->refSubSeqId[i]); + if (tmp != HANTRO_OK) + return(tmp); + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pSubSeqCharacteristics->refSubSeqDirection[i] = tmp; + } + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: DecodeFullFrameFreeze + + Functional description: + <++> + Inputs: + <++> + Outputs: + <++> + +------------------------------------------------------------------------------*/ + +static u32 DecodeFullFrameFreeze( + strmData_t *pStrmData, + seiFullFrameFreeze_t *pFullFrameFreeze) +{ + +/* Variables */ + + u32 tmp; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pFullFrameFreeze); + + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pFullFrameFreeze->fullFrameFreezeRepetitionPeriod); + if (tmp != HANTRO_OK) + return(tmp); + if (pFullFrameFreeze->fullFrameFreezeRepetitionPeriod > 16384) + return(HANTRO_NOK); + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: DecodeFullFrameSnapshot + + Functional description: + <++> + Inputs: + <++> + Outputs: + <++> + +------------------------------------------------------------------------------*/ + +static u32 DecodeFullFrameSnapshot( + strmData_t *pStrmData, + seiFullFrameSnapshot_t *pFullFrameSnapshot) +{ + +/* Variables */ + + u32 tmp; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pFullFrameSnapshot); + + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pFullFrameSnapshot->snapShotId); + if (tmp != HANTRO_OK) + return(tmp); + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: DecodeProgressiveRefinementSegmentStart + + Functional description: + <++> + Inputs: + <++> + Outputs: + <++> + +------------------------------------------------------------------------------*/ + +static u32 DecodeProgressiveRefinementSegmentStart( + strmData_t *pStrmData, + seiProgressiveRefinementSegmentStart_t *pProgressiveRefinementSegmentStart) +{ + +/* Variables */ + + u32 tmp; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pProgressiveRefinementSegmentStart); + + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pProgressiveRefinementSegmentStart->progressiveRefinementId); + if (tmp != HANTRO_OK) + return(tmp); + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pProgressiveRefinementSegmentStart->numRefinementSteps); + if (tmp != HANTRO_OK) + return(tmp); + pProgressiveRefinementSegmentStart->numRefinementSteps++; + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: DecodeProgressiveRefinementSegmentEnd + + Functional description: + <++> + Inputs: + <++> + Outputs: + <++> + +------------------------------------------------------------------------------*/ + +static u32 DecodeProgressiveRefinementSegmentEnd( + strmData_t *pStrmData, + seiProgressiveRefinementSegmentEnd_t *pProgressiveRefinementSegmentEnd) +{ + +/* Variables */ + + u32 tmp; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pProgressiveRefinementSegmentEnd); + + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pProgressiveRefinementSegmentEnd->progressiveRefinementId); + if (tmp != HANTRO_OK) + return(tmp); + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: DecodeMotionConstrainedSliceGroupSet + + Functional description: + <++> + Inputs: + <++> + Outputs: + <++> + +------------------------------------------------------------------------------*/ + +static u32 DecodeMotionConstrainedSliceGroupSet( + strmData_t *pStrmData, + seiMotionConstrainedSliceGroupSet_t *pMotionConstrainedSliceGroupSet, + u32 numSliceGroups) +{ + +/* Variables */ + + u32 tmp,i; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pMotionConstrainedSliceGroupSet); + ASSERT(numSliceGroups < MAX_NUM_SLICE_GROUPS); + + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pMotionConstrainedSliceGroupSet->numSliceGroupsInSet); + if (tmp != HANTRO_OK) + return(tmp); + pMotionConstrainedSliceGroupSet->numSliceGroupsInSet++; + if (pMotionConstrainedSliceGroupSet->numSliceGroupsInSet > numSliceGroups) + return(HANTRO_NOK); + + for (i = 0; i < pMotionConstrainedSliceGroupSet->numSliceGroupsInSet; i++) + { + tmp = h264bsdGetBits(pStrmData, + ceilLog2NumSliceGroups[numSliceGroups]); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pMotionConstrainedSliceGroupSet->sliceGroupId[i] = tmp; + if (pMotionConstrainedSliceGroupSet->sliceGroupId[i] > + pMotionConstrainedSliceGroupSet->numSliceGroupsInSet-1) + return(HANTRO_NOK); + } + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pMotionConstrainedSliceGroupSet->exactSampleValueMatchFlag = + tmp == 1 ? HANTRO_TRUE : HANTRO_FALSE; + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pMotionConstrainedSliceGroupSet->panScanRectFlag = tmp == 1 ? + HANTRO_TRUE : HANTRO_FALSE; + + if (pMotionConstrainedSliceGroupSet->panScanRectFlag) + { + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pMotionConstrainedSliceGroupSet->panScanRectId); + if (tmp != HANTRO_OK) + return(tmp); + } + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: DecodeReservedSeiMessage + + Functional description: + <++> + Inputs: + <++> + Outputs: + <++> + +------------------------------------------------------------------------------*/ + +static u32 DecodeReservedSeiMessage( + strmData_t *pStrmData, + seiReservedSeiMessage_t *pReservedSeiMessage, + u32 payloadSize) +{ + +/* Variables */ + + u32 i, tmp; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pReservedSeiMessage); + + + /* where corresponding FREE() ??? */ + ALLOCATE(pReservedSeiMessage->reservedSeiMessagePayloadByte,payloadSize,u8); + if (pReservedSeiMessage->reservedSeiMessagePayloadByte == NULL) + return(MEMORY_ALLOCATION_ERROR); + + pReservedSeiMessage->numPayloadBytes = payloadSize; + + for (i = 0; i < payloadSize; i++) + { + tmp = h264bsdGetBits(pStrmData,8); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pReservedSeiMessage->reservedSeiMessagePayloadByte[i] = (u8)tmp; + } + + return(HANTRO_OK); + +} + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_sei.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_sei.h new file mode 100755 index 0000000..efe543a --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_sei.h @@ -0,0 +1,252 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. Module defines + 3. Data types + 4. Function prototypes + +------------------------------------------------------------------------------*/ + +#ifndef H264SWDEC_SEI_H +#define H264SWDEC_SEI_H + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "basetype.h" +#include "h264bsd_stream.h" +#include "h264bsd_slice_header.h" +#include "h264bsd_seq_param_set.h" +#include "h264bsd_vui.h" + +/*------------------------------------------------------------------------------ + 2. Module defines +------------------------------------------------------------------------------*/ + +#define MAX_PAN_SCAN_CNT 32 +#define MAX_NUM_SPARE_PICS 16 +#define MAX_NUM_CLOCK_TS 3 +#define MAX_NUM_SUB_SEQ_LAYERS 256 + +/*------------------------------------------------------------------------------ + 3. Data types +------------------------------------------------------------------------------*/ + +typedef struct +{ + u32 seqParameterSetId; + u32 initialCpbRemovalDelay[MAX_CPB_CNT]; + u32 initialCpbRemovalDelayOffset[MAX_CPB_CNT]; +} seiBufferingPeriod_t; + +typedef struct +{ + u32 cpbRemovalDelay; + u32 dpbOutputDelay; + u32 picStruct; + u32 clockTimeStampFlag[MAX_NUM_CLOCK_TS]; + u32 clockTimeStamp[MAX_NUM_CLOCK_TS]; + u32 ctType[MAX_NUM_CLOCK_TS]; + u32 nuitFieldBasedFlag[MAX_NUM_CLOCK_TS]; + u32 countingType[MAX_NUM_CLOCK_TS]; + u32 fullTimeStampFlag[MAX_NUM_CLOCK_TS]; + u32 discontinuityFlag[MAX_NUM_CLOCK_TS]; + u32 cntDroppedFlag[MAX_NUM_CLOCK_TS]; + u32 nFrames[MAX_NUM_CLOCK_TS]; + u32 secondsFlag[MAX_NUM_CLOCK_TS]; + u32 secondsValue[MAX_NUM_CLOCK_TS]; + u32 minutesFlag[MAX_NUM_CLOCK_TS]; + u32 minutesValue[MAX_NUM_CLOCK_TS]; + u32 hoursFlag[MAX_NUM_CLOCK_TS]; + u32 hoursValue[MAX_NUM_CLOCK_TS]; + i32 timeOffset[MAX_NUM_CLOCK_TS]; +} seiPicTiming_t; + +typedef struct +{ + u32 panScanRectId; + u32 panScanRectCancelFlag; + u32 panScanCnt; + i32 panScanRectLeftOffset[MAX_PAN_SCAN_CNT]; + i32 panScanRectRightOffset[MAX_PAN_SCAN_CNT]; + i32 panScanRectTopOffset[MAX_PAN_SCAN_CNT]; + i32 panScanRectBottomOffset[MAX_PAN_SCAN_CNT]; + u32 panScanRectRepetitionPeriod; +} seiPanScanRect_t; + +typedef struct +{ + u32 ituTT35CountryCode; + u32 ituTT35CountryCodeExtensionByte; + u8 *ituTT35PayloadByte; + u32 numPayloadBytes; +} seiUserDataRegisteredItuTT35_t; + +typedef struct +{ + u32 uuidIsoIec11578[4]; + u8 *userDataPayloadByte; + u32 numPayloadBytes; +} seiUserDataUnregistered_t; + +typedef struct +{ + u32 recoveryFrameCnt; + u32 exactMatchFlag; + u32 brokenLinkFlag; + u32 changingSliceGroupIdc; +} seiRecoveryPoint_t; + +typedef struct +{ + u32 originalIdrFlag; + u32 originalFrameNum; + decRefPicMarking_t decRefPicMarking; +} seiDecRefPicMarkingRepetition_t; + +typedef struct +{ + u32 targetFrameNum; + u32 spareFieldFlag; + u32 targetBottomFieldFlag; + u32 numSparePics; + u32 deltaSpareFrameNum[MAX_NUM_SPARE_PICS]; + u32 spareBottomFieldFlag[MAX_NUM_SPARE_PICS]; + u32 spareAreaIdc[MAX_NUM_SPARE_PICS]; + u32 *spareUnitFlag[MAX_NUM_SPARE_PICS]; + u32 *zeroRunLength[MAX_NUM_SPARE_PICS]; +} seiSparePic_t; + +typedef struct +{ + u32 sceneInfoPresentFlag; + u32 sceneId; + u32 sceneTransitionType; + u32 secondSceneId; +} seiSceneInfo_t; + +typedef struct +{ + u32 subSeqLayerNum; + u32 subSeqId; + u32 firstRefPicFlag; + u32 leadingNonRefPicFlag; + u32 lastPicFlag; + u32 subSeqFrameNumFlag; + u32 subSeqFrameNum; +} seiSubSeqInfo_t; + +typedef struct +{ + u32 numSubSeqLayers; + u32 accurateStatisticsFlag[MAX_NUM_SUB_SEQ_LAYERS]; + u32 averageBitRate[MAX_NUM_SUB_SEQ_LAYERS]; + u32 averageFrameRate[MAX_NUM_SUB_SEQ_LAYERS]; +} seiSubSeqLayerCharacteristics_t; + +typedef struct +{ + u32 subSeqLayerNum; + u32 subSeqId; + u32 durationFlag; + u32 subSeqDuration; + u32 averageRateFlag; + u32 accurateStatisticsFlag; + u32 averageBitRate; + u32 averageFrameRate; + u32 numReferencedSubseqs; + u32 refSubSeqLayerNum[MAX_NUM_SUB_SEQ_LAYERS]; + u32 refSubSeqId[MAX_NUM_SUB_SEQ_LAYERS]; + u32 refSubSeqDirection[MAX_NUM_SUB_SEQ_LAYERS]; +} seiSubSeqCharacteristics_t; + +typedef struct +{ + u32 fullFrameFreezeRepetitionPeriod; +} seiFullFrameFreeze_t; + +typedef struct +{ + u32 snapShotId; +} seiFullFrameSnapshot_t; + +typedef struct +{ + u32 progressiveRefinementId; + u32 numRefinementSteps; +} seiProgressiveRefinementSegmentStart_t; + +typedef struct +{ + u32 progressiveRefinementId; +} seiProgressiveRefinementSegmentEnd_t; + +typedef struct +{ + u32 numSliceGroupsInSet; + u32 sliceGroupId[MAX_NUM_SLICE_GROUPS]; + u32 exactSampleValueMatchFlag; + u32 panScanRectFlag; + u32 panScanRectId; +} seiMotionConstrainedSliceGroupSet_t; + +typedef struct +{ + u8 *reservedSeiMessagePayloadByte; + u32 numPayloadBytes; +} seiReservedSeiMessage_t; + +typedef struct +{ + u32 payloadType; + seiBufferingPeriod_t bufferingPeriod; + seiPicTiming_t picTiming; + seiPanScanRect_t panScanRect; + seiUserDataRegisteredItuTT35_t userDataRegisteredItuTT35; + seiUserDataUnregistered_t userDataUnregistered; + seiRecoveryPoint_t recoveryPoint; + seiDecRefPicMarkingRepetition_t decRefPicMarkingRepetition; + seiSparePic_t sparePic; + seiSceneInfo_t sceneInfo; + seiSubSeqInfo_t subSeqInfo; + seiSubSeqLayerCharacteristics_t subSeqLayerCharacteristics; + seiSubSeqCharacteristics_t subSeqCharacteristics; + seiFullFrameFreeze_t fullFrameFreeze; + seiFullFrameSnapshot_t fullFrameSnapshot; + seiProgressiveRefinementSegmentStart_t progressiveRefinementSegmentStart; + seiProgressiveRefinementSegmentEnd_t progressiveRefinementSegmentEnd; + seiMotionConstrainedSliceGroupSet_t motionConstrainedSliceGroupSet; + seiReservedSeiMessage_t reservedSeiMessage; +} seiMessage_t; + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ + +u32 h264bsdDecodeSeiMessage( + strmData_t *pStrmData, + seqParamSet_t *pSeqParamSet, + seiMessage_t *pSeiMessage, + u32 numSliceGroups); + +#endif /* #ifdef H264SWDEC_SEI_H */ + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_seq_param_set.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_seq_param_set.c new file mode 100644 index 0000000..751051a --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_seq_param_set.c @@ -0,0 +1,577 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. External compiler flags + 3. Module defines + 4. Local function prototypes + 5. Functions + h264bsdDecodeSeqParamSet + GetDpbSize + h264bsdCompareSeqParamSets + +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "h264bsd_seq_param_set.h" +#include "h264bsd_util.h" +#include "h264bsd_vlc.h" +#include "h264bsd_vui.h" +#include "h264bsd_cfg.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +/* enumeration to indicate invalid return value from the GetDpbSize function */ +enum {INVALID_DPB_SIZE = 0x7FFFFFFF}; + +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ + +static u32 GetDpbSize(u32 picSizeInMbs, u32 levelIdc); + +/*------------------------------------------------------------------------------ + + Function name: h264bsdDecodeSeqParamSet + + Functional description: + Decode sequence parameter set information from the stream. + + Function allocates memory for offsetForRefFrame array if + picture order count type is 1 and numRefFramesInPicOrderCntCycle + is greater than zero. + + Inputs: + pStrmData pointer to stream data structure + + Outputs: + pSeqParamSet decoded information is stored here + + Returns: + HANTRO_OK success + HANTRO_NOK failure, invalid information or end of stream + MEMORY_ALLOCATION_ERROR for memory allocation failure + +------------------------------------------------------------------------------*/ + +u32 h264bsdDecodeSeqParamSet(strmData_t *pStrmData, seqParamSet_t *pSeqParamSet) +{ + +/* Variables */ + + u32 tmp, i, value; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pSeqParamSet); + + H264SwDecMemset(pSeqParamSet, 0, sizeof(seqParamSet_t)); + + /* profile_idc */ + tmp = h264bsdGetBits(pStrmData, 8); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + if (tmp != 66) + { + DEBUG(("NOT BASELINE PROFILE %d\n", tmp)); + } + pSeqParamSet->profileIdc = tmp; + + /* constrained_set0_flag */ + tmp = h264bsdGetBits(pStrmData, 1); + /* constrained_set1_flag */ + tmp = h264bsdGetBits(pStrmData, 1); + /* constrained_set2_flag */ + tmp = h264bsdGetBits(pStrmData, 1); + + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + + /* reserved_zero_5bits, values of these bits shall be ignored */ + tmp = h264bsdGetBits(pStrmData, 5); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + + tmp = h264bsdGetBits(pStrmData, 8); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pSeqParamSet->levelIdc = tmp; + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pSeqParamSet->seqParameterSetId); + if (tmp != HANTRO_OK) + return(tmp); + if (pSeqParamSet->seqParameterSetId >= MAX_NUM_SEQ_PARAM_SETS) + { + EPRINT("seq_param_set_id"); + return(HANTRO_NOK); + } + + /* log2_max_frame_num_minus4 */ + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + if (value > 12) + { + EPRINT("log2_max_frame_num_minus4"); + return(HANTRO_NOK); + } + /* maxFrameNum = 2^(log2_max_frame_num_minus4 + 4) */ + pSeqParamSet->maxFrameNum = 1 << (value+4); + + /* valid POC types are 0, 1 and 2 */ + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + if (value > 2) + { + EPRINT("pic_order_cnt_type"); + return(HANTRO_NOK); + } + pSeqParamSet->picOrderCntType = value; + + if (pSeqParamSet->picOrderCntType == 0) + { + /* log2_max_pic_order_cnt_lsb_minus4 */ + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + if (value > 12) + { + EPRINT("log2_max_pic_order_cnt_lsb_minus4"); + return(HANTRO_NOK); + } + /* maxPicOrderCntLsb = 2^(log2_max_pic_order_cnt_lsb_minus4 + 4) */ + pSeqParamSet->maxPicOrderCntLsb = 1 << (value+4); + } + else if (pSeqParamSet->picOrderCntType == 1) + { + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pSeqParamSet->deltaPicOrderAlwaysZeroFlag = (tmp == 1) ? + HANTRO_TRUE : HANTRO_FALSE; + + tmp = h264bsdDecodeExpGolombSigned(pStrmData, + &pSeqParamSet->offsetForNonRefPic); + if (tmp != HANTRO_OK) + return(tmp); + + tmp = h264bsdDecodeExpGolombSigned(pStrmData, + &pSeqParamSet->offsetForTopToBottomField); + if (tmp != HANTRO_OK) + return(tmp); + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pSeqParamSet->numRefFramesInPicOrderCntCycle); + if (tmp != HANTRO_OK) + return(tmp); + if (pSeqParamSet->numRefFramesInPicOrderCntCycle > 255) + { + EPRINT("num_ref_frames_in_pic_order_cnt_cycle"); + return(HANTRO_NOK); + } + + if (pSeqParamSet->numRefFramesInPicOrderCntCycle) + { + /* NOTE: This has to be freed somewhere! */ + ALLOCATE(pSeqParamSet->offsetForRefFrame, + pSeqParamSet->numRefFramesInPicOrderCntCycle, i32); + if (pSeqParamSet->offsetForRefFrame == NULL) + return(MEMORY_ALLOCATION_ERROR); + + for (i = 0; i < pSeqParamSet->numRefFramesInPicOrderCntCycle; i++) + { + tmp = h264bsdDecodeExpGolombSigned(pStrmData, + pSeqParamSet->offsetForRefFrame + i); + if (tmp != HANTRO_OK) + return(tmp); + } + } + else + { + pSeqParamSet->offsetForRefFrame = NULL; + } + } + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pSeqParamSet->numRefFrames); + if (tmp != HANTRO_OK) + return(tmp); + if (pSeqParamSet->numRefFrames > MAX_NUM_REF_PICS) + { + EPRINT("num_ref_frames"); + return(HANTRO_NOK); + } + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pSeqParamSet->gapsInFrameNumValueAllowedFlag = (tmp == 1) ? + HANTRO_TRUE : HANTRO_FALSE; + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + pSeqParamSet->picWidthInMbs = value + 1; + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + pSeqParamSet->picHeightInMbs = value + 1; + + /* frame_mbs_only_flag, shall be 1 for baseline profile */ + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + if (!tmp) + { + EPRINT("frame_mbs_only_flag"); + return(HANTRO_NOK); + } + + /* direct_8x8_inference_flag */ + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pSeqParamSet->frameCroppingFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; + + if (pSeqParamSet->frameCroppingFlag) + { + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pSeqParamSet->frameCropLeftOffset); + if (tmp != HANTRO_OK) + return(tmp); + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pSeqParamSet->frameCropRightOffset); + if (tmp != HANTRO_OK) + return(tmp); + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pSeqParamSet->frameCropTopOffset); + if (tmp != HANTRO_OK) + return(tmp); + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pSeqParamSet->frameCropBottomOffset); + if (tmp != HANTRO_OK) + return(tmp); + + /* check that frame cropping params are valid, parameters shall + * specify non-negative area within the original picture */ + if ( ( (i32)pSeqParamSet->frameCropLeftOffset > + ( 8 * (i32)pSeqParamSet->picWidthInMbs - + ((i32)pSeqParamSet->frameCropRightOffset + 1) ) ) || + ( (i32)pSeqParamSet->frameCropTopOffset > + ( 8 * (i32)pSeqParamSet->picHeightInMbs - + ((i32)pSeqParamSet->frameCropBottomOffset + 1) ) ) ) + { + EPRINT("frame_cropping"); + return(HANTRO_NOK); + } + } + + /* check that image dimensions and levelIdc match */ + tmp = pSeqParamSet->picWidthInMbs * pSeqParamSet->picHeightInMbs; + value = GetDpbSize(tmp, pSeqParamSet->levelIdc); + if (value == INVALID_DPB_SIZE || pSeqParamSet->numRefFrames > value) + { + DEBUG(("WARNING! Invalid DPB size based on SPS Level!\n")); + DEBUG(("WARNING! Using num_ref_frames =%d for DPB size!\n", + pSeqParamSet->numRefFrames)); + value = pSeqParamSet->numRefFrames; + } + pSeqParamSet->maxDpbSize = value; + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pSeqParamSet->vuiParametersPresentFlag = (tmp == 1) ? + HANTRO_TRUE : HANTRO_FALSE; + + /* VUI */ + if (pSeqParamSet->vuiParametersPresentFlag) + { + ALLOCATE(pSeqParamSet->vuiParameters, 1, vuiParameters_t); + if (pSeqParamSet->vuiParameters == NULL) + return(MEMORY_ALLOCATION_ERROR); + tmp = h264bsdDecodeVuiParameters(pStrmData, + pSeqParamSet->vuiParameters); + if (tmp != HANTRO_OK) + return(tmp); + /* check numReorderFrames and maxDecFrameBuffering */ + if (pSeqParamSet->vuiParameters->bitstreamRestrictionFlag) + { + if (pSeqParamSet->vuiParameters->numReorderFrames > + pSeqParamSet->vuiParameters->maxDecFrameBuffering || + pSeqParamSet->vuiParameters->maxDecFrameBuffering < + pSeqParamSet->numRefFrames || + pSeqParamSet->vuiParameters->maxDecFrameBuffering > + pSeqParamSet->maxDpbSize) + { + return(HANTRO_NOK); + } + + /* standard says that "the sequence shall not require a DPB with + * size of more than max(1, maxDecFrameBuffering) */ + pSeqParamSet->maxDpbSize = + MAX(1, pSeqParamSet->vuiParameters->maxDecFrameBuffering); + } + } + + tmp = h264bsdRbspTrailingBits(pStrmData); + + /* ignore possible errors in trailing bits of parameters sets */ + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: GetDpbSize + + Functional description: + Get size of the DPB in frames. Size is determined based on the + picture size and MaxDPB for the specified level. These determine + how many pictures may fit into to the buffer. However, the size + is also limited to a maximum of 16 frames and therefore function + returns the minimum of the determined size and 16. + + Inputs: + picSizeInMbs number of macroblocks in the picture + levelIdc indicates the level + + Outputs: + none + + Returns: + size of the DPB in frames + INVALID_DPB_SIZE when invalid levelIdc specified or picSizeInMbs + is higher than supported by the level in question + +------------------------------------------------------------------------------*/ + +u32 GetDpbSize(u32 picSizeInMbs, u32 levelIdc) +{ + +/* Variables */ + + u32 tmp; + u32 maxPicSizeInMbs; + +/* Code */ + + ASSERT(picSizeInMbs); + + /* use tmp as the size of the DPB in bytes, computes as 1024 * MaxDPB + * (from table A-1 in Annex A) */ + switch (levelIdc) + { + case 10: + tmp = 152064; + maxPicSizeInMbs = 99; + break; + + case 11: + tmp = 345600; + maxPicSizeInMbs = 396; + break; + + case 12: + tmp = 912384; + maxPicSizeInMbs = 396; + break; + + case 13: + tmp = 912384; + maxPicSizeInMbs = 396; + break; + + case 20: + tmp = 912384; + maxPicSizeInMbs = 396; + break; + + case 21: + tmp = 1824768; + maxPicSizeInMbs = 792; + break; + + case 22: + tmp = 3110400; + maxPicSizeInMbs = 1620; + break; + + case 30: + tmp = 3110400; + maxPicSizeInMbs = 1620; + break; + + case 31: + tmp = 6912000; + maxPicSizeInMbs = 3600; + break; + + case 32: + tmp = 7864320; + maxPicSizeInMbs = 5120; + break; + + case 40: + tmp = 12582912; + maxPicSizeInMbs = 8192; + break; + + case 41: + tmp = 12582912; + maxPicSizeInMbs = 8192; + break; + + case 42: + tmp = 34816*384; + maxPicSizeInMbs = 8704; + break; + + case 50: + /* standard says 42301440 here, but corrigendum "corrects" this to + * 42393600 */ + tmp = 42393600; + maxPicSizeInMbs = 22080; + break; + + case 51: + tmp = 70778880; + maxPicSizeInMbs = 36864; + break; + + default: + return(INVALID_DPB_SIZE); + } + + /* this is not "correct" return value! However, it results in error in + * decoding and this was easiest place to check picture size */ + if (picSizeInMbs > maxPicSizeInMbs) + return(INVALID_DPB_SIZE); + + tmp /= (picSizeInMbs*384); + + return(MIN(tmp, 16)); + +} + +/*------------------------------------------------------------------------------ + + Function name: h264bsdCompareSeqParamSets + + Functional description: + Compare two sequence parameter sets. + + Inputs: + pSps1 pointer to a sequence parameter set + pSps2 pointer to another sequence parameter set + + Outputs: + 0 sequence parameter sets are equal + 1 otherwise + +------------------------------------------------------------------------------*/ + +u32 h264bsdCompareSeqParamSets(seqParamSet_t *pSps1, seqParamSet_t *pSps2) +{ + +/* Variables */ + + u32 i; + +/* Code */ + + ASSERT(pSps1); + ASSERT(pSps2); + + /* first compare parameters whose existence does not depend on other + * parameters and only compare the rest of the params if these are equal */ + if (pSps1->profileIdc == pSps2->profileIdc && + pSps1->levelIdc == pSps2->levelIdc && + pSps1->maxFrameNum == pSps2->maxFrameNum && + pSps1->picOrderCntType == pSps2->picOrderCntType && + pSps1->numRefFrames == pSps2->numRefFrames && + pSps1->gapsInFrameNumValueAllowedFlag == + pSps2->gapsInFrameNumValueAllowedFlag && + pSps1->picWidthInMbs == pSps2->picWidthInMbs && + pSps1->picHeightInMbs == pSps2->picHeightInMbs && + pSps1->frameCroppingFlag == pSps2->frameCroppingFlag && + pSps1->vuiParametersPresentFlag == pSps2->vuiParametersPresentFlag) + { + if (pSps1->picOrderCntType == 0) + { + if (pSps1->maxPicOrderCntLsb != pSps2->maxPicOrderCntLsb) + return 1; + } + else if (pSps1->picOrderCntType == 1) + { + if (pSps1->deltaPicOrderAlwaysZeroFlag != + pSps2->deltaPicOrderAlwaysZeroFlag || + pSps1->offsetForNonRefPic != pSps2->offsetForNonRefPic || + pSps1->offsetForTopToBottomField != + pSps2->offsetForTopToBottomField || + pSps1->numRefFramesInPicOrderCntCycle != + pSps2->numRefFramesInPicOrderCntCycle) + { + return 1; + } + else + { + for (i = 0; i < pSps1->numRefFramesInPicOrderCntCycle; i++) + if (pSps1->offsetForRefFrame[i] != + pSps2->offsetForRefFrame[i]) + { + return 1; + } + } + } + if (pSps1->frameCroppingFlag) + { + if (pSps1->frameCropLeftOffset != pSps2->frameCropLeftOffset || + pSps1->frameCropRightOffset != pSps2->frameCropRightOffset || + pSps1->frameCropTopOffset != pSps2->frameCropTopOffset || + pSps1->frameCropBottomOffset != pSps2->frameCropBottomOffset) + { + return 1; + } + } + + return 0; + } + + return 1; +} + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_seq_param_set.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_seq_param_set.h new file mode 100755 index 0000000..e18df94 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_seq_param_set.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. Module defines + 3. Data types + 4. Function prototypes + +------------------------------------------------------------------------------*/ + +#ifndef H264SWDEC_SEQ_PARAM_SET_H +#define H264SWDEC_SEQ_PARAM_SET_H + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "basetype.h" +#include "h264bsd_stream.h" +#include "h264bsd_vui.h" + +/*------------------------------------------------------------------------------ + 2. Module defines +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 3. Data types +------------------------------------------------------------------------------*/ + +/* structure to store sequence parameter set information decoded from the + * stream */ +typedef struct +{ + u32 profileIdc; + u32 levelIdc; + u32 seqParameterSetId; + u32 maxFrameNum; + u32 picOrderCntType; + u32 maxPicOrderCntLsb; + u32 deltaPicOrderAlwaysZeroFlag; + i32 offsetForNonRefPic; + i32 offsetForTopToBottomField; + u32 numRefFramesInPicOrderCntCycle; + i32 *offsetForRefFrame; + u32 numRefFrames; + u32 gapsInFrameNumValueAllowedFlag; + u32 picWidthInMbs; + u32 picHeightInMbs; + u32 frameCroppingFlag; + u32 frameCropLeftOffset; + u32 frameCropRightOffset; + u32 frameCropTopOffset; + u32 frameCropBottomOffset; + u32 vuiParametersPresentFlag; + vuiParameters_t *vuiParameters; + u32 maxDpbSize; +} seqParamSet_t; + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ + +u32 h264bsdDecodeSeqParamSet(strmData_t *pStrmData, + seqParamSet_t *pSeqParamSet); + +u32 h264bsdCompareSeqParamSets(seqParamSet_t *pSps1, seqParamSet_t *pSps2); + +#endif /* #ifdef H264SWDEC_SEQ_PARAM_SET_H */ + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_data.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_data.c new file mode 100755 index 0000000..c288d4b --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_data.c @@ -0,0 +1,354 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. External compiler flags + 3. Module defines + 4. Local function prototypes + 5. Functions + h264bsdDecodeSliceData + SetMbParams + h264bsdMarkSliceCorrupted + +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "h264bsd_slice_data.h" +#include "h264bsd_util.h" +#include "h264bsd_vlc.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ + +static void SetMbParams(mbStorage_t *pMb, sliceHeader_t *pSlice, u32 sliceId, + i32 chromaQpIndexOffset); + +/*------------------------------------------------------------------------------ + + 5.1 Function name: h264bsdDecodeSliceData + + Functional description: + Decode one slice. Function decodes stream data, i.e. macroblocks + and possible skip_run fields. h264bsdDecodeMacroblock function is + called to handle all other macroblock related processing. + Macroblock to slice group mapping is considered when next + macroblock to process is determined (h264bsdNextMbAddress function) + map + + Inputs: + pStrmData pointer to stream data structure + pStorage pointer to storage structure + currImage pointer to current processed picture, needed for + intra prediction of the macroblocks + pSliceHeader pointer to slice header of the current slice + + Outputs: + currImage processed macroblocks are written to current image + pStorage mbStorage structure of each processed macroblock + is updated here + + Returns: + HANTRO_OK success + HANTRO_NOK invalid stream data + +------------------------------------------------------------------------------*/ + +u32 h264bsdDecodeSliceData(strmData_t *pStrmData, storage_t *pStorage, + image_t *currImage, sliceHeader_t *pSliceHeader) +{ + +/* Variables */ + + u8 mbData[384 + 15 + 32]; + u8 *data; + u32 tmp; + u32 skipRun; + u32 prevSkipped; + u32 currMbAddr; + u32 moreMbs; + u32 mbCount; + i32 qpY; + macroblockLayer_t *mbLayer; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pSliceHeader); + ASSERT(pStorage); + ASSERT(pSliceHeader->firstMbInSlice < pStorage->picSizeInMbs); + + /* ensure 16-byte alignment */ + data = (u8*)ALIGN(mbData, 16); + + mbLayer = pStorage->mbLayer; + + currMbAddr = pSliceHeader->firstMbInSlice; + skipRun = 0; + prevSkipped = HANTRO_FALSE; + + /* increment slice index, will be one for decoding of the first slice of + * the picture */ + pStorage->slice->sliceId++; + + /* lastMbAddr stores address of the macroblock that was last successfully + * decoded, needed for error handling */ + pStorage->slice->lastMbAddr = 0; + + mbCount = 0; + /* initial quantization parameter for the slice is obtained as the sum of + * initial QP for the picture and sliceQpDelta for the current slice */ + qpY = (i32)pStorage->activePps->picInitQp + pSliceHeader->sliceQpDelta; + do + { + /* primary picture and already decoded macroblock -> error */ + if (!pSliceHeader->redundantPicCnt && pStorage->mb[currMbAddr].decoded) + { + EPRINT("Primary and already decoded"); + return(HANTRO_NOK); + } + + SetMbParams(pStorage->mb + currMbAddr, pSliceHeader, + pStorage->slice->sliceId, pStorage->activePps->chromaQpIndexOffset); + + if (!IS_I_SLICE(pSliceHeader->sliceType)) + { + if (!prevSkipped) + { + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &skipRun); + if (tmp != HANTRO_OK) + return(tmp); + /* skip_run shall be less than or equal to number of + * macroblocks left */ + if (skipRun > (pStorage->picSizeInMbs - currMbAddr)) + { + EPRINT("skip_run"); + return(HANTRO_NOK); + } + if (skipRun) + { + prevSkipped = HANTRO_TRUE; + H264SwDecMemset(&mbLayer->mbPred, 0, sizeof(mbPred_t)); + /* mark current macroblock skipped */ + mbLayer->mbType = P_Skip; + } + } + } + + if (skipRun) + { + DEBUG(("Skipping macroblock %d\n", currMbAddr)); + skipRun--; + } + else + { + prevSkipped = HANTRO_FALSE; + tmp = h264bsdDecodeMacroblockLayer(pStrmData, mbLayer, + pStorage->mb + currMbAddr, pSliceHeader->sliceType, + pSliceHeader->numRefIdxL0Active); + if (tmp != HANTRO_OK) + { + EPRINT("macroblock_layer"); + return(tmp); + } + } + + tmp = h264bsdDecodeMacroblock(pStorage->mb + currMbAddr, mbLayer, + currImage, pStorage->dpb, &qpY, currMbAddr, + pStorage->activePps->constrainedIntraPredFlag, data); + if (tmp != HANTRO_OK) + { + EPRINT("MACRO_BLOCK"); + return(tmp); + } + + /* increment macroblock count only for macroblocks that were decoded + * for the first time (redundant slices) */ + if (pStorage->mb[currMbAddr].decoded == 1) + mbCount++; + + /* keep on processing as long as there is stream data left or + * processing of macroblocks to be skipped based on the last skipRun is + * not finished */ + moreMbs = (h264bsdMoreRbspData(pStrmData) || skipRun) ? + HANTRO_TRUE : HANTRO_FALSE; + + /* lastMbAddr is only updated for intra slices (all macroblocks of + * inter slices will be lost in case of an error) */ + if (IS_I_SLICE(pSliceHeader->sliceType)) + pStorage->slice->lastMbAddr = currMbAddr; + + currMbAddr = h264bsdNextMbAddress(pStorage->sliceGroupMap, + pStorage->picSizeInMbs, currMbAddr); + /* data left in the buffer but no more macroblocks for current slice + * group -> error */ + if (moreMbs && !currMbAddr) + { + EPRINT("Next mb address"); + return(HANTRO_NOK); + } + + } while (moreMbs); + + if ((pStorage->slice->numDecodedMbs + mbCount) > pStorage->picSizeInMbs) + { + EPRINT("Num decoded mbs"); + return(HANTRO_NOK); + } + + pStorage->slice->numDecodedMbs += mbCount; + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + 5.2 Function: SetMbParams + + Functional description: + Set macroblock parameters that remain constant for this slice + + Inputs: + pSlice pointer to current slice header + sliceId id of the current slice + chromaQpIndexOffset + + Outputs: + pMb pointer to macroblock structure which is updated + + Returns: + none + +------------------------------------------------------------------------------*/ + +void SetMbParams(mbStorage_t *pMb, sliceHeader_t *pSlice, u32 sliceId, + i32 chromaQpIndexOffset) +{ + +/* Variables */ + u32 tmp1; + i32 tmp2, tmp3; + +/* Code */ + + tmp1 = pSlice->disableDeblockingFilterIdc; + tmp2 = pSlice->sliceAlphaC0Offset; + tmp3 = pSlice->sliceBetaOffset; + pMb->sliceId = sliceId; + pMb->disableDeblockingFilterIdc = tmp1; + pMb->filterOffsetA = tmp2; + pMb->filterOffsetB = tmp3; + pMb->chromaQpIndexOffset = chromaQpIndexOffset; + +} + +/*------------------------------------------------------------------------------ + + 5.3 Function name: h264bsdMarkSliceCorrupted + + Functional description: + Mark macroblocks of the slice corrupted. If lastMbAddr in the slice + storage is set -> picWidhtInMbs (or at least 10) macroblocks back + from the lastMbAddr are marked corrupted. However, if lastMbAddr + is not set -> all macroblocks of the slice are marked. + + Inputs: + pStorage pointer to storage structure + firstMbInSlice address of the first macroblock in the slice, this + identifies the slice to be marked corrupted + + Outputs: + pStorage mbStorage for the corrupted macroblocks updated + + Returns: + none + +------------------------------------------------------------------------------*/ + +void h264bsdMarkSliceCorrupted(storage_t *pStorage, u32 firstMbInSlice) +{ + +/* Variables */ + + u32 tmp, i; + u32 sliceId; + u32 currMbAddr; + +/* Code */ + + ASSERT(pStorage); + ASSERT(firstMbInSlice < pStorage->picSizeInMbs); + + currMbAddr = firstMbInSlice; + + sliceId = pStorage->slice->sliceId; + + /* DecodeSliceData sets lastMbAddr for I slices -> if it was set, go back + * MAX(picWidthInMbs, 10) macroblocks and start marking from there */ + if (pStorage->slice->lastMbAddr) + { + ASSERT(pStorage->mb[pStorage->slice->lastMbAddr].sliceId == sliceId); + i = pStorage->slice->lastMbAddr - 1; + tmp = 0; + while (i > currMbAddr) + { + if (pStorage->mb[i].sliceId == sliceId) + { + tmp++; + if (tmp >= MAX(pStorage->activeSps->picWidthInMbs, 10)) + break; + } + i--; + } + currMbAddr = i; + } + + do + { + + if ( (pStorage->mb[currMbAddr].sliceId == sliceId) && + (pStorage->mb[currMbAddr].decoded) ) + { + pStorage->mb[currMbAddr].decoded--; + } + else + { + break; + } + + currMbAddr = h264bsdNextMbAddress(pStorage->sliceGroupMap, + pStorage->picSizeInMbs, currMbAddr); + + } while (currMbAddr); + +} + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_data.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_data.h new file mode 100755 index 0000000..f23d49e --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_data.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. Module defines + 3. Data types + 4. Function prototypes + +------------------------------------------------------------------------------*/ + +#ifndef H264SWDEC_SLICE_DATA_H +#define H264SWDEC_SLICE_DATA_H + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "basetype.h" +#include "h264bsd_stream.h" +#include "h264bsd_cfg.h" +#include "h264bsd_slice_header.h" +#include "h264bsd_storage.h" + +/*------------------------------------------------------------------------------ + 2. Module defines +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 3. Data types +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ + +u32 h264bsdDecodeSliceData(strmData_t *pStrmData, storage_t *pStorage, + image_t *currImage, sliceHeader_t *pSliceHeader); + +void h264bsdMarkSliceCorrupted(storage_t *pStorage, u32 firstMbInSlice); + +#endif /* #ifdef H264SWDEC_SLICE_DATA_H */ + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_group_map.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_group_map.c new file mode 100755 index 0000000..7cbb534 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_group_map.c @@ -0,0 +1,589 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. External compiler flags + 3. Module defines + 4. Local function prototypes + 5. Functions + DecodeInterleavedMap + DecodeDispersedMap + DecodeForegroundLeftOverMap + DecodeBoxOutMap + DecodeRasterScanMap + DecodeWipeMap + h264bsdDecodeSliceGroupMap + +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "basetype.h" +#include "h264bsd_slice_group_map.h" +#include "h264bsd_cfg.h" +#include "h264bsd_pic_param_set.h" +#include "h264bsd_util.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ + +static void DecodeInterleavedMap( + u32 *map, + u32 numSliceGroups, + u32 *runLength, + u32 picSize); + +static void DecodeDispersedMap( + u32 *map, + u32 numSliceGroups, + u32 picWidth, + u32 picHeight); + +static void DecodeForegroundLeftOverMap( + u32 *map, + u32 numSliceGroups, + u32 *topLeft, + u32 *bottomRight, + u32 picWidth, + u32 picHeight); + +static void DecodeBoxOutMap( + u32 *map, + u32 sliceGroupChangeDirectionFlag, + u32 unitsInSliceGroup0, + u32 picWidth, + u32 picHeight); + +static void DecodeRasterScanMap( + u32 *map, + u32 sliceGroupChangeDirectionFlag, + u32 sizeOfUpperLeftGroup, + u32 picSize); + +static void DecodeWipeMap( + u32 *map, + u32 sliceGroupChangeDirectionFlag, + u32 sizeOfUpperLeftGroup, + u32 picWidth, + u32 picHeight); + +/*------------------------------------------------------------------------------ + + Function: DecodeInterleavedMap + + Functional description: + Function to decode interleaved slice group map type, i.e. slice + group map type 0. + + Inputs: + map pointer to the map + numSliceGroups number of slice groups + runLength run_length[] values for each slice group + picSize picture size in macroblocks + + Outputs: + map slice group map is stored here + + Returns: + none + +------------------------------------------------------------------------------*/ + +void DecodeInterleavedMap( + u32 *map, + u32 numSliceGroups, + u32 *runLength, + u32 picSize) +{ + +/* Variables */ + + u32 i,j, group; + +/* Code */ + + ASSERT(map); + ASSERT(numSliceGroups >= 1 && numSliceGroups <= MAX_NUM_SLICE_GROUPS); + ASSERT(runLength); + + i = 0; + + do { + for (group = 0; group < numSliceGroups && i < picSize; + i += runLength[group++]) + { + ASSERT(runLength[group] <= picSize); + for (j = 0; j < runLength[group] && i + j < picSize; j++) + map[i+j] = group; + } + } while (i < picSize); + + +} + +/*------------------------------------------------------------------------------ + + Function: DecodeDispersedMap + + Functional description: + Function to decode dispersed slice group map type, i.e. slice + group map type 1. + + Inputs: + map pointer to the map + numSliceGroups number of slice groups + picWidth picture width in macroblocks + picHeight picture height in macroblocks + + Outputs: + map slice group map is stored here + + Returns: + none + +------------------------------------------------------------------------------*/ + +void DecodeDispersedMap( + u32 *map, + u32 numSliceGroups, + u32 picWidth, + u32 picHeight) +{ + +/* Variables */ + + u32 i, picSize; + +/* Code */ + + ASSERT(map); + ASSERT(numSliceGroups >= 1 && numSliceGroups <= MAX_NUM_SLICE_GROUPS); + ASSERT(picWidth); + ASSERT(picHeight); + + picSize = picWidth * picHeight; + + for (i = 0; i < picSize; i++) + map[i] = ((i % picWidth) + (((i / picWidth) * numSliceGroups) >> 1)) % + numSliceGroups; + + +} + +/*------------------------------------------------------------------------------ + + Function: DecodeForegroundLeftOverMap + + Functional description: + Function to decode foreground with left-over slice group map type, + i.e. slice group map type 2. + + Inputs: + map pointer to the map + numSliceGroups number of slice groups + topLeft top_left[] values + bottomRight bottom_right[] values + picWidth picture width in macroblocks + picHeight picture height in macroblocks + + Outputs: + map slice group map is stored here + + Returns: + none + +------------------------------------------------------------------------------*/ + +void DecodeForegroundLeftOverMap( + u32 *map, + u32 numSliceGroups, + u32 *topLeft, + u32 *bottomRight, + u32 picWidth, + u32 picHeight) +{ + +/* Variables */ + + u32 i,y,x,yTopLeft,yBottomRight,xTopLeft,xBottomRight, picSize; + u32 group; + +/* Code */ + + ASSERT(map); + ASSERT(numSliceGroups >= 1 && numSliceGroups <= MAX_NUM_SLICE_GROUPS); + ASSERT(topLeft); + ASSERT(bottomRight); + ASSERT(picWidth); + ASSERT(picHeight); + + picSize = picWidth * picHeight; + + for (i = 0; i < picSize; i++) + map[i] = numSliceGroups - 1; + + for (group = numSliceGroups - 1; group--; ) + { + ASSERT( topLeft[group] <= bottomRight[group] && + bottomRight[group] < picSize ); + yTopLeft = topLeft[group] / picWidth; + xTopLeft = topLeft[group] % picWidth; + yBottomRight = bottomRight[group] / picWidth; + xBottomRight = bottomRight[group] % picWidth; + ASSERT(xTopLeft <= xBottomRight); + + for (y = yTopLeft; y <= yBottomRight; y++) + for (x = xTopLeft; x <= xBottomRight; x++) + map[ y * picWidth + x ] = group; + } + + +} + +/*------------------------------------------------------------------------------ + + Function: DecodeBoxOutMap + + Functional description: + Function to decode box-out slice group map type, i.e. slice group + map type 3. + + Inputs: + map pointer to the map + sliceGroupChangeDirectionFlag slice_group_change_direction_flag + unitsInSliceGroup0 mbs on slice group 0 + picWidth picture width in macroblocks + picHeight picture height in macroblocks + + Outputs: + map slice group map is stored here + + Returns: + none + +------------------------------------------------------------------------------*/ + +void DecodeBoxOutMap( + u32 *map, + u32 sliceGroupChangeDirectionFlag, + u32 unitsInSliceGroup0, + u32 picWidth, + u32 picHeight) +{ + +/* Variables */ + + u32 i, k, picSize; + i32 x, y, xDir, yDir, leftBound, topBound, rightBound, bottomBound; + u32 mapUnitVacant; + +/* Code */ + + ASSERT(map); + ASSERT(picWidth); + ASSERT(picHeight); + + picSize = picWidth * picHeight; + ASSERT(unitsInSliceGroup0 <= picSize); + + for (i = 0; i < picSize; i++) + map[i] = 1; + + x = (picWidth - (u32)sliceGroupChangeDirectionFlag) >> 1; + y = (picHeight - (u32)sliceGroupChangeDirectionFlag) >> 1; + + leftBound = x; + topBound = y; + + rightBound = x; + bottomBound = y; + + xDir = (i32)sliceGroupChangeDirectionFlag - 1; + yDir = (i32)sliceGroupChangeDirectionFlag; + + for (k = 0; k < unitsInSliceGroup0; k += mapUnitVacant ? 1 : 0) + { + mapUnitVacant = (map[ (u32)y * picWidth + (u32)x ] == 1) ? + HANTRO_TRUE : HANTRO_FALSE; + + if (mapUnitVacant) + map[ (u32)y * picWidth + (u32)x ] = 0; + + if (xDir == -1 && x == leftBound) + { + leftBound = MAX(leftBound - 1, 0); + x = leftBound; + xDir = 0; + yDir = 2 * (i32)sliceGroupChangeDirectionFlag - 1; + } + else if (xDir == 1 && x == rightBound) + { + rightBound = MIN(rightBound + 1, (i32)picWidth - 1); + x = rightBound; + xDir = 0; + yDir = 1 - 2 * (i32)sliceGroupChangeDirectionFlag; + } + else if (yDir == -1 && y == topBound) + { + topBound = MAX(topBound - 1, 0); + y = topBound; + xDir = 1 - 2 * (i32)sliceGroupChangeDirectionFlag; + yDir = 0; + } + else if (yDir == 1 && y == bottomBound) + { + bottomBound = MIN(bottomBound + 1, (i32)picHeight - 1); + y = bottomBound; + xDir = 2 * (i32)sliceGroupChangeDirectionFlag - 1; + yDir = 0; + } + else + { + x += xDir; + y += yDir; + } + } + + +} + +/*------------------------------------------------------------------------------ + + Function: DecodeRasterScanMap + + Functional description: + Function to decode raster scan slice group map type, i.e. slice + group map type 4. + + Inputs: + map pointer to the map + sliceGroupChangeDirectionFlag slice_group_change_direction_flag + sizeOfUpperLeftGroup mbs in upperLeftGroup + picSize picture size in macroblocks + + Outputs: + map slice group map is stored here + + Returns: + none + +------------------------------------------------------------------------------*/ + +void DecodeRasterScanMap( + u32 *map, + u32 sliceGroupChangeDirectionFlag, + u32 sizeOfUpperLeftGroup, + u32 picSize) +{ + +/* Variables */ + + u32 i; + +/* Code */ + + ASSERT(map); + ASSERT(picSize); + ASSERT(sizeOfUpperLeftGroup <= picSize); + + for (i = 0; i < picSize; i++) + if (i < sizeOfUpperLeftGroup) + map[i] = (u32)sliceGroupChangeDirectionFlag; + else + map[i] = 1 - (u32)sliceGroupChangeDirectionFlag; + + +} + +/*------------------------------------------------------------------------------ + + Function: DecodeWipeMap + + Functional description: + Function to decode wipe slice group map type, i.e. slice group map + type 5. + + Inputs: + sliceGroupChangeDirectionFlag slice_group_change_direction_flag + sizeOfUpperLeftGroup mbs in upperLeftGroup + picWidth picture width in macroblocks + picHeight picture height in macroblocks + + Outputs: + map slice group map is stored here + + Returns: + none + +------------------------------------------------------------------------------*/ + +void DecodeWipeMap( + u32 *map, + u32 sliceGroupChangeDirectionFlag, + u32 sizeOfUpperLeftGroup, + u32 picWidth, + u32 picHeight) +{ + +/* Variables */ + + u32 i,j,k; + +/* Code */ + + ASSERT(map); + ASSERT(picWidth); + ASSERT(picHeight); + ASSERT(sizeOfUpperLeftGroup <= picWidth * picHeight); + + k = 0; + for (j = 0; j < picWidth; j++) + for (i = 0; i < picHeight; i++) + if (k++ < sizeOfUpperLeftGroup) + map[ i * picWidth + j ] = (u32)sliceGroupChangeDirectionFlag; + else + map[ i * picWidth + j ] = 1 - + (u32)sliceGroupChangeDirectionFlag; + + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdDecodeSliceGroupMap + + Functional description: + Function to decode macroblock to slice group map. Construction + of different slice group map types is handled by separate + functions defined above. See standard for details how slice group + maps are computed. + + Inputs: + pps active picture parameter set + sliceGroupChangeCycle slice_group_change_cycle + picWidth picture width in macroblocks + picHeight picture height in macroblocks + + Outputs: + map slice group map is stored here + + Returns: + none + +------------------------------------------------------------------------------*/ + +void h264bsdDecodeSliceGroupMap( + u32 *map, + picParamSet_t *pps, + u32 sliceGroupChangeCycle, + u32 picWidth, + u32 picHeight) +{ + +/* Variables */ + + u32 i, picSize, unitsInSliceGroup0 = 0, sizeOfUpperLeftGroup = 0; + +/* Code */ + + ASSERT(map); + ASSERT(pps); + ASSERT(picWidth); + ASSERT(picHeight); + ASSERT(pps->sliceGroupMapType < 7); + + picSize = picWidth * picHeight; + + /* just one slice group -> all macroblocks belong to group 0 */ + if (pps->numSliceGroups == 1) + { + H264SwDecMemset(map, 0, picSize * sizeof(u32)); + return; + } + + if (pps->sliceGroupMapType > 2 && pps->sliceGroupMapType < 6) + { + ASSERT(pps->sliceGroupChangeRate && + pps->sliceGroupChangeRate <= picSize); + + unitsInSliceGroup0 = + MIN(sliceGroupChangeCycle * pps->sliceGroupChangeRate, picSize); + + if (pps->sliceGroupMapType == 4 || pps->sliceGroupMapType == 5) + sizeOfUpperLeftGroup = pps->sliceGroupChangeDirectionFlag ? + (picSize - unitsInSliceGroup0) : unitsInSliceGroup0; + } + + switch (pps->sliceGroupMapType) + { + case 0: + DecodeInterleavedMap(map, pps->numSliceGroups, + pps->runLength, picSize); + break; + + case 1: + DecodeDispersedMap(map, pps->numSliceGroups, picWidth, + picHeight); + break; + + case 2: + DecodeForegroundLeftOverMap(map, pps->numSliceGroups, + pps->topLeft, pps->bottomRight, picWidth, picHeight); + break; + + case 3: + DecodeBoxOutMap(map, pps->sliceGroupChangeDirectionFlag, + unitsInSliceGroup0, picWidth, picHeight); + break; + + case 4: + DecodeRasterScanMap(map, + pps->sliceGroupChangeDirectionFlag, sizeOfUpperLeftGroup, + picSize); + break; + + case 5: + DecodeWipeMap(map, pps->sliceGroupChangeDirectionFlag, + sizeOfUpperLeftGroup, picWidth, picHeight); + break; + + default: + ASSERT(pps->sliceGroupId); + for (i = 0; i < picSize; i++) + { + ASSERT(pps->sliceGroupId[i] < pps->numSliceGroups); + map[i] = pps->sliceGroupId[i]; + } + break; + } + +} + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_group_map.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_group_map.h new file mode 100755 index 0000000..4bcb6f2 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_group_map.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. Module defines + 3. Data types + 4. Function prototypes + +------------------------------------------------------------------------------*/ + +#ifndef H264SWDEC_SLICE_GROUP_MAP_H +#define H264SWDEC_SLICE_GROUP_MAP_H + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "basetype.h" +#include "h264bsd_pic_param_set.h" + +/*------------------------------------------------------------------------------ + 2. Module defines +------------------------------------------------------------------------------*/ + + +/*------------------------------------------------------------------------------ + 3. Data types +------------------------------------------------------------------------------*/ + + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ + +void h264bsdDecodeSliceGroupMap( + u32 *map, + picParamSet_t *pps, + u32 sliceGroupChangeCycle, + u32 picWidth, + u32 picHeight); + +#endif /* #ifdef H264SWDEC_SLICE_GROUP_MAP_H */ + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_header.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_header.c new file mode 100755 index 0000000..a7c6f64 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_header.c @@ -0,0 +1,1511 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. External compiler flags + 3. Module defines + 4. Local function prototypes + 5. Functions + h264bsdDecodeSliceHeader + NumSliceGroupChangeCycleBits + RefPicListReordering + DecRefPicMarking + CheckPpsId + CheckFrameNum + CheckIdrPicId + CheckPicOrderCntLsb + CheckDeltaPicOrderCntBottom + CheckDeltaPicOrderCnt + CheckRedundantPicCnt + +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "h264bsd_slice_header.h" +#include "h264bsd_util.h" +#include "h264bsd_vlc.h" +#include "h264bsd_nal_unit.h" +#include "h264bsd_dpb.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ + +static u32 RefPicListReordering(strmData_t *, refPicListReordering_t *, + u32, u32); + +static u32 NumSliceGroupChangeCycleBits(u32 picSizeInMbs, + u32 sliceGroupChangeRate); + +static u32 DecRefPicMarking(strmData_t *pStrmData, + decRefPicMarking_t *pDecRefPicMarking, nalUnitType_e nalUnitType, + u32 numRefFrames); + + +/*------------------------------------------------------------------------------ + + Function name: h264bsdDecodeSliceHeader + + Functional description: + Decode slice header data from the stream. + + Inputs: + pStrmData pointer to stream data structure + pSeqParamSet pointer to active sequence parameter set + pPicParamSet pointer to active picture parameter set + pNalUnit pointer to current NAL unit structure + + Outputs: + pSliceHeader decoded data is stored here + + Returns: + HANTRO_OK success + HANTRO_NOK invalid stream data or end of stream + +------------------------------------------------------------------------------*/ + +u32 h264bsdDecodeSliceHeader(strmData_t *pStrmData, sliceHeader_t *pSliceHeader, + seqParamSet_t *pSeqParamSet, picParamSet_t *pPicParamSet, + nalUnit_t *pNalUnit) +{ + +/* Variables */ + + u32 tmp, i, value; + i32 itmp; + u32 picSizeInMbs; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pSliceHeader); + ASSERT(pSeqParamSet); + ASSERT(pPicParamSet); + ASSERT( pNalUnit->nalUnitType == NAL_CODED_SLICE || + pNalUnit->nalUnitType == NAL_CODED_SLICE_IDR ); + + + H264SwDecMemset(pSliceHeader, 0, sizeof(sliceHeader_t)); + + picSizeInMbs = pSeqParamSet->picWidthInMbs * pSeqParamSet->picHeightInMbs; + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + pSliceHeader->firstMbInSlice = value; + if (value >= picSizeInMbs) + { + EPRINT("first_mb_in_slice"); + return(HANTRO_NOK); + } + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + pSliceHeader->sliceType = value; + /* slice type has to be either I or P slice. P slice is not allowed when + * current NAL unit is an IDR NAL unit or num_ref_frames is 0 */ + if ( !IS_I_SLICE(pSliceHeader->sliceType) && + ( !IS_P_SLICE(pSliceHeader->sliceType) || + IS_IDR_NAL_UNIT(pNalUnit) || + !pSeqParamSet->numRefFrames ) ) + { + EPRINT("slice_type"); + return(HANTRO_NOK); + } + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + pSliceHeader->picParameterSetId = value; + if (pSliceHeader->picParameterSetId != pPicParamSet->picParameterSetId) + { + EPRINT("pic_parameter_set_id"); + return(HANTRO_NOK); + } + + /* log2(maxFrameNum) -> num bits to represent frame_num */ + i = 0; + while (pSeqParamSet->maxFrameNum >> i) + i++; + i--; + + tmp = h264bsdGetBits(pStrmData, i); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + if (IS_IDR_NAL_UNIT(pNalUnit) && tmp != 0) + { + EPRINT("frame_num"); + return(HANTRO_NOK); + } + pSliceHeader->frameNum = tmp; + + if (IS_IDR_NAL_UNIT(pNalUnit)) + { + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + pSliceHeader->idrPicId = value; + if (value > 65535) + { + EPRINT("idr_pic_id"); + return(HANTRO_NOK); + } + } + + if (pSeqParamSet->picOrderCntType == 0) + { + /* log2(maxPicOrderCntLsb) -> num bits to represent pic_order_cnt_lsb */ + i = 0; + while (pSeqParamSet->maxPicOrderCntLsb >> i) + i++; + i--; + + tmp = h264bsdGetBits(pStrmData, i); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pSliceHeader->picOrderCntLsb = tmp; + + if (pPicParamSet->picOrderPresentFlag) + { + tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp); + if (tmp != HANTRO_OK) + return(tmp); + pSliceHeader->deltaPicOrderCntBottom = itmp; + } + + /* check that picOrderCnt for IDR picture will be zero. See + * DecodePicOrderCnt function to understand the logic here */ + if ( IS_IDR_NAL_UNIT(pNalUnit) && + ( (pSliceHeader->picOrderCntLsb > + pSeqParamSet->maxPicOrderCntLsb/2) || + MIN((i32)pSliceHeader->picOrderCntLsb, + (i32)pSliceHeader->picOrderCntLsb + + pSliceHeader->deltaPicOrderCntBottom) != 0 ) ) + { + return(HANTRO_NOK); + } + } + + if ( (pSeqParamSet->picOrderCntType == 1) && + !pSeqParamSet->deltaPicOrderAlwaysZeroFlag ) + { + tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp); + if (tmp != HANTRO_OK) + return(tmp); + pSliceHeader->deltaPicOrderCnt[0] = itmp; + + if (pPicParamSet->picOrderPresentFlag) + { + tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp); + if (tmp != HANTRO_OK) + return(tmp); + pSliceHeader->deltaPicOrderCnt[1] = itmp; + } + + /* check that picOrderCnt for IDR picture will be zero. See + * DecodePicOrderCnt function to understand the logic here */ + if ( IS_IDR_NAL_UNIT(pNalUnit) && + MIN(pSliceHeader->deltaPicOrderCnt[0], + pSliceHeader->deltaPicOrderCnt[0] + + pSeqParamSet->offsetForTopToBottomField + + pSliceHeader->deltaPicOrderCnt[1]) != 0) + { + return(HANTRO_NOK); + } + } + + if (pPicParamSet->redundantPicCntPresentFlag) + { + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + pSliceHeader->redundantPicCnt = value; + if (value > 127) + { + EPRINT("redundant_pic_cnt"); + return(HANTRO_NOK); + } + } + + if (IS_P_SLICE(pSliceHeader->sliceType)) + { + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pSliceHeader->numRefIdxActiveOverrideFlag = tmp; + + if (pSliceHeader->numRefIdxActiveOverrideFlag) + { + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + if (value > 15) + { + EPRINT("num_ref_idx_l0_active_minus1"); + return(HANTRO_NOK); + } + pSliceHeader->numRefIdxL0Active = value + 1; + } + /* set numRefIdxL0Active from pic param set */ + else + { + /* if value (minus1) in picture parameter set exceeds 15 it should + * have been overridden here */ + if (pPicParamSet->numRefIdxL0Active > 16) + { + EPRINT("num_ref_idx_active_override_flag"); + return(HANTRO_NOK); + } + pSliceHeader->numRefIdxL0Active = pPicParamSet->numRefIdxL0Active; + } + } + + if (IS_P_SLICE(pSliceHeader->sliceType)) + { + tmp = RefPicListReordering(pStrmData, + &pSliceHeader->refPicListReordering, + pSliceHeader->numRefIdxL0Active, + pSeqParamSet->maxFrameNum); + if (tmp != HANTRO_OK) + return(tmp); + } + + if (pNalUnit->nalRefIdc != 0) + { + tmp = DecRefPicMarking(pStrmData, &pSliceHeader->decRefPicMarking, + pNalUnit->nalUnitType, pSeqParamSet->numRefFrames); + if (tmp != HANTRO_OK) + return(tmp); + } + + /* decode sliceQpDelta and check that initial QP for the slice will be on + * the range [0, 51] */ + tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp); + if (tmp != HANTRO_OK) + return(tmp); + pSliceHeader->sliceQpDelta = itmp; + itmp += (i32)pPicParamSet->picInitQp; + if ( (itmp < 0) || (itmp > 51) ) + { + EPRINT("slice_qp_delta"); + return(HANTRO_NOK); + } + + if (pPicParamSet->deblockingFilterControlPresentFlag) + { + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + pSliceHeader->disableDeblockingFilterIdc = value; + if (pSliceHeader->disableDeblockingFilterIdc > 2) + { + EPRINT("disable_deblocking_filter_idc"); + return(HANTRO_NOK); + } + + if (pSliceHeader->disableDeblockingFilterIdc != 1) + { + tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp); + if (tmp != HANTRO_OK) + return(tmp); + if ( (itmp < -6) || (itmp > 6) ) + { + EPRINT("slice_alpha_c0_offset_div2"); + return(HANTRO_NOK); + } + pSliceHeader->sliceAlphaC0Offset = itmp * 2; + + tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp); + if (tmp != HANTRO_OK) + return(tmp); + if ( (itmp < -6) || (itmp > 6) ) + { + EPRINT("slice_beta_offset_div2"); + return(HANTRO_NOK); + } + pSliceHeader->sliceBetaOffset = itmp * 2; + } + } + + if ( (pPicParamSet->numSliceGroups > 1) && + (pPicParamSet->sliceGroupMapType >= 3) && + (pPicParamSet->sliceGroupMapType <= 5) ) + { + /* set tmp to number of bits used to represent slice_group_change_cycle + * in the stream */ + tmp = NumSliceGroupChangeCycleBits(picSizeInMbs, + pPicParamSet->sliceGroupChangeRate); + value = h264bsdGetBits(pStrmData, tmp); + if (value == END_OF_STREAM) + return(HANTRO_NOK); + pSliceHeader->sliceGroupChangeCycle = value; + + /* corresponds to tmp = Ceil(picSizeInMbs / sliceGroupChangeRate) */ + tmp = (picSizeInMbs + pPicParamSet->sliceGroupChangeRate - 1) / + pPicParamSet->sliceGroupChangeRate; + if (pSliceHeader->sliceGroupChangeCycle > tmp) + { + EPRINT("slice_group_change_cycle"); + return(HANTRO_NOK); + } + } + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: NumSliceGroupChangeCycleBits + + Functional description: + Determine number of bits needed to represent + slice_group_change_cycle in the stream. The standard states that + slice_group_change_cycle is represented by + Ceil( Log2( (picSizeInMbs / sliceGroupChangeRate) + 1) ) + + bits. Division "/" in the equation is non-truncating division. + + Inputs: + picSizeInMbs picture size in macroblocks + sliceGroupChangeRate + + Outputs: + none + + Returns: + number of bits needed + +------------------------------------------------------------------------------*/ + +u32 NumSliceGroupChangeCycleBits(u32 picSizeInMbs, u32 sliceGroupChangeRate) +{ + +/* Variables */ + + u32 tmp,numBits,mask; + +/* Code */ + + ASSERT(picSizeInMbs); + ASSERT(sliceGroupChangeRate); + ASSERT(sliceGroupChangeRate <= picSizeInMbs); + + /* compute (picSizeInMbs / sliceGroupChangeRate + 1), rounded up */ + if (picSizeInMbs % sliceGroupChangeRate) + tmp = 2 + picSizeInMbs/sliceGroupChangeRate; + else + tmp = 1 + picSizeInMbs/sliceGroupChangeRate; + + numBits = 0; + mask = ~0U; + + /* set numBits to position of right-most non-zero bit */ + while (tmp & (mask<<++numBits)) + ; + numBits--; + + /* add one more bit if value greater than 2^numBits */ + if (tmp & ((1<<numBits)-1)) + numBits++; + + return(numBits); + +} + +/*------------------------------------------------------------------------------ + + Function: RefPicListReordering + + Functional description: + Decode reference picture list reordering syntax elements from + the stream. Max number of reordering commands is numRefIdxActive. + + Inputs: + pStrmData pointer to stream data structure + numRefIdxActive number of active reference indices to be used for + current slice + maxPicNum maxFrameNum from the active SPS + + Outputs: + pRefPicListReordering decoded data is stored here + + Returns: + HANTRO_OK success + HANTRO_NOK invalid stream data + +------------------------------------------------------------------------------*/ + +u32 RefPicListReordering(strmData_t *pStrmData, + refPicListReordering_t *pRefPicListReordering, u32 numRefIdxActive, + u32 maxPicNum) +{ + +/* Variables */ + + u32 tmp, value, i; + u32 command; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pRefPicListReordering); + ASSERT(numRefIdxActive); + ASSERT(maxPicNum); + + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + + pRefPicListReordering->refPicListReorderingFlagL0 = tmp; + + if (pRefPicListReordering->refPicListReorderingFlagL0) + { + i = 0; + + do + { + if (i > numRefIdxActive) + { + EPRINT("Too many reordering commands"); + return(HANTRO_NOK); + } + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &command); + if (tmp != HANTRO_OK) + return(tmp); + if (command > 3) + { + EPRINT("reordering_of_pic_nums_idc"); + return(HANTRO_NOK); + } + + pRefPicListReordering->command[i].reorderingOfPicNumsIdc = command; + + if ((command == 0) || (command == 1)) + { + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + if (value >= maxPicNum) + { + EPRINT("abs_diff_pic_num_minus1"); + return(HANTRO_NOK); + } + pRefPicListReordering->command[i].absDiffPicNum = value + 1; + } + else if (command == 2) + { + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + pRefPicListReordering->command[i].longTermPicNum = value; + } + i++; + } while (command != 3); + + /* there shall be at least one reordering command if + * refPicListReorderingFlagL0 was set */ + if (i == 1) + { + EPRINT("ref_pic_list_reordering"); + return(HANTRO_NOK); + } + } + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: DecRefPicMarking + + Functional description: + Decode decoded reference picture marking syntax elements from + the stream. + + Inputs: + pStrmData pointer to stream data structure + nalUnitType type of the current NAL unit + numRefFrames max number of reference frames from the active SPS + + Outputs: + pDecRefPicMarking decoded data is stored here + + Returns: + HANTRO_OK success + HANTRO_NOK invalid stream data + +------------------------------------------------------------------------------*/ + +u32 DecRefPicMarking(strmData_t *pStrmData, + decRefPicMarking_t *pDecRefPicMarking, nalUnitType_e nalUnitType, + u32 numRefFrames) +{ + +/* Variables */ + + u32 tmp, value; + u32 i; + u32 operation; + /* variables for error checking purposes, store number of memory + * management operations of certain type */ + u32 num4 = 0, num5 = 0, num6 = 0, num1to3 = 0; + +/* Code */ + + ASSERT( nalUnitType == NAL_CODED_SLICE_IDR || + nalUnitType == NAL_CODED_SLICE || + nalUnitType == NAL_SEI ); + + + if (nalUnitType == NAL_CODED_SLICE_IDR) + { + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pDecRefPicMarking->noOutputOfPriorPicsFlag = tmp; + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pDecRefPicMarking->longTermReferenceFlag = tmp; + if (!numRefFrames && pDecRefPicMarking->longTermReferenceFlag) + { + EPRINT("long_term_reference_flag"); + return(HANTRO_NOK); + } + } + else + { + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pDecRefPicMarking->adaptiveRefPicMarkingModeFlag = tmp; + if (pDecRefPicMarking->adaptiveRefPicMarkingModeFlag) + { + i = 0; + do + { + /* see explanation of the MAX_NUM_MMC_OPERATIONS in + * slice_header.h */ + if (i > (2 * numRefFrames + 2)) + { + EPRINT("Too many management operations"); + return(HANTRO_NOK); + } + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &operation); + if (tmp != HANTRO_OK) + return(tmp); + if (operation > 6) + { + EPRINT("memory_management_control_operation"); + return(HANTRO_NOK); + } + + pDecRefPicMarking->operation[i]. + memoryManagementControlOperation = operation; + if ((operation == 1) || (operation == 3)) + { + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + pDecRefPicMarking->operation[i].differenceOfPicNums = + value + 1; + } + if (operation == 2) + { + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + pDecRefPicMarking->operation[i].longTermPicNum = value; + } + if ((operation == 3) || (operation == 6)) + { + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + pDecRefPicMarking->operation[i].longTermFrameIdx = + value; + } + if (operation == 4) + { + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + /* value shall be in range [0, numRefFrames] */ + if (value > numRefFrames) + { + EPRINT("max_long_term_frame_idx_plus1"); + return(HANTRO_NOK); + } + if (value == 0) + { + pDecRefPicMarking->operation[i]. + maxLongTermFrameIdx = + NO_LONG_TERM_FRAME_INDICES; + } + else + { + pDecRefPicMarking->operation[i]. + maxLongTermFrameIdx = value - 1; + } + num4++; + } + if (operation == 5) + { + num5++; + } + if (operation && operation <= 3) + num1to3++; + if (operation == 6) + num6++; + + i++; + } while (operation != 0); + + /* error checking */ + if (num4 > 1 || num5 > 1 || num6 > 1 || (num1to3 && num5)) + return(HANTRO_NOK); + + } + } + + return(HANTRO_OK); +} + +/*------------------------------------------------------------------------------ + + Function name: h264bsdCheckPpsId + + Functional description: + Peek value of pic_parameter_set_id from the slice header. Function + does not modify current stream positions but copies the stream + data structure to tmp structure which is used while accessing + stream data. + + Inputs: + pStrmData pointer to stream data structure + + Outputs: + picParamSetId value is stored here + + Returns: + HANTRO_OK success + HANTRO_NOK invalid stream data + +------------------------------------------------------------------------------*/ + +u32 h264bsdCheckPpsId(strmData_t *pStrmData, u32 *picParamSetId) +{ + +/* Variables */ + + u32 tmp, value; + strmData_t tmpStrmData[1]; + +/* Code */ + + ASSERT(pStrmData); + + /* don't touch original stream position params */ + *tmpStrmData = *pStrmData; + + /* first_mb_in_slice */ + tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + + /* slice_type */ + tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + + tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + if (value >= MAX_NUM_PIC_PARAM_SETS) + return(HANTRO_NOK); + + *picParamSetId = value; + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdCheckFrameNum + + Functional description: + Peek value of frame_num from the slice header. Function does not + modify current stream positions but copies the stream data + structure to tmp structure which is used while accessing stream + data. + + Inputs: + pStrmData pointer to stream data structure + maxFrameNum + + Outputs: + frameNum value is stored here + + Returns: + HANTRO_OK success + HANTRO_NOK invalid stream data + +------------------------------------------------------------------------------*/ + +u32 h264bsdCheckFrameNum( + strmData_t *pStrmData, + u32 maxFrameNum, + u32 *frameNum) +{ + +/* Variables */ + + u32 tmp, value, i; + strmData_t tmpStrmData[1]; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(maxFrameNum); + ASSERT(frameNum); + + /* don't touch original stream position params */ + *tmpStrmData = *pStrmData; + + /* skip first_mb_in_slice */ + tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + + /* skip slice_type */ + tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + + /* skip pic_parameter_set_id */ + tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + + /* log2(maxFrameNum) -> num bits to represent frame_num */ + i = 0; + while (maxFrameNum >> i) + i++; + i--; + + /* frame_num */ + tmp = h264bsdGetBits(tmpStrmData, i); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + *frameNum = tmp; + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdCheckIdrPicId + + Functional description: + Peek value of idr_pic_id from the slice header. Function does not + modify current stream positions but copies the stream data + structure to tmp structure which is used while accessing stream + data. + + Inputs: + pStrmData pointer to stream data structure + maxFrameNum max frame number from active SPS + nalUnitType type of the current NAL unit + + Outputs: + idrPicId value is stored here + + Returns: + HANTRO_OK success + HANTRO_NOK invalid stream data + +------------------------------------------------------------------------------*/ + +u32 h264bsdCheckIdrPicId( + strmData_t *pStrmData, + u32 maxFrameNum, + nalUnitType_e nalUnitType, + u32 *idrPicId) +{ + +/* Variables */ + + u32 tmp, value, i; + strmData_t tmpStrmData[1]; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(maxFrameNum); + ASSERT(idrPicId); + + /* nalUnitType must be equal to 5 because otherwise idrPicId is not + * present */ + if (nalUnitType != NAL_CODED_SLICE_IDR) + return(HANTRO_NOK); + + /* don't touch original stream position params */ + *tmpStrmData = *pStrmData; + + /* skip first_mb_in_slice */ + tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + + /* skip slice_type */ + tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + + /* skip pic_parameter_set_id */ + tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + + /* log2(maxFrameNum) -> num bits to represent frame_num */ + i = 0; + while (maxFrameNum >> i) + i++; + i--; + + /* skip frame_num */ + tmp = h264bsdGetBits(tmpStrmData, i); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + + /* idr_pic_id */ + tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, idrPicId); + if (tmp != HANTRO_OK) + return(tmp); + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdCheckPicOrderCntLsb + + Functional description: + Peek value of pic_order_cnt_lsb from the slice header. Function + does not modify current stream positions but copies the stream + data structure to tmp structure which is used while accessing + stream data. + + Inputs: + pStrmData pointer to stream data structure + pSeqParamSet pointer to active SPS + nalUnitType type of the current NAL unit + + Outputs: + picOrderCntLsb value is stored here + + Returns: + HANTRO_OK success + HANTRO_NOK invalid stream data + +------------------------------------------------------------------------------*/ + +u32 h264bsdCheckPicOrderCntLsb( + strmData_t *pStrmData, + seqParamSet_t *pSeqParamSet, + nalUnitType_e nalUnitType, + u32 *picOrderCntLsb) +{ + +/* Variables */ + + u32 tmp, value, i; + strmData_t tmpStrmData[1]; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pSeqParamSet); + ASSERT(picOrderCntLsb); + + /* picOrderCntType must be equal to 0 */ + ASSERT(pSeqParamSet->picOrderCntType == 0); + ASSERT(pSeqParamSet->maxFrameNum); + ASSERT(pSeqParamSet->maxPicOrderCntLsb); + + /* don't touch original stream position params */ + *tmpStrmData = *pStrmData; + + /* skip first_mb_in_slice */ + tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + + /* skip slice_type */ + tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + + /* skip pic_parameter_set_id */ + tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + + /* log2(maxFrameNum) -> num bits to represent frame_num */ + i = 0; + while (pSeqParamSet->maxFrameNum >> i) + i++; + i--; + + /* skip frame_num */ + tmp = h264bsdGetBits(tmpStrmData, i); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + + /* skip idr_pic_id when necessary */ + if (nalUnitType == NAL_CODED_SLICE_IDR) + { + tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + } + + /* log2(maxPicOrderCntLsb) -> num bits to represent pic_order_cnt_lsb */ + i = 0; + while (pSeqParamSet->maxPicOrderCntLsb >> i) + i++; + i--; + + /* pic_order_cnt_lsb */ + tmp = h264bsdGetBits(tmpStrmData, i); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + *picOrderCntLsb = tmp; + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdCheckDeltaPicOrderCntBottom + + Functional description: + Peek value of delta_pic_order_cnt_bottom from the slice header. + Function does not modify current stream positions but copies the + stream data structure to tmp structure which is used while + accessing stream data. + + Inputs: + pStrmData pointer to stream data structure + pSeqParamSet pointer to active SPS + nalUnitType type of the current NAL unit + + Outputs: + deltaPicOrderCntBottom value is stored here + + Returns: + HANTRO_OK success + HANTRO_NOK invalid stream data + +------------------------------------------------------------------------------*/ + +u32 h264bsdCheckDeltaPicOrderCntBottom( + strmData_t *pStrmData, + seqParamSet_t *pSeqParamSet, + nalUnitType_e nalUnitType, + i32 *deltaPicOrderCntBottom) +{ + +/* Variables */ + + u32 tmp, value, i; + strmData_t tmpStrmData[1]; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pSeqParamSet); + ASSERT(deltaPicOrderCntBottom); + + /* picOrderCntType must be equal to 0 and picOrderPresentFlag must be TRUE + * */ + ASSERT(pSeqParamSet->picOrderCntType == 0); + ASSERT(pSeqParamSet->maxFrameNum); + ASSERT(pSeqParamSet->maxPicOrderCntLsb); + + /* don't touch original stream position params */ + *tmpStrmData = *pStrmData; + + /* skip first_mb_in_slice */ + tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + + /* skip slice_type */ + tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + + /* skip pic_parameter_set_id */ + tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + + /* log2(maxFrameNum) -> num bits to represent frame_num */ + i = 0; + while (pSeqParamSet->maxFrameNum >> i) + i++; + i--; + + /* skip frame_num */ + tmp = h264bsdGetBits(tmpStrmData, i); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + + /* skip idr_pic_id when necessary */ + if (nalUnitType == NAL_CODED_SLICE_IDR) + { + tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + } + + /* log2(maxPicOrderCntLsb) -> num bits to represent pic_order_cnt_lsb */ + i = 0; + while (pSeqParamSet->maxPicOrderCntLsb >> i) + i++; + i--; + + /* skip pic_order_cnt_lsb */ + tmp = h264bsdGetBits(tmpStrmData, i); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + + /* delta_pic_order_cnt_bottom */ + tmp = h264bsdDecodeExpGolombSigned(tmpStrmData, deltaPicOrderCntBottom); + if (tmp != HANTRO_OK) + return(tmp); + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdCheckDeltaPicOrderCnt + + Functional description: + Peek values delta_pic_order_cnt[0] and delta_pic_order_cnt[1] + from the slice header. Function does not modify current stream + positions but copies the stream data structure to tmp structure + which is used while accessing stream data. + + Inputs: + pStrmData pointer to stream data structure + pSeqParamSet pointer to active SPS + nalUnitType type of the current NAL unit + picOrderPresentFlag flag indicating if delta_pic_order_cnt[1] + is present in the stream + + Outputs: + deltaPicOrderCnt values are stored here + + Returns: + HANTRO_OK success + HANTRO_NOK invalid stream data + +------------------------------------------------------------------------------*/ + +u32 h264bsdCheckDeltaPicOrderCnt( + strmData_t *pStrmData, + seqParamSet_t *pSeqParamSet, + nalUnitType_e nalUnitType, + u32 picOrderPresentFlag, + i32 *deltaPicOrderCnt) +{ + +/* Variables */ + + u32 tmp, value, i; + strmData_t tmpStrmData[1]; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pSeqParamSet); + ASSERT(deltaPicOrderCnt); + + /* picOrderCntType must be equal to 1 and deltaPicOrderAlwaysZeroFlag must + * be FALSE */ + ASSERT(pSeqParamSet->picOrderCntType == 1); + ASSERT(!pSeqParamSet->deltaPicOrderAlwaysZeroFlag); + ASSERT(pSeqParamSet->maxFrameNum); + + /* don't touch original stream position params */ + *tmpStrmData = *pStrmData; + + /* skip first_mb_in_slice */ + tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + + /* skip slice_type */ + tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + + /* skip pic_parameter_set_id */ + tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + + /* log2(maxFrameNum) -> num bits to represent frame_num */ + i = 0; + while (pSeqParamSet->maxFrameNum >> i) + i++; + i--; + + /* skip frame_num */ + tmp = h264bsdGetBits(tmpStrmData, i); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + + /* skip idr_pic_id when necessary */ + if (nalUnitType == NAL_CODED_SLICE_IDR) + { + tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + } + + /* delta_pic_order_cnt[0] */ + tmp = h264bsdDecodeExpGolombSigned(tmpStrmData, &deltaPicOrderCnt[0]); + if (tmp != HANTRO_OK) + return(tmp); + + /* delta_pic_order_cnt[1] if present */ + if (picOrderPresentFlag) + { + tmp = h264bsdDecodeExpGolombSigned(tmpStrmData, &deltaPicOrderCnt[1]); + if (tmp != HANTRO_OK) + return(tmp); + } + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdCheckRedundantPicCnt + + Functional description: + Peek value of redundant_pic_cnt from the slice header. Function + does not modify current stream positions but copies the stream + data structure to tmp structure which is used while accessing + stream data. + + Inputs: + pStrmData pointer to stream data structure + pSeqParamSet pointer to active SPS + pPicParamSet pointer to active PPS + nalUnitType type of the current NAL unit + + Outputs: + redundantPicCnt value is stored here + + Returns: + HANTRO_OK success + HANTRO_NOK invalid stream data + +------------------------------------------------------------------------------*/ + +u32 h264bsdCheckRedundantPicCnt( + strmData_t *pStrmData, + seqParamSet_t *pSeqParamSet, + picParamSet_t *pPicParamSet, + nalUnitType_e nalUnitType, + u32 *redundantPicCnt) +{ + +/* Variables */ + + u32 tmp, value, i; + i32 ivalue; + strmData_t tmpStrmData[1]; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pSeqParamSet); + ASSERT(pPicParamSet); + ASSERT(redundantPicCnt); + + /* redundant_pic_cnt_flag must be TRUE */ + ASSERT(pPicParamSet->redundantPicCntPresentFlag); + ASSERT(pSeqParamSet->maxFrameNum); + ASSERT(pSeqParamSet->picOrderCntType > 0 || + pSeqParamSet->maxPicOrderCntLsb); + + /* don't touch original stream position params */ + *tmpStrmData = *pStrmData; + + /* skip first_mb_in_slice */ + tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + + /* skip slice_type */ + tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + + /* skip pic_parameter_set_id */ + tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + + /* log2(maxFrameNum) -> num bits to represent frame_num */ + i = 0; + while (pSeqParamSet->maxFrameNum >> i) + i++; + i--; + + /* skip frame_num */ + tmp = h264bsdGetBits(tmpStrmData, i); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + + /* skip idr_pic_id when necessary */ + if (nalUnitType == NAL_CODED_SLICE_IDR) + { + tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); + if (tmp != HANTRO_OK) + return(tmp); + } + + if (pSeqParamSet->picOrderCntType == 0) + { + /* log2(maxPicOrderCntLsb) -> num bits to represent pic_order_cnt_lsb */ + i = 0; + while (pSeqParamSet->maxPicOrderCntLsb >> i) + i++; + i--; + + /* pic_order_cnt_lsb */ + tmp = h264bsdGetBits(tmpStrmData, i); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + + if (pPicParamSet->picOrderPresentFlag) + { + /* skip delta_pic_order_cnt_bottom */ + tmp = h264bsdDecodeExpGolombSigned(tmpStrmData, &ivalue); + if (tmp != HANTRO_OK) + return(tmp); + } + } + + if (pSeqParamSet->picOrderCntType == 1 && + !pSeqParamSet->deltaPicOrderAlwaysZeroFlag) + { + /* delta_pic_order_cnt[0] */ + tmp = h264bsdDecodeExpGolombSigned(tmpStrmData, &ivalue); + if (tmp != HANTRO_OK) + return(tmp); + + /* delta_pic_order_cnt[1] if present */ + if (pPicParamSet->picOrderPresentFlag) + { + tmp = h264bsdDecodeExpGolombSigned(tmpStrmData, &ivalue); + if (tmp != HANTRO_OK) + return(tmp); + } + } + + /* redundant_pic_cnt */ + tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, redundantPicCnt); + if (tmp != HANTRO_OK) + return(tmp); + + return(HANTRO_OK); + +} + + +/*------------------------------------------------------------------------------ + + Function: h264bsdCheckPriorPicsFlag + + Functional description: + Peek value of no_output_of_prior_pics_flag from the slice header. + Function does not modify current stream positions but copies + the stream data structure to tmp structure which is used while + accessing stream data. + + Inputs: + pStrmData pointer to stream data structure + pSeqParamSet pointer to active SPS + pPicParamSet pointer to active PPS + nalUnitType type of the current NAL unit + + Outputs: + noOutputOfPriorPicsFlag value is stored here + + Returns: + HANTRO_OK success + HANTRO_NOK invalid stream data + +------------------------------------------------------------------------------*/ +/*lint -e715 disable lint info nalUnitType not referenced */ +u32 h264bsdCheckPriorPicsFlag(u32 * noOutputOfPriorPicsFlag, + const strmData_t * pStrmData, + const seqParamSet_t * pSeqParamSet, + const picParamSet_t * pPicParamSet, + nalUnitType_e nalUnitType) +{ +/* Variables */ + + u32 tmp, value, i; + i32 ivalue; + strmData_t tmpStrmData[1]; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pSeqParamSet); + ASSERT(pPicParamSet); + ASSERT(noOutputOfPriorPicsFlag); + + /* must be IDR lsice */ + ASSERT(nalUnitType == NAL_CODED_SLICE_IDR); + + /* don't touch original stream position params */ + *tmpStrmData = *pStrmData; + + /* skip first_mb_in_slice */ + tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); + if(tmp != HANTRO_OK) + return (tmp); + + /* slice_type */ + tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); + if(tmp != HANTRO_OK) + return (tmp); + + /* skip pic_parameter_set_id */ + tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); + if(tmp != HANTRO_OK) + return (tmp); + + /* log2(maxFrameNum) -> num bits to represent frame_num */ + i = 0; + while(pSeqParamSet->maxFrameNum >> i) + i++; + i--; + + /* skip frame_num */ + tmp = h264bsdGetBits(tmpStrmData, i); + if(tmp == END_OF_STREAM) + return (HANTRO_NOK); + + /* skip idr_pic_id */ + tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); + if(tmp != HANTRO_OK) + return (tmp); + + if(pSeqParamSet->picOrderCntType == 0) + { + /* log2(maxPicOrderCntLsb) -> num bits to represent pic_order_cnt_lsb */ + i = 0; + while(pSeqParamSet->maxPicOrderCntLsb >> i) + i++; + i--; + + /* skip pic_order_cnt_lsb */ + tmp = h264bsdGetBits(tmpStrmData, i); + if(tmp == END_OF_STREAM) + return (HANTRO_NOK); + + if(pPicParamSet->picOrderPresentFlag) + { + /* skip delta_pic_order_cnt_bottom */ + tmp = h264bsdDecodeExpGolombSigned(tmpStrmData, &ivalue); + if(tmp != HANTRO_OK) + return (tmp); + } + } + + if(pSeqParamSet->picOrderCntType == 1 && + !pSeqParamSet->deltaPicOrderAlwaysZeroFlag) + { + /* skip delta_pic_order_cnt[0] */ + tmp = h264bsdDecodeExpGolombSigned(tmpStrmData, &ivalue); + if(tmp != HANTRO_OK) + return (tmp); + + /* skip delta_pic_order_cnt[1] if present */ + if(pPicParamSet->picOrderPresentFlag) + { + tmp = h264bsdDecodeExpGolombSigned(tmpStrmData, &ivalue); + if(tmp != HANTRO_OK) + return (tmp); + } + } + + /* skip redundant_pic_cnt */ + if(pPicParamSet->redundantPicCntPresentFlag) + { + tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); + if(tmp != HANTRO_OK) + return (tmp); + } + + *noOutputOfPriorPicsFlag = h264bsdGetBits(tmpStrmData, 1); + if(*noOutputOfPriorPicsFlag == END_OF_STREAM) + return (HANTRO_NOK); + + return (HANTRO_OK); + +} +/*lint +e715 */ + + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_header.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_header.h new file mode 100755 index 0000000..198898a --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_header.h @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. Module defines + 3. Data types + 4. Function prototypes + +------------------------------------------------------------------------------*/ + +#ifndef H264SWDEC_SLICE_HEADER_H +#define H264SWDEC_SLICE_HEADER_H + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "basetype.h" +#include "h264bsd_stream.h" +#include "h264bsd_cfg.h" +#include "h264bsd_seq_param_set.h" +#include "h264bsd_pic_param_set.h" +#include "h264bsd_nal_unit.h" + +/*------------------------------------------------------------------------------ + 2. Module defines +------------------------------------------------------------------------------*/ + +enum { + P_SLICE = 0, + I_SLICE = 2 +}; + +enum {NO_LONG_TERM_FRAME_INDICES = 0xFFFF}; + +/* macro to determine if slice is an inter slice, sliceTypes 0 and 5 */ +#define IS_P_SLICE(sliceType) (((sliceType) == P_SLICE) || \ + ((sliceType) == P_SLICE + 5)) + +/* macro to determine if slice is an intra slice, sliceTypes 2 and 7 */ +#define IS_I_SLICE(sliceType) (((sliceType) == I_SLICE) || \ + ((sliceType) == I_SLICE + 5)) + +/*------------------------------------------------------------------------------ + 3. Data types +------------------------------------------------------------------------------*/ + +/* structure to store data of one reference picture list reordering operation */ +typedef struct +{ + u32 reorderingOfPicNumsIdc; + u32 absDiffPicNum; + u32 longTermPicNum; +} refPicListReorderingOperation_t; + +/* structure to store reference picture list reordering operations */ +typedef struct +{ + u32 refPicListReorderingFlagL0; + refPicListReorderingOperation_t command[MAX_NUM_REF_PICS+1]; +} refPicListReordering_t; + +/* structure to store data of one DPB memory management control operation */ +typedef struct +{ + u32 memoryManagementControlOperation; + u32 differenceOfPicNums; + u32 longTermPicNum; + u32 longTermFrameIdx; + u32 maxLongTermFrameIdx; +} memoryManagementOperation_t; + +/* worst case scenario: all MAX_NUM_REF_PICS pictures in the buffer are + * short term pictures, each one of them is first marked as long term + * reference picture which is then marked as unused for reference. + * Additionally, max long-term frame index is set and current picture is + * marked as long term reference picture. Last position reserved for + * end memory_management_control_operation command */ +#define MAX_NUM_MMC_OPERATIONS (2*MAX_NUM_REF_PICS+2+1) + +/* structure to store decoded reference picture marking data */ +typedef struct +{ + u32 noOutputOfPriorPicsFlag; + u32 longTermReferenceFlag; + u32 adaptiveRefPicMarkingModeFlag; + memoryManagementOperation_t operation[MAX_NUM_MMC_OPERATIONS]; +} decRefPicMarking_t; + +/* structure to store slice header data decoded from the stream */ +typedef struct +{ + u32 firstMbInSlice; + u32 sliceType; + u32 picParameterSetId; + u32 frameNum; + u32 idrPicId; + u32 picOrderCntLsb; + i32 deltaPicOrderCntBottom; + i32 deltaPicOrderCnt[2]; + u32 redundantPicCnt; + u32 numRefIdxActiveOverrideFlag; + u32 numRefIdxL0Active; + i32 sliceQpDelta; + u32 disableDeblockingFilterIdc; + i32 sliceAlphaC0Offset; + i32 sliceBetaOffset; + u32 sliceGroupChangeCycle; + refPicListReordering_t refPicListReordering; + decRefPicMarking_t decRefPicMarking; +} sliceHeader_t; + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ + +u32 h264bsdDecodeSliceHeader(strmData_t *pStrmData, + sliceHeader_t *pSliceHeader, + seqParamSet_t *pSeqParamSet, + picParamSet_t *pPicParamSet, + nalUnit_t *pNalUnit); + +u32 h264bsdCheckPpsId(strmData_t *pStrmData, u32 *ppsId); + +u32 h264bsdCheckFrameNum( + strmData_t *pStrmData, + u32 maxFrameNum, + u32 *frameNum); + +u32 h264bsdCheckIdrPicId( + strmData_t *pStrmData, + u32 maxFrameNum, + nalUnitType_e nalUnitType, + u32 *idrPicId); + +u32 h264bsdCheckPicOrderCntLsb( + strmData_t *pStrmData, + seqParamSet_t *pSeqParamSet, + nalUnitType_e nalUnitType, + u32 *picOrderCntLsb); + +u32 h264bsdCheckDeltaPicOrderCntBottom( + strmData_t *pStrmData, + seqParamSet_t *pSeqParamSet, + nalUnitType_e nalUnitType, + i32 *deltaPicOrderCntBottom); + +u32 h264bsdCheckDeltaPicOrderCnt( + strmData_t *pStrmData, + seqParamSet_t *pSeqParamSet, + nalUnitType_e nalUnitType, + u32 picOrderPresentFlag, + i32 *deltaPicOrderCnt); + +u32 h264bsdCheckRedundantPicCnt( + strmData_t *pStrmData, + seqParamSet_t *pSeqParamSet, + picParamSet_t *pPicParamSet, + nalUnitType_e nalUnitType, + u32 *redundantPicCnt); + +u32 h264bsdCheckPriorPicsFlag(u32 * noOutputOfPriorPicsFlag, + const strmData_t * pStrmData, + const seqParamSet_t * pSeqParamSet, + const picParamSet_t * pPicParamSet, + nalUnitType_e nalUnitType); + +#endif /* #ifdef H264SWDEC_SLICE_HEADER_H */ + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_storage.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_storage.c new file mode 100755 index 0000000..3234754 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_storage.c @@ -0,0 +1,888 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. External compiler flags + 3. Module defines + 4. Local function prototypes + 5. Functions + h264bsdInitStorage + h264bsdStoreSeqParamSet + h264bsdStorePicParamSet + h264bsdActivateParamSets + h264bsdResetStorage + h264bsdIsStartOfPicture + h264bsdIsEndOfPicture + h264bsdComputeSliceGroupMap + h264bsdCheckAccessUnitBoundary + CheckPps + h264bsdValidParamSets + +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "h264bsd_storage.h" +#include "h264bsd_util.h" +#include "h264bsd_neighbour.h" +#include "h264bsd_slice_group_map.h" +#include "h264bsd_dpb.h" +#include "h264bsd_nal_unit.h" +#include "h264bsd_slice_header.h" +#include "h264bsd_seq_param_set.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ + +static u32 CheckPps(picParamSet_t *pps, seqParamSet_t *sps); + +/*------------------------------------------------------------------------------ + + Function name: h264bsdInitStorage + + Functional description: + Initialize storage structure. Sets contents of the storage to '0' + except for the active parameter set ids, which are initialized + to invalid values. + + Inputs: + + Outputs: + pStorage initialized data stored here + + Returns: + none + +------------------------------------------------------------------------------*/ + +void h264bsdInitStorage(storage_t *pStorage) +{ + +/* Variables */ + +/* Code */ + + ASSERT(pStorage); + + H264SwDecMemset(pStorage, 0, sizeof(storage_t)); + + pStorage->activeSpsId = MAX_NUM_SEQ_PARAM_SETS; + pStorage->activePpsId = MAX_NUM_PIC_PARAM_SETS; + + pStorage->aub->firstCallFlag = HANTRO_TRUE; +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdStoreSeqParamSet + + Functional description: + Store sequence parameter set into the storage. If active SPS is + overwritten -> check if contents changes and if it does, set + parameters to force reactivation of parameter sets + + Inputs: + pStorage pointer to storage structure + pSeqParamSet pointer to param set to be stored + + Outputs: + none + + Returns: + HANTRO_OK success + MEMORY_ALLOCATION_ERROR failure in memory allocation + + +------------------------------------------------------------------------------*/ + +u32 h264bsdStoreSeqParamSet(storage_t *pStorage, seqParamSet_t *pSeqParamSet) +{ + +/* Variables */ + + u32 id; + +/* Code */ + + ASSERT(pStorage); + ASSERT(pSeqParamSet); + ASSERT(pSeqParamSet->seqParameterSetId < MAX_NUM_SEQ_PARAM_SETS); + + id = pSeqParamSet->seqParameterSetId; + + /* seq parameter set with id not used before -> allocate memory */ + if (pStorage->sps[id] == NULL) + { + ALLOCATE(pStorage->sps[id], 1, seqParamSet_t); + if (pStorage->sps[id] == NULL) + return(MEMORY_ALLOCATION_ERROR); + } + /* sequence parameter set with id equal to id of active sps */ + else if (id == pStorage->activeSpsId) + { + /* if seq parameter set contents changes + * -> overwrite and re-activate when next IDR picture decoded + * ids of active param sets set to invalid values to force + * re-activation. Memories allocated for old sps freed + * otherwise free memeries allocated for just decoded sps and + * continue */ + if (h264bsdCompareSeqParamSets(pSeqParamSet, pStorage->activeSps) != 0) + { + FREE(pStorage->sps[id]->offsetForRefFrame); + FREE(pStorage->sps[id]->vuiParameters); + pStorage->activeSpsId = MAX_NUM_SEQ_PARAM_SETS + 1; + pStorage->activePpsId = MAX_NUM_PIC_PARAM_SETS + 1; + pStorage->activeSps = NULL; + pStorage->activePps = NULL; + } + else + { + FREE(pSeqParamSet->offsetForRefFrame); + FREE(pSeqParamSet->vuiParameters); + return(HANTRO_OK); + } + } + /* overwrite seq param set other than active one -> free memories + * allocated for old param set */ + else + { + FREE(pStorage->sps[id]->offsetForRefFrame); + FREE(pStorage->sps[id]->vuiParameters); + } + + *pStorage->sps[id] = *pSeqParamSet; + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdStorePicParamSet + + Functional description: + Store picture parameter set into the storage. If active PPS is + overwritten -> check if active SPS changes and if it does -> set + parameters to force reactivation of parameter sets + + Inputs: + pStorage pointer to storage structure + pPicParamSet pointer to param set to be stored + + Outputs: + none + + Returns: + HANTRO_OK success + MEMORY_ALLOCATION_ERROR failure in memory allocation + +------------------------------------------------------------------------------*/ + +u32 h264bsdStorePicParamSet(storage_t *pStorage, picParamSet_t *pPicParamSet) +{ + +/* Variables */ + + u32 id; + +/* Code */ + + ASSERT(pStorage); + ASSERT(pPicParamSet); + ASSERT(pPicParamSet->picParameterSetId < MAX_NUM_PIC_PARAM_SETS); + ASSERT(pPicParamSet->seqParameterSetId < MAX_NUM_SEQ_PARAM_SETS); + + id = pPicParamSet->picParameterSetId; + + /* pic parameter set with id not used before -> allocate memory */ + if (pStorage->pps[id] == NULL) + { + ALLOCATE(pStorage->pps[id], 1, picParamSet_t); + if (pStorage->pps[id] == NULL) + return(MEMORY_ALLOCATION_ERROR); + } + /* picture parameter set with id equal to id of active pps */ + else if (id == pStorage->activePpsId) + { + /* check whether seq param set changes, force re-activation of + * param set if it does. Set activeSpsId to invalid value to + * accomplish this */ + if (pPicParamSet->seqParameterSetId != pStorage->activeSpsId) + { + pStorage->activePpsId = MAX_NUM_PIC_PARAM_SETS + 1; + } + /* free memories allocated for old param set */ + FREE(pStorage->pps[id]->runLength); + FREE(pStorage->pps[id]->topLeft); + FREE(pStorage->pps[id]->bottomRight); + FREE(pStorage->pps[id]->sliceGroupId); + } + /* overwrite pic param set other than active one -> free memories + * allocated for old param set */ + else + { + FREE(pStorage->pps[id]->runLength); + FREE(pStorage->pps[id]->topLeft); + FREE(pStorage->pps[id]->bottomRight); + FREE(pStorage->pps[id]->sliceGroupId); + } + + *pStorage->pps[id] = *pPicParamSet; + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdActivateParamSets + + Functional description: + Activate certain SPS/PPS combination. This function shall be + called in the beginning of each picture. Picture parameter set + can be changed as wanted, but sequence parameter set may only be + changed when the starting picture is an IDR picture. + + When new SPS is activated the function allocates memory for + macroblock storages and slice group map and (re-)initializes the + decoded picture buffer. If this is not the first activation the old + allocations are freed and FreeDpb called before new allocations. + + Inputs: + pStorage pointer to storage data structure + ppsId identifies the PPS to be activated, SPS id obtained + from the PPS + isIdr flag to indicate if the picture is an IDR picture + + Outputs: + none + + Returns: + HANTRO_OK success + HANTRO_NOK non-existing or invalid param set combination, + trying to change SPS with non-IDR picture + MEMORY_ALLOCATION_ERROR failure in memory allocation + +------------------------------------------------------------------------------*/ + +u32 h264bsdActivateParamSets(storage_t *pStorage, u32 ppsId, u32 isIdr) +{ + +/* Variables */ + + u32 tmp; + u32 flag; + +/* Code */ + + ASSERT(pStorage); + ASSERT(ppsId < MAX_NUM_PIC_PARAM_SETS); + + /* check that pps and corresponding sps exist */ + if ( (pStorage->pps[ppsId] == NULL) || + (pStorage->sps[pStorage->pps[ppsId]->seqParameterSetId] == NULL) ) + { + return(HANTRO_NOK); + } + + /* check that pps parameters do not violate picture size constraints */ + tmp = CheckPps(pStorage->pps[ppsId], + pStorage->sps[pStorage->pps[ppsId]->seqParameterSetId]); + if (tmp != HANTRO_OK) + return(tmp); + + /* first activation part1 */ + if (pStorage->activePpsId == MAX_NUM_PIC_PARAM_SETS) + { + pStorage->activePpsId = ppsId; + pStorage->activePps = pStorage->pps[ppsId]; + pStorage->activeSpsId = pStorage->activePps->seqParameterSetId; + pStorage->activeSps = pStorage->sps[pStorage->activeSpsId]; + pStorage->picSizeInMbs = + pStorage->activeSps->picWidthInMbs * + pStorage->activeSps->picHeightInMbs; + + pStorage->currImage->width = pStorage->activeSps->picWidthInMbs; + pStorage->currImage->height = pStorage->activeSps->picHeightInMbs; + + pStorage->pendingActivation = HANTRO_TRUE; + } + /* first activation part2 */ + else if (pStorage->pendingActivation) + { + pStorage->pendingActivation = HANTRO_FALSE; + + FREE(pStorage->mb); + FREE(pStorage->sliceGroupMap); + + ALLOCATE(pStorage->mb, pStorage->picSizeInMbs, mbStorage_t); + ALLOCATE(pStorage->sliceGroupMap, pStorage->picSizeInMbs, u32); + if (pStorage->mb == NULL || pStorage->sliceGroupMap == NULL) + return(MEMORY_ALLOCATION_ERROR); + + H264SwDecMemset(pStorage->mb, 0, + pStorage->picSizeInMbs * sizeof(mbStorage_t)); + + h264bsdInitMbNeighbours(pStorage->mb, + pStorage->activeSps->picWidthInMbs, + pStorage->picSizeInMbs); + + /* dpb output reordering disabled if + * 1) application set noReordering flag + * 2) POC type equal to 2 + * 3) num_reorder_frames in vui equal to 0 */ + if ( pStorage->noReordering || + pStorage->activeSps->picOrderCntType == 2 || + (pStorage->activeSps->vuiParametersPresentFlag && + pStorage->activeSps->vuiParameters->bitstreamRestrictionFlag && + !pStorage->activeSps->vuiParameters->numReorderFrames) ) + flag = HANTRO_TRUE; + else + flag = HANTRO_FALSE; + + tmp = h264bsdResetDpb(pStorage->dpb, + pStorage->activeSps->picWidthInMbs * + pStorage->activeSps->picHeightInMbs, + pStorage->activeSps->maxDpbSize, + pStorage->activeSps->numRefFrames, + pStorage->activeSps->maxFrameNum, + flag); + if (tmp != HANTRO_OK) + return(tmp); + } + else if (ppsId != pStorage->activePpsId) + { + /* sequence parameter set shall not change but before an IDR picture */ + if (pStorage->pps[ppsId]->seqParameterSetId != pStorage->activeSpsId) + { + DEBUG(("SEQ PARAM SET CHANGING...\n")); + if (isIdr) + { + pStorage->activePpsId = ppsId; + pStorage->activePps = pStorage->pps[ppsId]; + pStorage->activeSpsId = pStorage->activePps->seqParameterSetId; + pStorage->activeSps = pStorage->sps[pStorage->activeSpsId]; + pStorage->picSizeInMbs = + pStorage->activeSps->picWidthInMbs * + pStorage->activeSps->picHeightInMbs; + + pStorage->currImage->width = pStorage->activeSps->picWidthInMbs; + pStorage->currImage->height = + pStorage->activeSps->picHeightInMbs; + + pStorage->pendingActivation = HANTRO_TRUE; + } + else + { + DEBUG(("TRYING TO CHANGE SPS IN NON-IDR SLICE\n")); + return(HANTRO_NOK); + } + } + else + { + pStorage->activePpsId = ppsId; + pStorage->activePps = pStorage->pps[ppsId]; + } + } + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdResetStorage + + Functional description: + Reset contents of the storage. This should be called before + processing of new image is started. + + Inputs: + pStorage pointer to storage structure + + Outputs: + none + + Returns: + none + + +------------------------------------------------------------------------------*/ + +void h264bsdResetStorage(storage_t *pStorage) +{ + +/* Variables */ + + u32 i; + +/* Code */ + + ASSERT(pStorage); + + pStorage->slice->numDecodedMbs = 0; + pStorage->slice->sliceId = 0; + + for (i = 0; i < pStorage->picSizeInMbs; i++) + { + pStorage->mb[i].sliceId = 0; + pStorage->mb[i].decoded = 0; + } + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdIsStartOfPicture + + Functional description: + Determine if the decoder is in the start of a picture. This + information is needed to decide if h264bsdActivateParamSets and + h264bsdCheckGapsInFrameNum functions should be called. Function + considers that new picture is starting if no slice headers + have been successfully decoded for the current access unit. + + Inputs: + pStorage pointer to storage structure + + Outputs: + none + + Returns: + HANTRO_TRUE new picture is starting + HANTRO_FALSE not starting + +------------------------------------------------------------------------------*/ + +u32 h264bsdIsStartOfPicture(storage_t *pStorage) +{ + +/* Variables */ + + +/* Code */ + + if (pStorage->validSliceInAccessUnit == HANTRO_FALSE) + return(HANTRO_TRUE); + else + return(HANTRO_FALSE); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdIsEndOfPicture + + Functional description: + Determine if the decoder is in the end of a picture. This + information is needed to determine when deblocking filtering + and reference picture marking processes should be performed. + + If the decoder is processing primary slices the return value + is determined by checking the value of numDecodedMbs in the + storage. On the other hand, if the decoder is processing + redundant slices the numDecodedMbs may not contain valid + informationa and each macroblock has to be checked separately. + + Inputs: + pStorage pointer to storage structure + + Outputs: + none + + Returns: + HANTRO_TRUE end of picture + HANTRO_FALSE noup + +------------------------------------------------------------------------------*/ + +u32 h264bsdIsEndOfPicture(storage_t *pStorage) +{ + +/* Variables */ + + u32 i, tmp; + +/* Code */ + + /* primary picture */ + if (!pStorage->sliceHeader[0].redundantPicCnt) + { + if (pStorage->slice->numDecodedMbs == pStorage->picSizeInMbs) + return(HANTRO_TRUE); + } + else + { + for (i = 0, tmp = 0; i < pStorage->picSizeInMbs; i++) + tmp += pStorage->mb[i].decoded ? 1 : 0; + + if (tmp == pStorage->picSizeInMbs) + return(HANTRO_TRUE); + } + + return(HANTRO_FALSE); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdComputeSliceGroupMap + + Functional description: + Compute slice group map. Just call h264bsdDecodeSliceGroupMap with + appropriate parameters. + + Inputs: + pStorage pointer to storage structure + sliceGroupChangeCycle + + Outputs: + none + + Returns: + none + +------------------------------------------------------------------------------*/ + +void h264bsdComputeSliceGroupMap(storage_t *pStorage, u32 sliceGroupChangeCycle) +{ + +/* Variables */ + + +/* Code */ + + h264bsdDecodeSliceGroupMap(pStorage->sliceGroupMap, + pStorage->activePps, sliceGroupChangeCycle, + pStorage->activeSps->picWidthInMbs, + pStorage->activeSps->picHeightInMbs); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdCheckAccessUnitBoundary + + Functional description: + Check if next NAL unit starts a new access unit. Following + conditions specify start of a new access unit: + + -NAL unit types 6-11, 13-18 (e.g. SPS, PPS) + + following conditions checked only for slice NAL units, values + compared to ones obtained from previous slice: + + -NAL unit type differs (slice / IDR slice) + -frame_num differs + -nal_ref_idc differs and one of the values is 0 + -POC information differs + -both are IDR slices and idr_pic_id differs + + Inputs: + strm pointer to stream data structure + nuNext pointer to NAL unit structure + storage pointer to storage structure + + Outputs: + accessUnitBoundaryFlag the result is stored here, TRUE for + access unit boundary, FALSE otherwise + + Returns: + HANTRO_OK success + HANTRO_NOK failure, invalid stream data + PARAM_SET_ERROR invalid param set usage + +------------------------------------------------------------------------------*/ + +u32 h264bsdCheckAccessUnitBoundary( + strmData_t *strm, + nalUnit_t *nuNext, + storage_t *storage, + u32 *accessUnitBoundaryFlag) +{ + +/* Variables */ + + u32 tmp, ppsId, frameNum, idrPicId, picOrderCntLsb; + i32 deltaPicOrderCntBottom, deltaPicOrderCnt[2]; + seqParamSet_t *sps; + picParamSet_t *pps; + +/* Code */ + + ASSERT(strm); + ASSERT(nuNext); + ASSERT(storage); + ASSERT(storage->sps); + ASSERT(storage->pps); + + /* initialize default output to FALSE */ + *accessUnitBoundaryFlag = HANTRO_FALSE; + + if ( ( (nuNext->nalUnitType > 5) && (nuNext->nalUnitType < 12) ) || + ( (nuNext->nalUnitType > 12) && (nuNext->nalUnitType <= 18) ) ) + { + *accessUnitBoundaryFlag = HANTRO_TRUE; + return(HANTRO_OK); + } + else if ( nuNext->nalUnitType != NAL_CODED_SLICE && + nuNext->nalUnitType != NAL_CODED_SLICE_IDR ) + { + return(HANTRO_OK); + } + + /* check if this is the very first call to this function */ + if (storage->aub->firstCallFlag) + { + *accessUnitBoundaryFlag = HANTRO_TRUE; + storage->aub->firstCallFlag = HANTRO_FALSE; + } + + /* get picture parameter set id */ + tmp = h264bsdCheckPpsId(strm, &ppsId); + if (tmp != HANTRO_OK) + return(tmp); + + /* store sps and pps in separate pointers just to make names shorter */ + pps = storage->pps[ppsId]; + if ( pps == NULL || storage->sps[pps->seqParameterSetId] == NULL || + (storage->activeSpsId != MAX_NUM_SEQ_PARAM_SETS && + pps->seqParameterSetId != storage->activeSpsId && + nuNext->nalUnitType != NAL_CODED_SLICE_IDR) ) + return(PARAM_SET_ERROR); + sps = storage->sps[pps->seqParameterSetId]; + + if (storage->aub->nuPrev->nalRefIdc != nuNext->nalRefIdc && + (storage->aub->nuPrev->nalRefIdc == 0 || nuNext->nalRefIdc == 0)) + *accessUnitBoundaryFlag = HANTRO_TRUE; + + if ((storage->aub->nuPrev->nalUnitType == NAL_CODED_SLICE_IDR && + nuNext->nalUnitType != NAL_CODED_SLICE_IDR) || + (storage->aub->nuPrev->nalUnitType != NAL_CODED_SLICE_IDR && + nuNext->nalUnitType == NAL_CODED_SLICE_IDR)) + *accessUnitBoundaryFlag = HANTRO_TRUE; + + tmp = h264bsdCheckFrameNum(strm, sps->maxFrameNum, &frameNum); + if (tmp != HANTRO_OK) + return(HANTRO_NOK); + + if (storage->aub->prevFrameNum != frameNum) + { + storage->aub->prevFrameNum = frameNum; + *accessUnitBoundaryFlag = HANTRO_TRUE; + } + + if (nuNext->nalUnitType == NAL_CODED_SLICE_IDR) + { + tmp = h264bsdCheckIdrPicId(strm, sps->maxFrameNum, nuNext->nalUnitType, + &idrPicId); + if (tmp != HANTRO_OK) + return(HANTRO_NOK); + + if (storage->aub->nuPrev->nalUnitType == NAL_CODED_SLICE_IDR && + storage->aub->prevIdrPicId != idrPicId) + *accessUnitBoundaryFlag = HANTRO_TRUE; + + storage->aub->prevIdrPicId = idrPicId; + } + + if (sps->picOrderCntType == 0) + { + tmp = h264bsdCheckPicOrderCntLsb(strm, sps, nuNext->nalUnitType, + &picOrderCntLsb); + if (tmp != HANTRO_OK) + return(HANTRO_NOK); + + if (storage->aub->prevPicOrderCntLsb != picOrderCntLsb) + { + storage->aub->prevPicOrderCntLsb = picOrderCntLsb; + *accessUnitBoundaryFlag = HANTRO_TRUE; + } + + if (pps->picOrderPresentFlag) + { + tmp = h264bsdCheckDeltaPicOrderCntBottom(strm, sps, + nuNext->nalUnitType, &deltaPicOrderCntBottom); + if (tmp != HANTRO_OK) + return(tmp); + + if (storage->aub->prevDeltaPicOrderCntBottom != + deltaPicOrderCntBottom) + { + storage->aub->prevDeltaPicOrderCntBottom = + deltaPicOrderCntBottom; + *accessUnitBoundaryFlag = HANTRO_TRUE; + } + } + } + else if (sps->picOrderCntType == 1 && !sps->deltaPicOrderAlwaysZeroFlag) + { + tmp = h264bsdCheckDeltaPicOrderCnt(strm, sps, nuNext->nalUnitType, + pps->picOrderPresentFlag, deltaPicOrderCnt); + if (tmp != HANTRO_OK) + return(tmp); + + if (storage->aub->prevDeltaPicOrderCnt[0] != deltaPicOrderCnt[0]) + { + storage->aub->prevDeltaPicOrderCnt[0] = deltaPicOrderCnt[0]; + *accessUnitBoundaryFlag = HANTRO_TRUE; + } + + if (pps->picOrderPresentFlag) + if (storage->aub->prevDeltaPicOrderCnt[1] != deltaPicOrderCnt[1]) + { + storage->aub->prevDeltaPicOrderCnt[1] = deltaPicOrderCnt[1]; + *accessUnitBoundaryFlag = HANTRO_TRUE; + } + } + + *storage->aub->nuPrev = *nuNext; + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: CheckPps + + Functional description: + Check picture parameter set. Contents of the picture parameter + set information that depends on the image dimensions is checked + against the dimensions in the sps. + + Inputs: + pps pointer to picture paramter set + sps pointer to sequence parameter set + + Outputs: + none + + Returns: + HANTRO_OK everything ok + HANTRO_NOK invalid data in picture parameter set + +------------------------------------------------------------------------------*/ +u32 CheckPps(picParamSet_t *pps, seqParamSet_t *sps) +{ + + u32 i; + u32 picSize; + + picSize = sps->picWidthInMbs * sps->picHeightInMbs; + + /* check slice group params */ + if (pps->numSliceGroups > 1) + { + if (pps->sliceGroupMapType == 0) + { + ASSERT(pps->runLength); + for (i = 0; i < pps->numSliceGroups; i++) + { + if (pps->runLength[i] > picSize) + return(HANTRO_NOK); + } + } + else if (pps->sliceGroupMapType == 2) + { + ASSERT(pps->topLeft); + ASSERT(pps->bottomRight); + for (i = 0; i < pps->numSliceGroups-1; i++) + { + if (pps->topLeft[i] > pps->bottomRight[i] || + pps->bottomRight[i] >= picSize) + return(HANTRO_NOK); + + if ( (pps->topLeft[i] % sps->picWidthInMbs) > + (pps->bottomRight[i] % sps->picWidthInMbs) ) + return(HANTRO_NOK); + } + } + else if (pps->sliceGroupMapType > 2 && pps->sliceGroupMapType < 6) + { + if (pps->sliceGroupChangeRate > picSize) + return(HANTRO_NOK); + } + else if (pps->sliceGroupMapType == 6 && + pps->picSizeInMapUnits < picSize) + return(HANTRO_NOK); + } + + return(HANTRO_OK); +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdValidParamSets + + Functional description: + Check if any valid SPS/PPS combination exists in the storage. + Function tries each PPS in the buffer and checks if corresponding + SPS exists and calls CheckPps to determine if the PPS conforms + to image dimensions of the SPS. + + Inputs: + pStorage pointer to storage structure + + Outputs: + HANTRO_OK there is at least one valid combination + HANTRO_NOK no valid combinations found + + +------------------------------------------------------------------------------*/ + +u32 h264bsdValidParamSets(storage_t *pStorage) +{ + +/* Variables */ + + u32 i; + +/* Code */ + + ASSERT(pStorage); + + for (i = 0; i < MAX_NUM_PIC_PARAM_SETS; i++) + { + if ( pStorage->pps[i] && + pStorage->sps[pStorage->pps[i]->seqParameterSetId] && + CheckPps(pStorage->pps[i], + pStorage->sps[pStorage->pps[i]->seqParameterSetId]) == + HANTRO_OK) + { + return(HANTRO_OK); + } + } + + return(HANTRO_NOK); + +} + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_storage.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_storage.h new file mode 100755 index 0000000..ba3b2da --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_storage.h @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. Module defines + 3. Data types + 4. Function prototypes + +------------------------------------------------------------------------------*/ + +#ifndef H264SWDEC_STORAGE_H +#define H264SWDEC_STORAGE_H + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "basetype.h" +#include "h264bsd_cfg.h" +#include "h264bsd_seq_param_set.h" +#include "h264bsd_pic_param_set.h" +#include "h264bsd_macroblock_layer.h" +#include "h264bsd_nal_unit.h" +#include "h264bsd_slice_header.h" +#include "h264bsd_seq_param_set.h" +#include "h264bsd_dpb.h" +#include "h264bsd_pic_order_cnt.h" + +/*------------------------------------------------------------------------------ + 2. Module defines +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 3. Data types +------------------------------------------------------------------------------*/ + +typedef struct +{ + u32 sliceId; + u32 numDecodedMbs; + u32 lastMbAddr; +} sliceStorage_t; + +/* structure to store parameters needed for access unit boundary checking */ +typedef struct +{ + nalUnit_t nuPrev[1]; + u32 prevFrameNum; + u32 prevIdrPicId; + u32 prevPicOrderCntLsb; + i32 prevDeltaPicOrderCntBottom; + i32 prevDeltaPicOrderCnt[2]; + u32 firstCallFlag; +} aubCheck_t; + +/* storage data structure, holds all data of a decoder instance */ +typedef struct +{ + /* active paramet set ids and pointers */ + u32 oldSpsId; + u32 activePpsId; + u32 activeSpsId; + picParamSet_t *activePps; + seqParamSet_t *activeSps; + seqParamSet_t *sps[MAX_NUM_SEQ_PARAM_SETS]; + picParamSet_t *pps[MAX_NUM_PIC_PARAM_SETS]; + + /* current slice group map, recomputed for each slice */ + u32 *sliceGroupMap; + + u32 picSizeInMbs; + + /* this flag is set after all macroblocks of a picture successfully + * decoded -> redundant slices not decoded */ + u32 skipRedundantSlices; + u32 picStarted; + + /* flag to indicate if current access unit contains any valid slices */ + u32 validSliceInAccessUnit; + + /* store information needed for handling of slice decoding */ + sliceStorage_t slice[1]; + + /* number of concealed macroblocks in the current image */ + u32 numConcealedMbs; + + /* picId given by application */ + u32 currentPicId; + + /* macroblock specific storages, size determined by image dimensions */ + mbStorage_t *mb; + + /* flag to store noOutputReordering flag set by the application */ + u32 noReordering; + + /* DPB */ + dpbStorage_t dpb[1]; + + /* structure to store picture order count related information */ + pocStorage_t poc[1]; + + /* access unit boundary checking related data */ + aubCheck_t aub[1]; + + /* current processed image */ + image_t currImage[1]; + + /* last valid NAL unit header is stored here */ + nalUnit_t prevNalUnit[1]; + + /* slice header, second structure used as a temporary storage while + * decoding slice header, first one stores last successfully decoded + * slice header */ + sliceHeader_t sliceHeader[2]; + + /* fields to store old stream buffer pointers, needed when only part of + * a stream buffer is processed by h264bsdDecode function */ + u32 prevBufNotFinished; + u8 *prevBufPointer; + u32 prevBytesConsumed; + strmData_t strm[1]; + + /* macroblock layer structure, there is no need to store this but it + * would have increased the stack size excessively and needed to be + * allocated from head -> easiest to put it here */ + macroblockLayer_t *mbLayer; + + u32 pendingActivation; /* Activate parameter sets after returning + HEADERS_RDY to the user */ + u32 intraConcealmentFlag; /* 0 gray picture for corrupted intra + 1 previous frame used if available */ +} storage_t; + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ + +void h264bsdInitStorage(storage_t *pStorage); +void h264bsdResetStorage(storage_t *pStorage); +u32 h264bsdIsStartOfPicture(storage_t *pStorage); +u32 h264bsdIsEndOfPicture(storage_t *pStorage); +u32 h264bsdStoreSeqParamSet(storage_t *pStorage, seqParamSet_t *pSeqParamSet); +u32 h264bsdStorePicParamSet(storage_t *pStorage, picParamSet_t *pPicParamSet); +u32 h264bsdActivateParamSets(storage_t *pStorage, u32 ppsId, u32 isIdr); +void h264bsdComputeSliceGroupMap(storage_t *pStorage, + u32 sliceGroupChangeCycle); + +u32 h264bsdCheckAccessUnitBoundary( + strmData_t *strm, + nalUnit_t *nuNext, + storage_t *storage, + u32 *accessUnitBoundaryFlag); + +u32 h264bsdValidParamSets(storage_t *pStorage); + +#endif /* #ifdef H264SWDEC_STORAGE_H */ + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_stream.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_stream.c new file mode 100755 index 0000000..20d1083 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_stream.c @@ -0,0 +1,242 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. External compiler flags + 3. Module defines + 4. Local function prototypes + 5. Functions + h264bsdGetBits + h264bsdShowBits32 + h264bsdFlushBits + h264bsdIsByteAligned + +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "h264bsd_util.h" +#include "h264bsd_stream.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + + Function: h264bsdGetBits + + Functional description: + Read and remove bits from the stream buffer. + + Input: + pStrmData pointer to stream data structure + numBits number of bits to read + + Output: + none + + Returns: + bits read from stream + END_OF_STREAM if not enough bits left + +------------------------------------------------------------------------------*/ + +u32 h264bsdGetBits(strmData_t *pStrmData, u32 numBits) +{ + + u32 out; + + ASSERT(pStrmData); + ASSERT(numBits < 32); + + out = h264bsdShowBits32(pStrmData) >> (32 - numBits); + + if (h264bsdFlushBits(pStrmData, numBits) == HANTRO_OK) + { + return(out); + } + else + { + return(END_OF_STREAM); + } + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdShowBits32 + + Functional description: + Read 32 bits from the stream buffer. Buffer is left as it is, i.e. + no bits are removed. First bit read from the stream is the MSB of + the return value. If there is not enough bits in the buffer -> + bits beyong the end of the stream are set to '0' in the return + value. + + Input: + pStrmData pointer to stream data structure + + Output: + none + + Returns: + bits read from stream + +------------------------------------------------------------------------------*/ + +u32 h264bsdShowBits32(strmData_t *pStrmData) +{ + + i32 bits, shift; + u32 out; + u8 *pStrm; + + ASSERT(pStrmData); + ASSERT(pStrmData->pStrmCurrPos); + ASSERT(pStrmData->bitPosInWord < 8); + ASSERT(pStrmData->bitPosInWord == + (pStrmData->strmBuffReadBits & 0x7)); + + pStrm = pStrmData->pStrmCurrPos; + + /* number of bits left in the buffer */ + bits = (i32)pStrmData->strmBuffSize*8 - (i32)pStrmData->strmBuffReadBits; + + /* at least 32-bits in the buffer */ + if (bits >= 32) + { + u32 bitPosInWord = pStrmData->bitPosInWord; + out = ((u32)pStrm[0] << 24) | ((u32)pStrm[1] << 16) | + ((u32)pStrm[2] << 8) | ((u32)pStrm[3]); + + if (bitPosInWord) + { + u32 byte = (u32)pStrm[4]; + u32 tmp = (8-bitPosInWord); + out <<= bitPosInWord; + out |= byte>>tmp; + } + return (out); + } + /* at least one bit in the buffer */ + else if (bits > 0) + { + shift = (i32)(24 + pStrmData->bitPosInWord); + out = (u32)(*pStrm++) << shift; + bits -= (i32)(8 - pStrmData->bitPosInWord); + while (bits > 0) + { + shift -= 8; + out |= (u32)(*pStrm++) << shift; + bits -= 8; + } + return (out); + } + else + return (0); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdFlushBits + + Functional description: + Remove bits from the stream buffer + + Input: + pStrmData pointer to stream data structure + numBits number of bits to remove + + Output: + none + + Returns: + HANTRO_OK success + END_OF_STREAM not enough bits left + +------------------------------------------------------------------------------*/ +#ifndef H264DEC_NEON +u32 h264bsdFlushBits(strmData_t *pStrmData, u32 numBits) +{ + + ASSERT(pStrmData); + ASSERT(pStrmData->pStrmBuffStart); + ASSERT(pStrmData->pStrmCurrPos); + ASSERT(pStrmData->bitPosInWord < 8); + ASSERT(pStrmData->bitPosInWord == (pStrmData->strmBuffReadBits & 0x7)); + + pStrmData->strmBuffReadBits += numBits; + pStrmData->bitPosInWord = pStrmData->strmBuffReadBits & 0x7; + if ( (pStrmData->strmBuffReadBits ) <= (8*pStrmData->strmBuffSize) ) + { + pStrmData->pStrmCurrPos = pStrmData->pStrmBuffStart + + (pStrmData->strmBuffReadBits >> 3); + return(HANTRO_OK); + } + else + return(END_OF_STREAM); + +} +#endif +/*------------------------------------------------------------------------------ + + Function: h264bsdIsByteAligned + + Functional description: + Check if current stream position is byte aligned. + + Inputs: + pStrmData pointer to stream data structure + + Outputs: + none + + Returns: + TRUE stream is byte aligned + FALSE stream is not byte aligned + +------------------------------------------------------------------------------*/ + +u32 h264bsdIsByteAligned(strmData_t *pStrmData) +{ + +/* Variables */ + +/* Code */ + + if (!pStrmData->bitPosInWord) + return(HANTRO_TRUE); + else + return(HANTRO_FALSE); + +} + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_stream.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_stream.h new file mode 100755 index 0000000..4404b66 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_stream.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. Module defines + 3. Data types + 4. Function prototypes + +------------------------------------------------------------------------------*/ + +#ifndef H264SWDEC_STREAM_H +#define H264SWDEC_STREAM_H + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "basetype.h" + +/*------------------------------------------------------------------------------ + 2. Module defines +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 3. Data types +------------------------------------------------------------------------------*/ + +typedef struct +{ + u8 *pStrmBuffStart; /* pointer to start of stream buffer */ + u8 *pStrmCurrPos; /* current read address in stream buffer */ + u32 bitPosInWord; /* bit position in stream buffer byte */ + u32 strmBuffSize; /* size of stream buffer (bytes) */ + u32 strmBuffReadBits; /* number of bits read from stream buffer */ +} strmData_t; + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ + +u32 h264bsdGetBits(strmData_t *pStrmData, u32 numBits); + +u32 h264bsdShowBits32(strmData_t *pStrmData); + +u32 h264bsdFlushBits(strmData_t *pStrmData, u32 numBits); + +u32 h264bsdIsByteAligned(strmData_t *); + +#endif /* #ifdef H264SWDEC_STREAM_H */ + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_transform.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_transform.c new file mode 100755 index 0000000..4eb6dd0 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_transform.c @@ -0,0 +1,402 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. External compiler flags + 3. Module defines + 4. Local function prototypes + 5. Functions + h264bsdProcessBlock + h264bsdProcessLumaDc + h264bsdProcessChromaDc + +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "basetype.h" +#include "h264bsd_transform.h" +#include "h264bsd_util.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +/* Switch off the following Lint messages for this file: + * Info 701: Shift left of signed quantity (int) + * Info 702: Shift right of signed quantity (int) + */ +/*lint -e701 -e702 */ + +/* LevelScale function */ +static const i32 levelScale[6][3] = { + {10,13,16}, {11,14,18}, {13,16,20}, {14,18,23}, {16,20,25}, {18,23,29}}; + +/* qp % 6 as a function of qp */ +static const u8 qpMod6[52] = {0,1,2,3,4,5,0,1,2,3,4,5,0,1,2,3,4,5,0,1,2,3,4,5, + 0,1,2,3,4,5,0,1,2,3,4,5,0,1,2,3,4,5,0,1,2,3,4,5,0,1,2,3}; + +/* qp / 6 as a function of qp */ +static const u8 qpDiv6[52] = {0,0,0,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3, + 4,4,4,4,4,4,5,5,5,5,5,5,6,6,6,6,6,6,7,7,7,7,7,7,8,8,8,8}; + +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + + Function: h264bsdProcessBlock + + Functional description: + Function performs inverse zig-zag scan, inverse scaling and + inverse transform for a luma or a chroma residual block + + Inputs: + data pointer to data to be processed + qp quantization parameter + skip skip processing of data[0], set to non-zero value + if dc coeff hanled separately + coeffMap 16 lsb's indicate which coeffs are non-zero, + bit 0 (lsb) for coeff 0, bit 1 for coeff 1 etc. + + Outputs: + data processed data + + Returns: + HANTRO_OK success + HANTRO_NOK processed data not in valid range [-512, 511] + +------------------------------------------------------------------------------*/ +u32 h264bsdProcessBlock(i32 *data, u32 qp, u32 skip, u32 coeffMap) +{ + +/* Variables */ + + i32 tmp0, tmp1, tmp2, tmp3; + i32 d1, d2, d3; + u32 row,col; + u32 qpDiv; + i32 *ptr; + +/* Code */ + + qpDiv = qpDiv6[qp]; + tmp1 = levelScale[qpMod6[qp]][0] << qpDiv; + tmp2 = levelScale[qpMod6[qp]][1] << qpDiv; + tmp3 = levelScale[qpMod6[qp]][2] << qpDiv; + + if (!skip) + data[0] = (data[0] * tmp1); + + /* at least one of the rows 1, 2 or 3 contain non-zero coeffs, mask takes + * the scanning order into account */ + if (coeffMap & 0xFF9C) + { + /* do the zig-zag scan and inverse quantization */ + d1 = data[1]; + d2 = data[14]; + d3 = data[15]; + data[1] = (d1 * tmp2); + data[14] = (d2 * tmp2); + data[15] = (d3 * tmp3); + + d1 = data[2]; + d2 = data[5]; + d3 = data[4]; + data[4] = (d1 * tmp2); + data[2] = (d2 * tmp1); + data[5] = (d3 * tmp3); + + d1 = data[8]; + d2 = data[3]; + d3 = data[6]; + tmp0 = (d1 * tmp2); + data[8] = (d2 * tmp1); + data[3] = (d3 * tmp2); + d1 = data[7]; + d2 = data[12]; + d3 = data[9]; + data[6] = (d1 * tmp2); + data[7] = (d2 * tmp3); + data[12] = (d3 * tmp2); + data[9] = tmp0; + + d1 = data[10]; + d2 = data[11]; + d3 = data[13]; + data[13] = (d1 * tmp3); + data[10] = (d2 * tmp1); + data[11] = (d3 * tmp2); + + /* horizontal transform */ + for (row = 4, ptr = data; row--; ptr += 4) + { + tmp0 = ptr[0] + ptr[2]; + tmp1 = ptr[0] - ptr[2]; + tmp2 = (ptr[1] >> 1) - ptr[3]; + tmp3 = ptr[1] + (ptr[3] >> 1); + ptr[0] = tmp0 + tmp3; + ptr[1] = tmp1 + tmp2; + ptr[2] = tmp1 - tmp2; + ptr[3] = tmp0 - tmp3; + } + + /*lint +e661 +e662*/ + /* then vertical transform */ + for (col = 4; col--; data++) + { + tmp0 = data[0] + data[8]; + tmp1 = data[0] - data[8]; + tmp2 = (data[4] >> 1) - data[12]; + tmp3 = data[4] + (data[12] >> 1); + data[0 ] = (tmp0 + tmp3 + 32)>>6; + data[4 ] = (tmp1 + tmp2 + 32)>>6; + data[8 ] = (tmp1 - tmp2 + 32)>>6; + data[12] = (tmp0 - tmp3 + 32)>>6; + /* check that each value is in the range [-512,511] */ + if (((u32)(data[0] + 512) > 1023) || + ((u32)(data[4] + 512) > 1023) || + ((u32)(data[8] + 512) > 1023) || + ((u32)(data[12] + 512) > 1023) ) + return(HANTRO_NOK); + } + } + else /* rows 1, 2 and 3 are zero */ + { + /* only dc-coeff is non-zero, i.e. coeffs at original positions + * 1, 5 and 6 are zero */ + if ((coeffMap & 0x62) == 0) + { + tmp0 = (data[0] + 32) >> 6; + /* check that value is in the range [-512,511] */ + if ((u32)(tmp0 + 512) > 1023) + return(HANTRO_NOK); + data[0] = data[1] = data[2] = data[3] = data[4] = data[5] = + data[6] = data[7] = data[8] = data[9] = data[10] = + data[11] = data[12] = data[13] = data[14] = data[15] = + tmp0; + } + else /* at least one of the coeffs 1, 5 or 6 is non-zero */ + { + data[1] = (data[1] * tmp2); + data[2] = (data[5] * tmp1); + data[3] = (data[6] * tmp2); + tmp0 = data[0] + data[2]; + tmp1 = data[0] - data[2]; + tmp2 = (data[1] >> 1) - data[3]; + tmp3 = data[1] + (data[3] >> 1); + data[0] = (tmp0 + tmp3 + 32)>>6; + data[1] = (tmp1 + tmp2 + 32)>>6; + data[2] = (tmp1 - tmp2 + 32)>>6; + data[3] = (tmp0 - tmp3 + 32)>>6; + data[4] = data[8] = data[12] = data[0]; + data[5] = data[9] = data[13] = data[1]; + data[6] = data[10] = data[14] = data[2]; + data[7] = data[11] = data[15] = data[3]; + /* check that each value is in the range [-512,511] */ + if (((u32)(data[0] + 512) > 1023) || + ((u32)(data[1] + 512) > 1023) || + ((u32)(data[2] + 512) > 1023) || + ((u32)(data[3] + 512) > 1023) ) + return(HANTRO_NOK); + } + } + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdProcessLumaDc + + Functional description: + Function performs inverse zig-zag scan, inverse transform and + inverse scaling for a luma DC coefficients block + + Inputs: + data pointer to data to be processed + qp quantization parameter + + Outputs: + data processed data + + Returns: + none + +------------------------------------------------------------------------------*/ +void h264bsdProcessLumaDc(i32 *data, u32 qp) +{ + +/* Variables */ + + i32 tmp0, tmp1, tmp2, tmp3; + u32 row,col; + u32 qpMod, qpDiv; + i32 levScale; + i32 *ptr; + +/* Code */ + + qpMod = qpMod6[qp]; + qpDiv = qpDiv6[qp]; + + /* zig-zag scan */ + tmp0 = data[2]; + data[2] = data[5]; + data[5] = data[4]; + data[4] = tmp0; + + tmp0 = data[8]; + data[8] = data[3]; + data[3] = data[6]; + data[6] = data[7]; + data[7] = data[12]; + data[12] = data[9]; + data[9] = tmp0; + + tmp0 = data[10]; + data[10] = data[11]; + data[11] = data[13]; + data[13] = tmp0; + + /* horizontal transform */ + for (row = 4, ptr = data; row--; ptr += 4) + { + tmp0 = ptr[0] + ptr[2]; + tmp1 = ptr[0] - ptr[2]; + tmp2 = ptr[1] - ptr[3]; + tmp3 = ptr[1] + ptr[3]; + ptr[0] = tmp0 + tmp3; + ptr[1] = tmp1 + tmp2; + ptr[2] = tmp1 - tmp2; + ptr[3] = tmp0 - tmp3; + } + + /*lint +e661 +e662*/ + /* then vertical transform and inverse scaling */ + levScale = levelScale[ qpMod ][0]; + if (qp >= 12) + { + levScale <<= (qpDiv-2); + for (col = 4; col--; data++) + { + tmp0 = data[0] + data[8 ]; + tmp1 = data[0] - data[8 ]; + tmp2 = data[4] - data[12]; + tmp3 = data[4] + data[12]; + data[0 ] = ((tmp0 + tmp3)*levScale); + data[4 ] = ((tmp1 + tmp2)*levScale); + data[8 ] = ((tmp1 - tmp2)*levScale); + data[12] = ((tmp0 - tmp3)*levScale); + } + } + else + { + i32 tmp; + tmp = ((1 - qpDiv) == 0) ? 1 : 2; + for (col = 4; col--; data++) + { + tmp0 = data[0] + data[8 ]; + tmp1 = data[0] - data[8 ]; + tmp2 = data[4] - data[12]; + tmp3 = data[4] + data[12]; + data[0 ] = ((tmp0 + tmp3)*levScale+tmp) >> (2-qpDiv); + data[4 ] = ((tmp1 + tmp2)*levScale+tmp) >> (2-qpDiv); + data[8 ] = ((tmp1 - tmp2)*levScale+tmp) >> (2-qpDiv); + data[12] = ((tmp0 - tmp3)*levScale+tmp) >> (2-qpDiv); + } + } + +} + +/*------------------------------------------------------------------------------ + + Function: h264bsdProcessChromaDc + + Functional description: + Function performs inverse transform and inverse scaling for a + chroma DC coefficients block + + Inputs: + data pointer to data to be processed + qp quantization parameter + + Outputs: + data processed data + + Returns: + none + +------------------------------------------------------------------------------*/ +void h264bsdProcessChromaDc(i32 *data, u32 qp) +{ + +/* Variables */ + + i32 tmp0, tmp1, tmp2, tmp3; + u32 qpDiv; + i32 levScale; + u32 levShift; + +/* Code */ + + qpDiv = qpDiv6[qp]; + levScale = levelScale[ qpMod6[qp] ][0]; + + if (qp >= 6) + { + levScale <<= (qpDiv-1); + levShift = 0; + } + else + { + levShift = 1; + } + + tmp0 = data[0] + data[2]; + tmp1 = data[0] - data[2]; + tmp2 = data[1] - data[3]; + tmp3 = data[1] + data[3]; + data[0] = ((tmp0 + tmp3) * levScale) >> levShift; + data[1] = ((tmp0 - tmp3) * levScale) >> levShift; + data[2] = ((tmp1 + tmp2) * levScale) >> levShift; + data[3] = ((tmp1 - tmp2) * levScale) >> levShift; + tmp0 = data[4] + data[6]; + tmp1 = data[4] - data[6]; + tmp2 = data[5] - data[7]; + tmp3 = data[5] + data[7]; + data[4] = ((tmp0 + tmp3) * levScale) >> levShift; + data[5] = ((tmp0 - tmp3) * levScale) >> levShift; + data[6] = ((tmp1 + tmp2) * levScale) >> levShift; + data[7] = ((tmp1 - tmp2) * levScale) >> levShift; + +} + +/*lint +e701 +e702 */ + + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_transform.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_transform.h new file mode 100755 index 0000000..4f41a23 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_transform.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. Module defines + 3. Data types + 4. Function prototypes + +------------------------------------------------------------------------------*/ + +#ifndef H264SWDEC_TRANSFORM_H +#define H264SWDEC_TRANSFORM_H + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "basetype.h" + +/*------------------------------------------------------------------------------ + 2. Module defines +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 3. Data types +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ + +u32 h264bsdProcessBlock(i32 *data, u32 qp, u32 skip, u32 coeffMap); +void h264bsdProcessLumaDc(i32 *data, u32 qp); +void h264bsdProcessChromaDc(i32 *data, u32 qp); + +#endif /* #ifdef H264SWDEC_TRANSFORM_H */ + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.c new file mode 100755 index 0000000..53b2fd8 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.c @@ -0,0 +1,286 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. External compiler flags + 3. Module defines + 4. Local function prototypes + 5. Functions + h264bsdCountLeadingZeros + h264bsdRbspTrailingBits + h264bsdMoreRbspData + h264bsdNextMbAddress + h264bsdSetCurrImageMbPointers + +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "h264bsd_util.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +/* look-up table for expected values of stuffing bits */ +static const u32 stuffingTable[8] = {0x1,0x2,0x4,0x8,0x10,0x20,0x40,0x80}; + +/* look-up table for chroma quantization parameter as a function of luma QP */ +const u32 h264bsdQpC[52] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19, + 20,21,22,23,24,25,26,27,28,29,29,30,31,32,32,33,34,34,35,35,36,36,37,37,37, + 38,38,38,39,39,39,39}; + +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + + 5.1 Function: h264bsdCountLeadingZeros + + Functional description: + Count leading zeros in a code word. Code word is assumed to be + right-aligned, last bit of the code word in the lsb of the value. + + Inputs: + value code word + length number of bits in the code word + + Outputs: + none + + Returns: + number of leading zeros in the code word + +------------------------------------------------------------------------------*/ +#ifndef H264DEC_NEON +u32 h264bsdCountLeadingZeros(u32 value, u32 length) +{ + +/* Variables */ + + u32 zeros = 0; + u32 mask = 1 << (length - 1); + +/* Code */ + + ASSERT(length <= 32); + + while (mask && !(value & mask)) + { + zeros++; + mask >>= 1; + } + return(zeros); + +} +#endif +/*------------------------------------------------------------------------------ + + 5.2 Function: h264bsdRbspTrailingBits + + Functional description: + Check Raw Byte Stream Payload (RBSP) trailing bits, i.e. stuffing. + Rest of the current byte (whole byte if allready byte aligned) + in the stream buffer shall contain a '1' bit followed by zero or + more '0' bits. + + Inputs: + pStrmData pointer to stream data structure + + Outputs: + none + + Returns: + HANTRO_OK RBSP trailing bits found + HANTRO_NOK otherwise + +------------------------------------------------------------------------------*/ + +u32 h264bsdRbspTrailingBits(strmData_t *pStrmData) +{ + +/* Variables */ + + u32 stuffing; + u32 stuffingLength; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pStrmData->bitPosInWord < 8); + + stuffingLength = 8 - pStrmData->bitPosInWord; + + stuffing = h264bsdGetBits(pStrmData, stuffingLength); + if (stuffing == END_OF_STREAM) + return(HANTRO_NOK); + + if (stuffing != stuffingTable[stuffingLength - 1]) + return(HANTRO_NOK); + else + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + 5.3 Function: h264bsdMoreRbspData + + Functional description: + Check if there is more data in the current RBSP. The standard + defines this function so that there is more data if + -more than 8 bits left or + -last bits are not RBSP trailing bits + + Inputs: + pStrmData pointer to stream data structure + + Outputs: + none + + Returns: + HANTRO_TRUE there is more data + HANTRO_FALSE no more data + +------------------------------------------------------------------------------*/ + +u32 h264bsdMoreRbspData(strmData_t *pStrmData) +{ + +/* Variables */ + + u32 bits; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pStrmData->strmBuffReadBits <= 8 * pStrmData->strmBuffSize); + + bits = pStrmData->strmBuffSize * 8 - pStrmData->strmBuffReadBits; + + if (bits == 0) + return(HANTRO_FALSE); + + if ( (bits > 8) || + ((h264bsdShowBits32(pStrmData)>>(32-bits)) != (1 << (bits-1))) ) + return(HANTRO_TRUE); + else + return(HANTRO_FALSE); + +} + +/*------------------------------------------------------------------------------ + + 5.4 Function: h264bsdNextMbAddress + + Functional description: + Get address of the next macroblock in the current slice group. + + Inputs: + pSliceGroupMap slice group for each macroblock + picSizeInMbs size of the picture + currMbAddr where to start + + Outputs: + none + + Returns: + address of the next macroblock + 0 if none of the following macroblocks belong to same slice + group as currMbAddr + +------------------------------------------------------------------------------*/ + +u32 h264bsdNextMbAddress(u32 *pSliceGroupMap, u32 picSizeInMbs, u32 currMbAddr) +{ + +/* Variables */ + + u32 i, sliceGroup, tmp; + +/* Code */ + + ASSERT(pSliceGroupMap); + ASSERT(picSizeInMbs); + ASSERT(currMbAddr < picSizeInMbs); + + sliceGroup = pSliceGroupMap[currMbAddr]; + + i = currMbAddr + 1; + tmp = pSliceGroupMap[i]; + while ((i < picSizeInMbs) && (tmp != sliceGroup)) + { + i++; + tmp = pSliceGroupMap[i]; + } + + if (i == picSizeInMbs) + i = 0; + + return(i); + +} + + +/*------------------------------------------------------------------------------ + + 5.5 Function: h264bsdSetCurrImageMbPointers + + Functional description: + Set luma and chroma pointers in image_t for current MB + + Inputs: + image Current image + mbNum number of current MB + + Outputs: + none + + Returns: + none +------------------------------------------------------------------------------*/ +void h264bsdSetCurrImageMbPointers(image_t *image, u32 mbNum) +{ + u32 width, height; + u32 picSize; + u32 row, col; + u32 tmp; + + width = image->width; + height = image->height; + row = mbNum / width; + col = mbNum % width; + + tmp = row * width; + picSize = width * height; + + image->luma = (u8*)(image->data + col * 16 + tmp * 256); + image->cb = (u8*)(image->data + picSize * 256 + tmp * 64 + col * 8); + image->cr = (u8*)(image->cb + picSize * 64); +} + + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.h new file mode 100755 index 0000000..cb3adda --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.h @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. Module defines + 3. Data types + 4. Function prototypes + +------------------------------------------------------------------------------*/ + +#ifndef H264SWDEC_UTIL_H +#define H264SWDEC_UTIL_H + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#ifdef _ASSERT_USED +#include <assert.h> +#endif + +#include "H264SwDecApi.h" + +#if defined(_RANGE_CHECK) || defined(_DEBUG_PRINT) || defined(_ERROR_PRINT) +#include <stdio.h> +#endif + +#include "basetype.h" +#include "h264bsd_stream.h" +#include "h264bsd_image.h" + +/*------------------------------------------------------------------------------ + 2. Module defines +------------------------------------------------------------------------------*/ + +#define HANTRO_OK 0 +#define HANTRO_NOK 1 + +#define HANTRO_TRUE (1) +#define HANTRO_FALSE (0) + +#ifndef NULL +#define NULL 0 +#endif + +#define MEMORY_ALLOCATION_ERROR 0xFFFF +#define PARAM_SET_ERROR 0xFFF0 + +/* value to be returned by GetBits if stream buffer is empty */ +#define END_OF_STREAM 0xFFFFFFFFU + +#define EMPTY_RESIDUAL_INDICATOR 0xFFFFFF + +/* macro to mark a residual block empty, i.e. contain zero coefficients */ +#define MARK_RESIDUAL_EMPTY(residual) ((residual)[0] = EMPTY_RESIDUAL_INDICATOR) +/* macro to check if residual block is empty */ +#define IS_RESIDUAL_EMPTY(residual) ((residual)[0] == EMPTY_RESIDUAL_INDICATOR) + +/* macro for assertion, used only if compiler flag _ASSERT_USED is defined */ +#ifdef _ASSERT_USED +#define ASSERT(expr) assert(expr) +#else +#define ASSERT(expr) +#endif + +/* macro for range checking an value, used only if compiler flag _RANGE_CHECK + * is defined */ +#ifdef _RANGE_CHECK +#define RANGE_CHECK(value, minBound, maxBound) \ +{ \ + if ((value) < (minBound) || (value) > (maxBound)) \ + fprintf(stderr, "Warning: Value exceeds given limit(s)!\n"); \ +} +#else +#define RANGE_CHECK(value, minBound, maxBound) +#endif + +/* macro for range checking an array, used only if compiler flag _RANGE_CHECK + * is defined */ +#ifdef _RANGE_CHECK +#define RANGE_CHECK_ARRAY(array, minBound, maxBound, length) \ +{ \ + i32 i; \ + for (i = 0; i < (length); i++) \ + if ((array)[i] < (minBound) || (array)[i] > (maxBound)) \ + fprintf(stderr,"Warning: Value [%d] exceeds given limit(s)!\n",i); \ +} +#else +#define RANGE_CHECK_ARRAY(array, minBound, maxBound, length) +#endif + +/* macro for debug printing, used only if compiler flag _DEBUG_PRINT is + * defined */ +#ifdef _DEBUG_PRINT +#define DEBUG(args) printf args +#else +#define DEBUG(args) +#endif + +/* macro for error printing, used only if compiler flag _ERROR_PRINT is + * defined */ +#ifdef _ERROR_PRINT +#define EPRINT(msg) fprintf(stderr,"ERROR: %s\n",msg) +#else +#define EPRINT(msg) +#endif + +/* macro to get smaller of two values */ +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) + +/* macro to get greater of two values */ +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) + +/* macro to get absolute value */ +#define ABS(a) (((a) < 0) ? -(a) : (a)) + +/* macro to clip a value z, so that x <= z =< y */ +#define CLIP3(x,y,z) (((z) < (x)) ? (x) : (((z) > (y)) ? (y) : (z))) + +/* macro to clip a value z, so that 0 <= z =< 255 */ +#define CLIP1(z) (((z) < 0) ? 0 : (((z) > 255) ? 255 : (z))) + +/* macro to allocate memory */ +#define ALLOCATE(ptr, count, type) \ +{ \ + (ptr) = H264SwDecMalloc((count) * sizeof(type)); \ +} + +/* macro to free allocated memory */ +#define FREE(ptr) \ +{ \ + H264SwDecFree((ptr)); (ptr) = NULL; \ +} + +#define ALIGN(ptr, bytePos) \ + (ptr + ( ((bytePos - (int)ptr) & (bytePos - 1)) / sizeof(*ptr) )) + +extern const u32 h264bsdQpC[52]; + +/*------------------------------------------------------------------------------ + 3. Data types +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ +#ifndef H264DEC_NEON +u32 h264bsdCountLeadingZeros(u32 value, u32 length); +#else +u32 h264bsdCountLeadingZeros(u32 value); +#endif +u32 h264bsdRbspTrailingBits(strmData_t *strmData); + +u32 h264bsdMoreRbspData(strmData_t *strmData); + +u32 h264bsdNextMbAddress(u32 *pSliceGroupMap, u32 picSizeInMbs, u32 currMbAddr); + +void h264bsdSetCurrImageMbPointers(image_t *image, u32 mbNum); + +#endif /* #ifdef H264SWDEC_UTIL_H */ + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_vlc.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_vlc.c new file mode 100755 index 0000000..060f35e --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_vlc.c @@ -0,0 +1,391 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. External compiler flags + 3. Module defines + 4. Local function prototypes + 5. Functions + h264bsdDecodeExpGolombUnsigned + h264bsdDecodeExpGolombSigned + h264bsdDecodeExpGolombMapped + h264bsdDecodeExpGolombTruncated + +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "h264bsd_vlc.h" +#include "basetype.h" +#include "h264bsd_stream.h" +#include "h264bsd_util.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +/* definition of special code num, this along with the return value is used + * to handle code num in the range [0, 2^32] in the DecodeExpGolombUnsigned + * function */ +#define BIG_CODE_NUM 0xFFFFFFFFU + +/* Mapping tables for coded_block_pattern, used for decoding of mapped + * Exp-Golomb codes */ +static const u8 codedBlockPatternIntra4x4[48] = { + 47,31,15,0,23,27,29,30,7,11,13,14,39,43,45,46,16,3,5,10,12,19,21,26,28,35, + 37,42,44,1,2,4,8,17,18,20,24,6,9,22,25,32,33,34,36,40,38,41}; + +static const u8 codedBlockPatternInter[48] = { + 0,16,1,2,4,8,32,3,5,10,12,15,47,7,11,13,14,6,9,31,35,37,42,44,33,34,36,40, + 39,43,45,46,17,18,20,24,19,21,26,28,23,27,29,30,22,25,38,41}; + +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + + 5.1 Function: h264bsdDecodeExpGolombUnsigned + + Functional description: + Decode unsigned Exp-Golomb code. This is the same as codeNum used + in other Exp-Golomb code mappings. Code num (i.e. the decoded + symbol) is determined as + + codeNum = 2^leadingZeros - 1 + GetBits(leadingZeros) + + Normal decoded symbols are in the range [0, 2^32 - 2]. Symbol + 2^32-1 is indicated by BIG_CODE_NUM with return value HANTRO_OK + while symbol 2^32 is indicated by BIG_CODE_NUM with return value + HANTRO_NOK. These two symbols are special cases with code length + of 65, i.e. 32 '0' bits, a '1' bit, and either 0 or 1 represented + by 32 bits. + + Symbol 2^32 is out of unsigned 32-bit range but is needed for + DecodeExpGolombSigned to express value -2^31. + + Inputs: + pStrmData pointer to stream data structure + + Outputs: + codeNum decoded code word is stored here + + Returns: + HANTRO_OK success + HANTRO_NOK failure, no valid code word found, note exception + with BIG_CODE_NUM + +------------------------------------------------------------------------------*/ + +u32 h264bsdDecodeExpGolombUnsigned(strmData_t *pStrmData, u32 *codeNum) +{ + +/* Variables */ + + u32 bits, numZeros; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(codeNum); + + bits = h264bsdShowBits32(pStrmData); + + /* first bit is 1 -> code length 1 */ + if (bits >= 0x80000000) + { + h264bsdFlushBits(pStrmData, 1); + *codeNum = 0; + return(HANTRO_OK); + } + /* second bit is 1 -> code length 3 */ + else if (bits >= 0x40000000) + { + if (h264bsdFlushBits(pStrmData, 3) == END_OF_STREAM) + return(HANTRO_NOK); + *codeNum = 1 + ((bits >> 29) & 0x1); + return(HANTRO_OK); + } + /* third bit is 1 -> code length 5 */ + else if (bits >= 0x20000000) + { + if (h264bsdFlushBits(pStrmData, 5) == END_OF_STREAM) + return(HANTRO_NOK); + *codeNum = 3 + ((bits >> 27) & 0x3); + return(HANTRO_OK); + } + /* fourth bit is 1 -> code length 7 */ + else if (bits >= 0x10000000) + { + if (h264bsdFlushBits(pStrmData, 7) == END_OF_STREAM) + return(HANTRO_NOK); + *codeNum = 7 + ((bits >> 25) & 0x7); + return(HANTRO_OK); + } + /* other code lengths */ + else + { +#ifndef H264DEC_NEON + numZeros = 4 + h264bsdCountLeadingZeros(bits, 28); +#else + numZeros = h264bsdCountLeadingZeros(bits); +#endif + /* all 32 bits are zero */ + if (numZeros == 32) + { + *codeNum = 0; + h264bsdFlushBits(pStrmData,32); + bits = h264bsdGetBits(pStrmData, 1); + /* check 33rd bit, must be 1 */ + if (bits == 1) + { + /* cannot use h264bsdGetBits, limited to 31 bits */ + bits = h264bsdShowBits32(pStrmData); + if (h264bsdFlushBits(pStrmData, 32) == END_OF_STREAM) + return(HANTRO_NOK); + /* code num 2^32 - 1, needed for unsigned mapping */ + if (bits == 0) + { + *codeNum = BIG_CODE_NUM; + return(HANTRO_OK); + } + /* code num 2^32, needed for unsigned mapping + * (results in -2^31) */ + else if (bits == 1) + { + *codeNum = BIG_CODE_NUM; + return(HANTRO_NOK); + } + } + /* if more zeros than 32, it is an error */ + return(HANTRO_NOK); + } + else + h264bsdFlushBits(pStrmData,numZeros+1); + + bits = h264bsdGetBits(pStrmData, numZeros); + if (bits == END_OF_STREAM) + return(HANTRO_NOK); + + *codeNum = (1 << numZeros) - 1 + bits; + + } + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + 5.2 Function: h264bsdDecodeExpGolombSigned + + Functional description: + Decode signed Exp-Golomb code. Code num is determined by + h264bsdDecodeExpGolombUnsigned and then mapped to signed + representation as + + symbol = (-1)^(codeNum+1) * (codeNum+1)/2 + + Signed symbols shall be in the range [-2^31, 2^31 - 1]. Symbol + -2^31 is obtained when codeNum is 2^32, which cannot be expressed + by unsigned 32-bit value. This is signaled as a special case from + the h264bsdDecodeExpGolombUnsigned by setting codeNum to + BIG_CODE_NUM and returning HANTRO_NOK status. + + Inputs: + pStrmData pointer to stream data structure + + Outputs: + value decoded code word is stored here + + Returns: + HANTRO_OK success + HANTRO_NOK failure, no valid code word found + +------------------------------------------------------------------------------*/ + +u32 h264bsdDecodeExpGolombSigned(strmData_t *pStrmData, i32 *value) +{ + +/* Variables */ + + u32 status, codeNum = 0; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(value); + + status = h264bsdDecodeExpGolombUnsigned(pStrmData, &codeNum); + + if (codeNum == BIG_CODE_NUM) + { + /* BIG_CODE_NUM and HANTRO_OK status means codeNum 2^32-1 which would + * result in signed integer valued 2^31 (i.e. out of 32-bit signed + * integer range) */ + if (status == HANTRO_OK) + return(HANTRO_NOK); + /* BIG_CODE_NUM and HANTRO_NOK status means codeNum 2^32 which results + * in signed integer valued -2^31 */ + else + { + *value = (i32)(2147483648U); + return (HANTRO_OK); + } + } + else if (status == HANTRO_OK) + { + /* (-1)^(codeNum+1) results in positive sign if codeNum is odd, + * negative when it is even. (codeNum+1)/2 is obtained as + * (codeNum+1)>>1 when value is positive and as (-codeNum)>>1 for + * negative value */ + /*lint -e702 */ + *value = (codeNum & 0x1) ? (i32)((codeNum + 1) >> 1) : + -(i32)((codeNum + 1) >> 1); + /*lint +e702 */ + return(HANTRO_OK); + } + + return(HANTRO_NOK); + +} + +/*------------------------------------------------------------------------------ + + 5.3 Function: h264bsdDecodeExpGolombMapped + + Functional description: + Decode mapped Exp-Golomb code. Code num is determined by + h264bsdDecodeExpGolombUnsigned and then mapped to codedBlockPattern + either for intra or inter macroblock. The mapping is implemented by + look-up tables defined in the beginning of the file. + + Inputs: + pStrmData pointer to stream data structure + isIntra flag to indicate if intra or inter mapping is to + be used + + Outputs: + value decoded code word is stored here + + Returns: + HANTRO_OK success + HANTRO_NOK failure, no valid code word found + +------------------------------------------------------------------------------*/ + +u32 h264bsdDecodeExpGolombMapped(strmData_t *pStrmData, u32 *value, + u32 isIntra) +{ + +/* Variables */ + + u32 status, codeNum; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(value); + + status = h264bsdDecodeExpGolombUnsigned(pStrmData, &codeNum); + + if (status != HANTRO_OK) + return (HANTRO_NOK); + else + { + /* range of valid codeNums [0,47] */ + if (codeNum > 47) + return (HANTRO_NOK); + if (isIntra) + *value = codedBlockPatternIntra4x4[codeNum]; + else + *value = codedBlockPatternInter[codeNum]; + return(HANTRO_OK); + } + +} + +/*------------------------------------------------------------------------------ + + 5.4 Function: h264bsdDecodeExpGolombTruncated + + Functional description: + Decode truncated Exp-Golomb code. greaterThanOne flag indicates + the range of the symbol to be decoded as follows: + FALSE -> [0,1] + TRUE -> [0,2^32-1] + + If flag is false the decoding is performed by reading one bit + from the stream with h264bsdGetBits and mapping this to decoded + symbol as + symbol = bit ? 0 : 1 + + Otherwise, i.e. when flag is TRUE, code num is determined by + h264bsdDecodeExpGolombUnsigned and this is used as the decoded + symbol. + + Inputs: + pStrmData pointer to stream data structure + greaterThanOne flag to indicate if range is wider than [0,1] + + Outputs: + value decoded code word is stored here + + Returns: + HANTRO_OK success + HANTRO_NOK failure, no valid code word found + +------------------------------------------------------------------------------*/ + +u32 h264bsdDecodeExpGolombTruncated( + strmData_t *pStrmData, + u32 *value, + u32 greaterThanOne) +{ + +/* Variables */ + +/* Code */ + + ASSERT(pStrmData); + ASSERT(value); + + if (greaterThanOne) + { + return(h264bsdDecodeExpGolombUnsigned(pStrmData, value)); + } + else + { + *value = h264bsdGetBits(pStrmData,1); + if (*value == END_OF_STREAM) + return (HANTRO_NOK); + *value ^= 0x1; + } + + return (HANTRO_OK); + +} + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_vlc.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_vlc.h new file mode 100755 index 0000000..4c16773 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_vlc.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. Module defines + 3. Data types + 4. Function prototypes + +------------------------------------------------------------------------------*/ + +#ifndef H264SWDEC_VLC_H +#define H264SWDEC_VLC_H + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "basetype.h" +#include "h264bsd_stream.h" +#include "h264bsd_transform.h" + +/*------------------------------------------------------------------------------ + 2. Module defines +------------------------------------------------------------------------------*/ + + +/*------------------------------------------------------------------------------ + 3. Data types +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ + +u32 h264bsdDecodeExpGolombUnsigned(strmData_t *pStrmData, u32 *value); + +u32 h264bsdDecodeExpGolombSigned(strmData_t *pStrmData, i32 *value); + +u32 h264bsdDecodeExpGolombMapped(strmData_t *pStrmData, u32 *value, + u32 isIntra); + +u32 h264bsdDecodeExpGolombTruncated(strmData_t *pStrmData, u32 *value, + u32 greaterThanOne); + +#endif /* #ifdef H264SWDEC_VLC_H */ + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_vui.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_vui.c new file mode 100755 index 0000000..4a9335a --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_vui.c @@ -0,0 +1,490 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. External compiler flags + 3. Module defines + 4. Local function prototypes + 5. Functions + h264bsdDecodeVuiParameters + DecodeHrdParameters + +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "h264bsd_vui.h" +#include "basetype.h" +#include "h264bsd_vlc.h" +#include "h264bsd_stream.h" +#include "h264bsd_util.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +#define MAX_DPB_SIZE 16 +#define MAX_BR 240000 /* for level 5.1 */ +#define MAX_CPB 240000 /* for level 5.1 */ + +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ + +static u32 DecodeHrdParameters( + strmData_t *pStrmData, + hrdParameters_t *pHrdParameters); + +/*------------------------------------------------------------------------------ + + Function: h264bsdDecodeVuiParameters + + Functional description: + Decode VUI parameters from the stream. See standard for details. + + Inputs: + pStrmData pointer to stream data structure + + Outputs: + pVuiParameters decoded information is stored here + + Returns: + HANTRO_OK success + HANTRO_NOK invalid stream data or end of stream + +------------------------------------------------------------------------------*/ + +u32 h264bsdDecodeVuiParameters(strmData_t *pStrmData, + vuiParameters_t *pVuiParameters) +{ + +/* Variables */ + + u32 tmp; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pVuiParameters); + + H264SwDecMemset(pVuiParameters, 0, sizeof(vuiParameters_t)); + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pVuiParameters->aspectRatioPresentFlag = (tmp == 1) ? + HANTRO_TRUE : HANTRO_FALSE; + + if (pVuiParameters->aspectRatioPresentFlag) + { + tmp = h264bsdGetBits(pStrmData, 8); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pVuiParameters->aspectRatioIdc = tmp; + + if (pVuiParameters->aspectRatioIdc == ASPECT_RATIO_EXTENDED_SAR) + { + tmp = h264bsdGetBits(pStrmData, 16); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pVuiParameters->sarWidth = tmp; + + tmp = h264bsdGetBits(pStrmData, 16); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pVuiParameters->sarHeight = tmp; + } + } + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pVuiParameters->overscanInfoPresentFlag = (tmp == 1) ? + HANTRO_TRUE : HANTRO_FALSE; + + if (pVuiParameters->overscanInfoPresentFlag) + { + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pVuiParameters->overscanAppropriateFlag = (tmp == 1) ? + HANTRO_TRUE : HANTRO_FALSE; + } + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pVuiParameters->videoSignalTypePresentFlag = (tmp == 1) ? + HANTRO_TRUE : HANTRO_FALSE; + + if (pVuiParameters->videoSignalTypePresentFlag) + { + tmp = h264bsdGetBits(pStrmData, 3); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pVuiParameters->videoFormat = tmp; + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pVuiParameters->videoFullRangeFlag = (tmp == 1) ? + HANTRO_TRUE : HANTRO_FALSE; + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pVuiParameters->colourDescriptionPresentFlag = + (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; + + if (pVuiParameters->colourDescriptionPresentFlag) + { + tmp = h264bsdGetBits(pStrmData, 8); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pVuiParameters->colourPrimaries = tmp; + + tmp = h264bsdGetBits(pStrmData, 8); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pVuiParameters->transferCharacteristics = tmp; + + tmp = h264bsdGetBits(pStrmData, 8); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pVuiParameters->matrixCoefficients = tmp; + } + else + { + pVuiParameters->colourPrimaries = 2; + pVuiParameters->transferCharacteristics = 2; + pVuiParameters->matrixCoefficients = 2; + } + } + else + { + pVuiParameters->videoFormat = 5; + pVuiParameters->colourPrimaries = 2; + pVuiParameters->transferCharacteristics = 2; + pVuiParameters->matrixCoefficients = 2; + } + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pVuiParameters->chromaLocInfoPresentFlag = + (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; + + if (pVuiParameters->chromaLocInfoPresentFlag) + { + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pVuiParameters->chromaSampleLocTypeTopField); + if (tmp != HANTRO_OK) + return(tmp); + if (pVuiParameters->chromaSampleLocTypeTopField > 5) + return(HANTRO_NOK); + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pVuiParameters->chromaSampleLocTypeBottomField); + if (tmp != HANTRO_OK) + return(tmp); + if (pVuiParameters->chromaSampleLocTypeBottomField > 5) + return(HANTRO_NOK); + } + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pVuiParameters->timingInfoPresentFlag = + (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; + + if (pVuiParameters->timingInfoPresentFlag) + { + tmp = h264bsdShowBits32(pStrmData); + if (h264bsdFlushBits(pStrmData, 32) == END_OF_STREAM) + return(HANTRO_NOK); + if (tmp == 0) + return(HANTRO_NOK); + pVuiParameters->numUnitsInTick = tmp; + + tmp = h264bsdShowBits32(pStrmData); + if (h264bsdFlushBits(pStrmData, 32) == END_OF_STREAM) + return(HANTRO_NOK); + if (tmp == 0) + return(HANTRO_NOK); + pVuiParameters->timeScale = tmp; + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pVuiParameters->fixedFrameRateFlag = + (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; + } + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pVuiParameters->nalHrdParametersPresentFlag = + (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; + + if (pVuiParameters->nalHrdParametersPresentFlag) + { + tmp = DecodeHrdParameters(pStrmData, &pVuiParameters->nalHrdParameters); + if (tmp != HANTRO_OK) + return(tmp); + } + else + { + pVuiParameters->nalHrdParameters.cpbCnt = 1; + /* MaxBR and MaxCPB should be the values correspondig to the levelIdc + * in the SPS containing these VUI parameters. However, these values + * are not used anywhere and maximum for any level will be used here */ + pVuiParameters->nalHrdParameters.bitRateValue[0] = 1200 * MAX_BR + 1; + pVuiParameters->nalHrdParameters.cpbSizeValue[0] = 1200 * MAX_CPB + 1; + pVuiParameters->nalHrdParameters.initialCpbRemovalDelayLength = 24; + pVuiParameters->nalHrdParameters.cpbRemovalDelayLength = 24; + pVuiParameters->nalHrdParameters.dpbOutputDelayLength = 24; + pVuiParameters->nalHrdParameters.timeOffsetLength = 24; + } + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pVuiParameters->vclHrdParametersPresentFlag = + (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; + + if (pVuiParameters->vclHrdParametersPresentFlag) + { + tmp = DecodeHrdParameters(pStrmData, &pVuiParameters->vclHrdParameters); + if (tmp != HANTRO_OK) + return(tmp); + } + else + { + pVuiParameters->vclHrdParameters.cpbCnt = 1; + /* MaxBR and MaxCPB should be the values correspondig to the levelIdc + * in the SPS containing these VUI parameters. However, these values + * are not used anywhere and maximum for any level will be used here */ + pVuiParameters->vclHrdParameters.bitRateValue[0] = 1000 * MAX_BR + 1; + pVuiParameters->vclHrdParameters.cpbSizeValue[0] = 1000 * MAX_CPB + 1; + pVuiParameters->vclHrdParameters.initialCpbRemovalDelayLength = 24; + pVuiParameters->vclHrdParameters.cpbRemovalDelayLength = 24; + pVuiParameters->vclHrdParameters.dpbOutputDelayLength = 24; + pVuiParameters->vclHrdParameters.timeOffsetLength = 24; + } + + if (pVuiParameters->nalHrdParametersPresentFlag || + pVuiParameters->vclHrdParametersPresentFlag) + { + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pVuiParameters->lowDelayHrdFlag = + (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; + } + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pVuiParameters->picStructPresentFlag = + (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pVuiParameters->bitstreamRestrictionFlag = + (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; + + if (pVuiParameters->bitstreamRestrictionFlag) + { + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pVuiParameters->motionVectorsOverPicBoundariesFlag = + (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pVuiParameters->maxBytesPerPicDenom); + if (tmp != HANTRO_OK) + return(tmp); + if (pVuiParameters->maxBytesPerPicDenom > 16) + return(HANTRO_NOK); + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pVuiParameters->maxBitsPerMbDenom); + if (tmp != HANTRO_OK) + return(tmp); + if (pVuiParameters->maxBitsPerMbDenom > 16) + return(HANTRO_NOK); + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pVuiParameters->log2MaxMvLengthHorizontal); + if (tmp != HANTRO_OK) + return(tmp); + if (pVuiParameters->log2MaxMvLengthHorizontal > 16) + return(HANTRO_NOK); + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pVuiParameters->log2MaxMvLengthVertical); + if (tmp != HANTRO_OK) + return(tmp); + if (pVuiParameters->log2MaxMvLengthVertical > 16) + return(HANTRO_NOK); + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pVuiParameters->numReorderFrames); + if (tmp != HANTRO_OK) + return(tmp); + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pVuiParameters->maxDecFrameBuffering); + if (tmp != HANTRO_OK) + return(tmp); + } + else + { + pVuiParameters->motionVectorsOverPicBoundariesFlag = HANTRO_TRUE; + pVuiParameters->maxBytesPerPicDenom = 2; + pVuiParameters->maxBitsPerMbDenom = 1; + pVuiParameters->log2MaxMvLengthHorizontal = 16; + pVuiParameters->log2MaxMvLengthVertical = 16; + pVuiParameters->numReorderFrames = MAX_DPB_SIZE; + pVuiParameters->maxDecFrameBuffering = MAX_DPB_SIZE; + } + + return(HANTRO_OK); + +} + +/*------------------------------------------------------------------------------ + + Function: DecodeHrdParameters + + Functional description: + Decode HRD parameters from the stream. See standard for details. + + Inputs: + pStrmData pointer to stream data structure + + Outputs: + pHrdParameters decoded information is stored here + + Returns: + HANTRO_OK success + HANTRO_NOK invalid stream data + +------------------------------------------------------------------------------*/ + +static u32 DecodeHrdParameters( + strmData_t *pStrmData, + hrdParameters_t *pHrdParameters) +{ + +/* Variables */ + + u32 tmp, i; + +/* Code */ + + ASSERT(pStrmData); + ASSERT(pHrdParameters); + + + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pHrdParameters->cpbCnt); + if (tmp != HANTRO_OK) + return(tmp); + /* cpbCount = cpb_cnt_minus1 + 1 */ + pHrdParameters->cpbCnt++; + if (pHrdParameters->cpbCnt > MAX_CPB_CNT) + return(HANTRO_NOK); + + tmp = h264bsdGetBits(pStrmData, 4); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pHrdParameters->bitRateScale = tmp; + + tmp = h264bsdGetBits(pStrmData, 4); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pHrdParameters->cpbSizeScale = tmp; + + for (i = 0; i < pHrdParameters->cpbCnt; i++) + { + /* bit_rate_value_minus1 in the range [0, 2^32 - 2] */ + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pHrdParameters->bitRateValue[i]); + if (tmp != HANTRO_OK) + return(tmp); + if (pHrdParameters->bitRateValue[i] > 4294967294U) + return(HANTRO_NOK); + pHrdParameters->bitRateValue[i]++; + /* this may result in overflow, but this value is not used for + * anything */ + pHrdParameters->bitRateValue[i] *= + 1 << (6 + pHrdParameters->bitRateScale); + + /* cpb_size_value_minus1 in the range [0, 2^32 - 2] */ + tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, + &pHrdParameters->cpbSizeValue[i]); + if (tmp != HANTRO_OK) + return(tmp); + if (pHrdParameters->cpbSizeValue[i] > 4294967294U) + return(HANTRO_NOK); + pHrdParameters->cpbSizeValue[i]++; + /* this may result in overflow, but this value is not used for + * anything */ + pHrdParameters->cpbSizeValue[i] *= + 1 << (4 + pHrdParameters->cpbSizeScale); + + tmp = h264bsdGetBits(pStrmData, 1); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pHrdParameters->cbrFlag[i] = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; + } + + tmp = h264bsdGetBits(pStrmData, 5); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pHrdParameters->initialCpbRemovalDelayLength = tmp + 1; + + tmp = h264bsdGetBits(pStrmData, 5); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pHrdParameters->cpbRemovalDelayLength = tmp + 1; + + tmp = h264bsdGetBits(pStrmData, 5); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pHrdParameters->dpbOutputDelayLength = tmp + 1; + + tmp = h264bsdGetBits(pStrmData, 5); + if (tmp == END_OF_STREAM) + return(HANTRO_NOK); + pHrdParameters->timeOffsetLength = tmp; + + return(HANTRO_OK); + +} + diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_vui.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_vui.h new file mode 100755 index 0000000..05d52a4 --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_vui.h @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*------------------------------------------------------------------------------ + + Table of contents + + 1. Include headers + 2. Module defines + 3. Data types + 4. Function prototypes + +------------------------------------------------------------------------------*/ + +#ifndef H264SWDEC_VUI_H +#define H264SWDEC_VUI_H + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "basetype.h" +#include "h264bsd_stream.h" + +/*------------------------------------------------------------------------------ + 2. Module defines +------------------------------------------------------------------------------*/ + +#define MAX_CPB_CNT 32 + +/*------------------------------------------------------------------------------ + 3. Data types +------------------------------------------------------------------------------*/ + +/* enumerated sample aspect ratios, ASPECT_RATIO_M_N means M:N */ +enum +{ + ASPECT_RATIO_UNSPECIFIED = 0, + ASPECT_RATIO_1_1, + ASPECT_RATIO_12_11, + ASPECT_RATIO_10_11, + ASPECT_RATIO_16_11, + ASPECT_RATIO_40_33, + ASPECT_RATIO_24_11, + ASPECT_RATIO_20_11, + ASPECT_RATIO_32_11, + ASPECT_RATIO_80_33, + ASPECT_RATIO_18_11, + ASPECT_RATIO_15_11, + ASPECT_RATIO_64_33, + ASPECT_RATIO_160_99, + ASPECT_RATIO_EXTENDED_SAR = 255 +}; + +/* structure to store Hypothetical Reference Decoder (HRD) parameters */ +typedef struct +{ + u32 cpbCnt; + u32 bitRateScale; + u32 cpbSizeScale; + u32 bitRateValue[MAX_CPB_CNT]; + u32 cpbSizeValue[MAX_CPB_CNT]; + u32 cbrFlag[MAX_CPB_CNT]; + u32 initialCpbRemovalDelayLength; + u32 cpbRemovalDelayLength; + u32 dpbOutputDelayLength; + u32 timeOffsetLength; +} hrdParameters_t; + +/* storage for VUI parameters */ +typedef struct +{ + u32 aspectRatioPresentFlag; + u32 aspectRatioIdc; + u32 sarWidth; + u32 sarHeight; + u32 overscanInfoPresentFlag; + u32 overscanAppropriateFlag; + u32 videoSignalTypePresentFlag; + u32 videoFormat; + u32 videoFullRangeFlag; + u32 colourDescriptionPresentFlag; + u32 colourPrimaries; + u32 transferCharacteristics; + u32 matrixCoefficients; + u32 chromaLocInfoPresentFlag; + u32 chromaSampleLocTypeTopField; + u32 chromaSampleLocTypeBottomField; + u32 timingInfoPresentFlag; + u32 numUnitsInTick; + u32 timeScale; + u32 fixedFrameRateFlag; + u32 nalHrdParametersPresentFlag; + hrdParameters_t nalHrdParameters; + u32 vclHrdParametersPresentFlag; + hrdParameters_t vclHrdParameters; + u32 lowDelayHrdFlag; + u32 picStructPresentFlag; + u32 bitstreamRestrictionFlag; + u32 motionVectorsOverPicBoundariesFlag; + u32 maxBytesPerPicDenom; + u32 maxBitsPerMbDenom; + u32 log2MaxMvLengthHorizontal; + u32 log2MaxMvLengthVertical; + u32 numReorderFrames; + u32 maxDecFrameBuffering; +} vuiParameters_t; + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ + +u32 h264bsdDecodeVuiParameters(strmData_t *pStrmData, + vuiParameters_t *pVuiParameters); + +#endif /* #ifdef H264SWDEC_VUI_H */ + |