ref: 1fb2f7de0928afa9b3d2ae4c2388b07d370503db
parent: d43bfc1ecd07c08cfe0e65b492c863fd3c8ab59b
author: Martin Storsjö <martin@martin.st>
date: Fri Jul 27 20:47:05 EDT 2018
Restore unix newlines after "Merge pull request #2991 from xiaotianshi2/master" Some newlines were fixed in "Merge pull request #2997 from GuangweiWang/fix-issue-external", but lots were still left behind.
--- a/codec/api/svc/codec_api.h
+++ b/codec/api/svc/codec_api.h
@@ -1,591 +1,591 @@
-/*!
- *@page License
- *
- * \copy
- * Copyright (c) 2013, Cisco Systems
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#ifndef WELS_VIDEO_CODEC_SVC_API_H__
-#define WELS_VIDEO_CODEC_SVC_API_H__
-
-#ifndef __cplusplus
-#if defined(_MSC_VER) && (_MSC_VER < 1800)
-typedef unsigned char bool;
-#else
-#include <stdbool.h>
-#endif
-#endif
-
-#include "codec_app_def.h"
-#include "codec_def.h"
-
-#if defined(_WIN32) || defined(__cdecl)
-#define EXTAPI __cdecl
-#else
-#define EXTAPI
-#endif
-
-/**
- * @file codec_api.h
-*/
-
-/**
- * @page Overview
- * * This page is for openh264 codec API usage.
- * * For how to use the encoder,please refer to page UsageExampleForEncoder
- * * For how to use the decoder,please refer to page UsageExampleForDecoder
- * * For more detail about ISVEncoder,please refer to page ISVCEnoder
- * * For more detail about ISVDecoder,please refer to page ISVCDecoder
-*/
-
-/**
- * @page DecoderUsageExample
- *
- * @brief
- * * An example for using the decoder for Decoding only or Parsing only
- *
- * Step 1:decoder declaration
- * @code
- *
- * //decoder declaration
- * ISVCDecoder *pSvcDecoder;
- * //input: encoded bitstream start position; should include start code prefix
- * unsigned char *pBuf =...;
- * //input: encoded bit stream length; should include the size of start code prefix
- * int iSize =...;
- * //output: [0~2] for Y,U,V buffer for Decoding only
- * unsigned char *pData[3] =...;
- * //in-out: for Decoding only: declare and initialize the output buffer info, this should never co-exist with Parsing only
- * SBufferInfo sDstBufInfo;
- * memset(&sDstBufInfo, 0, sizeof(SBufferInfo));
- * //in-out: for Parsing only: declare and initialize the output bitstream buffer info for parse only, this should never co-exist with Decoding only
- * SParserBsInfo sDstParseInfo;
- * memset(&sDstParseInfo, 0, sizeof(SParserBsInfo));
- * sDstParseInfo.pDstBuff = new unsigned char[PARSE_SIZE]; //In Parsing only, allocate enough buffer to save transcoded bitstream for a frame
- *
- * @endcode
- *
- * Step 2:decoder creation
- * @code
- * CreateDecoder(pSvcDecoder);
- * @endcode
- *
- * Step 3:declare required parameter, used to differentiate Decoding only and Parsing only
- * @code
- * SDecodingParam sDecParam = {0};
- * sDecParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_AVC;
- * //for Parsing only, the assignment is mandatory
- * sDecParam.bParseOnly = true;
- * @endcode
- *
- * Step 4:initialize the parameter and decoder context, allocate memory
- * @code
- * Initialize(&sDecParam);
- * @endcode
- *
- * Step 5:do actual decoding process in slice level;
- * this can be done in a loop until data ends
- * @code
- * //for Decoding only
- * iRet = DecodeFrameNoDelay(pBuf, iSize, pData, &sDstBufInfo);
- * //or
- * iRet = DecodeFrame2(pBuf, iSize, pData, &sDstBufInfo);
- * //for Parsing only
- * iRet = DecodeParser(pBuf, iSize, &sDstParseInfo);
- * //decode failed
- * If (iRet != 0){
- * RequestIDR or something like that.
- * }
- * //for Decoding only, pData can be used for render.
- * if (sDstBufInfo.iBufferStatus==1){
- * output pData[0], pData[1], pData[2];
- * }
- * //for Parsing only, sDstParseInfo can be used for, e.g., HW decoding
- * if (sDstBufInfo.iNalNum > 0){
- * Hardware decoding sDstParseInfo;
- * }
- * //no-delay decoding can be realized by directly calling DecodeFrameNoDelay(), which is the recommended usage.
- * //no-delay decoding can also be realized by directly calling DecodeFrame2() again with NULL input, as in the following. In this case, decoder would immediately reconstruct the input data. This can also be used similarly for Parsing only. Consequent decoding error and output indication should also be considered as above.
- * iRet = DecodeFrame2(NULL, 0, pData, &sDstBufInfo);
- * judge iRet, sDstBufInfo.iBufferStatus ...
- * @endcode
- *
- * Step 6:uninitialize the decoder and memory free
- * @code
- * Uninitialize();
- * @endcode
- *
- * Step 7:destroy the decoder
- * @code
- * DestroyDecoder();
- * @endcode
- *
-*/
-
-/**
- * @page EncoderUsageExample1
- *
- * @brief
- * * An example for using encoder with basic parameter
- *
- * Step1:setup encoder
- * @code
- * int rv = WelsCreateSVCEncoder (&encoder_);
- * ASSERT_EQ (0, rv);
- * ASSERT_TRUE (encoder_ != NULL);
- * @endcode
- *
- * Step2:initilize with basic parameter
- * @code
- * SEncParamBase param;
- * memset (¶m, 0, sizeof (SEncParamBase));
- * param.iUsageType = usageType;
- * param.fMaxFrameRate = frameRate;
- * param.iPicWidth = width;
- * param.iPicHeight = height;
- * param.iTargetBitrate = 5000000;
- * encoder_->Initialize (¶m);
- * @endcode
- *
- * Step3:set option, set option during encoding process
- * @code
- * encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &g_LevelSetting);
- * int videoFormat = videoFormatI420;
- * encoder_->SetOption (ENCODER_OPTION_DATAFORMAT, &videoFormat);
- * @endcode
- *
- * Step4: encode and store ouput bistream
- * @code
- * int frameSize = width * height * 3 / 2;
- * BufferedData buf;
- * buf.SetLength (frameSize);
- * ASSERT_TRUE (buf.Length() == (size_t)frameSize);
- * SFrameBSInfo info;
- * memset (&info, 0, sizeof (SFrameBSInfo));
- * SSourcePicture pic;
- * memset (&pic, 0, sizeof (SsourcePicture));
- * pic.iPicWidth = width;
- * pic.iPicHeight = height;
- * pic.iColorFormat = videoFormatI420;
- * pic.iStride[0] = pic.iPicWidth;
- * pic.iStride[1] = pic.iStride[2] = pic.iPicWidth >> 1;
- * pic.pData[0] = buf.data();
- * pic.pData[1] = pic.pData[0] + width * height;
- * pic.pData[2] = pic.pData[1] + (width * height >> 2);
- * for(int num = 0;num<total_num;num++) {
- * //prepare input data
- * rv = encoder_->EncodeFrame (&pic, &info);
- * ASSERT_TRUE (rv == cmResultSuccess);
- * if (info.eFrameType != videoFrameTypeSkip && cbk != NULL) {
- * //output bitstream
- * }
- * }
- * @endcode
- *
- * Step5:teardown encoder
- * @code
- * if (encoder_) {
- * encoder_->Uninitialize();
- * WelsDestroySVCEncoder (encoder_);
- * }
- * @endcode
- *
- */
-
-/**
- * @page EncoderUsageExample2
- *
- * @brief
- * * An example for using the encoder with extension parameter.
- * * The same operation on Step 1,3,4,5 with Example-1
- *
- * Step 2:initialize with extension parameter
- * @code
- * SEncParamExt param;
- * encoder->GetDefaultParams (¶m);
- * param.iUsageType = usageType;
- * param.fMaxFrameRate = frameRate;
- * param.iPicWidth = width;
- * param.iPicHeight = height;
- * param.iTargetBitrate = 5000000;
- * param.bEnableDenoise = denoise;
- * param.iSpatialLayerNum = layers;
- * //SM_DYN_SLICE don't support multi-thread now
- * if (sliceMode != SM_SINGLE_SLICE && sliceMode != SM_DYN_SLICE)
- * param.iMultipleThreadIdc = 2;
- *
- * for (int i = 0; i < param.iSpatialLayerNum; i++) {
- * param.sSpatialLayers[i].iVideoWidth = width >> (param.iSpatialLayerNum - 1 - i);
- * param.sSpatialLayers[i].iVideoHeight = height >> (param.iSpatialLayerNum - 1 - i);
- * param.sSpatialLayers[i].fFrameRate = frameRate;
- * param.sSpatialLayers[i].iSpatialBitrate = param.iTargetBitrate;
- *
- * param.sSpatialLayers[i].sSliceCfg.uiSliceMode = sliceMode;
- * if (sliceMode == SM_DYN_SLICE) {
- * param.sSpatialLayers[i].sSliceCfg.sSliceArgument.uiSliceSizeConstraint = 600;
- * param.uiMaxNalSize = 1500;
- * }
- * }
- * param.iTargetBitrate *= param.iSpatialLayerNum;
- * encoder_->InitializeExt (¶m);
- * int videoFormat = videoFormatI420;
- * encoder_->SetOption (ENCODER_OPTION_DATAFORMAT, &videoFormat);
- *
- * @endcode
- */
-
-
-
-
-#ifdef __cplusplus
-/**
-* @brief Endocder definition
-*/
-class ISVCEncoder {
- public:
- /**
- * @brief Initialize the encoder
- * @param pParam basic encoder parameter
- * @return CM_RETURN: 0 - success; otherwise - failed;
- */
- virtual int EXTAPI Initialize (const SEncParamBase* pParam) = 0;
-
- /**
- * @brief Initilaize encoder by using extension parameters.
- * @param pParam extension parameter for encoder
- * @return CM_RETURN: 0 - success; otherwise - failed;
- */
- virtual int EXTAPI InitializeExt (const SEncParamExt* pParam) = 0;
-
- /**
- * @brief Get the default extension parameters.
- * If you want to change some parameters of encoder, firstly you need to get the default encoding parameters,
- * after that you can change part of parameters you want to.
- * @param pParam extension parameter for encoder
- * @return CM_RETURN: 0 - success; otherwise - failed;
- * */
- virtual int EXTAPI GetDefaultParams (SEncParamExt* pParam) = 0;
- /// uninitialize the encoder
- virtual int EXTAPI Uninitialize() = 0;
-
- /**
- * @brief Encode one frame
- * @param kpSrcPic the pointer to the source luminance plane
- * chrominance data:
- * CbData = kpSrc + m_iMaxPicWidth * m_iMaxPicHeight;
- * CrData = CbData + (m_iMaxPicWidth * m_iMaxPicHeight)/4;
- * the application calling this interface needs to ensure the data validation between the location
- * @param pBsInfo output bit stream
- * @return 0 - success; otherwise -failed;
- */
- virtual int EXTAPI EncodeFrame (const SSourcePicture* kpSrcPic, SFrameBSInfo* pBsInfo) = 0;
-
- /**
- * @brief Encode the parameters from output bit stream
- * @param pBsInfo output bit stream
- * @return 0 - success; otherwise - failed;
- */
- virtual int EXTAPI EncodeParameterSets (SFrameBSInfo* pBsInfo) = 0;
-
- /**
- * @brief Force encoder to encoder frame as IDR if bIDR set as true
- * @param bIDR true: force encoder to encode frame as IDR frame;false, return 1 and nothing to do
- * @return 0 - success; otherwise - failed;
- */
- virtual int EXTAPI ForceIntraFrame (bool bIDR, int iLayerId = -1) = 0;
-
- /**
- * @brief Set option for encoder, detail option type, please refer to enumurate ENCODER_OPTION.
- * @param pOption option for encoder such as InDataFormat, IDRInterval, SVC Encode Param, Frame Rate, Bitrate,...
- * @return CM_RETURN: 0 - success; otherwise - failed;
- */
- virtual int EXTAPI SetOption (ENCODER_OPTION eOptionId, void* pOption) = 0;
-
- /**
- * @brief Set option for encoder, detail option type, please refer to enumurate ENCODER_OPTION.
- * @param pOption option for encoder such as InDataFormat, IDRInterval, SVC Encode Param, Frame Rate, Bitrate,...
- * @return CM_RETURN: 0 - success; otherwise - failed;
- */
- virtual int EXTAPI GetOption (ENCODER_OPTION eOptionId, void* pOption) = 0;
- virtual ~ISVCEncoder() {}
-};
-
-
-
-/**
-* @brief Decoder definition
-*/
-class ISVCDecoder {
- public:
-
- /**
- * @brief Initilaize decoder
- * @param pParam parameter for decoder
- * @return 0 - success; otherwise - failed;
- */
- virtual long EXTAPI Initialize (const SDecodingParam* pParam) = 0;
-
- /// Uninitialize the decoder
- virtual long EXTAPI Uninitialize() = 0;
-
- /**
- * @brief Decode one frame
- * @param pSrc the h264 stream to be decoded
- * @param iSrcLen the length of h264 stream
- * @param ppDst buffer pointer of decoded data (YUV)
- * @param pStride output stride
- * @param iWidth output width
- * @param iHeight output height
- * @return 0 - success; otherwise -failed;
- */
- virtual DECODING_STATE EXTAPI DecodeFrame (const unsigned char* pSrc,
- const int iSrcLen,
- unsigned char** ppDst,
- int* pStride,
- int& iWidth,
- int& iHeight) = 0;
-
- /**
- * @brief For slice level DecodeFrameNoDelay() (4 parameters input),
- * whatever the function return value is, the output data
- * of I420 format will only be available when pDstInfo->iBufferStatus == 1,.
- * This function will parse and reconstruct the input frame immediately if it is complete
- * It is recommended as the main decoding function for H.264/AVC format input
- * @param pSrc the h264 stream to be decoded
- * @param iSrcLen the length of h264 stream
- * @param ppDst buffer pointer of decoded data (YUV)
- * @param pDstInfo information provided to API(width, height, etc.)
- * @return 0 - success; otherwise -failed;
- */
- virtual DECODING_STATE EXTAPI DecodeFrameNoDelay (const unsigned char* pSrc,
- const int iSrcLen,
- unsigned char** ppDst,
- SBufferInfo* pDstInfo) = 0;
-
- /**
- * @brief For slice level DecodeFrame2() (4 parameters input),
- * whatever the function return value is, the output data
- * of I420 format will only be available when pDstInfo->iBufferStatus == 1,.
- * (e.g., in multi-slice cases, only when the whole picture
- * is completely reconstructed, this variable would be set equal to 1.)
- * @param pSrc the h264 stream to be decoded
- * @param iSrcLen the length of h264 stream
- * @param ppDst buffer pointer of decoded data (YUV)
- * @param pDstInfo information provided to API(width, height, etc.)
- * @return 0 - success; otherwise -failed;
- */
- virtual DECODING_STATE EXTAPI DecodeFrame2 (const unsigned char* pSrc,
- const int iSrcLen,
- unsigned char** ppDst,
- SBufferInfo* pDstInfo) = 0;
-
-
- /**
- * @brief This function gets a decoded ready frame remaining in buffers after the last frame has been decoded.
- * Use GetOption with option DECODER_OPTION_NUM_OF_FRAMES_REMAINING_IN_BUFFER to get the number of frames remaining in buffers.
- * Note that it is only applicable for profile_idc != 66
- * @param ppDst buffer pointer of decoded data (YUV)
- * @param pDstInfo information provided to API(width, height, etc.)
- * @return 0 - success; otherwise -failed;
- */
- virtual DECODING_STATE EXTAPI FlushFrame (unsigned char** ppDst,
- SBufferInfo* pDstInfo) = 0;
-
- /**
- * @brief This function parse input bitstream only, and rewrite possible SVC syntax to AVC syntax
- * @param pSrc the h264 stream to be decoded
- * @param iSrcLen the length of h264 stream
- * @param pDstInfo bit stream info
- * @return 0 - success; otherwise -failed;
- */
- virtual DECODING_STATE EXTAPI DecodeParser (const unsigned char* pSrc,
- const int iSrcLen,
- SParserBsInfo* pDstInfo) = 0;
-
- /**
- * @brief This API does not work for now!! This is for future use to support non-I420 color format output.
- * @param pSrc the h264 stream to be decoded
- * @param iSrcLen the length of h264 stream
- * @param pDst buffer pointer of decoded data (YUV)
- * @param iDstStride output stride
- * @param iDstLen bit stream info
- * @param iWidth output width
- * @param iHeight output height
- * @param iColorFormat output color format
- * @return to do ...
- */
- virtual DECODING_STATE EXTAPI DecodeFrameEx (const unsigned char* pSrc,
- const int iSrcLen,
- unsigned char* pDst,
- int iDstStride,
- int& iDstLen,
- int& iWidth,
- int& iHeight,
- int& iColorFormat) = 0;
-
- /**
- * @brief Set option for decoder, detail option type, please refer to enumurate DECODER_OPTION.
- * @param pOption option for decoder such as OutDataFormat, Eos Flag, EC method, ...
- * @return CM_RETURN: 0 - success; otherwise - failed;
- */
- virtual long EXTAPI SetOption (DECODER_OPTION eOptionId, void* pOption) = 0;
-
- /**
- * @brief Get option for decoder, detail option type, please refer to enumurate DECODER_OPTION.
- * @param pOption option for decoder such as OutDataFormat, Eos Flag, EC method, ...
- * @return CM_RETURN: 0 - success; otherwise - failed;
- */
- virtual long EXTAPI GetOption (DECODER_OPTION eOptionId, void* pOption) = 0;
- virtual ~ISVCDecoder() {}
-};
-
-
-extern "C"
-{
-#else
-
-typedef struct ISVCEncoderVtbl ISVCEncoderVtbl;
-typedef const ISVCEncoderVtbl* ISVCEncoder;
-struct ISVCEncoderVtbl {
-
-int (*Initialize) (ISVCEncoder*, const SEncParamBase* pParam);
-int (*InitializeExt) (ISVCEncoder*, const SEncParamExt* pParam);
-
-int (*GetDefaultParams) (ISVCEncoder*, SEncParamExt* pParam);
-
-int (*Uninitialize) (ISVCEncoder*);
-
-int (*EncodeFrame) (ISVCEncoder*, const SSourcePicture* kpSrcPic, SFrameBSInfo* pBsInfo);
-int (*EncodeParameterSets) (ISVCEncoder*, SFrameBSInfo* pBsInfo);
-
-int (*ForceIntraFrame) (ISVCEncoder*, bool bIDR);
-
-int (*SetOption) (ISVCEncoder*, ENCODER_OPTION eOptionId, void* pOption);
-int (*GetOption) (ISVCEncoder*, ENCODER_OPTION eOptionId, void* pOption);
-};
-
-typedef struct ISVCDecoderVtbl ISVCDecoderVtbl;
-typedef const ISVCDecoderVtbl* ISVCDecoder;
-struct ISVCDecoderVtbl {
-long (*Initialize) (ISVCDecoder*, const SDecodingParam* pParam);
-long (*Uninitialize) (ISVCDecoder*);
-
-DECODING_STATE (*DecodeFrame) (ISVCDecoder*, const unsigned char* pSrc,
- const int iSrcLen,
- unsigned char** ppDst,
- int* pStride,
- int* iWidth,
- int* iHeight);
-
-DECODING_STATE (*DecodeFrameNoDelay) (ISVCDecoder*, const unsigned char* pSrc,
- const int iSrcLen,
- unsigned char** ppDst,
- SBufferInfo* pDstInfo);
-
-DECODING_STATE (*DecodeFrame2) (ISVCDecoder*, const unsigned char* pSrc,
- const int iSrcLen,
- unsigned char** ppDst,
- SBufferInfo* pDstInfo);
-
-DECODING_STATE (*FlushFrame) (ISVCDecoder*, unsigned char** ppDst,
- SBufferInfo* pDstInfo);
-
-DECODING_STATE (*DecodeParser) (ISVCDecoder*, const unsigned char* pSrc,
- const int iSrcLen,
- SParserBsInfo* pDstInfo);
-
-DECODING_STATE (*DecodeFrameEx) (ISVCDecoder*, const unsigned char* pSrc,
- const int iSrcLen,
- unsigned char* pDst,
- int iDstStride,
- int* iDstLen,
- int* iWidth,
- int* iHeight,
- int* iColorFormat);
-
-long (*SetOption) (ISVCDecoder*, DECODER_OPTION eOptionId, void* pOption);
-long (*GetOption) (ISVCDecoder*, DECODER_OPTION eOptionId, void* pOption);
-};
-#endif
-
-typedef void (*WelsTraceCallback) (void* ctx, int level, const char* string);
-
-/** @brief Create encoder
- * @param ppEncoder encoder
- * @return 0 - success; otherwise - failed;
-*/
-int WelsCreateSVCEncoder (ISVCEncoder** ppEncoder);
-
-
-/** @brief Destroy encoder
-* @param pEncoder encoder
- * @return void
-*/
-void WelsDestroySVCEncoder (ISVCEncoder* pEncoder);
-
-
-/** @brief Get the capability of decoder
- * @param pDecCapability decoder capability
- * @return 0 - success; otherwise - failed;
-*/
-int WelsGetDecoderCapability (SDecoderCapability* pDecCapability);
-
-
-/** @brief Create decoder
- * @param ppDecoder decoder
- * @return 0 - success; otherwise - failed;
-*/
-long WelsCreateDecoder (ISVCDecoder** ppDecoder);
-
-
-/** @brief Destroy decoder
- * @param pDecoder decoder
- * @return void
-*/
-void WelsDestroyDecoder (ISVCDecoder* pDecoder);
-
-/** @brief Get codec version
- * Note, old versions of Mingw (GCC < 4.7) are buggy and use an
- * incorrect/different ABI for calling this function, making it
- * incompatible with MSVC builds.
- * @return The linked codec version
-*/
-OpenH264Version WelsGetCodecVersion (void);
-
-/** @brief Get codec version
- * @param pVersion struct to fill in with the version
-*/
-void WelsGetCodecVersionEx (OpenH264Version* pVersion);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif//WELS_VIDEO_CODEC_SVC_API_H__
+/*!
+ *@page License
+ *
+ * \copy
+ * Copyright (c) 2013, Cisco Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef WELS_VIDEO_CODEC_SVC_API_H__
+#define WELS_VIDEO_CODEC_SVC_API_H__
+
+#ifndef __cplusplus
+#if defined(_MSC_VER) && (_MSC_VER < 1800)
+typedef unsigned char bool;
+#else
+#include <stdbool.h>
+#endif
+#endif
+
+#include "codec_app_def.h"
+#include "codec_def.h"
+
+#if defined(_WIN32) || defined(__cdecl)
+#define EXTAPI __cdecl
+#else
+#define EXTAPI
+#endif
+
+/**
+ * @file codec_api.h
+*/
+
+/**
+ * @page Overview
+ * * This page is for openh264 codec API usage.
+ * * For how to use the encoder,please refer to page UsageExampleForEncoder
+ * * For how to use the decoder,please refer to page UsageExampleForDecoder
+ * * For more detail about ISVEncoder,please refer to page ISVCEnoder
+ * * For more detail about ISVDecoder,please refer to page ISVCDecoder
+*/
+
+/**
+ * @page DecoderUsageExample
+ *
+ * @brief
+ * * An example for using the decoder for Decoding only or Parsing only
+ *
+ * Step 1:decoder declaration
+ * @code
+ *
+ * //decoder declaration
+ * ISVCDecoder *pSvcDecoder;
+ * //input: encoded bitstream start position; should include start code prefix
+ * unsigned char *pBuf =...;
+ * //input: encoded bit stream length; should include the size of start code prefix
+ * int iSize =...;
+ * //output: [0~2] for Y,U,V buffer for Decoding only
+ * unsigned char *pData[3] =...;
+ * //in-out: for Decoding only: declare and initialize the output buffer info, this should never co-exist with Parsing only
+ * SBufferInfo sDstBufInfo;
+ * memset(&sDstBufInfo, 0, sizeof(SBufferInfo));
+ * //in-out: for Parsing only: declare and initialize the output bitstream buffer info for parse only, this should never co-exist with Decoding only
+ * SParserBsInfo sDstParseInfo;
+ * memset(&sDstParseInfo, 0, sizeof(SParserBsInfo));
+ * sDstParseInfo.pDstBuff = new unsigned char[PARSE_SIZE]; //In Parsing only, allocate enough buffer to save transcoded bitstream for a frame
+ *
+ * @endcode
+ *
+ * Step 2:decoder creation
+ * @code
+ * CreateDecoder(pSvcDecoder);
+ * @endcode
+ *
+ * Step 3:declare required parameter, used to differentiate Decoding only and Parsing only
+ * @code
+ * SDecodingParam sDecParam = {0};
+ * sDecParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_AVC;
+ * //for Parsing only, the assignment is mandatory
+ * sDecParam.bParseOnly = true;
+ * @endcode
+ *
+ * Step 4:initialize the parameter and decoder context, allocate memory
+ * @code
+ * Initialize(&sDecParam);
+ * @endcode
+ *
+ * Step 5:do actual decoding process in slice level;
+ * this can be done in a loop until data ends
+ * @code
+ * //for Decoding only
+ * iRet = DecodeFrameNoDelay(pBuf, iSize, pData, &sDstBufInfo);
+ * //or
+ * iRet = DecodeFrame2(pBuf, iSize, pData, &sDstBufInfo);
+ * //for Parsing only
+ * iRet = DecodeParser(pBuf, iSize, &sDstParseInfo);
+ * //decode failed
+ * If (iRet != 0){
+ * RequestIDR or something like that.
+ * }
+ * //for Decoding only, pData can be used for render.
+ * if (sDstBufInfo.iBufferStatus==1){
+ * output pData[0], pData[1], pData[2];
+ * }
+ * //for Parsing only, sDstParseInfo can be used for, e.g., HW decoding
+ * if (sDstBufInfo.iNalNum > 0){
+ * Hardware decoding sDstParseInfo;
+ * }
+ * //no-delay decoding can be realized by directly calling DecodeFrameNoDelay(), which is the recommended usage.
+ * //no-delay decoding can also be realized by directly calling DecodeFrame2() again with NULL input, as in the following. In this case, decoder would immediately reconstruct the input data. This can also be used similarly for Parsing only. Consequent decoding error and output indication should also be considered as above.
+ * iRet = DecodeFrame2(NULL, 0, pData, &sDstBufInfo);
+ * judge iRet, sDstBufInfo.iBufferStatus ...
+ * @endcode
+ *
+ * Step 6:uninitialize the decoder and memory free
+ * @code
+ * Uninitialize();
+ * @endcode
+ *
+ * Step 7:destroy the decoder
+ * @code
+ * DestroyDecoder();
+ * @endcode
+ *
+*/
+
+/**
+ * @page EncoderUsageExample1
+ *
+ * @brief
+ * * An example for using encoder with basic parameter
+ *
+ * Step1:setup encoder
+ * @code
+ * int rv = WelsCreateSVCEncoder (&encoder_);
+ * ASSERT_EQ (0, rv);
+ * ASSERT_TRUE (encoder_ != NULL);
+ * @endcode
+ *
+ * Step2:initilize with basic parameter
+ * @code
+ * SEncParamBase param;
+ * memset (¶m, 0, sizeof (SEncParamBase));
+ * param.iUsageType = usageType;
+ * param.fMaxFrameRate = frameRate;
+ * param.iPicWidth = width;
+ * param.iPicHeight = height;
+ * param.iTargetBitrate = 5000000;
+ * encoder_->Initialize (¶m);
+ * @endcode
+ *
+ * Step3:set option, set option during encoding process
+ * @code
+ * encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &g_LevelSetting);
+ * int videoFormat = videoFormatI420;
+ * encoder_->SetOption (ENCODER_OPTION_DATAFORMAT, &videoFormat);
+ * @endcode
+ *
+ * Step4: encode and store ouput bistream
+ * @code
+ * int frameSize = width * height * 3 / 2;
+ * BufferedData buf;
+ * buf.SetLength (frameSize);
+ * ASSERT_TRUE (buf.Length() == (size_t)frameSize);
+ * SFrameBSInfo info;
+ * memset (&info, 0, sizeof (SFrameBSInfo));
+ * SSourcePicture pic;
+ * memset (&pic, 0, sizeof (SsourcePicture));
+ * pic.iPicWidth = width;
+ * pic.iPicHeight = height;
+ * pic.iColorFormat = videoFormatI420;
+ * pic.iStride[0] = pic.iPicWidth;
+ * pic.iStride[1] = pic.iStride[2] = pic.iPicWidth >> 1;
+ * pic.pData[0] = buf.data();
+ * pic.pData[1] = pic.pData[0] + width * height;
+ * pic.pData[2] = pic.pData[1] + (width * height >> 2);
+ * for(int num = 0;num<total_num;num++) {
+ * //prepare input data
+ * rv = encoder_->EncodeFrame (&pic, &info);
+ * ASSERT_TRUE (rv == cmResultSuccess);
+ * if (info.eFrameType != videoFrameTypeSkip && cbk != NULL) {
+ * //output bitstream
+ * }
+ * }
+ * @endcode
+ *
+ * Step5:teardown encoder
+ * @code
+ * if (encoder_) {
+ * encoder_->Uninitialize();
+ * WelsDestroySVCEncoder (encoder_);
+ * }
+ * @endcode
+ *
+ */
+
+/**
+ * @page EncoderUsageExample2
+ *
+ * @brief
+ * * An example for using the encoder with extension parameter.
+ * * The same operation on Step 1,3,4,5 with Example-1
+ *
+ * Step 2:initialize with extension parameter
+ * @code
+ * SEncParamExt param;
+ * encoder->GetDefaultParams (¶m);
+ * param.iUsageType = usageType;
+ * param.fMaxFrameRate = frameRate;
+ * param.iPicWidth = width;
+ * param.iPicHeight = height;
+ * param.iTargetBitrate = 5000000;
+ * param.bEnableDenoise = denoise;
+ * param.iSpatialLayerNum = layers;
+ * //SM_DYN_SLICE don't support multi-thread now
+ * if (sliceMode != SM_SINGLE_SLICE && sliceMode != SM_DYN_SLICE)
+ * param.iMultipleThreadIdc = 2;
+ *
+ * for (int i = 0; i < param.iSpatialLayerNum; i++) {
+ * param.sSpatialLayers[i].iVideoWidth = width >> (param.iSpatialLayerNum - 1 - i);
+ * param.sSpatialLayers[i].iVideoHeight = height >> (param.iSpatialLayerNum - 1 - i);
+ * param.sSpatialLayers[i].fFrameRate = frameRate;
+ * param.sSpatialLayers[i].iSpatialBitrate = param.iTargetBitrate;
+ *
+ * param.sSpatialLayers[i].sSliceCfg.uiSliceMode = sliceMode;
+ * if (sliceMode == SM_DYN_SLICE) {
+ * param.sSpatialLayers[i].sSliceCfg.sSliceArgument.uiSliceSizeConstraint = 600;
+ * param.uiMaxNalSize = 1500;
+ * }
+ * }
+ * param.iTargetBitrate *= param.iSpatialLayerNum;
+ * encoder_->InitializeExt (¶m);
+ * int videoFormat = videoFormatI420;
+ * encoder_->SetOption (ENCODER_OPTION_DATAFORMAT, &videoFormat);
+ *
+ * @endcode
+ */
+
+
+
+
+#ifdef __cplusplus
+/**
+* @brief Endocder definition
+*/
+class ISVCEncoder {
+ public:
+ /**
+ * @brief Initialize the encoder
+ * @param pParam basic encoder parameter
+ * @return CM_RETURN: 0 - success; otherwise - failed;
+ */
+ virtual int EXTAPI Initialize (const SEncParamBase* pParam) = 0;
+
+ /**
+ * @brief Initilaize encoder by using extension parameters.
+ * @param pParam extension parameter for encoder
+ * @return CM_RETURN: 0 - success; otherwise - failed;
+ */
+ virtual int EXTAPI InitializeExt (const SEncParamExt* pParam) = 0;
+
+ /**
+ * @brief Get the default extension parameters.
+ * If you want to change some parameters of encoder, firstly you need to get the default encoding parameters,
+ * after that you can change part of parameters you want to.
+ * @param pParam extension parameter for encoder
+ * @return CM_RETURN: 0 - success; otherwise - failed;
+ * */
+ virtual int EXTAPI GetDefaultParams (SEncParamExt* pParam) = 0;
+ /// uninitialize the encoder
+ virtual int EXTAPI Uninitialize() = 0;
+
+ /**
+ * @brief Encode one frame
+ * @param kpSrcPic the pointer to the source luminance plane
+ * chrominance data:
+ * CbData = kpSrc + m_iMaxPicWidth * m_iMaxPicHeight;
+ * CrData = CbData + (m_iMaxPicWidth * m_iMaxPicHeight)/4;
+ * the application calling this interface needs to ensure the data validation between the location
+ * @param pBsInfo output bit stream
+ * @return 0 - success; otherwise -failed;
+ */
+ virtual int EXTAPI EncodeFrame (const SSourcePicture* kpSrcPic, SFrameBSInfo* pBsInfo) = 0;
+
+ /**
+ * @brief Encode the parameters from output bit stream
+ * @param pBsInfo output bit stream
+ * @return 0 - success; otherwise - failed;
+ */
+ virtual int EXTAPI EncodeParameterSets (SFrameBSInfo* pBsInfo) = 0;
+
+ /**
+ * @brief Force encoder to encoder frame as IDR if bIDR set as true
+ * @param bIDR true: force encoder to encode frame as IDR frame;false, return 1 and nothing to do
+ * @return 0 - success; otherwise - failed;
+ */
+ virtual int EXTAPI ForceIntraFrame (bool bIDR, int iLayerId = -1) = 0;
+
+ /**
+ * @brief Set option for encoder, detail option type, please refer to enumurate ENCODER_OPTION.
+ * @param pOption option for encoder such as InDataFormat, IDRInterval, SVC Encode Param, Frame Rate, Bitrate,...
+ * @return CM_RETURN: 0 - success; otherwise - failed;
+ */
+ virtual int EXTAPI SetOption (ENCODER_OPTION eOptionId, void* pOption) = 0;
+
+ /**
+ * @brief Set option for encoder, detail option type, please refer to enumurate ENCODER_OPTION.
+ * @param pOption option for encoder such as InDataFormat, IDRInterval, SVC Encode Param, Frame Rate, Bitrate,...
+ * @return CM_RETURN: 0 - success; otherwise - failed;
+ */
+ virtual int EXTAPI GetOption (ENCODER_OPTION eOptionId, void* pOption) = 0;
+ virtual ~ISVCEncoder() {}
+};
+
+
+
+/**
+* @brief Decoder definition
+*/
+class ISVCDecoder {
+ public:
+
+ /**
+ * @brief Initilaize decoder
+ * @param pParam parameter for decoder
+ * @return 0 - success; otherwise - failed;
+ */
+ virtual long EXTAPI Initialize (const SDecodingParam* pParam) = 0;
+
+ /// Uninitialize the decoder
+ virtual long EXTAPI Uninitialize() = 0;
+
+ /**
+ * @brief Decode one frame
+ * @param pSrc the h264 stream to be decoded
+ * @param iSrcLen the length of h264 stream
+ * @param ppDst buffer pointer of decoded data (YUV)
+ * @param pStride output stride
+ * @param iWidth output width
+ * @param iHeight output height
+ * @return 0 - success; otherwise -failed;
+ */
+ virtual DECODING_STATE EXTAPI DecodeFrame (const unsigned char* pSrc,
+ const int iSrcLen,
+ unsigned char** ppDst,
+ int* pStride,
+ int& iWidth,
+ int& iHeight) = 0;
+
+ /**
+ * @brief For slice level DecodeFrameNoDelay() (4 parameters input),
+ * whatever the function return value is, the output data
+ * of I420 format will only be available when pDstInfo->iBufferStatus == 1,.
+ * This function will parse and reconstruct the input frame immediately if it is complete
+ * It is recommended as the main decoding function for H.264/AVC format input
+ * @param pSrc the h264 stream to be decoded
+ * @param iSrcLen the length of h264 stream
+ * @param ppDst buffer pointer of decoded data (YUV)
+ * @param pDstInfo information provided to API(width, height, etc.)
+ * @return 0 - success; otherwise -failed;
+ */
+ virtual DECODING_STATE EXTAPI DecodeFrameNoDelay (const unsigned char* pSrc,
+ const int iSrcLen,
+ unsigned char** ppDst,
+ SBufferInfo* pDstInfo) = 0;
+
+ /**
+ * @brief For slice level DecodeFrame2() (4 parameters input),
+ * whatever the function return value is, the output data
+ * of I420 format will only be available when pDstInfo->iBufferStatus == 1,.
+ * (e.g., in multi-slice cases, only when the whole picture
+ * is completely reconstructed, this variable would be set equal to 1.)
+ * @param pSrc the h264 stream to be decoded
+ * @param iSrcLen the length of h264 stream
+ * @param ppDst buffer pointer of decoded data (YUV)
+ * @param pDstInfo information provided to API(width, height, etc.)
+ * @return 0 - success; otherwise -failed;
+ */
+ virtual DECODING_STATE EXTAPI DecodeFrame2 (const unsigned char* pSrc,
+ const int iSrcLen,
+ unsigned char** ppDst,
+ SBufferInfo* pDstInfo) = 0;
+
+
+ /**
+ * @brief This function gets a decoded ready frame remaining in buffers after the last frame has been decoded.
+ * Use GetOption with option DECODER_OPTION_NUM_OF_FRAMES_REMAINING_IN_BUFFER to get the number of frames remaining in buffers.
+ * Note that it is only applicable for profile_idc != 66
+ * @param ppDst buffer pointer of decoded data (YUV)
+ * @param pDstInfo information provided to API(width, height, etc.)
+ * @return 0 - success; otherwise -failed;
+ */
+ virtual DECODING_STATE EXTAPI FlushFrame (unsigned char** ppDst,
+ SBufferInfo* pDstInfo) = 0;
+
+ /**
+ * @brief This function parse input bitstream only, and rewrite possible SVC syntax to AVC syntax
+ * @param pSrc the h264 stream to be decoded
+ * @param iSrcLen the length of h264 stream
+ * @param pDstInfo bit stream info
+ * @return 0 - success; otherwise -failed;
+ */
+ virtual DECODING_STATE EXTAPI DecodeParser (const unsigned char* pSrc,
+ const int iSrcLen,
+ SParserBsInfo* pDstInfo) = 0;
+
+ /**
+ * @brief This API does not work for now!! This is for future use to support non-I420 color format output.
+ * @param pSrc the h264 stream to be decoded
+ * @param iSrcLen the length of h264 stream
+ * @param pDst buffer pointer of decoded data (YUV)
+ * @param iDstStride output stride
+ * @param iDstLen bit stream info
+ * @param iWidth output width
+ * @param iHeight output height
+ * @param iColorFormat output color format
+ * @return to do ...
+ */
+ virtual DECODING_STATE EXTAPI DecodeFrameEx (const unsigned char* pSrc,
+ const int iSrcLen,
+ unsigned char* pDst,
+ int iDstStride,
+ int& iDstLen,
+ int& iWidth,
+ int& iHeight,
+ int& iColorFormat) = 0;
+
+ /**
+ * @brief Set option for decoder, detail option type, please refer to enumurate DECODER_OPTION.
+ * @param pOption option for decoder such as OutDataFormat, Eos Flag, EC method, ...
+ * @return CM_RETURN: 0 - success; otherwise - failed;
+ */
+ virtual long EXTAPI SetOption (DECODER_OPTION eOptionId, void* pOption) = 0;
+
+ /**
+ * @brief Get option for decoder, detail option type, please refer to enumurate DECODER_OPTION.
+ * @param pOption option for decoder such as OutDataFormat, Eos Flag, EC method, ...
+ * @return CM_RETURN: 0 - success; otherwise - failed;
+ */
+ virtual long EXTAPI GetOption (DECODER_OPTION eOptionId, void* pOption) = 0;
+ virtual ~ISVCDecoder() {}
+};
+
+
+extern "C"
+{
+#else
+
+typedef struct ISVCEncoderVtbl ISVCEncoderVtbl;
+typedef const ISVCEncoderVtbl* ISVCEncoder;
+struct ISVCEncoderVtbl {
+
+int (*Initialize) (ISVCEncoder*, const SEncParamBase* pParam);
+int (*InitializeExt) (ISVCEncoder*, const SEncParamExt* pParam);
+
+int (*GetDefaultParams) (ISVCEncoder*, SEncParamExt* pParam);
+
+int (*Uninitialize) (ISVCEncoder*);
+
+int (*EncodeFrame) (ISVCEncoder*, const SSourcePicture* kpSrcPic, SFrameBSInfo* pBsInfo);
+int (*EncodeParameterSets) (ISVCEncoder*, SFrameBSInfo* pBsInfo);
+
+int (*ForceIntraFrame) (ISVCEncoder*, bool bIDR);
+
+int (*SetOption) (ISVCEncoder*, ENCODER_OPTION eOptionId, void* pOption);
+int (*GetOption) (ISVCEncoder*, ENCODER_OPTION eOptionId, void* pOption);
+};
+
+typedef struct ISVCDecoderVtbl ISVCDecoderVtbl;
+typedef const ISVCDecoderVtbl* ISVCDecoder;
+struct ISVCDecoderVtbl {
+long (*Initialize) (ISVCDecoder*, const SDecodingParam* pParam);
+long (*Uninitialize) (ISVCDecoder*);
+
+DECODING_STATE (*DecodeFrame) (ISVCDecoder*, const unsigned char* pSrc,
+ const int iSrcLen,
+ unsigned char** ppDst,
+ int* pStride,
+ int* iWidth,
+ int* iHeight);
+
+DECODING_STATE (*DecodeFrameNoDelay) (ISVCDecoder*, const unsigned char* pSrc,
+ const int iSrcLen,
+ unsigned char** ppDst,
+ SBufferInfo* pDstInfo);
+
+DECODING_STATE (*DecodeFrame2) (ISVCDecoder*, const unsigned char* pSrc,
+ const int iSrcLen,
+ unsigned char** ppDst,
+ SBufferInfo* pDstInfo);
+
+DECODING_STATE (*FlushFrame) (ISVCDecoder*, unsigned char** ppDst,
+ SBufferInfo* pDstInfo);
+
+DECODING_STATE (*DecodeParser) (ISVCDecoder*, const unsigned char* pSrc,
+ const int iSrcLen,
+ SParserBsInfo* pDstInfo);
+
+DECODING_STATE (*DecodeFrameEx) (ISVCDecoder*, const unsigned char* pSrc,
+ const int iSrcLen,
+ unsigned char* pDst,
+ int iDstStride,
+ int* iDstLen,
+ int* iWidth,
+ int* iHeight,
+ int* iColorFormat);
+
+long (*SetOption) (ISVCDecoder*, DECODER_OPTION eOptionId, void* pOption);
+long (*GetOption) (ISVCDecoder*, DECODER_OPTION eOptionId, void* pOption);
+};
+#endif
+
+typedef void (*WelsTraceCallback) (void* ctx, int level, const char* string);
+
+/** @brief Create encoder
+ * @param ppEncoder encoder
+ * @return 0 - success; otherwise - failed;
+*/
+int WelsCreateSVCEncoder (ISVCEncoder** ppEncoder);
+
+
+/** @brief Destroy encoder
+* @param pEncoder encoder
+ * @return void
+*/
+void WelsDestroySVCEncoder (ISVCEncoder* pEncoder);
+
+
+/** @brief Get the capability of decoder
+ * @param pDecCapability decoder capability
+ * @return 0 - success; otherwise - failed;
+*/
+int WelsGetDecoderCapability (SDecoderCapability* pDecCapability);
+
+
+/** @brief Create decoder
+ * @param ppDecoder decoder
+ * @return 0 - success; otherwise - failed;
+*/
+long WelsCreateDecoder (ISVCDecoder** ppDecoder);
+
+
+/** @brief Destroy decoder
+ * @param pDecoder decoder
+ * @return void
+*/
+void WelsDestroyDecoder (ISVCDecoder* pDecoder);
+
+/** @brief Get codec version
+ * Note, old versions of Mingw (GCC < 4.7) are buggy and use an
+ * incorrect/different ABI for calling this function, making it
+ * incompatible with MSVC builds.
+ * @return The linked codec version
+*/
+OpenH264Version WelsGetCodecVersion (void);
+
+/** @brief Get codec version
+ * @param pVersion struct to fill in with the version
+*/
+void WelsGetCodecVersionEx (OpenH264Version* pVersion);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif//WELS_VIDEO_CODEC_SVC_API_H__
--- a/codec/console/dec/src/h264dec.cpp
+++ b/codec/console/dec/src/h264dec.cpp
@@ -1,520 +1,520 @@
-/*!
- * \copy
- * Copyright (c) 2004-2013, Cisco Systems
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * h264dec.cpp: Wels Decoder Console Implementation file
- */
-
-#if defined (_WIN32)
-#define _CRT_SECURE_NO_WARNINGS
-#include <windows.h>
-#include <tchar.h>
-#else
-#include <string.h>
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#if defined (ANDROID_NDK)
-#include <android/log.h>
-#endif
-#include "codec_def.h"
-#include "codec_app_def.h"
-#include "codec_api.h"
-#include "read_config.h"
-#include "typedefs.h"
-#include "measure_time.h"
-#include "d3d9_utils.h"
-
-
-using namespace std;
-
-#if defined (WINDOWS_PHONE)
-double g_dDecTime = 0.0;
-float g_fDecFPS = 0.0;
-int g_iDecodedFrameNum = 0;
-#endif
-
-#if defined(ANDROID_NDK)
-#define LOG_TAG "welsdec"
-#define LOGI(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
-#define printf LOGI
-#define fprintf(a, ...) LOGI(__VA_ARGS__)
-#endif
-//using namespace WelsDec;
-
-void H264DecodeInstance (ISVCDecoder* pDecoder, const char* kpH264FileName, const char* kpOuputFileName,
- int32_t& iWidth, int32_t& iHeight, const char* pOptionFileName, const char* pLengthFileName,
- int32_t iErrorConMethod,
- bool bLegacyCalling) {
- FILE* pH264File = NULL;
- FILE* pYuvFile = NULL;
- FILE* pOptionFile = NULL;
-// Lenght input mode support
- FILE* fpTrack = NULL;
-
- if (pDecoder == NULL) return;
-
- int32_t pInfo[4];
- unsigned long long uiTimeStamp = 0;
- int64_t iStart = 0, iEnd = 0, iTotal = 0;
- int32_t iSliceSize;
- int32_t iSliceIndex = 0;
- uint8_t* pBuf = NULL;
- uint8_t uiStartCode[4] = {0, 0, 0, 1};
-
- uint8_t* pData[3] = {NULL};
- uint8_t* pDst[3] = {NULL};
- SBufferInfo sDstBufInfo;
-
- int32_t iBufPos = 0;
- int32_t iFileSize;
- int32_t i = 0;
- int32_t iLastWidth = 0, iLastHeight = 0;
- int32_t iFrameCount = 0;
- int32_t iEndOfStreamFlag = 0;
- int32_t num_of_frames_in_buffer = 0;
- pDecoder->SetOption (DECODER_OPTION_ERROR_CON_IDC, &iErrorConMethod);
- CUtils cOutputModule;
- double dElapsed = 0;
-
- if (kpH264FileName) {
- pH264File = fopen (kpH264FileName, "rb");
- if (pH264File == NULL) {
- fprintf (stderr, "Can not open h264 source file, check its legal path related please..\n");
- return;
- }
- fprintf (stderr, "H264 source file name: %s..\n", kpH264FileName);
- } else {
- fprintf (stderr, "Can not find any h264 bitstream file to read..\n");
- fprintf (stderr, "----------------decoder return------------------------\n");
- return;
- }
-
- if (kpOuputFileName) {
- pYuvFile = fopen (kpOuputFileName, "wb");
- if (pYuvFile == NULL) {
- fprintf (stderr, "Can not open yuv file to output result of decoding..\n");
- // any options
- //return; // can let decoder work in quiet mode, no writing any output
- } else
- fprintf (stderr, "Sequence output file name: %s..\n", kpOuputFileName);
- } else {
- fprintf (stderr, "Can not find any output file to write..\n");
- // any options
- }
-
- if (pOptionFileName) {
- pOptionFile = fopen (pOptionFileName, "wb");
- if (pOptionFile == NULL) {
- fprintf (stderr, "Can not open optional file for write..\n");
- } else
- fprintf (stderr, "Extra optional file: %s..\n", pOptionFileName);
- }
-
- if (pLengthFileName != NULL) {
- fpTrack = fopen (pLengthFileName, "rb");
- if (fpTrack == NULL)
- printf ("Length file open ERROR!\n");
- }
-
- printf ("------------------------------------------------------\n");
-
- fseek (pH264File, 0L, SEEK_END);
- iFileSize = (int32_t) ftell (pH264File);
- if (iFileSize <= 0) {
- fprintf (stderr, "Current Bit Stream File is too small, read error!!!!\n");
- goto label_exit;
- }
- fseek (pH264File, 0L, SEEK_SET);
-
- pBuf = new uint8_t[iFileSize + 4];
- if (pBuf == NULL) {
- fprintf (stderr, "new buffer failed!\n");
- goto label_exit;
- }
-
- if (fread (pBuf, 1, iFileSize, pH264File) != (uint32_t)iFileSize) {
- fprintf (stderr, "Unable to read whole file\n");
- goto label_exit;
- }
-
- memcpy (pBuf + iFileSize, &uiStartCode[0], 4); //confirmed_safe_unsafe_usage
-
- while (true) {
-
- if (iBufPos >= iFileSize) {
- iEndOfStreamFlag = true;
- if (iEndOfStreamFlag)
- pDecoder->SetOption (DECODER_OPTION_END_OF_STREAM, (void*)&iEndOfStreamFlag);
- break;
- }
-// Read length from file if needed
- if (fpTrack) {
- if (fread (pInfo, 4, sizeof (int32_t), fpTrack) < 4)
- goto label_exit;
- iSliceSize = static_cast<int32_t> (pInfo[2]);
- } else {
- for (i = 0; i < iFileSize; i++) {
- if ((pBuf[iBufPos + i] == 0 && pBuf[iBufPos + i + 1] == 0 && pBuf[iBufPos + i + 2] == 0 && pBuf[iBufPos + i + 3] == 1
- && i > 0) || (pBuf[iBufPos + i] == 0 && pBuf[iBufPos + i + 1] == 0 && pBuf[iBufPos + i + 2] == 1 && i > 0)) {
- break;
- }
- }
- iSliceSize = i;
- }
- if (iSliceSize < 4) { //too small size, no effective data, ignore
- iBufPos += iSliceSize;
- continue;
- }
-
-//for coverage test purpose
- int32_t iEndOfStreamFlag;
- pDecoder->GetOption (DECODER_OPTION_END_OF_STREAM, &iEndOfStreamFlag);
- int32_t iCurIdrPicId;
- pDecoder->GetOption (DECODER_OPTION_IDR_PIC_ID, &iCurIdrPicId);
- int32_t iFrameNum;
- pDecoder->GetOption (DECODER_OPTION_FRAME_NUM, &iFrameNum);
- int32_t bCurAuContainLtrMarkSeFlag;
- pDecoder->GetOption (DECODER_OPTION_LTR_MARKING_FLAG, &bCurAuContainLtrMarkSeFlag);
- int32_t iFrameNumOfAuMarkedLtr;
- pDecoder->GetOption (DECODER_OPTION_LTR_MARKED_FRAME_NUM, &iFrameNumOfAuMarkedLtr);
- int32_t iFeedbackVclNalInAu;
- pDecoder->GetOption (DECODER_OPTION_VCL_NAL, &iFeedbackVclNalInAu);
- int32_t iFeedbackTidInAu;
- pDecoder->GetOption (DECODER_OPTION_TEMPORAL_ID, &iFeedbackTidInAu);
-//~end for
-
- iStart = WelsTime();
- pData[0] = NULL;
- pData[1] = NULL;
- pData[2] = NULL;
- uiTimeStamp ++;
- memset (&sDstBufInfo, 0, sizeof (SBufferInfo));
- sDstBufInfo.uiInBsTimeStamp = uiTimeStamp;
- if (!bLegacyCalling) {
- pDecoder->DecodeFrameNoDelay (pBuf + iBufPos, iSliceSize, pData, &sDstBufInfo);
- } else {
- pDecoder->DecodeFrame2 (pBuf + iBufPos, iSliceSize, pData, &sDstBufInfo);
- }
-
- if (sDstBufInfo.iBufferStatus == 1) {
- pDst[0] = pData[0];
- pDst[1] = pData[1];
- pDst[2] = pData[2];
- }
- iEnd = WelsTime();
- iTotal += iEnd - iStart;
- if (sDstBufInfo.iBufferStatus == 1) {
- cOutputModule.Process ((void**)pDst, &sDstBufInfo, pYuvFile);
- iWidth = sDstBufInfo.UsrData.sSystemBuffer.iWidth;
- iHeight = sDstBufInfo.UsrData.sSystemBuffer.iHeight;
-
- if (pOptionFile != NULL) {
- if (iWidth != iLastWidth && iHeight != iLastHeight) {
- fwrite (&iFrameCount, sizeof (iFrameCount), 1, pOptionFile);
- fwrite (&iWidth, sizeof (iWidth), 1, pOptionFile);
- fwrite (&iHeight, sizeof (iHeight), 1, pOptionFile);
- iLastWidth = iWidth;
- iLastHeight = iHeight;
- }
- }
- ++ iFrameCount;
- }
-
- if (bLegacyCalling) {
- iStart = WelsTime();
- pData[0] = NULL;
- pData[1] = NULL;
- pData[2] = NULL;
- memset (&sDstBufInfo, 0, sizeof (SBufferInfo));
- sDstBufInfo.uiInBsTimeStamp = uiTimeStamp;
- pDecoder->DecodeFrame2 (NULL, 0, pData, &sDstBufInfo);
- if (sDstBufInfo.iBufferStatus == 1) {
- pDst[0] = pData[0];
- pDst[1] = pData[1];
- pDst[2] = pData[2];
- }
- iEnd = WelsTime();
- iTotal += iEnd - iStart;
- if (sDstBufInfo.iBufferStatus == 1) {
- cOutputModule.Process ((void**)pDst, &sDstBufInfo, pYuvFile);
- iWidth = sDstBufInfo.UsrData.sSystemBuffer.iWidth;
- iHeight = sDstBufInfo.UsrData.sSystemBuffer.iHeight;
-
- if (pOptionFile != NULL) {
- if (iWidth != iLastWidth && iHeight != iLastHeight) {
- fwrite (&iFrameCount, sizeof (iFrameCount), 1, pOptionFile);
- fwrite (&iWidth, sizeof (iWidth), 1, pOptionFile);
- fwrite (&iHeight, sizeof (iHeight), 1, pOptionFile);
- iLastWidth = iWidth;
- iLastHeight = iHeight;
- }
- }
- ++ iFrameCount;
- }
- }
- iBufPos += iSliceSize;
- ++ iSliceIndex;
- }
-
- pDecoder->GetOption (DECODER_OPTION_NUM_OF_FRAMES_REMAINING_IN_BUFFER, &num_of_frames_in_buffer);
- for (int32_t i = 0; i < num_of_frames_in_buffer; ++i) {
- iStart = WelsTime();
- pData[0] = NULL;
- pData[1] = NULL;
- pData[2] = NULL;
- memset (&sDstBufInfo, 0, sizeof (SBufferInfo));
- sDstBufInfo.uiInBsTimeStamp = uiTimeStamp;
- sDstBufInfo.iBufferStatus = 1;
- pDecoder->FlushFrame (pData, &sDstBufInfo);
- if (sDstBufInfo.iBufferStatus == 1) {
- pDst[0] = pData[0];
- pDst[1] = pData[1];
- pDst[2] = pData[2];
- }
- iEnd = WelsTime();
- iTotal += iEnd - iStart;
- if (sDstBufInfo.iBufferStatus == 1) {
- cOutputModule.Process ((void**)pDst, &sDstBufInfo, pYuvFile);
- iWidth = sDstBufInfo.UsrData.sSystemBuffer.iWidth;
- iHeight = sDstBufInfo.UsrData.sSystemBuffer.iHeight;
-
- if (pOptionFile != NULL) {
- if (iWidth != iLastWidth && iHeight != iLastHeight) {
- fwrite (&iFrameCount, sizeof (iFrameCount), 1, pOptionFile);
- fwrite (&iWidth, sizeof (iWidth), 1, pOptionFile);
- fwrite (&iHeight, sizeof (iHeight), 1, pOptionFile);
- iLastWidth = iWidth;
- iLastHeight = iHeight;
- }
- }
- ++iFrameCount;
- }
- }
- dElapsed = iTotal / 1e6;
- fprintf (stderr, "-------------------------------------------------------\n");
- fprintf (stderr, "iWidth:\t\t%d\nheight:\t\t%d\nFrames:\t\t%d\ndecode time:\t%f sec\nFPS:\t\t%f fps\n",
- iWidth, iHeight, iFrameCount, dElapsed, (iFrameCount * 1.0) / dElapsed);
- fprintf (stderr, "-------------------------------------------------------\n");
-
-#if defined (WINDOWS_PHONE)
- g_dDecTime = dElapsed;
- g_fDecFPS = (iFrameCount * 1.0f) / (float) dElapsed;
- g_iDecodedFrameNum = iFrameCount;
-#endif
-
- // coverity scan uninitial
-label_exit:
- if (pBuf) {
- delete[] pBuf;
- pBuf = NULL;
- }
- if (pH264File) {
- fclose (pH264File);
- pH264File = NULL;
- }
- if (pYuvFile) {
- fclose (pYuvFile);
- pYuvFile = NULL;
- }
- if (pOptionFile) {
- fclose (pOptionFile);
- pOptionFile = NULL;
- }
- if (fpTrack) {
- fclose (fpTrack);
- fpTrack = NULL;
- }
-
-}
-
-#if (defined(ANDROID_NDK)||defined(APPLE_IOS) || defined (WINDOWS_PHONE))
-int32_t DecMain (int32_t iArgC, char* pArgV[]) {
-#else
-int32_t main (int32_t iArgC, char* pArgV[]) {
-#endif
- ISVCDecoder* pDecoder = NULL;
-
- SDecodingParam sDecParam = {0};
- string strInputFile (""), strOutputFile (""), strOptionFile (""), strLengthFile ("");
- int iLevelSetting = (int) WELS_LOG_WARNING;
- bool bLegacyCalling = false;
-
- sDecParam.sVideoProperty.size = sizeof (sDecParam.sVideoProperty);
- sDecParam.eEcActiveIdc = ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE;
-
- if (iArgC < 2) {
- printf ("usage 1: h264dec.exe welsdec.cfg\n");
- printf ("usage 2: h264dec.exe welsdec.264 out.yuv\n");
- printf ("usage 3: h264dec.exe welsdec.264\n");
- return 1;
- } else if (iArgC == 2) {
- if (strstr (pArgV[1], ".cfg")) { // read config file //confirmed_safe_unsafe_usage
- CReadConfig cReadCfg (pArgV[1]);
- string strTag[4];
- string strReconFile ("");
-
- if (!cReadCfg.ExistFile()) {
- printf ("Specified file: %s not exist, maybe invalid path or parameter settting.\n", cReadCfg.GetFileName().c_str());
- return 1;
- }
-
- while (!cReadCfg.EndOfFile()) {
- long nRd = cReadCfg.ReadLine (&strTag[0]);
- if (nRd > 0) {
- if (strTag[0].compare ("InputFile") == 0) {
- strInputFile = strTag[1];
- } else if (strTag[0].compare ("OutputFile") == 0) {
- strOutputFile = strTag[1];
- } else if (strTag[0].compare ("RestructionFile") == 0) {
- strReconFile = strTag[1];
- int32_t iLen = (int32_t)strReconFile.length();
- sDecParam.pFileNameRestructed = new char[iLen + 1];
- if (sDecParam.pFileNameRestructed != NULL) {
- sDecParam.pFileNameRestructed[iLen] = 0;
- }
-
- strncpy (sDecParam.pFileNameRestructed, strReconFile.c_str(), iLen); //confirmed_safe_unsafe_usage
- } else if (strTag[0].compare ("TargetDQID") == 0) {
- sDecParam.uiTargetDqLayer = (uint8_t)atol (strTag[1].c_str());
- } else if (strTag[0].compare ("ErrorConcealmentIdc") == 0) {
- sDecParam.eEcActiveIdc = (ERROR_CON_IDC)atol (strTag[1].c_str());
- } else if (strTag[0].compare ("CPULoad") == 0) {
- sDecParam.uiCpuLoad = (uint32_t)atol (strTag[1].c_str());
- } else if (strTag[0].compare ("VideoBitstreamType") == 0) {
- sDecParam.sVideoProperty.eVideoBsType = (VIDEO_BITSTREAM_TYPE)atol (strTag[1].c_str());
- }
- }
- }
- if (strOutputFile.empty()) {
- printf ("No output file specified in configuration file.\n");
- return 1;
- }
- } else if (strstr (pArgV[1],
- ".264")) { // no output dump yuv file, just try to render the decoded pictures //confirmed_safe_unsafe_usage
- strInputFile = pArgV[1];
- sDecParam.uiTargetDqLayer = (uint8_t) - 1;
- sDecParam.eEcActiveIdc = ERROR_CON_SLICE_COPY;
- sDecParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT;
- }
- } else { //iArgC > 2
- strInputFile = pArgV[1];
- strOutputFile = pArgV[2];
- sDecParam.uiTargetDqLayer = (uint8_t) - 1;
- sDecParam.eEcActiveIdc = ERROR_CON_SLICE_COPY;
- sDecParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT;
- if (iArgC > 3) {
- for (int i = 3; i < iArgC; i++) {
- char* cmd = pArgV[i];
-
- if (!strcmp (cmd, "-options")) {
- if (i + 1 < iArgC)
- strOptionFile = pArgV[++i];
- else {
- printf ("options file not specified.\n");
- return 1;
- }
- } else if (!strcmp (cmd, "-trace")) {
- if (i + 1 < iArgC)
- iLevelSetting = atoi (pArgV[++i]);
- else {
- printf ("trace level not specified.\n");
- return 1;
- }
- } else if (!strcmp (cmd, "-length")) {
- if (i + 1 < iArgC)
- strLengthFile = pArgV[++i];
- else {
- printf ("lenght file not specified.\n");
- return 1;
- }
- } else if (!strcmp (cmd, "-ec")) {
- if (i + 1 < iArgC) {
- int iEcActiveIdc = atoi (pArgV[++i]);
- sDecParam.eEcActiveIdc = (ERROR_CON_IDC)iEcActiveIdc;
- printf ("ERROR_CON(cealment) is set to %d.\n", iEcActiveIdc);
- }
- } else if (!strcmp (cmd, "-legacy")) {
- bLegacyCalling = true;
- }
- }
- }
-
- if (strOutputFile.empty()) {
- printf ("No output file specified in configuration file.\n");
- return 1;
- }
- }
-
- if (strInputFile.empty()) {
- printf ("No input file specified in configuration file.\n");
- return 1;
- }
-
-
-
-
- if (WelsCreateDecoder (&pDecoder) || (NULL == pDecoder)) {
- printf ("Create Decoder failed.\n");
- return 1;
- }
- if (iLevelSetting >= 0) {
- pDecoder->SetOption (DECODER_OPTION_TRACE_LEVEL, &iLevelSetting);
- }
-
- if (pDecoder->Initialize (&sDecParam)) {
- printf ("Decoder initialization failed.\n");
- return 1;
- }
-
-
- int32_t iWidth = 0;
- int32_t iHeight = 0;
-
-
- H264DecodeInstance (pDecoder, strInputFile.c_str(), !strOutputFile.empty() ? strOutputFile.c_str() : NULL, iWidth,
- iHeight,
- (!strOptionFile.empty() ? strOptionFile.c_str() : NULL), (!strLengthFile.empty() ? strLengthFile.c_str() : NULL),
- (int32_t)sDecParam.eEcActiveIdc,
- bLegacyCalling);
-
- if (sDecParam.pFileNameRestructed != NULL) {
- delete []sDecParam.pFileNameRestructed;
- sDecParam.pFileNameRestructed = NULL;
- }
-
- if (pDecoder) {
- pDecoder->Uninitialize();
-
- WelsDestroyDecoder (pDecoder);
- }
-
- return 0;
-}
+/*!
+ * \copy
+ * Copyright (c) 2004-2013, Cisco Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * h264dec.cpp: Wels Decoder Console Implementation file
+ */
+
+#if defined (_WIN32)
+#define _CRT_SECURE_NO_WARNINGS
+#include <windows.h>
+#include <tchar.h>
+#else
+#include <string.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#if defined (ANDROID_NDK)
+#include <android/log.h>
+#endif
+#include "codec_def.h"
+#include "codec_app_def.h"
+#include "codec_api.h"
+#include "read_config.h"
+#include "typedefs.h"
+#include "measure_time.h"
+#include "d3d9_utils.h"
+
+
+using namespace std;
+
+#if defined (WINDOWS_PHONE)
+double g_dDecTime = 0.0;
+float g_fDecFPS = 0.0;
+int g_iDecodedFrameNum = 0;
+#endif
+
+#if defined(ANDROID_NDK)
+#define LOG_TAG "welsdec"
+#define LOGI(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
+#define printf LOGI
+#define fprintf(a, ...) LOGI(__VA_ARGS__)
+#endif
+//using namespace WelsDec;
+
+void H264DecodeInstance (ISVCDecoder* pDecoder, const char* kpH264FileName, const char* kpOuputFileName,
+ int32_t& iWidth, int32_t& iHeight, const char* pOptionFileName, const char* pLengthFileName,
+ int32_t iErrorConMethod,
+ bool bLegacyCalling) {
+ FILE* pH264File = NULL;
+ FILE* pYuvFile = NULL;
+ FILE* pOptionFile = NULL;
+// Lenght input mode support
+ FILE* fpTrack = NULL;
+
+ if (pDecoder == NULL) return;
+
+ int32_t pInfo[4];
+ unsigned long long uiTimeStamp = 0;
+ int64_t iStart = 0, iEnd = 0, iTotal = 0;
+ int32_t iSliceSize;
+ int32_t iSliceIndex = 0;
+ uint8_t* pBuf = NULL;
+ uint8_t uiStartCode[4] = {0, 0, 0, 1};
+
+ uint8_t* pData[3] = {NULL};
+ uint8_t* pDst[3] = {NULL};
+ SBufferInfo sDstBufInfo;
+
+ int32_t iBufPos = 0;
+ int32_t iFileSize;
+ int32_t i = 0;
+ int32_t iLastWidth = 0, iLastHeight = 0;
+ int32_t iFrameCount = 0;
+ int32_t iEndOfStreamFlag = 0;
+ int32_t num_of_frames_in_buffer = 0;
+ pDecoder->SetOption (DECODER_OPTION_ERROR_CON_IDC, &iErrorConMethod);
+ CUtils cOutputModule;
+ double dElapsed = 0;
+
+ if (kpH264FileName) {
+ pH264File = fopen (kpH264FileName, "rb");
+ if (pH264File == NULL) {
+ fprintf (stderr, "Can not open h264 source file, check its legal path related please..\n");
+ return;
+ }
+ fprintf (stderr, "H264 source file name: %s..\n", kpH264FileName);
+ } else {
+ fprintf (stderr, "Can not find any h264 bitstream file to read..\n");
+ fprintf (stderr, "----------------decoder return------------------------\n");
+ return;
+ }
+
+ if (kpOuputFileName) {
+ pYuvFile = fopen (kpOuputFileName, "wb");
+ if (pYuvFile == NULL) {
+ fprintf (stderr, "Can not open yuv file to output result of decoding..\n");
+ // any options
+ //return; // can let decoder work in quiet mode, no writing any output
+ } else
+ fprintf (stderr, "Sequence output file name: %s..\n", kpOuputFileName);
+ } else {
+ fprintf (stderr, "Can not find any output file to write..\n");
+ // any options
+ }
+
+ if (pOptionFileName) {
+ pOptionFile = fopen (pOptionFileName, "wb");
+ if (pOptionFile == NULL) {
+ fprintf (stderr, "Can not open optional file for write..\n");
+ } else
+ fprintf (stderr, "Extra optional file: %s..\n", pOptionFileName);
+ }
+
+ if (pLengthFileName != NULL) {
+ fpTrack = fopen (pLengthFileName, "rb");
+ if (fpTrack == NULL)
+ printf ("Length file open ERROR!\n");
+ }
+
+ printf ("------------------------------------------------------\n");
+
+ fseek (pH264File, 0L, SEEK_END);
+ iFileSize = (int32_t) ftell (pH264File);
+ if (iFileSize <= 0) {
+ fprintf (stderr, "Current Bit Stream File is too small, read error!!!!\n");
+ goto label_exit;
+ }
+ fseek (pH264File, 0L, SEEK_SET);
+
+ pBuf = new uint8_t[iFileSize + 4];
+ if (pBuf == NULL) {
+ fprintf (stderr, "new buffer failed!\n");
+ goto label_exit;
+ }
+
+ if (fread (pBuf, 1, iFileSize, pH264File) != (uint32_t)iFileSize) {
+ fprintf (stderr, "Unable to read whole file\n");
+ goto label_exit;
+ }
+
+ memcpy (pBuf + iFileSize, &uiStartCode[0], 4); //confirmed_safe_unsafe_usage
+
+ while (true) {
+
+ if (iBufPos >= iFileSize) {
+ iEndOfStreamFlag = true;
+ if (iEndOfStreamFlag)
+ pDecoder->SetOption (DECODER_OPTION_END_OF_STREAM, (void*)&iEndOfStreamFlag);
+ break;
+ }
+// Read length from file if needed
+ if (fpTrack) {
+ if (fread (pInfo, 4, sizeof (int32_t), fpTrack) < 4)
+ goto label_exit;
+ iSliceSize = static_cast<int32_t> (pInfo[2]);
+ } else {
+ for (i = 0; i < iFileSize; i++) {
+ if ((pBuf[iBufPos + i] == 0 && pBuf[iBufPos + i + 1] == 0 && pBuf[iBufPos + i + 2] == 0 && pBuf[iBufPos + i + 3] == 1
+ && i > 0) || (pBuf[iBufPos + i] == 0 && pBuf[iBufPos + i + 1] == 0 && pBuf[iBufPos + i + 2] == 1 && i > 0)) {
+ break;
+ }
+ }
+ iSliceSize = i;
+ }
+ if (iSliceSize < 4) { //too small size, no effective data, ignore
+ iBufPos += iSliceSize;
+ continue;
+ }
+
+//for coverage test purpose
+ int32_t iEndOfStreamFlag;
+ pDecoder->GetOption (DECODER_OPTION_END_OF_STREAM, &iEndOfStreamFlag);
+ int32_t iCurIdrPicId;
+ pDecoder->GetOption (DECODER_OPTION_IDR_PIC_ID, &iCurIdrPicId);
+ int32_t iFrameNum;
+ pDecoder->GetOption (DECODER_OPTION_FRAME_NUM, &iFrameNum);
+ int32_t bCurAuContainLtrMarkSeFlag;
+ pDecoder->GetOption (DECODER_OPTION_LTR_MARKING_FLAG, &bCurAuContainLtrMarkSeFlag);
+ int32_t iFrameNumOfAuMarkedLtr;
+ pDecoder->GetOption (DECODER_OPTION_LTR_MARKED_FRAME_NUM, &iFrameNumOfAuMarkedLtr);
+ int32_t iFeedbackVclNalInAu;
+ pDecoder->GetOption (DECODER_OPTION_VCL_NAL, &iFeedbackVclNalInAu);
+ int32_t iFeedbackTidInAu;
+ pDecoder->GetOption (DECODER_OPTION_TEMPORAL_ID, &iFeedbackTidInAu);
+//~end for
+
+ iStart = WelsTime();
+ pData[0] = NULL;
+ pData[1] = NULL;
+ pData[2] = NULL;
+ uiTimeStamp ++;
+ memset (&sDstBufInfo, 0, sizeof (SBufferInfo));
+ sDstBufInfo.uiInBsTimeStamp = uiTimeStamp;
+ if (!bLegacyCalling) {
+ pDecoder->DecodeFrameNoDelay (pBuf + iBufPos, iSliceSize, pData, &sDstBufInfo);
+ } else {
+ pDecoder->DecodeFrame2 (pBuf + iBufPos, iSliceSize, pData, &sDstBufInfo);
+ }
+
+ if (sDstBufInfo.iBufferStatus == 1) {
+ pDst[0] = pData[0];
+ pDst[1] = pData[1];
+ pDst[2] = pData[2];
+ }
+ iEnd = WelsTime();
+ iTotal += iEnd - iStart;
+ if (sDstBufInfo.iBufferStatus == 1) {
+ cOutputModule.Process ((void**)pDst, &sDstBufInfo, pYuvFile);
+ iWidth = sDstBufInfo.UsrData.sSystemBuffer.iWidth;
+ iHeight = sDstBufInfo.UsrData.sSystemBuffer.iHeight;
+
+ if (pOptionFile != NULL) {
+ if (iWidth != iLastWidth && iHeight != iLastHeight) {
+ fwrite (&iFrameCount, sizeof (iFrameCount), 1, pOptionFile);
+ fwrite (&iWidth, sizeof (iWidth), 1, pOptionFile);
+ fwrite (&iHeight, sizeof (iHeight), 1, pOptionFile);
+ iLastWidth = iWidth;
+ iLastHeight = iHeight;
+ }
+ }
+ ++ iFrameCount;
+ }
+
+ if (bLegacyCalling) {
+ iStart = WelsTime();
+ pData[0] = NULL;
+ pData[1] = NULL;
+ pData[2] = NULL;
+ memset (&sDstBufInfo, 0, sizeof (SBufferInfo));
+ sDstBufInfo.uiInBsTimeStamp = uiTimeStamp;
+ pDecoder->DecodeFrame2 (NULL, 0, pData, &sDstBufInfo);
+ if (sDstBufInfo.iBufferStatus == 1) {
+ pDst[0] = pData[0];
+ pDst[1] = pData[1];
+ pDst[2] = pData[2];
+ }
+ iEnd = WelsTime();
+ iTotal += iEnd - iStart;
+ if (sDstBufInfo.iBufferStatus == 1) {
+ cOutputModule.Process ((void**)pDst, &sDstBufInfo, pYuvFile);
+ iWidth = sDstBufInfo.UsrData.sSystemBuffer.iWidth;
+ iHeight = sDstBufInfo.UsrData.sSystemBuffer.iHeight;
+
+ if (pOptionFile != NULL) {
+ if (iWidth != iLastWidth && iHeight != iLastHeight) {
+ fwrite (&iFrameCount, sizeof (iFrameCount), 1, pOptionFile);
+ fwrite (&iWidth, sizeof (iWidth), 1, pOptionFile);
+ fwrite (&iHeight, sizeof (iHeight), 1, pOptionFile);
+ iLastWidth = iWidth;
+ iLastHeight = iHeight;
+ }
+ }
+ ++ iFrameCount;
+ }
+ }
+ iBufPos += iSliceSize;
+ ++ iSliceIndex;
+ }
+
+ pDecoder->GetOption (DECODER_OPTION_NUM_OF_FRAMES_REMAINING_IN_BUFFER, &num_of_frames_in_buffer);
+ for (int32_t i = 0; i < num_of_frames_in_buffer; ++i) {
+ iStart = WelsTime();
+ pData[0] = NULL;
+ pData[1] = NULL;
+ pData[2] = NULL;
+ memset (&sDstBufInfo, 0, sizeof (SBufferInfo));
+ sDstBufInfo.uiInBsTimeStamp = uiTimeStamp;
+ sDstBufInfo.iBufferStatus = 1;
+ pDecoder->FlushFrame (pData, &sDstBufInfo);
+ if (sDstBufInfo.iBufferStatus == 1) {
+ pDst[0] = pData[0];
+ pDst[1] = pData[1];
+ pDst[2] = pData[2];
+ }
+ iEnd = WelsTime();
+ iTotal += iEnd - iStart;
+ if (sDstBufInfo.iBufferStatus == 1) {
+ cOutputModule.Process ((void**)pDst, &sDstBufInfo, pYuvFile);
+ iWidth = sDstBufInfo.UsrData.sSystemBuffer.iWidth;
+ iHeight = sDstBufInfo.UsrData.sSystemBuffer.iHeight;
+
+ if (pOptionFile != NULL) {
+ if (iWidth != iLastWidth && iHeight != iLastHeight) {
+ fwrite (&iFrameCount, sizeof (iFrameCount), 1, pOptionFile);
+ fwrite (&iWidth, sizeof (iWidth), 1, pOptionFile);
+ fwrite (&iHeight, sizeof (iHeight), 1, pOptionFile);
+ iLastWidth = iWidth;
+ iLastHeight = iHeight;
+ }
+ }
+ ++iFrameCount;
+ }
+ }
+ dElapsed = iTotal / 1e6;
+ fprintf (stderr, "-------------------------------------------------------\n");
+ fprintf (stderr, "iWidth:\t\t%d\nheight:\t\t%d\nFrames:\t\t%d\ndecode time:\t%f sec\nFPS:\t\t%f fps\n",
+ iWidth, iHeight, iFrameCount, dElapsed, (iFrameCount * 1.0) / dElapsed);
+ fprintf (stderr, "-------------------------------------------------------\n");
+
+#if defined (WINDOWS_PHONE)
+ g_dDecTime = dElapsed;
+ g_fDecFPS = (iFrameCount * 1.0f) / (float) dElapsed;
+ g_iDecodedFrameNum = iFrameCount;
+#endif
+
+ // coverity scan uninitial
+label_exit:
+ if (pBuf) {
+ delete[] pBuf;
+ pBuf = NULL;
+ }
+ if (pH264File) {
+ fclose (pH264File);
+ pH264File = NULL;
+ }
+ if (pYuvFile) {
+ fclose (pYuvFile);
+ pYuvFile = NULL;
+ }
+ if (pOptionFile) {
+ fclose (pOptionFile);
+ pOptionFile = NULL;
+ }
+ if (fpTrack) {
+ fclose (fpTrack);
+ fpTrack = NULL;
+ }
+
+}
+
+#if (defined(ANDROID_NDK)||defined(APPLE_IOS) || defined (WINDOWS_PHONE))
+int32_t DecMain (int32_t iArgC, char* pArgV[]) {
+#else
+int32_t main (int32_t iArgC, char* pArgV[]) {
+#endif
+ ISVCDecoder* pDecoder = NULL;
+
+ SDecodingParam sDecParam = {0};
+ string strInputFile (""), strOutputFile (""), strOptionFile (""), strLengthFile ("");
+ int iLevelSetting = (int) WELS_LOG_WARNING;
+ bool bLegacyCalling = false;
+
+ sDecParam.sVideoProperty.size = sizeof (sDecParam.sVideoProperty);
+ sDecParam.eEcActiveIdc = ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE;
+
+ if (iArgC < 2) {
+ printf ("usage 1: h264dec.exe welsdec.cfg\n");
+ printf ("usage 2: h264dec.exe welsdec.264 out.yuv\n");
+ printf ("usage 3: h264dec.exe welsdec.264\n");
+ return 1;
+ } else if (iArgC == 2) {
+ if (strstr (pArgV[1], ".cfg")) { // read config file //confirmed_safe_unsafe_usage
+ CReadConfig cReadCfg (pArgV[1]);
+ string strTag[4];
+ string strReconFile ("");
+
+ if (!cReadCfg.ExistFile()) {
+ printf ("Specified file: %s not exist, maybe invalid path or parameter settting.\n", cReadCfg.GetFileName().c_str());
+ return 1;
+ }
+
+ while (!cReadCfg.EndOfFile()) {
+ long nRd = cReadCfg.ReadLine (&strTag[0]);
+ if (nRd > 0) {
+ if (strTag[0].compare ("InputFile") == 0) {
+ strInputFile = strTag[1];
+ } else if (strTag[0].compare ("OutputFile") == 0) {
+ strOutputFile = strTag[1];
+ } else if (strTag[0].compare ("RestructionFile") == 0) {
+ strReconFile = strTag[1];
+ int32_t iLen = (int32_t)strReconFile.length();
+ sDecParam.pFileNameRestructed = new char[iLen + 1];
+ if (sDecParam.pFileNameRestructed != NULL) {
+ sDecParam.pFileNameRestructed[iLen] = 0;
+ }
+
+ strncpy (sDecParam.pFileNameRestructed, strReconFile.c_str(), iLen); //confirmed_safe_unsafe_usage
+ } else if (strTag[0].compare ("TargetDQID") == 0) {
+ sDecParam.uiTargetDqLayer = (uint8_t)atol (strTag[1].c_str());
+ } else if (strTag[0].compare ("ErrorConcealmentIdc") == 0) {
+ sDecParam.eEcActiveIdc = (ERROR_CON_IDC)atol (strTag[1].c_str());
+ } else if (strTag[0].compare ("CPULoad") == 0) {
+ sDecParam.uiCpuLoad = (uint32_t)atol (strTag[1].c_str());
+ } else if (strTag[0].compare ("VideoBitstreamType") == 0) {
+ sDecParam.sVideoProperty.eVideoBsType = (VIDEO_BITSTREAM_TYPE)atol (strTag[1].c_str());
+ }
+ }
+ }
+ if (strOutputFile.empty()) {
+ printf ("No output file specified in configuration file.\n");
+ return 1;
+ }
+ } else if (strstr (pArgV[1],
+ ".264")) { // no output dump yuv file, just try to render the decoded pictures //confirmed_safe_unsafe_usage
+ strInputFile = pArgV[1];
+ sDecParam.uiTargetDqLayer = (uint8_t) - 1;
+ sDecParam.eEcActiveIdc = ERROR_CON_SLICE_COPY;
+ sDecParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT;
+ }
+ } else { //iArgC > 2
+ strInputFile = pArgV[1];
+ strOutputFile = pArgV[2];
+ sDecParam.uiTargetDqLayer = (uint8_t) - 1;
+ sDecParam.eEcActiveIdc = ERROR_CON_SLICE_COPY;
+ sDecParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT;
+ if (iArgC > 3) {
+ for (int i = 3; i < iArgC; i++) {
+ char* cmd = pArgV[i];
+
+ if (!strcmp (cmd, "-options")) {
+ if (i + 1 < iArgC)
+ strOptionFile = pArgV[++i];
+ else {
+ printf ("options file not specified.\n");
+ return 1;
+ }
+ } else if (!strcmp (cmd, "-trace")) {
+ if (i + 1 < iArgC)
+ iLevelSetting = atoi (pArgV[++i]);
+ else {
+ printf ("trace level not specified.\n");
+ return 1;
+ }
+ } else if (!strcmp (cmd, "-length")) {
+ if (i + 1 < iArgC)
+ strLengthFile = pArgV[++i];
+ else {
+ printf ("lenght file not specified.\n");
+ return 1;
+ }
+ } else if (!strcmp (cmd, "-ec")) {
+ if (i + 1 < iArgC) {
+ int iEcActiveIdc = atoi (pArgV[++i]);
+ sDecParam.eEcActiveIdc = (ERROR_CON_IDC)iEcActiveIdc;
+ printf ("ERROR_CON(cealment) is set to %d.\n", iEcActiveIdc);
+ }
+ } else if (!strcmp (cmd, "-legacy")) {
+ bLegacyCalling = true;
+ }
+ }
+ }
+
+ if (strOutputFile.empty()) {
+ printf ("No output file specified in configuration file.\n");
+ return 1;
+ }
+ }
+
+ if (strInputFile.empty()) {
+ printf ("No input file specified in configuration file.\n");
+ return 1;
+ }
+
+
+
+
+ if (WelsCreateDecoder (&pDecoder) || (NULL == pDecoder)) {
+ printf ("Create Decoder failed.\n");
+ return 1;
+ }
+ if (iLevelSetting >= 0) {
+ pDecoder->SetOption (DECODER_OPTION_TRACE_LEVEL, &iLevelSetting);
+ }
+
+ if (pDecoder->Initialize (&sDecParam)) {
+ printf ("Decoder initialization failed.\n");
+ return 1;
+ }
+
+
+ int32_t iWidth = 0;
+ int32_t iHeight = 0;
+
+
+ H264DecodeInstance (pDecoder, strInputFile.c_str(), !strOutputFile.empty() ? strOutputFile.c_str() : NULL, iWidth,
+ iHeight,
+ (!strOptionFile.empty() ? strOptionFile.c_str() : NULL), (!strLengthFile.empty() ? strLengthFile.c_str() : NULL),
+ (int32_t)sDecParam.eEcActiveIdc,
+ bLegacyCalling);
+
+ if (sDecParam.pFileNameRestructed != NULL) {
+ delete []sDecParam.pFileNameRestructed;
+ sDecParam.pFileNameRestructed = NULL;
+ }
+
+ if (pDecoder) {
+ pDecoder->Uninitialize();
+
+ WelsDestroyDecoder (pDecoder);
+ }
+
+ return 0;
+}
--- a/codec/decoder/core/inc/dec_frame.h
+++ b/codec/decoder/core/inc/dec_frame.h
@@ -1,156 +1,156 @@
-/*!
- * \copy
- * Copyright (c) 2013, Cisco Systems
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-//dec_frame.h
-#ifndef WELS_DEC_FRAME_H__
-#define WELS_DEC_FRAME_H__
-
-#include "typedefs.h"
-#include "wels_const.h"
-#include "wels_common_basis.h"
-#include "parameter_sets.h"
-#include "nal_prefix.h"
-#include "slice.h"
-#include "picture.h"
-#include "bit_stream.h"
-#include "fmo.h"
-
-namespace WelsDec {
-
-///////////////////////////////////DQ Layer level///////////////////////////////////
-typedef struct TagDqLayer SDqLayer;
-typedef SDqLayer* PDqLayer;
-typedef struct TagLayerInfo {
- SNalUnitHeaderExt sNalHeaderExt;
- SSlice sSliceInLayer; // Here Slice identify to Frame on concept
- PSubsetSps pSubsetSps; // current pSubsetSps used, memory alloc in external
- PSps pSps; // current sps based avc used, memory alloc in external
- PPps pPps; // current pps used
-} SLayerInfo, *PLayerInfo;
-/* Layer Representation */
-
-struct TagDqLayer {
- SLayerInfo sLayerInfo;
-
- PBitStringAux pBitStringAux; // pointer to SBitStringAux
- PFmo pFmo; // Current fmo context pointer used
- uint32_t* pMbType;
- int32_t* pSliceIdc; // using int32_t for slice_idc
- int16_t (*pMv[LIST_A])[MB_BLOCK4x4_NUM][MV_A];
- int16_t (*pMvd[LIST_A])[MB_BLOCK4x4_NUM][MV_A];
- int8_t (*pRefIndex[LIST_A])[MB_BLOCK4x4_NUM];
- int8_t (*pDirect)[MB_BLOCK4x4_NUM];
- bool* pNoSubMbPartSizeLessThan8x8Flag;
- bool* pTransformSize8x8Flag;
- int8_t* pLumaQp;
- int8_t (*pChromaQp)[2];
- int8_t* pCbp;
- uint16_t *pCbfDc;
- int8_t (*pNzc)[24];
- int8_t (*pNzcRs)[24];
- int8_t* pResidualPredFlag;
- int8_t* pInterPredictionDoneFlag;
- bool* pMbCorrectlyDecodedFlag;
- bool* pMbRefConcealedFlag;
- int16_t (*pScaledTCoeff)[MB_COEFF_LIST_SIZE];
- int8_t (*pIntraPredMode)[8]; //0~3 top4x4 ; 4~6 left 4x4; 7 intra16x16
- int8_t (*pIntra4x4FinalMode)[MB_BLOCK4x4_NUM];
- uint8_t *pIntraNxNAvailFlag;
- int8_t* pChromaPredMode;
- //uint8_t (*motion_pred_flag[LIST_A])[MB_PARTITION_SIZE]; // 8x8
- uint32_t (*pSubMbType)[MB_SUB_PARTITION_SIZE];
- int32_t iLumaStride;
- int32_t iChromaStride;
- uint8_t* pPred[3];
- int32_t iMbX;
- int32_t iMbY;
- int32_t iMbXyIndex;
- int32_t iMbWidth; // MB width of this picture, equal to sSps.iMbWidth
- int32_t iMbHeight; // MB height of this picture, equal to sSps.iMbHeight;
-
- /* Common syntax elements across all slices of a DQLayer */
- int32_t iSliceIdcBackup;
- uint32_t uiSpsId;
- uint32_t uiPpsId;
- uint32_t uiDisableInterLayerDeblockingFilterIdc;
- int32_t iInterLayerSliceAlphaC0Offset;
- int32_t iInterLayerSliceBetaOffset;
- //SPosOffset sScaledRefLayer;
- int32_t iSliceGroupChangeCycle;
-
- PRefPicListReorderSyn pRefPicListReordering;
- PPredWeightTabSyn pPredWeightTable;
- PRefPicMarking pRefPicMarking; // Decoded reference picture marking syntaxs
- PRefBasePicMarking pRefPicBaseMarking;
-
- PPicture pRef; // reference picture pointer
- PPicture pDec; // reconstruction picture pointer for layer
-
- int16_t iColocMv[2][16][2]; //Colocated MV cache
- int8_t iColocRefIndex[2][16]; //Colocated RefIndex cache
- int8_t iColocIntra[16]; //Colocated Intra cache
-
- bool bUseWeightPredictionFlag;
- bool bUseWeightedBiPredIdc;
- bool bStoreRefBasePicFlag; // iCurTid == 0 && iCurQid = 0 && bEncodeKeyPic = 1
- bool bTCoeffLevelPredFlag;
- bool bConstrainedIntraResamplingFlag;
- uint8_t uiRefLayerDqId;
- uint8_t uiRefLayerChromaPhaseXPlus1Flag;
- uint8_t uiRefLayerChromaPhaseYPlus1;
- uint8_t uiLayerDqId; // dq_id of current layer
- bool bUseRefBasePicFlag; // whether reference pic or reference base pic is referred?
-};
-
-typedef struct TagGpuAvcLayer {
- SLayerInfo sLayerInfo;
- PBitStringAux pBitStringAux; // pointer to SBitStringAux
-
- uint32_t* pMbType;
- int32_t* pSliceIdc; // using int32_t for slice_idc
- int8_t* pLumaQp;
- int8_t* pCbp;
- int8_t (*pNzc)[24];
- int8_t (*pIntraPredMode)[8]; //0~3 top4x4 ; 4~6 left 4x4; 7 intra16x16
- int32_t iMbX;
- int32_t iMbY;
- int32_t iMbXyIndex;
- int32_t iMbWidth; // MB width of this picture, equal to sSps.iMbWidth
- int32_t iMbHeight; // MB height of this picture, equal to sSps.iMbHeight;
-
-} SGpuAvcDqLayer, *PGpuAvcDqLayer;
-
-///////////////////////////////////////////////////////////////////////
-
-} // namespace WelsDec
-
-#endif//WELS_DEC_FRAME_H__
+/*!
+ * \copy
+ * Copyright (c) 2013, Cisco Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+//dec_frame.h
+#ifndef WELS_DEC_FRAME_H__
+#define WELS_DEC_FRAME_H__
+
+#include "typedefs.h"
+#include "wels_const.h"
+#include "wels_common_basis.h"
+#include "parameter_sets.h"
+#include "nal_prefix.h"
+#include "slice.h"
+#include "picture.h"
+#include "bit_stream.h"
+#include "fmo.h"
+
+namespace WelsDec {
+
+///////////////////////////////////DQ Layer level///////////////////////////////////
+typedef struct TagDqLayer SDqLayer;
+typedef SDqLayer* PDqLayer;
+typedef struct TagLayerInfo {
+ SNalUnitHeaderExt sNalHeaderExt;
+ SSlice sSliceInLayer; // Here Slice identify to Frame on concept
+ PSubsetSps pSubsetSps; // current pSubsetSps used, memory alloc in external
+ PSps pSps; // current sps based avc used, memory alloc in external
+ PPps pPps; // current pps used
+} SLayerInfo, *PLayerInfo;
+/* Layer Representation */
+
+struct TagDqLayer {
+ SLayerInfo sLayerInfo;
+
+ PBitStringAux pBitStringAux; // pointer to SBitStringAux
+ PFmo pFmo; // Current fmo context pointer used
+ uint32_t* pMbType;
+ int32_t* pSliceIdc; // using int32_t for slice_idc
+ int16_t (*pMv[LIST_A])[MB_BLOCK4x4_NUM][MV_A];
+ int16_t (*pMvd[LIST_A])[MB_BLOCK4x4_NUM][MV_A];
+ int8_t (*pRefIndex[LIST_A])[MB_BLOCK4x4_NUM];
+ int8_t (*pDirect)[MB_BLOCK4x4_NUM];
+ bool* pNoSubMbPartSizeLessThan8x8Flag;
+ bool* pTransformSize8x8Flag;
+ int8_t* pLumaQp;
+ int8_t (*pChromaQp)[2];
+ int8_t* pCbp;
+ uint16_t *pCbfDc;
+ int8_t (*pNzc)[24];
+ int8_t (*pNzcRs)[24];
+ int8_t* pResidualPredFlag;
+ int8_t* pInterPredictionDoneFlag;
+ bool* pMbCorrectlyDecodedFlag;
+ bool* pMbRefConcealedFlag;
+ int16_t (*pScaledTCoeff)[MB_COEFF_LIST_SIZE];
+ int8_t (*pIntraPredMode)[8]; //0~3 top4x4 ; 4~6 left 4x4; 7 intra16x16
+ int8_t (*pIntra4x4FinalMode)[MB_BLOCK4x4_NUM];
+ uint8_t *pIntraNxNAvailFlag;
+ int8_t* pChromaPredMode;
+ //uint8_t (*motion_pred_flag[LIST_A])[MB_PARTITION_SIZE]; // 8x8
+ uint32_t (*pSubMbType)[MB_SUB_PARTITION_SIZE];
+ int32_t iLumaStride;
+ int32_t iChromaStride;
+ uint8_t* pPred[3];
+ int32_t iMbX;
+ int32_t iMbY;
+ int32_t iMbXyIndex;
+ int32_t iMbWidth; // MB width of this picture, equal to sSps.iMbWidth
+ int32_t iMbHeight; // MB height of this picture, equal to sSps.iMbHeight;
+
+ /* Common syntax elements across all slices of a DQLayer */
+ int32_t iSliceIdcBackup;
+ uint32_t uiSpsId;
+ uint32_t uiPpsId;
+ uint32_t uiDisableInterLayerDeblockingFilterIdc;
+ int32_t iInterLayerSliceAlphaC0Offset;
+ int32_t iInterLayerSliceBetaOffset;
+ //SPosOffset sScaledRefLayer;
+ int32_t iSliceGroupChangeCycle;
+
+ PRefPicListReorderSyn pRefPicListReordering;
+ PPredWeightTabSyn pPredWeightTable;
+ PRefPicMarking pRefPicMarking; // Decoded reference picture marking syntaxs
+ PRefBasePicMarking pRefPicBaseMarking;
+
+ PPicture pRef; // reference picture pointer
+ PPicture pDec; // reconstruction picture pointer for layer
+
+ int16_t iColocMv[2][16][2]; //Colocated MV cache
+ int8_t iColocRefIndex[2][16]; //Colocated RefIndex cache
+ int8_t iColocIntra[16]; //Colocated Intra cache
+
+ bool bUseWeightPredictionFlag;
+ bool bUseWeightedBiPredIdc;
+ bool bStoreRefBasePicFlag; // iCurTid == 0 && iCurQid = 0 && bEncodeKeyPic = 1
+ bool bTCoeffLevelPredFlag;
+ bool bConstrainedIntraResamplingFlag;
+ uint8_t uiRefLayerDqId;
+ uint8_t uiRefLayerChromaPhaseXPlus1Flag;
+ uint8_t uiRefLayerChromaPhaseYPlus1;
+ uint8_t uiLayerDqId; // dq_id of current layer
+ bool bUseRefBasePicFlag; // whether reference pic or reference base pic is referred?
+};
+
+typedef struct TagGpuAvcLayer {
+ SLayerInfo sLayerInfo;
+ PBitStringAux pBitStringAux; // pointer to SBitStringAux
+
+ uint32_t* pMbType;
+ int32_t* pSliceIdc; // using int32_t for slice_idc
+ int8_t* pLumaQp;
+ int8_t* pCbp;
+ int8_t (*pNzc)[24];
+ int8_t (*pIntraPredMode)[8]; //0~3 top4x4 ; 4~6 left 4x4; 7 intra16x16
+ int32_t iMbX;
+ int32_t iMbY;
+ int32_t iMbXyIndex;
+ int32_t iMbWidth; // MB width of this picture, equal to sSps.iMbWidth
+ int32_t iMbHeight; // MB height of this picture, equal to sSps.iMbHeight;
+
+} SGpuAvcDqLayer, *PGpuAvcDqLayer;
+
+///////////////////////////////////////////////////////////////////////
+
+} // namespace WelsDec
+
+#endif//WELS_DEC_FRAME_H__
--- a/codec/decoder/core/src/deblocking.cpp
+++ b/codec/decoder/core/src/deblocking.cpp
@@ -1,1383 +1,1383 @@
-/*!
- * \copy
- * Copyright (c) 2010-2013, Cisco Systems
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- *
- * \file deblocking.c
- *
- * \brief Interfaces introduced in frame deblocking filtering
- *
- * \date 08/02/2010
- *
- *************************************************************************************
- */
-
-#include "deblocking.h"
-#include "deblocking_common.h"
-#include "cpu_core.h"
-
-namespace WelsDec {
-
-#define NO_SUPPORTED_FILTER_IDX (-1)
-#define LEFT_FLAG_BIT 0
-#define TOP_FLAG_BIT 1
-#define LEFT_FLAG_MASK 0x01
-#define TOP_FLAG_MASK 0x02
-
-#define SAME_MB_DIFF_REFIDX
-#define g_kuiAlphaTable(x) g_kuiAlphaTable[(x)+12]
-#define g_kiBetaTable(x) g_kiBetaTable[(x)+12]
-#define g_kiTc0Table(x) g_kiTc0Table[(x)+12]
-
-#define MB_BS_MV(iRefIndex, iMotionVector, iMbXy, iMbBn, iIndex, iNeighIndex) \
-(\
- ( iRefIndex[iMbXy][iIndex] - iRefIndex[iMbBn][iNeighIndex] )||\
- ( WELS_ABS( iMotionVector[iMbXy][iIndex][0] - iMotionVector[iMbBn][iNeighIndex][0] ) >= 4 ) ||\
- ( WELS_ABS( iMotionVector[iMbXy][iIndex][1] - iMotionVector[iMbBn][iNeighIndex][1] ) >= 4 )\
-)
-
-#if defined(SAME_MB_DIFF_REFIDX)
-#define SMB_EDGE_MV(iRefIndex, iMotionVector, iIndex, iNeighIndex) \
-(\
- ( iRefIndex[iIndex] - iRefIndex[iNeighIndex] )||(\
- ( WELS_ABS( iMotionVector[iIndex][0] - iMotionVector[iNeighIndex][0] ) &(~3) ) |\
- ( WELS_ABS( iMotionVector[iIndex][1] - iMotionVector[iNeighIndex][1] ) &(~3) ))\
-)
-#else
-#define SMB_EDGE_MV(iRefIndex, iMotionVector, iIndex, iNeighIndex) \
-(\
- !!(( WELS_ABS( iMotionVector[iIndex][0] - iMotionVector[iNeighIndex][0] ) &(~3) ) |( WELS_ABS( iMotionVector[iIndex][1] - iMotionVector[iNeighIndex][1] ) &(~3) ))\
-)
-#endif
-
-#define BS_EDGE(bsx1, iRefIndex, iMotionVector, iIndex, iNeighIndex) \
-( (bsx1|SMB_EDGE_MV(iRefIndex, iMotionVector, iIndex, iNeighIndex))<<((uint8_t)(!!bsx1)))
-
-#define GET_ALPHA_BETA_FROM_QP(iQp, iAlphaOffset, iBetaOffset, iIndex, iAlpha, iBeta) \
-{\
- iIndex = (iQp + iAlphaOffset);\
- iAlpha = g_kuiAlphaTable(iIndex);\
- iBeta = g_kiBetaTable((iQp + iBetaOffset));\
-}
-
-static const uint8_t g_kuiAlphaTable[52 + 24] = { //this table refers to Table 8-16 in H.264/AVC standard
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 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
- , 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
-};
-
-static const int8_t g_kiBetaTable[52 + 24] = { //this table refers to Table 8-16 in H.264/AVC standard
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 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
- , 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18
-};
-
-static const int8_t g_kiTc0Table[52 + 24][4] = { //this table refers Table 8-17 in H.264/AVC standard
- { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 },
- { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 },
- { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 },
- { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 },
- { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 1 },
- { -1, 0, 0, 1 }, { -1, 0, 0, 1 }, { -1, 0, 0, 1 }, { -1, 0, 1, 1 }, { -1, 0, 1, 1 }, { -1, 1, 1, 1 },
- { -1, 1, 1, 1 }, { -1, 1, 1, 1 }, { -1, 1, 1, 1 }, { -1, 1, 1, 2 }, { -1, 1, 1, 2 }, { -1, 1, 1, 2 },
- { -1, 1, 1, 2 }, { -1, 1, 2, 3 }, { -1, 1, 2, 3 }, { -1, 2, 2, 3 }, { -1, 2, 2, 4 }, { -1, 2, 3, 4 },
- { -1, 2, 3, 4 }, { -1, 3, 3, 5 }, { -1, 3, 4, 6 }, { -1, 3, 4, 6 }, { -1, 4, 5, 7 }, { -1, 4, 5, 8 },
- { -1, 4, 6, 9 }, { -1, 5, 7, 10 }, { -1, 6, 8, 11 }, { -1, 6, 8, 13 }, { -1, 7, 10, 14 }, { -1, 8, 11, 16 },
- { -1, 9, 12, 18 }, { -1, 10, 13, 20 }, { -1, 11, 15, 23 }, { -1, 13, 17, 25 }
- , { -1, 13, 17, 25 }, { -1, 13, 17, 25 }, { -1, 13, 17, 25 }, { -1, 13, 17, 25 }, { -1, 13, 17, 25 }, { -1, 13, 17, 25 }
- , { -1, 13, 17, 25 }, { -1, 13, 17, 25 }, { -1, 13, 17, 25 }, { -1, 13, 17, 25 }, { -1, 13, 17, 25 }, { -1, 13, 17, 25 }
-};
-
-static const uint8_t g_kuiTableBIdx[2][8] = {
- {
- 0, 4, 8, 12,
- 3, 7, 11, 15
- },
-
- {
- 0, 1, 2, 3,
- 12, 13, 14, 15
- },
-};
-
-static const uint8_t g_kuiTableB8x8Idx[2][16] = {
- {
- 0, 1, 4, 5, 8, 9, 12, 13, // 0 1 | 2 3
- 2, 3, 6, 7, 10, 11, 14, 15 // 4 5 | 6 7
- }, // ------------
- // 8 9 | 10 11
- {
- // 12 13 | 14 15
- 0, 1, 4, 5, 2, 3, 6, 7,
- 8, 9, 12, 13, 10, 11, 14, 15
- },
-};
-
-#define TC0_TBL_LOOKUP(tc, iIndexA, pBS, bChroma) \
-{\
- tc[0] = g_kiTc0Table(iIndexA)[pBS[0]] + bChroma;\
- tc[1] = g_kiTc0Table(iIndexA)[pBS[1]] + bChroma;\
- tc[2] = g_kiTc0Table(iIndexA)[pBS[2]] + bChroma;\
- tc[3] = g_kiTc0Table(iIndexA)[pBS[3]] + bChroma;\
-}
-
-void inline DeblockingBSInsideMBAvsbase (int8_t* pNnzTab, uint8_t nBS[2][4][4], int32_t iLShiftFactor) {
- uint32_t uiNnz32b0, uiNnz32b1, uiNnz32b2, uiNnz32b3;
-
- uiNnz32b0 = * (uint32_t*) (pNnzTab + 0);
- uiNnz32b1 = * (uint32_t*) (pNnzTab + 4);
- uiNnz32b2 = * (uint32_t*) (pNnzTab + 8);
- uiNnz32b3 = * (uint32_t*) (pNnzTab + 12);
-
- nBS[0][1][0] = (pNnzTab[0] | pNnzTab[1]) << iLShiftFactor;
- nBS[0][2][0] = (pNnzTab[1] | pNnzTab[2]) << iLShiftFactor;
- nBS[0][3][0] = (pNnzTab[2] | pNnzTab[3]) << iLShiftFactor;
-
- nBS[0][1][1] = (pNnzTab[4] | pNnzTab[5]) << iLShiftFactor;
- nBS[0][2][1] = (pNnzTab[5] | pNnzTab[6]) << iLShiftFactor;
- nBS[0][3][1] = (pNnzTab[6] | pNnzTab[7]) << iLShiftFactor;
- * (uint32_t*)nBS[1][1] = (uiNnz32b0 | uiNnz32b1) << iLShiftFactor;
-
- nBS[0][1][2] = (pNnzTab[8] | pNnzTab[9]) << iLShiftFactor;
- nBS[0][2][2] = (pNnzTab[9] | pNnzTab[10]) << iLShiftFactor;
- nBS[0][3][2] = (pNnzTab[10] | pNnzTab[11]) << iLShiftFactor;
- * (uint32_t*)nBS[1][2] = (uiNnz32b1 | uiNnz32b2) << iLShiftFactor;
-
- nBS[0][1][3] = (pNnzTab[12] | pNnzTab[13]) << iLShiftFactor;
- nBS[0][2][3] = (pNnzTab[13] | pNnzTab[14]) << iLShiftFactor;
- nBS[0][3][3] = (pNnzTab[14] | pNnzTab[15]) << iLShiftFactor;
- * (uint32_t*)nBS[1][3] = (uiNnz32b2 | uiNnz32b3) << iLShiftFactor;
-}
-
-void inline DeblockingBSInsideMBAvsbase8x8 (int8_t* pNnzTab, uint8_t nBS[2][4][4], int32_t iLShiftFactor) {
- int8_t i8x8NnzTab[4];
- for (int32_t i = 0; i < 4; i++) {
- int32_t iBlkIdx = i << 2;
- i8x8NnzTab[i] = (pNnzTab[g_kuiMbCountScan4Idx[iBlkIdx]] | pNnzTab[g_kuiMbCountScan4Idx[iBlkIdx + 1]] |
- pNnzTab[g_kuiMbCountScan4Idx[iBlkIdx + 2]] | pNnzTab[g_kuiMbCountScan4Idx[iBlkIdx + 3]]);
- }
-
- //vertical
- nBS[0][2][0] = nBS[0][2][1] = (i8x8NnzTab[0] | i8x8NnzTab[1]) << iLShiftFactor;
- nBS[0][2][2] = nBS[0][2][3] = (i8x8NnzTab[2] | i8x8NnzTab[3]) << iLShiftFactor;
- //horizontal
- nBS[1][2][0] = nBS[1][2][1] = (i8x8NnzTab[0] | i8x8NnzTab[2]) << iLShiftFactor;
- nBS[1][2][2] = nBS[1][2][3] = (i8x8NnzTab[1] | i8x8NnzTab[3]) << iLShiftFactor;
-}
-
-void static inline DeblockingBSInsideMBNormal (PDqLayer pCurDqLayer, uint8_t nBS[2][4][4], int8_t* pNnzTab,
- int32_t iMbXy) {
- uint32_t uiNnz32b0, uiNnz32b1, uiNnz32b2, uiNnz32b3;
- int8_t* iRefIndex = pCurDqLayer->pRefIndex[LIST_0][iMbXy];
- ENFORCE_STACK_ALIGN_1D (uint8_t, uiBsx4, 4, 4);
-
- int8_t i8x8NnzTab[4];
-
- if (pCurDqLayer->pTransformSize8x8Flag[iMbXy]) {
- for (int32_t i = 0; i < 4; i++) {
- int32_t iBlkIdx = i << 2;
- i8x8NnzTab[i] = (pNnzTab[g_kuiMbCountScan4Idx[iBlkIdx]] | pNnzTab[g_kuiMbCountScan4Idx[iBlkIdx + 1]] |
- pNnzTab[g_kuiMbCountScan4Idx[iBlkIdx + 2]] | pNnzTab[g_kuiMbCountScan4Idx[iBlkIdx + 3]]);
- }
- //vertical
- nBS[0][2][0] = nBS[0][2][1] = BS_EDGE ((i8x8NnzTab[0] | i8x8NnzTab[1]), iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy],
- g_kuiMbCountScan4Idx[1 << 2], g_kuiMbCountScan4Idx[0]);
- nBS[0][2][2] = nBS[0][2][3] = BS_EDGE ((i8x8NnzTab[2] | i8x8NnzTab[3]), iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy],
- g_kuiMbCountScan4Idx[3 << 2], g_kuiMbCountScan4Idx[2 << 2]);
-
- //horizontal
- nBS[1][2][0] = nBS[1][2][1] = BS_EDGE ((i8x8NnzTab[0] | i8x8NnzTab[2]), iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy],
- g_kuiMbCountScan4Idx[2 << 2], g_kuiMbCountScan4Idx[0]);
- nBS[1][2][2] = nBS[1][2][3] = BS_EDGE ((i8x8NnzTab[1] | i8x8NnzTab[3]), iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy],
- g_kuiMbCountScan4Idx[3 << 2], g_kuiMbCountScan4Idx[1 << 2]);
- } else {
- uiNnz32b0 = * (uint32_t*) (pNnzTab + 0);
- uiNnz32b1 = * (uint32_t*) (pNnzTab + 4);
- uiNnz32b2 = * (uint32_t*) (pNnzTab + 8);
- uiNnz32b3 = * (uint32_t*) (pNnzTab + 12);
-
- for (int i = 0; i < 3; i++)
- uiBsx4[i] = pNnzTab[i] | pNnzTab[i + 1];
- nBS[0][1][0] = BS_EDGE (uiBsx4[0], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 1, 0);
- nBS[0][2][0] = BS_EDGE (uiBsx4[1], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 2, 1);
- nBS[0][3][0] = BS_EDGE (uiBsx4[2], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 3, 2);
-
- for (int i = 0; i < 3; i++)
- uiBsx4[i] = pNnzTab[4 + i] | pNnzTab[4 + i + 1];
- nBS[0][1][1] = BS_EDGE (uiBsx4[0], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 5, 4);
- nBS[0][2][1] = BS_EDGE (uiBsx4[1], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 6, 5);
- nBS[0][3][1] = BS_EDGE (uiBsx4[2], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 7, 6);
-
- for (int i = 0; i < 3; i++)
- uiBsx4[i] = pNnzTab[8 + i] | pNnzTab[8 + i + 1];
- nBS[0][1][2] = BS_EDGE (uiBsx4[0], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 9, 8);
- nBS[0][2][2] = BS_EDGE (uiBsx4[1], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 10, 9);
- nBS[0][3][2] = BS_EDGE (uiBsx4[2], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 11, 10);
-
- for (int i = 0; i < 3; i++)
- uiBsx4[i] = pNnzTab[12 + i] | pNnzTab[12 + i + 1];
- nBS[0][1][3] = BS_EDGE (uiBsx4[0], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 13, 12);
- nBS[0][2][3] = BS_EDGE (uiBsx4[1], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 14, 13);
- nBS[0][3][3] = BS_EDGE (uiBsx4[2], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 15, 14);
-
- // horizontal
- * (uint32_t*)uiBsx4 = (uiNnz32b0 | uiNnz32b1);
- nBS[1][1][0] = BS_EDGE (uiBsx4[0], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 4, 0);
- nBS[1][1][1] = BS_EDGE (uiBsx4[1], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 5, 1);
- nBS[1][1][2] = BS_EDGE (uiBsx4[2], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 6, 2);
- nBS[1][1][3] = BS_EDGE (uiBsx4[3], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 7, 3);
-
- * (uint32_t*)uiBsx4 = (uiNnz32b1 | uiNnz32b2);
- nBS[1][2][0] = BS_EDGE (uiBsx4[0], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 8, 4);
- nBS[1][2][1] = BS_EDGE (uiBsx4[1], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 9, 5);
- nBS[1][2][2] = BS_EDGE (uiBsx4[2], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 10, 6);
- nBS[1][2][3] = BS_EDGE (uiBsx4[3], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 11, 7);
-
- * (uint32_t*)uiBsx4 = (uiNnz32b2 | uiNnz32b3);
- nBS[1][3][0] = BS_EDGE (uiBsx4[0], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 12, 8);
- nBS[1][3][1] = BS_EDGE (uiBsx4[1], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 13, 9);
- nBS[1][3][2] = BS_EDGE (uiBsx4[2], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 14, 10);
- nBS[1][3][3] = BS_EDGE (uiBsx4[3], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 15, 11);
- }
-}
-
-void static inline DeblockingBSliceBSInsideMBNormal (PDqLayer pCurDqLayer, uint8_t nBS[2][4][4], int8_t* pNnzTab,
- int32_t iMbXy) {
- uint32_t uiNnz32b0, uiNnz32b1, uiNnz32b2, uiNnz32b3;
- int8_t* iRefIndex[LIST_A];
- iRefIndex[LIST_0] = pCurDqLayer->pRefIndex[LIST_0][iMbXy];
- iRefIndex[LIST_1] = pCurDqLayer->pRefIndex[LIST_1][iMbXy];
- ENFORCE_STACK_ALIGN_1D (uint8_t, uiBsx4, 4, 4);
-
- int8_t i8x8NnzTab[4];
-
- if (pCurDqLayer->pTransformSize8x8Flag[iMbXy]) {
- for (int32_t i = 0; i < 4; i++) {
- int32_t iBlkIdx = i << 2;
- i8x8NnzTab[i] = (pNnzTab[g_kuiMbCountScan4Idx[iBlkIdx]] | pNnzTab[g_kuiMbCountScan4Idx[iBlkIdx + 1]] |
- pNnzTab[g_kuiMbCountScan4Idx[iBlkIdx + 2]] | pNnzTab[g_kuiMbCountScan4Idx[iBlkIdx + 3]]);
- }
- //vertical
- int8_t iIndex = g_kuiMbCountScan4Idx[1 << 2];
- int8_t iNeigborIndex = g_kuiMbCountScan4Idx[0];
- nBS[0][2][0] = nBS[0][2][1] = 1;
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- if (iRefIndex[listIdx][iIndex] > REF_NOT_IN_LIST && iRefIndex[listIdx][iNeigborIndex] > REF_NOT_IN_LIST) {
- nBS[0][2][0] = nBS[0][2][1] = BS_EDGE ((i8x8NnzTab[0] | i8x8NnzTab[1]), iRefIndex[listIdx],
- pCurDqLayer->pMv[listIdx][iMbXy],
- iIndex, iNeigborIndex);
- break;
- }
- }
- iIndex = g_kuiMbCountScan4Idx[3 << 2];
- iNeigborIndex = g_kuiMbCountScan4Idx[2 << 2];
- nBS[0][2][2] = nBS[0][2][3] = 1;
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- if (iRefIndex[listIdx][iIndex] > REF_NOT_IN_LIST && iRefIndex[listIdx][iNeigborIndex] > REF_NOT_IN_LIST) {
- nBS[0][2][2] = nBS[0][2][3] = BS_EDGE ((i8x8NnzTab[2] | i8x8NnzTab[3]), iRefIndex[listIdx],
- pCurDqLayer->pMv[listIdx][iMbXy],
- iIndex, iNeigborIndex);
- break;
- }
- }
-
- //horizontal
- iIndex = g_kuiMbCountScan4Idx[2 << 2];
- iNeigborIndex = g_kuiMbCountScan4Idx[0];
- nBS[1][2][0] = nBS[1][2][1] = 1;
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- if (iRefIndex[listIdx][iIndex] > REF_NOT_IN_LIST && iRefIndex[listIdx][iNeigborIndex] > REF_NOT_IN_LIST) {
- nBS[1][2][0] = nBS[1][2][1] = BS_EDGE ((i8x8NnzTab[0] | i8x8NnzTab[2]), iRefIndex[listIdx],
- pCurDqLayer->pMv[listIdx][iMbXy],
- iIndex, iNeigborIndex);
- break;
- }
- }
-
- iIndex = g_kuiMbCountScan4Idx[3 << 2];
- iNeigborIndex = g_kuiMbCountScan4Idx[1 << 2];
- nBS[1][2][2] = nBS[1][2][3] = 1;
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- if (iRefIndex[listIdx][iIndex] > REF_NOT_IN_LIST && iRefIndex[listIdx][iNeigborIndex] > REF_NOT_IN_LIST) {
- nBS[1][2][2] = nBS[1][2][3] = BS_EDGE ((i8x8NnzTab[1] | i8x8NnzTab[3]), iRefIndex[listIdx],
- pCurDqLayer->pMv[listIdx][iMbXy],
- iIndex, iNeigborIndex);
- break;
- }
- }
- } else {
- uiNnz32b0 = * (uint32_t*) (pNnzTab + 0);
- uiNnz32b1 = * (uint32_t*) (pNnzTab + 4);
- uiNnz32b2 = * (uint32_t*) (pNnzTab + 8);
- uiNnz32b3 = * (uint32_t*) (pNnzTab + 12);
-
- for (int i = 0; i < 3; i++)
- uiBsx4[i] = pNnzTab[i] | pNnzTab[i + 1];
- nBS[0][1][0] = 1;
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- if (iRefIndex[listIdx][1] > REF_NOT_IN_LIST && iRefIndex[listIdx][0] > REF_NOT_IN_LIST) {
- nBS[0][1][0] = BS_EDGE (uiBsx4[0], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 1, 0);
- break;
- }
- }
- nBS[0][2][0] = 1;
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- if (iRefIndex[listIdx][2] > REF_NOT_IN_LIST && iRefIndex[listIdx][1] > REF_NOT_IN_LIST) {
- nBS[0][2][0] = BS_EDGE (uiBsx4[1], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 2, 1);
- break;
- }
- }
- nBS[0][3][0] = 1;
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- if (iRefIndex[listIdx][3] > REF_NOT_IN_LIST && iRefIndex[listIdx][2] > REF_NOT_IN_LIST) {
- nBS[0][3][0] = BS_EDGE (uiBsx4[2], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 3, 2);
- break;
- }
- }
-
- for (int i = 0; i < 3; i++)
- uiBsx4[i] = pNnzTab[4 + i] | pNnzTab[4 + i + 1];
- nBS[0][1][1] = 1;
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- if (iRefIndex[listIdx][5] > REF_NOT_IN_LIST && iRefIndex[listIdx][4] > REF_NOT_IN_LIST) {
- nBS[0][1][1] = BS_EDGE (uiBsx4[0], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 5, 4);
- break;
- }
- }
- nBS[0][2][1] = 1;
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- if (iRefIndex[listIdx][6] > REF_NOT_IN_LIST && iRefIndex[listIdx][5] > REF_NOT_IN_LIST) {
- nBS[0][2][1] = BS_EDGE (uiBsx4[1], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 6, 5);
- break;
- }
- }
- nBS[0][3][1] = 1;
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- if (iRefIndex[listIdx][7] > REF_NOT_IN_LIST && iRefIndex[listIdx][6] > REF_NOT_IN_LIST) {
- nBS[0][3][1] = BS_EDGE (uiBsx4[2], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 7, 6);
- break;
- }
- }
-
- for (int i = 0; i < 3; i++)
- uiBsx4[i] = pNnzTab[8 + i] | pNnzTab[8 + i + 1];
- nBS[0][1][2] = 1;
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- if (iRefIndex[listIdx][9] > REF_NOT_IN_LIST && iRefIndex[listIdx][8] > REF_NOT_IN_LIST) {
- nBS[0][1][2] = BS_EDGE (uiBsx4[0], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 9, 8);
- break;
- }
- }
- nBS[0][2][2] = 1;
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- if (iRefIndex[listIdx][10] > REF_NOT_IN_LIST && iRefIndex[listIdx][9] > REF_NOT_IN_LIST) {
- nBS[0][2][2] = BS_EDGE (uiBsx4[1], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 10, 9);
- break;
- }
- }
- nBS[0][3][2] = 1;
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- if (iRefIndex[listIdx][11] > REF_NOT_IN_LIST && iRefIndex[listIdx][10] > REF_NOT_IN_LIST) {
- nBS[0][3][2] = BS_EDGE (uiBsx4[2], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 11, 10);
- break;
- }
- }
-
- for (int i = 0; i < 3; i++)
- uiBsx4[i] = pNnzTab[12 + i] | pNnzTab[12 + i + 1];
- nBS[0][1][3] = 1;
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- if (iRefIndex[listIdx][13] > REF_NOT_IN_LIST && iRefIndex[listIdx][12] > REF_NOT_IN_LIST) {
- nBS[0][1][3] = BS_EDGE (uiBsx4[0], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 13, 12);
- break;
- }
- }
- nBS[0][2][3] = 1;
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- if (iRefIndex[listIdx][14] > REF_NOT_IN_LIST && iRefIndex[listIdx][13] > REF_NOT_IN_LIST) {
- nBS[0][2][3] = BS_EDGE (uiBsx4[1], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 14, 13);
- break;
- }
- }
- nBS[0][3][3] = 1;
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- if (iRefIndex[listIdx][15] > REF_NOT_IN_LIST && iRefIndex[listIdx][14] > REF_NOT_IN_LIST) {
- nBS[0][3][3] = BS_EDGE (uiBsx4[2], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 15, 14);
- break;
- }
- }
-
- // horizontal
- * (uint32_t*)uiBsx4 = (uiNnz32b0 | uiNnz32b1);
- nBS[1][1][0] = 1;
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- if (iRefIndex[listIdx][4] > REF_NOT_IN_LIST && iRefIndex[listIdx][0] > REF_NOT_IN_LIST) {
- nBS[1][1][0] = BS_EDGE (uiBsx4[0], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 4, 0);
- break;
- }
- }
- nBS[1][1][1] = 1;
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- if (iRefIndex[listIdx][5] > REF_NOT_IN_LIST && iRefIndex[listIdx][1] > REF_NOT_IN_LIST) {
- nBS[1][1][1] = BS_EDGE (uiBsx4[1], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 5, 1);
- break;
- }
- }
- nBS[1][1][2] = 1;
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- if (iRefIndex[listIdx][6] > REF_NOT_IN_LIST && iRefIndex[listIdx][2] > REF_NOT_IN_LIST) {
- nBS[1][1][2] = BS_EDGE (uiBsx4[2], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 6, 2);
- break;
- }
- }
- nBS[1][1][3] = 1;
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- if (iRefIndex[listIdx][7] > REF_NOT_IN_LIST && iRefIndex[listIdx][3] > REF_NOT_IN_LIST) {
- nBS[1][1][3] = BS_EDGE (uiBsx4[3], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 7, 3);
- break;
- }
- }
-
- * (uint32_t*)uiBsx4 = (uiNnz32b1 | uiNnz32b2);
- nBS[1][2][0] = 1;
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- if (iRefIndex[listIdx][8] > REF_NOT_IN_LIST && iRefIndex[listIdx][4] > REF_NOT_IN_LIST) {
- nBS[1][2][0] = BS_EDGE (uiBsx4[0], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 8, 4);
- break;
- }
- }
- nBS[1][2][1] = 1;
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- if (iRefIndex[listIdx][9] > REF_NOT_IN_LIST && iRefIndex[listIdx][5] > REF_NOT_IN_LIST) {
- nBS[1][2][1] = BS_EDGE (uiBsx4[1], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 9, 5);
- break;
- }
- }
- nBS[1][2][2] = 1;
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- if (iRefIndex[listIdx][10] > REF_NOT_IN_LIST && iRefIndex[listIdx][6] > REF_NOT_IN_LIST) {
- nBS[1][2][2] = BS_EDGE (uiBsx4[2], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 10, 6);
- break;
- }
- }
- nBS[1][2][3] = 1;
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- if (iRefIndex[listIdx][11] > REF_NOT_IN_LIST && iRefIndex[listIdx][7] > REF_NOT_IN_LIST) {
- nBS[1][2][3] = BS_EDGE (uiBsx4[3], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 11, 7);
- break;
- }
- }
-
- * (uint32_t*)uiBsx4 = (uiNnz32b2 | uiNnz32b3);
- nBS[1][3][0] = 1;
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- if (iRefIndex[listIdx][12] > REF_NOT_IN_LIST && iRefIndex[listIdx][8] > REF_NOT_IN_LIST) {
- nBS[1][3][0] = BS_EDGE (uiBsx4[0], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 12, 8);
- break;
- }
- }
- nBS[1][3][1] = 1;
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- if (iRefIndex[listIdx][13] > REF_NOT_IN_LIST && iRefIndex[listIdx][9] > REF_NOT_IN_LIST) {
- nBS[1][3][1] = BS_EDGE (uiBsx4[1], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 13, 9);
- break;
- }
- }
- nBS[1][3][2] = 1;
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- if (iRefIndex[listIdx][14] > REF_NOT_IN_LIST && iRefIndex[listIdx][10] > REF_NOT_IN_LIST) {
- nBS[1][3][2] = BS_EDGE (uiBsx4[2], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 14, 10);
- break;
- }
- }
- nBS[1][3][3] = 1;
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- if (iRefIndex[listIdx][15] > REF_NOT_IN_LIST && iRefIndex[listIdx][11] > REF_NOT_IN_LIST) {
- nBS[1][3][3] = BS_EDGE (uiBsx4[3], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 15, 11);
- break;
- }
- }
- }
-}
-
-
-uint32_t DeblockingBsMarginalMBAvcbase (PDqLayer pCurDqLayer, int32_t iEdge, int32_t iNeighMb, int32_t iMbXy) {
- int32_t i, j;
- uint32_t uiBSx4;
- uint8_t* pBS = (uint8_t*) (&uiBSx4);
- const uint8_t* pBIdx = &g_kuiTableBIdx[iEdge][0];
- const uint8_t* pBnIdx = &g_kuiTableBIdx[iEdge][4];
- const uint8_t* pB8x8Idx = &g_kuiTableB8x8Idx[iEdge][0];
- const uint8_t* pBn8x8Idx = &g_kuiTableB8x8Idx[iEdge][8];
-
- if (pCurDqLayer->pTransformSize8x8Flag[iMbXy] && pCurDqLayer->pTransformSize8x8Flag[iNeighMb]) {
- for (i = 0; i < 2; i++) {
- uint8_t uiNzc = 0;
- for (j = 0; uiNzc == 0 && j < 4; j++) {
- uiNzc |= (pCurDqLayer->pNzc[iMbXy][* (pB8x8Idx + j)] | pCurDqLayer->pNzc[iNeighMb][* (pBn8x8Idx + j)]);
- }
- if (uiNzc) {
- pBS[i << 1] = pBS[1 + (i << 1)] = 2;
- } else {
- pBS[i << 1] = pBS[1 + (i << 1)] = MB_BS_MV (pCurDqLayer->pRefIndex[LIST_0], pCurDqLayer->pMv[LIST_0], iMbXy, iNeighMb,
- *pB8x8Idx, *pBn8x8Idx);
- }
- pB8x8Idx += 4;
- pBn8x8Idx += 4;
- }
- } else if (pCurDqLayer->pTransformSize8x8Flag[iMbXy]) {
- for (i = 0; i < 2; i++) {
- uint8_t uiNzc = 0;
- for (j = 0; uiNzc == 0 && j < 4; j++) {
- uiNzc |= pCurDqLayer->pNzc[iMbXy][* (pB8x8Idx + j)];
- }
- for (j = 0; j < 2; j++) {
- if (uiNzc | pCurDqLayer->pNzc[iNeighMb][*pBnIdx]) {
- pBS[j + (i << 1)] = 2;
- } else {
- pBS[j + (i << 1)] = MB_BS_MV (pCurDqLayer->pRefIndex[LIST_0], pCurDqLayer->pMv[LIST_0], iMbXy, iNeighMb, *pB8x8Idx,
- *pBnIdx);
- }
- pBnIdx++;
- }
- pB8x8Idx += 4;
- }
- } else if (pCurDqLayer->pTransformSize8x8Flag[iNeighMb]) {
- for (i = 0; i < 2; i++) {
- uint8_t uiNzc = 0;
- for (j = 0; uiNzc == 0 && j < 4; j++) {
- uiNzc |= pCurDqLayer->pNzc[iNeighMb][* (pBn8x8Idx + j)];
- }
- for (j = 0; j < 2; j++) {
- if (uiNzc | pCurDqLayer->pNzc[iMbXy][*pBIdx]) {
- pBS[j + (i << 1)] = 2;
- } else {
- pBS[j + (i << 1)] = MB_BS_MV (pCurDqLayer->pRefIndex[LIST_0], pCurDqLayer->pMv[LIST_0], iMbXy, iNeighMb, *pBIdx,
- *pBn8x8Idx);
- }
- pBIdx++;
- }
- pBn8x8Idx += 4;
- }
- } else {
- // only 4x4 transform
- for (i = 0; i < 4; i++) {
- if (pCurDqLayer->pNzc[iMbXy][*pBIdx] | pCurDqLayer->pNzc[iNeighMb][*pBnIdx]) {
- pBS[i] = 2;
- } else {
- pBS[i] = MB_BS_MV (pCurDqLayer->pRefIndex[LIST_0], pCurDqLayer->pMv[LIST_0], iMbXy, iNeighMb, *pBIdx,
- *pBnIdx);
- }
- pBIdx++;
- pBnIdx++;
- }
- }
-
- return uiBSx4;
-}
-uint32_t DeblockingBSliceBsMarginalMBAvcbase (PDqLayer pCurDqLayer, int32_t iEdge, int32_t iNeighMb, int32_t iMbXy) {
- int32_t i, j;
- uint32_t uiBSx4;
- uint8_t* pBS = (uint8_t*) (&uiBSx4);
- const uint8_t* pBIdx = &g_kuiTableBIdx[iEdge][0];
- const uint8_t* pBnIdx = &g_kuiTableBIdx[iEdge][4];
- const uint8_t* pB8x8Idx = &g_kuiTableB8x8Idx[iEdge][0];
- const uint8_t* pBn8x8Idx = &g_kuiTableB8x8Idx[iEdge][8];
-
- if (pCurDqLayer->pTransformSize8x8Flag[iMbXy] && pCurDqLayer->pTransformSize8x8Flag[iNeighMb]) {
- for (i = 0; i < 2; i++) {
- uint8_t uiNzc = 0;
- for (j = 0; uiNzc == 0 && j < 4; j++) {
- uiNzc |= (pCurDqLayer->pNzc[iMbXy][* (pB8x8Idx + j)] | pCurDqLayer->pNzc[iNeighMb][* (pBn8x8Idx + j)]);
- }
- if (uiNzc) {
- pBS[i << 1] = pBS[1 + (i << 1)] = 2;
- } else {
- pBS[i << 1] = pBS[1 + (i << 1)] = 1;
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- if (pCurDqLayer->pRefIndex[listIdx][iMbXy][*pB8x8Idx] > REF_NOT_IN_LIST
- && pCurDqLayer->pRefIndex[listIdx][iMbXy][*pBn8x8Idx] > REF_NOT_IN_LIST) {
- pBS[i << 1] = pBS[1 + (i << 1)] = MB_BS_MV (pCurDqLayer->pRefIndex[listIdx], pCurDqLayer->pMv[listIdx], iMbXy, iNeighMb,
- *pB8x8Idx, *pBn8x8Idx);
- break;
- }
- }
- }
- pB8x8Idx += 4;
- pBn8x8Idx += 4;
- }
- } else if (pCurDqLayer->pTransformSize8x8Flag[iMbXy]) {
- for (i = 0; i < 2; i++) {
- uint8_t uiNzc = 0;
- for (j = 0; uiNzc == 0 && j < 4; j++) {
- uiNzc |= pCurDqLayer->pNzc[iMbXy][* (pB8x8Idx + j)];
- }
- for (j = 0; j < 2; j++) {
- if (uiNzc | pCurDqLayer->pNzc[iNeighMb][*pBnIdx]) {
- pBS[j + (i << 1)] = 2;
- } else {
- pBS[j + (i << 1)] = 1;
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- if (pCurDqLayer->pRefIndex[listIdx][iMbXy][*pB8x8Idx] > REF_NOT_IN_LIST
- && pCurDqLayer->pRefIndex[listIdx][iMbXy][*pBnIdx] > REF_NOT_IN_LIST) {
- pBS[j + (i << 1)] = MB_BS_MV (pCurDqLayer->pRefIndex[listIdx], pCurDqLayer->pMv[listIdx], iMbXy, iNeighMb, *pB8x8Idx,
- *pBnIdx);
- break;
- }
- }
- }
- pBnIdx++;
- }
- pB8x8Idx += 4;
- }
- } else if (pCurDqLayer->pTransformSize8x8Flag[iNeighMb]) {
- for (i = 0; i < 2; i++) {
- uint8_t uiNzc = 0;
- for (j = 0; uiNzc == 0 && j < 4; j++) {
- uiNzc |= pCurDqLayer->pNzc[iNeighMb][* (pBn8x8Idx + j)];
- }
- for (j = 0; j < 2; j++) {
- if (uiNzc | pCurDqLayer->pNzc[iMbXy][*pBIdx]) {
- pBS[j + (i << 1)] = 2;
- } else {
- pBS[j + (i << 1)] = 1;
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- if (pCurDqLayer->pRefIndex[listIdx][iMbXy][*pBIdx] > REF_NOT_IN_LIST
- && pCurDqLayer->pRefIndex[listIdx][iMbXy][*pBn8x8Idx] > REF_NOT_IN_LIST) {
- pBS[j + (i << 1)] = MB_BS_MV (pCurDqLayer->pRefIndex[listIdx], pCurDqLayer->pMv[listIdx], iMbXy, iNeighMb, *pBIdx,
- *pBn8x8Idx);
- break;
- }
- }
- }
- pBIdx++;
- }
- pBn8x8Idx += 4;
- }
- } else {
- // only 4x4 transform
- for (i = 0; i < 4; i++) {
- if (pCurDqLayer->pNzc[iMbXy][*pBIdx] | pCurDqLayer->pNzc[iNeighMb][*pBnIdx]) {
- pBS[i] = 2;
- } else {
- pBS[i] = 1;
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- if (pCurDqLayer->pRefIndex[listIdx][iMbXy][*pBIdx] > REF_NOT_IN_LIST
- && pCurDqLayer->pRefIndex[listIdx][iMbXy][*pBnIdx] > REF_NOT_IN_LIST) {
- pBS[i] = MB_BS_MV (pCurDqLayer->pRefIndex[listIdx], pCurDqLayer->pMv[listIdx], iMbXy, iNeighMb, *pBIdx, *pBnIdx);
- break;
- }
- }
- }
- pBIdx++;
- pBnIdx++;
- }
- }
-
- return uiBSx4;
-}
-int32_t DeblockingAvailableNoInterlayer (PDqLayer pCurDqLayer, int32_t iFilterIdc) {
- int32_t iMbY = pCurDqLayer->iMbY;
- int32_t iMbX = pCurDqLayer->iMbX;
- int32_t iMbXy = pCurDqLayer->iMbXyIndex;
- bool bLeftFlag = false;
- bool bTopFlag = false;
-
- if (2 == iFilterIdc) {
- bLeftFlag = (iMbX > 0) && (pCurDqLayer->pSliceIdc[iMbXy] == pCurDqLayer->pSliceIdc[iMbXy - 1]);
- bTopFlag = (iMbY > 0) && (pCurDqLayer->pSliceIdc[iMbXy] == pCurDqLayer->pSliceIdc[iMbXy - pCurDqLayer->iMbWidth]);
- } else { //if ( 0 == iFilterIdc )
- bLeftFlag = (iMbX > 0);
- bTopFlag = (iMbY > 0);
- }
- return (bLeftFlag << LEFT_FLAG_BIT) | (bTopFlag << TOP_FLAG_BIT);
-}
-
-void FilteringEdgeLumaH (SDeblockingFilter* pFilter, uint8_t* pPix, int32_t iStride, uint8_t* pBS) {
- int32_t iIndexA;
- int32_t iAlpha;
- int32_t iBeta;
- ENFORCE_STACK_ALIGN_1D (int8_t, tc, 4, 16);
-
- GET_ALPHA_BETA_FROM_QP (pFilter->iLumaQP, pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
- iBeta);
-
- if (iAlpha | iBeta) {
- TC0_TBL_LOOKUP (tc, iIndexA, pBS, 0);
- pFilter->pLoopf->pfLumaDeblockingLT4Ver (pPix, iStride, iAlpha, iBeta, tc);
- }
- return;
-}
-
-
-void FilteringEdgeLumaV (SDeblockingFilter* pFilter, uint8_t* pPix, int32_t iStride, uint8_t* pBS) {
- int32_t iIndexA;
- int32_t iAlpha;
- int32_t iBeta;
- ENFORCE_STACK_ALIGN_1D (int8_t, tc, 4, 16);
-
- GET_ALPHA_BETA_FROM_QP (pFilter->iLumaQP, pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
- iBeta);
-
- if (iAlpha | iBeta) {
- TC0_TBL_LOOKUP (tc, iIndexA, pBS, 0);
- pFilter->pLoopf->pfLumaDeblockingLT4Hor (pPix, iStride, iAlpha, iBeta, tc);
- }
- return;
-}
-
-
-void FilteringEdgeLumaIntraH (SDeblockingFilter* pFilter, uint8_t* pPix, int32_t iStride, uint8_t* pBS) {
- int32_t iIndexA;
- int32_t iAlpha;
- int32_t iBeta;
-
- GET_ALPHA_BETA_FROM_QP (pFilter->iLumaQP, pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
- iBeta);
-
- if (iAlpha | iBeta) {
- pFilter->pLoopf->pfLumaDeblockingEQ4Ver (pPix, iStride, iAlpha, iBeta);
- }
- return;
-}
-
-void FilteringEdgeLumaIntraV (SDeblockingFilter* pFilter, uint8_t* pPix, int32_t iStride, uint8_t* pBS) {
- int32_t iIndexA;
- int32_t iAlpha;
- int32_t iBeta;
-
- GET_ALPHA_BETA_FROM_QP (pFilter->iLumaQP, pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
- iBeta);
-
- if (iAlpha | iBeta) {
- pFilter->pLoopf->pfLumaDeblockingEQ4Hor (pPix, iStride, iAlpha, iBeta);
- }
- return;
-}
-void FilteringEdgeChromaH (SDeblockingFilter* pFilter, uint8_t* pPixCb, uint8_t* pPixCr, int32_t iStride,
- uint8_t* pBS) {
- int32_t iIndexA;
- int32_t iAlpha;
- int32_t iBeta;
- ENFORCE_STACK_ALIGN_1D (int8_t, tc, 4, 16);
- if (pFilter->iChromaQP[0] == pFilter->iChromaQP[1]) {
-
- GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP[0], pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
- iBeta);
-
- if (iAlpha | iBeta) {
- TC0_TBL_LOOKUP (tc, iIndexA, pBS, 1);
- pFilter->pLoopf->pfChromaDeblockingLT4Ver (pPixCb, pPixCr, iStride, iAlpha, iBeta, tc);
- }
- } else {
-
- for (int i = 0; i < 2; i++) {
-
-
- GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP[i], pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
- iBeta);
-
- if (iAlpha | iBeta) {
- uint8_t* pPixCbCr = (i == 0) ? pPixCb : pPixCr;
- TC0_TBL_LOOKUP (tc, iIndexA, pBS, 1);
- pFilter->pLoopf->pfChromaDeblockingLT4Ver2 (pPixCbCr, iStride, iAlpha, iBeta, tc);
- }
-
-
-
- }
-
- }
- return;
-}
-void FilteringEdgeChromaV (SDeblockingFilter* pFilter, uint8_t* pPixCb, uint8_t* pPixCr, int32_t iStride,
- uint8_t* pBS) {
- int32_t iIndexA;
- int32_t iAlpha;
- int32_t iBeta;
- ENFORCE_STACK_ALIGN_1D (int8_t, tc, 4, 16);
- if (pFilter->iChromaQP[0] == pFilter->iChromaQP[1]) {
-
-
- GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP[0], pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
- iBeta);
-
- if (iAlpha | iBeta) {
- TC0_TBL_LOOKUP (tc, iIndexA, pBS, 1);
- pFilter->pLoopf->pfChromaDeblockingLT4Hor (pPixCb, pPixCr, iStride, iAlpha, iBeta, tc);
- }
-
-
- } else {
-
- for (int i = 0; i < 2; i++) {
-
- GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP[i], pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
- iBeta);
-
- if (iAlpha | iBeta) {
- uint8_t* pPixCbCr = (i == 0) ? pPixCb : pPixCr;
- TC0_TBL_LOOKUP (tc, iIndexA, pBS, 1);
- pFilter->pLoopf->pfChromaDeblockingLT4Hor2 (pPixCbCr, iStride, iAlpha, iBeta, tc);
- }
-
-
- }
- }
- return;
-}
-
-void FilteringEdgeChromaIntraH (SDeblockingFilter* pFilter, uint8_t* pPixCb, uint8_t* pPixCr, int32_t iStride,
- uint8_t* pBS) {
- int32_t iIndexA;
- int32_t iAlpha;
- int32_t iBeta;
- if (pFilter->iChromaQP[0] == pFilter->iChromaQP[1]) {
-
- GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP[0], pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
- iBeta);
-
- if (iAlpha | iBeta) {
- pFilter->pLoopf->pfChromaDeblockingEQ4Ver (pPixCb, pPixCr, iStride, iAlpha, iBeta);
- }
- } else {
-
- for (int i = 0; i < 2; i++) {
-
- GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP[i], pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
- iBeta);
-
- if (iAlpha | iBeta) {
- uint8_t* pPixCbCr = (i == 0) ? pPixCb : pPixCr;
- pFilter->pLoopf->pfChromaDeblockingEQ4Ver2 (pPixCbCr, iStride, iAlpha, iBeta);
- }
-
- }
- }
- return;
-}
-
-void FilteringEdgeChromaIntraV (SDeblockingFilter* pFilter, uint8_t* pPixCb, uint8_t* pPixCr, int32_t iStride,
- uint8_t* pBS) {
- int32_t iIndexA;
- int32_t iAlpha;
- int32_t iBeta;
- if (pFilter->iChromaQP[0] == pFilter->iChromaQP[1]) { // QP of cb and cr are the same
-
-
-
-
- GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP[0], pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
- iBeta);
- if (iAlpha | iBeta) {
- pFilter->pLoopf->pfChromaDeblockingEQ4Hor (pPixCb, pPixCr, iStride, iAlpha, iBeta);
- }
- } else {
-
- for (int i = 0; i < 2; i++) {
-
-
- GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP[i], pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
- iBeta);
- if (iAlpha | iBeta) {
- uint8_t* pPixCbCr = (i == 0) ? pPixCb : pPixCr;
- pFilter->pLoopf->pfChromaDeblockingEQ4Hor2 (pPixCbCr, iStride, iAlpha, iBeta);
- }
- }
-
- }
- return;
-}
-
-
-void DeblockingInterMb (PDqLayer pCurDqLayer, PDeblockingFilter pFilter, uint8_t nBS[2][4][4],
- int32_t iBoundryFlag) {
- int32_t iMbXyIndex = pCurDqLayer->iMbXyIndex;
- int32_t iMbX = pCurDqLayer->iMbX;
- int32_t iMbY = pCurDqLayer->iMbY;
-
- int32_t iCurLumaQp = pCurDqLayer->pLumaQp[iMbXyIndex];
- //int32_t* iCurChromaQp = pCurDqLayer->pChromaQp[iMbXyIndex];
- int8_t* pCurChromaQp = pCurDqLayer->pChromaQp[iMbXyIndex];
- int32_t iLineSize = pFilter->iCsStride[0];
- int32_t iLineSizeUV = pFilter->iCsStride[1];
-
- uint8_t* pDestY, * pDestCb, * pDestCr;
- pDestY = pFilter->pCsData[0] + ((iMbY * iLineSize + iMbX) << 4);
- pDestCb = pFilter->pCsData[1] + ((iMbY * iLineSizeUV + iMbX) << 3);
- pDestCr = pFilter->pCsData[2] + ((iMbY * iLineSizeUV + iMbX) << 3);
-
-//Vertical margrin
- if (iBoundryFlag & LEFT_FLAG_MASK) {
- int32_t iLeftXyIndex = iMbXyIndex - 1;
- pFilter->iLumaQP = (iCurLumaQp + pCurDqLayer->pLumaQp[iLeftXyIndex] + 1) >> 1;
- for (int i = 0; i < 2; i++) {
- pFilter->iChromaQP[i] = (pCurChromaQp[i] + pCurDqLayer->pChromaQp[iLeftXyIndex][i] + 1) >> 1;
- }
- if (nBS[0][0][0] == 0x04) {
- FilteringEdgeLumaIntraV (pFilter, pDestY, iLineSize, NULL);
- FilteringEdgeChromaIntraV (pFilter, pDestCb, pDestCr, iLineSizeUV, NULL);
- } else {
- if (* (uint32_t*)nBS[0][0] != 0) {
- FilteringEdgeLumaV (pFilter, pDestY, iLineSize, nBS[0][0]);
- FilteringEdgeChromaV (pFilter, pDestCb, pDestCr, iLineSizeUV, nBS[0][0]);
- }
- }
- }
-
- pFilter->iLumaQP = iCurLumaQp;
- pFilter->iChromaQP[0] = pCurChromaQp[0];
- pFilter->iChromaQP[1] = pCurChromaQp[1];
-
- if (* (uint32_t*)nBS[0][1] != 0 && !pCurDqLayer->pTransformSize8x8Flag[iMbXyIndex]) {
- FilteringEdgeLumaV (pFilter, &pDestY[1 << 2], iLineSize, nBS[0][1]);
- }
-
- if (* (uint32_t*)nBS[0][2] != 0) {
- FilteringEdgeLumaV (pFilter, &pDestY[2 << 2], iLineSize, nBS[0][2]);
- FilteringEdgeChromaV (pFilter, &pDestCb[2 << 1], &pDestCr[2 << 1], iLineSizeUV, nBS[0][2]);
- }
-
- if (* (uint32_t*)nBS[0][3] != 0 && !pCurDqLayer->pTransformSize8x8Flag[iMbXyIndex]) {
- FilteringEdgeLumaV (pFilter, &pDestY[3 << 2], iLineSize, nBS[0][3]);
- }
-
- if (iBoundryFlag & TOP_FLAG_MASK) {
- int32_t iTopXyIndex = iMbXyIndex - pCurDqLayer->iMbWidth;
- pFilter->iLumaQP = (iCurLumaQp + pCurDqLayer->pLumaQp[iTopXyIndex] + 1) >> 1;
- for (int i = 0; i < 2; i++) {
- pFilter->iChromaQP[i] = (pCurChromaQp[i] + pCurDqLayer->pChromaQp[iTopXyIndex][i] + 1) >> 1;
- }
-
- if (nBS[1][0][0] == 0x04) {
- FilteringEdgeLumaIntraH (pFilter, pDestY, iLineSize, NULL);
- FilteringEdgeChromaIntraH (pFilter, pDestCb, pDestCr, iLineSizeUV, NULL);
- } else {
- if (* (uint32_t*)nBS[1][0] != 0) {
- FilteringEdgeLumaH (pFilter, pDestY, iLineSize, nBS[1][0]);
- FilteringEdgeChromaH (pFilter, pDestCb, pDestCr, iLineSizeUV, nBS[1][0]);
- }
- }
- }
-
- pFilter->iLumaQP = iCurLumaQp;
- pFilter->iChromaQP[0] = pCurChromaQp[0];
- pFilter->iChromaQP[1] = pCurChromaQp[1];
-
- if (* (uint32_t*)nBS[1][1] != 0 && !pCurDqLayer->pTransformSize8x8Flag[iMbXyIndex]) {
- FilteringEdgeLumaH (pFilter, &pDestY[ (1 << 2)*iLineSize], iLineSize, nBS[1][1]);
- }
-
- if (* (uint32_t*)nBS[1][2] != 0) {
- FilteringEdgeLumaH (pFilter, &pDestY[ (2 << 2)*iLineSize], iLineSize, nBS[1][2]);
- FilteringEdgeChromaH (pFilter, &pDestCb[ (2 << 1)*iLineSizeUV], &pDestCr[ (2 << 1)*iLineSizeUV], iLineSizeUV,
- nBS[1][2]);
- }
-
- if (* (uint32_t*)nBS[1][3] != 0 && !pCurDqLayer->pTransformSize8x8Flag[iMbXyIndex]) {
- FilteringEdgeLumaH (pFilter, &pDestY[ (3 << 2)*iLineSize], iLineSize, nBS[1][3]);
- }
-}
-
-void FilteringEdgeLumaHV (PDqLayer pCurDqLayer, PDeblockingFilter pFilter, int32_t iBoundryFlag) {
- int32_t iMbXyIndex = pCurDqLayer->iMbXyIndex;
- int32_t iMbX = pCurDqLayer->iMbX;
- int32_t iMbY = pCurDqLayer->iMbY;
- int32_t iMbWidth = pCurDqLayer->iMbWidth;
- int32_t iLineSize = pFilter->iCsStride[0];
-
- uint8_t* pDestY;
- int32_t iCurQp;
- int32_t iIndexA, iAlpha, iBeta;
-
- ENFORCE_STACK_ALIGN_1D (int8_t, iTc, 4, 16);
- ENFORCE_STACK_ALIGN_1D (uint8_t, uiBSx4, 4, 4);
-
- pDestY = pFilter->pCsData[0] + ((iMbY * iLineSize + iMbX) << 4);
- iCurQp = pCurDqLayer->pLumaQp[iMbXyIndex];
-
- * (uint32_t*)uiBSx4 = 0x03030303;
-
- // luma v
- if (iBoundryFlag & LEFT_FLAG_MASK) {
- pFilter->iLumaQP = (iCurQp + pCurDqLayer->pLumaQp[iMbXyIndex - 1] + 1) >> 1;
- FilteringEdgeLumaIntraV (pFilter, pDestY, iLineSize, NULL);
- }
-
- pFilter->iLumaQP = iCurQp;
- GET_ALPHA_BETA_FROM_QP (pFilter->iLumaQP, pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
- iBeta);
- if (iAlpha | iBeta) {
- TC0_TBL_LOOKUP (iTc, iIndexA, uiBSx4, 0);
-
- if (!pCurDqLayer->pTransformSize8x8Flag[iMbXyIndex]) {
- pFilter->pLoopf->pfLumaDeblockingLT4Hor (&pDestY[1 << 2], iLineSize, iAlpha, iBeta, iTc);
- }
-
- pFilter->pLoopf->pfLumaDeblockingLT4Hor (&pDestY[2 << 2], iLineSize, iAlpha, iBeta, iTc);
-
- if (!pCurDqLayer->pTransformSize8x8Flag[iMbXyIndex]) {
- pFilter->pLoopf->pfLumaDeblockingLT4Hor (&pDestY[3 << 2], iLineSize, iAlpha, iBeta, iTc);
- }
- }
-
- // luma h
- if (iBoundryFlag & TOP_FLAG_MASK) {
- pFilter->iLumaQP = (iCurQp + pCurDqLayer->pLumaQp[iMbXyIndex - iMbWidth] + 1) >> 1;
- FilteringEdgeLumaIntraH (pFilter, pDestY, iLineSize, NULL);
- }
-
- pFilter->iLumaQP = iCurQp;
- if (iAlpha | iBeta) {
- if (!pCurDqLayer->pTransformSize8x8Flag[iMbXyIndex]) {
- pFilter->pLoopf->pfLumaDeblockingLT4Ver (&pDestY[ (1 << 2)*iLineSize], iLineSize, iAlpha, iBeta, iTc);
- }
-
- pFilter->pLoopf->pfLumaDeblockingLT4Ver (&pDestY[ (2 << 2)*iLineSize], iLineSize, iAlpha, iBeta, iTc);
-
- if (!pCurDqLayer->pTransformSize8x8Flag[iMbXyIndex]) {
- pFilter->pLoopf->pfLumaDeblockingLT4Ver (&pDestY[ (3 << 2)*iLineSize], iLineSize, iAlpha, iBeta, iTc);
- }
- }
-}
-void FilteringEdgeChromaHV (PDqLayer pCurDqLayer, PDeblockingFilter pFilter, int32_t iBoundryFlag) {
- int32_t iMbXyIndex = pCurDqLayer->iMbXyIndex;
- int32_t iMbX = pCurDqLayer->iMbX;
- int32_t iMbY = pCurDqLayer->iMbY;
- int32_t iMbWidth = pCurDqLayer->iMbWidth;
- int32_t iLineSize = pFilter->iCsStride[1];
-
- uint8_t* pDestCb;
- uint8_t* pDestCr;
- //int32_t iCurQp;
- int8_t* pCurQp;
- int32_t iIndexA, iAlpha, iBeta;
-
- ENFORCE_STACK_ALIGN_1D (int8_t, iTc, 4, 16);
- ENFORCE_STACK_ALIGN_1D (uint8_t, uiBSx4, 4, 4);
-
- pDestCb = pFilter->pCsData[1] + ((iMbY * iLineSize + iMbX) << 3);
- pDestCr = pFilter->pCsData[2] + ((iMbY * iLineSize + iMbX) << 3);
- pCurQp = pCurDqLayer->pChromaQp[iMbXyIndex];
-
- * (uint32_t*)uiBSx4 = 0x03030303;
-
-
-// chroma v
- if (iBoundryFlag & LEFT_FLAG_MASK) {
-
- for (int i = 0; i < 2; i++) {
- pFilter->iChromaQP[i] = (pCurQp[i] + pCurDqLayer->pChromaQp[iMbXyIndex - 1][i] + 1) >> 1;
-
- }
- FilteringEdgeChromaIntraV (pFilter, pDestCb, pDestCr, iLineSize, NULL);
- }
-
- pFilter->iChromaQP[0] = pCurQp[0];
- pFilter->iChromaQP[1] = pCurQp[1];
- if (pFilter->iChromaQP[0] == pFilter->iChromaQP[1]) {
- GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP[0], pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
- iBeta);
- if (iAlpha | iBeta) {
- TC0_TBL_LOOKUP (iTc, iIndexA, uiBSx4, 1);
- pFilter->pLoopf->pfChromaDeblockingLT4Hor (&pDestCb[2 << 1], &pDestCr[2 << 1], iLineSize, iAlpha, iBeta, iTc);
- }
- } else {
-
- for (int i = 0; i < 2; i++) {
- GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP[i], pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
- iBeta);
- if (iAlpha | iBeta) {
- uint8_t* pDestCbCr = (i == 0) ? &pDestCb[2 << 1] : &pDestCr[2 << 1];
- TC0_TBL_LOOKUP (iTc, iIndexA, uiBSx4, 1);
- pFilter->pLoopf->pfChromaDeblockingLT4Hor2 (pDestCbCr, iLineSize, iAlpha, iBeta, iTc);
- }
-
- }
- }
-
- // chroma h
-
- if (iBoundryFlag & TOP_FLAG_MASK) {
- for (int i = 0; i < 2; i++) {
- pFilter->iChromaQP[i] = (pCurQp[i] + pCurDqLayer->pChromaQp[iMbXyIndex - iMbWidth][i] + 1) >> 1;
- }
- FilteringEdgeChromaIntraH (pFilter, pDestCb, pDestCr, iLineSize, NULL);
- }
-
- pFilter->iChromaQP[0] = pCurQp[0];
- pFilter->iChromaQP[1] = pCurQp[1];
-
- if (pFilter->iChromaQP[0] == pFilter->iChromaQP[1]) {
- GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP[0], pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
- iBeta);
- if (iAlpha | iBeta) {
- TC0_TBL_LOOKUP (iTc, iIndexA, uiBSx4, 1);
- pFilter->pLoopf->pfChromaDeblockingLT4Ver (&pDestCb[ (2 << 1)*iLineSize], &pDestCr[ (2 << 1)*iLineSize], iLineSize,
- iAlpha, iBeta, iTc);
- }
- } else {
- for (int i = 0; i < 2; i++) {
-
- GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP[i], pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
- iBeta);
- if (iAlpha | iBeta) {
- TC0_TBL_LOOKUP (iTc, iIndexA, uiBSx4, 1);
- uint8_t* pDestCbCr = (i == 0) ? &pDestCb[ (2 << 1) * iLineSize] : &pDestCr[ (2 << 1) * iLineSize];
- pFilter->pLoopf->pfChromaDeblockingLT4Ver2 (pDestCbCr, iLineSize,
- iAlpha, iBeta, iTc);
- }
- }
-
-
- }
-}
-
-// merge h&v lookup table operation to save performance
-void DeblockingIntraMb (PDqLayer pCurDqLayer, PDeblockingFilter pFilter, int32_t iBoundryFlag) {
- FilteringEdgeLumaHV (pCurDqLayer, pFilter, iBoundryFlag);
- FilteringEdgeChromaHV (pCurDqLayer, pFilter, iBoundryFlag);
-}
-
-void WelsDeblockingMb (PDqLayer pCurDqLayer, PDeblockingFilter pFilter, int32_t iBoundryFlag) {
- uint8_t nBS[2][4][4] = {{{ 0 }}};
-
- int32_t iMbXyIndex = pCurDqLayer->iMbXyIndex;
- uint32_t iCurMbType = pCurDqLayer->pMbType[iMbXyIndex];
- int32_t iMbNb;
-
- PSlice pSlice = &pCurDqLayer->sLayerInfo.sSliceInLayer;
- PSliceHeader pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader;
- bool bBSlice = pSliceHeader->eSliceType == B_SLICE;
-
- switch (iCurMbType) {
- case MB_TYPE_INTRA4x4:
- case MB_TYPE_INTRA8x8:
- case MB_TYPE_INTRA16x16:
- case MB_TYPE_INTRA_PCM:
- DeblockingIntraMb (pCurDqLayer, pFilter, iBoundryFlag);
- break;
- default:
-
- if (iBoundryFlag & LEFT_FLAG_MASK) {
- iMbNb = iMbXyIndex - 1;
- if (bBSlice) {
- * (uint32_t*)nBS[0][0] = IS_INTRA (pCurDqLayer->pMbType[iMbNb]) ? 0x04040404 : DeblockingBSliceBsMarginalMBAvcbase (
- pCurDqLayer, 0, iMbNb, iMbXyIndex);
- } else {
- * (uint32_t*)nBS[0][0] = IS_INTRA (pCurDqLayer->pMbType[iMbNb]) ? 0x04040404 : DeblockingBsMarginalMBAvcbase (
- pCurDqLayer, 0, iMbNb, iMbXyIndex);
- }
- } else {
- * (uint32_t*)nBS[0][0] = 0;
- }
- if (iBoundryFlag & TOP_FLAG_MASK) {
- iMbNb = iMbXyIndex - pCurDqLayer->iMbWidth;
- if (bBSlice) {
- * (uint32_t*)nBS[1][0] = IS_INTRA (pCurDqLayer->pMbType[iMbNb]) ? 0x04040404 : DeblockingBSliceBsMarginalMBAvcbase (
- pCurDqLayer, 1, iMbNb, iMbXyIndex);
- } else {
- * (uint32_t*)nBS[1][0] = IS_INTRA (pCurDqLayer->pMbType[iMbNb]) ? 0x04040404 : DeblockingBsMarginalMBAvcbase (
- pCurDqLayer, 1, iMbNb, iMbXyIndex);
- }
- } else {
- * (uint32_t*)nBS[1][0] = 0;
- }
- //SKIP MB_16x16 or others
- if (IS_SKIP (iCurMbType)) {
- * (uint32_t*)nBS[0][1] = * (uint32_t*)nBS[0][2] = * (uint32_t*)nBS[0][3] =
- * (uint32_t*)nBS[1][1] = * (uint32_t*)nBS[1][2] = * (uint32_t*)nBS[1][3] = 0;
- } else {
- if (IS_INTER_16x16 (iCurMbType)) {
- if (!pCurDqLayer->pTransformSize8x8Flag[pCurDqLayer->iMbXyIndex]) {
- DeblockingBSInsideMBAvsbase (pCurDqLayer->pNzc[iMbXyIndex], nBS, 1);
- } else {
- DeblockingBSInsideMBAvsbase8x8 (pCurDqLayer->pNzc[iMbXyIndex], nBS, 1);
- }
- } else {
-
- if (bBSlice) {
- DeblockingBSliceBSInsideMBNormal (pCurDqLayer, nBS, pCurDqLayer->pNzc[iMbXyIndex], iMbXyIndex);
- } else {
- DeblockingBSInsideMBNormal (pCurDqLayer, nBS, pCurDqLayer->pNzc[iMbXyIndex], iMbXyIndex);
- }
- }
- }
- DeblockingInterMb (pCurDqLayer, pFilter, nBS, iBoundryFlag);
- break;
- }
-}
-
-/*!
- * \brief AVC slice deblocking filtering target layer
- *
- * \param dec Wels avc decoder context
- *
- * \return NONE
- */
-void WelsDeblockingFilterSlice (PWelsDecoderContext pCtx, PDeblockingFilterMbFunc pDeblockMb) {
- PDqLayer pCurDqLayer = pCtx->pCurDqLayer;
- PSliceHeaderExt pSliceHeaderExt = &pCurDqLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt;
- int32_t iMbWidth = pCurDqLayer->iMbWidth;
- int32_t iTotalMbCount = pSliceHeaderExt->sSliceHeader.pSps->uiTotalMbCount;
-
- SDeblockingFilter pFilter;
- memset (&pFilter, 0, sizeof (pFilter));
- PFmo pFmo = pCtx->pFmo;
- int32_t iNextMbXyIndex = 0;
- int32_t iTotalNumMb = pCurDqLayer->sLayerInfo.sSliceInLayer.iTotalMbInCurSlice;
- int32_t iCountNumMb = 0;
- int32_t iBoundryFlag;
- int32_t iFilterIdc = pCurDqLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.uiDisableDeblockingFilterIdc;
-
- /* Step1: parameters set */
- pFilter.pCsData[0] = pCtx->pDec->pData[0];
- pFilter.pCsData[1] = pCtx->pDec->pData[1];
- pFilter.pCsData[2] = pCtx->pDec->pData[2];
-
- pFilter.iCsStride[0] = pCtx->pDec->iLinesize[0];
- pFilter.iCsStride[1] = pCtx->pDec->iLinesize[1];
-
- pFilter.eSliceType = (EWelsSliceType) pCurDqLayer->sLayerInfo.sSliceInLayer.eSliceType;
-
- pFilter.iSliceAlphaC0Offset = pSliceHeaderExt->sSliceHeader.iSliceAlphaC0Offset;
- pFilter.iSliceBetaOffset = pSliceHeaderExt->sSliceHeader.iSliceBetaOffset;
-
- pFilter.pLoopf = &pCtx->sDeblockingFunc;
-
- /* Step2: macroblock deblocking */
- if (0 == iFilterIdc || 2 == iFilterIdc) {
- iNextMbXyIndex = pSliceHeaderExt->sSliceHeader.iFirstMbInSlice;
- pCurDqLayer->iMbX = iNextMbXyIndex % iMbWidth;
- pCurDqLayer->iMbY = iNextMbXyIndex / iMbWidth;
- pCurDqLayer->iMbXyIndex = iNextMbXyIndex;
-
- do {
- iBoundryFlag = DeblockingAvailableNoInterlayer (pCurDqLayer, iFilterIdc);
-
- pDeblockMb (pCurDqLayer, &pFilter, iBoundryFlag);
-
- ++iCountNumMb;
- if (iCountNumMb >= iTotalNumMb) {
- break;
- }
-
- if (pSliceHeaderExt->sSliceHeader.pPps->uiNumSliceGroups > 1) {
- iNextMbXyIndex = FmoNextMb (pFmo, iNextMbXyIndex);
- } else {
- ++iNextMbXyIndex;
- }
- if (-1 == iNextMbXyIndex || iNextMbXyIndex >= iTotalMbCount) { // slice group boundary or end of a frame
- break;
- }
-
- pCurDqLayer->iMbX = iNextMbXyIndex % iMbWidth;
- pCurDqLayer->iMbY = iNextMbXyIndex / iMbWidth;
- pCurDqLayer->iMbXyIndex = iNextMbXyIndex;
- } while (1);
- }
-}
-/*!
- * \brief deblocking module initialize
- *
- * \param pf
- * cpu
- *
- * \return NONE
- */
-
-void DeblockingInit (SDeblockingFunc* pFunc, int32_t iCpu) {
- pFunc->pfLumaDeblockingLT4Ver = DeblockLumaLt4V_c;
- pFunc->pfLumaDeblockingEQ4Ver = DeblockLumaEq4V_c;
- pFunc->pfLumaDeblockingLT4Hor = DeblockLumaLt4H_c;
- pFunc->pfLumaDeblockingEQ4Hor = DeblockLumaEq4H_c;
-
- pFunc->pfChromaDeblockingLT4Ver = DeblockChromaLt4V_c;
- pFunc->pfChromaDeblockingEQ4Ver = DeblockChromaEq4V_c;
- pFunc->pfChromaDeblockingLT4Hor = DeblockChromaLt4H_c;
- pFunc->pfChromaDeblockingEQ4Hor = DeblockChromaEq4H_c;
-
- pFunc->pfChromaDeblockingLT4Ver2 = DeblockChromaLt4V2_c;
- pFunc->pfChromaDeblockingEQ4Ver2 = DeblockChromaEq4V2_c;
- pFunc->pfChromaDeblockingLT4Hor2 = DeblockChromaLt4H2_c;
- pFunc->pfChromaDeblockingEQ4Hor2 = DeblockChromaEq4H2_c;
-
-#ifdef X86_ASM
- if (iCpu & WELS_CPU_SSSE3) {
- pFunc->pfLumaDeblockingLT4Ver = DeblockLumaLt4V_ssse3;
- pFunc->pfLumaDeblockingEQ4Ver = DeblockLumaEq4V_ssse3;
- pFunc->pfLumaDeblockingLT4Hor = DeblockLumaLt4H_ssse3;
- pFunc->pfLumaDeblockingEQ4Hor = DeblockLumaEq4H_ssse3;
- pFunc->pfChromaDeblockingLT4Ver = DeblockChromaLt4V_ssse3;
- pFunc->pfChromaDeblockingEQ4Ver = DeblockChromaEq4V_ssse3;
- pFunc->pfChromaDeblockingLT4Hor = DeblockChromaLt4H_ssse3;
- pFunc->pfChromaDeblockingEQ4Hor = DeblockChromaEq4H_ssse3;
- }
-#endif
-
-#if defined(HAVE_NEON)
- if (iCpu & WELS_CPU_NEON) {
- pFunc->pfLumaDeblockingLT4Ver = DeblockLumaLt4V_neon;
- pFunc->pfLumaDeblockingEQ4Ver = DeblockLumaEq4V_neon;
- pFunc->pfLumaDeblockingLT4Hor = DeblockLumaLt4H_neon;
- pFunc->pfLumaDeblockingEQ4Hor = DeblockLumaEq4H_neon;
-
- pFunc->pfChromaDeblockingLT4Ver = DeblockChromaLt4V_neon;
- pFunc->pfChromaDeblockingEQ4Ver = DeblockChromaEq4V_neon;
- pFunc->pfChromaDeblockingLT4Hor = DeblockChromaLt4H_neon;
- pFunc->pfChromaDeblockingEQ4Hor = DeblockChromaEq4H_neon;
- }
-#endif
-
-#if defined(HAVE_NEON_AARCH64)
- if (iCpu & WELS_CPU_NEON) {
- pFunc->pfLumaDeblockingLT4Ver = DeblockLumaLt4V_AArch64_neon;
- pFunc->pfLumaDeblockingEQ4Ver = DeblockLumaEq4V_AArch64_neon;
- pFunc->pfLumaDeblockingLT4Hor = DeblockLumaLt4H_AArch64_neon;
- pFunc->pfLumaDeblockingEQ4Hor = DeblockLumaEq4H_AArch64_neon;
-
- pFunc->pfChromaDeblockingLT4Ver = DeblockChromaLt4V_AArch64_neon;
- pFunc->pfChromaDeblockingEQ4Ver = DeblockChromaEq4V_AArch64_neon;
- pFunc->pfChromaDeblockingLT4Hor = DeblockChromaLt4H_AArch64_neon;
- pFunc->pfChromaDeblockingEQ4Hor = DeblockChromaEq4H_AArch64_neon;
- }
-#endif
-}
-
-} // namespace WelsDec
+/*!
+ * \copy
+ * Copyright (c) 2010-2013, Cisco Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * \file deblocking.c
+ *
+ * \brief Interfaces introduced in frame deblocking filtering
+ *
+ * \date 08/02/2010
+ *
+ *************************************************************************************
+ */
+
+#include "deblocking.h"
+#include "deblocking_common.h"
+#include "cpu_core.h"
+
+namespace WelsDec {
+
+#define NO_SUPPORTED_FILTER_IDX (-1)
+#define LEFT_FLAG_BIT 0
+#define TOP_FLAG_BIT 1
+#define LEFT_FLAG_MASK 0x01
+#define TOP_FLAG_MASK 0x02
+
+#define SAME_MB_DIFF_REFIDX
+#define g_kuiAlphaTable(x) g_kuiAlphaTable[(x)+12]
+#define g_kiBetaTable(x) g_kiBetaTable[(x)+12]
+#define g_kiTc0Table(x) g_kiTc0Table[(x)+12]
+
+#define MB_BS_MV(iRefIndex, iMotionVector, iMbXy, iMbBn, iIndex, iNeighIndex) \
+(\
+ ( iRefIndex[iMbXy][iIndex] - iRefIndex[iMbBn][iNeighIndex] )||\
+ ( WELS_ABS( iMotionVector[iMbXy][iIndex][0] - iMotionVector[iMbBn][iNeighIndex][0] ) >= 4 ) ||\
+ ( WELS_ABS( iMotionVector[iMbXy][iIndex][1] - iMotionVector[iMbBn][iNeighIndex][1] ) >= 4 )\
+)
+
+#if defined(SAME_MB_DIFF_REFIDX)
+#define SMB_EDGE_MV(iRefIndex, iMotionVector, iIndex, iNeighIndex) \
+(\
+ ( iRefIndex[iIndex] - iRefIndex[iNeighIndex] )||(\
+ ( WELS_ABS( iMotionVector[iIndex][0] - iMotionVector[iNeighIndex][0] ) &(~3) ) |\
+ ( WELS_ABS( iMotionVector[iIndex][1] - iMotionVector[iNeighIndex][1] ) &(~3) ))\
+)
+#else
+#define SMB_EDGE_MV(iRefIndex, iMotionVector, iIndex, iNeighIndex) \
+(\
+ !!(( WELS_ABS( iMotionVector[iIndex][0] - iMotionVector[iNeighIndex][0] ) &(~3) ) |( WELS_ABS( iMotionVector[iIndex][1] - iMotionVector[iNeighIndex][1] ) &(~3) ))\
+)
+#endif
+
+#define BS_EDGE(bsx1, iRefIndex, iMotionVector, iIndex, iNeighIndex) \
+( (bsx1|SMB_EDGE_MV(iRefIndex, iMotionVector, iIndex, iNeighIndex))<<((uint8_t)(!!bsx1)))
+
+#define GET_ALPHA_BETA_FROM_QP(iQp, iAlphaOffset, iBetaOffset, iIndex, iAlpha, iBeta) \
+{\
+ iIndex = (iQp + iAlphaOffset);\
+ iAlpha = g_kuiAlphaTable(iIndex);\
+ iBeta = g_kiBetaTable((iQp + iBetaOffset));\
+}
+
+static const uint8_t g_kuiAlphaTable[52 + 24] = { //this table refers to Table 8-16 in H.264/AVC standard
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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
+ , 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
+};
+
+static const int8_t g_kiBetaTable[52 + 24] = { //this table refers to Table 8-16 in H.264/AVC standard
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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
+ , 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18
+};
+
+static const int8_t g_kiTc0Table[52 + 24][4] = { //this table refers Table 8-17 in H.264/AVC standard
+ { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 },
+ { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 },
+ { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 },
+ { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 },
+ { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 0 }, { -1, 0, 0, 1 },
+ { -1, 0, 0, 1 }, { -1, 0, 0, 1 }, { -1, 0, 0, 1 }, { -1, 0, 1, 1 }, { -1, 0, 1, 1 }, { -1, 1, 1, 1 },
+ { -1, 1, 1, 1 }, { -1, 1, 1, 1 }, { -1, 1, 1, 1 }, { -1, 1, 1, 2 }, { -1, 1, 1, 2 }, { -1, 1, 1, 2 },
+ { -1, 1, 1, 2 }, { -1, 1, 2, 3 }, { -1, 1, 2, 3 }, { -1, 2, 2, 3 }, { -1, 2, 2, 4 }, { -1, 2, 3, 4 },
+ { -1, 2, 3, 4 }, { -1, 3, 3, 5 }, { -1, 3, 4, 6 }, { -1, 3, 4, 6 }, { -1, 4, 5, 7 }, { -1, 4, 5, 8 },
+ { -1, 4, 6, 9 }, { -1, 5, 7, 10 }, { -1, 6, 8, 11 }, { -1, 6, 8, 13 }, { -1, 7, 10, 14 }, { -1, 8, 11, 16 },
+ { -1, 9, 12, 18 }, { -1, 10, 13, 20 }, { -1, 11, 15, 23 }, { -1, 13, 17, 25 }
+ , { -1, 13, 17, 25 }, { -1, 13, 17, 25 }, { -1, 13, 17, 25 }, { -1, 13, 17, 25 }, { -1, 13, 17, 25 }, { -1, 13, 17, 25 }
+ , { -1, 13, 17, 25 }, { -1, 13, 17, 25 }, { -1, 13, 17, 25 }, { -1, 13, 17, 25 }, { -1, 13, 17, 25 }, { -1, 13, 17, 25 }
+};
+
+static const uint8_t g_kuiTableBIdx[2][8] = {
+ {
+ 0, 4, 8, 12,
+ 3, 7, 11, 15
+ },
+
+ {
+ 0, 1, 2, 3,
+ 12, 13, 14, 15
+ },
+};
+
+static const uint8_t g_kuiTableB8x8Idx[2][16] = {
+ {
+ 0, 1, 4, 5, 8, 9, 12, 13, // 0 1 | 2 3
+ 2, 3, 6, 7, 10, 11, 14, 15 // 4 5 | 6 7
+ }, // ------------
+ // 8 9 | 10 11
+ {
+ // 12 13 | 14 15
+ 0, 1, 4, 5, 2, 3, 6, 7,
+ 8, 9, 12, 13, 10, 11, 14, 15
+ },
+};
+
+#define TC0_TBL_LOOKUP(tc, iIndexA, pBS, bChroma) \
+{\
+ tc[0] = g_kiTc0Table(iIndexA)[pBS[0]] + bChroma;\
+ tc[1] = g_kiTc0Table(iIndexA)[pBS[1]] + bChroma;\
+ tc[2] = g_kiTc0Table(iIndexA)[pBS[2]] + bChroma;\
+ tc[3] = g_kiTc0Table(iIndexA)[pBS[3]] + bChroma;\
+}
+
+void inline DeblockingBSInsideMBAvsbase (int8_t* pNnzTab, uint8_t nBS[2][4][4], int32_t iLShiftFactor) {
+ uint32_t uiNnz32b0, uiNnz32b1, uiNnz32b2, uiNnz32b3;
+
+ uiNnz32b0 = * (uint32_t*) (pNnzTab + 0);
+ uiNnz32b1 = * (uint32_t*) (pNnzTab + 4);
+ uiNnz32b2 = * (uint32_t*) (pNnzTab + 8);
+ uiNnz32b3 = * (uint32_t*) (pNnzTab + 12);
+
+ nBS[0][1][0] = (pNnzTab[0] | pNnzTab[1]) << iLShiftFactor;
+ nBS[0][2][0] = (pNnzTab[1] | pNnzTab[2]) << iLShiftFactor;
+ nBS[0][3][0] = (pNnzTab[2] | pNnzTab[3]) << iLShiftFactor;
+
+ nBS[0][1][1] = (pNnzTab[4] | pNnzTab[5]) << iLShiftFactor;
+ nBS[0][2][1] = (pNnzTab[5] | pNnzTab[6]) << iLShiftFactor;
+ nBS[0][3][1] = (pNnzTab[6] | pNnzTab[7]) << iLShiftFactor;
+ * (uint32_t*)nBS[1][1] = (uiNnz32b0 | uiNnz32b1) << iLShiftFactor;
+
+ nBS[0][1][2] = (pNnzTab[8] | pNnzTab[9]) << iLShiftFactor;
+ nBS[0][2][2] = (pNnzTab[9] | pNnzTab[10]) << iLShiftFactor;
+ nBS[0][3][2] = (pNnzTab[10] | pNnzTab[11]) << iLShiftFactor;
+ * (uint32_t*)nBS[1][2] = (uiNnz32b1 | uiNnz32b2) << iLShiftFactor;
+
+ nBS[0][1][3] = (pNnzTab[12] | pNnzTab[13]) << iLShiftFactor;
+ nBS[0][2][3] = (pNnzTab[13] | pNnzTab[14]) << iLShiftFactor;
+ nBS[0][3][3] = (pNnzTab[14] | pNnzTab[15]) << iLShiftFactor;
+ * (uint32_t*)nBS[1][3] = (uiNnz32b2 | uiNnz32b3) << iLShiftFactor;
+}
+
+void inline DeblockingBSInsideMBAvsbase8x8 (int8_t* pNnzTab, uint8_t nBS[2][4][4], int32_t iLShiftFactor) {
+ int8_t i8x8NnzTab[4];
+ for (int32_t i = 0; i < 4; i++) {
+ int32_t iBlkIdx = i << 2;
+ i8x8NnzTab[i] = (pNnzTab[g_kuiMbCountScan4Idx[iBlkIdx]] | pNnzTab[g_kuiMbCountScan4Idx[iBlkIdx + 1]] |
+ pNnzTab[g_kuiMbCountScan4Idx[iBlkIdx + 2]] | pNnzTab[g_kuiMbCountScan4Idx[iBlkIdx + 3]]);
+ }
+
+ //vertical
+ nBS[0][2][0] = nBS[0][2][1] = (i8x8NnzTab[0] | i8x8NnzTab[1]) << iLShiftFactor;
+ nBS[0][2][2] = nBS[0][2][3] = (i8x8NnzTab[2] | i8x8NnzTab[3]) << iLShiftFactor;
+ //horizontal
+ nBS[1][2][0] = nBS[1][2][1] = (i8x8NnzTab[0] | i8x8NnzTab[2]) << iLShiftFactor;
+ nBS[1][2][2] = nBS[1][2][3] = (i8x8NnzTab[1] | i8x8NnzTab[3]) << iLShiftFactor;
+}
+
+void static inline DeblockingBSInsideMBNormal (PDqLayer pCurDqLayer, uint8_t nBS[2][4][4], int8_t* pNnzTab,
+ int32_t iMbXy) {
+ uint32_t uiNnz32b0, uiNnz32b1, uiNnz32b2, uiNnz32b3;
+ int8_t* iRefIndex = pCurDqLayer->pRefIndex[LIST_0][iMbXy];
+ ENFORCE_STACK_ALIGN_1D (uint8_t, uiBsx4, 4, 4);
+
+ int8_t i8x8NnzTab[4];
+
+ if (pCurDqLayer->pTransformSize8x8Flag[iMbXy]) {
+ for (int32_t i = 0; i < 4; i++) {
+ int32_t iBlkIdx = i << 2;
+ i8x8NnzTab[i] = (pNnzTab[g_kuiMbCountScan4Idx[iBlkIdx]] | pNnzTab[g_kuiMbCountScan4Idx[iBlkIdx + 1]] |
+ pNnzTab[g_kuiMbCountScan4Idx[iBlkIdx + 2]] | pNnzTab[g_kuiMbCountScan4Idx[iBlkIdx + 3]]);
+ }
+ //vertical
+ nBS[0][2][0] = nBS[0][2][1] = BS_EDGE ((i8x8NnzTab[0] | i8x8NnzTab[1]), iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy],
+ g_kuiMbCountScan4Idx[1 << 2], g_kuiMbCountScan4Idx[0]);
+ nBS[0][2][2] = nBS[0][2][3] = BS_EDGE ((i8x8NnzTab[2] | i8x8NnzTab[3]), iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy],
+ g_kuiMbCountScan4Idx[3 << 2], g_kuiMbCountScan4Idx[2 << 2]);
+
+ //horizontal
+ nBS[1][2][0] = nBS[1][2][1] = BS_EDGE ((i8x8NnzTab[0] | i8x8NnzTab[2]), iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy],
+ g_kuiMbCountScan4Idx[2 << 2], g_kuiMbCountScan4Idx[0]);
+ nBS[1][2][2] = nBS[1][2][3] = BS_EDGE ((i8x8NnzTab[1] | i8x8NnzTab[3]), iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy],
+ g_kuiMbCountScan4Idx[3 << 2], g_kuiMbCountScan4Idx[1 << 2]);
+ } else {
+ uiNnz32b0 = * (uint32_t*) (pNnzTab + 0);
+ uiNnz32b1 = * (uint32_t*) (pNnzTab + 4);
+ uiNnz32b2 = * (uint32_t*) (pNnzTab + 8);
+ uiNnz32b3 = * (uint32_t*) (pNnzTab + 12);
+
+ for (int i = 0; i < 3; i++)
+ uiBsx4[i] = pNnzTab[i] | pNnzTab[i + 1];
+ nBS[0][1][0] = BS_EDGE (uiBsx4[0], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 1, 0);
+ nBS[0][2][0] = BS_EDGE (uiBsx4[1], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 2, 1);
+ nBS[0][3][0] = BS_EDGE (uiBsx4[2], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 3, 2);
+
+ for (int i = 0; i < 3; i++)
+ uiBsx4[i] = pNnzTab[4 + i] | pNnzTab[4 + i + 1];
+ nBS[0][1][1] = BS_EDGE (uiBsx4[0], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 5, 4);
+ nBS[0][2][1] = BS_EDGE (uiBsx4[1], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 6, 5);
+ nBS[0][3][1] = BS_EDGE (uiBsx4[2], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 7, 6);
+
+ for (int i = 0; i < 3; i++)
+ uiBsx4[i] = pNnzTab[8 + i] | pNnzTab[8 + i + 1];
+ nBS[0][1][2] = BS_EDGE (uiBsx4[0], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 9, 8);
+ nBS[0][2][2] = BS_EDGE (uiBsx4[1], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 10, 9);
+ nBS[0][3][2] = BS_EDGE (uiBsx4[2], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 11, 10);
+
+ for (int i = 0; i < 3; i++)
+ uiBsx4[i] = pNnzTab[12 + i] | pNnzTab[12 + i + 1];
+ nBS[0][1][3] = BS_EDGE (uiBsx4[0], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 13, 12);
+ nBS[0][2][3] = BS_EDGE (uiBsx4[1], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 14, 13);
+ nBS[0][3][3] = BS_EDGE (uiBsx4[2], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 15, 14);
+
+ // horizontal
+ * (uint32_t*)uiBsx4 = (uiNnz32b0 | uiNnz32b1);
+ nBS[1][1][0] = BS_EDGE (uiBsx4[0], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 4, 0);
+ nBS[1][1][1] = BS_EDGE (uiBsx4[1], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 5, 1);
+ nBS[1][1][2] = BS_EDGE (uiBsx4[2], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 6, 2);
+ nBS[1][1][3] = BS_EDGE (uiBsx4[3], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 7, 3);
+
+ * (uint32_t*)uiBsx4 = (uiNnz32b1 | uiNnz32b2);
+ nBS[1][2][0] = BS_EDGE (uiBsx4[0], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 8, 4);
+ nBS[1][2][1] = BS_EDGE (uiBsx4[1], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 9, 5);
+ nBS[1][2][2] = BS_EDGE (uiBsx4[2], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 10, 6);
+ nBS[1][2][3] = BS_EDGE (uiBsx4[3], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 11, 7);
+
+ * (uint32_t*)uiBsx4 = (uiNnz32b2 | uiNnz32b3);
+ nBS[1][3][0] = BS_EDGE (uiBsx4[0], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 12, 8);
+ nBS[1][3][1] = BS_EDGE (uiBsx4[1], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 13, 9);
+ nBS[1][3][2] = BS_EDGE (uiBsx4[2], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 14, 10);
+ nBS[1][3][3] = BS_EDGE (uiBsx4[3], iRefIndex, pCurDqLayer->pMv[LIST_0][iMbXy], 15, 11);
+ }
+}
+
+void static inline DeblockingBSliceBSInsideMBNormal (PDqLayer pCurDqLayer, uint8_t nBS[2][4][4], int8_t* pNnzTab,
+ int32_t iMbXy) {
+ uint32_t uiNnz32b0, uiNnz32b1, uiNnz32b2, uiNnz32b3;
+ int8_t* iRefIndex[LIST_A];
+ iRefIndex[LIST_0] = pCurDqLayer->pRefIndex[LIST_0][iMbXy];
+ iRefIndex[LIST_1] = pCurDqLayer->pRefIndex[LIST_1][iMbXy];
+ ENFORCE_STACK_ALIGN_1D (uint8_t, uiBsx4, 4, 4);
+
+ int8_t i8x8NnzTab[4];
+
+ if (pCurDqLayer->pTransformSize8x8Flag[iMbXy]) {
+ for (int32_t i = 0; i < 4; i++) {
+ int32_t iBlkIdx = i << 2;
+ i8x8NnzTab[i] = (pNnzTab[g_kuiMbCountScan4Idx[iBlkIdx]] | pNnzTab[g_kuiMbCountScan4Idx[iBlkIdx + 1]] |
+ pNnzTab[g_kuiMbCountScan4Idx[iBlkIdx + 2]] | pNnzTab[g_kuiMbCountScan4Idx[iBlkIdx + 3]]);
+ }
+ //vertical
+ int8_t iIndex = g_kuiMbCountScan4Idx[1 << 2];
+ int8_t iNeigborIndex = g_kuiMbCountScan4Idx[0];
+ nBS[0][2][0] = nBS[0][2][1] = 1;
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ if (iRefIndex[listIdx][iIndex] > REF_NOT_IN_LIST && iRefIndex[listIdx][iNeigborIndex] > REF_NOT_IN_LIST) {
+ nBS[0][2][0] = nBS[0][2][1] = BS_EDGE ((i8x8NnzTab[0] | i8x8NnzTab[1]), iRefIndex[listIdx],
+ pCurDqLayer->pMv[listIdx][iMbXy],
+ iIndex, iNeigborIndex);
+ break;
+ }
+ }
+ iIndex = g_kuiMbCountScan4Idx[3 << 2];
+ iNeigborIndex = g_kuiMbCountScan4Idx[2 << 2];
+ nBS[0][2][2] = nBS[0][2][3] = 1;
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ if (iRefIndex[listIdx][iIndex] > REF_NOT_IN_LIST && iRefIndex[listIdx][iNeigborIndex] > REF_NOT_IN_LIST) {
+ nBS[0][2][2] = nBS[0][2][3] = BS_EDGE ((i8x8NnzTab[2] | i8x8NnzTab[3]), iRefIndex[listIdx],
+ pCurDqLayer->pMv[listIdx][iMbXy],
+ iIndex, iNeigborIndex);
+ break;
+ }
+ }
+
+ //horizontal
+ iIndex = g_kuiMbCountScan4Idx[2 << 2];
+ iNeigborIndex = g_kuiMbCountScan4Idx[0];
+ nBS[1][2][0] = nBS[1][2][1] = 1;
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ if (iRefIndex[listIdx][iIndex] > REF_NOT_IN_LIST && iRefIndex[listIdx][iNeigborIndex] > REF_NOT_IN_LIST) {
+ nBS[1][2][0] = nBS[1][2][1] = BS_EDGE ((i8x8NnzTab[0] | i8x8NnzTab[2]), iRefIndex[listIdx],
+ pCurDqLayer->pMv[listIdx][iMbXy],
+ iIndex, iNeigborIndex);
+ break;
+ }
+ }
+
+ iIndex = g_kuiMbCountScan4Idx[3 << 2];
+ iNeigborIndex = g_kuiMbCountScan4Idx[1 << 2];
+ nBS[1][2][2] = nBS[1][2][3] = 1;
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ if (iRefIndex[listIdx][iIndex] > REF_NOT_IN_LIST && iRefIndex[listIdx][iNeigborIndex] > REF_NOT_IN_LIST) {
+ nBS[1][2][2] = nBS[1][2][3] = BS_EDGE ((i8x8NnzTab[1] | i8x8NnzTab[3]), iRefIndex[listIdx],
+ pCurDqLayer->pMv[listIdx][iMbXy],
+ iIndex, iNeigborIndex);
+ break;
+ }
+ }
+ } else {
+ uiNnz32b0 = * (uint32_t*) (pNnzTab + 0);
+ uiNnz32b1 = * (uint32_t*) (pNnzTab + 4);
+ uiNnz32b2 = * (uint32_t*) (pNnzTab + 8);
+ uiNnz32b3 = * (uint32_t*) (pNnzTab + 12);
+
+ for (int i = 0; i < 3; i++)
+ uiBsx4[i] = pNnzTab[i] | pNnzTab[i + 1];
+ nBS[0][1][0] = 1;
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ if (iRefIndex[listIdx][1] > REF_NOT_IN_LIST && iRefIndex[listIdx][0] > REF_NOT_IN_LIST) {
+ nBS[0][1][0] = BS_EDGE (uiBsx4[0], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 1, 0);
+ break;
+ }
+ }
+ nBS[0][2][0] = 1;
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ if (iRefIndex[listIdx][2] > REF_NOT_IN_LIST && iRefIndex[listIdx][1] > REF_NOT_IN_LIST) {
+ nBS[0][2][0] = BS_EDGE (uiBsx4[1], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 2, 1);
+ break;
+ }
+ }
+ nBS[0][3][0] = 1;
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ if (iRefIndex[listIdx][3] > REF_NOT_IN_LIST && iRefIndex[listIdx][2] > REF_NOT_IN_LIST) {
+ nBS[0][3][0] = BS_EDGE (uiBsx4[2], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 3, 2);
+ break;
+ }
+ }
+
+ for (int i = 0; i < 3; i++)
+ uiBsx4[i] = pNnzTab[4 + i] | pNnzTab[4 + i + 1];
+ nBS[0][1][1] = 1;
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ if (iRefIndex[listIdx][5] > REF_NOT_IN_LIST && iRefIndex[listIdx][4] > REF_NOT_IN_LIST) {
+ nBS[0][1][1] = BS_EDGE (uiBsx4[0], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 5, 4);
+ break;
+ }
+ }
+ nBS[0][2][1] = 1;
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ if (iRefIndex[listIdx][6] > REF_NOT_IN_LIST && iRefIndex[listIdx][5] > REF_NOT_IN_LIST) {
+ nBS[0][2][1] = BS_EDGE (uiBsx4[1], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 6, 5);
+ break;
+ }
+ }
+ nBS[0][3][1] = 1;
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ if (iRefIndex[listIdx][7] > REF_NOT_IN_LIST && iRefIndex[listIdx][6] > REF_NOT_IN_LIST) {
+ nBS[0][3][1] = BS_EDGE (uiBsx4[2], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 7, 6);
+ break;
+ }
+ }
+
+ for (int i = 0; i < 3; i++)
+ uiBsx4[i] = pNnzTab[8 + i] | pNnzTab[8 + i + 1];
+ nBS[0][1][2] = 1;
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ if (iRefIndex[listIdx][9] > REF_NOT_IN_LIST && iRefIndex[listIdx][8] > REF_NOT_IN_LIST) {
+ nBS[0][1][2] = BS_EDGE (uiBsx4[0], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 9, 8);
+ break;
+ }
+ }
+ nBS[0][2][2] = 1;
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ if (iRefIndex[listIdx][10] > REF_NOT_IN_LIST && iRefIndex[listIdx][9] > REF_NOT_IN_LIST) {
+ nBS[0][2][2] = BS_EDGE (uiBsx4[1], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 10, 9);
+ break;
+ }
+ }
+ nBS[0][3][2] = 1;
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ if (iRefIndex[listIdx][11] > REF_NOT_IN_LIST && iRefIndex[listIdx][10] > REF_NOT_IN_LIST) {
+ nBS[0][3][2] = BS_EDGE (uiBsx4[2], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 11, 10);
+ break;
+ }
+ }
+
+ for (int i = 0; i < 3; i++)
+ uiBsx4[i] = pNnzTab[12 + i] | pNnzTab[12 + i + 1];
+ nBS[0][1][3] = 1;
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ if (iRefIndex[listIdx][13] > REF_NOT_IN_LIST && iRefIndex[listIdx][12] > REF_NOT_IN_LIST) {
+ nBS[0][1][3] = BS_EDGE (uiBsx4[0], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 13, 12);
+ break;
+ }
+ }
+ nBS[0][2][3] = 1;
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ if (iRefIndex[listIdx][14] > REF_NOT_IN_LIST && iRefIndex[listIdx][13] > REF_NOT_IN_LIST) {
+ nBS[0][2][3] = BS_EDGE (uiBsx4[1], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 14, 13);
+ break;
+ }
+ }
+ nBS[0][3][3] = 1;
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ if (iRefIndex[listIdx][15] > REF_NOT_IN_LIST && iRefIndex[listIdx][14] > REF_NOT_IN_LIST) {
+ nBS[0][3][3] = BS_EDGE (uiBsx4[2], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 15, 14);
+ break;
+ }
+ }
+
+ // horizontal
+ * (uint32_t*)uiBsx4 = (uiNnz32b0 | uiNnz32b1);
+ nBS[1][1][0] = 1;
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ if (iRefIndex[listIdx][4] > REF_NOT_IN_LIST && iRefIndex[listIdx][0] > REF_NOT_IN_LIST) {
+ nBS[1][1][0] = BS_EDGE (uiBsx4[0], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 4, 0);
+ break;
+ }
+ }
+ nBS[1][1][1] = 1;
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ if (iRefIndex[listIdx][5] > REF_NOT_IN_LIST && iRefIndex[listIdx][1] > REF_NOT_IN_LIST) {
+ nBS[1][1][1] = BS_EDGE (uiBsx4[1], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 5, 1);
+ break;
+ }
+ }
+ nBS[1][1][2] = 1;
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ if (iRefIndex[listIdx][6] > REF_NOT_IN_LIST && iRefIndex[listIdx][2] > REF_NOT_IN_LIST) {
+ nBS[1][1][2] = BS_EDGE (uiBsx4[2], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 6, 2);
+ break;
+ }
+ }
+ nBS[1][1][3] = 1;
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ if (iRefIndex[listIdx][7] > REF_NOT_IN_LIST && iRefIndex[listIdx][3] > REF_NOT_IN_LIST) {
+ nBS[1][1][3] = BS_EDGE (uiBsx4[3], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 7, 3);
+ break;
+ }
+ }
+
+ * (uint32_t*)uiBsx4 = (uiNnz32b1 | uiNnz32b2);
+ nBS[1][2][0] = 1;
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ if (iRefIndex[listIdx][8] > REF_NOT_IN_LIST && iRefIndex[listIdx][4] > REF_NOT_IN_LIST) {
+ nBS[1][2][0] = BS_EDGE (uiBsx4[0], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 8, 4);
+ break;
+ }
+ }
+ nBS[1][2][1] = 1;
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ if (iRefIndex[listIdx][9] > REF_NOT_IN_LIST && iRefIndex[listIdx][5] > REF_NOT_IN_LIST) {
+ nBS[1][2][1] = BS_EDGE (uiBsx4[1], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 9, 5);
+ break;
+ }
+ }
+ nBS[1][2][2] = 1;
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ if (iRefIndex[listIdx][10] > REF_NOT_IN_LIST && iRefIndex[listIdx][6] > REF_NOT_IN_LIST) {
+ nBS[1][2][2] = BS_EDGE (uiBsx4[2], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 10, 6);
+ break;
+ }
+ }
+ nBS[1][2][3] = 1;
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ if (iRefIndex[listIdx][11] > REF_NOT_IN_LIST && iRefIndex[listIdx][7] > REF_NOT_IN_LIST) {
+ nBS[1][2][3] = BS_EDGE (uiBsx4[3], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 11, 7);
+ break;
+ }
+ }
+
+ * (uint32_t*)uiBsx4 = (uiNnz32b2 | uiNnz32b3);
+ nBS[1][3][0] = 1;
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ if (iRefIndex[listIdx][12] > REF_NOT_IN_LIST && iRefIndex[listIdx][8] > REF_NOT_IN_LIST) {
+ nBS[1][3][0] = BS_EDGE (uiBsx4[0], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 12, 8);
+ break;
+ }
+ }
+ nBS[1][3][1] = 1;
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ if (iRefIndex[listIdx][13] > REF_NOT_IN_LIST && iRefIndex[listIdx][9] > REF_NOT_IN_LIST) {
+ nBS[1][3][1] = BS_EDGE (uiBsx4[1], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 13, 9);
+ break;
+ }
+ }
+ nBS[1][3][2] = 1;
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ if (iRefIndex[listIdx][14] > REF_NOT_IN_LIST && iRefIndex[listIdx][10] > REF_NOT_IN_LIST) {
+ nBS[1][3][2] = BS_EDGE (uiBsx4[2], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 14, 10);
+ break;
+ }
+ }
+ nBS[1][3][3] = 1;
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ if (iRefIndex[listIdx][15] > REF_NOT_IN_LIST && iRefIndex[listIdx][11] > REF_NOT_IN_LIST) {
+ nBS[1][3][3] = BS_EDGE (uiBsx4[3], iRefIndex[listIdx], pCurDqLayer->pMv[listIdx][iMbXy], 15, 11);
+ break;
+ }
+ }
+ }
+}
+
+
+uint32_t DeblockingBsMarginalMBAvcbase (PDqLayer pCurDqLayer, int32_t iEdge, int32_t iNeighMb, int32_t iMbXy) {
+ int32_t i, j;
+ uint32_t uiBSx4;
+ uint8_t* pBS = (uint8_t*) (&uiBSx4);
+ const uint8_t* pBIdx = &g_kuiTableBIdx[iEdge][0];
+ const uint8_t* pBnIdx = &g_kuiTableBIdx[iEdge][4];
+ const uint8_t* pB8x8Idx = &g_kuiTableB8x8Idx[iEdge][0];
+ const uint8_t* pBn8x8Idx = &g_kuiTableB8x8Idx[iEdge][8];
+
+ if (pCurDqLayer->pTransformSize8x8Flag[iMbXy] && pCurDqLayer->pTransformSize8x8Flag[iNeighMb]) {
+ for (i = 0; i < 2; i++) {
+ uint8_t uiNzc = 0;
+ for (j = 0; uiNzc == 0 && j < 4; j++) {
+ uiNzc |= (pCurDqLayer->pNzc[iMbXy][* (pB8x8Idx + j)] | pCurDqLayer->pNzc[iNeighMb][* (pBn8x8Idx + j)]);
+ }
+ if (uiNzc) {
+ pBS[i << 1] = pBS[1 + (i << 1)] = 2;
+ } else {
+ pBS[i << 1] = pBS[1 + (i << 1)] = MB_BS_MV (pCurDqLayer->pRefIndex[LIST_0], pCurDqLayer->pMv[LIST_0], iMbXy, iNeighMb,
+ *pB8x8Idx, *pBn8x8Idx);
+ }
+ pB8x8Idx += 4;
+ pBn8x8Idx += 4;
+ }
+ } else if (pCurDqLayer->pTransformSize8x8Flag[iMbXy]) {
+ for (i = 0; i < 2; i++) {
+ uint8_t uiNzc = 0;
+ for (j = 0; uiNzc == 0 && j < 4; j++) {
+ uiNzc |= pCurDqLayer->pNzc[iMbXy][* (pB8x8Idx + j)];
+ }
+ for (j = 0; j < 2; j++) {
+ if (uiNzc | pCurDqLayer->pNzc[iNeighMb][*pBnIdx]) {
+ pBS[j + (i << 1)] = 2;
+ } else {
+ pBS[j + (i << 1)] = MB_BS_MV (pCurDqLayer->pRefIndex[LIST_0], pCurDqLayer->pMv[LIST_0], iMbXy, iNeighMb, *pB8x8Idx,
+ *pBnIdx);
+ }
+ pBnIdx++;
+ }
+ pB8x8Idx += 4;
+ }
+ } else if (pCurDqLayer->pTransformSize8x8Flag[iNeighMb]) {
+ for (i = 0; i < 2; i++) {
+ uint8_t uiNzc = 0;
+ for (j = 0; uiNzc == 0 && j < 4; j++) {
+ uiNzc |= pCurDqLayer->pNzc[iNeighMb][* (pBn8x8Idx + j)];
+ }
+ for (j = 0; j < 2; j++) {
+ if (uiNzc | pCurDqLayer->pNzc[iMbXy][*pBIdx]) {
+ pBS[j + (i << 1)] = 2;
+ } else {
+ pBS[j + (i << 1)] = MB_BS_MV (pCurDqLayer->pRefIndex[LIST_0], pCurDqLayer->pMv[LIST_0], iMbXy, iNeighMb, *pBIdx,
+ *pBn8x8Idx);
+ }
+ pBIdx++;
+ }
+ pBn8x8Idx += 4;
+ }
+ } else {
+ // only 4x4 transform
+ for (i = 0; i < 4; i++) {
+ if (pCurDqLayer->pNzc[iMbXy][*pBIdx] | pCurDqLayer->pNzc[iNeighMb][*pBnIdx]) {
+ pBS[i] = 2;
+ } else {
+ pBS[i] = MB_BS_MV (pCurDqLayer->pRefIndex[LIST_0], pCurDqLayer->pMv[LIST_0], iMbXy, iNeighMb, *pBIdx,
+ *pBnIdx);
+ }
+ pBIdx++;
+ pBnIdx++;
+ }
+ }
+
+ return uiBSx4;
+}
+uint32_t DeblockingBSliceBsMarginalMBAvcbase (PDqLayer pCurDqLayer, int32_t iEdge, int32_t iNeighMb, int32_t iMbXy) {
+ int32_t i, j;
+ uint32_t uiBSx4;
+ uint8_t* pBS = (uint8_t*) (&uiBSx4);
+ const uint8_t* pBIdx = &g_kuiTableBIdx[iEdge][0];
+ const uint8_t* pBnIdx = &g_kuiTableBIdx[iEdge][4];
+ const uint8_t* pB8x8Idx = &g_kuiTableB8x8Idx[iEdge][0];
+ const uint8_t* pBn8x8Idx = &g_kuiTableB8x8Idx[iEdge][8];
+
+ if (pCurDqLayer->pTransformSize8x8Flag[iMbXy] && pCurDqLayer->pTransformSize8x8Flag[iNeighMb]) {
+ for (i = 0; i < 2; i++) {
+ uint8_t uiNzc = 0;
+ for (j = 0; uiNzc == 0 && j < 4; j++) {
+ uiNzc |= (pCurDqLayer->pNzc[iMbXy][* (pB8x8Idx + j)] | pCurDqLayer->pNzc[iNeighMb][* (pBn8x8Idx + j)]);
+ }
+ if (uiNzc) {
+ pBS[i << 1] = pBS[1 + (i << 1)] = 2;
+ } else {
+ pBS[i << 1] = pBS[1 + (i << 1)] = 1;
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ if (pCurDqLayer->pRefIndex[listIdx][iMbXy][*pB8x8Idx] > REF_NOT_IN_LIST
+ && pCurDqLayer->pRefIndex[listIdx][iMbXy][*pBn8x8Idx] > REF_NOT_IN_LIST) {
+ pBS[i << 1] = pBS[1 + (i << 1)] = MB_BS_MV (pCurDqLayer->pRefIndex[listIdx], pCurDqLayer->pMv[listIdx], iMbXy, iNeighMb,
+ *pB8x8Idx, *pBn8x8Idx);
+ break;
+ }
+ }
+ }
+ pB8x8Idx += 4;
+ pBn8x8Idx += 4;
+ }
+ } else if (pCurDqLayer->pTransformSize8x8Flag[iMbXy]) {
+ for (i = 0; i < 2; i++) {
+ uint8_t uiNzc = 0;
+ for (j = 0; uiNzc == 0 && j < 4; j++) {
+ uiNzc |= pCurDqLayer->pNzc[iMbXy][* (pB8x8Idx + j)];
+ }
+ for (j = 0; j < 2; j++) {
+ if (uiNzc | pCurDqLayer->pNzc[iNeighMb][*pBnIdx]) {
+ pBS[j + (i << 1)] = 2;
+ } else {
+ pBS[j + (i << 1)] = 1;
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ if (pCurDqLayer->pRefIndex[listIdx][iMbXy][*pB8x8Idx] > REF_NOT_IN_LIST
+ && pCurDqLayer->pRefIndex[listIdx][iMbXy][*pBnIdx] > REF_NOT_IN_LIST) {
+ pBS[j + (i << 1)] = MB_BS_MV (pCurDqLayer->pRefIndex[listIdx], pCurDqLayer->pMv[listIdx], iMbXy, iNeighMb, *pB8x8Idx,
+ *pBnIdx);
+ break;
+ }
+ }
+ }
+ pBnIdx++;
+ }
+ pB8x8Idx += 4;
+ }
+ } else if (pCurDqLayer->pTransformSize8x8Flag[iNeighMb]) {
+ for (i = 0; i < 2; i++) {
+ uint8_t uiNzc = 0;
+ for (j = 0; uiNzc == 0 && j < 4; j++) {
+ uiNzc |= pCurDqLayer->pNzc[iNeighMb][* (pBn8x8Idx + j)];
+ }
+ for (j = 0; j < 2; j++) {
+ if (uiNzc | pCurDqLayer->pNzc[iMbXy][*pBIdx]) {
+ pBS[j + (i << 1)] = 2;
+ } else {
+ pBS[j + (i << 1)] = 1;
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ if (pCurDqLayer->pRefIndex[listIdx][iMbXy][*pBIdx] > REF_NOT_IN_LIST
+ && pCurDqLayer->pRefIndex[listIdx][iMbXy][*pBn8x8Idx] > REF_NOT_IN_LIST) {
+ pBS[j + (i << 1)] = MB_BS_MV (pCurDqLayer->pRefIndex[listIdx], pCurDqLayer->pMv[listIdx], iMbXy, iNeighMb, *pBIdx,
+ *pBn8x8Idx);
+ break;
+ }
+ }
+ }
+ pBIdx++;
+ }
+ pBn8x8Idx += 4;
+ }
+ } else {
+ // only 4x4 transform
+ for (i = 0; i < 4; i++) {
+ if (pCurDqLayer->pNzc[iMbXy][*pBIdx] | pCurDqLayer->pNzc[iNeighMb][*pBnIdx]) {
+ pBS[i] = 2;
+ } else {
+ pBS[i] = 1;
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ if (pCurDqLayer->pRefIndex[listIdx][iMbXy][*pBIdx] > REF_NOT_IN_LIST
+ && pCurDqLayer->pRefIndex[listIdx][iMbXy][*pBnIdx] > REF_NOT_IN_LIST) {
+ pBS[i] = MB_BS_MV (pCurDqLayer->pRefIndex[listIdx], pCurDqLayer->pMv[listIdx], iMbXy, iNeighMb, *pBIdx, *pBnIdx);
+ break;
+ }
+ }
+ }
+ pBIdx++;
+ pBnIdx++;
+ }
+ }
+
+ return uiBSx4;
+}
+int32_t DeblockingAvailableNoInterlayer (PDqLayer pCurDqLayer, int32_t iFilterIdc) {
+ int32_t iMbY = pCurDqLayer->iMbY;
+ int32_t iMbX = pCurDqLayer->iMbX;
+ int32_t iMbXy = pCurDqLayer->iMbXyIndex;
+ bool bLeftFlag = false;
+ bool bTopFlag = false;
+
+ if (2 == iFilterIdc) {
+ bLeftFlag = (iMbX > 0) && (pCurDqLayer->pSliceIdc[iMbXy] == pCurDqLayer->pSliceIdc[iMbXy - 1]);
+ bTopFlag = (iMbY > 0) && (pCurDqLayer->pSliceIdc[iMbXy] == pCurDqLayer->pSliceIdc[iMbXy - pCurDqLayer->iMbWidth]);
+ } else { //if ( 0 == iFilterIdc )
+ bLeftFlag = (iMbX > 0);
+ bTopFlag = (iMbY > 0);
+ }
+ return (bLeftFlag << LEFT_FLAG_BIT) | (bTopFlag << TOP_FLAG_BIT);
+}
+
+void FilteringEdgeLumaH (SDeblockingFilter* pFilter, uint8_t* pPix, int32_t iStride, uint8_t* pBS) {
+ int32_t iIndexA;
+ int32_t iAlpha;
+ int32_t iBeta;
+ ENFORCE_STACK_ALIGN_1D (int8_t, tc, 4, 16);
+
+ GET_ALPHA_BETA_FROM_QP (pFilter->iLumaQP, pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
+ iBeta);
+
+ if (iAlpha | iBeta) {
+ TC0_TBL_LOOKUP (tc, iIndexA, pBS, 0);
+ pFilter->pLoopf->pfLumaDeblockingLT4Ver (pPix, iStride, iAlpha, iBeta, tc);
+ }
+ return;
+}
+
+
+void FilteringEdgeLumaV (SDeblockingFilter* pFilter, uint8_t* pPix, int32_t iStride, uint8_t* pBS) {
+ int32_t iIndexA;
+ int32_t iAlpha;
+ int32_t iBeta;
+ ENFORCE_STACK_ALIGN_1D (int8_t, tc, 4, 16);
+
+ GET_ALPHA_BETA_FROM_QP (pFilter->iLumaQP, pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
+ iBeta);
+
+ if (iAlpha | iBeta) {
+ TC0_TBL_LOOKUP (tc, iIndexA, pBS, 0);
+ pFilter->pLoopf->pfLumaDeblockingLT4Hor (pPix, iStride, iAlpha, iBeta, tc);
+ }
+ return;
+}
+
+
+void FilteringEdgeLumaIntraH (SDeblockingFilter* pFilter, uint8_t* pPix, int32_t iStride, uint8_t* pBS) {
+ int32_t iIndexA;
+ int32_t iAlpha;
+ int32_t iBeta;
+
+ GET_ALPHA_BETA_FROM_QP (pFilter->iLumaQP, pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
+ iBeta);
+
+ if (iAlpha | iBeta) {
+ pFilter->pLoopf->pfLumaDeblockingEQ4Ver (pPix, iStride, iAlpha, iBeta);
+ }
+ return;
+}
+
+void FilteringEdgeLumaIntraV (SDeblockingFilter* pFilter, uint8_t* pPix, int32_t iStride, uint8_t* pBS) {
+ int32_t iIndexA;
+ int32_t iAlpha;
+ int32_t iBeta;
+
+ GET_ALPHA_BETA_FROM_QP (pFilter->iLumaQP, pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
+ iBeta);
+
+ if (iAlpha | iBeta) {
+ pFilter->pLoopf->pfLumaDeblockingEQ4Hor (pPix, iStride, iAlpha, iBeta);
+ }
+ return;
+}
+void FilteringEdgeChromaH (SDeblockingFilter* pFilter, uint8_t* pPixCb, uint8_t* pPixCr, int32_t iStride,
+ uint8_t* pBS) {
+ int32_t iIndexA;
+ int32_t iAlpha;
+ int32_t iBeta;
+ ENFORCE_STACK_ALIGN_1D (int8_t, tc, 4, 16);
+ if (pFilter->iChromaQP[0] == pFilter->iChromaQP[1]) {
+
+ GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP[0], pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
+ iBeta);
+
+ if (iAlpha | iBeta) {
+ TC0_TBL_LOOKUP (tc, iIndexA, pBS, 1);
+ pFilter->pLoopf->pfChromaDeblockingLT4Ver (pPixCb, pPixCr, iStride, iAlpha, iBeta, tc);
+ }
+ } else {
+
+ for (int i = 0; i < 2; i++) {
+
+
+ GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP[i], pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
+ iBeta);
+
+ if (iAlpha | iBeta) {
+ uint8_t* pPixCbCr = (i == 0) ? pPixCb : pPixCr;
+ TC0_TBL_LOOKUP (tc, iIndexA, pBS, 1);
+ pFilter->pLoopf->pfChromaDeblockingLT4Ver2 (pPixCbCr, iStride, iAlpha, iBeta, tc);
+ }
+
+
+
+ }
+
+ }
+ return;
+}
+void FilteringEdgeChromaV (SDeblockingFilter* pFilter, uint8_t* pPixCb, uint8_t* pPixCr, int32_t iStride,
+ uint8_t* pBS) {
+ int32_t iIndexA;
+ int32_t iAlpha;
+ int32_t iBeta;
+ ENFORCE_STACK_ALIGN_1D (int8_t, tc, 4, 16);
+ if (pFilter->iChromaQP[0] == pFilter->iChromaQP[1]) {
+
+
+ GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP[0], pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
+ iBeta);
+
+ if (iAlpha | iBeta) {
+ TC0_TBL_LOOKUP (tc, iIndexA, pBS, 1);
+ pFilter->pLoopf->pfChromaDeblockingLT4Hor (pPixCb, pPixCr, iStride, iAlpha, iBeta, tc);
+ }
+
+
+ } else {
+
+ for (int i = 0; i < 2; i++) {
+
+ GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP[i], pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
+ iBeta);
+
+ if (iAlpha | iBeta) {
+ uint8_t* pPixCbCr = (i == 0) ? pPixCb : pPixCr;
+ TC0_TBL_LOOKUP (tc, iIndexA, pBS, 1);
+ pFilter->pLoopf->pfChromaDeblockingLT4Hor2 (pPixCbCr, iStride, iAlpha, iBeta, tc);
+ }
+
+
+ }
+ }
+ return;
+}
+
+void FilteringEdgeChromaIntraH (SDeblockingFilter* pFilter, uint8_t* pPixCb, uint8_t* pPixCr, int32_t iStride,
+ uint8_t* pBS) {
+ int32_t iIndexA;
+ int32_t iAlpha;
+ int32_t iBeta;
+ if (pFilter->iChromaQP[0] == pFilter->iChromaQP[1]) {
+
+ GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP[0], pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
+ iBeta);
+
+ if (iAlpha | iBeta) {
+ pFilter->pLoopf->pfChromaDeblockingEQ4Ver (pPixCb, pPixCr, iStride, iAlpha, iBeta);
+ }
+ } else {
+
+ for (int i = 0; i < 2; i++) {
+
+ GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP[i], pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
+ iBeta);
+
+ if (iAlpha | iBeta) {
+ uint8_t* pPixCbCr = (i == 0) ? pPixCb : pPixCr;
+ pFilter->pLoopf->pfChromaDeblockingEQ4Ver2 (pPixCbCr, iStride, iAlpha, iBeta);
+ }
+
+ }
+ }
+ return;
+}
+
+void FilteringEdgeChromaIntraV (SDeblockingFilter* pFilter, uint8_t* pPixCb, uint8_t* pPixCr, int32_t iStride,
+ uint8_t* pBS) {
+ int32_t iIndexA;
+ int32_t iAlpha;
+ int32_t iBeta;
+ if (pFilter->iChromaQP[0] == pFilter->iChromaQP[1]) { // QP of cb and cr are the same
+
+
+
+
+ GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP[0], pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
+ iBeta);
+ if (iAlpha | iBeta) {
+ pFilter->pLoopf->pfChromaDeblockingEQ4Hor (pPixCb, pPixCr, iStride, iAlpha, iBeta);
+ }
+ } else {
+
+ for (int i = 0; i < 2; i++) {
+
+
+ GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP[i], pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
+ iBeta);
+ if (iAlpha | iBeta) {
+ uint8_t* pPixCbCr = (i == 0) ? pPixCb : pPixCr;
+ pFilter->pLoopf->pfChromaDeblockingEQ4Hor2 (pPixCbCr, iStride, iAlpha, iBeta);
+ }
+ }
+
+ }
+ return;
+}
+
+
+void DeblockingInterMb (PDqLayer pCurDqLayer, PDeblockingFilter pFilter, uint8_t nBS[2][4][4],
+ int32_t iBoundryFlag) {
+ int32_t iMbXyIndex = pCurDqLayer->iMbXyIndex;
+ int32_t iMbX = pCurDqLayer->iMbX;
+ int32_t iMbY = pCurDqLayer->iMbY;
+
+ int32_t iCurLumaQp = pCurDqLayer->pLumaQp[iMbXyIndex];
+ //int32_t* iCurChromaQp = pCurDqLayer->pChromaQp[iMbXyIndex];
+ int8_t* pCurChromaQp = pCurDqLayer->pChromaQp[iMbXyIndex];
+ int32_t iLineSize = pFilter->iCsStride[0];
+ int32_t iLineSizeUV = pFilter->iCsStride[1];
+
+ uint8_t* pDestY, * pDestCb, * pDestCr;
+ pDestY = pFilter->pCsData[0] + ((iMbY * iLineSize + iMbX) << 4);
+ pDestCb = pFilter->pCsData[1] + ((iMbY * iLineSizeUV + iMbX) << 3);
+ pDestCr = pFilter->pCsData[2] + ((iMbY * iLineSizeUV + iMbX) << 3);
+
+//Vertical margrin
+ if (iBoundryFlag & LEFT_FLAG_MASK) {
+ int32_t iLeftXyIndex = iMbXyIndex - 1;
+ pFilter->iLumaQP = (iCurLumaQp + pCurDqLayer->pLumaQp[iLeftXyIndex] + 1) >> 1;
+ for (int i = 0; i < 2; i++) {
+ pFilter->iChromaQP[i] = (pCurChromaQp[i] + pCurDqLayer->pChromaQp[iLeftXyIndex][i] + 1) >> 1;
+ }
+ if (nBS[0][0][0] == 0x04) {
+ FilteringEdgeLumaIntraV (pFilter, pDestY, iLineSize, NULL);
+ FilteringEdgeChromaIntraV (pFilter, pDestCb, pDestCr, iLineSizeUV, NULL);
+ } else {
+ if (* (uint32_t*)nBS[0][0] != 0) {
+ FilteringEdgeLumaV (pFilter, pDestY, iLineSize, nBS[0][0]);
+ FilteringEdgeChromaV (pFilter, pDestCb, pDestCr, iLineSizeUV, nBS[0][0]);
+ }
+ }
+ }
+
+ pFilter->iLumaQP = iCurLumaQp;
+ pFilter->iChromaQP[0] = pCurChromaQp[0];
+ pFilter->iChromaQP[1] = pCurChromaQp[1];
+
+ if (* (uint32_t*)nBS[0][1] != 0 && !pCurDqLayer->pTransformSize8x8Flag[iMbXyIndex]) {
+ FilteringEdgeLumaV (pFilter, &pDestY[1 << 2], iLineSize, nBS[0][1]);
+ }
+
+ if (* (uint32_t*)nBS[0][2] != 0) {
+ FilteringEdgeLumaV (pFilter, &pDestY[2 << 2], iLineSize, nBS[0][2]);
+ FilteringEdgeChromaV (pFilter, &pDestCb[2 << 1], &pDestCr[2 << 1], iLineSizeUV, nBS[0][2]);
+ }
+
+ if (* (uint32_t*)nBS[0][3] != 0 && !pCurDqLayer->pTransformSize8x8Flag[iMbXyIndex]) {
+ FilteringEdgeLumaV (pFilter, &pDestY[3 << 2], iLineSize, nBS[0][3]);
+ }
+
+ if (iBoundryFlag & TOP_FLAG_MASK) {
+ int32_t iTopXyIndex = iMbXyIndex - pCurDqLayer->iMbWidth;
+ pFilter->iLumaQP = (iCurLumaQp + pCurDqLayer->pLumaQp[iTopXyIndex] + 1) >> 1;
+ for (int i = 0; i < 2; i++) {
+ pFilter->iChromaQP[i] = (pCurChromaQp[i] + pCurDqLayer->pChromaQp[iTopXyIndex][i] + 1) >> 1;
+ }
+
+ if (nBS[1][0][0] == 0x04) {
+ FilteringEdgeLumaIntraH (pFilter, pDestY, iLineSize, NULL);
+ FilteringEdgeChromaIntraH (pFilter, pDestCb, pDestCr, iLineSizeUV, NULL);
+ } else {
+ if (* (uint32_t*)nBS[1][0] != 0) {
+ FilteringEdgeLumaH (pFilter, pDestY, iLineSize, nBS[1][0]);
+ FilteringEdgeChromaH (pFilter, pDestCb, pDestCr, iLineSizeUV, nBS[1][0]);
+ }
+ }
+ }
+
+ pFilter->iLumaQP = iCurLumaQp;
+ pFilter->iChromaQP[0] = pCurChromaQp[0];
+ pFilter->iChromaQP[1] = pCurChromaQp[1];
+
+ if (* (uint32_t*)nBS[1][1] != 0 && !pCurDqLayer->pTransformSize8x8Flag[iMbXyIndex]) {
+ FilteringEdgeLumaH (pFilter, &pDestY[ (1 << 2)*iLineSize], iLineSize, nBS[1][1]);
+ }
+
+ if (* (uint32_t*)nBS[1][2] != 0) {
+ FilteringEdgeLumaH (pFilter, &pDestY[ (2 << 2)*iLineSize], iLineSize, nBS[1][2]);
+ FilteringEdgeChromaH (pFilter, &pDestCb[ (2 << 1)*iLineSizeUV], &pDestCr[ (2 << 1)*iLineSizeUV], iLineSizeUV,
+ nBS[1][2]);
+ }
+
+ if (* (uint32_t*)nBS[1][3] != 0 && !pCurDqLayer->pTransformSize8x8Flag[iMbXyIndex]) {
+ FilteringEdgeLumaH (pFilter, &pDestY[ (3 << 2)*iLineSize], iLineSize, nBS[1][3]);
+ }
+}
+
+void FilteringEdgeLumaHV (PDqLayer pCurDqLayer, PDeblockingFilter pFilter, int32_t iBoundryFlag) {
+ int32_t iMbXyIndex = pCurDqLayer->iMbXyIndex;
+ int32_t iMbX = pCurDqLayer->iMbX;
+ int32_t iMbY = pCurDqLayer->iMbY;
+ int32_t iMbWidth = pCurDqLayer->iMbWidth;
+ int32_t iLineSize = pFilter->iCsStride[0];
+
+ uint8_t* pDestY;
+ int32_t iCurQp;
+ int32_t iIndexA, iAlpha, iBeta;
+
+ ENFORCE_STACK_ALIGN_1D (int8_t, iTc, 4, 16);
+ ENFORCE_STACK_ALIGN_1D (uint8_t, uiBSx4, 4, 4);
+
+ pDestY = pFilter->pCsData[0] + ((iMbY * iLineSize + iMbX) << 4);
+ iCurQp = pCurDqLayer->pLumaQp[iMbXyIndex];
+
+ * (uint32_t*)uiBSx4 = 0x03030303;
+
+ // luma v
+ if (iBoundryFlag & LEFT_FLAG_MASK) {
+ pFilter->iLumaQP = (iCurQp + pCurDqLayer->pLumaQp[iMbXyIndex - 1] + 1) >> 1;
+ FilteringEdgeLumaIntraV (pFilter, pDestY, iLineSize, NULL);
+ }
+
+ pFilter->iLumaQP = iCurQp;
+ GET_ALPHA_BETA_FROM_QP (pFilter->iLumaQP, pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
+ iBeta);
+ if (iAlpha | iBeta) {
+ TC0_TBL_LOOKUP (iTc, iIndexA, uiBSx4, 0);
+
+ if (!pCurDqLayer->pTransformSize8x8Flag[iMbXyIndex]) {
+ pFilter->pLoopf->pfLumaDeblockingLT4Hor (&pDestY[1 << 2], iLineSize, iAlpha, iBeta, iTc);
+ }
+
+ pFilter->pLoopf->pfLumaDeblockingLT4Hor (&pDestY[2 << 2], iLineSize, iAlpha, iBeta, iTc);
+
+ if (!pCurDqLayer->pTransformSize8x8Flag[iMbXyIndex]) {
+ pFilter->pLoopf->pfLumaDeblockingLT4Hor (&pDestY[3 << 2], iLineSize, iAlpha, iBeta, iTc);
+ }
+ }
+
+ // luma h
+ if (iBoundryFlag & TOP_FLAG_MASK) {
+ pFilter->iLumaQP = (iCurQp + pCurDqLayer->pLumaQp[iMbXyIndex - iMbWidth] + 1) >> 1;
+ FilteringEdgeLumaIntraH (pFilter, pDestY, iLineSize, NULL);
+ }
+
+ pFilter->iLumaQP = iCurQp;
+ if (iAlpha | iBeta) {
+ if (!pCurDqLayer->pTransformSize8x8Flag[iMbXyIndex]) {
+ pFilter->pLoopf->pfLumaDeblockingLT4Ver (&pDestY[ (1 << 2)*iLineSize], iLineSize, iAlpha, iBeta, iTc);
+ }
+
+ pFilter->pLoopf->pfLumaDeblockingLT4Ver (&pDestY[ (2 << 2)*iLineSize], iLineSize, iAlpha, iBeta, iTc);
+
+ if (!pCurDqLayer->pTransformSize8x8Flag[iMbXyIndex]) {
+ pFilter->pLoopf->pfLumaDeblockingLT4Ver (&pDestY[ (3 << 2)*iLineSize], iLineSize, iAlpha, iBeta, iTc);
+ }
+ }
+}
+void FilteringEdgeChromaHV (PDqLayer pCurDqLayer, PDeblockingFilter pFilter, int32_t iBoundryFlag) {
+ int32_t iMbXyIndex = pCurDqLayer->iMbXyIndex;
+ int32_t iMbX = pCurDqLayer->iMbX;
+ int32_t iMbY = pCurDqLayer->iMbY;
+ int32_t iMbWidth = pCurDqLayer->iMbWidth;
+ int32_t iLineSize = pFilter->iCsStride[1];
+
+ uint8_t* pDestCb;
+ uint8_t* pDestCr;
+ //int32_t iCurQp;
+ int8_t* pCurQp;
+ int32_t iIndexA, iAlpha, iBeta;
+
+ ENFORCE_STACK_ALIGN_1D (int8_t, iTc, 4, 16);
+ ENFORCE_STACK_ALIGN_1D (uint8_t, uiBSx4, 4, 4);
+
+ pDestCb = pFilter->pCsData[1] + ((iMbY * iLineSize + iMbX) << 3);
+ pDestCr = pFilter->pCsData[2] + ((iMbY * iLineSize + iMbX) << 3);
+ pCurQp = pCurDqLayer->pChromaQp[iMbXyIndex];
+
+ * (uint32_t*)uiBSx4 = 0x03030303;
+
+
+// chroma v
+ if (iBoundryFlag & LEFT_FLAG_MASK) {
+
+ for (int i = 0; i < 2; i++) {
+ pFilter->iChromaQP[i] = (pCurQp[i] + pCurDqLayer->pChromaQp[iMbXyIndex - 1][i] + 1) >> 1;
+
+ }
+ FilteringEdgeChromaIntraV (pFilter, pDestCb, pDestCr, iLineSize, NULL);
+ }
+
+ pFilter->iChromaQP[0] = pCurQp[0];
+ pFilter->iChromaQP[1] = pCurQp[1];
+ if (pFilter->iChromaQP[0] == pFilter->iChromaQP[1]) {
+ GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP[0], pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
+ iBeta);
+ if (iAlpha | iBeta) {
+ TC0_TBL_LOOKUP (iTc, iIndexA, uiBSx4, 1);
+ pFilter->pLoopf->pfChromaDeblockingLT4Hor (&pDestCb[2 << 1], &pDestCr[2 << 1], iLineSize, iAlpha, iBeta, iTc);
+ }
+ } else {
+
+ for (int i = 0; i < 2; i++) {
+ GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP[i], pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
+ iBeta);
+ if (iAlpha | iBeta) {
+ uint8_t* pDestCbCr = (i == 0) ? &pDestCb[2 << 1] : &pDestCr[2 << 1];
+ TC0_TBL_LOOKUP (iTc, iIndexA, uiBSx4, 1);
+ pFilter->pLoopf->pfChromaDeblockingLT4Hor2 (pDestCbCr, iLineSize, iAlpha, iBeta, iTc);
+ }
+
+ }
+ }
+
+ // chroma h
+
+ if (iBoundryFlag & TOP_FLAG_MASK) {
+ for (int i = 0; i < 2; i++) {
+ pFilter->iChromaQP[i] = (pCurQp[i] + pCurDqLayer->pChromaQp[iMbXyIndex - iMbWidth][i] + 1) >> 1;
+ }
+ FilteringEdgeChromaIntraH (pFilter, pDestCb, pDestCr, iLineSize, NULL);
+ }
+
+ pFilter->iChromaQP[0] = pCurQp[0];
+ pFilter->iChromaQP[1] = pCurQp[1];
+
+ if (pFilter->iChromaQP[0] == pFilter->iChromaQP[1]) {
+ GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP[0], pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
+ iBeta);
+ if (iAlpha | iBeta) {
+ TC0_TBL_LOOKUP (iTc, iIndexA, uiBSx4, 1);
+ pFilter->pLoopf->pfChromaDeblockingLT4Ver (&pDestCb[ (2 << 1)*iLineSize], &pDestCr[ (2 << 1)*iLineSize], iLineSize,
+ iAlpha, iBeta, iTc);
+ }
+ } else {
+ for (int i = 0; i < 2; i++) {
+
+ GET_ALPHA_BETA_FROM_QP (pFilter->iChromaQP[i], pFilter->iSliceAlphaC0Offset, pFilter->iSliceBetaOffset, iIndexA, iAlpha,
+ iBeta);
+ if (iAlpha | iBeta) {
+ TC0_TBL_LOOKUP (iTc, iIndexA, uiBSx4, 1);
+ uint8_t* pDestCbCr = (i == 0) ? &pDestCb[ (2 << 1) * iLineSize] : &pDestCr[ (2 << 1) * iLineSize];
+ pFilter->pLoopf->pfChromaDeblockingLT4Ver2 (pDestCbCr, iLineSize,
+ iAlpha, iBeta, iTc);
+ }
+ }
+
+
+ }
+}
+
+// merge h&v lookup table operation to save performance
+void DeblockingIntraMb (PDqLayer pCurDqLayer, PDeblockingFilter pFilter, int32_t iBoundryFlag) {
+ FilteringEdgeLumaHV (pCurDqLayer, pFilter, iBoundryFlag);
+ FilteringEdgeChromaHV (pCurDqLayer, pFilter, iBoundryFlag);
+}
+
+void WelsDeblockingMb (PDqLayer pCurDqLayer, PDeblockingFilter pFilter, int32_t iBoundryFlag) {
+ uint8_t nBS[2][4][4] = {{{ 0 }}};
+
+ int32_t iMbXyIndex = pCurDqLayer->iMbXyIndex;
+ uint32_t iCurMbType = pCurDqLayer->pMbType[iMbXyIndex];
+ int32_t iMbNb;
+
+ PSlice pSlice = &pCurDqLayer->sLayerInfo.sSliceInLayer;
+ PSliceHeader pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader;
+ bool bBSlice = pSliceHeader->eSliceType == B_SLICE;
+
+ switch (iCurMbType) {
+ case MB_TYPE_INTRA4x4:
+ case MB_TYPE_INTRA8x8:
+ case MB_TYPE_INTRA16x16:
+ case MB_TYPE_INTRA_PCM:
+ DeblockingIntraMb (pCurDqLayer, pFilter, iBoundryFlag);
+ break;
+ default:
+
+ if (iBoundryFlag & LEFT_FLAG_MASK) {
+ iMbNb = iMbXyIndex - 1;
+ if (bBSlice) {
+ * (uint32_t*)nBS[0][0] = IS_INTRA (pCurDqLayer->pMbType[iMbNb]) ? 0x04040404 : DeblockingBSliceBsMarginalMBAvcbase (
+ pCurDqLayer, 0, iMbNb, iMbXyIndex);
+ } else {
+ * (uint32_t*)nBS[0][0] = IS_INTRA (pCurDqLayer->pMbType[iMbNb]) ? 0x04040404 : DeblockingBsMarginalMBAvcbase (
+ pCurDqLayer, 0, iMbNb, iMbXyIndex);
+ }
+ } else {
+ * (uint32_t*)nBS[0][0] = 0;
+ }
+ if (iBoundryFlag & TOP_FLAG_MASK) {
+ iMbNb = iMbXyIndex - pCurDqLayer->iMbWidth;
+ if (bBSlice) {
+ * (uint32_t*)nBS[1][0] = IS_INTRA (pCurDqLayer->pMbType[iMbNb]) ? 0x04040404 : DeblockingBSliceBsMarginalMBAvcbase (
+ pCurDqLayer, 1, iMbNb, iMbXyIndex);
+ } else {
+ * (uint32_t*)nBS[1][0] = IS_INTRA (pCurDqLayer->pMbType[iMbNb]) ? 0x04040404 : DeblockingBsMarginalMBAvcbase (
+ pCurDqLayer, 1, iMbNb, iMbXyIndex);
+ }
+ } else {
+ * (uint32_t*)nBS[1][0] = 0;
+ }
+ //SKIP MB_16x16 or others
+ if (IS_SKIP (iCurMbType)) {
+ * (uint32_t*)nBS[0][1] = * (uint32_t*)nBS[0][2] = * (uint32_t*)nBS[0][3] =
+ * (uint32_t*)nBS[1][1] = * (uint32_t*)nBS[1][2] = * (uint32_t*)nBS[1][3] = 0;
+ } else {
+ if (IS_INTER_16x16 (iCurMbType)) {
+ if (!pCurDqLayer->pTransformSize8x8Flag[pCurDqLayer->iMbXyIndex]) {
+ DeblockingBSInsideMBAvsbase (pCurDqLayer->pNzc[iMbXyIndex], nBS, 1);
+ } else {
+ DeblockingBSInsideMBAvsbase8x8 (pCurDqLayer->pNzc[iMbXyIndex], nBS, 1);
+ }
+ } else {
+
+ if (bBSlice) {
+ DeblockingBSliceBSInsideMBNormal (pCurDqLayer, nBS, pCurDqLayer->pNzc[iMbXyIndex], iMbXyIndex);
+ } else {
+ DeblockingBSInsideMBNormal (pCurDqLayer, nBS, pCurDqLayer->pNzc[iMbXyIndex], iMbXyIndex);
+ }
+ }
+ }
+ DeblockingInterMb (pCurDqLayer, pFilter, nBS, iBoundryFlag);
+ break;
+ }
+}
+
+/*!
+ * \brief AVC slice deblocking filtering target layer
+ *
+ * \param dec Wels avc decoder context
+ *
+ * \return NONE
+ */
+void WelsDeblockingFilterSlice (PWelsDecoderContext pCtx, PDeblockingFilterMbFunc pDeblockMb) {
+ PDqLayer pCurDqLayer = pCtx->pCurDqLayer;
+ PSliceHeaderExt pSliceHeaderExt = &pCurDqLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt;
+ int32_t iMbWidth = pCurDqLayer->iMbWidth;
+ int32_t iTotalMbCount = pSliceHeaderExt->sSliceHeader.pSps->uiTotalMbCount;
+
+ SDeblockingFilter pFilter;
+ memset (&pFilter, 0, sizeof (pFilter));
+ PFmo pFmo = pCtx->pFmo;
+ int32_t iNextMbXyIndex = 0;
+ int32_t iTotalNumMb = pCurDqLayer->sLayerInfo.sSliceInLayer.iTotalMbInCurSlice;
+ int32_t iCountNumMb = 0;
+ int32_t iBoundryFlag;
+ int32_t iFilterIdc = pCurDqLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.uiDisableDeblockingFilterIdc;
+
+ /* Step1: parameters set */
+ pFilter.pCsData[0] = pCtx->pDec->pData[0];
+ pFilter.pCsData[1] = pCtx->pDec->pData[1];
+ pFilter.pCsData[2] = pCtx->pDec->pData[2];
+
+ pFilter.iCsStride[0] = pCtx->pDec->iLinesize[0];
+ pFilter.iCsStride[1] = pCtx->pDec->iLinesize[1];
+
+ pFilter.eSliceType = (EWelsSliceType) pCurDqLayer->sLayerInfo.sSliceInLayer.eSliceType;
+
+ pFilter.iSliceAlphaC0Offset = pSliceHeaderExt->sSliceHeader.iSliceAlphaC0Offset;
+ pFilter.iSliceBetaOffset = pSliceHeaderExt->sSliceHeader.iSliceBetaOffset;
+
+ pFilter.pLoopf = &pCtx->sDeblockingFunc;
+
+ /* Step2: macroblock deblocking */
+ if (0 == iFilterIdc || 2 == iFilterIdc) {
+ iNextMbXyIndex = pSliceHeaderExt->sSliceHeader.iFirstMbInSlice;
+ pCurDqLayer->iMbX = iNextMbXyIndex % iMbWidth;
+ pCurDqLayer->iMbY = iNextMbXyIndex / iMbWidth;
+ pCurDqLayer->iMbXyIndex = iNextMbXyIndex;
+
+ do {
+ iBoundryFlag = DeblockingAvailableNoInterlayer (pCurDqLayer, iFilterIdc);
+
+ pDeblockMb (pCurDqLayer, &pFilter, iBoundryFlag);
+
+ ++iCountNumMb;
+ if (iCountNumMb >= iTotalNumMb) {
+ break;
+ }
+
+ if (pSliceHeaderExt->sSliceHeader.pPps->uiNumSliceGroups > 1) {
+ iNextMbXyIndex = FmoNextMb (pFmo, iNextMbXyIndex);
+ } else {
+ ++iNextMbXyIndex;
+ }
+ if (-1 == iNextMbXyIndex || iNextMbXyIndex >= iTotalMbCount) { // slice group boundary or end of a frame
+ break;
+ }
+
+ pCurDqLayer->iMbX = iNextMbXyIndex % iMbWidth;
+ pCurDqLayer->iMbY = iNextMbXyIndex / iMbWidth;
+ pCurDqLayer->iMbXyIndex = iNextMbXyIndex;
+ } while (1);
+ }
+}
+/*!
+ * \brief deblocking module initialize
+ *
+ * \param pf
+ * cpu
+ *
+ * \return NONE
+ */
+
+void DeblockingInit (SDeblockingFunc* pFunc, int32_t iCpu) {
+ pFunc->pfLumaDeblockingLT4Ver = DeblockLumaLt4V_c;
+ pFunc->pfLumaDeblockingEQ4Ver = DeblockLumaEq4V_c;
+ pFunc->pfLumaDeblockingLT4Hor = DeblockLumaLt4H_c;
+ pFunc->pfLumaDeblockingEQ4Hor = DeblockLumaEq4H_c;
+
+ pFunc->pfChromaDeblockingLT4Ver = DeblockChromaLt4V_c;
+ pFunc->pfChromaDeblockingEQ4Ver = DeblockChromaEq4V_c;
+ pFunc->pfChromaDeblockingLT4Hor = DeblockChromaLt4H_c;
+ pFunc->pfChromaDeblockingEQ4Hor = DeblockChromaEq4H_c;
+
+ pFunc->pfChromaDeblockingLT4Ver2 = DeblockChromaLt4V2_c;
+ pFunc->pfChromaDeblockingEQ4Ver2 = DeblockChromaEq4V2_c;
+ pFunc->pfChromaDeblockingLT4Hor2 = DeblockChromaLt4H2_c;
+ pFunc->pfChromaDeblockingEQ4Hor2 = DeblockChromaEq4H2_c;
+
+#ifdef X86_ASM
+ if (iCpu & WELS_CPU_SSSE3) {
+ pFunc->pfLumaDeblockingLT4Ver = DeblockLumaLt4V_ssse3;
+ pFunc->pfLumaDeblockingEQ4Ver = DeblockLumaEq4V_ssse3;
+ pFunc->pfLumaDeblockingLT4Hor = DeblockLumaLt4H_ssse3;
+ pFunc->pfLumaDeblockingEQ4Hor = DeblockLumaEq4H_ssse3;
+ pFunc->pfChromaDeblockingLT4Ver = DeblockChromaLt4V_ssse3;
+ pFunc->pfChromaDeblockingEQ4Ver = DeblockChromaEq4V_ssse3;
+ pFunc->pfChromaDeblockingLT4Hor = DeblockChromaLt4H_ssse3;
+ pFunc->pfChromaDeblockingEQ4Hor = DeblockChromaEq4H_ssse3;
+ }
+#endif
+
+#if defined(HAVE_NEON)
+ if (iCpu & WELS_CPU_NEON) {
+ pFunc->pfLumaDeblockingLT4Ver = DeblockLumaLt4V_neon;
+ pFunc->pfLumaDeblockingEQ4Ver = DeblockLumaEq4V_neon;
+ pFunc->pfLumaDeblockingLT4Hor = DeblockLumaLt4H_neon;
+ pFunc->pfLumaDeblockingEQ4Hor = DeblockLumaEq4H_neon;
+
+ pFunc->pfChromaDeblockingLT4Ver = DeblockChromaLt4V_neon;
+ pFunc->pfChromaDeblockingEQ4Ver = DeblockChromaEq4V_neon;
+ pFunc->pfChromaDeblockingLT4Hor = DeblockChromaLt4H_neon;
+ pFunc->pfChromaDeblockingEQ4Hor = DeblockChromaEq4H_neon;
+ }
+#endif
+
+#if defined(HAVE_NEON_AARCH64)
+ if (iCpu & WELS_CPU_NEON) {
+ pFunc->pfLumaDeblockingLT4Ver = DeblockLumaLt4V_AArch64_neon;
+ pFunc->pfLumaDeblockingEQ4Ver = DeblockLumaEq4V_AArch64_neon;
+ pFunc->pfLumaDeblockingLT4Hor = DeblockLumaLt4H_AArch64_neon;
+ pFunc->pfLumaDeblockingEQ4Hor = DeblockLumaEq4H_AArch64_neon;
+
+ pFunc->pfChromaDeblockingLT4Ver = DeblockChromaLt4V_AArch64_neon;
+ pFunc->pfChromaDeblockingEQ4Ver = DeblockChromaEq4V_AArch64_neon;
+ pFunc->pfChromaDeblockingLT4Hor = DeblockChromaLt4H_AArch64_neon;
+ pFunc->pfChromaDeblockingEQ4Hor = DeblockChromaEq4H_AArch64_neon;
+ }
+#endif
+}
+
+} // namespace WelsDec
--- a/codec/decoder/core/src/manage_dec_ref.cpp
+++ b/codec/decoder/core/src/manage_dec_ref.cpp
@@ -1,897 +1,897 @@
-/*!
- * \copy
- * Copyright (c) 2008-2013, Cisco Systems
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- *
- * manage_dec_ref.cpp
- *
- * Abstract
- * Implementation for managing reference picture
- *
- * History
- * 07/21/2008 Created
- *
- *****************************************************************************/
-
-#include "manage_dec_ref.h"
-#include "error_concealment.h"
-#include "error_code.h"
-
-namespace WelsDec {
-
-static PPicture WelsDelShortFromList (PRefPic pRefPic, int32_t iFrameNum);
-static PPicture WelsDelLongFromList (PRefPic pRefPic, uint32_t uiLongTermFrameIdx);
-static PPicture WelsDelShortFromListSetUnref (PRefPic pRefPic, int32_t iFrameNum);
-static PPicture WelsDelLongFromListSetUnref (PRefPic pRefPic, uint32_t uiLongTermFrameIdx);
-
-static int32_t MMCO (PWelsDecoderContext pCtx, PRefPicMarking pRefPicMarking);
-static int32_t MMCOProcess (PWelsDecoderContext pCtx, uint32_t uiMmcoType,
- int32_t iShortFrameNum, uint32_t uiLongTermPicNum, int32_t iLongTermFrameIdx, int32_t iMaxLongTermFrameIdx);
-static int32_t SlidingWindow (PWelsDecoderContext pCtx);
-
-static int32_t AddShortTermToList (PRefPic pRefPic, PPicture pPic);
-static int32_t AddLongTermToList (PRefPic pRefPic, PPicture pPic, int32_t iLongTermFrameIdx, uint32_t uiLongTermPicNum);
-static int32_t MarkAsLongTerm (PRefPic pRefPic, int32_t iFrameNum, int32_t iLongTermFrameIdx,
- uint32_t uiLongTermPicNum);
-static int32_t WelsCheckAndRecoverForFutureDecoding (PWelsDecoderContext pCtx);
-#ifdef LONG_TERM_REF
-int32_t GetLTRFrameIndex (PRefPic pRefPic, int32_t iAncLTRFrameNum);
-#endif
-static int32_t RemainOneBufferInDpbForEC (PWelsDecoderContext pCtx);
-
-static void SetUnRef (PPicture pRef) {
- if (NULL != pRef) {
- pRef->bUsedAsRef = false;
- pRef->bIsLongRef = false;
- pRef->iFrameNum = -1;
- pRef->iFrameWrapNum = -1;
- //pRef->iFramePoc = 0;
- pRef->iLongTermFrameIdx = -1;
- pRef->uiLongTermPicNum = 0;
- pRef->uiQualityId = -1;
- pRef->uiTemporalId = -1;
- pRef->uiSpatialId = -1;
- pRef->iSpsId = -1;
- pRef->bIsComplete = false;
- }
-}
-
-//reset pRefList when
-// 1.sps arrived that is new sequence starting
-// 2.IDR NAL i.e. 1st layer in IDR AU
-
-void WelsResetRefPic (PWelsDecoderContext pCtx) {
- int32_t i = 0;
- PRefPic pRefPic = &pCtx->sRefPic;
- pCtx->sRefPic.uiLongRefCount[LIST_0] = pCtx->sRefPic.uiShortRefCount[LIST_0] = 0;
-
- pRefPic->uiRefCount[LIST_0] = 0;
- pRefPic->uiRefCount[LIST_1] = 0;
-
- for (i = 0; i < MAX_DPB_COUNT; i++) {
- if (pRefPic->pShortRefList[LIST_0][i] != NULL) {
- SetUnRef (pRefPic->pShortRefList[LIST_0][i]);
- pRefPic->pShortRefList[LIST_0][i] = NULL;
- }
- }
- pRefPic->uiShortRefCount[LIST_0] = 0;
-
- for (i = 0; i < MAX_DPB_COUNT; i++) {
- if (pRefPic->pLongRefList[LIST_0][i] != NULL) {
- SetUnRef (pRefPic->pLongRefList[LIST_0][i]);
- pRefPic->pLongRefList[LIST_0][i] = NULL;
- }
- }
- pRefPic->uiLongRefCount[LIST_0] = 0;
-}
-
-static int32_t WelsCheckAndRecoverForFutureDecoding (PWelsDecoderContext pCtx) {
- if ((pCtx->sRefPic.uiShortRefCount[LIST_0] + pCtx->sRefPic.uiLongRefCount[LIST_0] <= 0) && (pCtx->eSliceType != I_SLICE
- && pCtx->eSliceType != SI_SLICE)) {
- if (pCtx->pParam->eEcActiveIdc !=
- ERROR_CON_DISABLE) { //IDR lost!, recover it for future decoding with data all set to 0
- PPicture pRef = PrefetchPic (pCtx->pPicBuff);
- if (pRef != NULL) {
- // IDR lost, set new
- pRef->bIsComplete = false; // Set complete flag to false for lost IDR ref picture
- pRef->iSpsId = pCtx->pSps->iSpsId;
- pRef->iPpsId = pCtx->pPps->iPpsId;
- pCtx->iErrorCode |= dsDataErrorConcealed;
- bool bCopyPrevious = ((ERROR_CON_FRAME_COPY_CROSS_IDR == pCtx->pParam->eEcActiveIdc)
- || (ERROR_CON_SLICE_COPY_CROSS_IDR == pCtx->pParam->eEcActiveIdc)
- || (ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE == pCtx->pParam->eEcActiveIdc)
- || (ERROR_CON_SLICE_MV_COPY_CROSS_IDR == pCtx->pParam->eEcActiveIdc)
- || (ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE == pCtx->pParam->eEcActiveIdc))
- && (NULL != pCtx->pPreviousDecodedPictureInDpb);
- bCopyPrevious = bCopyPrevious && (pRef->iWidthInPixel == pCtx->pPreviousDecodedPictureInDpb->iWidthInPixel)
- && (pRef->iHeightInPixel == pCtx->pPreviousDecodedPictureInDpb->iHeightInPixel);
-
- if (!bCopyPrevious) {
- memset (pRef->pData[0], 128, pRef->iLinesize[0] * pRef->iHeightInPixel);
- memset (pRef->pData[1], 128, pRef->iLinesize[1] * pRef->iHeightInPixel / 2);
- memset (pRef->pData[2], 128, pRef->iLinesize[2] * pRef->iHeightInPixel / 2);
- } else if (pRef == pCtx->pPreviousDecodedPictureInDpb) {
- WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "WelsInitRefList()::EC memcpy overlap.");
- } else {
- memcpy (pRef->pData[0], pCtx->pPreviousDecodedPictureInDpb->pData[0], pRef->iLinesize[0] * pRef->iHeightInPixel);
- memcpy (pRef->pData[1], pCtx->pPreviousDecodedPictureInDpb->pData[1], pRef->iLinesize[1] * pRef->iHeightInPixel / 2);
- memcpy (pRef->pData[2], pCtx->pPreviousDecodedPictureInDpb->pData[2], pRef->iLinesize[2] * pRef->iHeightInPixel / 2);
- }
- pRef->iFrameNum = 0;
- pRef->iFramePoc = 0;
- pRef->uiTemporalId = pRef->uiQualityId = 0;
- ExpandReferencingPicture (pRef->pData, pRef->iWidthInPixel, pRef->iHeightInPixel, pRef->iLinesize,
- pCtx->sExpandPicFunc.pfExpandLumaPicture, pCtx->sExpandPicFunc.pfExpandChromaPicture);
- AddShortTermToList (&pCtx->sRefPic, pRef);
- } else {
- WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "WelsInitRefList()::PrefetchPic for EC errors.");
- pCtx->iErrorCode |= dsOutOfMemory;
- return ERR_INFO_REF_COUNT_OVERFLOW;
- }
- }
- }
- return ERR_NONE;
-}
-
-static void WrapShortRefPicNum (PWelsDecoderContext pCtx) {
- int32_t i;
- PSliceHeader pSliceHeader = &pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader;
- int32_t iMaxPicNum = 1 << pSliceHeader->pSps->uiLog2MaxFrameNum;
- PPicture* ppShoreRefList = pCtx->sRefPic.pShortRefList[LIST_0];
- int32_t iShortRefCount = pCtx->sRefPic.uiShortRefCount[LIST_0];
- //wrap pic num
- for (i = 0; i < iShortRefCount; i++) {
- if (ppShoreRefList[i]) {
- if (ppShoreRefList[i]->iFrameNum > pSliceHeader->iFrameNum)
- ppShoreRefList[i]->iFrameWrapNum = ppShoreRefList[i]->iFrameNum - iMaxPicNum;
- else
- ppShoreRefList[i]->iFrameWrapNum = ppShoreRefList[i]->iFrameNum;
- }
- }
-}
-
-/**
-* fills the pRefPic.pRefList LIST_0 and LIST_0 for B-Slice.
-*/
-int32_t WelsInitBSliceRefList (PWelsDecoderContext pCtx, int32_t iPoc) {
-
- int32_t err = WelsCheckAndRecoverForFutureDecoding (pCtx);
- if (err != ERR_NONE) return err;
-
- WrapShortRefPicNum (pCtx);
-
- PPicture* ppShoreRefList = pCtx->sRefPic.pShortRefList[LIST_0];
- PPicture* ppLongRefList = pCtx->sRefPic.pLongRefList[LIST_0];
- memset (pCtx->sRefPic.pRefList[LIST_0], 0, MAX_DPB_COUNT * sizeof (PPicture));
- memset (pCtx->sRefPic.pRefList[LIST_1], 0, MAX_DPB_COUNT * sizeof (PPicture));
- int32_t iLSCurrPocCount = 0;
- int32_t iLTCurrPocCount = 0;
- PPicture pLSCurrPocList0[MAX_DPB_COUNT];
- PPicture pLTCurrPocList0[MAX_DPB_COUNT];
- for (int32_t i = 0; i < pCtx->sRefPic.uiShortRefCount[LIST_0]; ++i) {
- if (ppShoreRefList[i]->iFramePoc < iPoc) {
- pLSCurrPocList0[iLSCurrPocCount++] = ppShoreRefList[i];
- }
- }
- for (int32_t i = pCtx->sRefPic.uiShortRefCount[LIST_0] - 1; i >= 0; --i) {
- if (ppShoreRefList[i]->iFramePoc > iPoc) {
- pLTCurrPocList0[iLTCurrPocCount++] = ppShoreRefList[i];
- }
- }
- if (pCtx->sRefPic.uiLongRefCount[LIST_0] > 1) {
- //long sorts in increasing order
- PPicture pTemp;
- for (int32_t i = 0; i < pCtx->sRefPic.uiLongRefCount[LIST_0]; ++i) {
- for (int32_t j = i + 1; j < pCtx->sRefPic.uiLongRefCount[LIST_0]; ++j) {
- if (ppLongRefList[j]->iFramePoc < ppLongRefList[i]->iFramePoc) {
- pTemp = ppLongRefList[i];
- ppLongRefList[i] = ppLongRefList[j];
- ppLongRefList[j] = pTemp;
- }
- }
- }
- }
- int32_t iCurrPocCount = iLSCurrPocCount + iLTCurrPocCount;
- int32_t iCount = 0;
- //LIST_0
- //short
- //It may need to sort LIST_0 and LIST_1 so that they will have the right default orders.
- for (int32_t i = 0; i < iLSCurrPocCount; ++i) {
- pCtx->sRefPic.pRefList[LIST_0][iCount++] = pLSCurrPocList0[i];
- }
- if (iLSCurrPocCount > 1) {
- //LIST_0 short sorts in decreasing order
- PPicture pTemp;
- for (int32_t i = 0; i < iLSCurrPocCount; ++i) {
- for (int32_t j = i + 1; j < iLSCurrPocCount; ++j) {
- if (pCtx->sRefPic.pRefList[LIST_0][j]->iFramePoc > pCtx->sRefPic.pRefList[LIST_0][i]->iFramePoc) {
- pTemp = pCtx->sRefPic.pRefList[LIST_0][i];
- pCtx->sRefPic.pRefList[LIST_0][i] = pCtx->sRefPic.pRefList[LIST_0][j];
- pCtx->sRefPic.pRefList[LIST_0][j] = pTemp;
- }
- }
- }
- }
- for (int32_t i = 0; i < iLTCurrPocCount; ++i) {
- pCtx->sRefPic.pRefList[LIST_0][iCount++] = pLTCurrPocList0[i];
- }
- if (iLTCurrPocCount > 1) {
- //LIST_0 short sorts in increasing order
- PPicture pTemp;
- for (int32_t i = iLSCurrPocCount; i < iCurrPocCount; ++i) {
- for (int32_t j = i + 1; j < iCurrPocCount; ++j) {
- if (pCtx->sRefPic.pRefList[LIST_0][j]->iFramePoc < pCtx->sRefPic.pRefList[LIST_0][i]->iFramePoc) {
- pTemp = pCtx->sRefPic.pRefList[LIST_0][i];
- pCtx->sRefPic.pRefList[LIST_0][i] = pCtx->sRefPic.pRefList[LIST_0][j];
- pCtx->sRefPic.pRefList[LIST_0][j] = pTemp;
- }
- }
- }
- }
- //long
- for (int32_t i = 0; i < pCtx->sRefPic.uiLongRefCount[LIST_0]; ++i) {
- pCtx->sRefPic.pRefList[LIST_0][iCount++] = ppLongRefList[i];
- }
- pCtx->sRefPic.uiRefCount[LIST_0] = iCount;
-
- iCount = 0;
- //LIST_1
- //short
- for (int32_t i = 0; i < iLTCurrPocCount; ++i) {
- pCtx->sRefPic.pRefList[LIST_1][iCount++] = pLTCurrPocList0[i];
- }
- if (iLTCurrPocCount > 1) {
- //LIST_1 short sorts in increasing order
- PPicture pTemp;
- for (int32_t i = 0; i < iLTCurrPocCount; ++i) {
- for (int32_t j = i + 1; j < iLTCurrPocCount; ++j) {
- if (pCtx->sRefPic.pRefList[LIST_1][j]->iFramePoc < pCtx->sRefPic.pRefList[LIST_1][i]->iFramePoc) {
- pTemp = pCtx->sRefPic.pRefList[LIST_1][i];
- pCtx->sRefPic.pRefList[LIST_1][i] = pCtx->sRefPic.pRefList[LIST_1][j];
- pCtx->sRefPic.pRefList[LIST_1][j] = pTemp;
- }
- }
- }
- }
- for (int32_t i = 0; i < iLSCurrPocCount; ++i) {
- pCtx->sRefPic.pRefList[LIST_1][iCount++] = pLSCurrPocList0[i];
- }
- if (iLSCurrPocCount > 1) {
- //LIST_1 short sorts in decreasing order
- PPicture pTemp;
- for (int32_t i = iLTCurrPocCount; i < iCurrPocCount; ++i) {
- for (int32_t j = i + 1; j < iCurrPocCount; ++j) {
- if (pCtx->sRefPic.pRefList[LIST_1][j]->iFramePoc > pCtx->sRefPic.pRefList[LIST_1][i]->iFramePoc) {
- pTemp = pCtx->sRefPic.pRefList[LIST_1][i];
- pCtx->sRefPic.pRefList[LIST_1][i] = pCtx->sRefPic.pRefList[LIST_1][j];
- pCtx->sRefPic.pRefList[LIST_1][j] = pTemp;
- }
- }
- }
- }
- //long
- for (int32_t i = 0; i < pCtx->sRefPic.uiLongRefCount[LIST_0]; ++i) {
- pCtx->sRefPic.pRefList[LIST_1][iCount++] = ppLongRefList[i];
- }
- pCtx->sRefPic.uiRefCount[LIST_1] = iCount;
- return ERR_NONE;
-}
-
-/**
- * fills the pRefPic.pRefList.
- */
-int32_t WelsInitRefList (PWelsDecoderContext pCtx, int32_t iPoc) {
-
- int32_t err = WelsCheckAndRecoverForFutureDecoding (pCtx);
- if (err != ERR_NONE) return err;
-
- WrapShortRefPicNum (pCtx);
-
- PPicture* ppShoreRefList = pCtx->sRefPic.pShortRefList[LIST_0];
- PPicture* ppLongRefList = pCtx->sRefPic.pLongRefList[LIST_0];
- memset (pCtx->sRefPic.pRefList[LIST_0], 0, MAX_DPB_COUNT * sizeof (PPicture));
-
- int32_t i, iCount = 0;
- //short
- for (i = 0; i < pCtx->sRefPic.uiShortRefCount[LIST_0]; ++i) {
- pCtx->sRefPic.pRefList[LIST_0][iCount++ ] = ppShoreRefList[i];
- }
-
- //long
- for (i = 0; i < pCtx->sRefPic.uiLongRefCount[LIST_0] ; ++i) {
- pCtx->sRefPic.pRefList[LIST_0][iCount++ ] = ppLongRefList[i];
- }
- pCtx->sRefPic.uiRefCount[LIST_0] = iCount;
-
- return ERR_NONE;
-}
-
-int32_t WelsReorderRefList (PWelsDecoderContext pCtx) {
-
- if (pCtx->eSliceType == I_SLICE || pCtx->eSliceType == SI_SLICE) {
- return ERR_NONE;
- }
-
- PRefPicListReorderSyn pRefPicListReorderSyn = pCtx->pCurDqLayer->pRefPicListReordering;
- PNalUnitHeaderExt pNalHeaderExt = &pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt;
- PSliceHeader pSliceHeader = &pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader;
- int32_t ListCount = 1;
- if (pCtx->eSliceType == B_SLICE) ListCount = 2;
- for (int32_t listIdx = 0; listIdx < ListCount; ++listIdx) {
- PPicture pPic = NULL;
- PPicture* ppRefList = pCtx->sRefPic.pRefList[listIdx];
- int32_t iMaxRefIdx = pCtx->pSps->iNumRefFrames;
- int32_t iRefCount = pCtx->sRefPic.uiRefCount[listIdx];
- int32_t iPredFrameNum = pSliceHeader->iFrameNum;
- int32_t iMaxPicNum = 1 << pSliceHeader->pSps->uiLog2MaxFrameNum;
- int32_t iAbsDiffPicNum = -1;
- int32_t iReorderingIndex = 0;
- int32_t i = 0;
-
- if (iRefCount <= 0) {
- pCtx->iErrorCode = dsNoParamSets; //No any reference for decoding, SHOULD request IDR
- return ERR_INFO_REFERENCE_PIC_LOST;
- }
-
- if (pRefPicListReorderSyn->bRefPicListReorderingFlag[listIdx]) {
- while ((iReorderingIndex < iMaxRefIdx)
- && (pRefPicListReorderSyn->sReorderingSyn[listIdx][iReorderingIndex].uiReorderingOfPicNumsIdc != 3)) {
- uint16_t uiReorderingOfPicNumsIdc =
- pRefPicListReorderSyn->sReorderingSyn[listIdx][iReorderingIndex].uiReorderingOfPicNumsIdc;
- if (uiReorderingOfPicNumsIdc < 2) {
- iAbsDiffPicNum = pRefPicListReorderSyn->sReorderingSyn[listIdx][iReorderingIndex].uiAbsDiffPicNumMinus1 + 1;
-
- if (uiReorderingOfPicNumsIdc == 0) {
- iPredFrameNum -= iAbsDiffPicNum;
- } else {
- iPredFrameNum += iAbsDiffPicNum;
- }
- iPredFrameNum &= iMaxPicNum - 1;
-
- for (i = iMaxRefIdx - 1; i >= 0; i--) {
- if (ppRefList[i] != NULL && ppRefList[i]->iFrameNum == iPredFrameNum && !ppRefList[i]->bIsLongRef) {
- if ((pNalHeaderExt->uiQualityId == ppRefList[i]->uiQualityId)
- && (pSliceHeader->iSpsId != ppRefList[i]->iSpsId)) { //check;
- WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "WelsReorderRefList()::::BASE LAYER::::iSpsId:%d, ref_sps_id:%d",
- pSliceHeader->iSpsId, ppRefList[i]->iSpsId);
- pCtx->iErrorCode = dsNoParamSets; //cross-IDR reference frame selection, SHOULD request IDR.--
- return ERR_INFO_REFERENCE_PIC_LOST;
- } else {
- break;
- }
- }
- }
-
- } else if (uiReorderingOfPicNumsIdc == 2) {
- for (i = iMaxRefIdx - 1; i >= 0; i--) {
- if (ppRefList[i] != NULL && ppRefList[i]->bIsLongRef
- && ppRefList[i]->iLongTermFrameIdx ==
- pRefPicListReorderSyn->sReorderingSyn[listIdx][iReorderingIndex].uiLongTermPicNum) {
- if ((pNalHeaderExt->uiQualityId == ppRefList[i]->uiQualityId)
- && (pSliceHeader->iSpsId != ppRefList[i]->iSpsId)) { //check;
- WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "WelsReorderRefList()::::BASE LAYER::::iSpsId:%d, ref_sps_id:%d",
- pSliceHeader->iSpsId, ppRefList[i]->iSpsId);
- pCtx->iErrorCode = dsNoParamSets; //cross-IDR reference frame selection, SHOULD request IDR.--
- return ERR_INFO_REFERENCE_PIC_LOST;
- } else {
- break;
- }
- }
- }
- }
- if (i < 0) {
- return ERR_INFO_REFERENCE_PIC_LOST;
- }
- pPic = ppRefList[i];
- if (i > iReorderingIndex) {
- memmove (&ppRefList[1 + iReorderingIndex], &ppRefList[iReorderingIndex],
- (i - iReorderingIndex) * sizeof (PPicture)); //confirmed_safe_unsafe_usage
- } else if (i < iReorderingIndex) {
- memmove (&ppRefList[1 + iReorderingIndex], &ppRefList[iReorderingIndex],
- (iMaxRefIdx - iReorderingIndex) * sizeof (PPicture));
- }
- ppRefList[iReorderingIndex] = pPic;
- iReorderingIndex++;
- }
- }
- }
- return ERR_NONE;
-}
-
-//WelsReorderRefList2 is the test code
-int32_t WelsReorderRefList2 (PWelsDecoderContext pCtx) {
-
- if (pCtx->eSliceType == I_SLICE || pCtx->eSliceType == SI_SLICE) {
- return ERR_NONE;
- }
-
- PRefPicListReorderSyn pRefPicListReorderSyn = pCtx->pCurDqLayer->pRefPicListReordering;
- PSliceHeader pSliceHeader = &pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader;
-
- PPicture* ppShoreRefList = pCtx->sRefPic.pShortRefList[LIST_0];
- int32_t iShortRefCount = pCtx->sRefPic.uiShortRefCount[LIST_0];
- PPicture* ppLongRefList = pCtx->sRefPic.pLongRefList[LIST_0];
- int32_t iLongRefCount = pCtx->sRefPic.uiLongRefCount[LIST_0];
- int32_t i = 0;
- int32_t j = 0;
- int32_t k = 0;
- int32_t iMaxRefIdx = pCtx->pSps->iNumRefFrames;
- const int32_t iCurFrameNum = pSliceHeader->iFrameNum;
- const int32_t iMaxPicNum = 1 << pSliceHeader->pSps->uiLog2MaxFrameNum;
- int32_t iListCount = 1;
- if (pCtx->eSliceType == B_SLICE) iListCount = 2;
- for (int32_t listIdx = 0; listIdx < iListCount; ++listIdx) {
- PPicture* ppRefList = pCtx->sRefPic.pRefList[listIdx];
- int32_t iCount = 0;
- int32_t iRefCount = pSliceHeader->uiRefCount[listIdx];
- int32_t iAbsDiffPicNum = -1;
-
- if (pRefPicListReorderSyn->bRefPicListReorderingFlag[listIdx]) {
- int32_t iPredFrameNum = iCurFrameNum;
- for (i = 0; pRefPicListReorderSyn->sReorderingSyn[listIdx][i].uiReorderingOfPicNumsIdc != 3; i++) {
- if (iCount >= iMaxRefIdx)
- break;
-
- for (j = iRefCount; j > iCount; j--)
- ppRefList[j] = ppRefList[j - 1];
-
- uint16_t uiReorderingOfPicNumsIdc =
- pRefPicListReorderSyn->sReorderingSyn[listIdx][i].uiReorderingOfPicNumsIdc;
-
- if (uiReorderingOfPicNumsIdc < 2) { // reorder short references
- iAbsDiffPicNum = (int32_t) (pRefPicListReorderSyn->sReorderingSyn[listIdx][i].uiAbsDiffPicNumMinus1 + 1);
- if (uiReorderingOfPicNumsIdc == 0) {
- if (iPredFrameNum - iAbsDiffPicNum < 0)
- iPredFrameNum -= (iAbsDiffPicNum - iMaxPicNum);
- else
- iPredFrameNum -= iAbsDiffPicNum;
- } else {
- if (iPredFrameNum + iAbsDiffPicNum >= iMaxPicNum)
- iPredFrameNum += (iAbsDiffPicNum - iMaxPicNum);
- else
- iPredFrameNum += iAbsDiffPicNum;
- }
-
- if (iPredFrameNum > iCurFrameNum) {
- iPredFrameNum -= iMaxPicNum;
- }
-
- for (j = 0; j < iShortRefCount; j++) {
- if (ppShoreRefList[j]) {
- if (ppShoreRefList[j]->iFrameWrapNum == iPredFrameNum) {
- ppRefList[iCount++] = ppShoreRefList[j];
- break;
- }
- }
- }
- k = iCount;
- for (j = k; j <= iRefCount; j++) {
- if (ppRefList[j] != NULL) {
- if (ppRefList[j]->bIsLongRef || ppRefList[j]->iFrameWrapNum != iPredFrameNum)
- ppRefList[k++] = ppRefList[j];
- }
- }
- } else { // reorder long term references uiReorderingOfPicNumsIdc == 2
- iPredFrameNum = pRefPicListReorderSyn->sReorderingSyn[listIdx][i].uiLongTermPicNum;
- for (j = 0; j < iLongRefCount; j++) {
- if (ppLongRefList[j] != NULL) {
- if (ppLongRefList[j]->uiLongTermPicNum == (uint32_t)iPredFrameNum) {
- ppRefList[iCount++] = ppLongRefList[j];
- break;
- }
- }
- }
- k = iCount;
- for (j = k; j <= iRefCount; j++) {
- if (ppRefList[j] != NULL) {
- if (!ppRefList[j]->bIsLongRef || ppLongRefList[j]->uiLongTermPicNum != (uint32_t)iPredFrameNum)
- ppRefList[k++] = ppRefList[j];
- }
- }
- }
- }
- }
-
- for (i = WELS_MAX (1, WELS_MAX (iCount, pCtx->sRefPic.uiRefCount[listIdx])); i < iRefCount; i++)
- ppRefList[i] = ppRefList[i - 1];
- pCtx->sRefPic.uiRefCount[listIdx] = (uint8_t)WELS_MIN (WELS_MAX (iCount, pCtx->sRefPic.uiRefCount[listIdx]), iRefCount);
- }
- return ERR_NONE;
-}
-
-int32_t WelsMarkAsRef (PWelsDecoderContext pCtx) {
- PRefPic pRefPic = &pCtx->sRefPic;
- PRefPicMarking pRefPicMarking = pCtx->pCurDqLayer->pRefPicMarking;
- PAccessUnit pCurAU = pCtx->pAccessUnitList;
- bool bIsIDRAU = false;
- uint32_t j;
-
- int32_t iRet = ERR_NONE;
-
- pCtx->pDec->uiQualityId = pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt.uiQualityId;
- pCtx->pDec->uiTemporalId = pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt.uiTemporalId;
- pCtx->pDec->iSpsId = pCtx->pSps->iSpsId;
- pCtx->pDec->iPpsId = pCtx->pPps->iPpsId;
-
- for (j = pCurAU->uiStartPos; j <= pCurAU->uiEndPos; j++) {
- if (pCurAU->pNalUnitsList[j]->sNalHeaderExt.sNalUnitHeader.eNalUnitType == NAL_UNIT_CODED_SLICE_IDR
- || pCurAU->pNalUnitsList[j]->sNalHeaderExt.bIdrFlag) {
- bIsIDRAU = true;
- break;
- }
- }
- if (bIsIDRAU) {
- if (pRefPicMarking->bLongTermRefFlag) {
- pCtx->sRefPic.iMaxLongTermFrameIdx = 0;
- AddLongTermToList (pRefPic, pCtx->pDec, 0, 0);
- } else {
- pCtx->sRefPic.iMaxLongTermFrameIdx = -1;
- }
- } else {
- if (pRefPicMarking->bAdaptiveRefPicMarkingModeFlag) {
- iRet = MMCO (pCtx, pRefPicMarking);
- if (iRet != ERR_NONE) {
- if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) {
- iRet = RemainOneBufferInDpbForEC (pCtx);
- WELS_VERIFY_RETURN_IF (iRet, iRet);
- } else {
- return iRet;
- }
- }
-
- if (pCtx->bLastHasMmco5) {
- pCtx->pDec->iFrameNum = 0;
- pCtx->pDec->iFramePoc = 0;
- }
-
- } else {
- iRet = SlidingWindow (pCtx);
- if (iRet != ERR_NONE) {
- if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) {
- iRet = RemainOneBufferInDpbForEC (pCtx);
- WELS_VERIFY_RETURN_IF (iRet, iRet);
- } else {
- return iRet;
- }
- }
- }
- }
-
- if (!pCtx->pDec->bIsLongRef) {
- if (pRefPic->uiLongRefCount[LIST_0] + pRefPic->uiShortRefCount[LIST_0] >= WELS_MAX (1, pCtx->pSps->iNumRefFrames)) {
- if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) {
- iRet = RemainOneBufferInDpbForEC (pCtx);
- WELS_VERIFY_RETURN_IF (iRet, iRet);
- } else {
- return ERR_INFO_INVALID_MMCO_REF_NUM_OVERFLOW;
- }
- }
- iRet = AddShortTermToList (pRefPic, pCtx->pDec);
- }
-
- return iRet;
-}
-
-static int32_t MMCO (PWelsDecoderContext pCtx, PRefPicMarking pRefPicMarking) {
- PSps pSps = pCtx->pCurDqLayer->sLayerInfo.pSps;
- int32_t i = 0;
- int32_t iRet = ERR_NONE;
- for (i = 0; i < MAX_MMCO_COUNT && pRefPicMarking->sMmcoRef[i].uiMmcoType != MMCO_END; i++) {
- uint32_t uiMmcoType = pRefPicMarking->sMmcoRef[i].uiMmcoType;
- int32_t iShortFrameNum = (pCtx->iFrameNum - pRefPicMarking->sMmcoRef[i].iDiffOfPicNum) & ((
- 1 << pSps->uiLog2MaxFrameNum) - 1);
- uint32_t uiLongTermPicNum = pRefPicMarking->sMmcoRef[i].uiLongTermPicNum;
- int32_t iLongTermFrameIdx = pRefPicMarking->sMmcoRef[i].iLongTermFrameIdx;
- int32_t iMaxLongTermFrameIdx = pRefPicMarking->sMmcoRef[i].iMaxLongTermFrameIdx;
- if (uiMmcoType > MMCO_LONG) {
- return ERR_INFO_INVALID_MMCO_OPCODE_BASE;
- }
- iRet = MMCOProcess (pCtx, uiMmcoType, iShortFrameNum, uiLongTermPicNum, iLongTermFrameIdx, iMaxLongTermFrameIdx);
- if (iRet != ERR_NONE) {
- return iRet;
- }
- }
- if (i == MAX_MMCO_COUNT) { //although Rec does not handle this condition, we here prohibit too many MMCO op
- return ERR_INFO_INVALID_MMCO_NUM;
- }
-
- return ERR_NONE;
-}
-static int32_t MMCOProcess (PWelsDecoderContext pCtx, uint32_t uiMmcoType,
- int32_t iShortFrameNum, uint32_t uiLongTermPicNum, int32_t iLongTermFrameIdx, int32_t iMaxLongTermFrameIdx) {
- PRefPic pRefPic = &pCtx->sRefPic;
- PPicture pPic = NULL;
- int32_t i = 0;
- int32_t iRet = ERR_NONE;
-
- switch (uiMmcoType) {
- case MMCO_SHORT2UNUSED:
- pPic = WelsDelShortFromListSetUnref (pRefPic, iShortFrameNum);
- if (pPic == NULL) {
- WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "MMCO_SHORT2UNUSED: delete an empty entry from short term list");
- }
- break;
- case MMCO_LONG2UNUSED:
- pPic = WelsDelLongFromListSetUnref (pRefPic, uiLongTermPicNum);
- if (pPic == NULL) {
- WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "MMCO_LONG2UNUSED: delete an empty entry from long term list");
- }
- break;
- case MMCO_SHORT2LONG:
- if (iLongTermFrameIdx > pRefPic->iMaxLongTermFrameIdx) {
- return ERR_INFO_INVALID_MMCO_LONG_TERM_IDX_EXCEED_MAX;
- }
- pPic = WelsDelShortFromList (pRefPic, iShortFrameNum);
- if (pPic == NULL) {
- WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "MMCO_LONG2LONG: delete an empty entry from short term list");
- break;
- }
- WelsDelLongFromListSetUnref (pRefPic, iLongTermFrameIdx);
-#ifdef LONG_TERM_REF
- pCtx->bCurAuContainLtrMarkSeFlag = true;
- pCtx->iFrameNumOfAuMarkedLtr = iShortFrameNum;
- WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO, "ex_mark_avc():::MMCO_SHORT2LONG:::LTR marking....iFrameNum: %d",
- pCtx->iFrameNumOfAuMarkedLtr);
-#endif
-
- MarkAsLongTerm (pRefPic, iShortFrameNum, iLongTermFrameIdx, uiLongTermPicNum);
- break;
- case MMCO_SET_MAX_LONG:
- pRefPic->iMaxLongTermFrameIdx = iMaxLongTermFrameIdx;
- for (i = 0 ; i < pRefPic->uiLongRefCount[LIST_0]; i++) {
- if (pRefPic->pLongRefList[LIST_0][i]->iLongTermFrameIdx > pRefPic->iMaxLongTermFrameIdx) {
- WelsDelLongFromListSetUnref (pRefPic, pRefPic->pLongRefList[LIST_0][i]->iLongTermFrameIdx);
- }
- }
- break;
- case MMCO_RESET:
- WelsResetRefPic (pCtx);
- pCtx->bLastHasMmco5 = true;
- break;
- case MMCO_LONG:
- if (iLongTermFrameIdx > pRefPic->iMaxLongTermFrameIdx) {
- return ERR_INFO_INVALID_MMCO_LONG_TERM_IDX_EXCEED_MAX;
- }
- WelsDelLongFromListSetUnref (pRefPic, iLongTermFrameIdx);
- if (pRefPic->uiLongRefCount[LIST_0] + pRefPic->uiShortRefCount[LIST_0] >= WELS_MAX (1, pCtx->pSps->iNumRefFrames)) {
- return ERR_INFO_INVALID_MMCO_REF_NUM_OVERFLOW;
- }
-#ifdef LONG_TERM_REF
- pCtx->bCurAuContainLtrMarkSeFlag = true;
- pCtx->iFrameNumOfAuMarkedLtr = pCtx->iFrameNum;
- WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO, "ex_mark_avc():::MMCO_LONG:::LTR marking....iFrameNum: %d",
- pCtx->iFrameNum);
-#endif
- iRet = AddLongTermToList (pRefPic, pCtx->pDec, iLongTermFrameIdx, uiLongTermPicNum);
- break;
- default :
- break;
- }
-
- return iRet;
-}
-
-static int32_t SlidingWindow (PWelsDecoderContext pCtx) {
- PRefPic pRefPic = &pCtx->sRefPic;
- PPicture pPic = NULL;
- int32_t i = 0;
-
- if (pCtx->sRefPic.uiShortRefCount[LIST_0] + pCtx->sRefPic.uiLongRefCount[LIST_0] >= pCtx->pSps->iNumRefFrames) {
- if (pCtx->sRefPic.uiShortRefCount[LIST_0] == 0) {
- WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "No reference picture in short term list when sliding window");
- return ERR_INFO_INVALID_MMCO_REF_NUM_NOT_ENOUGH;
- }
- for (i = pRefPic->uiShortRefCount[LIST_0] - 1; i >= 0; i--) {
- pPic = WelsDelShortFromList (pRefPic, pRefPic->pShortRefList[LIST_0][i]->iFrameNum);
- if (pPic) {
- SetUnRef (pPic);
- break;
- } else {
- return ERR_INFO_INVALID_MMCO_REF_NUM_OVERFLOW;
- }
- }
- }
- return ERR_NONE;
-}
-
-static PPicture WelsDelShortFromList (PRefPic pRefPic, int32_t iFrameNum) {
- int32_t i = 0;
- int32_t iMoveSize = 0;
- PPicture pPic = NULL;
-
- for (i = 0; i < pRefPic->uiShortRefCount[LIST_0]; i++) {
- if (pRefPic->pShortRefList[LIST_0][i]->iFrameNum == iFrameNum) {
- iMoveSize = pRefPic->uiShortRefCount[LIST_0] - i - 1;
- pRefPic->pShortRefList[LIST_0][i]->bUsedAsRef = false;
- pPic = pRefPic->pShortRefList[LIST_0][i];
- pRefPic->pShortRefList[LIST_0][i] = NULL;
- if (iMoveSize > 0) {
- memmove (&pRefPic->pShortRefList[LIST_0][i], &pRefPic->pShortRefList[LIST_0][i + 1],
- iMoveSize * sizeof (PPicture)); //confirmed_safe_unsafe_usage
- }
- pRefPic->uiShortRefCount[LIST_0]--;
- pRefPic->pShortRefList[LIST_0][pRefPic->uiShortRefCount[LIST_0]] = NULL;
- break;
- }
- }
-
- return pPic;
-}
-
-static PPicture WelsDelShortFromListSetUnref (PRefPic pRefPic, int32_t iFrameNum) {
- PPicture pPic = WelsDelShortFromList (pRefPic, iFrameNum);
- if (pPic) {
- SetUnRef (pPic);
- }
- return pPic;
-}
-
-static PPicture WelsDelLongFromList (PRefPic pRefPic, uint32_t uiLongTermFrameIdx) {
- PPicture pPic = NULL;
- int32_t i = 0;
- for (i = 0; i < pRefPic->uiLongRefCount[LIST_0]; i++) {
- pPic = pRefPic->pLongRefList[LIST_0][i];
- if (pPic->iLongTermFrameIdx == (int32_t)uiLongTermFrameIdx) {
- int32_t iMoveSize = pRefPic->uiLongRefCount[LIST_0] - i - 1;
- pPic->bUsedAsRef = false;
- pPic->bIsLongRef = false;
- if (iMoveSize > 0) {
- memmove (&pRefPic->pLongRefList[LIST_0][i], &pRefPic->pLongRefList[LIST_0][i + 1],
- iMoveSize * sizeof (PPicture)); //confirmed_safe_unsafe_usage
- }
- pRefPic->uiLongRefCount[LIST_0]--;
- pRefPic->pLongRefList[LIST_0][pRefPic->uiLongRefCount[LIST_0]] = NULL;
- return pPic;
- }
- }
- return NULL;
-}
-
-static PPicture WelsDelLongFromListSetUnref (PRefPic pRefPic, uint32_t uiLongTermFrameIdx) {
- PPicture pPic = WelsDelLongFromList (pRefPic, uiLongTermFrameIdx);
- if (pPic) {
- SetUnRef (pPic);
- }
- return pPic;
-}
-
-static int32_t AddShortTermToList (PRefPic pRefPic, PPicture pPic) {
- pPic->bUsedAsRef = true;
- pPic->bIsLongRef = false;
- pPic->iLongTermFrameIdx = -1;
- if (pRefPic->uiShortRefCount[LIST_0] > 0) {
- // Check the duplicate frame_num in short ref list
- for (int32_t iPos = 0; iPos < pRefPic->uiShortRefCount[LIST_0]; iPos++) {
- if (pPic->iFrameNum == pRefPic->pShortRefList[LIST_0][iPos]->iFrameNum) {
- // Replace the previous ref pic with the new one with the same frame_num
- pRefPic->pShortRefList[LIST_0][iPos] = pPic;
- return ERR_INFO_DUPLICATE_FRAME_NUM;
- }
- }
-
- memmove (&pRefPic->pShortRefList[LIST_0][1], &pRefPic->pShortRefList[LIST_0][0],
- pRefPic->uiShortRefCount[LIST_0]*sizeof (PPicture));//confirmed_safe_unsafe_usage
- }
- pRefPic->pShortRefList[LIST_0][0] = pPic;
- pRefPic->uiShortRefCount[LIST_0]++;
- return ERR_NONE;
-}
-
-static int32_t AddLongTermToList (PRefPic pRefPic, PPicture pPic, int32_t iLongTermFrameIdx,
- uint32_t uiLongTermPicNum) {
- int32_t i = 0;
-
- pPic->bUsedAsRef = true;
- pPic->bIsLongRef = true;
- pPic->iLongTermFrameIdx = iLongTermFrameIdx;
- pPic->uiLongTermPicNum = uiLongTermPicNum;
- if (pRefPic->uiLongRefCount[LIST_0] == 0) {
- pRefPic->pLongRefList[LIST_0][pRefPic->uiLongRefCount[LIST_0]] = pPic;
- } else {
- for (i = 0; i < pRefPic->uiLongRefCount[LIST_0]; i++) {
- if (pRefPic->pLongRefList[LIST_0][i]->iLongTermFrameIdx > pPic->iLongTermFrameIdx) {
- break;
- }
- }
- memmove (&pRefPic->pLongRefList[LIST_0][i + 1], &pRefPic->pLongRefList[LIST_0][i],
- (pRefPic->uiLongRefCount[LIST_0] - i)*sizeof (PPicture)); //confirmed_safe_unsafe_usage
- pRefPic->pLongRefList[LIST_0][i] = pPic;
- }
-
- pRefPic->uiLongRefCount[LIST_0]++;
- return ERR_NONE;
-}
-
-static int32_t MarkAsLongTerm (PRefPic pRefPic, int32_t iFrameNum, int32_t iLongTermFrameIdx,
- uint32_t uiLongTermPicNum) {
- PPicture pPic = NULL;
- int32_t i = 0;
- int32_t iRet = ERR_NONE;
- WelsDelLongFromListSetUnref (pRefPic, iLongTermFrameIdx);
-
- for (i = 0; i < pRefPic->uiRefCount[LIST_0]; i++) {
- pPic = pRefPic->pRefList[LIST_0][i];
- if (pPic->iFrameNum == iFrameNum && !pPic->bIsLongRef) {
- iRet = AddLongTermToList (pRefPic, pPic, iLongTermFrameIdx, uiLongTermPicNum);
- break;
- }
- }
-
- return iRet;
-}
-
-#ifdef LONG_TERM_REF
-int32_t GetLTRFrameIndex (PRefPic pRefPic, int32_t iAncLTRFrameNum) {
- int32_t iLTRFrameIndex = -1;
- PPicture pPic;
- for (int i = 0; i < pRefPic->uiLongRefCount[0]; ++i) {
- pPic = pRefPic->pLongRefList[LIST_0][i];
- if (pPic->iFrameNum == iAncLTRFrameNum) {
- return (pPic->iLongTermFrameIdx);
- }
- }
- return iLTRFrameIndex;
-}
-#endif
-
-static int32_t RemainOneBufferInDpbForEC (PWelsDecoderContext pCtx) {
- int32_t iRet = ERR_NONE;
- PRefPic pRefPic = &pCtx->sRefPic;
- if (pRefPic->uiShortRefCount[0] + pRefPic->uiLongRefCount[0] < pCtx->pSps->iNumRefFrames)
- return iRet;
-
- if (pRefPic->uiShortRefCount[0] > 0) {
- iRet = SlidingWindow (pCtx);
- } else { //all LTR, remove the smallest long_term_frame_idx
- int32_t iLongTermFrameIdx = 0;
- int32_t iMaxLongTermFrameIdx = pRefPic->iMaxLongTermFrameIdx;
-#ifdef LONG_TERM_REF
- int32_t iCurrLTRFrameIdx = GetLTRFrameIndex (pRefPic, pCtx->iFrameNumOfAuMarkedLtr);
-#endif
- while ((pRefPic->uiLongRefCount[0] >= pCtx->pSps->iNumRefFrames) && (iLongTermFrameIdx <= iMaxLongTermFrameIdx)) {
-#ifdef LONG_TERM_REF
- if (iLongTermFrameIdx == iCurrLTRFrameIdx) {
- iLongTermFrameIdx++;
- continue;
- }
-#endif
- WelsDelLongFromListSetUnref (pRefPic, iLongTermFrameIdx);
- iLongTermFrameIdx++;
- }
- }
- if (pRefPic->uiShortRefCount[0] + pRefPic->uiLongRefCount[0] >=
- pCtx->pSps->iNumRefFrames) { //fail to remain one empty buffer in DPB
- WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "RemainOneBufferInDpbForEC(): empty one DPB failed for EC!");
- iRet = ERR_INFO_REF_COUNT_OVERFLOW;
- }
-
- return iRet;
-}
-
-} // namespace WelsDec
+/*!
+ * \copy
+ * Copyright (c) 2008-2013, Cisco Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * manage_dec_ref.cpp
+ *
+ * Abstract
+ * Implementation for managing reference picture
+ *
+ * History
+ * 07/21/2008 Created
+ *
+ *****************************************************************************/
+
+#include "manage_dec_ref.h"
+#include "error_concealment.h"
+#include "error_code.h"
+
+namespace WelsDec {
+
+static PPicture WelsDelShortFromList (PRefPic pRefPic, int32_t iFrameNum);
+static PPicture WelsDelLongFromList (PRefPic pRefPic, uint32_t uiLongTermFrameIdx);
+static PPicture WelsDelShortFromListSetUnref (PRefPic pRefPic, int32_t iFrameNum);
+static PPicture WelsDelLongFromListSetUnref (PRefPic pRefPic, uint32_t uiLongTermFrameIdx);
+
+static int32_t MMCO (PWelsDecoderContext pCtx, PRefPicMarking pRefPicMarking);
+static int32_t MMCOProcess (PWelsDecoderContext pCtx, uint32_t uiMmcoType,
+ int32_t iShortFrameNum, uint32_t uiLongTermPicNum, int32_t iLongTermFrameIdx, int32_t iMaxLongTermFrameIdx);
+static int32_t SlidingWindow (PWelsDecoderContext pCtx);
+
+static int32_t AddShortTermToList (PRefPic pRefPic, PPicture pPic);
+static int32_t AddLongTermToList (PRefPic pRefPic, PPicture pPic, int32_t iLongTermFrameIdx, uint32_t uiLongTermPicNum);
+static int32_t MarkAsLongTerm (PRefPic pRefPic, int32_t iFrameNum, int32_t iLongTermFrameIdx,
+ uint32_t uiLongTermPicNum);
+static int32_t WelsCheckAndRecoverForFutureDecoding (PWelsDecoderContext pCtx);
+#ifdef LONG_TERM_REF
+int32_t GetLTRFrameIndex (PRefPic pRefPic, int32_t iAncLTRFrameNum);
+#endif
+static int32_t RemainOneBufferInDpbForEC (PWelsDecoderContext pCtx);
+
+static void SetUnRef (PPicture pRef) {
+ if (NULL != pRef) {
+ pRef->bUsedAsRef = false;
+ pRef->bIsLongRef = false;
+ pRef->iFrameNum = -1;
+ pRef->iFrameWrapNum = -1;
+ //pRef->iFramePoc = 0;
+ pRef->iLongTermFrameIdx = -1;
+ pRef->uiLongTermPicNum = 0;
+ pRef->uiQualityId = -1;
+ pRef->uiTemporalId = -1;
+ pRef->uiSpatialId = -1;
+ pRef->iSpsId = -1;
+ pRef->bIsComplete = false;
+ }
+}
+
+//reset pRefList when
+// 1.sps arrived that is new sequence starting
+// 2.IDR NAL i.e. 1st layer in IDR AU
+
+void WelsResetRefPic (PWelsDecoderContext pCtx) {
+ int32_t i = 0;
+ PRefPic pRefPic = &pCtx->sRefPic;
+ pCtx->sRefPic.uiLongRefCount[LIST_0] = pCtx->sRefPic.uiShortRefCount[LIST_0] = 0;
+
+ pRefPic->uiRefCount[LIST_0] = 0;
+ pRefPic->uiRefCount[LIST_1] = 0;
+
+ for (i = 0; i < MAX_DPB_COUNT; i++) {
+ if (pRefPic->pShortRefList[LIST_0][i] != NULL) {
+ SetUnRef (pRefPic->pShortRefList[LIST_0][i]);
+ pRefPic->pShortRefList[LIST_0][i] = NULL;
+ }
+ }
+ pRefPic->uiShortRefCount[LIST_0] = 0;
+
+ for (i = 0; i < MAX_DPB_COUNT; i++) {
+ if (pRefPic->pLongRefList[LIST_0][i] != NULL) {
+ SetUnRef (pRefPic->pLongRefList[LIST_0][i]);
+ pRefPic->pLongRefList[LIST_0][i] = NULL;
+ }
+ }
+ pRefPic->uiLongRefCount[LIST_0] = 0;
+}
+
+static int32_t WelsCheckAndRecoverForFutureDecoding (PWelsDecoderContext pCtx) {
+ if ((pCtx->sRefPic.uiShortRefCount[LIST_0] + pCtx->sRefPic.uiLongRefCount[LIST_0] <= 0) && (pCtx->eSliceType != I_SLICE
+ && pCtx->eSliceType != SI_SLICE)) {
+ if (pCtx->pParam->eEcActiveIdc !=
+ ERROR_CON_DISABLE) { //IDR lost!, recover it for future decoding with data all set to 0
+ PPicture pRef = PrefetchPic (pCtx->pPicBuff);
+ if (pRef != NULL) {
+ // IDR lost, set new
+ pRef->bIsComplete = false; // Set complete flag to false for lost IDR ref picture
+ pRef->iSpsId = pCtx->pSps->iSpsId;
+ pRef->iPpsId = pCtx->pPps->iPpsId;
+ pCtx->iErrorCode |= dsDataErrorConcealed;
+ bool bCopyPrevious = ((ERROR_CON_FRAME_COPY_CROSS_IDR == pCtx->pParam->eEcActiveIdc)
+ || (ERROR_CON_SLICE_COPY_CROSS_IDR == pCtx->pParam->eEcActiveIdc)
+ || (ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE == pCtx->pParam->eEcActiveIdc)
+ || (ERROR_CON_SLICE_MV_COPY_CROSS_IDR == pCtx->pParam->eEcActiveIdc)
+ || (ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE == pCtx->pParam->eEcActiveIdc))
+ && (NULL != pCtx->pPreviousDecodedPictureInDpb);
+ bCopyPrevious = bCopyPrevious && (pRef->iWidthInPixel == pCtx->pPreviousDecodedPictureInDpb->iWidthInPixel)
+ && (pRef->iHeightInPixel == pCtx->pPreviousDecodedPictureInDpb->iHeightInPixel);
+
+ if (!bCopyPrevious) {
+ memset (pRef->pData[0], 128, pRef->iLinesize[0] * pRef->iHeightInPixel);
+ memset (pRef->pData[1], 128, pRef->iLinesize[1] * pRef->iHeightInPixel / 2);
+ memset (pRef->pData[2], 128, pRef->iLinesize[2] * pRef->iHeightInPixel / 2);
+ } else if (pRef == pCtx->pPreviousDecodedPictureInDpb) {
+ WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "WelsInitRefList()::EC memcpy overlap.");
+ } else {
+ memcpy (pRef->pData[0], pCtx->pPreviousDecodedPictureInDpb->pData[0], pRef->iLinesize[0] * pRef->iHeightInPixel);
+ memcpy (pRef->pData[1], pCtx->pPreviousDecodedPictureInDpb->pData[1], pRef->iLinesize[1] * pRef->iHeightInPixel / 2);
+ memcpy (pRef->pData[2], pCtx->pPreviousDecodedPictureInDpb->pData[2], pRef->iLinesize[2] * pRef->iHeightInPixel / 2);
+ }
+ pRef->iFrameNum = 0;
+ pRef->iFramePoc = 0;
+ pRef->uiTemporalId = pRef->uiQualityId = 0;
+ ExpandReferencingPicture (pRef->pData, pRef->iWidthInPixel, pRef->iHeightInPixel, pRef->iLinesize,
+ pCtx->sExpandPicFunc.pfExpandLumaPicture, pCtx->sExpandPicFunc.pfExpandChromaPicture);
+ AddShortTermToList (&pCtx->sRefPic, pRef);
+ } else {
+ WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "WelsInitRefList()::PrefetchPic for EC errors.");
+ pCtx->iErrorCode |= dsOutOfMemory;
+ return ERR_INFO_REF_COUNT_OVERFLOW;
+ }
+ }
+ }
+ return ERR_NONE;
+}
+
+static void WrapShortRefPicNum (PWelsDecoderContext pCtx) {
+ int32_t i;
+ PSliceHeader pSliceHeader = &pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader;
+ int32_t iMaxPicNum = 1 << pSliceHeader->pSps->uiLog2MaxFrameNum;
+ PPicture* ppShoreRefList = pCtx->sRefPic.pShortRefList[LIST_0];
+ int32_t iShortRefCount = pCtx->sRefPic.uiShortRefCount[LIST_0];
+ //wrap pic num
+ for (i = 0; i < iShortRefCount; i++) {
+ if (ppShoreRefList[i]) {
+ if (ppShoreRefList[i]->iFrameNum > pSliceHeader->iFrameNum)
+ ppShoreRefList[i]->iFrameWrapNum = ppShoreRefList[i]->iFrameNum - iMaxPicNum;
+ else
+ ppShoreRefList[i]->iFrameWrapNum = ppShoreRefList[i]->iFrameNum;
+ }
+ }
+}
+
+/**
+* fills the pRefPic.pRefList LIST_0 and LIST_0 for B-Slice.
+*/
+int32_t WelsInitBSliceRefList (PWelsDecoderContext pCtx, int32_t iPoc) {
+
+ int32_t err = WelsCheckAndRecoverForFutureDecoding (pCtx);
+ if (err != ERR_NONE) return err;
+
+ WrapShortRefPicNum (pCtx);
+
+ PPicture* ppShoreRefList = pCtx->sRefPic.pShortRefList[LIST_0];
+ PPicture* ppLongRefList = pCtx->sRefPic.pLongRefList[LIST_0];
+ memset (pCtx->sRefPic.pRefList[LIST_0], 0, MAX_DPB_COUNT * sizeof (PPicture));
+ memset (pCtx->sRefPic.pRefList[LIST_1], 0, MAX_DPB_COUNT * sizeof (PPicture));
+ int32_t iLSCurrPocCount = 0;
+ int32_t iLTCurrPocCount = 0;
+ PPicture pLSCurrPocList0[MAX_DPB_COUNT];
+ PPicture pLTCurrPocList0[MAX_DPB_COUNT];
+ for (int32_t i = 0; i < pCtx->sRefPic.uiShortRefCount[LIST_0]; ++i) {
+ if (ppShoreRefList[i]->iFramePoc < iPoc) {
+ pLSCurrPocList0[iLSCurrPocCount++] = ppShoreRefList[i];
+ }
+ }
+ for (int32_t i = pCtx->sRefPic.uiShortRefCount[LIST_0] - 1; i >= 0; --i) {
+ if (ppShoreRefList[i]->iFramePoc > iPoc) {
+ pLTCurrPocList0[iLTCurrPocCount++] = ppShoreRefList[i];
+ }
+ }
+ if (pCtx->sRefPic.uiLongRefCount[LIST_0] > 1) {
+ //long sorts in increasing order
+ PPicture pTemp;
+ for (int32_t i = 0; i < pCtx->sRefPic.uiLongRefCount[LIST_0]; ++i) {
+ for (int32_t j = i + 1; j < pCtx->sRefPic.uiLongRefCount[LIST_0]; ++j) {
+ if (ppLongRefList[j]->iFramePoc < ppLongRefList[i]->iFramePoc) {
+ pTemp = ppLongRefList[i];
+ ppLongRefList[i] = ppLongRefList[j];
+ ppLongRefList[j] = pTemp;
+ }
+ }
+ }
+ }
+ int32_t iCurrPocCount = iLSCurrPocCount + iLTCurrPocCount;
+ int32_t iCount = 0;
+ //LIST_0
+ //short
+ //It may need to sort LIST_0 and LIST_1 so that they will have the right default orders.
+ for (int32_t i = 0; i < iLSCurrPocCount; ++i) {
+ pCtx->sRefPic.pRefList[LIST_0][iCount++] = pLSCurrPocList0[i];
+ }
+ if (iLSCurrPocCount > 1) {
+ //LIST_0 short sorts in decreasing order
+ PPicture pTemp;
+ for (int32_t i = 0; i < iLSCurrPocCount; ++i) {
+ for (int32_t j = i + 1; j < iLSCurrPocCount; ++j) {
+ if (pCtx->sRefPic.pRefList[LIST_0][j]->iFramePoc > pCtx->sRefPic.pRefList[LIST_0][i]->iFramePoc) {
+ pTemp = pCtx->sRefPic.pRefList[LIST_0][i];
+ pCtx->sRefPic.pRefList[LIST_0][i] = pCtx->sRefPic.pRefList[LIST_0][j];
+ pCtx->sRefPic.pRefList[LIST_0][j] = pTemp;
+ }
+ }
+ }
+ }
+ for (int32_t i = 0; i < iLTCurrPocCount; ++i) {
+ pCtx->sRefPic.pRefList[LIST_0][iCount++] = pLTCurrPocList0[i];
+ }
+ if (iLTCurrPocCount > 1) {
+ //LIST_0 short sorts in increasing order
+ PPicture pTemp;
+ for (int32_t i = iLSCurrPocCount; i < iCurrPocCount; ++i) {
+ for (int32_t j = i + 1; j < iCurrPocCount; ++j) {
+ if (pCtx->sRefPic.pRefList[LIST_0][j]->iFramePoc < pCtx->sRefPic.pRefList[LIST_0][i]->iFramePoc) {
+ pTemp = pCtx->sRefPic.pRefList[LIST_0][i];
+ pCtx->sRefPic.pRefList[LIST_0][i] = pCtx->sRefPic.pRefList[LIST_0][j];
+ pCtx->sRefPic.pRefList[LIST_0][j] = pTemp;
+ }
+ }
+ }
+ }
+ //long
+ for (int32_t i = 0; i < pCtx->sRefPic.uiLongRefCount[LIST_0]; ++i) {
+ pCtx->sRefPic.pRefList[LIST_0][iCount++] = ppLongRefList[i];
+ }
+ pCtx->sRefPic.uiRefCount[LIST_0] = iCount;
+
+ iCount = 0;
+ //LIST_1
+ //short
+ for (int32_t i = 0; i < iLTCurrPocCount; ++i) {
+ pCtx->sRefPic.pRefList[LIST_1][iCount++] = pLTCurrPocList0[i];
+ }
+ if (iLTCurrPocCount > 1) {
+ //LIST_1 short sorts in increasing order
+ PPicture pTemp;
+ for (int32_t i = 0; i < iLTCurrPocCount; ++i) {
+ for (int32_t j = i + 1; j < iLTCurrPocCount; ++j) {
+ if (pCtx->sRefPic.pRefList[LIST_1][j]->iFramePoc < pCtx->sRefPic.pRefList[LIST_1][i]->iFramePoc) {
+ pTemp = pCtx->sRefPic.pRefList[LIST_1][i];
+ pCtx->sRefPic.pRefList[LIST_1][i] = pCtx->sRefPic.pRefList[LIST_1][j];
+ pCtx->sRefPic.pRefList[LIST_1][j] = pTemp;
+ }
+ }
+ }
+ }
+ for (int32_t i = 0; i < iLSCurrPocCount; ++i) {
+ pCtx->sRefPic.pRefList[LIST_1][iCount++] = pLSCurrPocList0[i];
+ }
+ if (iLSCurrPocCount > 1) {
+ //LIST_1 short sorts in decreasing order
+ PPicture pTemp;
+ for (int32_t i = iLTCurrPocCount; i < iCurrPocCount; ++i) {
+ for (int32_t j = i + 1; j < iCurrPocCount; ++j) {
+ if (pCtx->sRefPic.pRefList[LIST_1][j]->iFramePoc > pCtx->sRefPic.pRefList[LIST_1][i]->iFramePoc) {
+ pTemp = pCtx->sRefPic.pRefList[LIST_1][i];
+ pCtx->sRefPic.pRefList[LIST_1][i] = pCtx->sRefPic.pRefList[LIST_1][j];
+ pCtx->sRefPic.pRefList[LIST_1][j] = pTemp;
+ }
+ }
+ }
+ }
+ //long
+ for (int32_t i = 0; i < pCtx->sRefPic.uiLongRefCount[LIST_0]; ++i) {
+ pCtx->sRefPic.pRefList[LIST_1][iCount++] = ppLongRefList[i];
+ }
+ pCtx->sRefPic.uiRefCount[LIST_1] = iCount;
+ return ERR_NONE;
+}
+
+/**
+ * fills the pRefPic.pRefList.
+ */
+int32_t WelsInitRefList (PWelsDecoderContext pCtx, int32_t iPoc) {
+
+ int32_t err = WelsCheckAndRecoverForFutureDecoding (pCtx);
+ if (err != ERR_NONE) return err;
+
+ WrapShortRefPicNum (pCtx);
+
+ PPicture* ppShoreRefList = pCtx->sRefPic.pShortRefList[LIST_0];
+ PPicture* ppLongRefList = pCtx->sRefPic.pLongRefList[LIST_0];
+ memset (pCtx->sRefPic.pRefList[LIST_0], 0, MAX_DPB_COUNT * sizeof (PPicture));
+
+ int32_t i, iCount = 0;
+ //short
+ for (i = 0; i < pCtx->sRefPic.uiShortRefCount[LIST_0]; ++i) {
+ pCtx->sRefPic.pRefList[LIST_0][iCount++ ] = ppShoreRefList[i];
+ }
+
+ //long
+ for (i = 0; i < pCtx->sRefPic.uiLongRefCount[LIST_0] ; ++i) {
+ pCtx->sRefPic.pRefList[LIST_0][iCount++ ] = ppLongRefList[i];
+ }
+ pCtx->sRefPic.uiRefCount[LIST_0] = iCount;
+
+ return ERR_NONE;
+}
+
+int32_t WelsReorderRefList (PWelsDecoderContext pCtx) {
+
+ if (pCtx->eSliceType == I_SLICE || pCtx->eSliceType == SI_SLICE) {
+ return ERR_NONE;
+ }
+
+ PRefPicListReorderSyn pRefPicListReorderSyn = pCtx->pCurDqLayer->pRefPicListReordering;
+ PNalUnitHeaderExt pNalHeaderExt = &pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt;
+ PSliceHeader pSliceHeader = &pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader;
+ int32_t ListCount = 1;
+ if (pCtx->eSliceType == B_SLICE) ListCount = 2;
+ for (int32_t listIdx = 0; listIdx < ListCount; ++listIdx) {
+ PPicture pPic = NULL;
+ PPicture* ppRefList = pCtx->sRefPic.pRefList[listIdx];
+ int32_t iMaxRefIdx = pCtx->pSps->iNumRefFrames;
+ int32_t iRefCount = pCtx->sRefPic.uiRefCount[listIdx];
+ int32_t iPredFrameNum = pSliceHeader->iFrameNum;
+ int32_t iMaxPicNum = 1 << pSliceHeader->pSps->uiLog2MaxFrameNum;
+ int32_t iAbsDiffPicNum = -1;
+ int32_t iReorderingIndex = 0;
+ int32_t i = 0;
+
+ if (iRefCount <= 0) {
+ pCtx->iErrorCode = dsNoParamSets; //No any reference for decoding, SHOULD request IDR
+ return ERR_INFO_REFERENCE_PIC_LOST;
+ }
+
+ if (pRefPicListReorderSyn->bRefPicListReorderingFlag[listIdx]) {
+ while ((iReorderingIndex < iMaxRefIdx)
+ && (pRefPicListReorderSyn->sReorderingSyn[listIdx][iReorderingIndex].uiReorderingOfPicNumsIdc != 3)) {
+ uint16_t uiReorderingOfPicNumsIdc =
+ pRefPicListReorderSyn->sReorderingSyn[listIdx][iReorderingIndex].uiReorderingOfPicNumsIdc;
+ if (uiReorderingOfPicNumsIdc < 2) {
+ iAbsDiffPicNum = pRefPicListReorderSyn->sReorderingSyn[listIdx][iReorderingIndex].uiAbsDiffPicNumMinus1 + 1;
+
+ if (uiReorderingOfPicNumsIdc == 0) {
+ iPredFrameNum -= iAbsDiffPicNum;
+ } else {
+ iPredFrameNum += iAbsDiffPicNum;
+ }
+ iPredFrameNum &= iMaxPicNum - 1;
+
+ for (i = iMaxRefIdx - 1; i >= 0; i--) {
+ if (ppRefList[i] != NULL && ppRefList[i]->iFrameNum == iPredFrameNum && !ppRefList[i]->bIsLongRef) {
+ if ((pNalHeaderExt->uiQualityId == ppRefList[i]->uiQualityId)
+ && (pSliceHeader->iSpsId != ppRefList[i]->iSpsId)) { //check;
+ WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "WelsReorderRefList()::::BASE LAYER::::iSpsId:%d, ref_sps_id:%d",
+ pSliceHeader->iSpsId, ppRefList[i]->iSpsId);
+ pCtx->iErrorCode = dsNoParamSets; //cross-IDR reference frame selection, SHOULD request IDR.--
+ return ERR_INFO_REFERENCE_PIC_LOST;
+ } else {
+ break;
+ }
+ }
+ }
+
+ } else if (uiReorderingOfPicNumsIdc == 2) {
+ for (i = iMaxRefIdx - 1; i >= 0; i--) {
+ if (ppRefList[i] != NULL && ppRefList[i]->bIsLongRef
+ && ppRefList[i]->iLongTermFrameIdx ==
+ pRefPicListReorderSyn->sReorderingSyn[listIdx][iReorderingIndex].uiLongTermPicNum) {
+ if ((pNalHeaderExt->uiQualityId == ppRefList[i]->uiQualityId)
+ && (pSliceHeader->iSpsId != ppRefList[i]->iSpsId)) { //check;
+ WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "WelsReorderRefList()::::BASE LAYER::::iSpsId:%d, ref_sps_id:%d",
+ pSliceHeader->iSpsId, ppRefList[i]->iSpsId);
+ pCtx->iErrorCode = dsNoParamSets; //cross-IDR reference frame selection, SHOULD request IDR.--
+ return ERR_INFO_REFERENCE_PIC_LOST;
+ } else {
+ break;
+ }
+ }
+ }
+ }
+ if (i < 0) {
+ return ERR_INFO_REFERENCE_PIC_LOST;
+ }
+ pPic = ppRefList[i];
+ if (i > iReorderingIndex) {
+ memmove (&ppRefList[1 + iReorderingIndex], &ppRefList[iReorderingIndex],
+ (i - iReorderingIndex) * sizeof (PPicture)); //confirmed_safe_unsafe_usage
+ } else if (i < iReorderingIndex) {
+ memmove (&ppRefList[1 + iReorderingIndex], &ppRefList[iReorderingIndex],
+ (iMaxRefIdx - iReorderingIndex) * sizeof (PPicture));
+ }
+ ppRefList[iReorderingIndex] = pPic;
+ iReorderingIndex++;
+ }
+ }
+ }
+ return ERR_NONE;
+}
+
+//WelsReorderRefList2 is the test code
+int32_t WelsReorderRefList2 (PWelsDecoderContext pCtx) {
+
+ if (pCtx->eSliceType == I_SLICE || pCtx->eSliceType == SI_SLICE) {
+ return ERR_NONE;
+ }
+
+ PRefPicListReorderSyn pRefPicListReorderSyn = pCtx->pCurDqLayer->pRefPicListReordering;
+ PSliceHeader pSliceHeader = &pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader;
+
+ PPicture* ppShoreRefList = pCtx->sRefPic.pShortRefList[LIST_0];
+ int32_t iShortRefCount = pCtx->sRefPic.uiShortRefCount[LIST_0];
+ PPicture* ppLongRefList = pCtx->sRefPic.pLongRefList[LIST_0];
+ int32_t iLongRefCount = pCtx->sRefPic.uiLongRefCount[LIST_0];
+ int32_t i = 0;
+ int32_t j = 0;
+ int32_t k = 0;
+ int32_t iMaxRefIdx = pCtx->pSps->iNumRefFrames;
+ const int32_t iCurFrameNum = pSliceHeader->iFrameNum;
+ const int32_t iMaxPicNum = 1 << pSliceHeader->pSps->uiLog2MaxFrameNum;
+ int32_t iListCount = 1;
+ if (pCtx->eSliceType == B_SLICE) iListCount = 2;
+ for (int32_t listIdx = 0; listIdx < iListCount; ++listIdx) {
+ PPicture* ppRefList = pCtx->sRefPic.pRefList[listIdx];
+ int32_t iCount = 0;
+ int32_t iRefCount = pSliceHeader->uiRefCount[listIdx];
+ int32_t iAbsDiffPicNum = -1;
+
+ if (pRefPicListReorderSyn->bRefPicListReorderingFlag[listIdx]) {
+ int32_t iPredFrameNum = iCurFrameNum;
+ for (i = 0; pRefPicListReorderSyn->sReorderingSyn[listIdx][i].uiReorderingOfPicNumsIdc != 3; i++) {
+ if (iCount >= iMaxRefIdx)
+ break;
+
+ for (j = iRefCount; j > iCount; j--)
+ ppRefList[j] = ppRefList[j - 1];
+
+ uint16_t uiReorderingOfPicNumsIdc =
+ pRefPicListReorderSyn->sReorderingSyn[listIdx][i].uiReorderingOfPicNumsIdc;
+
+ if (uiReorderingOfPicNumsIdc < 2) { // reorder short references
+ iAbsDiffPicNum = (int32_t) (pRefPicListReorderSyn->sReorderingSyn[listIdx][i].uiAbsDiffPicNumMinus1 + 1);
+ if (uiReorderingOfPicNumsIdc == 0) {
+ if (iPredFrameNum - iAbsDiffPicNum < 0)
+ iPredFrameNum -= (iAbsDiffPicNum - iMaxPicNum);
+ else
+ iPredFrameNum -= iAbsDiffPicNum;
+ } else {
+ if (iPredFrameNum + iAbsDiffPicNum >= iMaxPicNum)
+ iPredFrameNum += (iAbsDiffPicNum - iMaxPicNum);
+ else
+ iPredFrameNum += iAbsDiffPicNum;
+ }
+
+ if (iPredFrameNum > iCurFrameNum) {
+ iPredFrameNum -= iMaxPicNum;
+ }
+
+ for (j = 0; j < iShortRefCount; j++) {
+ if (ppShoreRefList[j]) {
+ if (ppShoreRefList[j]->iFrameWrapNum == iPredFrameNum) {
+ ppRefList[iCount++] = ppShoreRefList[j];
+ break;
+ }
+ }
+ }
+ k = iCount;
+ for (j = k; j <= iRefCount; j++) {
+ if (ppRefList[j] != NULL) {
+ if (ppRefList[j]->bIsLongRef || ppRefList[j]->iFrameWrapNum != iPredFrameNum)
+ ppRefList[k++] = ppRefList[j];
+ }
+ }
+ } else { // reorder long term references uiReorderingOfPicNumsIdc == 2
+ iPredFrameNum = pRefPicListReorderSyn->sReorderingSyn[listIdx][i].uiLongTermPicNum;
+ for (j = 0; j < iLongRefCount; j++) {
+ if (ppLongRefList[j] != NULL) {
+ if (ppLongRefList[j]->uiLongTermPicNum == (uint32_t)iPredFrameNum) {
+ ppRefList[iCount++] = ppLongRefList[j];
+ break;
+ }
+ }
+ }
+ k = iCount;
+ for (j = k; j <= iRefCount; j++) {
+ if (ppRefList[j] != NULL) {
+ if (!ppRefList[j]->bIsLongRef || ppLongRefList[j]->uiLongTermPicNum != (uint32_t)iPredFrameNum)
+ ppRefList[k++] = ppRefList[j];
+ }
+ }
+ }
+ }
+ }
+
+ for (i = WELS_MAX (1, WELS_MAX (iCount, pCtx->sRefPic.uiRefCount[listIdx])); i < iRefCount; i++)
+ ppRefList[i] = ppRefList[i - 1];
+ pCtx->sRefPic.uiRefCount[listIdx] = (uint8_t)WELS_MIN (WELS_MAX (iCount, pCtx->sRefPic.uiRefCount[listIdx]), iRefCount);
+ }
+ return ERR_NONE;
+}
+
+int32_t WelsMarkAsRef (PWelsDecoderContext pCtx) {
+ PRefPic pRefPic = &pCtx->sRefPic;
+ PRefPicMarking pRefPicMarking = pCtx->pCurDqLayer->pRefPicMarking;
+ PAccessUnit pCurAU = pCtx->pAccessUnitList;
+ bool bIsIDRAU = false;
+ uint32_t j;
+
+ int32_t iRet = ERR_NONE;
+
+ pCtx->pDec->uiQualityId = pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt.uiQualityId;
+ pCtx->pDec->uiTemporalId = pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt.uiTemporalId;
+ pCtx->pDec->iSpsId = pCtx->pSps->iSpsId;
+ pCtx->pDec->iPpsId = pCtx->pPps->iPpsId;
+
+ for (j = pCurAU->uiStartPos; j <= pCurAU->uiEndPos; j++) {
+ if (pCurAU->pNalUnitsList[j]->sNalHeaderExt.sNalUnitHeader.eNalUnitType == NAL_UNIT_CODED_SLICE_IDR
+ || pCurAU->pNalUnitsList[j]->sNalHeaderExt.bIdrFlag) {
+ bIsIDRAU = true;
+ break;
+ }
+ }
+ if (bIsIDRAU) {
+ if (pRefPicMarking->bLongTermRefFlag) {
+ pCtx->sRefPic.iMaxLongTermFrameIdx = 0;
+ AddLongTermToList (pRefPic, pCtx->pDec, 0, 0);
+ } else {
+ pCtx->sRefPic.iMaxLongTermFrameIdx = -1;
+ }
+ } else {
+ if (pRefPicMarking->bAdaptiveRefPicMarkingModeFlag) {
+ iRet = MMCO (pCtx, pRefPicMarking);
+ if (iRet != ERR_NONE) {
+ if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) {
+ iRet = RemainOneBufferInDpbForEC (pCtx);
+ WELS_VERIFY_RETURN_IF (iRet, iRet);
+ } else {
+ return iRet;
+ }
+ }
+
+ if (pCtx->bLastHasMmco5) {
+ pCtx->pDec->iFrameNum = 0;
+ pCtx->pDec->iFramePoc = 0;
+ }
+
+ } else {
+ iRet = SlidingWindow (pCtx);
+ if (iRet != ERR_NONE) {
+ if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) {
+ iRet = RemainOneBufferInDpbForEC (pCtx);
+ WELS_VERIFY_RETURN_IF (iRet, iRet);
+ } else {
+ return iRet;
+ }
+ }
+ }
+ }
+
+ if (!pCtx->pDec->bIsLongRef) {
+ if (pRefPic->uiLongRefCount[LIST_0] + pRefPic->uiShortRefCount[LIST_0] >= WELS_MAX (1, pCtx->pSps->iNumRefFrames)) {
+ if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) {
+ iRet = RemainOneBufferInDpbForEC (pCtx);
+ WELS_VERIFY_RETURN_IF (iRet, iRet);
+ } else {
+ return ERR_INFO_INVALID_MMCO_REF_NUM_OVERFLOW;
+ }
+ }
+ iRet = AddShortTermToList (pRefPic, pCtx->pDec);
+ }
+
+ return iRet;
+}
+
+static int32_t MMCO (PWelsDecoderContext pCtx, PRefPicMarking pRefPicMarking) {
+ PSps pSps = pCtx->pCurDqLayer->sLayerInfo.pSps;
+ int32_t i = 0;
+ int32_t iRet = ERR_NONE;
+ for (i = 0; i < MAX_MMCO_COUNT && pRefPicMarking->sMmcoRef[i].uiMmcoType != MMCO_END; i++) {
+ uint32_t uiMmcoType = pRefPicMarking->sMmcoRef[i].uiMmcoType;
+ int32_t iShortFrameNum = (pCtx->iFrameNum - pRefPicMarking->sMmcoRef[i].iDiffOfPicNum) & ((
+ 1 << pSps->uiLog2MaxFrameNum) - 1);
+ uint32_t uiLongTermPicNum = pRefPicMarking->sMmcoRef[i].uiLongTermPicNum;
+ int32_t iLongTermFrameIdx = pRefPicMarking->sMmcoRef[i].iLongTermFrameIdx;
+ int32_t iMaxLongTermFrameIdx = pRefPicMarking->sMmcoRef[i].iMaxLongTermFrameIdx;
+ if (uiMmcoType > MMCO_LONG) {
+ return ERR_INFO_INVALID_MMCO_OPCODE_BASE;
+ }
+ iRet = MMCOProcess (pCtx, uiMmcoType, iShortFrameNum, uiLongTermPicNum, iLongTermFrameIdx, iMaxLongTermFrameIdx);
+ if (iRet != ERR_NONE) {
+ return iRet;
+ }
+ }
+ if (i == MAX_MMCO_COUNT) { //although Rec does not handle this condition, we here prohibit too many MMCO op
+ return ERR_INFO_INVALID_MMCO_NUM;
+ }
+
+ return ERR_NONE;
+}
+static int32_t MMCOProcess (PWelsDecoderContext pCtx, uint32_t uiMmcoType,
+ int32_t iShortFrameNum, uint32_t uiLongTermPicNum, int32_t iLongTermFrameIdx, int32_t iMaxLongTermFrameIdx) {
+ PRefPic pRefPic = &pCtx->sRefPic;
+ PPicture pPic = NULL;
+ int32_t i = 0;
+ int32_t iRet = ERR_NONE;
+
+ switch (uiMmcoType) {
+ case MMCO_SHORT2UNUSED:
+ pPic = WelsDelShortFromListSetUnref (pRefPic, iShortFrameNum);
+ if (pPic == NULL) {
+ WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "MMCO_SHORT2UNUSED: delete an empty entry from short term list");
+ }
+ break;
+ case MMCO_LONG2UNUSED:
+ pPic = WelsDelLongFromListSetUnref (pRefPic, uiLongTermPicNum);
+ if (pPic == NULL) {
+ WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "MMCO_LONG2UNUSED: delete an empty entry from long term list");
+ }
+ break;
+ case MMCO_SHORT2LONG:
+ if (iLongTermFrameIdx > pRefPic->iMaxLongTermFrameIdx) {
+ return ERR_INFO_INVALID_MMCO_LONG_TERM_IDX_EXCEED_MAX;
+ }
+ pPic = WelsDelShortFromList (pRefPic, iShortFrameNum);
+ if (pPic == NULL) {
+ WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "MMCO_LONG2LONG: delete an empty entry from short term list");
+ break;
+ }
+ WelsDelLongFromListSetUnref (pRefPic, iLongTermFrameIdx);
+#ifdef LONG_TERM_REF
+ pCtx->bCurAuContainLtrMarkSeFlag = true;
+ pCtx->iFrameNumOfAuMarkedLtr = iShortFrameNum;
+ WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO, "ex_mark_avc():::MMCO_SHORT2LONG:::LTR marking....iFrameNum: %d",
+ pCtx->iFrameNumOfAuMarkedLtr);
+#endif
+
+ MarkAsLongTerm (pRefPic, iShortFrameNum, iLongTermFrameIdx, uiLongTermPicNum);
+ break;
+ case MMCO_SET_MAX_LONG:
+ pRefPic->iMaxLongTermFrameIdx = iMaxLongTermFrameIdx;
+ for (i = 0 ; i < pRefPic->uiLongRefCount[LIST_0]; i++) {
+ if (pRefPic->pLongRefList[LIST_0][i]->iLongTermFrameIdx > pRefPic->iMaxLongTermFrameIdx) {
+ WelsDelLongFromListSetUnref (pRefPic, pRefPic->pLongRefList[LIST_0][i]->iLongTermFrameIdx);
+ }
+ }
+ break;
+ case MMCO_RESET:
+ WelsResetRefPic (pCtx);
+ pCtx->bLastHasMmco5 = true;
+ break;
+ case MMCO_LONG:
+ if (iLongTermFrameIdx > pRefPic->iMaxLongTermFrameIdx) {
+ return ERR_INFO_INVALID_MMCO_LONG_TERM_IDX_EXCEED_MAX;
+ }
+ WelsDelLongFromListSetUnref (pRefPic, iLongTermFrameIdx);
+ if (pRefPic->uiLongRefCount[LIST_0] + pRefPic->uiShortRefCount[LIST_0] >= WELS_MAX (1, pCtx->pSps->iNumRefFrames)) {
+ return ERR_INFO_INVALID_MMCO_REF_NUM_OVERFLOW;
+ }
+#ifdef LONG_TERM_REF
+ pCtx->bCurAuContainLtrMarkSeFlag = true;
+ pCtx->iFrameNumOfAuMarkedLtr = pCtx->iFrameNum;
+ WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO, "ex_mark_avc():::MMCO_LONG:::LTR marking....iFrameNum: %d",
+ pCtx->iFrameNum);
+#endif
+ iRet = AddLongTermToList (pRefPic, pCtx->pDec, iLongTermFrameIdx, uiLongTermPicNum);
+ break;
+ default :
+ break;
+ }
+
+ return iRet;
+}
+
+static int32_t SlidingWindow (PWelsDecoderContext pCtx) {
+ PRefPic pRefPic = &pCtx->sRefPic;
+ PPicture pPic = NULL;
+ int32_t i = 0;
+
+ if (pCtx->sRefPic.uiShortRefCount[LIST_0] + pCtx->sRefPic.uiLongRefCount[LIST_0] >= pCtx->pSps->iNumRefFrames) {
+ if (pCtx->sRefPic.uiShortRefCount[LIST_0] == 0) {
+ WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "No reference picture in short term list when sliding window");
+ return ERR_INFO_INVALID_MMCO_REF_NUM_NOT_ENOUGH;
+ }
+ for (i = pRefPic->uiShortRefCount[LIST_0] - 1; i >= 0; i--) {
+ pPic = WelsDelShortFromList (pRefPic, pRefPic->pShortRefList[LIST_0][i]->iFrameNum);
+ if (pPic) {
+ SetUnRef (pPic);
+ break;
+ } else {
+ return ERR_INFO_INVALID_MMCO_REF_NUM_OVERFLOW;
+ }
+ }
+ }
+ return ERR_NONE;
+}
+
+static PPicture WelsDelShortFromList (PRefPic pRefPic, int32_t iFrameNum) {
+ int32_t i = 0;
+ int32_t iMoveSize = 0;
+ PPicture pPic = NULL;
+
+ for (i = 0; i < pRefPic->uiShortRefCount[LIST_0]; i++) {
+ if (pRefPic->pShortRefList[LIST_0][i]->iFrameNum == iFrameNum) {
+ iMoveSize = pRefPic->uiShortRefCount[LIST_0] - i - 1;
+ pRefPic->pShortRefList[LIST_0][i]->bUsedAsRef = false;
+ pPic = pRefPic->pShortRefList[LIST_0][i];
+ pRefPic->pShortRefList[LIST_0][i] = NULL;
+ if (iMoveSize > 0) {
+ memmove (&pRefPic->pShortRefList[LIST_0][i], &pRefPic->pShortRefList[LIST_0][i + 1],
+ iMoveSize * sizeof (PPicture)); //confirmed_safe_unsafe_usage
+ }
+ pRefPic->uiShortRefCount[LIST_0]--;
+ pRefPic->pShortRefList[LIST_0][pRefPic->uiShortRefCount[LIST_0]] = NULL;
+ break;
+ }
+ }
+
+ return pPic;
+}
+
+static PPicture WelsDelShortFromListSetUnref (PRefPic pRefPic, int32_t iFrameNum) {
+ PPicture pPic = WelsDelShortFromList (pRefPic, iFrameNum);
+ if (pPic) {
+ SetUnRef (pPic);
+ }
+ return pPic;
+}
+
+static PPicture WelsDelLongFromList (PRefPic pRefPic, uint32_t uiLongTermFrameIdx) {
+ PPicture pPic = NULL;
+ int32_t i = 0;
+ for (i = 0; i < pRefPic->uiLongRefCount[LIST_0]; i++) {
+ pPic = pRefPic->pLongRefList[LIST_0][i];
+ if (pPic->iLongTermFrameIdx == (int32_t)uiLongTermFrameIdx) {
+ int32_t iMoveSize = pRefPic->uiLongRefCount[LIST_0] - i - 1;
+ pPic->bUsedAsRef = false;
+ pPic->bIsLongRef = false;
+ if (iMoveSize > 0) {
+ memmove (&pRefPic->pLongRefList[LIST_0][i], &pRefPic->pLongRefList[LIST_0][i + 1],
+ iMoveSize * sizeof (PPicture)); //confirmed_safe_unsafe_usage
+ }
+ pRefPic->uiLongRefCount[LIST_0]--;
+ pRefPic->pLongRefList[LIST_0][pRefPic->uiLongRefCount[LIST_0]] = NULL;
+ return pPic;
+ }
+ }
+ return NULL;
+}
+
+static PPicture WelsDelLongFromListSetUnref (PRefPic pRefPic, uint32_t uiLongTermFrameIdx) {
+ PPicture pPic = WelsDelLongFromList (pRefPic, uiLongTermFrameIdx);
+ if (pPic) {
+ SetUnRef (pPic);
+ }
+ return pPic;
+}
+
+static int32_t AddShortTermToList (PRefPic pRefPic, PPicture pPic) {
+ pPic->bUsedAsRef = true;
+ pPic->bIsLongRef = false;
+ pPic->iLongTermFrameIdx = -1;
+ if (pRefPic->uiShortRefCount[LIST_0] > 0) {
+ // Check the duplicate frame_num in short ref list
+ for (int32_t iPos = 0; iPos < pRefPic->uiShortRefCount[LIST_0]; iPos++) {
+ if (pPic->iFrameNum == pRefPic->pShortRefList[LIST_0][iPos]->iFrameNum) {
+ // Replace the previous ref pic with the new one with the same frame_num
+ pRefPic->pShortRefList[LIST_0][iPos] = pPic;
+ return ERR_INFO_DUPLICATE_FRAME_NUM;
+ }
+ }
+
+ memmove (&pRefPic->pShortRefList[LIST_0][1], &pRefPic->pShortRefList[LIST_0][0],
+ pRefPic->uiShortRefCount[LIST_0]*sizeof (PPicture));//confirmed_safe_unsafe_usage
+ }
+ pRefPic->pShortRefList[LIST_0][0] = pPic;
+ pRefPic->uiShortRefCount[LIST_0]++;
+ return ERR_NONE;
+}
+
+static int32_t AddLongTermToList (PRefPic pRefPic, PPicture pPic, int32_t iLongTermFrameIdx,
+ uint32_t uiLongTermPicNum) {
+ int32_t i = 0;
+
+ pPic->bUsedAsRef = true;
+ pPic->bIsLongRef = true;
+ pPic->iLongTermFrameIdx = iLongTermFrameIdx;
+ pPic->uiLongTermPicNum = uiLongTermPicNum;
+ if (pRefPic->uiLongRefCount[LIST_0] == 0) {
+ pRefPic->pLongRefList[LIST_0][pRefPic->uiLongRefCount[LIST_0]] = pPic;
+ } else {
+ for (i = 0; i < pRefPic->uiLongRefCount[LIST_0]; i++) {
+ if (pRefPic->pLongRefList[LIST_0][i]->iLongTermFrameIdx > pPic->iLongTermFrameIdx) {
+ break;
+ }
+ }
+ memmove (&pRefPic->pLongRefList[LIST_0][i + 1], &pRefPic->pLongRefList[LIST_0][i],
+ (pRefPic->uiLongRefCount[LIST_0] - i)*sizeof (PPicture)); //confirmed_safe_unsafe_usage
+ pRefPic->pLongRefList[LIST_0][i] = pPic;
+ }
+
+ pRefPic->uiLongRefCount[LIST_0]++;
+ return ERR_NONE;
+}
+
+static int32_t MarkAsLongTerm (PRefPic pRefPic, int32_t iFrameNum, int32_t iLongTermFrameIdx,
+ uint32_t uiLongTermPicNum) {
+ PPicture pPic = NULL;
+ int32_t i = 0;
+ int32_t iRet = ERR_NONE;
+ WelsDelLongFromListSetUnref (pRefPic, iLongTermFrameIdx);
+
+ for (i = 0; i < pRefPic->uiRefCount[LIST_0]; i++) {
+ pPic = pRefPic->pRefList[LIST_0][i];
+ if (pPic->iFrameNum == iFrameNum && !pPic->bIsLongRef) {
+ iRet = AddLongTermToList (pRefPic, pPic, iLongTermFrameIdx, uiLongTermPicNum);
+ break;
+ }
+ }
+
+ return iRet;
+}
+
+#ifdef LONG_TERM_REF
+int32_t GetLTRFrameIndex (PRefPic pRefPic, int32_t iAncLTRFrameNum) {
+ int32_t iLTRFrameIndex = -1;
+ PPicture pPic;
+ for (int i = 0; i < pRefPic->uiLongRefCount[0]; ++i) {
+ pPic = pRefPic->pLongRefList[LIST_0][i];
+ if (pPic->iFrameNum == iAncLTRFrameNum) {
+ return (pPic->iLongTermFrameIdx);
+ }
+ }
+ return iLTRFrameIndex;
+}
+#endif
+
+static int32_t RemainOneBufferInDpbForEC (PWelsDecoderContext pCtx) {
+ int32_t iRet = ERR_NONE;
+ PRefPic pRefPic = &pCtx->sRefPic;
+ if (pRefPic->uiShortRefCount[0] + pRefPic->uiLongRefCount[0] < pCtx->pSps->iNumRefFrames)
+ return iRet;
+
+ if (pRefPic->uiShortRefCount[0] > 0) {
+ iRet = SlidingWindow (pCtx);
+ } else { //all LTR, remove the smallest long_term_frame_idx
+ int32_t iLongTermFrameIdx = 0;
+ int32_t iMaxLongTermFrameIdx = pRefPic->iMaxLongTermFrameIdx;
+#ifdef LONG_TERM_REF
+ int32_t iCurrLTRFrameIdx = GetLTRFrameIndex (pRefPic, pCtx->iFrameNumOfAuMarkedLtr);
+#endif
+ while ((pRefPic->uiLongRefCount[0] >= pCtx->pSps->iNumRefFrames) && (iLongTermFrameIdx <= iMaxLongTermFrameIdx)) {
+#ifdef LONG_TERM_REF
+ if (iLongTermFrameIdx == iCurrLTRFrameIdx) {
+ iLongTermFrameIdx++;
+ continue;
+ }
+#endif
+ WelsDelLongFromListSetUnref (pRefPic, iLongTermFrameIdx);
+ iLongTermFrameIdx++;
+ }
+ }
+ if (pRefPic->uiShortRefCount[0] + pRefPic->uiLongRefCount[0] >=
+ pCtx->pSps->iNumRefFrames) { //fail to remain one empty buffer in DPB
+ WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "RemainOneBufferInDpbForEC(): empty one DPB failed for EC!");
+ iRet = ERR_INFO_REF_COUNT_OVERFLOW;
+ }
+
+ return iRet;
+}
+
+} // namespace WelsDec
--- a/codec/decoder/core/src/parse_mb_syn_cabac.cpp
+++ b/codec/decoder/core/src/parse_mb_syn_cabac.cpp
@@ -1,1658 +1,1658 @@
-/*!
- * \copy
- * Copyright (c) 2013, Cisco Systems
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * parse_mb_syn_cabac.cpp: cabac parse for syntax elements
- */
-#include "parse_mb_syn_cabac.h"
-#include "decode_slice.h"
-#include "mv_pred.h"
-#include "error_code.h"
-#include <stdio.h>
-namespace WelsDec {
-#define IDX_UNUSED -1
-
-static const int16_t g_kMaxPos [] = {IDX_UNUSED, 15, 14, 15, 3, 14, 63, 3, 3, 14, 14};
-static const int16_t g_kMaxC2 [] = {IDX_UNUSED, 4, 4, 4, 3, 4, 4, 3, 3, 4, 4};
-static const int16_t g_kBlockCat2CtxOffsetCBF[] = {IDX_UNUSED, 0, 4, 8, 12, 16, 0, 12, 12, 16, 16};
-static const int16_t g_kBlockCat2CtxOffsetMap [] = {IDX_UNUSED, 0, 15, 29, 44, 47, 0, 44, 44, 47, 47};
-static const int16_t g_kBlockCat2CtxOffsetLast[] = {IDX_UNUSED, 0, 15, 29, 44, 47, 0, 44, 44, 47, 47};
-static const int16_t g_kBlockCat2CtxOffsetOne [] = {IDX_UNUSED, 0, 10, 20, 30, 39, 0, 30, 30, 39, 39};
-static const int16_t g_kBlockCat2CtxOffsetAbs [] = {IDX_UNUSED, 0, 10, 20, 30, 39, 0, 30, 30, 39, 39};
-
-const uint8_t g_kTopBlkInsideMb[24] = { //for index with z-order 0~23
- // 0 1 | 4 5 luma 8*8 block pNonZeroCount[16+8]
- 0, 0, 1, 1, // 2 3 | 6 7 0 | 1 0 1 2 3
- 0, 0, 1, 1, //--------------- --------- 4 5 6 7
- 1, 1, 1, 1, // 8 9 | 12 13 2 | 3 8 9 10 11
- 1, 1, 1, 1, // 10 11 | 14 15-----------------------------> 12 13 14 15
- 0, 0, 1, 1, //---------------- chroma 8*8 block 16 17 18 19
- 0, 0, 1, 1 // 16 17 | 20 21 0 1 20 21 22 23
- // 18 19 | 22 23
-};
-
-const uint8_t g_kLeftBlkInsideMb[24] = { //for index with z-order 0~23
- // 0 1 | 4 5 luma 8*8 block pNonZeroCount[16+8]
- 0, 1, 0, 1, // 2 3 | 6 7 0 | 1 0 1 2 3
- 1, 1, 1, 1, //--------------- --------- 4 5 6 7
- 0, 1, 0, 1, // 8 9 | 12 13 2 | 3 8 9 10 11
- 1, 1, 1, 1, // 10 11 | 14 15-----------------------------> 12 13 14 15
- 0, 1, 0, 1, //---------------- chroma 8*8 block 16 17 18 19
- 0, 1, 0, 1 // 16 17 | 20 21 0 1 20 21 22 23
- // 18 19 | 22 23
-};
-
-static uint32_t DecodeCabacIntraMbType (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, int ctx_base) {
- uint32_t uiCode;
- uint32_t uiMbType = 0;
-
- PWelsCabacDecEngine pCabacDecEngine = pCtx->pCabacDecEngine;
- PWelsCabacCtx pBinCtx = pCtx->pCabacCtx + ctx_base;
-
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx, uiCode));
- if (!uiCode) {
- return 0; /* I4x4 */
- }
-
- DecodeTerminateCabac (pCabacDecEngine, uiCode);
- if (uiCode) {
- return 25; /* PCM */
- }
- uiMbType = 1; /* I16x16 */
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 1, uiCode)); /* cbp_luma != 0 */
- uiMbType += 12 * uiCode;
-
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 2, uiCode));
- if (uiCode) {
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 2, uiCode));
- uiMbType += 4 + 4 * uiCode;
- }
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 3, uiCode));
- uiMbType += 2 * uiCode;
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 3, uiCode));
- uiMbType += 1 * uiCode;
- return uiMbType;
-}
-
-void UpdateP16x8RefIdxCabac (PDqLayer pCurDqLayer, int8_t pRefIndex[LIST_A][30], int32_t iPartIdx, const int8_t iRef,
- const int8_t iListIdx) {
- uint32_t iRef32Bit = (uint32_t) iRef;
- const int32_t iRef4Bytes = (iRef32Bit << 24) | (iRef32Bit << 16) | (iRef32Bit << 8) | iRef32Bit;
- int32_t iMbXy = pCurDqLayer->iMbXyIndex;
- const uint8_t iScan4Idx = g_kuiScan4[iPartIdx];
- const uint8_t iScan4Idx4 = 4 + iScan4Idx;
- const uint8_t iCacheIdx = g_kuiCache30ScanIdx[iPartIdx];
- const uint8_t iCacheIdx6 = 6 + iCacheIdx;
- //mb
- ST32 (&pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx ], iRef4Bytes);
- ST32 (&pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx4], iRef4Bytes);
- //cache
- ST32 (&pRefIndex[iListIdx][iCacheIdx ], iRef4Bytes);
- ST32 (&pRefIndex[iListIdx][iCacheIdx6], iRef4Bytes);
-}
-
-void UpdateP8x16RefIdxCabac (PDqLayer pCurDqLayer, int8_t pRefIndex[LIST_A][30], int32_t iPartIdx, const int8_t iRef,
- const int8_t iListIdx) {
- uint16_t iRef16Bit = (uint16_t) iRef;
- const int16_t iRef2Bytes = (iRef16Bit << 8) | iRef16Bit;
- int32_t i;
- int32_t iMbXy = pCurDqLayer->iMbXyIndex;
- for (i = 0; i < 2; i++, iPartIdx += 8) {
- const uint8_t iScan4Idx = g_kuiScan4[iPartIdx];
- const uint8_t iCacheIdx = g_kuiCache30ScanIdx[iPartIdx];
- const uint8_t iScan4Idx4 = 4 + iScan4Idx;
- const uint8_t iCacheIdx6 = 6 + iCacheIdx;
- //mb
- ST16 (&pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx ], iRef2Bytes);
- ST16 (&pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx4], iRef2Bytes);
- //cache
- ST16 (&pRefIndex[iListIdx][iCacheIdx ], iRef2Bytes);
- ST16 (&pRefIndex[iListIdx][iCacheIdx6], iRef2Bytes);
- }
-}
-
-void UpdateP8x8RefIdxCabac (PDqLayer pCurDqLayer, int8_t pRefIndex[LIST_A][30], int32_t iPartIdx, const int8_t iRef,
- const int8_t iListIdx) {
- int32_t iMbXy = pCurDqLayer->iMbXyIndex;
- const uint8_t iScan4Idx = g_kuiScan4[iPartIdx];
- pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx] = pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx + 1] =
- pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx + 4] = pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx + 5] = iRef;
-}
-
-void UpdateP8x8DirectCabac (PDqLayer pCurDqLayer, int32_t iPartIdx) {
- int32_t iMbXy = pCurDqLayer->iMbXyIndex;
- const uint8_t iScan4Idx = g_kuiScan4[iPartIdx];
- pCurDqLayer->pDirect[iMbXy][iScan4Idx] = pCurDqLayer->pDirect[iMbXy][iScan4Idx + 1] =
- pCurDqLayer->pDirect[iMbXy][iScan4Idx + 4] = pCurDqLayer->pDirect[iMbXy][iScan4Idx + 5] = 1;
-}
-
-void UpdateP16x16DirectCabac (PDqLayer pCurDqLayer) {
- int32_t i;
- int32_t iMbXy = pCurDqLayer->iMbXyIndex;
- const int16_t direct = (1 << 8) | 1;
- for (i = 0; i < 16; i += 4) {
- const uint8_t kuiScan4Idx = g_kuiScan4[i];
- const uint8_t kuiScan4IdxPlus4 = 4 + kuiScan4Idx;
- ST16 (&pCurDqLayer->pDirect[iMbXy][kuiScan4Idx], direct);
- ST16 (&pCurDqLayer->pDirect[iMbXy][kuiScan4IdxPlus4], direct);
- }
-}
-
-void UpdateP16x16MvdCabac (SDqLayer* pCurDqLayer, int16_t pMvd[2], const int8_t iListIdx) {
- int32_t pMvd32[2];
- ST32 (&pMvd32[0], LD32 (pMvd));
- ST32 (&pMvd32[1], LD32 (pMvd));
- int32_t i;
- int32_t iMbXy = pCurDqLayer->iMbXyIndex;
- for (i = 0; i < 16; i += 2) {
- ST64 (pCurDqLayer->pMvd[iListIdx][iMbXy][i], LD64 (pMvd32));
- }
-}
-
-void UpdateP16x8MvdCabac (SDqLayer* pCurDqLayer, int16_t pMvdCache[LIST_A][30][MV_A], int32_t iPartIdx, int16_t pMvd[2],
- const int8_t iListIdx) {
- int32_t pMvd32[2];
- ST32 (&pMvd32[0], LD32 (pMvd));
- ST32 (&pMvd32[1], LD32 (pMvd));
- int32_t i;
- int32_t iMbXy = pCurDqLayer->iMbXyIndex;
- for (i = 0; i < 2; i++, iPartIdx += 4) {
- const uint8_t iScan4Idx = g_kuiScan4[iPartIdx];
- const uint8_t iScan4Idx4 = 4 + iScan4Idx;
- const uint8_t iCacheIdx = g_kuiCache30ScanIdx[iPartIdx];
- const uint8_t iCacheIdx6 = 6 + iCacheIdx;
- //mb
- ST64 (pCurDqLayer->pMvd[iListIdx][iMbXy][ iScan4Idx ], LD64 (pMvd32));
- ST64 (pCurDqLayer->pMvd[iListIdx][iMbXy][ iScan4Idx4], LD64 (pMvd32));
- //cache
- ST64 (pMvdCache[iListIdx][ iCacheIdx ], LD64 (pMvd32));
- ST64 (pMvdCache[iListIdx][ iCacheIdx6], LD64 (pMvd32));
- }
-}
-
-void UpdateP8x16MvdCabac (SDqLayer* pCurDqLayer, int16_t pMvdCache[LIST_A][30][MV_A], int32_t iPartIdx, int16_t pMvd[2],
- const int8_t iListIdx) {
- int32_t pMvd32[2];
- ST32 (&pMvd32[0], LD32 (pMvd));
- ST32 (&pMvd32[1], LD32 (pMvd));
- int32_t i;
- int32_t iMbXy = pCurDqLayer->iMbXyIndex;
-
- for (i = 0; i < 2; i++, iPartIdx += 8) {
- const uint8_t iScan4Idx = g_kuiScan4[iPartIdx];
- const uint8_t iCacheIdx = g_kuiCache30ScanIdx[iPartIdx];
- const uint8_t iScan4Idx4 = 4 + iScan4Idx;
- const uint8_t iCacheIdx6 = 6 + iCacheIdx;
- //mb
- ST64 (pCurDqLayer->pMvd[iListIdx][iMbXy][ iScan4Idx ], LD64 (pMvd32));
- ST64 (pCurDqLayer->pMvd[iListIdx][iMbXy][ iScan4Idx4], LD64 (pMvd32));
- //cache
- ST64 (pMvdCache[iListIdx][ iCacheIdx ], LD64 (pMvd32));
- ST64 (pMvdCache[iListIdx][ iCacheIdx6], LD64 (pMvd32));
- }
-}
-
-int32_t ParseEndOfSliceCabac (PWelsDecoderContext pCtx, uint32_t& uiBinVal) {
- uiBinVal = 0;
- WELS_READ_VERIFY (DecodeTerminateCabac (pCtx->pCabacDecEngine, uiBinVal));
- return ERR_NONE;
-}
-
-int32_t ParseSkipFlagCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiSkip) {
- uiSkip = 0;
- int32_t iCtxInc = NEW_CTX_OFFSET_SKIP;
- iCtxInc += (pNeighAvail->iLeftAvail && !IS_SKIP (pNeighAvail->iLeftType)) + (pNeighAvail->iTopAvail
- && !IS_SKIP (pNeighAvail->iTopType));
- if (B_SLICE == pCtx->eSliceType)
- iCtxInc += 13;
- PWelsCabacCtx pBinCtx = (pCtx->pCabacCtx + iCtxInc);
- WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pBinCtx, uiSkip));
- return ERR_NONE;
-}
-
-
-int32_t ParseMBTypeISliceCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiBinVal) {
- uint32_t uiCode;
- int32_t iIdxA = 0, iIdxB = 0;
- int32_t iCtxInc;
- uiBinVal = 0;
- PWelsCabacDecEngine pCabacDecEngine = pCtx->pCabacDecEngine;
- PWelsCabacCtx pBinCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_MB_TYPE_I; //I mode in I slice
- iIdxA = (pNeighAvail->iLeftAvail) && (pNeighAvail->iLeftType != MB_TYPE_INTRA4x4
- && pNeighAvail->iLeftType != MB_TYPE_INTRA8x8);
- iIdxB = (pNeighAvail->iTopAvail) && (pNeighAvail->iTopType != MB_TYPE_INTRA4x4
- && pNeighAvail->iTopType != MB_TYPE_INTRA8x8);
- iCtxInc = iIdxA + iIdxB;
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + iCtxInc, uiCode));
- uiBinVal = uiCode;
- if (uiBinVal != 0) { //I16x16
- WELS_READ_VERIFY (DecodeTerminateCabac (pCabacDecEngine, uiCode));
- if (uiCode == 1)
- uiBinVal = 25; //I_PCM
- else {
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 3, uiCode));
- uiBinVal = 1 + uiCode * 12;
- //decoding of uiCbp:0,1,2
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 4, uiCode));
- if (uiCode != 0) {
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 5, uiCode));
- uiBinVal += 4;
- if (uiCode != 0)
- uiBinVal += 4;
- }
- //decoding of I pred-mode: 0,1,2,3
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 6, uiCode));
- uiBinVal += (uiCode << 1);
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 7, uiCode));
- uiBinVal += uiCode;
- }
- }
- //I4x4
- return ERR_NONE;
-}
-
-int32_t ParseMBTypePSliceCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiMbType) {
- uint32_t uiCode;
- uiMbType = 0;
- PWelsCabacDecEngine pCabacDecEngine = pCtx->pCabacDecEngine;
-
- PWelsCabacCtx pBinCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_SKIP;
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 3, uiCode));
- if (uiCode) {
- // Intra MB
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 6, uiCode));
- if (uiCode) { // Intra 16x16
- WELS_READ_VERIFY (DecodeTerminateCabac (pCabacDecEngine, uiCode));
- if (uiCode) {
- uiMbType = 30;
- return ERR_NONE;//MB_TYPE_INTRA_PCM;
- }
-
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 7, uiCode));
- uiMbType = 6 + uiCode * 12;
-
- //uiCbp: 0,1,2
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 8, uiCode));
- if (uiCode) {
- uiMbType += 4;
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 8, uiCode));
- if (uiCode)
- uiMbType += 4;
- }
-
- //IPredMode: 0,1,2,3
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 9, uiCode));
- uiMbType += (uiCode << 1);
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 9, uiCode));
- uiMbType += uiCode;
- } else
- // Intra 4x4
- uiMbType = 5;
- } else { // P MB
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 4, uiCode));
- if (uiCode) { //second bit
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 6, uiCode));
- if (uiCode)
- uiMbType = 1;
- else
- uiMbType = 2;
- } else {
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 5, uiCode));
- if (uiCode)
- uiMbType = 3;
- else
- uiMbType = 0;
- }
- }
- return ERR_NONE;
-}
-
-int32_t ParseMBTypeBSliceCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiMbType) {
- uint32_t uiCode;
- uiMbType = 0;
- int32_t iIdxA = 0, iIdxB = 0;
- int32_t iCtxInc;
-
- PWelsCabacDecEngine pCabacDecEngine = pCtx->pCabacDecEngine;
- PWelsCabacCtx pBinCtx = pCtx->pCabacCtx + 27; //B slice
-
- iIdxA = (pNeighAvail->iLeftAvail) && !IS_DIRECT (pNeighAvail->iLeftType);
- iIdxB = (pNeighAvail->iTopAvail) && !IS_DIRECT (pNeighAvail->iTopType);
-
- iCtxInc = iIdxA + iIdxB;
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + iCtxInc, uiCode));
- if (!uiCode)
- uiMbType = 0; // Bi_Direct
- else {
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 3, uiCode));
- if (!uiCode) {
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 5, uiCode));
- uiMbType = 1 + uiCode; // 16x16 L0L1
- } else {
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 4, uiCode));
- uiMbType = uiCode << 3;
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 5, uiCode));
- uiMbType |= uiCode << 2;
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 5, uiCode));
- uiMbType |= uiCode << 1;
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 5, uiCode));
- uiMbType |= uiCode;
- if (uiMbType < 8) {
- uiMbType += 3;
- return ERR_NONE;
- } else if (uiMbType == 13) {
- uiMbType = DecodeCabacIntraMbType (pCtx, pNeighAvail, 32) + 23;
- return ERR_NONE;
- } else if (uiMbType == 14) {
- uiMbType = 11; // Bi8x16
- return ERR_NONE;
- } else if (uiMbType == 15) {
- uiMbType = 22; // 8x8
- return ERR_NONE;
- }
- uiMbType <<= 1;
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 5, uiCode));
- uiMbType |= uiCode;
- uiMbType -= 4;
- }
- }
- return ERR_NONE;
-}
-
-int32_t ParseTransformSize8x8FlagCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail,
- bool& bTransformSize8x8Flag) {
- uint32_t uiCode;
- int32_t iIdxA, iIdxB;
- int32_t iCtxInc;
- PWelsCabacDecEngine pCabacDecEngine = pCtx->pCabacDecEngine;
- PWelsCabacCtx pBinCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_TS_8x8_FLAG;
- iIdxA = (pNeighAvail->iLeftAvail) && (pCtx->pCurDqLayer->pTransformSize8x8Flag[pCtx->pCurDqLayer->iMbXyIndex - 1]);
- iIdxB = (pNeighAvail->iTopAvail)
- && (pCtx->pCurDqLayer->pTransformSize8x8Flag[pCtx->pCurDqLayer->iMbXyIndex - pCtx->pCurDqLayer->iMbWidth]);
- iCtxInc = iIdxA + iIdxB;
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + iCtxInc, uiCode));
- bTransformSize8x8Flag = !!uiCode;
-
- return ERR_NONE;
-}
-
-int32_t ParseSubMBTypeCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiSubMbType) {
- uint32_t uiCode;
- PWelsCabacDecEngine pCabacDecEngine = pCtx->pCabacDecEngine;
- PWelsCabacCtx pBinCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_SUBMB_TYPE;
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx, uiCode));
- if (uiCode)
- uiSubMbType = 0;
- else {
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 1, uiCode));
- if (uiCode) {
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 2, uiCode));
- uiSubMbType = 3 - uiCode;
- } else {
- uiSubMbType = 1;
- }
- }
- return ERR_NONE;
-}
-
-int32_t ParseBSubMBTypeCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiSubMbType) {
- uint32_t uiCode;
- PWelsCabacDecEngine pCabacDecEngine = pCtx->pCabacDecEngine;
- PWelsCabacCtx pBinCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_B_SUBMB_TYPE;
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx, uiCode));
- if (!uiCode) {
- uiSubMbType = 0; /* B_Direct_8x8 */
- return ERR_NONE;
- }
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 1, uiCode));
- if (!uiCode) {
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 3, uiCode));
- uiSubMbType = 1 + uiCode; /* B_L0_8x8, B_L1_8x8 */
- return ERR_NONE;
- }
- uiSubMbType = 3;
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 2, uiCode));
- if (uiCode) {
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 3, uiCode));
- if (uiCode) {
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 3, uiCode));
- uiSubMbType = 11 + uiCode; /* B_L1_4x4, B_Bi_4x4 */
- return ERR_NONE;
- }
- uiSubMbType += 4;
- }
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 3, uiCode));
- uiSubMbType += 2 * uiCode;
- WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 3, uiCode));
- uiSubMbType += uiCode;
-
- return ERR_NONE;
-}
-
-int32_t ParseIntraPredModeLumaCabac (PWelsDecoderContext pCtx, int32_t& iBinVal) {
- uint32_t uiCode;
- iBinVal = 0;
- WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_IPR, uiCode));
- if (uiCode == 1)
- iBinVal = -1;
- else {
- WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_IPR + 1, uiCode));
- iBinVal |= uiCode;
- WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_IPR + 1, uiCode));
- iBinVal |= (uiCode << 1);
- WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_IPR + 1, uiCode));
- iBinVal |= (uiCode << 2);
- }
- return ERR_NONE;
-}
-
-int32_t ParseIntraPredModeChromaCabac (PWelsDecoderContext pCtx, uint8_t uiNeighAvail, int32_t& iBinVal) {
- uint32_t uiCode;
- int32_t iIdxA, iIdxB, iCtxInc;
- int8_t* pChromaPredMode = pCtx->pCurDqLayer->pChromaPredMode;
- uint32_t* pMbType = pCtx->pCurDqLayer->pMbType;
- int32_t iLeftAvail = uiNeighAvail & 0x04;
- int32_t iTopAvail = uiNeighAvail & 0x01;
-
- int32_t iMbXy = pCtx->pCurDqLayer->iMbXyIndex;
- int32_t iMbXyTop = iMbXy - pCtx->pCurDqLayer->iMbWidth;
- int32_t iMbXyLeft = iMbXy - 1;
-
- iBinVal = 0;
-
- iIdxB = iTopAvail && (pChromaPredMode[iMbXyTop] > 0 && pChromaPredMode[iMbXyTop] <= 3)
- && pMbType[iMbXyTop] != MB_TYPE_INTRA_PCM;
- iIdxA = iLeftAvail && (pChromaPredMode[iMbXyLeft] > 0 && pChromaPredMode[iMbXyLeft] <= 3)
- && pMbType[iMbXyLeft] != MB_TYPE_INTRA_PCM;
- iCtxInc = iIdxA + iIdxB;
- WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CIPR + iCtxInc, uiCode));
- iBinVal = uiCode;
- if (iBinVal != 0) {
- uint32_t iSym;
- WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CIPR + 3, iSym));
- if (iSym == 0) {
- iBinVal = (iSym + 1);
- return ERR_NONE;
- }
- iSym = 0;
- do {
- WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CIPR + 3, uiCode));
- ++iSym;
- } while ((uiCode != 0) && (iSym < 1));
-
- if ((uiCode != 0) && (iSym == 1))
- ++ iSym;
- iBinVal = (iSym + 1);
- return ERR_NONE;
- }
- return ERR_NONE;
-}
-
-int32_t ParseInterPMotionInfoCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
- int16_t pMotionVector[LIST_A][30][MV_A], int16_t pMvdCache[LIST_A][30][MV_A], int8_t pRefIndex[LIST_A][30]) {
- PSlice pSlice = &pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer;
- PSliceHeader pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader;
- PDqLayer pCurDqLayer = pCtx->pCurDqLayer;
- PPicture* ppRefPic = pCtx->sRefPic.pRefList[LIST_0];
- int32_t pRefCount[2];
- int32_t i, j;
- int32_t iMbXy = pCurDqLayer->iMbXyIndex;
- int16_t pMv[4] = {0};
- int16_t pMvd[4] = {0};
- int8_t iRef[2] = {0};
- int32_t iPartIdx;
- int16_t iMinVmv = pSliceHeader->pSps->pSLevelLimits->iMinVmv;
- int16_t iMaxVmv = pSliceHeader->pSps->pSLevelLimits->iMaxVmv;
- pRefCount[0] = pSliceHeader->uiRefCount[0];
- pRefCount[1] = pSliceHeader->uiRefCount[1];
-
- switch (pCurDqLayer->pMbType[iMbXy]) {
- case MB_TYPE_16x16: {
- iPartIdx = 0;
- WELS_READ_VERIFY (ParseRefIdxCabac (pCtx, pNeighAvail, pNonZeroCount, pRefIndex, 0, LIST_0, iPartIdx, pRefCount[0], 0,
- iRef[0]));
- if ((iRef[0] < 0) || (iRef[0] >= pRefCount[0]) || (ppRefPic[iRef[0]] == NULL)) { //error ref_idx
- pCtx->bMbRefConcealed = true;
- if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) {
- iRef[0] = 0;
- pCtx->iErrorCode |= dsBitstreamError;
- } else {
- return GENERATE_ERROR_NO (ERR_LEVEL_MB_DATA, ERR_INFO_INVALID_REF_INDEX);
- }
- }
- pCtx->bMbRefConcealed = pCtx->bRPLRError || pCtx->bMbRefConcealed || ! (ppRefPic[iRef[0]]
- && ppRefPic[iRef[0]]->bIsComplete);
- PredMv (pMotionVector, pRefIndex, LIST_0, 0, 4, iRef[0], pMv);
- WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, LIST_0, 0, pMvd[0]));
- WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, LIST_0, 1, pMvd[1]));
- pMv[0] += pMvd[0];
- pMv[1] += pMvd[1];
- WELS_CHECK_SE_BOTH_WARNING (pMv[1], iMinVmv, iMaxVmv, "vertical mv");
- UpdateP16x16MotionInfo (pCurDqLayer, LIST_0, iRef[0], pMv);
- UpdateP16x16MvdCabac (pCurDqLayer, pMvd, LIST_0);
- }
- break;
- case MB_TYPE_16x8:
- for (i = 0; i < 2; i++) {
- iPartIdx = i << 3;
- WELS_READ_VERIFY (ParseRefIdxCabac (pCtx, pNeighAvail, pNonZeroCount, pRefIndex, 0, LIST_0, iPartIdx, pRefCount[0], 0,
- iRef[i]));
- if ((iRef[i] < 0) || (iRef[i] >= pRefCount[0]) || (ppRefPic[iRef[i]] == NULL)) { //error ref_idx
- pCtx->bMbRefConcealed = true;
- if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) {
- iRef[i] = 0;
- pCtx->iErrorCode |= dsBitstreamError;
- } else {
- return GENERATE_ERROR_NO (ERR_LEVEL_MB_DATA, ERR_INFO_INVALID_REF_INDEX);
- }
- }
- pCtx->bMbRefConcealed = pCtx->bRPLRError || pCtx->bMbRefConcealed || ! (ppRefPic[iRef[i]]
- && ppRefPic[iRef[i]]->bIsComplete);
- UpdateP16x8RefIdxCabac (pCurDqLayer, pRefIndex, iPartIdx, iRef[i], LIST_0);
- }
- for (i = 0; i < 2; i++) {
- iPartIdx = i << 3;
- PredInter16x8Mv (pMotionVector, pRefIndex, LIST_0, iPartIdx, iRef[i], pMv);
- WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, LIST_0, 0, pMvd[0]));
- WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, LIST_0, 1, pMvd[1]));
- pMv[0] += pMvd[0];
- pMv[1] += pMvd[1];
- WELS_CHECK_SE_BOTH_WARNING (pMv[1], iMinVmv, iMaxVmv, "vertical mv");
- UpdateP16x8MotionInfo (pCurDqLayer, pMotionVector, pRefIndex, LIST_0, iPartIdx, iRef[i], pMv);
- UpdateP16x8MvdCabac (pCurDqLayer, pMvdCache, iPartIdx, pMvd, LIST_0);
- }
- break;
- case MB_TYPE_8x16:
- for (i = 0; i < 2; i++) {
- iPartIdx = i << 2;
- WELS_READ_VERIFY (ParseRefIdxCabac (pCtx, pNeighAvail, pNonZeroCount, pRefIndex, 0, LIST_0, iPartIdx, pRefCount[0], 0,
- iRef[i]));
- if ((iRef[i] < 0) || (iRef[i] >= pRefCount[0]) || (ppRefPic[iRef[i]] == NULL)) { //error ref_idx
- pCtx->bMbRefConcealed = true;
- if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) {
- iRef[i] = 0;
- pCtx->iErrorCode |= dsBitstreamError;
- } else {
- return GENERATE_ERROR_NO (ERR_LEVEL_MB_DATA, ERR_INFO_INVALID_REF_INDEX);
- }
- }
- pCtx->bMbRefConcealed = pCtx->bRPLRError || pCtx->bMbRefConcealed || ! (ppRefPic[iRef[i]]
- && ppRefPic[iRef[i]]->bIsComplete);
- UpdateP8x16RefIdxCabac (pCurDqLayer, pRefIndex, iPartIdx, iRef[i], LIST_0);
- }
- for (i = 0; i < 2; i++) {
- iPartIdx = i << 2;
- PredInter8x16Mv (pMotionVector, pRefIndex, LIST_0, i << 2, iRef[i], pMv/*&mv[0], &mv[1]*/);
-
- WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, LIST_0, 0, pMvd[0]));
- WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, LIST_0, 1, pMvd[1]));
- pMv[0] += pMvd[0];
- pMv[1] += pMvd[1];
- WELS_CHECK_SE_BOTH_WARNING (pMv[1], iMinVmv, iMaxVmv, "vertical mv");
- UpdateP8x16MotionInfo (pCurDqLayer, pMotionVector, pRefIndex, LIST_0, iPartIdx, iRef[i], pMv);
- UpdateP8x16MvdCabac (pCurDqLayer, pMvdCache, iPartIdx, pMvd, LIST_0);
- }
- break;
- case MB_TYPE_8x8:
- case MB_TYPE_8x8_REF0: {
- int8_t pRefIdx[4] = {0}, pSubPartCount[4], pPartW[4];
- uint32_t uiSubMbType;
- //sub_mb_type, partition
- for (i = 0; i < 4; i++) {
- WELS_READ_VERIFY (ParseSubMBTypeCabac (pCtx, pNeighAvail, uiSubMbType));
- if (uiSubMbType >= 4) { //invalid sub_mb_type
- return GENERATE_ERROR_NO (ERR_LEVEL_MB_DATA, ERR_INFO_INVALID_SUB_MB_TYPE);
- }
- pCurDqLayer->pSubMbType[iMbXy][i] = g_ksInterPSubMbTypeInfo[uiSubMbType].iType;
- pSubPartCount[i] = g_ksInterPSubMbTypeInfo[uiSubMbType].iPartCount;
- pPartW[i] = g_ksInterPSubMbTypeInfo[uiSubMbType].iPartWidth;
-
- // Need modification when B picture add in, reference to 7.3.5
- pCurDqLayer->pNoSubMbPartSizeLessThan8x8Flag[iMbXy] &= (uiSubMbType == 0);
- }
-
- for (i = 0; i < 4; i++) {
- int16_t iIdx8 = i << 2;
- WELS_READ_VERIFY (ParseRefIdxCabac (pCtx, pNeighAvail, pNonZeroCount, pRefIndex, 0, LIST_0, iIdx8, pRefCount[0], 1,
- pRefIdx[i]));
- if ((pRefIdx[i] < 0) || (pRefIdx[i] >= pRefCount[0]) || (ppRefPic[pRefIdx[i]] == NULL)) { //error ref_idx
- pCtx->bMbRefConcealed = true;
- if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) {
- pRefIdx[i] = 0;
- pCtx->iErrorCode |= dsBitstreamError;
- } else {
- return GENERATE_ERROR_NO (ERR_LEVEL_MB_DATA, ERR_INFO_INVALID_REF_INDEX);
- }
- }
- pCtx->bMbRefConcealed = pCtx->bRPLRError || pCtx->bMbRefConcealed || ! (ppRefPic[pRefIdx[i]]
- && ppRefPic[pRefIdx[i]]->bIsComplete);
- UpdateP8x8RefIdxCabac (pCurDqLayer, pRefIndex, iIdx8, pRefIdx[i], LIST_0);
- }
- //mv
- for (i = 0; i < 4; i++) {
- int8_t iPartCount = pSubPartCount[i];
- uiSubMbType = pCurDqLayer->pSubMbType[iMbXy][i];
- int16_t iPartIdx, iBlockW = pPartW[i];
- uint8_t iScan4Idx, iCacheIdx;
- iCacheIdx = g_kuiCache30ScanIdx[i << 2];
- pRefIndex[0][iCacheIdx ] = pRefIndex[0][iCacheIdx + 1]
- = pRefIndex[0][iCacheIdx + 6] = pRefIndex[0][iCacheIdx + 7] = pRefIdx[i];
-
- for (j = 0; j < iPartCount; j++) {
- iPartIdx = (i << 2) + j * iBlockW;
- iScan4Idx = g_kuiScan4[iPartIdx];
- iCacheIdx = g_kuiCache30ScanIdx[iPartIdx];
- PredMv (pMotionVector, pRefIndex, LIST_0, iPartIdx, iBlockW, pRefIdx[i], pMv);
- WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, LIST_0, 0, pMvd[0]));
- WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, LIST_0, 1, pMvd[1]));
- pMv[0] += pMvd[0];
- pMv[1] += pMvd[1];
- WELS_CHECK_SE_BOTH_WARNING (pMv[1], iMinVmv, iMaxVmv, "vertical mv");
- if (SUB_MB_TYPE_8x8 == uiSubMbType) {
- ST32 ((pMv + 2), LD32 (pMv));
- ST32 ((pMvd + 2), LD32 (pMvd));
- ST64 (pCurDqLayer->pMv[0][iMbXy][iScan4Idx], LD64 (pMv));
- ST64 (pCurDqLayer->pMv[0][iMbXy][iScan4Idx + 4], LD64 (pMv));
- ST64 (pCurDqLayer->pMvd[0][iMbXy][iScan4Idx], LD64 (pMvd));
- ST64 (pCurDqLayer->pMvd[0][iMbXy][iScan4Idx + 4], LD64 (pMvd));
- ST64 (pMotionVector[0][iCacheIdx ], LD64 (pMv));
- ST64 (pMotionVector[0][iCacheIdx + 6], LD64 (pMv));
- ST64 (pMvdCache[0][iCacheIdx ], LD64 (pMvd));
- ST64 (pMvdCache[0][iCacheIdx + 6], LD64 (pMvd));
- } else if (SUB_MB_TYPE_8x4 == uiSubMbType) {
- ST32 ((pMv + 2), LD32 (pMv));
- ST32 ((pMvd + 2), LD32 (pMvd));
- ST64 (pCurDqLayer->pMv[0][iMbXy][iScan4Idx ], LD64 (pMv));
- ST64 (pCurDqLayer->pMvd[0][iMbXy][iScan4Idx ], LD64 (pMvd));
- ST64 (pMotionVector[0][iCacheIdx ], LD64 (pMv));
- ST64 (pMvdCache[0][iCacheIdx ], LD64 (pMvd));
- } else if (SUB_MB_TYPE_4x8 == uiSubMbType) {
- ST32 (pCurDqLayer->pMv[0][iMbXy][iScan4Idx ], LD32 (pMv));
- ST32 (pCurDqLayer->pMv[0][iMbXy][iScan4Idx + 4], LD32 (pMv));
- ST32 (pCurDqLayer->pMvd[0][iMbXy][iScan4Idx ], LD32 (pMvd));
- ST32 (pCurDqLayer->pMvd[0][iMbXy][iScan4Idx + 4], LD32 (pMvd));
- ST32 (pMotionVector[0][iCacheIdx ], LD32 (pMv));
- ST32 (pMotionVector[0][iCacheIdx + 6], LD32 (pMv));
- ST32 (pMvdCache[0][iCacheIdx ], LD32 (pMvd));
- ST32 (pMvdCache[0][iCacheIdx + 6], LD32 (pMvd));
- } else { //SUB_MB_TYPE_4x4
- ST32 (pCurDqLayer->pMv[0][iMbXy][iScan4Idx ], LD32 (pMv));
- ST32 (pCurDqLayer->pMvd[0][iMbXy][iScan4Idx ], LD32 (pMvd));
- ST32 (pMotionVector[0][iCacheIdx ], LD32 (pMv));
- ST32 (pMvdCache[0][iCacheIdx ], LD32 (pMvd));
- }
- }
- }
- }
- break;
- default:
- break;
- }
- return ERR_NONE;
-}
-
-int32_t ParseInterBMotionInfoCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
- int16_t pMotionVector[LIST_A][30][MV_A], int16_t pMvdCache[LIST_A][30][MV_A], int8_t pRefIndex[LIST_A][30],
- int8_t pDirect[30]) {
- PSlice pSlice = &pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer;
- PSliceHeader pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader;
- PDqLayer pCurDqLayer = pCtx->pCurDqLayer;
- int32_t pRefCount[LIST_A];
- int32_t iMbXy = pCurDqLayer->iMbXyIndex;
- int16_t pMv[4] = { 0 };
- int16_t pMvd[4] = { 0 };
- int8_t iRef[LIST_A] = { 0 };
- int32_t iPartIdx;
- int16_t iMinVmv = pSliceHeader->pSps->pSLevelLimits->iMinVmv;
- int16_t iMaxVmv = pSliceHeader->pSps->pSLevelLimits->iMaxVmv;
- pRefCount[0] = pSliceHeader->uiRefCount[0];
- pRefCount[1] = pSliceHeader->uiRefCount[1];
-
- MbType mbType = pCurDqLayer->pMbType[iMbXy];
-
- if (IS_DIRECT (mbType)) {
-
- int16_t pMvDirect[LIST_A][2] = { { 0, 0 }, { 0, 0 } };
- if (pSliceHeader->iDirectSpatialMvPredFlag) {
- //predict direct spatial mv
- PredMvBDirectSpatial (pCtx, pMvDirect, iRef);
- } else {
- //temporal direct 16x16 mode
- ComputeColocated (pCtx);
- PredBDirectTemporal (pCtx, pMvDirect, iRef);
- }
- } else if (IS_INTER_16x16 (mbType)) {
- iPartIdx = 0;
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- iRef[listIdx] = REF_NOT_IN_LIST;
- if (IS_DIR (mbType, 0, listIdx)) {
- WELS_READ_VERIFY (ParseRefIdxCabac (pCtx, pNeighAvail, pNonZeroCount, pRefIndex, pDirect, listIdx, iPartIdx,
- pRefCount[listIdx], 0,
- iRef[listIdx]));
- if ((iRef[listIdx] < 0) || (iRef[listIdx] >= pRefCount[listIdx])
- || (pCtx->sRefPic.pRefList[listIdx][iRef[listIdx]] == NULL)) { //error ref_idx
- pCtx->bMbRefConcealed = true;
- if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) {
- iRef[listIdx] = 0;
- pCtx->iErrorCode |= dsBitstreamError;
- } else {
- return GENERATE_ERROR_NO (ERR_LEVEL_MB_DATA, ERR_INFO_INVALID_REF_INDEX);
- }
- }
- pCtx->bMbRefConcealed = pCtx->bRPLRError || pCtx->bMbRefConcealed || ! (pCtx->sRefPic.pRefList[listIdx][iRef[listIdx]]
- && pCtx->sRefPic.pRefList[listIdx][iRef[listIdx]]->bIsComplete);
- }
- }
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- if (IS_DIR (mbType, 0, listIdx)) {
- PredMv (pMotionVector, pRefIndex, listIdx, 0, 4, iRef[listIdx], pMv);
- WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, listIdx, 0, pMvd[0]));
- WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, listIdx, 1, pMvd[1]));
- pMv[0] += pMvd[0];
- pMv[1] += pMvd[1];
- WELS_CHECK_SE_BOTH_WARNING (pMv[1], iMinVmv, iMaxVmv, "vertical mv");
- } else {
- * (uint32_t*)pMv = * (uint32_t*)pMvd = 0;
- }
- UpdateP16x16MotionInfo (pCurDqLayer, listIdx, iRef[listIdx], pMv);
- UpdateP16x16MvdCabac (pCurDqLayer, pMvd, listIdx);
- }
- } else if (IS_INTER_16x8 (mbType)) {
- int8_t ref_idx_list[LIST_A][2] = { {REF_NOT_IN_LIST, REF_NOT_IN_LIST}, { REF_NOT_IN_LIST, REF_NOT_IN_LIST } };
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- for (int32_t i = 0; i < 2; ++i) {
- iPartIdx = i << 3;
- int8_t ref_idx = REF_NOT_IN_LIST;
- if (IS_DIR (mbType, i, listIdx)) {
- WELS_READ_VERIFY (ParseRefIdxCabac (pCtx, pNeighAvail, pNonZeroCount, pRefIndex, pDirect, listIdx, iPartIdx,
- pRefCount[listIdx], 0, ref_idx));
- if ((ref_idx < 0) || (ref_idx >= pRefCount[listIdx])
- || (pCtx->sRefPic.pRefList[listIdx][ref_idx] == NULL)) { //error ref_idx
- pCtx->bMbRefConcealed = true;
- if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) {
- ref_idx = 0;
- pCtx->iErrorCode |= dsBitstreamError;
- } else {
- return GENERATE_ERROR_NO (ERR_LEVEL_MB_DATA, ERR_INFO_INVALID_REF_INDEX);
- }
- }
- pCtx->bMbRefConcealed = pCtx->bRPLRError || pCtx->bMbRefConcealed || ! (pCtx->sRefPic.pRefList[listIdx][ref_idx]
- && pCtx->sRefPic.pRefList[listIdx][ref_idx]->bIsComplete);
- }
- UpdateP16x8RefIdxCabac (pCurDqLayer, pRefIndex, iPartIdx, ref_idx, listIdx);
- ref_idx_list[listIdx][i] = ref_idx;
- }
- }
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- for (int32_t i = 0; i < 2; ++i) {
- iPartIdx = i << 3;
- int8_t ref_idx = ref_idx_list[listIdx][i];
- if (IS_DIR (mbType, i, listIdx)) {
- PredInter16x8Mv (pMotionVector, pRefIndex, listIdx, iPartIdx, ref_idx, pMv);
- WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, listIdx, 0, pMvd[0]));
- WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, listIdx, 1, pMvd[1]));
- pMv[0] += pMvd[0];
- pMv[1] += pMvd[1];
- WELS_CHECK_SE_BOTH_WARNING (pMv[1], iMinVmv, iMaxVmv, "vertical mv");
- } else {
- * (uint32_t*)pMv = * (uint32_t*)pMvd = 0;
- }
- UpdateP16x8MotionInfo (pCurDqLayer, pMotionVector, pRefIndex, listIdx, iPartIdx, ref_idx, pMv);
- UpdateP16x8MvdCabac (pCurDqLayer, pMvdCache, iPartIdx, pMvd, listIdx);
- }
- }
- } else if (IS_INTER_8x16 (mbType)) {
- int8_t ref_idx_list[LIST_A][2] = { { REF_NOT_IN_LIST, REF_NOT_IN_LIST }, { REF_NOT_IN_LIST, REF_NOT_IN_LIST } };
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- for (int32_t i = 0; i < 2; ++i) {
- iPartIdx = i << 2;
- int8_t ref_idx = REF_NOT_IN_LIST;
- if (IS_DIR (mbType, i, listIdx)) {
- WELS_READ_VERIFY (ParseRefIdxCabac (pCtx, pNeighAvail, pNonZeroCount, pRefIndex, pDirect, listIdx, iPartIdx,
- pRefCount[listIdx], 0, ref_idx));
- if ((ref_idx < 0) || (ref_idx >= pRefCount[listIdx])
- || (pCtx->sRefPic.pRefList[listIdx][ref_idx] == NULL)) { //error ref_idx
- pCtx->bMbRefConcealed = true;
- if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) {
- ref_idx = 0;
- pCtx->iErrorCode |= dsBitstreamError;
- } else {
- return GENERATE_ERROR_NO (ERR_LEVEL_MB_DATA, ERR_INFO_INVALID_REF_INDEX);
- }
- }
- pCtx->bMbRefConcealed = pCtx->bRPLRError || pCtx->bMbRefConcealed || ! (pCtx->sRefPic.pRefList[listIdx][ref_idx]
- && pCtx->sRefPic.pRefList[listIdx][ref_idx]->bIsComplete);
- }
- UpdateP8x16RefIdxCabac (pCurDqLayer, pRefIndex, iPartIdx, ref_idx, listIdx);
- ref_idx_list[listIdx][i] = ref_idx;
- }
- }
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- for (int32_t i = 0; i < 2; ++i) {
- iPartIdx = i << 2;
- int8_t ref_idx = ref_idx_list[listIdx][i];
- if (IS_DIR (mbType, i, listIdx)) {
- PredInter8x16Mv (pMotionVector, pRefIndex, listIdx, iPartIdx, ref_idx, pMv);
- WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, listIdx, 0, pMvd[0]));
- WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, listIdx, 1, pMvd[1]));
- pMv[0] += pMvd[0];
- pMv[1] += pMvd[1];
- WELS_CHECK_SE_BOTH_WARNING (pMv[1], iMinVmv, iMaxVmv, "vertical mv");
- } else {
- * (uint32_t*)pMv = * (uint32_t*)pMvd = 0;
- }
- UpdateP8x16MotionInfo (pCurDqLayer, pMotionVector, pRefIndex, listIdx, iPartIdx, ref_idx, pMv);
- UpdateP8x16MvdCabac (pCurDqLayer, pMvdCache, iPartIdx, pMvd, listIdx);
- }
- }
- } else if (IS_Inter_8x8 (mbType)) {
- int8_t pSubPartCount[4], pPartW[4];
- uint32_t uiSubMbType;
- //sub_mb_type, partition
- int16_t pMvDirect[LIST_A][2] = { {0, 0}, {0, 0} };
- bool has_direct_called = false;
- SubMbType directSubMbType = 0;
- for (int32_t i = 0; i < 4; i++) {
- WELS_READ_VERIFY (ParseBSubMBTypeCabac (pCtx, pNeighAvail, uiSubMbType));
- if (uiSubMbType > 13) { //invalid sub_mb_type
- return GENERATE_ERROR_NO (ERR_LEVEL_MB_DATA, ERR_INFO_INVALID_SUB_MB_TYPE);
- }
-// pCurDqLayer->pSubMbType[iMbXy][i] = g_ksInterBSubMbTypeInfo[uiSubMbType].iType;
- pSubPartCount[i] = g_ksInterBSubMbTypeInfo[uiSubMbType].iPartCount;
- pPartW[i] = g_ksInterBSubMbTypeInfo[uiSubMbType].iPartWidth;
-
- // Need modification when B picture add in, reference to 7.3.5
- if (pSubPartCount[i] > 1)
- pCurDqLayer->pNoSubMbPartSizeLessThan8x8Flag[iMbXy] = false;
-
- if (IS_DIRECT (g_ksInterBSubMbTypeInfo[uiSubMbType].iType)) {
- if (!has_direct_called) {
- if (pSliceHeader->iDirectSpatialMvPredFlag) {
- directSubMbType = PredMvBDirectSpatial (pCtx, pMvDirect, iRef);
- } else {
- //temporal direct mode
- ComputeColocated (pCtx);
- PredBDirectTemporal (pCtx, pMvDirect, iRef);
- }
- has_direct_called = true;
- }
- pCurDqLayer->pSubMbType[iMbXy][i] = directSubMbType;
- if (IS_SUB_4x4 (pCurDqLayer->pSubMbType[iMbXy][i])) {
- pSubPartCount[i] = 4;
- pPartW[i] = 1;
- }
- } else {
- pCurDqLayer->pSubMbType[iMbXy][i] = g_ksInterBSubMbTypeInfo[uiSubMbType].iType;
- }
- }
- for (int32_t i = 0; i < 4; i++) { //Direct 8x8 Ref and mv
-
- int16_t iIdx8 = i << 2;
- if (IS_DIRECT (pCurDqLayer->pSubMbType[iMbXy][i])) {
-
- int8_t iPartCount = pSubPartCount[i];
- int16_t iPartIdx, iBlockW = pPartW[i];
- uint8_t iScan4Idx, iCacheIdx, iColocIdx;
- iCacheIdx = g_kuiCache30ScanIdx[iIdx8];
-
- if (!pSliceHeader->iDirectSpatialMvPredFlag) {
- iRef[LIST_1] = 0;
- if (pCurDqLayer->iColocIntra[g_kuiScan4[iIdx8]]) {
- iRef[LIST_0] = 0;
- } else {
- if (pCurDqLayer->iColocRefIndex[LIST_0][iIdx8] >= 0) {
- iRef[LIST_0] = pCurDqLayer->iColocRefIndex[LIST_0][iIdx8];
- } else {
- iRef[LIST_0] = pCurDqLayer->iColocRefIndex[LIST_1][iIdx8];
- }
- }
- }
- for (int32_t j = 0; j < iPartCount; j++) {
- iPartIdx = iIdx8 + j * iBlockW;
- iColocIdx = g_kuiScan4[iPartIdx];
- iScan4Idx = g_kuiScan4[iPartIdx];
- iCacheIdx = g_kuiCache30ScanIdx[iPartIdx];
-
- if (pSliceHeader->iDirectSpatialMvPredFlag) {
- int16_t pMV[4] = { 0 };
- if (IS_SUB_8x8 (pCurDqLayer->pSubMbType[iMbXy][i])) {
- * (uint32_t*)pMV = * (uint32_t*)pMvDirect[LIST_0];
- ST32 ((pMV + 2), LD32 (pMV));
- ST64 (pCurDqLayer->pMv[LIST_0][iMbXy][iScan4Idx], LD64 (pMV));
- ST64 (pCurDqLayer->pMv[LIST_0][iMbXy][iScan4Idx + 4], LD64 (pMV));
- ST64 (pCurDqLayer->pMvd[LIST_0][iMbXy][iScan4Idx], 0);
- ST64 (pCurDqLayer->pMvd[LIST_0][iMbXy][iScan4Idx + 4], 0);
- ST64 (pMotionVector[LIST_0][iCacheIdx], LD64 (pMV));
- ST64 (pMotionVector[LIST_0][iCacheIdx + 6], LD64 (pMV));
- ST64 (pMvdCache[LIST_0][iCacheIdx], 0);
- ST64 (pMvdCache[LIST_0][iCacheIdx + 6], 0);
- * (uint32_t*)pMV = * (uint32_t*)pMvDirect[LIST_1];
- ST32 ((pMV + 2), LD32 (pMV));
- ST64 (pCurDqLayer->pMv[LIST_1][iMbXy][iScan4Idx], LD64 (pMV));
- ST64 (pCurDqLayer->pMv[LIST_1][iMbXy][iScan4Idx + 4], LD64 (pMV));
- ST64 (pCurDqLayer->pMvd[LIST_1][iMbXy][iScan4Idx], 0);
- ST64 (pCurDqLayer->pMvd[LIST_1][iMbXy][iScan4Idx + 4], 0);
- ST64 (pMotionVector[LIST_1][iCacheIdx], LD64 (pMV));
- ST64 (pMotionVector[LIST_1][iCacheIdx + 6], LD64 (pMV));
- ST64 (pMvdCache[LIST_1][iCacheIdx], 0);
- ST64 (pMvdCache[LIST_1][iCacheIdx + 6], 0);
- } else { //SUB_4x4
- * (uint32_t*)pMV = * (uint32_t*)pMvDirect[LIST_0];
- ST32 (pCurDqLayer->pMv[LIST_0][iMbXy][iScan4Idx], LD32 (pMV));
- ST32 (pCurDqLayer->pMvd[LIST_0][iMbXy][iScan4Idx], 0);
- ST32 (pMotionVector[LIST_0][iCacheIdx], LD32 (pMV));
- ST32 (pMvdCache[LIST_0][iCacheIdx], 0);
- * (uint32_t*)pMV = * (uint32_t*)pMvDirect[LIST_1];
- ST32 (pCurDqLayer->pMv[LIST_1][iMbXy][iScan4Idx], LD32 (pMV));
- ST32 (pCurDqLayer->pMvd[LIST_1][iMbXy][iScan4Idx], 0);
- ST32 (pMotionVector[LIST_1][iCacheIdx], LD32 (pMV));
- ST32 (pMvdCache[LIST_1][iCacheIdx], 0);
- }
-
- if ((* (int32_t*)pMvDirect[LIST_0] | * (int32_t*)pMvDirect[LIST_1])) {
- bool bIsLongRef = pCtx->sRefPic.pRefList[LIST_1][0]->bIsLongRef;
- uint32_t uiColZeroFlag = (0 == pCurDqLayer->iColocIntra[iColocIdx]) && !bIsLongRef &&
- (pCurDqLayer->iColocRefIndex[LIST_0][iColocIdx] == 0 || (pCurDqLayer->iColocRefIndex[LIST_0][iColocIdx] < 0
- && pCurDqLayer->iColocRefIndex[LIST_1][iColocIdx] == 0));
- const int16_t (*mvColoc)[2] = pCurDqLayer->iColocRefIndex[LIST_0][iColocIdx] == 0 ? pCurDqLayer->iColocMv[LIST_0] :
- pCurDqLayer->iColocMv[LIST_1];
- const int16_t* mv = mvColoc[iColocIdx];
- if (IS_SUB_8x8 (pCurDqLayer->pSubMbType[iMbXy][i])) {
- if (uiColZeroFlag && ((unsigned) (mv[0] + 1) <= 2 && (unsigned) (mv[1] + 1) <= 2)) {
- if (iRef[LIST_0] == 0) {
- ST64 (pCurDqLayer->pMv[LIST_0][iMbXy][iScan4Idx], 0);
- ST64 (pCurDqLayer->pMv[LIST_0][iMbXy][iScan4Idx + 4], 0);
- ST64 (pCurDqLayer->pMvd[LIST_0][iMbXy][iScan4Idx], 0);
- ST64 (pCurDqLayer->pMvd[LIST_0][iMbXy][iScan4Idx + 4], 0);
- ST64 (pMotionVector[LIST_0][iCacheIdx], 0);
- ST64 (pMotionVector[LIST_0][iCacheIdx + 6], 0);
- ST64 (pMvdCache[LIST_0][iCacheIdx], 0);
- ST64 (pMvdCache[LIST_0][iCacheIdx + 6], 0);
- }
-
- if (iRef[LIST_1] == 0) {
- ST64 (pCurDqLayer->pMv[LIST_1][iMbXy][iScan4Idx], 0);
- ST64 (pCurDqLayer->pMv[LIST_1][iMbXy][iScan4Idx + 4], 0);
- ST64 (pCurDqLayer->pMvd[LIST_1][iMbXy][iScan4Idx], 0);
- ST64 (pCurDqLayer->pMvd[LIST_1][iMbXy][iScan4Idx + 4], 0);
- ST64 (pMotionVector[LIST_1][iCacheIdx], 0);
- ST64 (pMotionVector[LIST_1][iCacheIdx + 6], 0);
- ST64 (pMvdCache[LIST_1][iCacheIdx], 0);
- ST64 (pMvdCache[LIST_1][iCacheIdx + 6], 0);
- }
- }
- } else {
- if (uiColZeroFlag && ((unsigned) (mv[0] + 1) <= 2 && (unsigned) (mv[1] + 1) <= 2)) {
- if (iRef[LIST_0] == 0) {
- ST32 (pCurDqLayer->pMv[LIST_0][iMbXy][iScan4Idx], 0);
- ST32 (pCurDqLayer->pMvd[LIST_0][iMbXy][iScan4Idx], 0);
- ST32 (pMotionVector[LIST_0][iCacheIdx], 0);
- ST32 (pMvdCache[LIST_0][iCacheIdx], 0);
- }
- if (iRef[LIST_1] == 0) {
- ST32 (pCurDqLayer->pMv[LIST_1][iMbXy][iScan4Idx], 0);
- ST32 (pCurDqLayer->pMvd[LIST_1][iMbXy][iScan4Idx], 0);
- ST32 (pMotionVector[LIST_1][iCacheIdx], 0);
- ST32 (pMvdCache[LIST_1][iCacheIdx], 0);
- }
- }
- }
- }
- } else {
- int16_t (*mvColoc)[2] = pCurDqLayer->iColocMv[LIST_0];
- int16_t* mv = mvColoc[iColocIdx];
- int16_t pMV[4] = { 0 };
- int16_t iMvp[LIST_A][2];
- if (IS_SUB_8x8 (pCurDqLayer->pSubMbType[iMbXy][i])) {
- iMvp[LIST_0][0] = (pSlice->iMvScale[LIST_0][iRef[LIST_0]] * mv[0] + 128) >> 8;
- iMvp[LIST_0][1] = (pSlice->iMvScale[LIST_0][iRef[LIST_0]] * mv[1] + 128) >> 8;
- ST32 (pMV, LD32 (iMvp[LIST_0]));
- ST32 ((pMV + 2), LD32 (iMvp[LIST_0]));
- ST64 (pCurDqLayer->pMv[LIST_0][iMbXy][iScan4Idx], LD64 (pMV));
- ST64 (pCurDqLayer->pMv[LIST_0][iMbXy][iScan4Idx + 4], LD64 (pMV));
- ST64 (pCurDqLayer->pMvd[LIST_0][iMbXy][iScan4Idx], 0);
- ST64 (pCurDqLayer->pMvd[LIST_0][iMbXy][iScan4Idx + 4], 0);
- iMvp[LIST_1][0] -= iMvp[LIST_0][0] - mv[0];
- iMvp[LIST_1][1] -= iMvp[LIST_0][0] - mv[1];
- ST32 (pMV, LD32 (iMvp[LIST_1]));
- ST32 ((pMV + 2), LD32 (iMvp[LIST_1]));
- ST64 (pCurDqLayer->pMv[LIST_1][iMbXy][iScan4Idx], LD64 (pMV));
- ST64 (pCurDqLayer->pMv[LIST_1][iMbXy][iScan4Idx + 4], LD64 (pMV));
- ST64 (pCurDqLayer->pMvd[LIST_1][iMbXy][iScan4Idx], 0);
- ST64 (pCurDqLayer->pMvd[LIST_1][iMbXy][iScan4Idx + 4], 0);
- } else { //SUB_4x4
- iMvp[LIST_0][0] = (pSlice->iMvScale[LIST_0][iRef[LIST_0]] * mv[0] + 128) >> 8;
- iMvp[LIST_0][1] = (pSlice->iMvScale[LIST_0][iRef[LIST_0]] * mv[1] + 128) >> 8;
- ST32 (pCurDqLayer->pMv[LIST_0][iMbXy][iScan4Idx], LD32 (iMvp[LIST_0]));
- ST32 (pCurDqLayer->pMvd[LIST_0][iMbXy][iScan4Idx], 0);
- iMvp[LIST_1][0] -= iMvp[LIST_0][0] - mv[0];
- iMvp[LIST_1][1] -= iMvp[LIST_0][0] - mv[1];
- ST32 (pCurDqLayer->pMv[LIST_1][iMbXy][iScan4Idx], LD32 (iMvp[LIST_1]));
- ST32 (pCurDqLayer->pMvd[LIST_1][iMbXy][iScan4Idx], 0);
- }
- }
- }
- }
- }
- //ref no-direct
- int8_t ref_idx_list[LIST_A][4] = { {REF_NOT_IN_LIST, REF_NOT_IN_LIST}, { REF_NOT_IN_LIST, REF_NOT_IN_LIST } };
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- for (int32_t i = 0; i < 4; i++) {
- int16_t iIdx8 = i << 2;
- int32_t subMbType = pCurDqLayer->pSubMbType[iMbXy][i];
- int8_t iref = REF_NOT_IN_LIST;
- if (IS_DIRECT (subMbType)) {
- if (pSliceHeader->iDirectSpatialMvPredFlag) {
- iref = iRef[listIdx];
- } else {
- iref = 0;
- if (listIdx == LIST_0) {
- if (!pCurDqLayer->iColocIntra[g_kuiScan4[iIdx8]]) {
- if (pCurDqLayer->iColocRefIndex[LIST_0][iIdx8] >= 0) {
- iref = pCurDqLayer->iColocRefIndex[LIST_0][iIdx8];
- } else {
- iref = pCurDqLayer->iColocRefIndex[LIST_1][iIdx8];
- }
- }
- }
- }
- UpdateP8x8DirectCabac (pCurDqLayer, iIdx8);
- } else {
- if (IS_DIR (subMbType, 0, listIdx)) {
- WELS_READ_VERIFY (ParseRefIdxCabac (pCtx, pNeighAvail, pNonZeroCount, pRefIndex, pDirect, listIdx, iIdx8,
- pRefCount[listIdx], 1,
- iref));
- if ((iref < 0) || (iref >= pRefCount[listIdx]) || (pCtx->sRefPic.pRefList[listIdx][iref] == NULL)) { //error ref_idx
- pCtx->bMbRefConcealed = true;
- if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) {
- iref = 0;
- pCtx->iErrorCode |= dsBitstreamError;
- } else {
- return GENERATE_ERROR_NO (ERR_LEVEL_MB_DATA, ERR_INFO_INVALID_REF_INDEX);
- }
- }
- pCtx->bMbRefConcealed = pCtx->bRPLRError || pCtx->bMbRefConcealed || ! (pCtx->sRefPic.pRefList[listIdx][iref]
- && pCtx->sRefPic.pRefList[listIdx][iref]->bIsComplete);
- }
- }
- UpdateP8x8RefIdxCabac (pCurDqLayer, pRefIndex, iIdx8, iref, listIdx);
- ref_idx_list[listIdx][i] = iref;
- }
- }
- //mv
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- for (int32_t i = 0; i < 4; i++) {
- int8_t iPartCount = pSubPartCount[i];
- int16_t iPartIdx, iBlockW = pPartW[i];
- uint8_t iScan4Idx, iCacheIdx;
-
- iCacheIdx = g_kuiCache30ScanIdx[i << 2];
-
- int8_t iref = ref_idx_list[listIdx][i];
- pRefIndex[listIdx][iCacheIdx] = pRefIndex[listIdx][iCacheIdx + 1]
- = pRefIndex[listIdx][iCacheIdx + 6] = pRefIndex[listIdx][iCacheIdx + 7] = iref;
-
- uint32_t subMbType = pCurDqLayer->pSubMbType[iMbXy][i];
- if (IS_DIRECT (subMbType)) {
- continue;
- }
- bool is_dir = IS_DIR (subMbType, 0, listIdx) > 0;
- for (int32_t j = 0; j < iPartCount; j++) {
- iPartIdx = (i << 2) + j * iBlockW;
- iScan4Idx = g_kuiScan4[iPartIdx];
- iCacheIdx = g_kuiCache30ScanIdx[iPartIdx];
- if (is_dir) {
- PredMv (pMotionVector, pRefIndex, listIdx, iPartIdx, iBlockW, iref, pMv);
- WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, listIdx, 0, pMvd[0]));
- WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, listIdx, 1, pMvd[1]));
- pMv[0] += pMvd[0];
- pMv[1] += pMvd[1];
- WELS_CHECK_SE_BOTH_WARNING (pMv[1], iMinVmv, iMaxVmv, "vertical mv");
- } else {
- * (uint32_t*)pMv = * (uint32_t*)pMvd = 0;
- }
- if (IS_SUB_8x8 (subMbType)) { //MB_TYPE_8x8
- ST32 ((pMv + 2), LD32 (pMv));
- ST32 ((pMvd + 2), LD32 (pMvd));
- ST64 (pCurDqLayer->pMv[listIdx][iMbXy][iScan4Idx], LD64 (pMv));
- ST64 (pCurDqLayer->pMv[listIdx][iMbXy][iScan4Idx + 4], LD64 (pMv));
- ST64 (pCurDqLayer->pMvd[listIdx][iMbXy][iScan4Idx], LD64 (pMvd));
- ST64 (pCurDqLayer->pMvd[listIdx][iMbXy][iScan4Idx + 4], LD64 (pMvd));
- ST64 (pMotionVector[listIdx][iCacheIdx], LD64 (pMv));
- ST64 (pMotionVector[listIdx][iCacheIdx + 6], LD64 (pMv));
- ST64 (pMvdCache[listIdx][iCacheIdx], LD64 (pMvd));
- ST64 (pMvdCache[listIdx][iCacheIdx + 6], LD64 (pMvd));
- } else if (IS_SUB_4x4 (subMbType)) { //MB_TYPE_4x4
- ST32 (pCurDqLayer->pMv[listIdx][iMbXy][iScan4Idx], LD32 (pMv));
- ST32 (pCurDqLayer->pMvd[listIdx][iMbXy][iScan4Idx], LD32 (pMvd));
- ST32 (pMotionVector[listIdx][iCacheIdx], LD32 (pMv));
- ST32 (pMvdCache[listIdx][iCacheIdx], LD32 (pMvd));
- } else if (IS_SUB_4x8 (subMbType)) { //MB_TYPE_4x8 5, 7, 9
- ST32 (pCurDqLayer->pMv[listIdx][iMbXy][iScan4Idx], LD32 (pMv));
- ST32 (pCurDqLayer->pMv[listIdx][iMbXy][iScan4Idx + 4], LD32 (pMv));
- ST32 (pCurDqLayer->pMvd[listIdx][iMbXy][iScan4Idx], LD32 (pMvd));
- ST32 (pCurDqLayer->pMvd[listIdx][iMbXy][iScan4Idx + 4], LD32 (pMvd));
- ST32 (pMotionVector[listIdx][iCacheIdx], LD32 (pMv));
- ST32 (pMotionVector[listIdx][iCacheIdx + 6], LD32 (pMv));
- ST32 (pMvdCache[listIdx][iCacheIdx], LD32 (pMvd));
- ST32 (pMvdCache[listIdx][iCacheIdx + 6], LD32 (pMvd));
- } else { //MB_TYPE_8x4 4, 6, 8
- ST32 ((pMv + 2), LD32 (pMv));
- ST32 ((pMvd + 2), LD32 (pMvd));
- ST64 (pCurDqLayer->pMv[listIdx][iMbXy][iScan4Idx], LD64 (pMv));
- ST64 (pCurDqLayer->pMvd[listIdx][iMbXy][iScan4Idx], LD64 (pMvd));
- ST64 (pMotionVector[listIdx][iCacheIdx], LD64 (pMv));
- ST64 (pMvdCache[listIdx][iCacheIdx], LD64 (pMvd));
- }
- }
- }
- }
- }
- return ERR_NONE;
-}
-
-int32_t ParseRefIdxCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint8_t* nzc,
- int8_t ref_idx[LIST_A][30], int8_t direct[30],
- int32_t iListIdx, int32_t iZOrderIdx, int32_t iActiveRefNum, int32_t b8mode, int8_t& iRefIdxVal) {
- if (iActiveRefNum == 1) {
- iRefIdxVal = 0;
- return ERR_NONE;
- }
- uint32_t uiCode;
- int32_t iIdxA = 0, iIdxB = 0;
- int32_t iCtxInc = 0;
- int8_t* pRefIdxInMB = pCtx->pCurDqLayer->pRefIndex[iListIdx][pCtx->pCurDqLayer->iMbXyIndex];
- int8_t* pDirect = pCtx->pCurDqLayer->pDirect[pCtx->pCurDqLayer->iMbXyIndex];
- if (iZOrderIdx == 0) {
- iIdxB = (pNeighAvail->iTopAvail && pNeighAvail->iTopType != MB_TYPE_INTRA_PCM
- && ref_idx[iListIdx][g_kuiCache30ScanIdx[iZOrderIdx] - 6] > 0);
- iIdxA = (pNeighAvail->iLeftAvail && pNeighAvail->iLeftType != MB_TYPE_INTRA_PCM
- && ref_idx[iListIdx][g_kuiCache30ScanIdx[iZOrderIdx] - 1] > 0);
- if (pCtx->eSliceType == B_SLICE) {
- if (iIdxB > 0 && direct[g_kuiCache30ScanIdx[iZOrderIdx] - 6] == 0) {
- iCtxInc += 2;
- }
- if (iIdxA > 0 && direct[g_kuiCache30ScanIdx[iZOrderIdx] - 1] == 0) {
- iCtxInc++;
- }
- }
- } else if (iZOrderIdx == 4) {
- iIdxB = (pNeighAvail->iTopAvail && pNeighAvail->iTopType != MB_TYPE_INTRA_PCM
- && ref_idx[iListIdx][g_kuiCache30ScanIdx[iZOrderIdx] - 6] > 0);
- iIdxA = pRefIdxInMB[g_kuiScan4[iZOrderIdx] - 1] > 0;
- if (pCtx->eSliceType == B_SLICE) {
- if (iIdxB > 0 && direct[g_kuiCache30ScanIdx[iZOrderIdx] - 6] == 0) {
- iCtxInc += 2;
- }
- if (iIdxA > 0 && pDirect[g_kuiScan4[iZOrderIdx] - 1] == 0) {
- iCtxInc ++;
- }
- }
- } else if (iZOrderIdx == 8) {
-
- iIdxB = pRefIdxInMB[g_kuiScan4[iZOrderIdx] - 4] > 0;
- iIdxA = (pNeighAvail->iLeftAvail && pNeighAvail->iLeftType != MB_TYPE_INTRA_PCM
- && ref_idx[iListIdx][g_kuiCache30ScanIdx[iZOrderIdx] - 1] > 0);
- if (pCtx->eSliceType == B_SLICE) {
- if (iIdxB > 0 && pDirect[g_kuiScan4[iZOrderIdx] - 4] == 0) {
- iCtxInc += 2;
- }
- if (iIdxA > 0 && direct[g_kuiCache30ScanIdx[iZOrderIdx] - 1] == 0) {
- iCtxInc++;
- }
- }
- } else {
- iIdxB = pRefIdxInMB[g_kuiScan4[iZOrderIdx] - 4] > 0;
- iIdxA = pRefIdxInMB[g_kuiScan4[iZOrderIdx] - 1] > 0;
- if (pCtx->eSliceType == B_SLICE) {
- if (iIdxB > 0 && pDirect[g_kuiScan4[iZOrderIdx] - 4] == 0) {
- iCtxInc += 2;
- }
- if (iIdxA > 0 && pDirect[g_kuiScan4[iZOrderIdx] - 1] == 0) {
- iCtxInc++;
- }
- }
- }
- if (pCtx->eSliceType != B_SLICE) {
- iCtxInc = iIdxA + (iIdxB << 1);
- }
-
- WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_REF_NO + iCtxInc, uiCode));
- if (uiCode) {
- WELS_READ_VERIFY (DecodeUnaryBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_REF_NO + 4, 1, uiCode));
- ++uiCode;
- }
- iRefIdxVal = (int8_t) uiCode;
- return ERR_NONE;
-}
-
-int32_t ParseMvdInfoCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, int8_t pRefIndex[LIST_A][30],
- int16_t pMvdCache[LIST_A][30][2], int32_t index, int8_t iListIdx, int8_t iMvComp, int16_t& iMvdVal) {
- uint32_t uiCode;
- int32_t iIdxA = 0;
- //int32_t sym;
- PWelsCabacCtx pBinCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_MVD + iMvComp * CTX_NUM_MVD;
- iMvdVal = 0;
-
- if (pRefIndex[iListIdx][g_kuiCache30ScanIdx[index] - 6] >= 0)
- iIdxA = WELS_ABS (pMvdCache[iListIdx][g_kuiCache30ScanIdx[index] - 6][iMvComp]);
- if (pRefIndex[iListIdx][g_kuiCache30ScanIdx[index] - 1] >= 0)
- iIdxA += WELS_ABS (pMvdCache[iListIdx][g_kuiCache30ScanIdx[index] - 1][iMvComp]);
-
- int32_t iCtxInc = 0;
- if (iIdxA >= 3)
- iCtxInc = 1 + (iIdxA > 32);
-
- WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pBinCtx + iCtxInc, uiCode));
- if (uiCode) {
- WELS_READ_VERIFY (DecodeUEGMvCabac (pCtx->pCabacDecEngine, pBinCtx + 3, 3, uiCode));
- iMvdVal = (int16_t) (uiCode + 1);
- WELS_READ_VERIFY (DecodeBypassCabac (pCtx->pCabacDecEngine, uiCode));
- if (uiCode) {
- iMvdVal = -iMvdVal;
- }
- } else {
- iMvdVal = 0;
- }
- return ERR_NONE;
-}
-
-int32_t ParseCbpInfoCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiCbp) {
- int32_t iIdxA = 0, iIdxB = 0, pALeftMb[2], pBTopMb[2];
- uiCbp = 0;
- uint32_t pCbpBit[6];
- int32_t iCtxInc;
-
- //Luma: bit by bit for 4 8x8 blocks in z-order
- pBTopMb[0] = pNeighAvail->iTopAvail && pNeighAvail->iTopType != MB_TYPE_INTRA_PCM
- && ((pNeighAvail->iTopCbp & (1 << 2)) == 0);
- pBTopMb[1] = pNeighAvail->iTopAvail && pNeighAvail->iTopType != MB_TYPE_INTRA_PCM
- && ((pNeighAvail->iTopCbp & (1 << 3)) == 0);
- pALeftMb[0] = pNeighAvail->iLeftAvail && pNeighAvail->iLeftType != MB_TYPE_INTRA_PCM
- && ((pNeighAvail->iLeftCbp & (1 << 1)) == 0);
- pALeftMb[1] = pNeighAvail->iLeftAvail && pNeighAvail->iLeftType != MB_TYPE_INTRA_PCM
- && ((pNeighAvail->iLeftCbp & (1 << 3)) == 0);
-
- //left_top 8x8 block
- iCtxInc = pALeftMb[0] + (pBTopMb[0] << 1);
- WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CBP + iCtxInc, pCbpBit[0]));
- if (pCbpBit[0])
- uiCbp += 0x01;
-
- //right_top 8x8 block
- iIdxA = !pCbpBit[0];
- iCtxInc = iIdxA + (pBTopMb[1] << 1);
- WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CBP + iCtxInc, pCbpBit[1]));
- if (pCbpBit[1])
- uiCbp += 0x02;
-
- //left_bottom 8x8 block
- iIdxB = !pCbpBit[0];
- iCtxInc = pALeftMb[1] + (iIdxB << 1);
- WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CBP + iCtxInc, pCbpBit[2]));
- if (pCbpBit[2])
- uiCbp += 0x04;
-
- //right_bottom 8x8 block
- iIdxB = !pCbpBit[1];
- iIdxA = !pCbpBit[2];
- iCtxInc = iIdxA + (iIdxB << 1);
- WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CBP + iCtxInc, pCbpBit[3]));
- if (pCbpBit[3])
- uiCbp += 0x08;
-
- if (pCtx->pSps->uiChromaFormatIdc == 0)//monochroma
- return ERR_NONE;
-
-
- //Chroma: bit by bit
- iIdxB = pNeighAvail->iTopAvail && (pNeighAvail->iTopType == MB_TYPE_INTRA_PCM || (pNeighAvail->iTopCbp >> 4));
- iIdxA = pNeighAvail->iLeftAvail && (pNeighAvail->iLeftType == MB_TYPE_INTRA_PCM || (pNeighAvail->iLeftCbp >> 4));
-
- //BitIdx = 0
- iCtxInc = iIdxA + (iIdxB << 1);
- WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CBP + CTX_NUM_CBP + iCtxInc,
- pCbpBit[4]));
-
- //BitIdx = 1
- if (pCbpBit[4]) {
- iIdxB = pNeighAvail->iTopAvail && (pNeighAvail->iTopType == MB_TYPE_INTRA_PCM || (pNeighAvail->iTopCbp >> 4) == 2);
- iIdxA = pNeighAvail->iLeftAvail && (pNeighAvail->iLeftType == MB_TYPE_INTRA_PCM || (pNeighAvail->iLeftCbp >> 4) == 2);
- iCtxInc = iIdxA + (iIdxB << 1);
- WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine,
- pCtx->pCabacCtx + NEW_CTX_OFFSET_CBP + 2 * CTX_NUM_CBP + iCtxInc,
- pCbpBit[5]));
- uiCbp += 1 << (4 + pCbpBit[5]);
-
- }
-
- return ERR_NONE;
-}
-
-int32_t ParseDeltaQpCabac (PWelsDecoderContext pCtx, int32_t& iQpDelta) {
- uint32_t uiCode;
- PSlice pCurrSlice = & (pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer);
- iQpDelta = 0;
- PWelsCabacCtx pBinCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_DELTA_QP;
- int32_t iCtxInc = (pCurrSlice->iLastDeltaQp != 0);
- WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pBinCtx + iCtxInc, uiCode));
- if (uiCode != 0) {
- WELS_READ_VERIFY (DecodeUnaryBinCabac (pCtx->pCabacDecEngine, pBinCtx + 2, 1, uiCode));
- uiCode++;
- iQpDelta = (uiCode + 1) >> 1;
- if ((uiCode & 1) == 0)
- iQpDelta = - iQpDelta;
- }
- pCurrSlice->iLastDeltaQp = iQpDelta;
- return ERR_NONE;
-}
-
-int32_t ParseCbfInfoCabac (PWelsNeighAvail pNeighAvail, uint8_t* pNzcCache, int32_t iZIndex, int32_t iResProperty,
- PWelsDecoderContext pCtx, uint32_t& uiCbfBit) {
- int8_t nA, nB/*, zigzag_idx = 0*/;
- int32_t iCurrBlkXy = pCtx->pCurDqLayer->iMbXyIndex;
- int32_t iTopBlkXy = iCurrBlkXy - pCtx->pCurDqLayer->iMbWidth; //default value: MB neighboring
- int32_t iLeftBlkXy = iCurrBlkXy - 1; //default value: MB neighboring
- uint16_t* pCbfDc = pCtx->pCurDqLayer->pCbfDc;
- uint32_t* pMbType = pCtx->pCurDqLayer->pMbType;
- int32_t iCtxInc;
- uiCbfBit = 0;
- nA = nB = (int8_t)!!IS_INTRA (pMbType[iCurrBlkXy]);
-
- if (iResProperty == I16_LUMA_DC || iResProperty == CHROMA_DC_U || iResProperty == CHROMA_DC_V) { //DC
- if (pNeighAvail->iTopAvail)
- nB = (pMbType[iTopBlkXy] == MB_TYPE_INTRA_PCM) || ((pCbfDc[iTopBlkXy] >> iResProperty) & 1);
- if (pNeighAvail->iLeftAvail)
- nA = (pMbType[iLeftBlkXy] == MB_TYPE_INTRA_PCM) || ((pCbfDc[iLeftBlkXy] >> iResProperty) & 1);
- iCtxInc = nA + (nB << 1);
- WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine,
- pCtx->pCabacCtx + NEW_CTX_OFFSET_CBF + g_kBlockCat2CtxOffsetCBF[iResProperty] + iCtxInc, uiCbfBit));
- if (uiCbfBit)
- pCbfDc[iCurrBlkXy] |= (1 << iResProperty);
- } else { //AC
- //for 4x4 blk, make sure blk-idx is correct
- if (pNzcCache[g_kCacheNzcScanIdx[iZIndex] - 8] != 0xff) { //top blk available
- if (g_kTopBlkInsideMb[iZIndex])
- iTopBlkXy = iCurrBlkXy;
- nB = pNzcCache[g_kCacheNzcScanIdx[iZIndex] - 8] || pMbType[iTopBlkXy] == MB_TYPE_INTRA_PCM;
- }
- if (pNzcCache[g_kCacheNzcScanIdx[iZIndex] - 1] != 0xff) { //left blk available
- if (g_kLeftBlkInsideMb[iZIndex])
- iLeftBlkXy = iCurrBlkXy;
- nA = pNzcCache[g_kCacheNzcScanIdx[iZIndex] - 1] || pMbType[iLeftBlkXy] == MB_TYPE_INTRA_PCM;
- }
-
- iCtxInc = nA + (nB << 1);
- WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine,
- pCtx->pCabacCtx + NEW_CTX_OFFSET_CBF + g_kBlockCat2CtxOffsetCBF[iResProperty] + iCtxInc, uiCbfBit));
- }
- return ERR_NONE;
-}
-
-int32_t ParseSignificantMapCabac (int32_t* pSignificantMap, int32_t iResProperty, PWelsDecoderContext pCtx,
- uint32_t& uiCoeffNum) {
- uint32_t uiCode;
-
- PWelsCabacCtx pMapCtx = pCtx->pCabacCtx + (iResProperty == LUMA_DC_AC_8 ? NEW_CTX_OFFSET_MAP_8x8 : NEW_CTX_OFFSET_MAP)
- + g_kBlockCat2CtxOffsetMap [iResProperty];
- PWelsCabacCtx pLastCtx = pCtx->pCabacCtx + (iResProperty == LUMA_DC_AC_8 ? NEW_CTX_OFFSET_LAST_8x8 :
- NEW_CTX_OFFSET_LAST) + g_kBlockCat2CtxOffsetLast[iResProperty];
-
-
- int32_t i;
- uiCoeffNum = 0;
- int32_t i0 = 0;
- int32_t i1 = g_kMaxPos[iResProperty];
-
- int32_t iCtx;
-
- for (i = i0; i < i1; ++i) {
- iCtx = (iResProperty == LUMA_DC_AC_8 ? g_kuiIdx2CtxSignificantCoeffFlag8x8[i] : i);
- //read significant
- WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pMapCtx + iCtx, uiCode));
- if (uiCode) {
- * (pSignificantMap++) = 1;
- ++ uiCoeffNum;
- //read last significant
- iCtx = (iResProperty == LUMA_DC_AC_8 ? g_kuiIdx2CtxLastSignificantCoeffFlag8x8[i] : i);
- WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pLastCtx + iCtx, uiCode));
- if (uiCode) {
- memset (pSignificantMap, 0, (i1 - i) * sizeof (int32_t));
- return ERR_NONE;
- }
- } else
- * (pSignificantMap++) = 0;
- }
-
- //deal with last pSignificantMap if no data
- //if(i < i1+1)
- {
- *pSignificantMap = 1;
- ++uiCoeffNum;
- }
-
- return ERR_NONE;
-}
-
-int32_t ParseSignificantCoeffCabac (int32_t* pSignificant, int32_t iResProperty, PWelsDecoderContext pCtx) {
- uint32_t uiCode;
- PWelsCabacCtx pOneCtx = pCtx->pCabacCtx + (iResProperty == LUMA_DC_AC_8 ? NEW_CTX_OFFSET_ONE_8x8 : NEW_CTX_OFFSET_ONE) +
- g_kBlockCat2CtxOffsetOne[iResProperty];
- PWelsCabacCtx pAbsCtx = pCtx->pCabacCtx + (iResProperty == LUMA_DC_AC_8 ? NEW_CTX_OFFSET_ABS_8x8 : NEW_CTX_OFFSET_ABS) +
- g_kBlockCat2CtxOffsetAbs[iResProperty];
-
- const int16_t iMaxType = g_kMaxC2[iResProperty];
- int32_t i = g_kMaxPos[iResProperty];
- int32_t* pCoff = pSignificant + i;
- int32_t c1 = 1;
- int32_t c2 = 0;
- for (; i >= 0; --i) {
- if (*pCoff != 0) {
- WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pOneCtx + c1, uiCode));
- *pCoff += uiCode;
- if (*pCoff == 2) {
- WELS_READ_VERIFY (DecodeUEGLevelCabac (pCtx->pCabacDecEngine, pAbsCtx + c2, uiCode));
- *pCoff += uiCode;
- ++c2;
- c2 = WELS_MIN (c2, iMaxType);
- c1 = 0;
- } else if (c1) {
- ++c1;
- c1 = WELS_MIN (c1, 4);
- }
- WELS_READ_VERIFY (DecodeBypassCabac (pCtx->pCabacDecEngine, uiCode));
- if (uiCode)
- *pCoff = - *pCoff;
- }
- pCoff--;
- }
- return ERR_NONE;
-}
-
-int32_t ParseResidualBlockCabac8x8 (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCountCache, SBitStringAux* pBsAux,
- int32_t iIndex, int32_t iMaxNumCoeff, const uint8_t* pScanTable, int32_t iResProperty,
- short* sTCoeff, /*int mb_mode*/ uint8_t uiQp, PWelsDecoderContext pCtx) {
- uint32_t uiTotalCoeffNum = 0;
- uint32_t uiCbpBit;
- int32_t pSignificantMap[64] = {0};
-
- int32_t iMbResProperty = 0;
- GetMbResProperty (&iMbResProperty, &iResProperty, false);
- const uint16_t* pDeQuantMul = (pCtx->bUseScalingList) ? pCtx->pDequant_coeff8x8[iMbResProperty - 6][uiQp] :
- g_kuiDequantCoeff8x8[uiQp];
-
- uiCbpBit = 1; // for 8x8, MaxNumCoeff == 64 && uiCbpBit == 1
- if (uiCbpBit) { //has coeff
- WELS_READ_VERIFY (ParseSignificantMapCabac (pSignificantMap, iResProperty, pCtx, uiTotalCoeffNum));
- WELS_READ_VERIFY (ParseSignificantCoeffCabac (pSignificantMap, iResProperty, pCtx));
- }
-
- pNonZeroCountCache[g_kCacheNzcScanIdx[iIndex]] =
- pNonZeroCountCache[g_kCacheNzcScanIdx[iIndex + 1]] =
- pNonZeroCountCache[g_kCacheNzcScanIdx[iIndex + 2]] =
- pNonZeroCountCache[g_kCacheNzcScanIdx[iIndex + 3]] = (uint8_t)uiTotalCoeffNum;
- if (uiTotalCoeffNum == 0) {
- return ERR_NONE;
- }
- int32_t j = 0, i;
- if (iResProperty == LUMA_DC_AC_8) {
- do {
- if (pSignificantMap[j] != 0) {
- i = pScanTable[ j ];
- sTCoeff[i] = uiQp >= 36 ? ((pSignificantMap[j] * pDeQuantMul[i]) * (1 << (uiQp / 6 - 6))) : ((
- pSignificantMap[j] * pDeQuantMul[i] + (1 << (5 - uiQp / 6))) >> (6 - uiQp / 6));
- }
- ++j;
- } while (j < 64);
- }
-
- return ERR_NONE;
-}
-
-int32_t ParseResidualBlockCabac (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCountCache, SBitStringAux* pBsAux,
- int32_t iIndex, int32_t iMaxNumCoeff,
- const uint8_t* pScanTable, int32_t iResProperty, short* sTCoeff, /*int mb_mode*/ uint8_t uiQp,
- PWelsDecoderContext pCtx) {
- int32_t iCurNzCacheIdx;
- uint32_t uiTotalCoeffNum = 0;
- uint32_t uiCbpBit;
- int32_t pSignificantMap[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-
- int32_t iMbResProperty = 0;
- GetMbResProperty (&iMbResProperty, &iResProperty, false);
- const uint16_t* pDeQuantMul = (pCtx->bUseScalingList) ? pCtx->pDequant_coeff4x4[iMbResProperty][uiQp] :
- g_kuiDequantCoeff[uiQp];
-
- WELS_READ_VERIFY (ParseCbfInfoCabac (pNeighAvail, pNonZeroCountCache, iIndex, iResProperty, pCtx, uiCbpBit));
- if (uiCbpBit) { //has coeff
- WELS_READ_VERIFY (ParseSignificantMapCabac (pSignificantMap, iResProperty, pCtx, uiTotalCoeffNum));
- WELS_READ_VERIFY (ParseSignificantCoeffCabac (pSignificantMap, iResProperty, pCtx));
- }
-
- iCurNzCacheIdx = g_kCacheNzcScanIdx[iIndex];
- pNonZeroCountCache[iCurNzCacheIdx] = (uint8_t)uiTotalCoeffNum;
- if (uiTotalCoeffNum == 0) {
- return ERR_NONE;
- }
- int32_t j = 0;
- if (iResProperty == I16_LUMA_DC) {
- do {
- sTCoeff[pScanTable[j]] = pSignificantMap[j];
- ++j;
- } while (j < 16);
- WelsLumaDcDequantIdct (sTCoeff, uiQp, pCtx);
- } else if (iResProperty == CHROMA_DC_U || iResProperty == CHROMA_DC_V) {
- do {
- sTCoeff[pScanTable[j]] = pSignificantMap[j];
- ++j;
- } while (j < 4);
- //iHadamard2x2
- WelsChromaDcIdct (sTCoeff);
- //scaling
- if (!pCtx->bUseScalingList) {
- for (j = 0; j < 4; ++j) {
- sTCoeff[pScanTable[j]] = (int16_t) ((int64_t)sTCoeff[pScanTable[j]] * (int64_t)pDeQuantMul[0] >> 1);
- }
- } else { //with scaling list
- for (j = 0; j < 4; ++j) {
- sTCoeff[pScanTable[j]] = (int16_t) ((int64_t)sTCoeff[pScanTable[j]] * (int64_t)pDeQuantMul[0] >> 5);
- }
- }
- } else { //luma ac, chroma ac
- do {
- if (pSignificantMap[j] != 0) {
- if (!pCtx->bUseScalingList) {
- sTCoeff[pScanTable[j]] = pSignificantMap[j] * pDeQuantMul[pScanTable[j] & 0x07];
- } else {
- sTCoeff[pScanTable[j]] = (int16_t) (((int64_t)pSignificantMap[j] * (int64_t)pDeQuantMul[pScanTable[j]] + 8) >> 4);
- }
- }
- ++j;
- } while (j < 16);
- }
- return ERR_NONE;
-}
-
-int32_t ParseIPCMInfoCabac (PWelsDecoderContext pCtx) {
- int32_t i;
- PWelsCabacDecEngine pCabacDecEngine = pCtx->pCabacDecEngine;
- SBitStringAux* pBsAux = pCtx->pCurDqLayer->pBitStringAux;
- SDqLayer* pCurLayer = pCtx->pCurDqLayer;
- int32_t iDstStrideLuma = pCurLayer->pDec->iLinesize[0];
- int32_t iDstStrideChroma = pCurLayer->pDec->iLinesize[1];
- int32_t iMbX = pCurLayer->iMbX;
- int32_t iMbY = pCurLayer->iMbY;
- int32_t iMbXy = pCurLayer->iMbXyIndex;
-
- int32_t iMbOffsetLuma = (iMbX + iMbY * iDstStrideLuma) << 4;
- int32_t iMbOffsetChroma = (iMbX + iMbY * iDstStrideChroma) << 3;
-
- uint8_t* pMbDstY = pCtx->pDec->pData[0] + iMbOffsetLuma;
- uint8_t* pMbDstU = pCtx->pDec->pData[1] + iMbOffsetChroma;
- uint8_t* pMbDstV = pCtx->pDec->pData[2] + iMbOffsetChroma;
-
- uint8_t* pPtrSrc;
-
- pCurLayer->pMbType[iMbXy] = MB_TYPE_INTRA_PCM;
- RestoreCabacDecEngineToBS (pCabacDecEngine, pBsAux);
- intX_t iBytesLeft = pBsAux->pEndBuf - pBsAux->pCurBuf;
- if (iBytesLeft < 384) {
- return GENERATE_ERROR_NO (ERR_LEVEL_MB_DATA, ERR_CABAC_NO_BS_TO_READ);
- }
- pPtrSrc = pBsAux->pCurBuf;
- if (!pCtx->pParam->bParseOnly) {
- for (i = 0; i < 16; i++) { //luma
- memcpy (pMbDstY, pPtrSrc, 16);
- pMbDstY += iDstStrideLuma;
- pPtrSrc += 16;
- }
- for (i = 0; i < 8; i++) { //cb
- memcpy (pMbDstU, pPtrSrc, 8);
- pMbDstU += iDstStrideChroma;
- pPtrSrc += 8;
- }
- for (i = 0; i < 8; i++) { //cr
- memcpy (pMbDstV, pPtrSrc, 8);
- pMbDstV += iDstStrideChroma;
- pPtrSrc += 8;
- }
- }
-
- pBsAux->pCurBuf += 384;
-
- pCurLayer->pLumaQp[iMbXy] = 0;
- pCurLayer->pChromaQp[iMbXy][0] = pCurLayer->pChromaQp[iMbXy][1] = 0;
- memset (pCurLayer->pNzc[iMbXy], 16, sizeof (pCurLayer->pNzc[iMbXy]));
-
- //step 4: cabac engine init
- WELS_READ_VERIFY (InitReadBits (pBsAux, 1));
- WELS_READ_VERIFY (InitCabacDecEngineFromBS (pCabacDecEngine, pBsAux));
- return ERR_NONE;
-}
-}
+/*!
+ * \copy
+ * Copyright (c) 2013, Cisco Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * parse_mb_syn_cabac.cpp: cabac parse for syntax elements
+ */
+#include "parse_mb_syn_cabac.h"
+#include "decode_slice.h"
+#include "mv_pred.h"
+#include "error_code.h"
+#include <stdio.h>
+namespace WelsDec {
+#define IDX_UNUSED -1
+
+static const int16_t g_kMaxPos [] = {IDX_UNUSED, 15, 14, 15, 3, 14, 63, 3, 3, 14, 14};
+static const int16_t g_kMaxC2 [] = {IDX_UNUSED, 4, 4, 4, 3, 4, 4, 3, 3, 4, 4};
+static const int16_t g_kBlockCat2CtxOffsetCBF[] = {IDX_UNUSED, 0, 4, 8, 12, 16, 0, 12, 12, 16, 16};
+static const int16_t g_kBlockCat2CtxOffsetMap [] = {IDX_UNUSED, 0, 15, 29, 44, 47, 0, 44, 44, 47, 47};
+static const int16_t g_kBlockCat2CtxOffsetLast[] = {IDX_UNUSED, 0, 15, 29, 44, 47, 0, 44, 44, 47, 47};
+static const int16_t g_kBlockCat2CtxOffsetOne [] = {IDX_UNUSED, 0, 10, 20, 30, 39, 0, 30, 30, 39, 39};
+static const int16_t g_kBlockCat2CtxOffsetAbs [] = {IDX_UNUSED, 0, 10, 20, 30, 39, 0, 30, 30, 39, 39};
+
+const uint8_t g_kTopBlkInsideMb[24] = { //for index with z-order 0~23
+ // 0 1 | 4 5 luma 8*8 block pNonZeroCount[16+8]
+ 0, 0, 1, 1, // 2 3 | 6 7 0 | 1 0 1 2 3
+ 0, 0, 1, 1, //--------------- --------- 4 5 6 7
+ 1, 1, 1, 1, // 8 9 | 12 13 2 | 3 8 9 10 11
+ 1, 1, 1, 1, // 10 11 | 14 15-----------------------------> 12 13 14 15
+ 0, 0, 1, 1, //---------------- chroma 8*8 block 16 17 18 19
+ 0, 0, 1, 1 // 16 17 | 20 21 0 1 20 21 22 23
+ // 18 19 | 22 23
+};
+
+const uint8_t g_kLeftBlkInsideMb[24] = { //for index with z-order 0~23
+ // 0 1 | 4 5 luma 8*8 block pNonZeroCount[16+8]
+ 0, 1, 0, 1, // 2 3 | 6 7 0 | 1 0 1 2 3
+ 1, 1, 1, 1, //--------------- --------- 4 5 6 7
+ 0, 1, 0, 1, // 8 9 | 12 13 2 | 3 8 9 10 11
+ 1, 1, 1, 1, // 10 11 | 14 15-----------------------------> 12 13 14 15
+ 0, 1, 0, 1, //---------------- chroma 8*8 block 16 17 18 19
+ 0, 1, 0, 1 // 16 17 | 20 21 0 1 20 21 22 23
+ // 18 19 | 22 23
+};
+
+static uint32_t DecodeCabacIntraMbType (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, int ctx_base) {
+ uint32_t uiCode;
+ uint32_t uiMbType = 0;
+
+ PWelsCabacDecEngine pCabacDecEngine = pCtx->pCabacDecEngine;
+ PWelsCabacCtx pBinCtx = pCtx->pCabacCtx + ctx_base;
+
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx, uiCode));
+ if (!uiCode) {
+ return 0; /* I4x4 */
+ }
+
+ DecodeTerminateCabac (pCabacDecEngine, uiCode);
+ if (uiCode) {
+ return 25; /* PCM */
+ }
+ uiMbType = 1; /* I16x16 */
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 1, uiCode)); /* cbp_luma != 0 */
+ uiMbType += 12 * uiCode;
+
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 2, uiCode));
+ if (uiCode) {
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 2, uiCode));
+ uiMbType += 4 + 4 * uiCode;
+ }
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 3, uiCode));
+ uiMbType += 2 * uiCode;
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 3, uiCode));
+ uiMbType += 1 * uiCode;
+ return uiMbType;
+}
+
+void UpdateP16x8RefIdxCabac (PDqLayer pCurDqLayer, int8_t pRefIndex[LIST_A][30], int32_t iPartIdx, const int8_t iRef,
+ const int8_t iListIdx) {
+ uint32_t iRef32Bit = (uint32_t) iRef;
+ const int32_t iRef4Bytes = (iRef32Bit << 24) | (iRef32Bit << 16) | (iRef32Bit << 8) | iRef32Bit;
+ int32_t iMbXy = pCurDqLayer->iMbXyIndex;
+ const uint8_t iScan4Idx = g_kuiScan4[iPartIdx];
+ const uint8_t iScan4Idx4 = 4 + iScan4Idx;
+ const uint8_t iCacheIdx = g_kuiCache30ScanIdx[iPartIdx];
+ const uint8_t iCacheIdx6 = 6 + iCacheIdx;
+ //mb
+ ST32 (&pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx ], iRef4Bytes);
+ ST32 (&pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx4], iRef4Bytes);
+ //cache
+ ST32 (&pRefIndex[iListIdx][iCacheIdx ], iRef4Bytes);
+ ST32 (&pRefIndex[iListIdx][iCacheIdx6], iRef4Bytes);
+}
+
+void UpdateP8x16RefIdxCabac (PDqLayer pCurDqLayer, int8_t pRefIndex[LIST_A][30], int32_t iPartIdx, const int8_t iRef,
+ const int8_t iListIdx) {
+ uint16_t iRef16Bit = (uint16_t) iRef;
+ const int16_t iRef2Bytes = (iRef16Bit << 8) | iRef16Bit;
+ int32_t i;
+ int32_t iMbXy = pCurDqLayer->iMbXyIndex;
+ for (i = 0; i < 2; i++, iPartIdx += 8) {
+ const uint8_t iScan4Idx = g_kuiScan4[iPartIdx];
+ const uint8_t iCacheIdx = g_kuiCache30ScanIdx[iPartIdx];
+ const uint8_t iScan4Idx4 = 4 + iScan4Idx;
+ const uint8_t iCacheIdx6 = 6 + iCacheIdx;
+ //mb
+ ST16 (&pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx ], iRef2Bytes);
+ ST16 (&pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx4], iRef2Bytes);
+ //cache
+ ST16 (&pRefIndex[iListIdx][iCacheIdx ], iRef2Bytes);
+ ST16 (&pRefIndex[iListIdx][iCacheIdx6], iRef2Bytes);
+ }
+}
+
+void UpdateP8x8RefIdxCabac (PDqLayer pCurDqLayer, int8_t pRefIndex[LIST_A][30], int32_t iPartIdx, const int8_t iRef,
+ const int8_t iListIdx) {
+ int32_t iMbXy = pCurDqLayer->iMbXyIndex;
+ const uint8_t iScan4Idx = g_kuiScan4[iPartIdx];
+ pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx] = pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx + 1] =
+ pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx + 4] = pCurDqLayer->pRefIndex[iListIdx][iMbXy][iScan4Idx + 5] = iRef;
+}
+
+void UpdateP8x8DirectCabac (PDqLayer pCurDqLayer, int32_t iPartIdx) {
+ int32_t iMbXy = pCurDqLayer->iMbXyIndex;
+ const uint8_t iScan4Idx = g_kuiScan4[iPartIdx];
+ pCurDqLayer->pDirect[iMbXy][iScan4Idx] = pCurDqLayer->pDirect[iMbXy][iScan4Idx + 1] =
+ pCurDqLayer->pDirect[iMbXy][iScan4Idx + 4] = pCurDqLayer->pDirect[iMbXy][iScan4Idx + 5] = 1;
+}
+
+void UpdateP16x16DirectCabac (PDqLayer pCurDqLayer) {
+ int32_t i;
+ int32_t iMbXy = pCurDqLayer->iMbXyIndex;
+ const int16_t direct = (1 << 8) | 1;
+ for (i = 0; i < 16; i += 4) {
+ const uint8_t kuiScan4Idx = g_kuiScan4[i];
+ const uint8_t kuiScan4IdxPlus4 = 4 + kuiScan4Idx;
+ ST16 (&pCurDqLayer->pDirect[iMbXy][kuiScan4Idx], direct);
+ ST16 (&pCurDqLayer->pDirect[iMbXy][kuiScan4IdxPlus4], direct);
+ }
+}
+
+void UpdateP16x16MvdCabac (SDqLayer* pCurDqLayer, int16_t pMvd[2], const int8_t iListIdx) {
+ int32_t pMvd32[2];
+ ST32 (&pMvd32[0], LD32 (pMvd));
+ ST32 (&pMvd32[1], LD32 (pMvd));
+ int32_t i;
+ int32_t iMbXy = pCurDqLayer->iMbXyIndex;
+ for (i = 0; i < 16; i += 2) {
+ ST64 (pCurDqLayer->pMvd[iListIdx][iMbXy][i], LD64 (pMvd32));
+ }
+}
+
+void UpdateP16x8MvdCabac (SDqLayer* pCurDqLayer, int16_t pMvdCache[LIST_A][30][MV_A], int32_t iPartIdx, int16_t pMvd[2],
+ const int8_t iListIdx) {
+ int32_t pMvd32[2];
+ ST32 (&pMvd32[0], LD32 (pMvd));
+ ST32 (&pMvd32[1], LD32 (pMvd));
+ int32_t i;
+ int32_t iMbXy = pCurDqLayer->iMbXyIndex;
+ for (i = 0; i < 2; i++, iPartIdx += 4) {
+ const uint8_t iScan4Idx = g_kuiScan4[iPartIdx];
+ const uint8_t iScan4Idx4 = 4 + iScan4Idx;
+ const uint8_t iCacheIdx = g_kuiCache30ScanIdx[iPartIdx];
+ const uint8_t iCacheIdx6 = 6 + iCacheIdx;
+ //mb
+ ST64 (pCurDqLayer->pMvd[iListIdx][iMbXy][ iScan4Idx ], LD64 (pMvd32));
+ ST64 (pCurDqLayer->pMvd[iListIdx][iMbXy][ iScan4Idx4], LD64 (pMvd32));
+ //cache
+ ST64 (pMvdCache[iListIdx][ iCacheIdx ], LD64 (pMvd32));
+ ST64 (pMvdCache[iListIdx][ iCacheIdx6], LD64 (pMvd32));
+ }
+}
+
+void UpdateP8x16MvdCabac (SDqLayer* pCurDqLayer, int16_t pMvdCache[LIST_A][30][MV_A], int32_t iPartIdx, int16_t pMvd[2],
+ const int8_t iListIdx) {
+ int32_t pMvd32[2];
+ ST32 (&pMvd32[0], LD32 (pMvd));
+ ST32 (&pMvd32[1], LD32 (pMvd));
+ int32_t i;
+ int32_t iMbXy = pCurDqLayer->iMbXyIndex;
+
+ for (i = 0; i < 2; i++, iPartIdx += 8) {
+ const uint8_t iScan4Idx = g_kuiScan4[iPartIdx];
+ const uint8_t iCacheIdx = g_kuiCache30ScanIdx[iPartIdx];
+ const uint8_t iScan4Idx4 = 4 + iScan4Idx;
+ const uint8_t iCacheIdx6 = 6 + iCacheIdx;
+ //mb
+ ST64 (pCurDqLayer->pMvd[iListIdx][iMbXy][ iScan4Idx ], LD64 (pMvd32));
+ ST64 (pCurDqLayer->pMvd[iListIdx][iMbXy][ iScan4Idx4], LD64 (pMvd32));
+ //cache
+ ST64 (pMvdCache[iListIdx][ iCacheIdx ], LD64 (pMvd32));
+ ST64 (pMvdCache[iListIdx][ iCacheIdx6], LD64 (pMvd32));
+ }
+}
+
+int32_t ParseEndOfSliceCabac (PWelsDecoderContext pCtx, uint32_t& uiBinVal) {
+ uiBinVal = 0;
+ WELS_READ_VERIFY (DecodeTerminateCabac (pCtx->pCabacDecEngine, uiBinVal));
+ return ERR_NONE;
+}
+
+int32_t ParseSkipFlagCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiSkip) {
+ uiSkip = 0;
+ int32_t iCtxInc = NEW_CTX_OFFSET_SKIP;
+ iCtxInc += (pNeighAvail->iLeftAvail && !IS_SKIP (pNeighAvail->iLeftType)) + (pNeighAvail->iTopAvail
+ && !IS_SKIP (pNeighAvail->iTopType));
+ if (B_SLICE == pCtx->eSliceType)
+ iCtxInc += 13;
+ PWelsCabacCtx pBinCtx = (pCtx->pCabacCtx + iCtxInc);
+ WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pBinCtx, uiSkip));
+ return ERR_NONE;
+}
+
+
+int32_t ParseMBTypeISliceCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiBinVal) {
+ uint32_t uiCode;
+ int32_t iIdxA = 0, iIdxB = 0;
+ int32_t iCtxInc;
+ uiBinVal = 0;
+ PWelsCabacDecEngine pCabacDecEngine = pCtx->pCabacDecEngine;
+ PWelsCabacCtx pBinCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_MB_TYPE_I; //I mode in I slice
+ iIdxA = (pNeighAvail->iLeftAvail) && (pNeighAvail->iLeftType != MB_TYPE_INTRA4x4
+ && pNeighAvail->iLeftType != MB_TYPE_INTRA8x8);
+ iIdxB = (pNeighAvail->iTopAvail) && (pNeighAvail->iTopType != MB_TYPE_INTRA4x4
+ && pNeighAvail->iTopType != MB_TYPE_INTRA8x8);
+ iCtxInc = iIdxA + iIdxB;
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + iCtxInc, uiCode));
+ uiBinVal = uiCode;
+ if (uiBinVal != 0) { //I16x16
+ WELS_READ_VERIFY (DecodeTerminateCabac (pCabacDecEngine, uiCode));
+ if (uiCode == 1)
+ uiBinVal = 25; //I_PCM
+ else {
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 3, uiCode));
+ uiBinVal = 1 + uiCode * 12;
+ //decoding of uiCbp:0,1,2
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 4, uiCode));
+ if (uiCode != 0) {
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 5, uiCode));
+ uiBinVal += 4;
+ if (uiCode != 0)
+ uiBinVal += 4;
+ }
+ //decoding of I pred-mode: 0,1,2,3
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 6, uiCode));
+ uiBinVal += (uiCode << 1);
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 7, uiCode));
+ uiBinVal += uiCode;
+ }
+ }
+ //I4x4
+ return ERR_NONE;
+}
+
+int32_t ParseMBTypePSliceCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiMbType) {
+ uint32_t uiCode;
+ uiMbType = 0;
+ PWelsCabacDecEngine pCabacDecEngine = pCtx->pCabacDecEngine;
+
+ PWelsCabacCtx pBinCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_SKIP;
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 3, uiCode));
+ if (uiCode) {
+ // Intra MB
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 6, uiCode));
+ if (uiCode) { // Intra 16x16
+ WELS_READ_VERIFY (DecodeTerminateCabac (pCabacDecEngine, uiCode));
+ if (uiCode) {
+ uiMbType = 30;
+ return ERR_NONE;//MB_TYPE_INTRA_PCM;
+ }
+
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 7, uiCode));
+ uiMbType = 6 + uiCode * 12;
+
+ //uiCbp: 0,1,2
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 8, uiCode));
+ if (uiCode) {
+ uiMbType += 4;
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 8, uiCode));
+ if (uiCode)
+ uiMbType += 4;
+ }
+
+ //IPredMode: 0,1,2,3
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 9, uiCode));
+ uiMbType += (uiCode << 1);
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 9, uiCode));
+ uiMbType += uiCode;
+ } else
+ // Intra 4x4
+ uiMbType = 5;
+ } else { // P MB
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 4, uiCode));
+ if (uiCode) { //second bit
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 6, uiCode));
+ if (uiCode)
+ uiMbType = 1;
+ else
+ uiMbType = 2;
+ } else {
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 5, uiCode));
+ if (uiCode)
+ uiMbType = 3;
+ else
+ uiMbType = 0;
+ }
+ }
+ return ERR_NONE;
+}
+
+int32_t ParseMBTypeBSliceCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiMbType) {
+ uint32_t uiCode;
+ uiMbType = 0;
+ int32_t iIdxA = 0, iIdxB = 0;
+ int32_t iCtxInc;
+
+ PWelsCabacDecEngine pCabacDecEngine = pCtx->pCabacDecEngine;
+ PWelsCabacCtx pBinCtx = pCtx->pCabacCtx + 27; //B slice
+
+ iIdxA = (pNeighAvail->iLeftAvail) && !IS_DIRECT (pNeighAvail->iLeftType);
+ iIdxB = (pNeighAvail->iTopAvail) && !IS_DIRECT (pNeighAvail->iTopType);
+
+ iCtxInc = iIdxA + iIdxB;
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + iCtxInc, uiCode));
+ if (!uiCode)
+ uiMbType = 0; // Bi_Direct
+ else {
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 3, uiCode));
+ if (!uiCode) {
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 5, uiCode));
+ uiMbType = 1 + uiCode; // 16x16 L0L1
+ } else {
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 4, uiCode));
+ uiMbType = uiCode << 3;
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 5, uiCode));
+ uiMbType |= uiCode << 2;
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 5, uiCode));
+ uiMbType |= uiCode << 1;
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 5, uiCode));
+ uiMbType |= uiCode;
+ if (uiMbType < 8) {
+ uiMbType += 3;
+ return ERR_NONE;
+ } else if (uiMbType == 13) {
+ uiMbType = DecodeCabacIntraMbType (pCtx, pNeighAvail, 32) + 23;
+ return ERR_NONE;
+ } else if (uiMbType == 14) {
+ uiMbType = 11; // Bi8x16
+ return ERR_NONE;
+ } else if (uiMbType == 15) {
+ uiMbType = 22; // 8x8
+ return ERR_NONE;
+ }
+ uiMbType <<= 1;
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 5, uiCode));
+ uiMbType |= uiCode;
+ uiMbType -= 4;
+ }
+ }
+ return ERR_NONE;
+}
+
+int32_t ParseTransformSize8x8FlagCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail,
+ bool& bTransformSize8x8Flag) {
+ uint32_t uiCode;
+ int32_t iIdxA, iIdxB;
+ int32_t iCtxInc;
+ PWelsCabacDecEngine pCabacDecEngine = pCtx->pCabacDecEngine;
+ PWelsCabacCtx pBinCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_TS_8x8_FLAG;
+ iIdxA = (pNeighAvail->iLeftAvail) && (pCtx->pCurDqLayer->pTransformSize8x8Flag[pCtx->pCurDqLayer->iMbXyIndex - 1]);
+ iIdxB = (pNeighAvail->iTopAvail)
+ && (pCtx->pCurDqLayer->pTransformSize8x8Flag[pCtx->pCurDqLayer->iMbXyIndex - pCtx->pCurDqLayer->iMbWidth]);
+ iCtxInc = iIdxA + iIdxB;
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + iCtxInc, uiCode));
+ bTransformSize8x8Flag = !!uiCode;
+
+ return ERR_NONE;
+}
+
+int32_t ParseSubMBTypeCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiSubMbType) {
+ uint32_t uiCode;
+ PWelsCabacDecEngine pCabacDecEngine = pCtx->pCabacDecEngine;
+ PWelsCabacCtx pBinCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_SUBMB_TYPE;
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx, uiCode));
+ if (uiCode)
+ uiSubMbType = 0;
+ else {
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 1, uiCode));
+ if (uiCode) {
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 2, uiCode));
+ uiSubMbType = 3 - uiCode;
+ } else {
+ uiSubMbType = 1;
+ }
+ }
+ return ERR_NONE;
+}
+
+int32_t ParseBSubMBTypeCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiSubMbType) {
+ uint32_t uiCode;
+ PWelsCabacDecEngine pCabacDecEngine = pCtx->pCabacDecEngine;
+ PWelsCabacCtx pBinCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_B_SUBMB_TYPE;
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx, uiCode));
+ if (!uiCode) {
+ uiSubMbType = 0; /* B_Direct_8x8 */
+ return ERR_NONE;
+ }
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 1, uiCode));
+ if (!uiCode) {
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 3, uiCode));
+ uiSubMbType = 1 + uiCode; /* B_L0_8x8, B_L1_8x8 */
+ return ERR_NONE;
+ }
+ uiSubMbType = 3;
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 2, uiCode));
+ if (uiCode) {
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 3, uiCode));
+ if (uiCode) {
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 3, uiCode));
+ uiSubMbType = 11 + uiCode; /* B_L1_4x4, B_Bi_4x4 */
+ return ERR_NONE;
+ }
+ uiSubMbType += 4;
+ }
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 3, uiCode));
+ uiSubMbType += 2 * uiCode;
+ WELS_READ_VERIFY (DecodeBinCabac (pCabacDecEngine, pBinCtx + 3, uiCode));
+ uiSubMbType += uiCode;
+
+ return ERR_NONE;
+}
+
+int32_t ParseIntraPredModeLumaCabac (PWelsDecoderContext pCtx, int32_t& iBinVal) {
+ uint32_t uiCode;
+ iBinVal = 0;
+ WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_IPR, uiCode));
+ if (uiCode == 1)
+ iBinVal = -1;
+ else {
+ WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_IPR + 1, uiCode));
+ iBinVal |= uiCode;
+ WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_IPR + 1, uiCode));
+ iBinVal |= (uiCode << 1);
+ WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_IPR + 1, uiCode));
+ iBinVal |= (uiCode << 2);
+ }
+ return ERR_NONE;
+}
+
+int32_t ParseIntraPredModeChromaCabac (PWelsDecoderContext pCtx, uint8_t uiNeighAvail, int32_t& iBinVal) {
+ uint32_t uiCode;
+ int32_t iIdxA, iIdxB, iCtxInc;
+ int8_t* pChromaPredMode = pCtx->pCurDqLayer->pChromaPredMode;
+ uint32_t* pMbType = pCtx->pCurDqLayer->pMbType;
+ int32_t iLeftAvail = uiNeighAvail & 0x04;
+ int32_t iTopAvail = uiNeighAvail & 0x01;
+
+ int32_t iMbXy = pCtx->pCurDqLayer->iMbXyIndex;
+ int32_t iMbXyTop = iMbXy - pCtx->pCurDqLayer->iMbWidth;
+ int32_t iMbXyLeft = iMbXy - 1;
+
+ iBinVal = 0;
+
+ iIdxB = iTopAvail && (pChromaPredMode[iMbXyTop] > 0 && pChromaPredMode[iMbXyTop] <= 3)
+ && pMbType[iMbXyTop] != MB_TYPE_INTRA_PCM;
+ iIdxA = iLeftAvail && (pChromaPredMode[iMbXyLeft] > 0 && pChromaPredMode[iMbXyLeft] <= 3)
+ && pMbType[iMbXyLeft] != MB_TYPE_INTRA_PCM;
+ iCtxInc = iIdxA + iIdxB;
+ WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CIPR + iCtxInc, uiCode));
+ iBinVal = uiCode;
+ if (iBinVal != 0) {
+ uint32_t iSym;
+ WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CIPR + 3, iSym));
+ if (iSym == 0) {
+ iBinVal = (iSym + 1);
+ return ERR_NONE;
+ }
+ iSym = 0;
+ do {
+ WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CIPR + 3, uiCode));
+ ++iSym;
+ } while ((uiCode != 0) && (iSym < 1));
+
+ if ((uiCode != 0) && (iSym == 1))
+ ++ iSym;
+ iBinVal = (iSym + 1);
+ return ERR_NONE;
+ }
+ return ERR_NONE;
+}
+
+int32_t ParseInterPMotionInfoCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
+ int16_t pMotionVector[LIST_A][30][MV_A], int16_t pMvdCache[LIST_A][30][MV_A], int8_t pRefIndex[LIST_A][30]) {
+ PSlice pSlice = &pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer;
+ PSliceHeader pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader;
+ PDqLayer pCurDqLayer = pCtx->pCurDqLayer;
+ PPicture* ppRefPic = pCtx->sRefPic.pRefList[LIST_0];
+ int32_t pRefCount[2];
+ int32_t i, j;
+ int32_t iMbXy = pCurDqLayer->iMbXyIndex;
+ int16_t pMv[4] = {0};
+ int16_t pMvd[4] = {0};
+ int8_t iRef[2] = {0};
+ int32_t iPartIdx;
+ int16_t iMinVmv = pSliceHeader->pSps->pSLevelLimits->iMinVmv;
+ int16_t iMaxVmv = pSliceHeader->pSps->pSLevelLimits->iMaxVmv;
+ pRefCount[0] = pSliceHeader->uiRefCount[0];
+ pRefCount[1] = pSliceHeader->uiRefCount[1];
+
+ switch (pCurDqLayer->pMbType[iMbXy]) {
+ case MB_TYPE_16x16: {
+ iPartIdx = 0;
+ WELS_READ_VERIFY (ParseRefIdxCabac (pCtx, pNeighAvail, pNonZeroCount, pRefIndex, 0, LIST_0, iPartIdx, pRefCount[0], 0,
+ iRef[0]));
+ if ((iRef[0] < 0) || (iRef[0] >= pRefCount[0]) || (ppRefPic[iRef[0]] == NULL)) { //error ref_idx
+ pCtx->bMbRefConcealed = true;
+ if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) {
+ iRef[0] = 0;
+ pCtx->iErrorCode |= dsBitstreamError;
+ } else {
+ return GENERATE_ERROR_NO (ERR_LEVEL_MB_DATA, ERR_INFO_INVALID_REF_INDEX);
+ }
+ }
+ pCtx->bMbRefConcealed = pCtx->bRPLRError || pCtx->bMbRefConcealed || ! (ppRefPic[iRef[0]]
+ && ppRefPic[iRef[0]]->bIsComplete);
+ PredMv (pMotionVector, pRefIndex, LIST_0, 0, 4, iRef[0], pMv);
+ WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, LIST_0, 0, pMvd[0]));
+ WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, LIST_0, 1, pMvd[1]));
+ pMv[0] += pMvd[0];
+ pMv[1] += pMvd[1];
+ WELS_CHECK_SE_BOTH_WARNING (pMv[1], iMinVmv, iMaxVmv, "vertical mv");
+ UpdateP16x16MotionInfo (pCurDqLayer, LIST_0, iRef[0], pMv);
+ UpdateP16x16MvdCabac (pCurDqLayer, pMvd, LIST_0);
+ }
+ break;
+ case MB_TYPE_16x8:
+ for (i = 0; i < 2; i++) {
+ iPartIdx = i << 3;
+ WELS_READ_VERIFY (ParseRefIdxCabac (pCtx, pNeighAvail, pNonZeroCount, pRefIndex, 0, LIST_0, iPartIdx, pRefCount[0], 0,
+ iRef[i]));
+ if ((iRef[i] < 0) || (iRef[i] >= pRefCount[0]) || (ppRefPic[iRef[i]] == NULL)) { //error ref_idx
+ pCtx->bMbRefConcealed = true;
+ if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) {
+ iRef[i] = 0;
+ pCtx->iErrorCode |= dsBitstreamError;
+ } else {
+ return GENERATE_ERROR_NO (ERR_LEVEL_MB_DATA, ERR_INFO_INVALID_REF_INDEX);
+ }
+ }
+ pCtx->bMbRefConcealed = pCtx->bRPLRError || pCtx->bMbRefConcealed || ! (ppRefPic[iRef[i]]
+ && ppRefPic[iRef[i]]->bIsComplete);
+ UpdateP16x8RefIdxCabac (pCurDqLayer, pRefIndex, iPartIdx, iRef[i], LIST_0);
+ }
+ for (i = 0; i < 2; i++) {
+ iPartIdx = i << 3;
+ PredInter16x8Mv (pMotionVector, pRefIndex, LIST_0, iPartIdx, iRef[i], pMv);
+ WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, LIST_0, 0, pMvd[0]));
+ WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, LIST_0, 1, pMvd[1]));
+ pMv[0] += pMvd[0];
+ pMv[1] += pMvd[1];
+ WELS_CHECK_SE_BOTH_WARNING (pMv[1], iMinVmv, iMaxVmv, "vertical mv");
+ UpdateP16x8MotionInfo (pCurDqLayer, pMotionVector, pRefIndex, LIST_0, iPartIdx, iRef[i], pMv);
+ UpdateP16x8MvdCabac (pCurDqLayer, pMvdCache, iPartIdx, pMvd, LIST_0);
+ }
+ break;
+ case MB_TYPE_8x16:
+ for (i = 0; i < 2; i++) {
+ iPartIdx = i << 2;
+ WELS_READ_VERIFY (ParseRefIdxCabac (pCtx, pNeighAvail, pNonZeroCount, pRefIndex, 0, LIST_0, iPartIdx, pRefCount[0], 0,
+ iRef[i]));
+ if ((iRef[i] < 0) || (iRef[i] >= pRefCount[0]) || (ppRefPic[iRef[i]] == NULL)) { //error ref_idx
+ pCtx->bMbRefConcealed = true;
+ if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) {
+ iRef[i] = 0;
+ pCtx->iErrorCode |= dsBitstreamError;
+ } else {
+ return GENERATE_ERROR_NO (ERR_LEVEL_MB_DATA, ERR_INFO_INVALID_REF_INDEX);
+ }
+ }
+ pCtx->bMbRefConcealed = pCtx->bRPLRError || pCtx->bMbRefConcealed || ! (ppRefPic[iRef[i]]
+ && ppRefPic[iRef[i]]->bIsComplete);
+ UpdateP8x16RefIdxCabac (pCurDqLayer, pRefIndex, iPartIdx, iRef[i], LIST_0);
+ }
+ for (i = 0; i < 2; i++) {
+ iPartIdx = i << 2;
+ PredInter8x16Mv (pMotionVector, pRefIndex, LIST_0, i << 2, iRef[i], pMv/*&mv[0], &mv[1]*/);
+
+ WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, LIST_0, 0, pMvd[0]));
+ WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, LIST_0, 1, pMvd[1]));
+ pMv[0] += pMvd[0];
+ pMv[1] += pMvd[1];
+ WELS_CHECK_SE_BOTH_WARNING (pMv[1], iMinVmv, iMaxVmv, "vertical mv");
+ UpdateP8x16MotionInfo (pCurDqLayer, pMotionVector, pRefIndex, LIST_0, iPartIdx, iRef[i], pMv);
+ UpdateP8x16MvdCabac (pCurDqLayer, pMvdCache, iPartIdx, pMvd, LIST_0);
+ }
+ break;
+ case MB_TYPE_8x8:
+ case MB_TYPE_8x8_REF0: {
+ int8_t pRefIdx[4] = {0}, pSubPartCount[4], pPartW[4];
+ uint32_t uiSubMbType;
+ //sub_mb_type, partition
+ for (i = 0; i < 4; i++) {
+ WELS_READ_VERIFY (ParseSubMBTypeCabac (pCtx, pNeighAvail, uiSubMbType));
+ if (uiSubMbType >= 4) { //invalid sub_mb_type
+ return GENERATE_ERROR_NO (ERR_LEVEL_MB_DATA, ERR_INFO_INVALID_SUB_MB_TYPE);
+ }
+ pCurDqLayer->pSubMbType[iMbXy][i] = g_ksInterPSubMbTypeInfo[uiSubMbType].iType;
+ pSubPartCount[i] = g_ksInterPSubMbTypeInfo[uiSubMbType].iPartCount;
+ pPartW[i] = g_ksInterPSubMbTypeInfo[uiSubMbType].iPartWidth;
+
+ // Need modification when B picture add in, reference to 7.3.5
+ pCurDqLayer->pNoSubMbPartSizeLessThan8x8Flag[iMbXy] &= (uiSubMbType == 0);
+ }
+
+ for (i = 0; i < 4; i++) {
+ int16_t iIdx8 = i << 2;
+ WELS_READ_VERIFY (ParseRefIdxCabac (pCtx, pNeighAvail, pNonZeroCount, pRefIndex, 0, LIST_0, iIdx8, pRefCount[0], 1,
+ pRefIdx[i]));
+ if ((pRefIdx[i] < 0) || (pRefIdx[i] >= pRefCount[0]) || (ppRefPic[pRefIdx[i]] == NULL)) { //error ref_idx
+ pCtx->bMbRefConcealed = true;
+ if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) {
+ pRefIdx[i] = 0;
+ pCtx->iErrorCode |= dsBitstreamError;
+ } else {
+ return GENERATE_ERROR_NO (ERR_LEVEL_MB_DATA, ERR_INFO_INVALID_REF_INDEX);
+ }
+ }
+ pCtx->bMbRefConcealed = pCtx->bRPLRError || pCtx->bMbRefConcealed || ! (ppRefPic[pRefIdx[i]]
+ && ppRefPic[pRefIdx[i]]->bIsComplete);
+ UpdateP8x8RefIdxCabac (pCurDqLayer, pRefIndex, iIdx8, pRefIdx[i], LIST_0);
+ }
+ //mv
+ for (i = 0; i < 4; i++) {
+ int8_t iPartCount = pSubPartCount[i];
+ uiSubMbType = pCurDqLayer->pSubMbType[iMbXy][i];
+ int16_t iPartIdx, iBlockW = pPartW[i];
+ uint8_t iScan4Idx, iCacheIdx;
+ iCacheIdx = g_kuiCache30ScanIdx[i << 2];
+ pRefIndex[0][iCacheIdx ] = pRefIndex[0][iCacheIdx + 1]
+ = pRefIndex[0][iCacheIdx + 6] = pRefIndex[0][iCacheIdx + 7] = pRefIdx[i];
+
+ for (j = 0; j < iPartCount; j++) {
+ iPartIdx = (i << 2) + j * iBlockW;
+ iScan4Idx = g_kuiScan4[iPartIdx];
+ iCacheIdx = g_kuiCache30ScanIdx[iPartIdx];
+ PredMv (pMotionVector, pRefIndex, LIST_0, iPartIdx, iBlockW, pRefIdx[i], pMv);
+ WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, LIST_0, 0, pMvd[0]));
+ WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, LIST_0, 1, pMvd[1]));
+ pMv[0] += pMvd[0];
+ pMv[1] += pMvd[1];
+ WELS_CHECK_SE_BOTH_WARNING (pMv[1], iMinVmv, iMaxVmv, "vertical mv");
+ if (SUB_MB_TYPE_8x8 == uiSubMbType) {
+ ST32 ((pMv + 2), LD32 (pMv));
+ ST32 ((pMvd + 2), LD32 (pMvd));
+ ST64 (pCurDqLayer->pMv[0][iMbXy][iScan4Idx], LD64 (pMv));
+ ST64 (pCurDqLayer->pMv[0][iMbXy][iScan4Idx + 4], LD64 (pMv));
+ ST64 (pCurDqLayer->pMvd[0][iMbXy][iScan4Idx], LD64 (pMvd));
+ ST64 (pCurDqLayer->pMvd[0][iMbXy][iScan4Idx + 4], LD64 (pMvd));
+ ST64 (pMotionVector[0][iCacheIdx ], LD64 (pMv));
+ ST64 (pMotionVector[0][iCacheIdx + 6], LD64 (pMv));
+ ST64 (pMvdCache[0][iCacheIdx ], LD64 (pMvd));
+ ST64 (pMvdCache[0][iCacheIdx + 6], LD64 (pMvd));
+ } else if (SUB_MB_TYPE_8x4 == uiSubMbType) {
+ ST32 ((pMv + 2), LD32 (pMv));
+ ST32 ((pMvd + 2), LD32 (pMvd));
+ ST64 (pCurDqLayer->pMv[0][iMbXy][iScan4Idx ], LD64 (pMv));
+ ST64 (pCurDqLayer->pMvd[0][iMbXy][iScan4Idx ], LD64 (pMvd));
+ ST64 (pMotionVector[0][iCacheIdx ], LD64 (pMv));
+ ST64 (pMvdCache[0][iCacheIdx ], LD64 (pMvd));
+ } else if (SUB_MB_TYPE_4x8 == uiSubMbType) {
+ ST32 (pCurDqLayer->pMv[0][iMbXy][iScan4Idx ], LD32 (pMv));
+ ST32 (pCurDqLayer->pMv[0][iMbXy][iScan4Idx + 4], LD32 (pMv));
+ ST32 (pCurDqLayer->pMvd[0][iMbXy][iScan4Idx ], LD32 (pMvd));
+ ST32 (pCurDqLayer->pMvd[0][iMbXy][iScan4Idx + 4], LD32 (pMvd));
+ ST32 (pMotionVector[0][iCacheIdx ], LD32 (pMv));
+ ST32 (pMotionVector[0][iCacheIdx + 6], LD32 (pMv));
+ ST32 (pMvdCache[0][iCacheIdx ], LD32 (pMvd));
+ ST32 (pMvdCache[0][iCacheIdx + 6], LD32 (pMvd));
+ } else { //SUB_MB_TYPE_4x4
+ ST32 (pCurDqLayer->pMv[0][iMbXy][iScan4Idx ], LD32 (pMv));
+ ST32 (pCurDqLayer->pMvd[0][iMbXy][iScan4Idx ], LD32 (pMvd));
+ ST32 (pMotionVector[0][iCacheIdx ], LD32 (pMv));
+ ST32 (pMvdCache[0][iCacheIdx ], LD32 (pMvd));
+ }
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ return ERR_NONE;
+}
+
+int32_t ParseInterBMotionInfoCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCount,
+ int16_t pMotionVector[LIST_A][30][MV_A], int16_t pMvdCache[LIST_A][30][MV_A], int8_t pRefIndex[LIST_A][30],
+ int8_t pDirect[30]) {
+ PSlice pSlice = &pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer;
+ PSliceHeader pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader;
+ PDqLayer pCurDqLayer = pCtx->pCurDqLayer;
+ int32_t pRefCount[LIST_A];
+ int32_t iMbXy = pCurDqLayer->iMbXyIndex;
+ int16_t pMv[4] = { 0 };
+ int16_t pMvd[4] = { 0 };
+ int8_t iRef[LIST_A] = { 0 };
+ int32_t iPartIdx;
+ int16_t iMinVmv = pSliceHeader->pSps->pSLevelLimits->iMinVmv;
+ int16_t iMaxVmv = pSliceHeader->pSps->pSLevelLimits->iMaxVmv;
+ pRefCount[0] = pSliceHeader->uiRefCount[0];
+ pRefCount[1] = pSliceHeader->uiRefCount[1];
+
+ MbType mbType = pCurDqLayer->pMbType[iMbXy];
+
+ if (IS_DIRECT (mbType)) {
+
+ int16_t pMvDirect[LIST_A][2] = { { 0, 0 }, { 0, 0 } };
+ if (pSliceHeader->iDirectSpatialMvPredFlag) {
+ //predict direct spatial mv
+ PredMvBDirectSpatial (pCtx, pMvDirect, iRef);
+ } else {
+ //temporal direct 16x16 mode
+ ComputeColocated (pCtx);
+ PredBDirectTemporal (pCtx, pMvDirect, iRef);
+ }
+ } else if (IS_INTER_16x16 (mbType)) {
+ iPartIdx = 0;
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ iRef[listIdx] = REF_NOT_IN_LIST;
+ if (IS_DIR (mbType, 0, listIdx)) {
+ WELS_READ_VERIFY (ParseRefIdxCabac (pCtx, pNeighAvail, pNonZeroCount, pRefIndex, pDirect, listIdx, iPartIdx,
+ pRefCount[listIdx], 0,
+ iRef[listIdx]));
+ if ((iRef[listIdx] < 0) || (iRef[listIdx] >= pRefCount[listIdx])
+ || (pCtx->sRefPic.pRefList[listIdx][iRef[listIdx]] == NULL)) { //error ref_idx
+ pCtx->bMbRefConcealed = true;
+ if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) {
+ iRef[listIdx] = 0;
+ pCtx->iErrorCode |= dsBitstreamError;
+ } else {
+ return GENERATE_ERROR_NO (ERR_LEVEL_MB_DATA, ERR_INFO_INVALID_REF_INDEX);
+ }
+ }
+ pCtx->bMbRefConcealed = pCtx->bRPLRError || pCtx->bMbRefConcealed || ! (pCtx->sRefPic.pRefList[listIdx][iRef[listIdx]]
+ && pCtx->sRefPic.pRefList[listIdx][iRef[listIdx]]->bIsComplete);
+ }
+ }
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ if (IS_DIR (mbType, 0, listIdx)) {
+ PredMv (pMotionVector, pRefIndex, listIdx, 0, 4, iRef[listIdx], pMv);
+ WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, listIdx, 0, pMvd[0]));
+ WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, listIdx, 1, pMvd[1]));
+ pMv[0] += pMvd[0];
+ pMv[1] += pMvd[1];
+ WELS_CHECK_SE_BOTH_WARNING (pMv[1], iMinVmv, iMaxVmv, "vertical mv");
+ } else {
+ * (uint32_t*)pMv = * (uint32_t*)pMvd = 0;
+ }
+ UpdateP16x16MotionInfo (pCurDqLayer, listIdx, iRef[listIdx], pMv);
+ UpdateP16x16MvdCabac (pCurDqLayer, pMvd, listIdx);
+ }
+ } else if (IS_INTER_16x8 (mbType)) {
+ int8_t ref_idx_list[LIST_A][2] = { {REF_NOT_IN_LIST, REF_NOT_IN_LIST}, { REF_NOT_IN_LIST, REF_NOT_IN_LIST } };
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ for (int32_t i = 0; i < 2; ++i) {
+ iPartIdx = i << 3;
+ int8_t ref_idx = REF_NOT_IN_LIST;
+ if (IS_DIR (mbType, i, listIdx)) {
+ WELS_READ_VERIFY (ParseRefIdxCabac (pCtx, pNeighAvail, pNonZeroCount, pRefIndex, pDirect, listIdx, iPartIdx,
+ pRefCount[listIdx], 0, ref_idx));
+ if ((ref_idx < 0) || (ref_idx >= pRefCount[listIdx])
+ || (pCtx->sRefPic.pRefList[listIdx][ref_idx] == NULL)) { //error ref_idx
+ pCtx->bMbRefConcealed = true;
+ if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) {
+ ref_idx = 0;
+ pCtx->iErrorCode |= dsBitstreamError;
+ } else {
+ return GENERATE_ERROR_NO (ERR_LEVEL_MB_DATA, ERR_INFO_INVALID_REF_INDEX);
+ }
+ }
+ pCtx->bMbRefConcealed = pCtx->bRPLRError || pCtx->bMbRefConcealed || ! (pCtx->sRefPic.pRefList[listIdx][ref_idx]
+ && pCtx->sRefPic.pRefList[listIdx][ref_idx]->bIsComplete);
+ }
+ UpdateP16x8RefIdxCabac (pCurDqLayer, pRefIndex, iPartIdx, ref_idx, listIdx);
+ ref_idx_list[listIdx][i] = ref_idx;
+ }
+ }
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ for (int32_t i = 0; i < 2; ++i) {
+ iPartIdx = i << 3;
+ int8_t ref_idx = ref_idx_list[listIdx][i];
+ if (IS_DIR (mbType, i, listIdx)) {
+ PredInter16x8Mv (pMotionVector, pRefIndex, listIdx, iPartIdx, ref_idx, pMv);
+ WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, listIdx, 0, pMvd[0]));
+ WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, listIdx, 1, pMvd[1]));
+ pMv[0] += pMvd[0];
+ pMv[1] += pMvd[1];
+ WELS_CHECK_SE_BOTH_WARNING (pMv[1], iMinVmv, iMaxVmv, "vertical mv");
+ } else {
+ * (uint32_t*)pMv = * (uint32_t*)pMvd = 0;
+ }
+ UpdateP16x8MotionInfo (pCurDqLayer, pMotionVector, pRefIndex, listIdx, iPartIdx, ref_idx, pMv);
+ UpdateP16x8MvdCabac (pCurDqLayer, pMvdCache, iPartIdx, pMvd, listIdx);
+ }
+ }
+ } else if (IS_INTER_8x16 (mbType)) {
+ int8_t ref_idx_list[LIST_A][2] = { { REF_NOT_IN_LIST, REF_NOT_IN_LIST }, { REF_NOT_IN_LIST, REF_NOT_IN_LIST } };
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ for (int32_t i = 0; i < 2; ++i) {
+ iPartIdx = i << 2;
+ int8_t ref_idx = REF_NOT_IN_LIST;
+ if (IS_DIR (mbType, i, listIdx)) {
+ WELS_READ_VERIFY (ParseRefIdxCabac (pCtx, pNeighAvail, pNonZeroCount, pRefIndex, pDirect, listIdx, iPartIdx,
+ pRefCount[listIdx], 0, ref_idx));
+ if ((ref_idx < 0) || (ref_idx >= pRefCount[listIdx])
+ || (pCtx->sRefPic.pRefList[listIdx][ref_idx] == NULL)) { //error ref_idx
+ pCtx->bMbRefConcealed = true;
+ if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) {
+ ref_idx = 0;
+ pCtx->iErrorCode |= dsBitstreamError;
+ } else {
+ return GENERATE_ERROR_NO (ERR_LEVEL_MB_DATA, ERR_INFO_INVALID_REF_INDEX);
+ }
+ }
+ pCtx->bMbRefConcealed = pCtx->bRPLRError || pCtx->bMbRefConcealed || ! (pCtx->sRefPic.pRefList[listIdx][ref_idx]
+ && pCtx->sRefPic.pRefList[listIdx][ref_idx]->bIsComplete);
+ }
+ UpdateP8x16RefIdxCabac (pCurDqLayer, pRefIndex, iPartIdx, ref_idx, listIdx);
+ ref_idx_list[listIdx][i] = ref_idx;
+ }
+ }
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ for (int32_t i = 0; i < 2; ++i) {
+ iPartIdx = i << 2;
+ int8_t ref_idx = ref_idx_list[listIdx][i];
+ if (IS_DIR (mbType, i, listIdx)) {
+ PredInter8x16Mv (pMotionVector, pRefIndex, listIdx, iPartIdx, ref_idx, pMv);
+ WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, listIdx, 0, pMvd[0]));
+ WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, listIdx, 1, pMvd[1]));
+ pMv[0] += pMvd[0];
+ pMv[1] += pMvd[1];
+ WELS_CHECK_SE_BOTH_WARNING (pMv[1], iMinVmv, iMaxVmv, "vertical mv");
+ } else {
+ * (uint32_t*)pMv = * (uint32_t*)pMvd = 0;
+ }
+ UpdateP8x16MotionInfo (pCurDqLayer, pMotionVector, pRefIndex, listIdx, iPartIdx, ref_idx, pMv);
+ UpdateP8x16MvdCabac (pCurDqLayer, pMvdCache, iPartIdx, pMvd, listIdx);
+ }
+ }
+ } else if (IS_Inter_8x8 (mbType)) {
+ int8_t pSubPartCount[4], pPartW[4];
+ uint32_t uiSubMbType;
+ //sub_mb_type, partition
+ int16_t pMvDirect[LIST_A][2] = { {0, 0}, {0, 0} };
+ bool has_direct_called = false;
+ SubMbType directSubMbType = 0;
+ for (int32_t i = 0; i < 4; i++) {
+ WELS_READ_VERIFY (ParseBSubMBTypeCabac (pCtx, pNeighAvail, uiSubMbType));
+ if (uiSubMbType > 13) { //invalid sub_mb_type
+ return GENERATE_ERROR_NO (ERR_LEVEL_MB_DATA, ERR_INFO_INVALID_SUB_MB_TYPE);
+ }
+// pCurDqLayer->pSubMbType[iMbXy][i] = g_ksInterBSubMbTypeInfo[uiSubMbType].iType;
+ pSubPartCount[i] = g_ksInterBSubMbTypeInfo[uiSubMbType].iPartCount;
+ pPartW[i] = g_ksInterBSubMbTypeInfo[uiSubMbType].iPartWidth;
+
+ // Need modification when B picture add in, reference to 7.3.5
+ if (pSubPartCount[i] > 1)
+ pCurDqLayer->pNoSubMbPartSizeLessThan8x8Flag[iMbXy] = false;
+
+ if (IS_DIRECT (g_ksInterBSubMbTypeInfo[uiSubMbType].iType)) {
+ if (!has_direct_called) {
+ if (pSliceHeader->iDirectSpatialMvPredFlag) {
+ directSubMbType = PredMvBDirectSpatial (pCtx, pMvDirect, iRef);
+ } else {
+ //temporal direct mode
+ ComputeColocated (pCtx);
+ PredBDirectTemporal (pCtx, pMvDirect, iRef);
+ }
+ has_direct_called = true;
+ }
+ pCurDqLayer->pSubMbType[iMbXy][i] = directSubMbType;
+ if (IS_SUB_4x4 (pCurDqLayer->pSubMbType[iMbXy][i])) {
+ pSubPartCount[i] = 4;
+ pPartW[i] = 1;
+ }
+ } else {
+ pCurDqLayer->pSubMbType[iMbXy][i] = g_ksInterBSubMbTypeInfo[uiSubMbType].iType;
+ }
+ }
+ for (int32_t i = 0; i < 4; i++) { //Direct 8x8 Ref and mv
+
+ int16_t iIdx8 = i << 2;
+ if (IS_DIRECT (pCurDqLayer->pSubMbType[iMbXy][i])) {
+
+ int8_t iPartCount = pSubPartCount[i];
+ int16_t iPartIdx, iBlockW = pPartW[i];
+ uint8_t iScan4Idx, iCacheIdx, iColocIdx;
+ iCacheIdx = g_kuiCache30ScanIdx[iIdx8];
+
+ if (!pSliceHeader->iDirectSpatialMvPredFlag) {
+ iRef[LIST_1] = 0;
+ if (pCurDqLayer->iColocIntra[g_kuiScan4[iIdx8]]) {
+ iRef[LIST_0] = 0;
+ } else {
+ if (pCurDqLayer->iColocRefIndex[LIST_0][iIdx8] >= 0) {
+ iRef[LIST_0] = pCurDqLayer->iColocRefIndex[LIST_0][iIdx8];
+ } else {
+ iRef[LIST_0] = pCurDqLayer->iColocRefIndex[LIST_1][iIdx8];
+ }
+ }
+ }
+ for (int32_t j = 0; j < iPartCount; j++) {
+ iPartIdx = iIdx8 + j * iBlockW;
+ iColocIdx = g_kuiScan4[iPartIdx];
+ iScan4Idx = g_kuiScan4[iPartIdx];
+ iCacheIdx = g_kuiCache30ScanIdx[iPartIdx];
+
+ if (pSliceHeader->iDirectSpatialMvPredFlag) {
+ int16_t pMV[4] = { 0 };
+ if (IS_SUB_8x8 (pCurDqLayer->pSubMbType[iMbXy][i])) {
+ * (uint32_t*)pMV = * (uint32_t*)pMvDirect[LIST_0];
+ ST32 ((pMV + 2), LD32 (pMV));
+ ST64 (pCurDqLayer->pMv[LIST_0][iMbXy][iScan4Idx], LD64 (pMV));
+ ST64 (pCurDqLayer->pMv[LIST_0][iMbXy][iScan4Idx + 4], LD64 (pMV));
+ ST64 (pCurDqLayer->pMvd[LIST_0][iMbXy][iScan4Idx], 0);
+ ST64 (pCurDqLayer->pMvd[LIST_0][iMbXy][iScan4Idx + 4], 0);
+ ST64 (pMotionVector[LIST_0][iCacheIdx], LD64 (pMV));
+ ST64 (pMotionVector[LIST_0][iCacheIdx + 6], LD64 (pMV));
+ ST64 (pMvdCache[LIST_0][iCacheIdx], 0);
+ ST64 (pMvdCache[LIST_0][iCacheIdx + 6], 0);
+ * (uint32_t*)pMV = * (uint32_t*)pMvDirect[LIST_1];
+ ST32 ((pMV + 2), LD32 (pMV));
+ ST64 (pCurDqLayer->pMv[LIST_1][iMbXy][iScan4Idx], LD64 (pMV));
+ ST64 (pCurDqLayer->pMv[LIST_1][iMbXy][iScan4Idx + 4], LD64 (pMV));
+ ST64 (pCurDqLayer->pMvd[LIST_1][iMbXy][iScan4Idx], 0);
+ ST64 (pCurDqLayer->pMvd[LIST_1][iMbXy][iScan4Idx + 4], 0);
+ ST64 (pMotionVector[LIST_1][iCacheIdx], LD64 (pMV));
+ ST64 (pMotionVector[LIST_1][iCacheIdx + 6], LD64 (pMV));
+ ST64 (pMvdCache[LIST_1][iCacheIdx], 0);
+ ST64 (pMvdCache[LIST_1][iCacheIdx + 6], 0);
+ } else { //SUB_4x4
+ * (uint32_t*)pMV = * (uint32_t*)pMvDirect[LIST_0];
+ ST32 (pCurDqLayer->pMv[LIST_0][iMbXy][iScan4Idx], LD32 (pMV));
+ ST32 (pCurDqLayer->pMvd[LIST_0][iMbXy][iScan4Idx], 0);
+ ST32 (pMotionVector[LIST_0][iCacheIdx], LD32 (pMV));
+ ST32 (pMvdCache[LIST_0][iCacheIdx], 0);
+ * (uint32_t*)pMV = * (uint32_t*)pMvDirect[LIST_1];
+ ST32 (pCurDqLayer->pMv[LIST_1][iMbXy][iScan4Idx], LD32 (pMV));
+ ST32 (pCurDqLayer->pMvd[LIST_1][iMbXy][iScan4Idx], 0);
+ ST32 (pMotionVector[LIST_1][iCacheIdx], LD32 (pMV));
+ ST32 (pMvdCache[LIST_1][iCacheIdx], 0);
+ }
+
+ if ((* (int32_t*)pMvDirect[LIST_0] | * (int32_t*)pMvDirect[LIST_1])) {
+ bool bIsLongRef = pCtx->sRefPic.pRefList[LIST_1][0]->bIsLongRef;
+ uint32_t uiColZeroFlag = (0 == pCurDqLayer->iColocIntra[iColocIdx]) && !bIsLongRef &&
+ (pCurDqLayer->iColocRefIndex[LIST_0][iColocIdx] == 0 || (pCurDqLayer->iColocRefIndex[LIST_0][iColocIdx] < 0
+ && pCurDqLayer->iColocRefIndex[LIST_1][iColocIdx] == 0));
+ const int16_t (*mvColoc)[2] = pCurDqLayer->iColocRefIndex[LIST_0][iColocIdx] == 0 ? pCurDqLayer->iColocMv[LIST_0] :
+ pCurDqLayer->iColocMv[LIST_1];
+ const int16_t* mv = mvColoc[iColocIdx];
+ if (IS_SUB_8x8 (pCurDqLayer->pSubMbType[iMbXy][i])) {
+ if (uiColZeroFlag && ((unsigned) (mv[0] + 1) <= 2 && (unsigned) (mv[1] + 1) <= 2)) {
+ if (iRef[LIST_0] == 0) {
+ ST64 (pCurDqLayer->pMv[LIST_0][iMbXy][iScan4Idx], 0);
+ ST64 (pCurDqLayer->pMv[LIST_0][iMbXy][iScan4Idx + 4], 0);
+ ST64 (pCurDqLayer->pMvd[LIST_0][iMbXy][iScan4Idx], 0);
+ ST64 (pCurDqLayer->pMvd[LIST_0][iMbXy][iScan4Idx + 4], 0);
+ ST64 (pMotionVector[LIST_0][iCacheIdx], 0);
+ ST64 (pMotionVector[LIST_0][iCacheIdx + 6], 0);
+ ST64 (pMvdCache[LIST_0][iCacheIdx], 0);
+ ST64 (pMvdCache[LIST_0][iCacheIdx + 6], 0);
+ }
+
+ if (iRef[LIST_1] == 0) {
+ ST64 (pCurDqLayer->pMv[LIST_1][iMbXy][iScan4Idx], 0);
+ ST64 (pCurDqLayer->pMv[LIST_1][iMbXy][iScan4Idx + 4], 0);
+ ST64 (pCurDqLayer->pMvd[LIST_1][iMbXy][iScan4Idx], 0);
+ ST64 (pCurDqLayer->pMvd[LIST_1][iMbXy][iScan4Idx + 4], 0);
+ ST64 (pMotionVector[LIST_1][iCacheIdx], 0);
+ ST64 (pMotionVector[LIST_1][iCacheIdx + 6], 0);
+ ST64 (pMvdCache[LIST_1][iCacheIdx], 0);
+ ST64 (pMvdCache[LIST_1][iCacheIdx + 6], 0);
+ }
+ }
+ } else {
+ if (uiColZeroFlag && ((unsigned) (mv[0] + 1) <= 2 && (unsigned) (mv[1] + 1) <= 2)) {
+ if (iRef[LIST_0] == 0) {
+ ST32 (pCurDqLayer->pMv[LIST_0][iMbXy][iScan4Idx], 0);
+ ST32 (pCurDqLayer->pMvd[LIST_0][iMbXy][iScan4Idx], 0);
+ ST32 (pMotionVector[LIST_0][iCacheIdx], 0);
+ ST32 (pMvdCache[LIST_0][iCacheIdx], 0);
+ }
+ if (iRef[LIST_1] == 0) {
+ ST32 (pCurDqLayer->pMv[LIST_1][iMbXy][iScan4Idx], 0);
+ ST32 (pCurDqLayer->pMvd[LIST_1][iMbXy][iScan4Idx], 0);
+ ST32 (pMotionVector[LIST_1][iCacheIdx], 0);
+ ST32 (pMvdCache[LIST_1][iCacheIdx], 0);
+ }
+ }
+ }
+ }
+ } else {
+ int16_t (*mvColoc)[2] = pCurDqLayer->iColocMv[LIST_0];
+ int16_t* mv = mvColoc[iColocIdx];
+ int16_t pMV[4] = { 0 };
+ int16_t iMvp[LIST_A][2];
+ if (IS_SUB_8x8 (pCurDqLayer->pSubMbType[iMbXy][i])) {
+ iMvp[LIST_0][0] = (pSlice->iMvScale[LIST_0][iRef[LIST_0]] * mv[0] + 128) >> 8;
+ iMvp[LIST_0][1] = (pSlice->iMvScale[LIST_0][iRef[LIST_0]] * mv[1] + 128) >> 8;
+ ST32 (pMV, LD32 (iMvp[LIST_0]));
+ ST32 ((pMV + 2), LD32 (iMvp[LIST_0]));
+ ST64 (pCurDqLayer->pMv[LIST_0][iMbXy][iScan4Idx], LD64 (pMV));
+ ST64 (pCurDqLayer->pMv[LIST_0][iMbXy][iScan4Idx + 4], LD64 (pMV));
+ ST64 (pCurDqLayer->pMvd[LIST_0][iMbXy][iScan4Idx], 0);
+ ST64 (pCurDqLayer->pMvd[LIST_0][iMbXy][iScan4Idx + 4], 0);
+ iMvp[LIST_1][0] -= iMvp[LIST_0][0] - mv[0];
+ iMvp[LIST_1][1] -= iMvp[LIST_0][0] - mv[1];
+ ST32 (pMV, LD32 (iMvp[LIST_1]));
+ ST32 ((pMV + 2), LD32 (iMvp[LIST_1]));
+ ST64 (pCurDqLayer->pMv[LIST_1][iMbXy][iScan4Idx], LD64 (pMV));
+ ST64 (pCurDqLayer->pMv[LIST_1][iMbXy][iScan4Idx + 4], LD64 (pMV));
+ ST64 (pCurDqLayer->pMvd[LIST_1][iMbXy][iScan4Idx], 0);
+ ST64 (pCurDqLayer->pMvd[LIST_1][iMbXy][iScan4Idx + 4], 0);
+ } else { //SUB_4x4
+ iMvp[LIST_0][0] = (pSlice->iMvScale[LIST_0][iRef[LIST_0]] * mv[0] + 128) >> 8;
+ iMvp[LIST_0][1] = (pSlice->iMvScale[LIST_0][iRef[LIST_0]] * mv[1] + 128) >> 8;
+ ST32 (pCurDqLayer->pMv[LIST_0][iMbXy][iScan4Idx], LD32 (iMvp[LIST_0]));
+ ST32 (pCurDqLayer->pMvd[LIST_0][iMbXy][iScan4Idx], 0);
+ iMvp[LIST_1][0] -= iMvp[LIST_0][0] - mv[0];
+ iMvp[LIST_1][1] -= iMvp[LIST_0][0] - mv[1];
+ ST32 (pCurDqLayer->pMv[LIST_1][iMbXy][iScan4Idx], LD32 (iMvp[LIST_1]));
+ ST32 (pCurDqLayer->pMvd[LIST_1][iMbXy][iScan4Idx], 0);
+ }
+ }
+ }
+ }
+ }
+ //ref no-direct
+ int8_t ref_idx_list[LIST_A][4] = { {REF_NOT_IN_LIST, REF_NOT_IN_LIST}, { REF_NOT_IN_LIST, REF_NOT_IN_LIST } };
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ for (int32_t i = 0; i < 4; i++) {
+ int16_t iIdx8 = i << 2;
+ int32_t subMbType = pCurDqLayer->pSubMbType[iMbXy][i];
+ int8_t iref = REF_NOT_IN_LIST;
+ if (IS_DIRECT (subMbType)) {
+ if (pSliceHeader->iDirectSpatialMvPredFlag) {
+ iref = iRef[listIdx];
+ } else {
+ iref = 0;
+ if (listIdx == LIST_0) {
+ if (!pCurDqLayer->iColocIntra[g_kuiScan4[iIdx8]]) {
+ if (pCurDqLayer->iColocRefIndex[LIST_0][iIdx8] >= 0) {
+ iref = pCurDqLayer->iColocRefIndex[LIST_0][iIdx8];
+ } else {
+ iref = pCurDqLayer->iColocRefIndex[LIST_1][iIdx8];
+ }
+ }
+ }
+ }
+ UpdateP8x8DirectCabac (pCurDqLayer, iIdx8);
+ } else {
+ if (IS_DIR (subMbType, 0, listIdx)) {
+ WELS_READ_VERIFY (ParseRefIdxCabac (pCtx, pNeighAvail, pNonZeroCount, pRefIndex, pDirect, listIdx, iIdx8,
+ pRefCount[listIdx], 1,
+ iref));
+ if ((iref < 0) || (iref >= pRefCount[listIdx]) || (pCtx->sRefPic.pRefList[listIdx][iref] == NULL)) { //error ref_idx
+ pCtx->bMbRefConcealed = true;
+ if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) {
+ iref = 0;
+ pCtx->iErrorCode |= dsBitstreamError;
+ } else {
+ return GENERATE_ERROR_NO (ERR_LEVEL_MB_DATA, ERR_INFO_INVALID_REF_INDEX);
+ }
+ }
+ pCtx->bMbRefConcealed = pCtx->bRPLRError || pCtx->bMbRefConcealed || ! (pCtx->sRefPic.pRefList[listIdx][iref]
+ && pCtx->sRefPic.pRefList[listIdx][iref]->bIsComplete);
+ }
+ }
+ UpdateP8x8RefIdxCabac (pCurDqLayer, pRefIndex, iIdx8, iref, listIdx);
+ ref_idx_list[listIdx][i] = iref;
+ }
+ }
+ //mv
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ for (int32_t i = 0; i < 4; i++) {
+ int8_t iPartCount = pSubPartCount[i];
+ int16_t iPartIdx, iBlockW = pPartW[i];
+ uint8_t iScan4Idx, iCacheIdx;
+
+ iCacheIdx = g_kuiCache30ScanIdx[i << 2];
+
+ int8_t iref = ref_idx_list[listIdx][i];
+ pRefIndex[listIdx][iCacheIdx] = pRefIndex[listIdx][iCacheIdx + 1]
+ = pRefIndex[listIdx][iCacheIdx + 6] = pRefIndex[listIdx][iCacheIdx + 7] = iref;
+
+ uint32_t subMbType = pCurDqLayer->pSubMbType[iMbXy][i];
+ if (IS_DIRECT (subMbType)) {
+ continue;
+ }
+ bool is_dir = IS_DIR (subMbType, 0, listIdx) > 0;
+ for (int32_t j = 0; j < iPartCount; j++) {
+ iPartIdx = (i << 2) + j * iBlockW;
+ iScan4Idx = g_kuiScan4[iPartIdx];
+ iCacheIdx = g_kuiCache30ScanIdx[iPartIdx];
+ if (is_dir) {
+ PredMv (pMotionVector, pRefIndex, listIdx, iPartIdx, iBlockW, iref, pMv);
+ WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, listIdx, 0, pMvd[0]));
+ WELS_READ_VERIFY (ParseMvdInfoCabac (pCtx, pNeighAvail, pRefIndex, pMvdCache, iPartIdx, listIdx, 1, pMvd[1]));
+ pMv[0] += pMvd[0];
+ pMv[1] += pMvd[1];
+ WELS_CHECK_SE_BOTH_WARNING (pMv[1], iMinVmv, iMaxVmv, "vertical mv");
+ } else {
+ * (uint32_t*)pMv = * (uint32_t*)pMvd = 0;
+ }
+ if (IS_SUB_8x8 (subMbType)) { //MB_TYPE_8x8
+ ST32 ((pMv + 2), LD32 (pMv));
+ ST32 ((pMvd + 2), LD32 (pMvd));
+ ST64 (pCurDqLayer->pMv[listIdx][iMbXy][iScan4Idx], LD64 (pMv));
+ ST64 (pCurDqLayer->pMv[listIdx][iMbXy][iScan4Idx + 4], LD64 (pMv));
+ ST64 (pCurDqLayer->pMvd[listIdx][iMbXy][iScan4Idx], LD64 (pMvd));
+ ST64 (pCurDqLayer->pMvd[listIdx][iMbXy][iScan4Idx + 4], LD64 (pMvd));
+ ST64 (pMotionVector[listIdx][iCacheIdx], LD64 (pMv));
+ ST64 (pMotionVector[listIdx][iCacheIdx + 6], LD64 (pMv));
+ ST64 (pMvdCache[listIdx][iCacheIdx], LD64 (pMvd));
+ ST64 (pMvdCache[listIdx][iCacheIdx + 6], LD64 (pMvd));
+ } else if (IS_SUB_4x4 (subMbType)) { //MB_TYPE_4x4
+ ST32 (pCurDqLayer->pMv[listIdx][iMbXy][iScan4Idx], LD32 (pMv));
+ ST32 (pCurDqLayer->pMvd[listIdx][iMbXy][iScan4Idx], LD32 (pMvd));
+ ST32 (pMotionVector[listIdx][iCacheIdx], LD32 (pMv));
+ ST32 (pMvdCache[listIdx][iCacheIdx], LD32 (pMvd));
+ } else if (IS_SUB_4x8 (subMbType)) { //MB_TYPE_4x8 5, 7, 9
+ ST32 (pCurDqLayer->pMv[listIdx][iMbXy][iScan4Idx], LD32 (pMv));
+ ST32 (pCurDqLayer->pMv[listIdx][iMbXy][iScan4Idx + 4], LD32 (pMv));
+ ST32 (pCurDqLayer->pMvd[listIdx][iMbXy][iScan4Idx], LD32 (pMvd));
+ ST32 (pCurDqLayer->pMvd[listIdx][iMbXy][iScan4Idx + 4], LD32 (pMvd));
+ ST32 (pMotionVector[listIdx][iCacheIdx], LD32 (pMv));
+ ST32 (pMotionVector[listIdx][iCacheIdx + 6], LD32 (pMv));
+ ST32 (pMvdCache[listIdx][iCacheIdx], LD32 (pMvd));
+ ST32 (pMvdCache[listIdx][iCacheIdx + 6], LD32 (pMvd));
+ } else { //MB_TYPE_8x4 4, 6, 8
+ ST32 ((pMv + 2), LD32 (pMv));
+ ST32 ((pMvd + 2), LD32 (pMvd));
+ ST64 (pCurDqLayer->pMv[listIdx][iMbXy][iScan4Idx], LD64 (pMv));
+ ST64 (pCurDqLayer->pMvd[listIdx][iMbXy][iScan4Idx], LD64 (pMvd));
+ ST64 (pMotionVector[listIdx][iCacheIdx], LD64 (pMv));
+ ST64 (pMvdCache[listIdx][iCacheIdx], LD64 (pMvd));
+ }
+ }
+ }
+ }
+ }
+ return ERR_NONE;
+}
+
+int32_t ParseRefIdxCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint8_t* nzc,
+ int8_t ref_idx[LIST_A][30], int8_t direct[30],
+ int32_t iListIdx, int32_t iZOrderIdx, int32_t iActiveRefNum, int32_t b8mode, int8_t& iRefIdxVal) {
+ if (iActiveRefNum == 1) {
+ iRefIdxVal = 0;
+ return ERR_NONE;
+ }
+ uint32_t uiCode;
+ int32_t iIdxA = 0, iIdxB = 0;
+ int32_t iCtxInc = 0;
+ int8_t* pRefIdxInMB = pCtx->pCurDqLayer->pRefIndex[iListIdx][pCtx->pCurDqLayer->iMbXyIndex];
+ int8_t* pDirect = pCtx->pCurDqLayer->pDirect[pCtx->pCurDqLayer->iMbXyIndex];
+ if (iZOrderIdx == 0) {
+ iIdxB = (pNeighAvail->iTopAvail && pNeighAvail->iTopType != MB_TYPE_INTRA_PCM
+ && ref_idx[iListIdx][g_kuiCache30ScanIdx[iZOrderIdx] - 6] > 0);
+ iIdxA = (pNeighAvail->iLeftAvail && pNeighAvail->iLeftType != MB_TYPE_INTRA_PCM
+ && ref_idx[iListIdx][g_kuiCache30ScanIdx[iZOrderIdx] - 1] > 0);
+ if (pCtx->eSliceType == B_SLICE) {
+ if (iIdxB > 0 && direct[g_kuiCache30ScanIdx[iZOrderIdx] - 6] == 0) {
+ iCtxInc += 2;
+ }
+ if (iIdxA > 0 && direct[g_kuiCache30ScanIdx[iZOrderIdx] - 1] == 0) {
+ iCtxInc++;
+ }
+ }
+ } else if (iZOrderIdx == 4) {
+ iIdxB = (pNeighAvail->iTopAvail && pNeighAvail->iTopType != MB_TYPE_INTRA_PCM
+ && ref_idx[iListIdx][g_kuiCache30ScanIdx[iZOrderIdx] - 6] > 0);
+ iIdxA = pRefIdxInMB[g_kuiScan4[iZOrderIdx] - 1] > 0;
+ if (pCtx->eSliceType == B_SLICE) {
+ if (iIdxB > 0 && direct[g_kuiCache30ScanIdx[iZOrderIdx] - 6] == 0) {
+ iCtxInc += 2;
+ }
+ if (iIdxA > 0 && pDirect[g_kuiScan4[iZOrderIdx] - 1] == 0) {
+ iCtxInc ++;
+ }
+ }
+ } else if (iZOrderIdx == 8) {
+
+ iIdxB = pRefIdxInMB[g_kuiScan4[iZOrderIdx] - 4] > 0;
+ iIdxA = (pNeighAvail->iLeftAvail && pNeighAvail->iLeftType != MB_TYPE_INTRA_PCM
+ && ref_idx[iListIdx][g_kuiCache30ScanIdx[iZOrderIdx] - 1] > 0);
+ if (pCtx->eSliceType == B_SLICE) {
+ if (iIdxB > 0 && pDirect[g_kuiScan4[iZOrderIdx] - 4] == 0) {
+ iCtxInc += 2;
+ }
+ if (iIdxA > 0 && direct[g_kuiCache30ScanIdx[iZOrderIdx] - 1] == 0) {
+ iCtxInc++;
+ }
+ }
+ } else {
+ iIdxB = pRefIdxInMB[g_kuiScan4[iZOrderIdx] - 4] > 0;
+ iIdxA = pRefIdxInMB[g_kuiScan4[iZOrderIdx] - 1] > 0;
+ if (pCtx->eSliceType == B_SLICE) {
+ if (iIdxB > 0 && pDirect[g_kuiScan4[iZOrderIdx] - 4] == 0) {
+ iCtxInc += 2;
+ }
+ if (iIdxA > 0 && pDirect[g_kuiScan4[iZOrderIdx] - 1] == 0) {
+ iCtxInc++;
+ }
+ }
+ }
+ if (pCtx->eSliceType != B_SLICE) {
+ iCtxInc = iIdxA + (iIdxB << 1);
+ }
+
+ WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_REF_NO + iCtxInc, uiCode));
+ if (uiCode) {
+ WELS_READ_VERIFY (DecodeUnaryBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_REF_NO + 4, 1, uiCode));
+ ++uiCode;
+ }
+ iRefIdxVal = (int8_t) uiCode;
+ return ERR_NONE;
+}
+
+int32_t ParseMvdInfoCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, int8_t pRefIndex[LIST_A][30],
+ int16_t pMvdCache[LIST_A][30][2], int32_t index, int8_t iListIdx, int8_t iMvComp, int16_t& iMvdVal) {
+ uint32_t uiCode;
+ int32_t iIdxA = 0;
+ //int32_t sym;
+ PWelsCabacCtx pBinCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_MVD + iMvComp * CTX_NUM_MVD;
+ iMvdVal = 0;
+
+ if (pRefIndex[iListIdx][g_kuiCache30ScanIdx[index] - 6] >= 0)
+ iIdxA = WELS_ABS (pMvdCache[iListIdx][g_kuiCache30ScanIdx[index] - 6][iMvComp]);
+ if (pRefIndex[iListIdx][g_kuiCache30ScanIdx[index] - 1] >= 0)
+ iIdxA += WELS_ABS (pMvdCache[iListIdx][g_kuiCache30ScanIdx[index] - 1][iMvComp]);
+
+ int32_t iCtxInc = 0;
+ if (iIdxA >= 3)
+ iCtxInc = 1 + (iIdxA > 32);
+
+ WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pBinCtx + iCtxInc, uiCode));
+ if (uiCode) {
+ WELS_READ_VERIFY (DecodeUEGMvCabac (pCtx->pCabacDecEngine, pBinCtx + 3, 3, uiCode));
+ iMvdVal = (int16_t) (uiCode + 1);
+ WELS_READ_VERIFY (DecodeBypassCabac (pCtx->pCabacDecEngine, uiCode));
+ if (uiCode) {
+ iMvdVal = -iMvdVal;
+ }
+ } else {
+ iMvdVal = 0;
+ }
+ return ERR_NONE;
+}
+
+int32_t ParseCbpInfoCabac (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, uint32_t& uiCbp) {
+ int32_t iIdxA = 0, iIdxB = 0, pALeftMb[2], pBTopMb[2];
+ uiCbp = 0;
+ uint32_t pCbpBit[6];
+ int32_t iCtxInc;
+
+ //Luma: bit by bit for 4 8x8 blocks in z-order
+ pBTopMb[0] = pNeighAvail->iTopAvail && pNeighAvail->iTopType != MB_TYPE_INTRA_PCM
+ && ((pNeighAvail->iTopCbp & (1 << 2)) == 0);
+ pBTopMb[1] = pNeighAvail->iTopAvail && pNeighAvail->iTopType != MB_TYPE_INTRA_PCM
+ && ((pNeighAvail->iTopCbp & (1 << 3)) == 0);
+ pALeftMb[0] = pNeighAvail->iLeftAvail && pNeighAvail->iLeftType != MB_TYPE_INTRA_PCM
+ && ((pNeighAvail->iLeftCbp & (1 << 1)) == 0);
+ pALeftMb[1] = pNeighAvail->iLeftAvail && pNeighAvail->iLeftType != MB_TYPE_INTRA_PCM
+ && ((pNeighAvail->iLeftCbp & (1 << 3)) == 0);
+
+ //left_top 8x8 block
+ iCtxInc = pALeftMb[0] + (pBTopMb[0] << 1);
+ WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CBP + iCtxInc, pCbpBit[0]));
+ if (pCbpBit[0])
+ uiCbp += 0x01;
+
+ //right_top 8x8 block
+ iIdxA = !pCbpBit[0];
+ iCtxInc = iIdxA + (pBTopMb[1] << 1);
+ WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CBP + iCtxInc, pCbpBit[1]));
+ if (pCbpBit[1])
+ uiCbp += 0x02;
+
+ //left_bottom 8x8 block
+ iIdxB = !pCbpBit[0];
+ iCtxInc = pALeftMb[1] + (iIdxB << 1);
+ WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CBP + iCtxInc, pCbpBit[2]));
+ if (pCbpBit[2])
+ uiCbp += 0x04;
+
+ //right_bottom 8x8 block
+ iIdxB = !pCbpBit[1];
+ iIdxA = !pCbpBit[2];
+ iCtxInc = iIdxA + (iIdxB << 1);
+ WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CBP + iCtxInc, pCbpBit[3]));
+ if (pCbpBit[3])
+ uiCbp += 0x08;
+
+ if (pCtx->pSps->uiChromaFormatIdc == 0)//monochroma
+ return ERR_NONE;
+
+
+ //Chroma: bit by bit
+ iIdxB = pNeighAvail->iTopAvail && (pNeighAvail->iTopType == MB_TYPE_INTRA_PCM || (pNeighAvail->iTopCbp >> 4));
+ iIdxA = pNeighAvail->iLeftAvail && (pNeighAvail->iLeftType == MB_TYPE_INTRA_PCM || (pNeighAvail->iLeftCbp >> 4));
+
+ //BitIdx = 0
+ iCtxInc = iIdxA + (iIdxB << 1);
+ WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pCtx->pCabacCtx + NEW_CTX_OFFSET_CBP + CTX_NUM_CBP + iCtxInc,
+ pCbpBit[4]));
+
+ //BitIdx = 1
+ if (pCbpBit[4]) {
+ iIdxB = pNeighAvail->iTopAvail && (pNeighAvail->iTopType == MB_TYPE_INTRA_PCM || (pNeighAvail->iTopCbp >> 4) == 2);
+ iIdxA = pNeighAvail->iLeftAvail && (pNeighAvail->iLeftType == MB_TYPE_INTRA_PCM || (pNeighAvail->iLeftCbp >> 4) == 2);
+ iCtxInc = iIdxA + (iIdxB << 1);
+ WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine,
+ pCtx->pCabacCtx + NEW_CTX_OFFSET_CBP + 2 * CTX_NUM_CBP + iCtxInc,
+ pCbpBit[5]));
+ uiCbp += 1 << (4 + pCbpBit[5]);
+
+ }
+
+ return ERR_NONE;
+}
+
+int32_t ParseDeltaQpCabac (PWelsDecoderContext pCtx, int32_t& iQpDelta) {
+ uint32_t uiCode;
+ PSlice pCurrSlice = & (pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer);
+ iQpDelta = 0;
+ PWelsCabacCtx pBinCtx = pCtx->pCabacCtx + NEW_CTX_OFFSET_DELTA_QP;
+ int32_t iCtxInc = (pCurrSlice->iLastDeltaQp != 0);
+ WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pBinCtx + iCtxInc, uiCode));
+ if (uiCode != 0) {
+ WELS_READ_VERIFY (DecodeUnaryBinCabac (pCtx->pCabacDecEngine, pBinCtx + 2, 1, uiCode));
+ uiCode++;
+ iQpDelta = (uiCode + 1) >> 1;
+ if ((uiCode & 1) == 0)
+ iQpDelta = - iQpDelta;
+ }
+ pCurrSlice->iLastDeltaQp = iQpDelta;
+ return ERR_NONE;
+}
+
+int32_t ParseCbfInfoCabac (PWelsNeighAvail pNeighAvail, uint8_t* pNzcCache, int32_t iZIndex, int32_t iResProperty,
+ PWelsDecoderContext pCtx, uint32_t& uiCbfBit) {
+ int8_t nA, nB/*, zigzag_idx = 0*/;
+ int32_t iCurrBlkXy = pCtx->pCurDqLayer->iMbXyIndex;
+ int32_t iTopBlkXy = iCurrBlkXy - pCtx->pCurDqLayer->iMbWidth; //default value: MB neighboring
+ int32_t iLeftBlkXy = iCurrBlkXy - 1; //default value: MB neighboring
+ uint16_t* pCbfDc = pCtx->pCurDqLayer->pCbfDc;
+ uint32_t* pMbType = pCtx->pCurDqLayer->pMbType;
+ int32_t iCtxInc;
+ uiCbfBit = 0;
+ nA = nB = (int8_t)!!IS_INTRA (pMbType[iCurrBlkXy]);
+
+ if (iResProperty == I16_LUMA_DC || iResProperty == CHROMA_DC_U || iResProperty == CHROMA_DC_V) { //DC
+ if (pNeighAvail->iTopAvail)
+ nB = (pMbType[iTopBlkXy] == MB_TYPE_INTRA_PCM) || ((pCbfDc[iTopBlkXy] >> iResProperty) & 1);
+ if (pNeighAvail->iLeftAvail)
+ nA = (pMbType[iLeftBlkXy] == MB_TYPE_INTRA_PCM) || ((pCbfDc[iLeftBlkXy] >> iResProperty) & 1);
+ iCtxInc = nA + (nB << 1);
+ WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine,
+ pCtx->pCabacCtx + NEW_CTX_OFFSET_CBF + g_kBlockCat2CtxOffsetCBF[iResProperty] + iCtxInc, uiCbfBit));
+ if (uiCbfBit)
+ pCbfDc[iCurrBlkXy] |= (1 << iResProperty);
+ } else { //AC
+ //for 4x4 blk, make sure blk-idx is correct
+ if (pNzcCache[g_kCacheNzcScanIdx[iZIndex] - 8] != 0xff) { //top blk available
+ if (g_kTopBlkInsideMb[iZIndex])
+ iTopBlkXy = iCurrBlkXy;
+ nB = pNzcCache[g_kCacheNzcScanIdx[iZIndex] - 8] || pMbType[iTopBlkXy] == MB_TYPE_INTRA_PCM;
+ }
+ if (pNzcCache[g_kCacheNzcScanIdx[iZIndex] - 1] != 0xff) { //left blk available
+ if (g_kLeftBlkInsideMb[iZIndex])
+ iLeftBlkXy = iCurrBlkXy;
+ nA = pNzcCache[g_kCacheNzcScanIdx[iZIndex] - 1] || pMbType[iLeftBlkXy] == MB_TYPE_INTRA_PCM;
+ }
+
+ iCtxInc = nA + (nB << 1);
+ WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine,
+ pCtx->pCabacCtx + NEW_CTX_OFFSET_CBF + g_kBlockCat2CtxOffsetCBF[iResProperty] + iCtxInc, uiCbfBit));
+ }
+ return ERR_NONE;
+}
+
+int32_t ParseSignificantMapCabac (int32_t* pSignificantMap, int32_t iResProperty, PWelsDecoderContext pCtx,
+ uint32_t& uiCoeffNum) {
+ uint32_t uiCode;
+
+ PWelsCabacCtx pMapCtx = pCtx->pCabacCtx + (iResProperty == LUMA_DC_AC_8 ? NEW_CTX_OFFSET_MAP_8x8 : NEW_CTX_OFFSET_MAP)
+ + g_kBlockCat2CtxOffsetMap [iResProperty];
+ PWelsCabacCtx pLastCtx = pCtx->pCabacCtx + (iResProperty == LUMA_DC_AC_8 ? NEW_CTX_OFFSET_LAST_8x8 :
+ NEW_CTX_OFFSET_LAST) + g_kBlockCat2CtxOffsetLast[iResProperty];
+
+
+ int32_t i;
+ uiCoeffNum = 0;
+ int32_t i0 = 0;
+ int32_t i1 = g_kMaxPos[iResProperty];
+
+ int32_t iCtx;
+
+ for (i = i0; i < i1; ++i) {
+ iCtx = (iResProperty == LUMA_DC_AC_8 ? g_kuiIdx2CtxSignificantCoeffFlag8x8[i] : i);
+ //read significant
+ WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pMapCtx + iCtx, uiCode));
+ if (uiCode) {
+ * (pSignificantMap++) = 1;
+ ++ uiCoeffNum;
+ //read last significant
+ iCtx = (iResProperty == LUMA_DC_AC_8 ? g_kuiIdx2CtxLastSignificantCoeffFlag8x8[i] : i);
+ WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pLastCtx + iCtx, uiCode));
+ if (uiCode) {
+ memset (pSignificantMap, 0, (i1 - i) * sizeof (int32_t));
+ return ERR_NONE;
+ }
+ } else
+ * (pSignificantMap++) = 0;
+ }
+
+ //deal with last pSignificantMap if no data
+ //if(i < i1+1)
+ {
+ *pSignificantMap = 1;
+ ++uiCoeffNum;
+ }
+
+ return ERR_NONE;
+}
+
+int32_t ParseSignificantCoeffCabac (int32_t* pSignificant, int32_t iResProperty, PWelsDecoderContext pCtx) {
+ uint32_t uiCode;
+ PWelsCabacCtx pOneCtx = pCtx->pCabacCtx + (iResProperty == LUMA_DC_AC_8 ? NEW_CTX_OFFSET_ONE_8x8 : NEW_CTX_OFFSET_ONE) +
+ g_kBlockCat2CtxOffsetOne[iResProperty];
+ PWelsCabacCtx pAbsCtx = pCtx->pCabacCtx + (iResProperty == LUMA_DC_AC_8 ? NEW_CTX_OFFSET_ABS_8x8 : NEW_CTX_OFFSET_ABS) +
+ g_kBlockCat2CtxOffsetAbs[iResProperty];
+
+ const int16_t iMaxType = g_kMaxC2[iResProperty];
+ int32_t i = g_kMaxPos[iResProperty];
+ int32_t* pCoff = pSignificant + i;
+ int32_t c1 = 1;
+ int32_t c2 = 0;
+ for (; i >= 0; --i) {
+ if (*pCoff != 0) {
+ WELS_READ_VERIFY (DecodeBinCabac (pCtx->pCabacDecEngine, pOneCtx + c1, uiCode));
+ *pCoff += uiCode;
+ if (*pCoff == 2) {
+ WELS_READ_VERIFY (DecodeUEGLevelCabac (pCtx->pCabacDecEngine, pAbsCtx + c2, uiCode));
+ *pCoff += uiCode;
+ ++c2;
+ c2 = WELS_MIN (c2, iMaxType);
+ c1 = 0;
+ } else if (c1) {
+ ++c1;
+ c1 = WELS_MIN (c1, 4);
+ }
+ WELS_READ_VERIFY (DecodeBypassCabac (pCtx->pCabacDecEngine, uiCode));
+ if (uiCode)
+ *pCoff = - *pCoff;
+ }
+ pCoff--;
+ }
+ return ERR_NONE;
+}
+
+int32_t ParseResidualBlockCabac8x8 (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCountCache, SBitStringAux* pBsAux,
+ int32_t iIndex, int32_t iMaxNumCoeff, const uint8_t* pScanTable, int32_t iResProperty,
+ short* sTCoeff, /*int mb_mode*/ uint8_t uiQp, PWelsDecoderContext pCtx) {
+ uint32_t uiTotalCoeffNum = 0;
+ uint32_t uiCbpBit;
+ int32_t pSignificantMap[64] = {0};
+
+ int32_t iMbResProperty = 0;
+ GetMbResProperty (&iMbResProperty, &iResProperty, false);
+ const uint16_t* pDeQuantMul = (pCtx->bUseScalingList) ? pCtx->pDequant_coeff8x8[iMbResProperty - 6][uiQp] :
+ g_kuiDequantCoeff8x8[uiQp];
+
+ uiCbpBit = 1; // for 8x8, MaxNumCoeff == 64 && uiCbpBit == 1
+ if (uiCbpBit) { //has coeff
+ WELS_READ_VERIFY (ParseSignificantMapCabac (pSignificantMap, iResProperty, pCtx, uiTotalCoeffNum));
+ WELS_READ_VERIFY (ParseSignificantCoeffCabac (pSignificantMap, iResProperty, pCtx));
+ }
+
+ pNonZeroCountCache[g_kCacheNzcScanIdx[iIndex]] =
+ pNonZeroCountCache[g_kCacheNzcScanIdx[iIndex + 1]] =
+ pNonZeroCountCache[g_kCacheNzcScanIdx[iIndex + 2]] =
+ pNonZeroCountCache[g_kCacheNzcScanIdx[iIndex + 3]] = (uint8_t)uiTotalCoeffNum;
+ if (uiTotalCoeffNum == 0) {
+ return ERR_NONE;
+ }
+ int32_t j = 0, i;
+ if (iResProperty == LUMA_DC_AC_8) {
+ do {
+ if (pSignificantMap[j] != 0) {
+ i = pScanTable[ j ];
+ sTCoeff[i] = uiQp >= 36 ? ((pSignificantMap[j] * pDeQuantMul[i]) * (1 << (uiQp / 6 - 6))) : ((
+ pSignificantMap[j] * pDeQuantMul[i] + (1 << (5 - uiQp / 6))) >> (6 - uiQp / 6));
+ }
+ ++j;
+ } while (j < 64);
+ }
+
+ return ERR_NONE;
+}
+
+int32_t ParseResidualBlockCabac (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroCountCache, SBitStringAux* pBsAux,
+ int32_t iIndex, int32_t iMaxNumCoeff,
+ const uint8_t* pScanTable, int32_t iResProperty, short* sTCoeff, /*int mb_mode*/ uint8_t uiQp,
+ PWelsDecoderContext pCtx) {
+ int32_t iCurNzCacheIdx;
+ uint32_t uiTotalCoeffNum = 0;
+ uint32_t uiCbpBit;
+ int32_t pSignificantMap[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+ int32_t iMbResProperty = 0;
+ GetMbResProperty (&iMbResProperty, &iResProperty, false);
+ const uint16_t* pDeQuantMul = (pCtx->bUseScalingList) ? pCtx->pDequant_coeff4x4[iMbResProperty][uiQp] :
+ g_kuiDequantCoeff[uiQp];
+
+ WELS_READ_VERIFY (ParseCbfInfoCabac (pNeighAvail, pNonZeroCountCache, iIndex, iResProperty, pCtx, uiCbpBit));
+ if (uiCbpBit) { //has coeff
+ WELS_READ_VERIFY (ParseSignificantMapCabac (pSignificantMap, iResProperty, pCtx, uiTotalCoeffNum));
+ WELS_READ_VERIFY (ParseSignificantCoeffCabac (pSignificantMap, iResProperty, pCtx));
+ }
+
+ iCurNzCacheIdx = g_kCacheNzcScanIdx[iIndex];
+ pNonZeroCountCache[iCurNzCacheIdx] = (uint8_t)uiTotalCoeffNum;
+ if (uiTotalCoeffNum == 0) {
+ return ERR_NONE;
+ }
+ int32_t j = 0;
+ if (iResProperty == I16_LUMA_DC) {
+ do {
+ sTCoeff[pScanTable[j]] = pSignificantMap[j];
+ ++j;
+ } while (j < 16);
+ WelsLumaDcDequantIdct (sTCoeff, uiQp, pCtx);
+ } else if (iResProperty == CHROMA_DC_U || iResProperty == CHROMA_DC_V) {
+ do {
+ sTCoeff[pScanTable[j]] = pSignificantMap[j];
+ ++j;
+ } while (j < 4);
+ //iHadamard2x2
+ WelsChromaDcIdct (sTCoeff);
+ //scaling
+ if (!pCtx->bUseScalingList) {
+ for (j = 0; j < 4; ++j) {
+ sTCoeff[pScanTable[j]] = (int16_t) ((int64_t)sTCoeff[pScanTable[j]] * (int64_t)pDeQuantMul[0] >> 1);
+ }
+ } else { //with scaling list
+ for (j = 0; j < 4; ++j) {
+ sTCoeff[pScanTable[j]] = (int16_t) ((int64_t)sTCoeff[pScanTable[j]] * (int64_t)pDeQuantMul[0] >> 5);
+ }
+ }
+ } else { //luma ac, chroma ac
+ do {
+ if (pSignificantMap[j] != 0) {
+ if (!pCtx->bUseScalingList) {
+ sTCoeff[pScanTable[j]] = pSignificantMap[j] * pDeQuantMul[pScanTable[j] & 0x07];
+ } else {
+ sTCoeff[pScanTable[j]] = (int16_t) (((int64_t)pSignificantMap[j] * (int64_t)pDeQuantMul[pScanTable[j]] + 8) >> 4);
+ }
+ }
+ ++j;
+ } while (j < 16);
+ }
+ return ERR_NONE;
+}
+
+int32_t ParseIPCMInfoCabac (PWelsDecoderContext pCtx) {
+ int32_t i;
+ PWelsCabacDecEngine pCabacDecEngine = pCtx->pCabacDecEngine;
+ SBitStringAux* pBsAux = pCtx->pCurDqLayer->pBitStringAux;
+ SDqLayer* pCurLayer = pCtx->pCurDqLayer;
+ int32_t iDstStrideLuma = pCurLayer->pDec->iLinesize[0];
+ int32_t iDstStrideChroma = pCurLayer->pDec->iLinesize[1];
+ int32_t iMbX = pCurLayer->iMbX;
+ int32_t iMbY = pCurLayer->iMbY;
+ int32_t iMbXy = pCurLayer->iMbXyIndex;
+
+ int32_t iMbOffsetLuma = (iMbX + iMbY * iDstStrideLuma) << 4;
+ int32_t iMbOffsetChroma = (iMbX + iMbY * iDstStrideChroma) << 3;
+
+ uint8_t* pMbDstY = pCtx->pDec->pData[0] + iMbOffsetLuma;
+ uint8_t* pMbDstU = pCtx->pDec->pData[1] + iMbOffsetChroma;
+ uint8_t* pMbDstV = pCtx->pDec->pData[2] + iMbOffsetChroma;
+
+ uint8_t* pPtrSrc;
+
+ pCurLayer->pMbType[iMbXy] = MB_TYPE_INTRA_PCM;
+ RestoreCabacDecEngineToBS (pCabacDecEngine, pBsAux);
+ intX_t iBytesLeft = pBsAux->pEndBuf - pBsAux->pCurBuf;
+ if (iBytesLeft < 384) {
+ return GENERATE_ERROR_NO (ERR_LEVEL_MB_DATA, ERR_CABAC_NO_BS_TO_READ);
+ }
+ pPtrSrc = pBsAux->pCurBuf;
+ if (!pCtx->pParam->bParseOnly) {
+ for (i = 0; i < 16; i++) { //luma
+ memcpy (pMbDstY, pPtrSrc, 16);
+ pMbDstY += iDstStrideLuma;
+ pPtrSrc += 16;
+ }
+ for (i = 0; i < 8; i++) { //cb
+ memcpy (pMbDstU, pPtrSrc, 8);
+ pMbDstU += iDstStrideChroma;
+ pPtrSrc += 8;
+ }
+ for (i = 0; i < 8; i++) { //cr
+ memcpy (pMbDstV, pPtrSrc, 8);
+ pMbDstV += iDstStrideChroma;
+ pPtrSrc += 8;
+ }
+ }
+
+ pBsAux->pCurBuf += 384;
+
+ pCurLayer->pLumaQp[iMbXy] = 0;
+ pCurLayer->pChromaQp[iMbXy][0] = pCurLayer->pChromaQp[iMbXy][1] = 0;
+ memset (pCurLayer->pNzc[iMbXy], 16, sizeof (pCurLayer->pNzc[iMbXy]));
+
+ //step 4: cabac engine init
+ WELS_READ_VERIFY (InitReadBits (pBsAux, 1));
+ WELS_READ_VERIFY (InitCabacDecEngineFromBS (pCabacDecEngine, pBsAux));
+ return ERR_NONE;
+}
+}
--- a/codec/decoder/core/src/rec_mb.cpp
+++ b/codec/decoder/core/src/rec_mb.cpp
@@ -1,1044 +1,1044 @@
-/*!
- * \copy
- * Copyright (c) 2009-2013, Cisco Systems
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- *
- * \file rec_mb.c
- *
- * \brief implementation for all macroblock decoding process after mb syntax parsing and residual decoding with cavlc.
- *
- * \date 3/18/2009 Created
- *
- *************************************************************************************
- */
-
-
-#include "rec_mb.h"
-#include "decode_slice.h"
-
-namespace WelsDec {
-
-void WelsFillRecNeededMbInfo (PWelsDecoderContext pCtx, bool bOutput, PDqLayer pCurLayer) {
- PPicture pCurPic = pCtx->pDec;
- int32_t iLumaStride = pCurPic->iLinesize[0];
- int32_t iChromaStride = pCurPic->iLinesize[1];
- int32_t iMbX = pCurLayer->iMbX;
- int32_t iMbY = pCurLayer->iMbY;
-
- pCurLayer->iLumaStride = iLumaStride;
- pCurLayer->iChromaStride = iChromaStride;
-
- if (bOutput) {
- pCurLayer->pPred[0] = pCurPic->pData[0] + ((iMbY * iLumaStride + iMbX) << 4);
- pCurLayer->pPred[1] = pCurPic->pData[1] + ((iMbY * iChromaStride + iMbX) << 3);
- pCurLayer->pPred[2] = pCurPic->pData[2] + ((iMbY * iChromaStride + iMbX) << 3);
- }
-}
-
-int32_t RecI8x8Mb (int32_t iMbXy, PWelsDecoderContext pCtx, int16_t* pScoeffLevel, PDqLayer pDqLayer) {
- RecI8x8Luma (iMbXy, pCtx, pScoeffLevel, pDqLayer);
- RecI4x4Chroma (iMbXy, pCtx, pScoeffLevel, pDqLayer);
- return ERR_NONE;
-}
-
-int32_t RecI8x8Luma (int32_t iMbXy, PWelsDecoderContext pCtx, int16_t* pScoeffLevel, PDqLayer pDqLayer) {
- /*****get local variable from outer variable********/
- /*prediction info*/
- uint8_t* pPred = pDqLayer->pPred[0];
-
- int32_t iLumaStride = pDqLayer->iLumaStride;
- int32_t* pBlockOffset = pCtx->iDecBlockOffsetArray;
- PGetIntraPred8x8Func* pGetI8x8LumaPredFunc = pCtx->pGetI8x8LumaPredFunc;
-
- int8_t* pIntra8x8PredMode = pDqLayer->pIntra4x4FinalMode[iMbXy]; // I_NxN
- int16_t* pRS = pScoeffLevel;
- /*itransform info*/
- PIdctResAddPredFunc pIdctResAddPredFunc = pCtx->pIdctResAddPredFunc8x8;
-
- /*************local variable********************/
- uint8_t i = 0;
- bool bTLAvail[4], bTRAvail[4];
- // Top-Right : Left : Top-Left : Top
- bTLAvail[0] = !! (pDqLayer->pIntraNxNAvailFlag[iMbXy] & 0x02);
- bTLAvail[1] = !! (pDqLayer->pIntraNxNAvailFlag[iMbXy] & 0x01);
- bTLAvail[2] = !! (pDqLayer->pIntraNxNAvailFlag[iMbXy] & 0x04);
- bTLAvail[3] = true;
-
- bTRAvail[0] = !! (pDqLayer->pIntraNxNAvailFlag[iMbXy] & 0x01);
- bTRAvail[1] = !! (pDqLayer->pIntraNxNAvailFlag[iMbXy] & 0x08);
- bTRAvail[2] = true;
- bTRAvail[3] = false;
-
- /*************real process*********************/
- for (i = 0; i < 4; i++) {
-
- uint8_t* pPredI8x8 = pPred + pBlockOffset[i << 2];
- uint8_t uiMode = pIntra8x8PredMode[g_kuiScan4[i << 2]];
-
- pGetI8x8LumaPredFunc[uiMode] (pPredI8x8, iLumaStride, bTLAvail[i], bTRAvail[i]);
-
- int32_t iIndex = g_kuiMbCountScan4Idx[i << 2];
- if (pDqLayer->pNzc[iMbXy][iIndex] || pDqLayer->pNzc[iMbXy][iIndex + 1] || pDqLayer->pNzc[iMbXy][iIndex + 4]
- || pDqLayer->pNzc[iMbXy][iIndex + 5]) {
- int16_t* pRSI8x8 = &pRS[i << 6];
- pIdctResAddPredFunc (pPredI8x8, iLumaStride, pRSI8x8);
- }
- }
-
- return ERR_NONE;
-}
-
-int32_t RecI4x4Mb (int32_t iMBXY, PWelsDecoderContext pCtx, int16_t* pScoeffLevel, PDqLayer pDqLayer) {
- RecI4x4Luma (iMBXY, pCtx, pScoeffLevel, pDqLayer);
- RecI4x4Chroma (iMBXY, pCtx, pScoeffLevel, pDqLayer);
- return ERR_NONE;
-}
-
-
-int32_t RecI4x4Luma (int32_t iMBXY, PWelsDecoderContext pCtx, int16_t* pScoeffLevel, PDqLayer pDqLayer) {
- /*****get local variable from outer variable********/
- /*prediction info*/
- uint8_t* pPred = pDqLayer->pPred[0];
-
- int32_t iLumaStride = pDqLayer->iLumaStride;
- int32_t* pBlockOffset = pCtx->iDecBlockOffsetArray;
- PGetIntraPredFunc* pGetI4x4LumaPredFunc = pCtx->pGetI4x4LumaPredFunc;
-
- int8_t* pIntra4x4PredMode = pDqLayer->pIntra4x4FinalMode[iMBXY];
- int16_t* pRS = pScoeffLevel;
- /*itransform info*/
- PIdctResAddPredFunc pIdctResAddPredFunc = pCtx->pIdctResAddPredFunc;
-
-
- /*************local variable********************/
- uint8_t i = 0;
-
- /*************real process*********************/
- for (i = 0; i < 16; i++) {
-
- uint8_t* pPredI4x4 = pPred + pBlockOffset[i];
- uint8_t uiMode = pIntra4x4PredMode[g_kuiScan4[i]];
-
- pGetI4x4LumaPredFunc[uiMode] (pPredI4x4, iLumaStride);
-
- if (pDqLayer->pNzc[iMBXY][g_kuiMbCountScan4Idx[i]]) {
- int16_t* pRSI4x4 = &pRS[i << 4];
- pIdctResAddPredFunc (pPredI4x4, iLumaStride, pRSI4x4);
- }
- }
-
- return ERR_NONE;
-}
-
-
-int32_t RecI4x4Chroma (int32_t iMBXY, PWelsDecoderContext pCtx, int16_t* pScoeffLevel, PDqLayer pDqLayer) {
- int32_t iChromaStride = pCtx->pCurDqLayer->pDec->iLinesize[1];
-
- int8_t iChromaPredMode = pDqLayer->pChromaPredMode[iMBXY];
-
- PGetIntraPredFunc* pGetIChromaPredFunc = pCtx->pGetIChromaPredFunc;
-
- uint8_t* pPred = pDqLayer->pPred[1];
-
- pGetIChromaPredFunc[iChromaPredMode] (pPred, iChromaStride);
- pPred = pDqLayer->pPred[2];
- pGetIChromaPredFunc[iChromaPredMode] (pPred, iChromaStride);
-
- RecChroma (iMBXY, pCtx, pScoeffLevel, pDqLayer);
-
- return ERR_NONE;
-}
-
-
-int32_t RecI16x16Mb (int32_t iMBXY, PWelsDecoderContext pCtx, int16_t* pScoeffLevel, PDqLayer pDqLayer) {
- /*decoder use, encoder no use*/
- int8_t iI16x16PredMode = pDqLayer->pIntraPredMode[iMBXY][7];
- int8_t iChromaPredMode = pDqLayer->pChromaPredMode[iMBXY];
- PGetIntraPredFunc* pGetIChromaPredFunc = pCtx->pGetIChromaPredFunc;
- PGetIntraPredFunc* pGetI16x16LumaPredFunc = pCtx->pGetI16x16LumaPredFunc;
- int32_t iUVStride = pCtx->pCurDqLayer->pDec->iLinesize[1];
-
- /*common use by decoder&encoder*/
- int32_t iYStride = pDqLayer->iLumaStride;
- int16_t* pRS = pScoeffLevel;
-
- uint8_t* pPred = pDqLayer->pPred[0];
-
- PIdctFourResAddPredFunc pIdctFourResAddPredFunc = pCtx->pIdctFourResAddPredFunc;
-
- /*decode i16x16 y*/
- pGetI16x16LumaPredFunc[iI16x16PredMode] (pPred, iYStride);
-
- /*1 mb is divided 16 4x4_block to idct*/
- const int8_t* pNzc = pDqLayer->pNzc[iMBXY];
- pIdctFourResAddPredFunc (pPred + 0 * iYStride + 0, iYStride, pRS + 0 * 64, pNzc + 0);
- pIdctFourResAddPredFunc (pPred + 0 * iYStride + 8, iYStride, pRS + 1 * 64, pNzc + 2);
- pIdctFourResAddPredFunc (pPred + 8 * iYStride + 0, iYStride, pRS + 2 * 64, pNzc + 8);
- pIdctFourResAddPredFunc (pPred + 8 * iYStride + 8, iYStride, pRS + 3 * 64, pNzc + 10);
-
- /*decode intra mb cb&cr*/
- pPred = pDqLayer->pPred[1];
- pGetIChromaPredFunc[iChromaPredMode] (pPred, iUVStride);
- pPred = pDqLayer->pPred[2];
- pGetIChromaPredFunc[iChromaPredMode] (pPred, iUVStride);
- RecChroma (iMBXY, pCtx, pScoeffLevel, pDqLayer);
-
- return ERR_NONE;
-}
-
-
-//according to current 8*8 block ref_index to gain reference picture
-static inline void GetRefPic (sMCRefMember* pMCRefMem, PWelsDecoderContext pCtx, int8_t* pRefIdxList,
- int32_t iIndex, int32_t listIdx) {
- PPicture pRefPic;
-
- int8_t iRefIdx = pRefIdxList[iIndex];
- if (iRefIdx >= 0) {
- pRefPic = pCtx->sRefPic.pRefList[listIdx][iRefIdx];
-
- if (pRefPic != NULL) {
- pMCRefMem->iSrcLineLuma = pRefPic->iLinesize[0];
- pMCRefMem->iSrcLineChroma = pRefPic->iLinesize[1];
-
- pMCRefMem->pSrcY = pRefPic->pData[0];
- pMCRefMem->pSrcU = pRefPic->pData[1];
- pMCRefMem->pSrcV = pRefPic->pData[2];
- }
- }
-}
-
-
-#ifndef MC_FLOW_SIMPLE_JUDGE
-#define MC_FLOW_SIMPLE_JUDGE 1
-#endif //MC_FLOW_SIMPLE_JUDGE
-void BaseMC (sMCRefMember* pMCRefMem, int32_t iXOffset, int32_t iYOffset, SMcFunc* pMCFunc,
- int32_t iBlkWidth, int32_t iBlkHeight, int16_t iMVs[2]) {
- int32_t iFullMVx = (iXOffset << 2) + iMVs[0]; //quarter pixel
- int32_t iFullMVy = (iYOffset << 2) + iMVs[1];
- iFullMVx = WELS_CLIP3 (iFullMVx, ((-PADDING_LENGTH + 2) * (1 << 2)),
- ((pMCRefMem->iPicWidth + PADDING_LENGTH - 19) * (1 << 2)));
- iFullMVy = WELS_CLIP3 (iFullMVy, ((-PADDING_LENGTH + 2) * (1 << 2)),
- ((pMCRefMem->iPicHeight + PADDING_LENGTH - 19) * (1 << 2)));
-
- int32_t iSrcPixOffsetLuma = (iFullMVx >> 2) + (iFullMVy >> 2) * pMCRefMem->iSrcLineLuma;
- int32_t iSrcPixOffsetChroma = (iFullMVx >> 3) + (iFullMVy >> 3) * pMCRefMem->iSrcLineChroma;
-
- int32_t iBlkWidthChroma = iBlkWidth >> 1;
- int32_t iBlkHeightChroma = iBlkHeight >> 1;
-
- uint8_t* pSrcY = pMCRefMem->pSrcY + iSrcPixOffsetLuma;
- uint8_t* pSrcU = pMCRefMem->pSrcU + iSrcPixOffsetChroma;
- uint8_t* pSrcV = pMCRefMem->pSrcV + iSrcPixOffsetChroma;
- uint8_t* pDstY = pMCRefMem->pDstY;
- uint8_t* pDstU = pMCRefMem->pDstU;
- uint8_t* pDstV = pMCRefMem->pDstV;
-
- pMCFunc->pMcLumaFunc (pSrcY, pMCRefMem->iSrcLineLuma, pDstY, pMCRefMem->iDstLineLuma, iFullMVx, iFullMVy, iBlkWidth,
- iBlkHeight);
- pMCFunc->pMcChromaFunc (pSrcU, pMCRefMem->iSrcLineChroma, pDstU, pMCRefMem->iDstLineChroma, iFullMVx, iFullMVy,
- iBlkWidthChroma, iBlkHeightChroma);
- pMCFunc->pMcChromaFunc (pSrcV, pMCRefMem->iSrcLineChroma, pDstV, pMCRefMem->iDstLineChroma, iFullMVx, iFullMVy,
- iBlkWidthChroma, iBlkHeightChroma);
-
-}
-
-static void WeightPrediction (PDqLayer pCurDqLayer, sMCRefMember* pMCRefMem, int32_t listIdx, int32_t iRefIdx,
- int32_t iBlkWidth,
- int32_t iBlkHeight) {
-
-
- int32_t iLog2denom, iWoc, iOoc;
- int32_t iPredTemp, iLineStride;
- int32_t iPixel = 0;
- uint8_t* pDst;
- //luma
- iLog2denom = pCurDqLayer->pPredWeightTable->uiLumaLog2WeightDenom;
- iWoc = pCurDqLayer->pPredWeightTable->sPredList[listIdx].iLumaWeight[iRefIdx];
- iOoc = pCurDqLayer->pPredWeightTable->sPredList[listIdx].iLumaOffset[iRefIdx];
- iLineStride = pMCRefMem->iDstLineLuma;
-
- for (int i = 0; i < iBlkHeight; i++) {
- for (int j = 0; j < iBlkWidth; j++) {
- iPixel = j + i * (iLineStride);
- if (iLog2denom >= 1) {
- iPredTemp = ((pMCRefMem->pDstY[iPixel] * iWoc + (1 << (iLog2denom - 1))) >> iLog2denom) + iOoc;
-
- pMCRefMem->pDstY[iPixel] = WELS_CLIP3 (iPredTemp, 0, 255);
- } else {
- iPredTemp = pMCRefMem->pDstY[iPixel] * iWoc + iOoc;
-
- pMCRefMem->pDstY[iPixel] = WELS_CLIP3 (iPredTemp, 0, 255);
-
- }
- }
- }
-
-
- //UV
- iBlkWidth = iBlkWidth >> 1;
- iBlkHeight = iBlkHeight >> 1;
- iLog2denom = pCurDqLayer->pPredWeightTable->uiChromaLog2WeightDenom;
- iLineStride = pMCRefMem->iDstLineChroma;
-
- for (int i = 0; i < 2; i++) {
-
-
- //iLog2denom = pCurDqLayer->pPredWeightTable->uiChromaLog2WeightDenom;
- iWoc = pCurDqLayer->pPredWeightTable->sPredList[listIdx].iChromaWeight[iRefIdx][i];
- iOoc = pCurDqLayer->pPredWeightTable->sPredList[listIdx].iChromaOffset[iRefIdx][i];
- pDst = i ? pMCRefMem->pDstV : pMCRefMem->pDstU;
- //iLineStride = pMCRefMem->iDstLineChroma;
-
- for (int i = 0; i < iBlkHeight ; i++) {
- for (int j = 0; j < iBlkWidth; j++) {
- iPixel = j + i * (iLineStride);
- if (iLog2denom >= 1) {
- iPredTemp = ((pDst[iPixel] * iWoc + (1 << (iLog2denom - 1))) >> iLog2denom) + iOoc;
-
- pDst[iPixel] = WELS_CLIP3 (iPredTemp, 0, 255);
- } else {
- iPredTemp = pDst[iPixel] * iWoc + iOoc;
-
- pDst[iPixel] = WELS_CLIP3 (iPredTemp, 0, 255);
-
- }
- }
-
- }
-
-
- }
-}
-
-static void BiWeightPrediction (PDqLayer pCurDqLayer, sMCRefMember* pMCRefMem, sMCRefMember* pTempMCRefMem,
- int32_t iRefIdx1, int32_t iRefIdx2, bool bWeightedBipredIdcIs1, int32_t iBlkWidth,
- int32_t iBlkHeight) {
- int32_t iWoc1 = 0, iOoc1 = 0, iWoc2 = 0, iOoc2 = 0;
- int32_t iPredTemp, iLineStride;
- int32_t iPixel = 0;
- //luma
- int32_t iLog2denom = pCurDqLayer->pPredWeightTable->uiLumaLog2WeightDenom;
- if (bWeightedBipredIdcIs1) {
- iWoc1 = pCurDqLayer->pPredWeightTable->sPredList[LIST_0].iLumaWeight[iRefIdx1];
- iOoc1 = pCurDqLayer->pPredWeightTable->sPredList[LIST_0].iLumaOffset[iRefIdx1];
- iWoc2 = pCurDqLayer->pPredWeightTable->sPredList[LIST_1].iLumaWeight[iRefIdx2];
- iOoc2 = pCurDqLayer->pPredWeightTable->sPredList[LIST_1].iLumaOffset[iRefIdx2];
- } else {
- iWoc1 = pCurDqLayer->pPredWeightTable->iImplicitWeight[iRefIdx1][iRefIdx2];
- iWoc2 = 64 - iWoc1;
- }
- iLineStride = pMCRefMem->iDstLineLuma;
-
- for (int i = 0; i < iBlkHeight; i++) {
- for (int j = 0; j < iBlkWidth; j++) {
- iPixel = j + i * (iLineStride);
- iPredTemp = ((pMCRefMem->pDstY[iPixel] * iWoc1 + pTempMCRefMem->pDstY[iPixel] * iWoc2 + (1 << iLog2denom)) >>
- (iLog2denom + 1)) + ((iOoc1 + iOoc2 + 1) >> 1);
- pMCRefMem->pDstY[iPixel] = WELS_CLIP3 (iPredTemp, 0, 255);
- }
- }
-
- //UV
- iBlkWidth = iBlkWidth >> 1;
- iBlkHeight = iBlkHeight >> 1;
- iLog2denom = pCurDqLayer->pPredWeightTable->uiChromaLog2WeightDenom;
- iLineStride = pMCRefMem->iDstLineChroma;
-
- uint8_t* pDst;
- uint8_t* pTempDst;
- for (int k = 0; k < 2; k++) {
- //iLog2denom = pCurDqLayer->pPredWeightTable->uiChromaLog2WeightDenom;
- if (bWeightedBipredIdcIs1) {
- iWoc1 = pCurDqLayer->pPredWeightTable->sPredList[LIST_0].iChromaWeight[iRefIdx1][k];
- iOoc1 = pCurDqLayer->pPredWeightTable->sPredList[LIST_0].iChromaOffset[iRefIdx1][k];
- iWoc2 = pCurDqLayer->pPredWeightTable->sPredList[LIST_1].iChromaWeight[iRefIdx2][k];
- iOoc2 = pCurDqLayer->pPredWeightTable->sPredList[LIST_1].iChromaOffset[iRefIdx2][k];
- }
- pDst = k ? pMCRefMem->pDstV : pMCRefMem->pDstU;
- pTempDst = k ? pTempMCRefMem->pDstV : pTempMCRefMem->pDstU;
- //iLineStride = pMCRefMem->iDstLineChroma;
-
- for (int i = 0; i < iBlkHeight; i++) {
- for (int j = 0; j < iBlkWidth; j++) {
- iPixel = j + i * (iLineStride);
- iPredTemp = ((pDst[iPixel] * iWoc1 + pTempDst[iPixel] * iWoc2 + (1 << iLog2denom)) >> (iLog2denom + 1)) + ((
- iOoc1 + iOoc2 + 1) >> 1);
- pDst[iPixel] = WELS_CLIP3 (iPredTemp, 0, 255);
- }
- }
- }
-}
-
-static void BiPrediction (PDqLayer pCurDqLayer, sMCRefMember* pMCRefMem, sMCRefMember* pTempMCRefMem, int32_t iBlkWidth,
- int32_t iBlkHeight) {
- int32_t iPredTemp, iLineStride;
- int32_t iPixel = 0;
- //luma
- iLineStride = pMCRefMem->iDstLineLuma;
-
- for (int i = 0; i < iBlkHeight; i++) {
- for (int j = 0; j < iBlkWidth; j++) {
- iPixel = j + i * (iLineStride);
- iPredTemp = (pMCRefMem->pDstY[iPixel] + pTempMCRefMem->pDstY[iPixel] + 1) >> 1;
- pMCRefMem->pDstY[iPixel] = WELS_CLIP3 (iPredTemp, 0, 255);
- }
- }
-
- //UV
- iBlkWidth = iBlkWidth >> 1;
- iBlkHeight = iBlkHeight >> 1;
- iLineStride = pMCRefMem->iDstLineChroma;
-
- uint8_t* pDst;
- uint8_t* pTempDst;
- for (int k = 0; k < 2; k++) {
- pDst = k ? pMCRefMem->pDstV : pMCRefMem->pDstU;
- pTempDst = k ? pTempMCRefMem->pDstV : pTempMCRefMem->pDstU;
- //iLineStride = pMCRefMem->iDstLineChroma;
-
- for (int i = 0; i < iBlkHeight; i++) {
- for (int j = 0; j < iBlkWidth; j++) {
- iPixel = j + i * (iLineStride);
- iPredTemp = (pDst[iPixel] + pTempDst[iPixel] + 1) >> 1;
- pDst[iPixel] = WELS_CLIP3 (iPredTemp, 0, 255);
- }
- }
- }
-}
-
-void GetInterPred (uint8_t* pPredY, uint8_t* pPredCb, uint8_t* pPredCr, PWelsDecoderContext pCtx) {
- sMCRefMember pMCRefMem;
- PDqLayer pCurDqLayer = pCtx->pCurDqLayer;
- SMcFunc* pMCFunc = &pCtx->sMcFunc;
-
- int32_t iMBXY = pCurDqLayer->iMbXyIndex;
-
- int16_t iMVs[2] = {0};
-
- uint32_t iMBType = pCurDqLayer->pMbType[iMBXY];
-
- int32_t iMBOffsetX = pCurDqLayer->iMbX << 4;
- int32_t iMBOffsetY = pCurDqLayer->iMbY << 4;
-
- int32_t iDstLineLuma = pCtx->pDec->iLinesize[0];
- int32_t iDstLineChroma = pCtx->pDec->iLinesize[1];
-
- int32_t iBlk8X, iBlk8Y, iBlk4X, iBlk4Y, i, j, iIIdx, iJIdx;
-
- pMCRefMem.iPicWidth = (pCurDqLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.iMbWidth << 4);
- pMCRefMem.iPicHeight = (pCurDqLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.iMbHeight << 4);
-
- pMCRefMem.pDstY = pPredY;
- pMCRefMem.pDstU = pPredCb;
- pMCRefMem.pDstV = pPredCr;
-
- pMCRefMem.iDstLineLuma = iDstLineLuma;
- pMCRefMem.iDstLineChroma = iDstLineChroma;
-
- int32_t iRefIndex = 0;
-
- switch (iMBType) {
- case MB_TYPE_SKIP:
- case MB_TYPE_16x16:
- iMVs[0] = pCurDqLayer->pMv[0][iMBXY][0][0];
- iMVs[1] = pCurDqLayer->pMv[0][iMBXY][0][1];
- GetRefPic (&pMCRefMem, pCtx, pCurDqLayer->pRefIndex[0][iMBXY], 0, LIST_0);
- BaseMC (&pMCRefMem, iMBOffsetX, iMBOffsetY, pMCFunc, 16, 16, iMVs);
-
- if (pCurDqLayer->bUseWeightPredictionFlag) {
- iRefIndex = pCurDqLayer->pRefIndex[0][iMBXY][0];
- WeightPrediction (pCurDqLayer, &pMCRefMem, LIST_0, iRefIndex, 16, 16);
- }
- break;
- case MB_TYPE_16x8:
- iMVs[0] = pCurDqLayer->pMv[0][iMBXY][0][0];
- iMVs[1] = pCurDqLayer->pMv[0][iMBXY][0][1];
- GetRefPic (&pMCRefMem, pCtx, pCurDqLayer->pRefIndex[0][iMBXY], 0, LIST_0);
- BaseMC (&pMCRefMem, iMBOffsetX, iMBOffsetY, pMCFunc, 16, 8, iMVs);
-
- if (pCurDqLayer->bUseWeightPredictionFlag) {
- iRefIndex = pCurDqLayer->pRefIndex[0][iMBXY][0];
- WeightPrediction (pCurDqLayer, &pMCRefMem, LIST_0, iRefIndex, 16, 8);
- }
-
- iMVs[0] = pCurDqLayer->pMv[0][iMBXY][8][0];
- iMVs[1] = pCurDqLayer->pMv[0][iMBXY][8][1];
- GetRefPic (&pMCRefMem, pCtx, pCurDqLayer->pRefIndex[0][iMBXY], 8, LIST_0);
- pMCRefMem.pDstY = pPredY + (iDstLineLuma << 3);
- pMCRefMem.pDstU = pPredCb + (iDstLineChroma << 2);
- pMCRefMem.pDstV = pPredCr + (iDstLineChroma << 2);
- BaseMC (&pMCRefMem, iMBOffsetX, iMBOffsetY + 8, pMCFunc, 16, 8, iMVs);
-
- if (pCurDqLayer->bUseWeightPredictionFlag) {
- iRefIndex = pCurDqLayer->pRefIndex[0][iMBXY][8];
- WeightPrediction (pCurDqLayer, &pMCRefMem, LIST_0, iRefIndex, 16, 8);
- }
- break;
- case MB_TYPE_8x16:
- iMVs[0] = pCurDqLayer->pMv[0][iMBXY][0][0];
- iMVs[1] = pCurDqLayer->pMv[0][iMBXY][0][1];
- GetRefPic (&pMCRefMem, pCtx, pCurDqLayer->pRefIndex[0][iMBXY], 0, LIST_0);
- BaseMC (&pMCRefMem, iMBOffsetX, iMBOffsetY, pMCFunc, 8, 16, iMVs);
- if (pCurDqLayer->bUseWeightPredictionFlag) {
- iRefIndex = pCurDqLayer->pRefIndex[0][iMBXY][0];
- WeightPrediction (pCurDqLayer, &pMCRefMem, LIST_0, iRefIndex, 8, 16);
- }
-
- iMVs[0] = pCurDqLayer->pMv[0][iMBXY][2][0];
- iMVs[1] = pCurDqLayer->pMv[0][iMBXY][2][1];
- GetRefPic (&pMCRefMem, pCtx, pCurDqLayer->pRefIndex[0][iMBXY], 2, LIST_0);
- pMCRefMem.pDstY = pPredY + 8;
- pMCRefMem.pDstU = pPredCb + 4;
- pMCRefMem.pDstV = pPredCr + 4;
- BaseMC (&pMCRefMem, iMBOffsetX + 8, iMBOffsetY, pMCFunc, 8, 16, iMVs);
-
- if (pCurDqLayer->bUseWeightPredictionFlag) {
- iRefIndex = pCurDqLayer->pRefIndex[0][iMBXY][2];
- WeightPrediction (pCurDqLayer, &pMCRefMem, LIST_0, iRefIndex, 8, 16);
- }
- break;
- case MB_TYPE_8x8:
- case MB_TYPE_8x8_REF0: {
- uint32_t iSubMBType;
- int32_t iXOffset, iYOffset;
- uint8_t* pDstY, *pDstU, *pDstV;
- for (i = 0; i < 4; i++) {
- iSubMBType = pCurDqLayer->pSubMbType[iMBXY][i];
- iBlk8X = (i & 1) << 3;
- iBlk8Y = (i >> 1) << 3;
- iXOffset = iMBOffsetX + iBlk8X;
- iYOffset = iMBOffsetY + iBlk8Y;
-
- iIIdx = ((i >> 1) << 3) + ((i & 1) << 1);
- GetRefPic (&pMCRefMem, pCtx, pCurDqLayer->pRefIndex[0][iMBXY], iIIdx, LIST_0);
- iRefIndex = pCurDqLayer->bUseWeightPredictionFlag ? pCurDqLayer->pRefIndex[0][iMBXY][iIIdx] : 0;
-
- pDstY = pPredY + iBlk8X + iBlk8Y * iDstLineLuma;
- pDstU = pPredCb + (iBlk8X >> 1) + (iBlk8Y >> 1) * iDstLineChroma;
- pDstV = pPredCr + (iBlk8X >> 1) + (iBlk8Y >> 1) * iDstLineChroma;
- pMCRefMem.pDstY = pDstY;
- pMCRefMem.pDstU = pDstU;
- pMCRefMem.pDstV = pDstV;
- switch (iSubMBType) {
- case SUB_MB_TYPE_8x8:
- iMVs[0] = pCurDqLayer->pMv[0][iMBXY][iIIdx][0];
- iMVs[1] = pCurDqLayer->pMv[0][iMBXY][iIIdx][1];
- BaseMC (&pMCRefMem, iXOffset, iYOffset, pMCFunc, 8, 8, iMVs);
- if (pCurDqLayer->bUseWeightPredictionFlag) {
-
- WeightPrediction (pCurDqLayer, &pMCRefMem, LIST_0, iRefIndex, 8, 8);
- }
-
- break;
- case SUB_MB_TYPE_8x4:
- iMVs[0] = pCurDqLayer->pMv[0][iMBXY][iIIdx][0];
- iMVs[1] = pCurDqLayer->pMv[0][iMBXY][iIIdx][1];
- BaseMC (&pMCRefMem, iXOffset, iYOffset, pMCFunc, 8, 4, iMVs);
- if (pCurDqLayer->bUseWeightPredictionFlag) {
-
- WeightPrediction (pCurDqLayer, &pMCRefMem, LIST_0, iRefIndex, 8, 4);
- }
-
-
- iMVs[0] = pCurDqLayer->pMv[0][iMBXY][iIIdx + 4][0];
- iMVs[1] = pCurDqLayer->pMv[0][iMBXY][iIIdx + 4][1];
- pMCRefMem.pDstY += (iDstLineLuma << 2);
- pMCRefMem.pDstU += (iDstLineChroma << 1);
- pMCRefMem.pDstV += (iDstLineChroma << 1);
- BaseMC (&pMCRefMem, iXOffset, iYOffset + 4, pMCFunc, 8, 4, iMVs);
- if (pCurDqLayer->bUseWeightPredictionFlag) {
-
- WeightPrediction (pCurDqLayer, &pMCRefMem, LIST_0, iRefIndex, 8, 4);
- }
-
- break;
- case SUB_MB_TYPE_4x8:
- iMVs[0] = pCurDqLayer->pMv[0][iMBXY][iIIdx][0];
- iMVs[1] = pCurDqLayer->pMv[0][iMBXY][iIIdx][1];
- BaseMC (&pMCRefMem, iXOffset, iYOffset, pMCFunc, 4, 8, iMVs);
- if (pCurDqLayer->bUseWeightPredictionFlag) {
-
- WeightPrediction (pCurDqLayer, &pMCRefMem, LIST_0, iRefIndex, 4, 8);
- }
-
-
- iMVs[0] = pCurDqLayer->pMv[0][iMBXY][iIIdx + 1][0];
- iMVs[1] = pCurDqLayer->pMv[0][iMBXY][iIIdx + 1][1];
- pMCRefMem.pDstY += 4;
- pMCRefMem.pDstU += 2;
- pMCRefMem.pDstV += 2;
- BaseMC (&pMCRefMem, iXOffset + 4, iYOffset, pMCFunc, 4, 8, iMVs);
- if (pCurDqLayer->bUseWeightPredictionFlag) {
-
- WeightPrediction (pCurDqLayer, &pMCRefMem, LIST_0, iRefIndex, 4, 8);
- }
-
- break;
- case SUB_MB_TYPE_4x4: {
- for (j = 0; j < 4; j++) {
- int32_t iUVLineStride;
- iJIdx = ((j >> 1) << 2) + (j & 1);
-
- iBlk4X = (j & 1) << 2;
- iBlk4Y = (j >> 1) << 2;
-
- iUVLineStride = (iBlk4X >> 1) + (iBlk4Y >> 1) * iDstLineChroma;
- pMCRefMem.pDstY = pDstY + iBlk4X + iBlk4Y * iDstLineLuma;
- pMCRefMem.pDstU = pDstU + iUVLineStride;
- pMCRefMem.pDstV = pDstV + iUVLineStride;
-
- iMVs[0] = pCurDqLayer->pMv[0][iMBXY][iIIdx + iJIdx][0];
- iMVs[1] = pCurDqLayer->pMv[0][iMBXY][iIIdx + iJIdx][1];
- BaseMC (&pMCRefMem, iXOffset + iBlk4X, iYOffset + iBlk4Y, pMCFunc, 4, 4, iMVs);
- if (pCurDqLayer->bUseWeightPredictionFlag) {
-
- WeightPrediction (pCurDqLayer, &pMCRefMem, LIST_0, iRefIndex, 4, 4);
- }
-
- }
- }
- break;
- default:
- break;
- }
- }
- }
- break;
- default:
- break;
- }
-}
-
-void GetInterBPred (uint8_t* pPredYCbCr[3], uint8_t* pTempPredYCbCr[3], PWelsDecoderContext pCtx) {
- sMCRefMember pMCRefMem;
- sMCRefMember pTempMCRefMem;
-
- PDqLayer pCurDqLayer = pCtx->pCurDqLayer;
- SMcFunc* pMCFunc = &pCtx->sMcFunc;
-
- int32_t iMBXY = pCurDqLayer->iMbXyIndex;
-
- int16_t iMVs[2] = { 0 };
-
- uint32_t iMBType = pCurDqLayer->pMbType[iMBXY];
-
- int32_t iMBOffsetX = pCurDqLayer->iMbX << 4;
- int32_t iMBOffsetY = pCurDqLayer->iMbY << 4;
-
- int32_t iDstLineLuma = pCtx->pDec->iLinesize[0];
- int32_t iDstLineChroma = pCtx->pDec->iLinesize[1];
-
-
- pMCRefMem.iPicWidth = (pCurDqLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.iMbWidth << 4);
- pMCRefMem.iPicHeight = (pCurDqLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.iMbHeight << 4);
-
- pMCRefMem.pDstY = pPredYCbCr[0];
- pMCRefMem.pDstU = pPredYCbCr[1];
- pMCRefMem.pDstV = pPredYCbCr[2];
-
- pMCRefMem.iDstLineLuma = iDstLineLuma;
- pMCRefMem.iDstLineChroma = iDstLineChroma;
-
- pTempMCRefMem = pMCRefMem;
- pTempMCRefMem.pDstY = pTempPredYCbCr[0];
- pTempMCRefMem.pDstU = pTempPredYCbCr[1];
- pTempMCRefMem.pDstV = pTempPredYCbCr[2];
-
-
- int32_t iRefIndex1 = 0;
- int32_t iRefIndex2 = 0;
-
- bool bWeightedBipredIdcIs1 = pCurDqLayer->sLayerInfo.pPps->uiWeightedBipredIdc == 1;
-
- if (IS_INTER_16x16 (iMBType)) {
- if (IS_TYPE_L0 (iMBType) && IS_TYPE_L1 (iMBType)) {
- iMVs[0] = pCurDqLayer->pMv[LIST_0][iMBXY][0][0];
- iMVs[1] = pCurDqLayer->pMv[LIST_0][iMBXY][0][1];
- GetRefPic (&pMCRefMem, pCtx, pCurDqLayer->pRefIndex[LIST_0][iMBXY], 0, LIST_0);
- BaseMC (&pMCRefMem, iMBOffsetX, iMBOffsetY, pMCFunc, 16, 16, iMVs);
-
- iMVs[0] = pCurDqLayer->pMv[LIST_1][iMBXY][0][0];
- iMVs[1] = pCurDqLayer->pMv[LIST_1][iMBXY][0][1];
- GetRefPic (&pTempMCRefMem, pCtx, pCurDqLayer->pRefIndex[LIST_1][iMBXY], 0, LIST_1);
- BaseMC (&pTempMCRefMem, iMBOffsetX, iMBOffsetY, pMCFunc, 16, 16, iMVs);
- iRefIndex1 = pCurDqLayer->pRefIndex[LIST_0][iMBXY][0];
- iRefIndex2 = pCurDqLayer->pRefIndex[LIST_1][iMBXY][0];
- if (pCurDqLayer->bUseWeightedBiPredIdc) {
- BiWeightPrediction (pCurDqLayer, &pMCRefMem, &pTempMCRefMem, iRefIndex1, iRefIndex2, bWeightedBipredIdcIs1, 16, 16);
- } else {
- BiPrediction (pCurDqLayer, &pMCRefMem, &pTempMCRefMem, 16, 16);
- }
- } else {
- int32_t listIdx = (iMBType & MB_TYPE_P0L0) ? LIST_0 : LIST_1;
- iMVs[0] = pCurDqLayer->pMv[listIdx][iMBXY][0][0];
- iMVs[1] = pCurDqLayer->pMv[listIdx][iMBXY][0][1];
- GetRefPic (&pMCRefMem, pCtx, pCurDqLayer->pRefIndex[listIdx][iMBXY], 0, listIdx);
- BaseMC (&pMCRefMem, iMBOffsetX, iMBOffsetY, pMCFunc, 16, 16, iMVs);
- if (bWeightedBipredIdcIs1) {
- int32_t iRefIndex = pCurDqLayer->pRefIndex[listIdx][iMBXY][0];
- WeightPrediction (pCurDqLayer, &pMCRefMem, listIdx, iRefIndex, 16, 16);
- }
- }
- } else if (IS_INTER_16x8 (iMBType)) {
- for (int32_t i = 0; i < 2; ++i) {
- int32_t iPartIdx = i << 3;
- uint32_t listCount = 0;
- int32_t lastListIdx = LIST_0;
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- if (IS_DIR (iMBType, i, listIdx)) {
- lastListIdx = listIdx;
- iMVs[0] = pCurDqLayer->pMv[listIdx][iMBXY][iPartIdx][0];
- iMVs[1] = pCurDqLayer->pMv[listIdx][iMBXY][iPartIdx][1];
- GetRefPic (&pMCRefMem, pCtx, pCurDqLayer->pRefIndex[listIdx][iMBXY], iPartIdx, listIdx);
- if (i) {
- pMCRefMem.pDstY += (iDstLineLuma << 3);
- pMCRefMem.pDstU += (iDstLineChroma << 2);
- pMCRefMem.pDstV += (iDstLineChroma << 2);
- }
- BaseMC (&pMCRefMem, iMBOffsetX, iMBOffsetY + iPartIdx, pMCFunc, 16, 8, iMVs);
- if (++listCount == 2) {
- iMVs[0] = pCurDqLayer->pMv[LIST_1][iMBXY][iPartIdx][0];
- iMVs[1] = pCurDqLayer->pMv[LIST_1][iMBXY][iPartIdx][1];
- GetRefPic (&pTempMCRefMem, pCtx, pCurDqLayer->pRefIndex[LIST_1][iMBXY], iPartIdx, LIST_1);
- if (i) {
- pTempMCRefMem.pDstY += (iDstLineLuma << 3);
- pTempMCRefMem.pDstU += (iDstLineChroma << 2);
- pTempMCRefMem.pDstV += (iDstLineChroma << 2);
- }
- BaseMC (&pTempMCRefMem, iMBOffsetX, iMBOffsetY + iPartIdx, pMCFunc, 16, 8, iMVs);
- if (pCurDqLayer->bUseWeightedBiPredIdc) {
- iRefIndex1 = pCurDqLayer->pRefIndex[LIST_0][iMBXY][iPartIdx];
- iRefIndex2 = pCurDqLayer->pRefIndex[LIST_1][iMBXY][iPartIdx];
- BiWeightPrediction (pCurDqLayer, &pMCRefMem, &pTempMCRefMem, iRefIndex1, iRefIndex2, bWeightedBipredIdcIs1, 16, 8);
- } else {
- BiPrediction (pCurDqLayer, &pMCRefMem, &pTempMCRefMem, 16, 8);
- }
- }
- }
- }
- if (listCount == 1) {
- if (bWeightedBipredIdcIs1) {
- int32_t iRefIndex = pCurDqLayer->pRefIndex[lastListIdx][iMBXY][iPartIdx];
- WeightPrediction (pCurDqLayer, &pMCRefMem, lastListIdx, iRefIndex, 16, 8);
- }
- }
- }
- } else if (IS_INTER_8x16 (iMBType)) {
- for (int32_t i = 0; i < 2; ++i) {
- uint32_t listCount = 0;
- int32_t lastListIdx = LIST_0;
- for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
- if (IS_DIR (iMBType, i, listIdx)) {
- lastListIdx = listIdx;
- iMVs[0] = pCurDqLayer->pMv[listIdx][iMBXY][i << 1][0];
- iMVs[1] = pCurDqLayer->pMv[listIdx][iMBXY][i << 1][1];
- GetRefPic (&pMCRefMem, pCtx, pCurDqLayer->pRefIndex[listIdx][iMBXY], i << 1, listIdx);
- if (i) {
- pMCRefMem.pDstY += 8;
- pMCRefMem.pDstU += 4;
- pMCRefMem.pDstV += 4;
- }
- BaseMC (&pMCRefMem, iMBOffsetX + (i ? 8 : 0), iMBOffsetY, pMCFunc, 8, 16, iMVs);
- if (++listCount == 2) {
- iMVs[0] = pCurDqLayer->pMv[LIST_1][iMBXY][i << 1][0];
- iMVs[1] = pCurDqLayer->pMv[LIST_1][iMBXY][i << 1][1];
- GetRefPic (&pTempMCRefMem, pCtx, pCurDqLayer->pRefIndex[LIST_1][iMBXY], i << 1, LIST_1);
- if (i) {
- pTempMCRefMem.pDstY += 8;
- pTempMCRefMem.pDstU += 4;
- pTempMCRefMem.pDstV += 4;
- }
- BaseMC (&pTempMCRefMem, iMBOffsetX + (i ? 8 : 0), iMBOffsetY, pMCFunc, 8, 16, iMVs);
- if (pCurDqLayer->bUseWeightedBiPredIdc) {
- iRefIndex1 = pCurDqLayer->pRefIndex[LIST_0][iMBXY][i << 1];
- iRefIndex2 = pCurDqLayer->pRefIndex[LIST_1][iMBXY][i << 1];
- BiWeightPrediction (pCurDqLayer, &pMCRefMem, &pTempMCRefMem, iRefIndex1, iRefIndex2, bWeightedBipredIdcIs1, 8, 16);
- } else {
- BiPrediction (pCurDqLayer, &pMCRefMem, &pTempMCRefMem, 8, 16);
- }
- }
- }
- }
- if (listCount == 1) {
- if (bWeightedBipredIdcIs1) {
- int32_t iRefIndex = pCurDqLayer->pRefIndex[lastListIdx][iMBXY][i << 1];
- WeightPrediction (pCurDqLayer, &pMCRefMem, lastListIdx, iRefIndex, 8, 16);
- }
- }
- }
- } else if (IS_Inter_8x8 (iMBType)) {
- int32_t iBlk8X, iBlk8Y, iBlk4X, iBlk4Y, iIIdx, iJIdx;
- uint32_t iSubMBType;
- int32_t iXOffset, iYOffset;
- uint8_t* pDstY, *pDstU, *pDstV;
- uint8_t* pDstY2, *pDstU2, *pDstV2;
- for (int32_t i = 0; i < 4; i++) {
- iSubMBType = pCurDqLayer->pSubMbType[iMBXY][i];
- iBlk8X = (i & 1) << 3;
- iBlk8Y = (i >> 1) << 3;
- iXOffset = iMBOffsetX + iBlk8X;
- iYOffset = iMBOffsetY + iBlk8Y;
-
- iIIdx = ((i >> 1) << 3) + ((i & 1) << 1);
-
- pDstY = pPredYCbCr[0] + iBlk8X + iBlk8Y * iDstLineLuma;
- pDstU = pPredYCbCr[1] + (iBlk8X >> 1) + (iBlk8Y >> 1) * iDstLineChroma;
- pDstV = pPredYCbCr[2] + (iBlk8X >> 1) + (iBlk8Y >> 1) * iDstLineChroma;
- pMCRefMem.pDstY = pDstY;
- pMCRefMem.pDstU = pDstU;
- pMCRefMem.pDstV = pDstV;
-
- pTempMCRefMem = pMCRefMem;
- pDstY2 = pTempPredYCbCr[0] + iBlk8X + iBlk8Y * iDstLineLuma;
- pDstU2 = pTempPredYCbCr[1] + (iBlk8X >> 1) + (iBlk8Y >> 1) * iDstLineChroma;
- pDstV2 = pTempPredYCbCr[2] + (iBlk8X >> 1) + (iBlk8Y >> 1) * iDstLineChroma;
-
- pTempMCRefMem.pDstY = pDstY2;
- pTempMCRefMem.pDstU = pDstU2;
- pTempMCRefMem.pDstV = pDstV2;
-
- if ((IS_TYPE_L0 (iSubMBType) && IS_TYPE_L1 (iSubMBType))) {
- iRefIndex1 = pCurDqLayer->pRefIndex[LIST_0][iMBXY][iIIdx];
- GetRefPic (&pMCRefMem, pCtx, pCurDqLayer->pRefIndex[LIST_0][iMBXY], iIIdx, LIST_0);
-
- iRefIndex2 = pCurDqLayer->pRefIndex[LIST_1][iMBXY][iIIdx];
- GetRefPic (&pTempMCRefMem, pCtx, pCurDqLayer->pRefIndex[LIST_1][iMBXY], iIIdx, LIST_1);
- } else {
- int32_t listIdx = IS_TYPE_L0 (iSubMBType) ? LIST_0 : LIST_1;
- iRefIndex1 = pCurDqLayer->pRefIndex[listIdx][iMBXY][iIIdx];
- GetRefPic (&pMCRefMem, pCtx, pCurDqLayer->pRefIndex[listIdx][iMBXY], iIIdx, listIdx);
- }
-
- if (IS_SUB_8x8 (iSubMBType)) {
- if (IS_TYPE_L0 (iSubMBType) && IS_TYPE_L1 (iSubMBType)) {
- iMVs[0] = pCurDqLayer->pMv[LIST_0][iMBXY][iIIdx][0];
- iMVs[1] = pCurDqLayer->pMv[LIST_0][iMBXY][iIIdx][1];
- BaseMC (&pMCRefMem, iXOffset, iYOffset, pMCFunc, 8, 8, iMVs);
-
- iMVs[0] = pCurDqLayer->pMv[LIST_1][iMBXY][iIIdx][0];
- iMVs[1] = pCurDqLayer->pMv[LIST_1][iMBXY][iIIdx][1];
- BaseMC (&pTempMCRefMem, iXOffset, iYOffset, pMCFunc, 8, 8, iMVs);
-
- if (pCurDqLayer->bUseWeightedBiPredIdc) {
- BiWeightPrediction (pCurDqLayer, &pMCRefMem, &pTempMCRefMem, iRefIndex1, iRefIndex2, bWeightedBipredIdcIs1, 8, 8);
- } else {
- BiPrediction (pCurDqLayer, &pMCRefMem, &pTempMCRefMem, 8, 8);
- }
- } else {
- int32_t listIdx = IS_TYPE_L0 (iSubMBType) ? LIST_0 : LIST_1;
- iMVs[0] = pCurDqLayer->pMv[listIdx][iMBXY][iIIdx][0];
- iMVs[1] = pCurDqLayer->pMv[listIdx][iMBXY][iIIdx][1];
- BaseMC (&pMCRefMem, iXOffset, iYOffset, pMCFunc, 8, 8, iMVs);
- if (bWeightedBipredIdcIs1) {
- int32_t iRefIndex = pCurDqLayer->pRefIndex[listIdx][iMBXY][iIIdx];
- WeightPrediction (pCurDqLayer, &pMCRefMem, listIdx, iRefIndex, 8, 8);
- }
- }
- } else if (IS_SUB_8x4 (iSubMBType)) {
- if (IS_TYPE_L0 (iSubMBType) && IS_TYPE_L1 (iSubMBType)) { //B_Bi_8x4
- iMVs[0] = pCurDqLayer->pMv[LIST_0][iMBXY][iIIdx][0];
- iMVs[1] = pCurDqLayer->pMv[LIST_0][iMBXY][iIIdx][1];
- BaseMC (&pMCRefMem, iXOffset, iYOffset, pMCFunc, 8, 4, iMVs);
- iMVs[0] = pCurDqLayer->pMv[LIST_1][iMBXY][iIIdx][0];
- iMVs[1] = pCurDqLayer->pMv[LIST_1][iMBXY][iIIdx][1];
- BaseMC (&pTempMCRefMem, iXOffset, iYOffset, pMCFunc, 8, 4, iMVs);
-
- if (pCurDqLayer->bUseWeightedBiPredIdc) {
- BiWeightPrediction (pCurDqLayer, &pMCRefMem, &pTempMCRefMem, iRefIndex1, iRefIndex2, bWeightedBipredIdcIs1, 8, 4);
- } else {
- BiPrediction (pCurDqLayer, &pMCRefMem, &pTempMCRefMem, 8, 4);
- }
-
- pMCRefMem.pDstY += (iDstLineLuma << 2);
- pMCRefMem.pDstU += (iDstLineChroma << 1);
- pMCRefMem.pDstV += (iDstLineChroma << 1);
- iMVs[0] = pCurDqLayer->pMv[LIST_0][iMBXY][iIIdx + 4][0];
- iMVs[1] = pCurDqLayer->pMv[LIST_0][iMBXY][iIIdx + 4][1];
- BaseMC (&pMCRefMem, iXOffset, iYOffset + 4, pMCFunc, 8, 4, iMVs);
-
- pTempMCRefMem.pDstY += (iDstLineLuma << 2);
- pTempMCRefMem.pDstU += (iDstLineChroma << 1);
- pTempMCRefMem.pDstV += (iDstLineChroma << 1);
- iMVs[0] = pCurDqLayer->pMv[LIST_1][iMBXY][iIIdx + 4][0];
- iMVs[1] = pCurDqLayer->pMv[LIST_1][iMBXY][iIIdx + 4][1];
- BaseMC (&pTempMCRefMem, iXOffset, iYOffset + 4, pMCFunc, 8, 4, iMVs);
-
- if (pCurDqLayer->bUseWeightedBiPredIdc) {
- BiWeightPrediction (pCurDqLayer, &pMCRefMem, &pTempMCRefMem, iRefIndex1, iRefIndex2, bWeightedBipredIdcIs1, 8, 4);
- } else {
- BiPrediction (pCurDqLayer, &pMCRefMem, &pTempMCRefMem, 8, 4);
- }
- } else { //B_L0_8x4 B_L1_8x4
- int32_t listIdx = IS_TYPE_L0 (iSubMBType) ? LIST_0 : LIST_1;
- iMVs[0] = pCurDqLayer->pMv[listIdx][iMBXY][iIIdx][0];
- iMVs[1] = pCurDqLayer->pMv[listIdx][iMBXY][iIIdx][1];
- BaseMC (&pMCRefMem, iXOffset, iYOffset, pMCFunc, 8, 4, iMVs);
- pMCRefMem.pDstY += (iDstLineLuma << 2);
- pMCRefMem.pDstU += (iDstLineChroma << 1);
- pMCRefMem.pDstV += (iDstLineChroma << 1);
- iMVs[0] = pCurDqLayer->pMv[listIdx][iMBXY][iIIdx + 4][0];
- iMVs[1] = pCurDqLayer->pMv[listIdx][iMBXY][iIIdx + 4][1];
- BaseMC (&pMCRefMem, iXOffset, iYOffset + 4, pMCFunc, 8, 4, iMVs);
- if (bWeightedBipredIdcIs1) {
- int32_t iRefIndex = pCurDqLayer->pRefIndex[listIdx][iMBXY][iIIdx];
- WeightPrediction (pCurDqLayer, &pMCRefMem, listIdx, iRefIndex, 8, 4);
- }
- }
- } else if (IS_SUB_4x8 (iSubMBType)) {
- if (IS_TYPE_L0 (iSubMBType) && IS_TYPE_L1 (iSubMBType)) { //B_Bi_4x8
- iMVs[0] = pCurDqLayer->pMv[LIST_0][iMBXY][iIIdx][0];
- iMVs[1] = pCurDqLayer->pMv[LIST_0][iMBXY][iIIdx][1];
- BaseMC (&pMCRefMem, iXOffset, iYOffset, pMCFunc, 4, 8, iMVs);
- iMVs[0] = pCurDqLayer->pMv[LIST_1][iMBXY][iIIdx][0];
- iMVs[1] = pCurDqLayer->pMv[LIST_1][iMBXY][iIIdx][1];
- BaseMC (&pTempMCRefMem, iXOffset, iYOffset, pMCFunc, 4, 8, iMVs);
-
- if (pCurDqLayer->bUseWeightedBiPredIdc) {
- BiWeightPrediction (pCurDqLayer, &pMCRefMem, &pTempMCRefMem, iRefIndex1, iRefIndex2, bWeightedBipredIdcIs1, 4, 8);
- } else {
- BiPrediction (pCurDqLayer, &pMCRefMem, &pTempMCRefMem, 4, 8);
- }
-
- pMCRefMem.pDstY += 4;
- pMCRefMem.pDstU += 2;
- pMCRefMem.pDstV += 2;
- iMVs[0] = pCurDqLayer->pMv[LIST_0][iMBXY][iIIdx + 1][0];
- iMVs[1] = pCurDqLayer->pMv[LIST_0][iMBXY][iIIdx + 1][1];
- BaseMC (&pMCRefMem, iXOffset + 4, iYOffset, pMCFunc, 4, 8, iMVs);
-
- pTempMCRefMem.pDstY += 4;
- pTempMCRefMem.pDstU += 2;
- pTempMCRefMem.pDstV += 2;
- iMVs[0] = pCurDqLayer->pMv[LIST_1][iMBXY][iIIdx + 1][0];
- iMVs[1] = pCurDqLayer->pMv[LIST_1][iMBXY][iIIdx + 1][1];
- BaseMC (&pTempMCRefMem, iXOffset + 4, iYOffset, pMCFunc, 4, 8, iMVs);
-
- if (pCurDqLayer->bUseWeightedBiPredIdc) {
- BiWeightPrediction (pCurDqLayer, &pMCRefMem, &pTempMCRefMem, iRefIndex1, iRefIndex2, bWeightedBipredIdcIs1, 4, 8);
- } else {
- BiPrediction (pCurDqLayer, &pMCRefMem, &pTempMCRefMem, 4, 8);
- }
- } else { //B_L0_4x8 B_L1_4x8
- int32_t listIdx = IS_TYPE_L0 (iSubMBType) ? LIST_0 : LIST_1;
- iMVs[0] = pCurDqLayer->pMv[listIdx][iMBXY][iIIdx][0];
- iMVs[1] = pCurDqLayer->pMv[listIdx][iMBXY][iIIdx][1];
- BaseMC (&pMCRefMem, iXOffset, iYOffset, pMCFunc, 4, 8, iMVs);
- pMCRefMem.pDstY += 4;
- pMCRefMem.pDstU += 2;
- pMCRefMem.pDstV += 2;
- iMVs[0] = pCurDqLayer->pMv[listIdx][iMBXY][iIIdx + 1][0];
- iMVs[1] = pCurDqLayer->pMv[listIdx][iMBXY][iIIdx + 1][1];
- BaseMC (&pMCRefMem, iXOffset + 4, iYOffset, pMCFunc, 4, 8, iMVs);
- if (bWeightedBipredIdcIs1) {
- int32_t iRefIndex = pCurDqLayer->pRefIndex[listIdx][iMBXY][iIIdx];
- WeightPrediction (pCurDqLayer, &pMCRefMem, listIdx, iRefIndex, 4, 8);
- }
- }
- } else if (IS_SUB_4x4 (iSubMBType)) {
- if (IS_TYPE_L0 (iSubMBType) && IS_TYPE_L1 (iSubMBType)) {
- for (int32_t j = 0; j < 4; j++) {
- int32_t iUVLineStride;
- iJIdx = ((j >> 1) << 2) + (j & 1);
-
- iBlk4X = (j & 1) << 2;
- iBlk4Y = (j >> 1) << 2;
-
- iUVLineStride = (iBlk4X >> 1) + (iBlk4Y >> 1) * iDstLineChroma;
- pMCRefMem.pDstY = pDstY + iBlk4X + iBlk4Y * iDstLineLuma;
- pMCRefMem.pDstU = pDstU + iUVLineStride;
- pMCRefMem.pDstV = pDstV + iUVLineStride;
-
- iMVs[0] = pCurDqLayer->pMv[LIST_0][iMBXY][iIIdx + iJIdx][0];
- iMVs[1] = pCurDqLayer->pMv[LIST_0][iMBXY][iIIdx + iJIdx][1];
- BaseMC (&pMCRefMem, iXOffset + iBlk4X, iYOffset + iBlk4Y, pMCFunc, 4, 4, iMVs);
-
- pTempMCRefMem.pDstY = pDstY2 + iBlk8X + iBlk8Y * iDstLineLuma;
- pTempMCRefMem.pDstU = pDstU2 + iUVLineStride;
- pTempMCRefMem.pDstV = pDstV2 + iUVLineStride;;
-
- iMVs[0] = pCurDqLayer->pMv[LIST_1][iMBXY][iIIdx + iJIdx][0];
- iMVs[1] = pCurDqLayer->pMv[LIST_1][iMBXY][iIIdx + iJIdx][1];
- BaseMC (&pTempMCRefMem, iXOffset + iBlk4X, iYOffset + iBlk4Y, pMCFunc, 4, 4, iMVs);
-
- if (pCurDqLayer->bUseWeightedBiPredIdc) {
- BiWeightPrediction (pCurDqLayer, &pMCRefMem, &pTempMCRefMem, iRefIndex1, iRefIndex2, bWeightedBipredIdcIs1, 4, 4);
- } else {
- BiPrediction (pCurDqLayer, &pMCRefMem, &pTempMCRefMem, 4, 4);
- }
- }
- } else {
- int32_t listIdx = IS_TYPE_L0 (iSubMBType) ? LIST_0 : LIST_1;
- int32_t iRefIndex = pCurDqLayer->pRefIndex[listIdx][iMBXY][iIIdx];
- for (int32_t j = 0; j < 4; j++) {
- int32_t iUVLineStride;
- iJIdx = ((j >> 1) << 2) + (j & 1);
-
- iBlk4X = (j & 1) << 2;
- iBlk4Y = (j >> 1) << 2;
-
- iUVLineStride = (iBlk4X >> 1) + (iBlk4Y >> 1) * iDstLineChroma;
- pMCRefMem.pDstY = pDstY + iBlk4X + iBlk4Y * iDstLineLuma;
- pMCRefMem.pDstU = pDstU + iUVLineStride;
- pMCRefMem.pDstV = pDstV + iUVLineStride;
-
- iMVs[0] = pCurDqLayer->pMv[listIdx][iMBXY][iIIdx + iJIdx][0];
- iMVs[1] = pCurDqLayer->pMv[listIdx][iMBXY][iIIdx + iJIdx][1];
- BaseMC (&pMCRefMem, iXOffset + iBlk4X, iYOffset + iBlk4Y, pMCFunc, 4, 4, iMVs);
- if (bWeightedBipredIdcIs1) {
- WeightPrediction (pCurDqLayer, &pMCRefMem, listIdx, iRefIndex, 4, 4);
- }
- }
- }
- }
- }
- }
-}
-
-int32_t RecChroma (int32_t iMBXY, PWelsDecoderContext pCtx, int16_t* pScoeffLevel, PDqLayer pDqLayer) {
- int32_t iChromaStride = pCtx->pCurDqLayer->pDec->iLinesize[1];
- PIdctFourResAddPredFunc pIdctFourResAddPredFunc = pCtx->pIdctFourResAddPredFunc;
-
- uint8_t i = 0;
- uint8_t uiCbpC = pDqLayer->pCbp[iMBXY] >> 4;
-
- if (1 == uiCbpC || 2 == uiCbpC) {
- for (i = 0; i < 2; i++) {
- int16_t* pRS = pScoeffLevel + 256 + (i << 6);
- uint8_t* pPred = pDqLayer->pPred[i + 1];
- const int8_t* pNzc = pDqLayer->pNzc[iMBXY] + 16 + 2 * i;
-
- /*1 chroma is divided 4 4x4_block to idct*/
- pIdctFourResAddPredFunc (pPred, iChromaStride, pRS, pNzc);
- }
- }
-
- return ERR_NONE;
-}
-
-} // namespace WelsDec
+/*!
+ * \copy
+ * Copyright (c) 2009-2013, Cisco Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * \file rec_mb.c
+ *
+ * \brief implementation for all macroblock decoding process after mb syntax parsing and residual decoding with cavlc.
+ *
+ * \date 3/18/2009 Created
+ *
+ *************************************************************************************
+ */
+
+
+#include "rec_mb.h"
+#include "decode_slice.h"
+
+namespace WelsDec {
+
+void WelsFillRecNeededMbInfo (PWelsDecoderContext pCtx, bool bOutput, PDqLayer pCurLayer) {
+ PPicture pCurPic = pCtx->pDec;
+ int32_t iLumaStride = pCurPic->iLinesize[0];
+ int32_t iChromaStride = pCurPic->iLinesize[1];
+ int32_t iMbX = pCurLayer->iMbX;
+ int32_t iMbY = pCurLayer->iMbY;
+
+ pCurLayer->iLumaStride = iLumaStride;
+ pCurLayer->iChromaStride = iChromaStride;
+
+ if (bOutput) {
+ pCurLayer->pPred[0] = pCurPic->pData[0] + ((iMbY * iLumaStride + iMbX) << 4);
+ pCurLayer->pPred[1] = pCurPic->pData[1] + ((iMbY * iChromaStride + iMbX) << 3);
+ pCurLayer->pPred[2] = pCurPic->pData[2] + ((iMbY * iChromaStride + iMbX) << 3);
+ }
+}
+
+int32_t RecI8x8Mb (int32_t iMbXy, PWelsDecoderContext pCtx, int16_t* pScoeffLevel, PDqLayer pDqLayer) {
+ RecI8x8Luma (iMbXy, pCtx, pScoeffLevel, pDqLayer);
+ RecI4x4Chroma (iMbXy, pCtx, pScoeffLevel, pDqLayer);
+ return ERR_NONE;
+}
+
+int32_t RecI8x8Luma (int32_t iMbXy, PWelsDecoderContext pCtx, int16_t* pScoeffLevel, PDqLayer pDqLayer) {
+ /*****get local variable from outer variable********/
+ /*prediction info*/
+ uint8_t* pPred = pDqLayer->pPred[0];
+
+ int32_t iLumaStride = pDqLayer->iLumaStride;
+ int32_t* pBlockOffset = pCtx->iDecBlockOffsetArray;
+ PGetIntraPred8x8Func* pGetI8x8LumaPredFunc = pCtx->pGetI8x8LumaPredFunc;
+
+ int8_t* pIntra8x8PredMode = pDqLayer->pIntra4x4FinalMode[iMbXy]; // I_NxN
+ int16_t* pRS = pScoeffLevel;
+ /*itransform info*/
+ PIdctResAddPredFunc pIdctResAddPredFunc = pCtx->pIdctResAddPredFunc8x8;
+
+ /*************local variable********************/
+ uint8_t i = 0;
+ bool bTLAvail[4], bTRAvail[4];
+ // Top-Right : Left : Top-Left : Top
+ bTLAvail[0] = !! (pDqLayer->pIntraNxNAvailFlag[iMbXy] & 0x02);
+ bTLAvail[1] = !! (pDqLayer->pIntraNxNAvailFlag[iMbXy] & 0x01);
+ bTLAvail[2] = !! (pDqLayer->pIntraNxNAvailFlag[iMbXy] & 0x04);
+ bTLAvail[3] = true;
+
+ bTRAvail[0] = !! (pDqLayer->pIntraNxNAvailFlag[iMbXy] & 0x01);
+ bTRAvail[1] = !! (pDqLayer->pIntraNxNAvailFlag[iMbXy] & 0x08);
+ bTRAvail[2] = true;
+ bTRAvail[3] = false;
+
+ /*************real process*********************/
+ for (i = 0; i < 4; i++) {
+
+ uint8_t* pPredI8x8 = pPred + pBlockOffset[i << 2];
+ uint8_t uiMode = pIntra8x8PredMode[g_kuiScan4[i << 2]];
+
+ pGetI8x8LumaPredFunc[uiMode] (pPredI8x8, iLumaStride, bTLAvail[i], bTRAvail[i]);
+
+ int32_t iIndex = g_kuiMbCountScan4Idx[i << 2];
+ if (pDqLayer->pNzc[iMbXy][iIndex] || pDqLayer->pNzc[iMbXy][iIndex + 1] || pDqLayer->pNzc[iMbXy][iIndex + 4]
+ || pDqLayer->pNzc[iMbXy][iIndex + 5]) {
+ int16_t* pRSI8x8 = &pRS[i << 6];
+ pIdctResAddPredFunc (pPredI8x8, iLumaStride, pRSI8x8);
+ }
+ }
+
+ return ERR_NONE;
+}
+
+int32_t RecI4x4Mb (int32_t iMBXY, PWelsDecoderContext pCtx, int16_t* pScoeffLevel, PDqLayer pDqLayer) {
+ RecI4x4Luma (iMBXY, pCtx, pScoeffLevel, pDqLayer);
+ RecI4x4Chroma (iMBXY, pCtx, pScoeffLevel, pDqLayer);
+ return ERR_NONE;
+}
+
+
+int32_t RecI4x4Luma (int32_t iMBXY, PWelsDecoderContext pCtx, int16_t* pScoeffLevel, PDqLayer pDqLayer) {
+ /*****get local variable from outer variable********/
+ /*prediction info*/
+ uint8_t* pPred = pDqLayer->pPred[0];
+
+ int32_t iLumaStride = pDqLayer->iLumaStride;
+ int32_t* pBlockOffset = pCtx->iDecBlockOffsetArray;
+ PGetIntraPredFunc* pGetI4x4LumaPredFunc = pCtx->pGetI4x4LumaPredFunc;
+
+ int8_t* pIntra4x4PredMode = pDqLayer->pIntra4x4FinalMode[iMBXY];
+ int16_t* pRS = pScoeffLevel;
+ /*itransform info*/
+ PIdctResAddPredFunc pIdctResAddPredFunc = pCtx->pIdctResAddPredFunc;
+
+
+ /*************local variable********************/
+ uint8_t i = 0;
+
+ /*************real process*********************/
+ for (i = 0; i < 16; i++) {
+
+ uint8_t* pPredI4x4 = pPred + pBlockOffset[i];
+ uint8_t uiMode = pIntra4x4PredMode[g_kuiScan4[i]];
+
+ pGetI4x4LumaPredFunc[uiMode] (pPredI4x4, iLumaStride);
+
+ if (pDqLayer->pNzc[iMBXY][g_kuiMbCountScan4Idx[i]]) {
+ int16_t* pRSI4x4 = &pRS[i << 4];
+ pIdctResAddPredFunc (pPredI4x4, iLumaStride, pRSI4x4);
+ }
+ }
+
+ return ERR_NONE;
+}
+
+
+int32_t RecI4x4Chroma (int32_t iMBXY, PWelsDecoderContext pCtx, int16_t* pScoeffLevel, PDqLayer pDqLayer) {
+ int32_t iChromaStride = pCtx->pCurDqLayer->pDec->iLinesize[1];
+
+ int8_t iChromaPredMode = pDqLayer->pChromaPredMode[iMBXY];
+
+ PGetIntraPredFunc* pGetIChromaPredFunc = pCtx->pGetIChromaPredFunc;
+
+ uint8_t* pPred = pDqLayer->pPred[1];
+
+ pGetIChromaPredFunc[iChromaPredMode] (pPred, iChromaStride);
+ pPred = pDqLayer->pPred[2];
+ pGetIChromaPredFunc[iChromaPredMode] (pPred, iChromaStride);
+
+ RecChroma (iMBXY, pCtx, pScoeffLevel, pDqLayer);
+
+ return ERR_NONE;
+}
+
+
+int32_t RecI16x16Mb (int32_t iMBXY, PWelsDecoderContext pCtx, int16_t* pScoeffLevel, PDqLayer pDqLayer) {
+ /*decoder use, encoder no use*/
+ int8_t iI16x16PredMode = pDqLayer->pIntraPredMode[iMBXY][7];
+ int8_t iChromaPredMode = pDqLayer->pChromaPredMode[iMBXY];
+ PGetIntraPredFunc* pGetIChromaPredFunc = pCtx->pGetIChromaPredFunc;
+ PGetIntraPredFunc* pGetI16x16LumaPredFunc = pCtx->pGetI16x16LumaPredFunc;
+ int32_t iUVStride = pCtx->pCurDqLayer->pDec->iLinesize[1];
+
+ /*common use by decoder&encoder*/
+ int32_t iYStride = pDqLayer->iLumaStride;
+ int16_t* pRS = pScoeffLevel;
+
+ uint8_t* pPred = pDqLayer->pPred[0];
+
+ PIdctFourResAddPredFunc pIdctFourResAddPredFunc = pCtx->pIdctFourResAddPredFunc;
+
+ /*decode i16x16 y*/
+ pGetI16x16LumaPredFunc[iI16x16PredMode] (pPred, iYStride);
+
+ /*1 mb is divided 16 4x4_block to idct*/
+ const int8_t* pNzc = pDqLayer->pNzc[iMBXY];
+ pIdctFourResAddPredFunc (pPred + 0 * iYStride + 0, iYStride, pRS + 0 * 64, pNzc + 0);
+ pIdctFourResAddPredFunc (pPred + 0 * iYStride + 8, iYStride, pRS + 1 * 64, pNzc + 2);
+ pIdctFourResAddPredFunc (pPred + 8 * iYStride + 0, iYStride, pRS + 2 * 64, pNzc + 8);
+ pIdctFourResAddPredFunc (pPred + 8 * iYStride + 8, iYStride, pRS + 3 * 64, pNzc + 10);
+
+ /*decode intra mb cb&cr*/
+ pPred = pDqLayer->pPred[1];
+ pGetIChromaPredFunc[iChromaPredMode] (pPred, iUVStride);
+ pPred = pDqLayer->pPred[2];
+ pGetIChromaPredFunc[iChromaPredMode] (pPred, iUVStride);
+ RecChroma (iMBXY, pCtx, pScoeffLevel, pDqLayer);
+
+ return ERR_NONE;
+}
+
+
+//according to current 8*8 block ref_index to gain reference picture
+static inline void GetRefPic (sMCRefMember* pMCRefMem, PWelsDecoderContext pCtx, int8_t* pRefIdxList,
+ int32_t iIndex, int32_t listIdx) {
+ PPicture pRefPic;
+
+ int8_t iRefIdx = pRefIdxList[iIndex];
+ if (iRefIdx >= 0) {
+ pRefPic = pCtx->sRefPic.pRefList[listIdx][iRefIdx];
+
+ if (pRefPic != NULL) {
+ pMCRefMem->iSrcLineLuma = pRefPic->iLinesize[0];
+ pMCRefMem->iSrcLineChroma = pRefPic->iLinesize[1];
+
+ pMCRefMem->pSrcY = pRefPic->pData[0];
+ pMCRefMem->pSrcU = pRefPic->pData[1];
+ pMCRefMem->pSrcV = pRefPic->pData[2];
+ }
+ }
+}
+
+
+#ifndef MC_FLOW_SIMPLE_JUDGE
+#define MC_FLOW_SIMPLE_JUDGE 1
+#endif //MC_FLOW_SIMPLE_JUDGE
+void BaseMC (sMCRefMember* pMCRefMem, int32_t iXOffset, int32_t iYOffset, SMcFunc* pMCFunc,
+ int32_t iBlkWidth, int32_t iBlkHeight, int16_t iMVs[2]) {
+ int32_t iFullMVx = (iXOffset << 2) + iMVs[0]; //quarter pixel
+ int32_t iFullMVy = (iYOffset << 2) + iMVs[1];
+ iFullMVx = WELS_CLIP3 (iFullMVx, ((-PADDING_LENGTH + 2) * (1 << 2)),
+ ((pMCRefMem->iPicWidth + PADDING_LENGTH - 19) * (1 << 2)));
+ iFullMVy = WELS_CLIP3 (iFullMVy, ((-PADDING_LENGTH + 2) * (1 << 2)),
+ ((pMCRefMem->iPicHeight + PADDING_LENGTH - 19) * (1 << 2)));
+
+ int32_t iSrcPixOffsetLuma = (iFullMVx >> 2) + (iFullMVy >> 2) * pMCRefMem->iSrcLineLuma;
+ int32_t iSrcPixOffsetChroma = (iFullMVx >> 3) + (iFullMVy >> 3) * pMCRefMem->iSrcLineChroma;
+
+ int32_t iBlkWidthChroma = iBlkWidth >> 1;
+ int32_t iBlkHeightChroma = iBlkHeight >> 1;
+
+ uint8_t* pSrcY = pMCRefMem->pSrcY + iSrcPixOffsetLuma;
+ uint8_t* pSrcU = pMCRefMem->pSrcU + iSrcPixOffsetChroma;
+ uint8_t* pSrcV = pMCRefMem->pSrcV + iSrcPixOffsetChroma;
+ uint8_t* pDstY = pMCRefMem->pDstY;
+ uint8_t* pDstU = pMCRefMem->pDstU;
+ uint8_t* pDstV = pMCRefMem->pDstV;
+
+ pMCFunc->pMcLumaFunc (pSrcY, pMCRefMem->iSrcLineLuma, pDstY, pMCRefMem->iDstLineLuma, iFullMVx, iFullMVy, iBlkWidth,
+ iBlkHeight);
+ pMCFunc->pMcChromaFunc (pSrcU, pMCRefMem->iSrcLineChroma, pDstU, pMCRefMem->iDstLineChroma, iFullMVx, iFullMVy,
+ iBlkWidthChroma, iBlkHeightChroma);
+ pMCFunc->pMcChromaFunc (pSrcV, pMCRefMem->iSrcLineChroma, pDstV, pMCRefMem->iDstLineChroma, iFullMVx, iFullMVy,
+ iBlkWidthChroma, iBlkHeightChroma);
+
+}
+
+static void WeightPrediction (PDqLayer pCurDqLayer, sMCRefMember* pMCRefMem, int32_t listIdx, int32_t iRefIdx,
+ int32_t iBlkWidth,
+ int32_t iBlkHeight) {
+
+
+ int32_t iLog2denom, iWoc, iOoc;
+ int32_t iPredTemp, iLineStride;
+ int32_t iPixel = 0;
+ uint8_t* pDst;
+ //luma
+ iLog2denom = pCurDqLayer->pPredWeightTable->uiLumaLog2WeightDenom;
+ iWoc = pCurDqLayer->pPredWeightTable->sPredList[listIdx].iLumaWeight[iRefIdx];
+ iOoc = pCurDqLayer->pPredWeightTable->sPredList[listIdx].iLumaOffset[iRefIdx];
+ iLineStride = pMCRefMem->iDstLineLuma;
+
+ for (int i = 0; i < iBlkHeight; i++) {
+ for (int j = 0; j < iBlkWidth; j++) {
+ iPixel = j + i * (iLineStride);
+ if (iLog2denom >= 1) {
+ iPredTemp = ((pMCRefMem->pDstY[iPixel] * iWoc + (1 << (iLog2denom - 1))) >> iLog2denom) + iOoc;
+
+ pMCRefMem->pDstY[iPixel] = WELS_CLIP3 (iPredTemp, 0, 255);
+ } else {
+ iPredTemp = pMCRefMem->pDstY[iPixel] * iWoc + iOoc;
+
+ pMCRefMem->pDstY[iPixel] = WELS_CLIP3 (iPredTemp, 0, 255);
+
+ }
+ }
+ }
+
+
+ //UV
+ iBlkWidth = iBlkWidth >> 1;
+ iBlkHeight = iBlkHeight >> 1;
+ iLog2denom = pCurDqLayer->pPredWeightTable->uiChromaLog2WeightDenom;
+ iLineStride = pMCRefMem->iDstLineChroma;
+
+ for (int i = 0; i < 2; i++) {
+
+
+ //iLog2denom = pCurDqLayer->pPredWeightTable->uiChromaLog2WeightDenom;
+ iWoc = pCurDqLayer->pPredWeightTable->sPredList[listIdx].iChromaWeight[iRefIdx][i];
+ iOoc = pCurDqLayer->pPredWeightTable->sPredList[listIdx].iChromaOffset[iRefIdx][i];
+ pDst = i ? pMCRefMem->pDstV : pMCRefMem->pDstU;
+ //iLineStride = pMCRefMem->iDstLineChroma;
+
+ for (int i = 0; i < iBlkHeight ; i++) {
+ for (int j = 0; j < iBlkWidth; j++) {
+ iPixel = j + i * (iLineStride);
+ if (iLog2denom >= 1) {
+ iPredTemp = ((pDst[iPixel] * iWoc + (1 << (iLog2denom - 1))) >> iLog2denom) + iOoc;
+
+ pDst[iPixel] = WELS_CLIP3 (iPredTemp, 0, 255);
+ } else {
+ iPredTemp = pDst[iPixel] * iWoc + iOoc;
+
+ pDst[iPixel] = WELS_CLIP3 (iPredTemp, 0, 255);
+
+ }
+ }
+
+ }
+
+
+ }
+}
+
+static void BiWeightPrediction (PDqLayer pCurDqLayer, sMCRefMember* pMCRefMem, sMCRefMember* pTempMCRefMem,
+ int32_t iRefIdx1, int32_t iRefIdx2, bool bWeightedBipredIdcIs1, int32_t iBlkWidth,
+ int32_t iBlkHeight) {
+ int32_t iWoc1 = 0, iOoc1 = 0, iWoc2 = 0, iOoc2 = 0;
+ int32_t iPredTemp, iLineStride;
+ int32_t iPixel = 0;
+ //luma
+ int32_t iLog2denom = pCurDqLayer->pPredWeightTable->uiLumaLog2WeightDenom;
+ if (bWeightedBipredIdcIs1) {
+ iWoc1 = pCurDqLayer->pPredWeightTable->sPredList[LIST_0].iLumaWeight[iRefIdx1];
+ iOoc1 = pCurDqLayer->pPredWeightTable->sPredList[LIST_0].iLumaOffset[iRefIdx1];
+ iWoc2 = pCurDqLayer->pPredWeightTable->sPredList[LIST_1].iLumaWeight[iRefIdx2];
+ iOoc2 = pCurDqLayer->pPredWeightTable->sPredList[LIST_1].iLumaOffset[iRefIdx2];
+ } else {
+ iWoc1 = pCurDqLayer->pPredWeightTable->iImplicitWeight[iRefIdx1][iRefIdx2];
+ iWoc2 = 64 - iWoc1;
+ }
+ iLineStride = pMCRefMem->iDstLineLuma;
+
+ for (int i = 0; i < iBlkHeight; i++) {
+ for (int j = 0; j < iBlkWidth; j++) {
+ iPixel = j + i * (iLineStride);
+ iPredTemp = ((pMCRefMem->pDstY[iPixel] * iWoc1 + pTempMCRefMem->pDstY[iPixel] * iWoc2 + (1 << iLog2denom)) >>
+ (iLog2denom + 1)) + ((iOoc1 + iOoc2 + 1) >> 1);
+ pMCRefMem->pDstY[iPixel] = WELS_CLIP3 (iPredTemp, 0, 255);
+ }
+ }
+
+ //UV
+ iBlkWidth = iBlkWidth >> 1;
+ iBlkHeight = iBlkHeight >> 1;
+ iLog2denom = pCurDqLayer->pPredWeightTable->uiChromaLog2WeightDenom;
+ iLineStride = pMCRefMem->iDstLineChroma;
+
+ uint8_t* pDst;
+ uint8_t* pTempDst;
+ for (int k = 0; k < 2; k++) {
+ //iLog2denom = pCurDqLayer->pPredWeightTable->uiChromaLog2WeightDenom;
+ if (bWeightedBipredIdcIs1) {
+ iWoc1 = pCurDqLayer->pPredWeightTable->sPredList[LIST_0].iChromaWeight[iRefIdx1][k];
+ iOoc1 = pCurDqLayer->pPredWeightTable->sPredList[LIST_0].iChromaOffset[iRefIdx1][k];
+ iWoc2 = pCurDqLayer->pPredWeightTable->sPredList[LIST_1].iChromaWeight[iRefIdx2][k];
+ iOoc2 = pCurDqLayer->pPredWeightTable->sPredList[LIST_1].iChromaOffset[iRefIdx2][k];
+ }
+ pDst = k ? pMCRefMem->pDstV : pMCRefMem->pDstU;
+ pTempDst = k ? pTempMCRefMem->pDstV : pTempMCRefMem->pDstU;
+ //iLineStride = pMCRefMem->iDstLineChroma;
+
+ for (int i = 0; i < iBlkHeight; i++) {
+ for (int j = 0; j < iBlkWidth; j++) {
+ iPixel = j + i * (iLineStride);
+ iPredTemp = ((pDst[iPixel] * iWoc1 + pTempDst[iPixel] * iWoc2 + (1 << iLog2denom)) >> (iLog2denom + 1)) + ((
+ iOoc1 + iOoc2 + 1) >> 1);
+ pDst[iPixel] = WELS_CLIP3 (iPredTemp, 0, 255);
+ }
+ }
+ }
+}
+
+static void BiPrediction (PDqLayer pCurDqLayer, sMCRefMember* pMCRefMem, sMCRefMember* pTempMCRefMem, int32_t iBlkWidth,
+ int32_t iBlkHeight) {
+ int32_t iPredTemp, iLineStride;
+ int32_t iPixel = 0;
+ //luma
+ iLineStride = pMCRefMem->iDstLineLuma;
+
+ for (int i = 0; i < iBlkHeight; i++) {
+ for (int j = 0; j < iBlkWidth; j++) {
+ iPixel = j + i * (iLineStride);
+ iPredTemp = (pMCRefMem->pDstY[iPixel] + pTempMCRefMem->pDstY[iPixel] + 1) >> 1;
+ pMCRefMem->pDstY[iPixel] = WELS_CLIP3 (iPredTemp, 0, 255);
+ }
+ }
+
+ //UV
+ iBlkWidth = iBlkWidth >> 1;
+ iBlkHeight = iBlkHeight >> 1;
+ iLineStride = pMCRefMem->iDstLineChroma;
+
+ uint8_t* pDst;
+ uint8_t* pTempDst;
+ for (int k = 0; k < 2; k++) {
+ pDst = k ? pMCRefMem->pDstV : pMCRefMem->pDstU;
+ pTempDst = k ? pTempMCRefMem->pDstV : pTempMCRefMem->pDstU;
+ //iLineStride = pMCRefMem->iDstLineChroma;
+
+ for (int i = 0; i < iBlkHeight; i++) {
+ for (int j = 0; j < iBlkWidth; j++) {
+ iPixel = j + i * (iLineStride);
+ iPredTemp = (pDst[iPixel] + pTempDst[iPixel] + 1) >> 1;
+ pDst[iPixel] = WELS_CLIP3 (iPredTemp, 0, 255);
+ }
+ }
+ }
+}
+
+void GetInterPred (uint8_t* pPredY, uint8_t* pPredCb, uint8_t* pPredCr, PWelsDecoderContext pCtx) {
+ sMCRefMember pMCRefMem;
+ PDqLayer pCurDqLayer = pCtx->pCurDqLayer;
+ SMcFunc* pMCFunc = &pCtx->sMcFunc;
+
+ int32_t iMBXY = pCurDqLayer->iMbXyIndex;
+
+ int16_t iMVs[2] = {0};
+
+ uint32_t iMBType = pCurDqLayer->pMbType[iMBXY];
+
+ int32_t iMBOffsetX = pCurDqLayer->iMbX << 4;
+ int32_t iMBOffsetY = pCurDqLayer->iMbY << 4;
+
+ int32_t iDstLineLuma = pCtx->pDec->iLinesize[0];
+ int32_t iDstLineChroma = pCtx->pDec->iLinesize[1];
+
+ int32_t iBlk8X, iBlk8Y, iBlk4X, iBlk4Y, i, j, iIIdx, iJIdx;
+
+ pMCRefMem.iPicWidth = (pCurDqLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.iMbWidth << 4);
+ pMCRefMem.iPicHeight = (pCurDqLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.iMbHeight << 4);
+
+ pMCRefMem.pDstY = pPredY;
+ pMCRefMem.pDstU = pPredCb;
+ pMCRefMem.pDstV = pPredCr;
+
+ pMCRefMem.iDstLineLuma = iDstLineLuma;
+ pMCRefMem.iDstLineChroma = iDstLineChroma;
+
+ int32_t iRefIndex = 0;
+
+ switch (iMBType) {
+ case MB_TYPE_SKIP:
+ case MB_TYPE_16x16:
+ iMVs[0] = pCurDqLayer->pMv[0][iMBXY][0][0];
+ iMVs[1] = pCurDqLayer->pMv[0][iMBXY][0][1];
+ GetRefPic (&pMCRefMem, pCtx, pCurDqLayer->pRefIndex[0][iMBXY], 0, LIST_0);
+ BaseMC (&pMCRefMem, iMBOffsetX, iMBOffsetY, pMCFunc, 16, 16, iMVs);
+
+ if (pCurDqLayer->bUseWeightPredictionFlag) {
+ iRefIndex = pCurDqLayer->pRefIndex[0][iMBXY][0];
+ WeightPrediction (pCurDqLayer, &pMCRefMem, LIST_0, iRefIndex, 16, 16);
+ }
+ break;
+ case MB_TYPE_16x8:
+ iMVs[0] = pCurDqLayer->pMv[0][iMBXY][0][0];
+ iMVs[1] = pCurDqLayer->pMv[0][iMBXY][0][1];
+ GetRefPic (&pMCRefMem, pCtx, pCurDqLayer->pRefIndex[0][iMBXY], 0, LIST_0);
+ BaseMC (&pMCRefMem, iMBOffsetX, iMBOffsetY, pMCFunc, 16, 8, iMVs);
+
+ if (pCurDqLayer->bUseWeightPredictionFlag) {
+ iRefIndex = pCurDqLayer->pRefIndex[0][iMBXY][0];
+ WeightPrediction (pCurDqLayer, &pMCRefMem, LIST_0, iRefIndex, 16, 8);
+ }
+
+ iMVs[0] = pCurDqLayer->pMv[0][iMBXY][8][0];
+ iMVs[1] = pCurDqLayer->pMv[0][iMBXY][8][1];
+ GetRefPic (&pMCRefMem, pCtx, pCurDqLayer->pRefIndex[0][iMBXY], 8, LIST_0);
+ pMCRefMem.pDstY = pPredY + (iDstLineLuma << 3);
+ pMCRefMem.pDstU = pPredCb + (iDstLineChroma << 2);
+ pMCRefMem.pDstV = pPredCr + (iDstLineChroma << 2);
+ BaseMC (&pMCRefMem, iMBOffsetX, iMBOffsetY + 8, pMCFunc, 16, 8, iMVs);
+
+ if (pCurDqLayer->bUseWeightPredictionFlag) {
+ iRefIndex = pCurDqLayer->pRefIndex[0][iMBXY][8];
+ WeightPrediction (pCurDqLayer, &pMCRefMem, LIST_0, iRefIndex, 16, 8);
+ }
+ break;
+ case MB_TYPE_8x16:
+ iMVs[0] = pCurDqLayer->pMv[0][iMBXY][0][0];
+ iMVs[1] = pCurDqLayer->pMv[0][iMBXY][0][1];
+ GetRefPic (&pMCRefMem, pCtx, pCurDqLayer->pRefIndex[0][iMBXY], 0, LIST_0);
+ BaseMC (&pMCRefMem, iMBOffsetX, iMBOffsetY, pMCFunc, 8, 16, iMVs);
+ if (pCurDqLayer->bUseWeightPredictionFlag) {
+ iRefIndex = pCurDqLayer->pRefIndex[0][iMBXY][0];
+ WeightPrediction (pCurDqLayer, &pMCRefMem, LIST_0, iRefIndex, 8, 16);
+ }
+
+ iMVs[0] = pCurDqLayer->pMv[0][iMBXY][2][0];
+ iMVs[1] = pCurDqLayer->pMv[0][iMBXY][2][1];
+ GetRefPic (&pMCRefMem, pCtx, pCurDqLayer->pRefIndex[0][iMBXY], 2, LIST_0);
+ pMCRefMem.pDstY = pPredY + 8;
+ pMCRefMem.pDstU = pPredCb + 4;
+ pMCRefMem.pDstV = pPredCr + 4;
+ BaseMC (&pMCRefMem, iMBOffsetX + 8, iMBOffsetY, pMCFunc, 8, 16, iMVs);
+
+ if (pCurDqLayer->bUseWeightPredictionFlag) {
+ iRefIndex = pCurDqLayer->pRefIndex[0][iMBXY][2];
+ WeightPrediction (pCurDqLayer, &pMCRefMem, LIST_0, iRefIndex, 8, 16);
+ }
+ break;
+ case MB_TYPE_8x8:
+ case MB_TYPE_8x8_REF0: {
+ uint32_t iSubMBType;
+ int32_t iXOffset, iYOffset;
+ uint8_t* pDstY, *pDstU, *pDstV;
+ for (i = 0; i < 4; i++) {
+ iSubMBType = pCurDqLayer->pSubMbType[iMBXY][i];
+ iBlk8X = (i & 1) << 3;
+ iBlk8Y = (i >> 1) << 3;
+ iXOffset = iMBOffsetX + iBlk8X;
+ iYOffset = iMBOffsetY + iBlk8Y;
+
+ iIIdx = ((i >> 1) << 3) + ((i & 1) << 1);
+ GetRefPic (&pMCRefMem, pCtx, pCurDqLayer->pRefIndex[0][iMBXY], iIIdx, LIST_0);
+ iRefIndex = pCurDqLayer->bUseWeightPredictionFlag ? pCurDqLayer->pRefIndex[0][iMBXY][iIIdx] : 0;
+
+ pDstY = pPredY + iBlk8X + iBlk8Y * iDstLineLuma;
+ pDstU = pPredCb + (iBlk8X >> 1) + (iBlk8Y >> 1) * iDstLineChroma;
+ pDstV = pPredCr + (iBlk8X >> 1) + (iBlk8Y >> 1) * iDstLineChroma;
+ pMCRefMem.pDstY = pDstY;
+ pMCRefMem.pDstU = pDstU;
+ pMCRefMem.pDstV = pDstV;
+ switch (iSubMBType) {
+ case SUB_MB_TYPE_8x8:
+ iMVs[0] = pCurDqLayer->pMv[0][iMBXY][iIIdx][0];
+ iMVs[1] = pCurDqLayer->pMv[0][iMBXY][iIIdx][1];
+ BaseMC (&pMCRefMem, iXOffset, iYOffset, pMCFunc, 8, 8, iMVs);
+ if (pCurDqLayer->bUseWeightPredictionFlag) {
+
+ WeightPrediction (pCurDqLayer, &pMCRefMem, LIST_0, iRefIndex, 8, 8);
+ }
+
+ break;
+ case SUB_MB_TYPE_8x4:
+ iMVs[0] = pCurDqLayer->pMv[0][iMBXY][iIIdx][0];
+ iMVs[1] = pCurDqLayer->pMv[0][iMBXY][iIIdx][1];
+ BaseMC (&pMCRefMem, iXOffset, iYOffset, pMCFunc, 8, 4, iMVs);
+ if (pCurDqLayer->bUseWeightPredictionFlag) {
+
+ WeightPrediction (pCurDqLayer, &pMCRefMem, LIST_0, iRefIndex, 8, 4);
+ }
+
+
+ iMVs[0] = pCurDqLayer->pMv[0][iMBXY][iIIdx + 4][0];
+ iMVs[1] = pCurDqLayer->pMv[0][iMBXY][iIIdx + 4][1];
+ pMCRefMem.pDstY += (iDstLineLuma << 2);
+ pMCRefMem.pDstU += (iDstLineChroma << 1);
+ pMCRefMem.pDstV += (iDstLineChroma << 1);
+ BaseMC (&pMCRefMem, iXOffset, iYOffset + 4, pMCFunc, 8, 4, iMVs);
+ if (pCurDqLayer->bUseWeightPredictionFlag) {
+
+ WeightPrediction (pCurDqLayer, &pMCRefMem, LIST_0, iRefIndex, 8, 4);
+ }
+
+ break;
+ case SUB_MB_TYPE_4x8:
+ iMVs[0] = pCurDqLayer->pMv[0][iMBXY][iIIdx][0];
+ iMVs[1] = pCurDqLayer->pMv[0][iMBXY][iIIdx][1];
+ BaseMC (&pMCRefMem, iXOffset, iYOffset, pMCFunc, 4, 8, iMVs);
+ if (pCurDqLayer->bUseWeightPredictionFlag) {
+
+ WeightPrediction (pCurDqLayer, &pMCRefMem, LIST_0, iRefIndex, 4, 8);
+ }
+
+
+ iMVs[0] = pCurDqLayer->pMv[0][iMBXY][iIIdx + 1][0];
+ iMVs[1] = pCurDqLayer->pMv[0][iMBXY][iIIdx + 1][1];
+ pMCRefMem.pDstY += 4;
+ pMCRefMem.pDstU += 2;
+ pMCRefMem.pDstV += 2;
+ BaseMC (&pMCRefMem, iXOffset + 4, iYOffset, pMCFunc, 4, 8, iMVs);
+ if (pCurDqLayer->bUseWeightPredictionFlag) {
+
+ WeightPrediction (pCurDqLayer, &pMCRefMem, LIST_0, iRefIndex, 4, 8);
+ }
+
+ break;
+ case SUB_MB_TYPE_4x4: {
+ for (j = 0; j < 4; j++) {
+ int32_t iUVLineStride;
+ iJIdx = ((j >> 1) << 2) + (j & 1);
+
+ iBlk4X = (j & 1) << 2;
+ iBlk4Y = (j >> 1) << 2;
+
+ iUVLineStride = (iBlk4X >> 1) + (iBlk4Y >> 1) * iDstLineChroma;
+ pMCRefMem.pDstY = pDstY + iBlk4X + iBlk4Y * iDstLineLuma;
+ pMCRefMem.pDstU = pDstU + iUVLineStride;
+ pMCRefMem.pDstV = pDstV + iUVLineStride;
+
+ iMVs[0] = pCurDqLayer->pMv[0][iMBXY][iIIdx + iJIdx][0];
+ iMVs[1] = pCurDqLayer->pMv[0][iMBXY][iIIdx + iJIdx][1];
+ BaseMC (&pMCRefMem, iXOffset + iBlk4X, iYOffset + iBlk4Y, pMCFunc, 4, 4, iMVs);
+ if (pCurDqLayer->bUseWeightPredictionFlag) {
+
+ WeightPrediction (pCurDqLayer, &pMCRefMem, LIST_0, iRefIndex, 4, 4);
+ }
+
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void GetInterBPred (uint8_t* pPredYCbCr[3], uint8_t* pTempPredYCbCr[3], PWelsDecoderContext pCtx) {
+ sMCRefMember pMCRefMem;
+ sMCRefMember pTempMCRefMem;
+
+ PDqLayer pCurDqLayer = pCtx->pCurDqLayer;
+ SMcFunc* pMCFunc = &pCtx->sMcFunc;
+
+ int32_t iMBXY = pCurDqLayer->iMbXyIndex;
+
+ int16_t iMVs[2] = { 0 };
+
+ uint32_t iMBType = pCurDqLayer->pMbType[iMBXY];
+
+ int32_t iMBOffsetX = pCurDqLayer->iMbX << 4;
+ int32_t iMBOffsetY = pCurDqLayer->iMbY << 4;
+
+ int32_t iDstLineLuma = pCtx->pDec->iLinesize[0];
+ int32_t iDstLineChroma = pCtx->pDec->iLinesize[1];
+
+
+ pMCRefMem.iPicWidth = (pCurDqLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.iMbWidth << 4);
+ pMCRefMem.iPicHeight = (pCurDqLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.iMbHeight << 4);
+
+ pMCRefMem.pDstY = pPredYCbCr[0];
+ pMCRefMem.pDstU = pPredYCbCr[1];
+ pMCRefMem.pDstV = pPredYCbCr[2];
+
+ pMCRefMem.iDstLineLuma = iDstLineLuma;
+ pMCRefMem.iDstLineChroma = iDstLineChroma;
+
+ pTempMCRefMem = pMCRefMem;
+ pTempMCRefMem.pDstY = pTempPredYCbCr[0];
+ pTempMCRefMem.pDstU = pTempPredYCbCr[1];
+ pTempMCRefMem.pDstV = pTempPredYCbCr[2];
+
+
+ int32_t iRefIndex1 = 0;
+ int32_t iRefIndex2 = 0;
+
+ bool bWeightedBipredIdcIs1 = pCurDqLayer->sLayerInfo.pPps->uiWeightedBipredIdc == 1;
+
+ if (IS_INTER_16x16 (iMBType)) {
+ if (IS_TYPE_L0 (iMBType) && IS_TYPE_L1 (iMBType)) {
+ iMVs[0] = pCurDqLayer->pMv[LIST_0][iMBXY][0][0];
+ iMVs[1] = pCurDqLayer->pMv[LIST_0][iMBXY][0][1];
+ GetRefPic (&pMCRefMem, pCtx, pCurDqLayer->pRefIndex[LIST_0][iMBXY], 0, LIST_0);
+ BaseMC (&pMCRefMem, iMBOffsetX, iMBOffsetY, pMCFunc, 16, 16, iMVs);
+
+ iMVs[0] = pCurDqLayer->pMv[LIST_1][iMBXY][0][0];
+ iMVs[1] = pCurDqLayer->pMv[LIST_1][iMBXY][0][1];
+ GetRefPic (&pTempMCRefMem, pCtx, pCurDqLayer->pRefIndex[LIST_1][iMBXY], 0, LIST_1);
+ BaseMC (&pTempMCRefMem, iMBOffsetX, iMBOffsetY, pMCFunc, 16, 16, iMVs);
+ iRefIndex1 = pCurDqLayer->pRefIndex[LIST_0][iMBXY][0];
+ iRefIndex2 = pCurDqLayer->pRefIndex[LIST_1][iMBXY][0];
+ if (pCurDqLayer->bUseWeightedBiPredIdc) {
+ BiWeightPrediction (pCurDqLayer, &pMCRefMem, &pTempMCRefMem, iRefIndex1, iRefIndex2, bWeightedBipredIdcIs1, 16, 16);
+ } else {
+ BiPrediction (pCurDqLayer, &pMCRefMem, &pTempMCRefMem, 16, 16);
+ }
+ } else {
+ int32_t listIdx = (iMBType & MB_TYPE_P0L0) ? LIST_0 : LIST_1;
+ iMVs[0] = pCurDqLayer->pMv[listIdx][iMBXY][0][0];
+ iMVs[1] = pCurDqLayer->pMv[listIdx][iMBXY][0][1];
+ GetRefPic (&pMCRefMem, pCtx, pCurDqLayer->pRefIndex[listIdx][iMBXY], 0, listIdx);
+ BaseMC (&pMCRefMem, iMBOffsetX, iMBOffsetY, pMCFunc, 16, 16, iMVs);
+ if (bWeightedBipredIdcIs1) {
+ int32_t iRefIndex = pCurDqLayer->pRefIndex[listIdx][iMBXY][0];
+ WeightPrediction (pCurDqLayer, &pMCRefMem, listIdx, iRefIndex, 16, 16);
+ }
+ }
+ } else if (IS_INTER_16x8 (iMBType)) {
+ for (int32_t i = 0; i < 2; ++i) {
+ int32_t iPartIdx = i << 3;
+ uint32_t listCount = 0;
+ int32_t lastListIdx = LIST_0;
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ if (IS_DIR (iMBType, i, listIdx)) {
+ lastListIdx = listIdx;
+ iMVs[0] = pCurDqLayer->pMv[listIdx][iMBXY][iPartIdx][0];
+ iMVs[1] = pCurDqLayer->pMv[listIdx][iMBXY][iPartIdx][1];
+ GetRefPic (&pMCRefMem, pCtx, pCurDqLayer->pRefIndex[listIdx][iMBXY], iPartIdx, listIdx);
+ if (i) {
+ pMCRefMem.pDstY += (iDstLineLuma << 3);
+ pMCRefMem.pDstU += (iDstLineChroma << 2);
+ pMCRefMem.pDstV += (iDstLineChroma << 2);
+ }
+ BaseMC (&pMCRefMem, iMBOffsetX, iMBOffsetY + iPartIdx, pMCFunc, 16, 8, iMVs);
+ if (++listCount == 2) {
+ iMVs[0] = pCurDqLayer->pMv[LIST_1][iMBXY][iPartIdx][0];
+ iMVs[1] = pCurDqLayer->pMv[LIST_1][iMBXY][iPartIdx][1];
+ GetRefPic (&pTempMCRefMem, pCtx, pCurDqLayer->pRefIndex[LIST_1][iMBXY], iPartIdx, LIST_1);
+ if (i) {
+ pTempMCRefMem.pDstY += (iDstLineLuma << 3);
+ pTempMCRefMem.pDstU += (iDstLineChroma << 2);
+ pTempMCRefMem.pDstV += (iDstLineChroma << 2);
+ }
+ BaseMC (&pTempMCRefMem, iMBOffsetX, iMBOffsetY + iPartIdx, pMCFunc, 16, 8, iMVs);
+ if (pCurDqLayer->bUseWeightedBiPredIdc) {
+ iRefIndex1 = pCurDqLayer->pRefIndex[LIST_0][iMBXY][iPartIdx];
+ iRefIndex2 = pCurDqLayer->pRefIndex[LIST_1][iMBXY][iPartIdx];
+ BiWeightPrediction (pCurDqLayer, &pMCRefMem, &pTempMCRefMem, iRefIndex1, iRefIndex2, bWeightedBipredIdcIs1, 16, 8);
+ } else {
+ BiPrediction (pCurDqLayer, &pMCRefMem, &pTempMCRefMem, 16, 8);
+ }
+ }
+ }
+ }
+ if (listCount == 1) {
+ if (bWeightedBipredIdcIs1) {
+ int32_t iRefIndex = pCurDqLayer->pRefIndex[lastListIdx][iMBXY][iPartIdx];
+ WeightPrediction (pCurDqLayer, &pMCRefMem, lastListIdx, iRefIndex, 16, 8);
+ }
+ }
+ }
+ } else if (IS_INTER_8x16 (iMBType)) {
+ for (int32_t i = 0; i < 2; ++i) {
+ uint32_t listCount = 0;
+ int32_t lastListIdx = LIST_0;
+ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
+ if (IS_DIR (iMBType, i, listIdx)) {
+ lastListIdx = listIdx;
+ iMVs[0] = pCurDqLayer->pMv[listIdx][iMBXY][i << 1][0];
+ iMVs[1] = pCurDqLayer->pMv[listIdx][iMBXY][i << 1][1];
+ GetRefPic (&pMCRefMem, pCtx, pCurDqLayer->pRefIndex[listIdx][iMBXY], i << 1, listIdx);
+ if (i) {
+ pMCRefMem.pDstY += 8;
+ pMCRefMem.pDstU += 4;
+ pMCRefMem.pDstV += 4;
+ }
+ BaseMC (&pMCRefMem, iMBOffsetX + (i ? 8 : 0), iMBOffsetY, pMCFunc, 8, 16, iMVs);
+ if (++listCount == 2) {
+ iMVs[0] = pCurDqLayer->pMv[LIST_1][iMBXY][i << 1][0];
+ iMVs[1] = pCurDqLayer->pMv[LIST_1][iMBXY][i << 1][1];
+ GetRefPic (&pTempMCRefMem, pCtx, pCurDqLayer->pRefIndex[LIST_1][iMBXY], i << 1, LIST_1);
+ if (i) {
+ pTempMCRefMem.pDstY += 8;
+ pTempMCRefMem.pDstU += 4;
+ pTempMCRefMem.pDstV += 4;
+ }
+ BaseMC (&pTempMCRefMem, iMBOffsetX + (i ? 8 : 0), iMBOffsetY, pMCFunc, 8, 16, iMVs);
+ if (pCurDqLayer->bUseWeightedBiPredIdc) {
+ iRefIndex1 = pCurDqLayer->pRefIndex[LIST_0][iMBXY][i << 1];
+ iRefIndex2 = pCurDqLayer->pRefIndex[LIST_1][iMBXY][i << 1];
+ BiWeightPrediction (pCurDqLayer, &pMCRefMem, &pTempMCRefMem, iRefIndex1, iRefIndex2, bWeightedBipredIdcIs1, 8, 16);
+ } else {
+ BiPrediction (pCurDqLayer, &pMCRefMem, &pTempMCRefMem, 8, 16);
+ }
+ }
+ }
+ }
+ if (listCount == 1) {
+ if (bWeightedBipredIdcIs1) {
+ int32_t iRefIndex = pCurDqLayer->pRefIndex[lastListIdx][iMBXY][i << 1];
+ WeightPrediction (pCurDqLayer, &pMCRefMem, lastListIdx, iRefIndex, 8, 16);
+ }
+ }
+ }
+ } else if (IS_Inter_8x8 (iMBType)) {
+ int32_t iBlk8X, iBlk8Y, iBlk4X, iBlk4Y, iIIdx, iJIdx;
+ uint32_t iSubMBType;
+ int32_t iXOffset, iYOffset;
+ uint8_t* pDstY, *pDstU, *pDstV;
+ uint8_t* pDstY2, *pDstU2, *pDstV2;
+ for (int32_t i = 0; i < 4; i++) {
+ iSubMBType = pCurDqLayer->pSubMbType[iMBXY][i];
+ iBlk8X = (i & 1) << 3;
+ iBlk8Y = (i >> 1) << 3;
+ iXOffset = iMBOffsetX + iBlk8X;
+ iYOffset = iMBOffsetY + iBlk8Y;
+
+ iIIdx = ((i >> 1) << 3) + ((i & 1) << 1);
+
+ pDstY = pPredYCbCr[0] + iBlk8X + iBlk8Y * iDstLineLuma;
+ pDstU = pPredYCbCr[1] + (iBlk8X >> 1) + (iBlk8Y >> 1) * iDstLineChroma;
+ pDstV = pPredYCbCr[2] + (iBlk8X >> 1) + (iBlk8Y >> 1) * iDstLineChroma;
+ pMCRefMem.pDstY = pDstY;
+ pMCRefMem.pDstU = pDstU;
+ pMCRefMem.pDstV = pDstV;
+
+ pTempMCRefMem = pMCRefMem;
+ pDstY2 = pTempPredYCbCr[0] + iBlk8X + iBlk8Y * iDstLineLuma;
+ pDstU2 = pTempPredYCbCr[1] + (iBlk8X >> 1) + (iBlk8Y >> 1) * iDstLineChroma;
+ pDstV2 = pTempPredYCbCr[2] + (iBlk8X >> 1) + (iBlk8Y >> 1) * iDstLineChroma;
+
+ pTempMCRefMem.pDstY = pDstY2;
+ pTempMCRefMem.pDstU = pDstU2;
+ pTempMCRefMem.pDstV = pDstV2;
+
+ if ((IS_TYPE_L0 (iSubMBType) && IS_TYPE_L1 (iSubMBType))) {
+ iRefIndex1 = pCurDqLayer->pRefIndex[LIST_0][iMBXY][iIIdx];
+ GetRefPic (&pMCRefMem, pCtx, pCurDqLayer->pRefIndex[LIST_0][iMBXY], iIIdx, LIST_0);
+
+ iRefIndex2 = pCurDqLayer->pRefIndex[LIST_1][iMBXY][iIIdx];
+ GetRefPic (&pTempMCRefMem, pCtx, pCurDqLayer->pRefIndex[LIST_1][iMBXY], iIIdx, LIST_1);
+ } else {
+ int32_t listIdx = IS_TYPE_L0 (iSubMBType) ? LIST_0 : LIST_1;
+ iRefIndex1 = pCurDqLayer->pRefIndex[listIdx][iMBXY][iIIdx];
+ GetRefPic (&pMCRefMem, pCtx, pCurDqLayer->pRefIndex[listIdx][iMBXY], iIIdx, listIdx);
+ }
+
+ if (IS_SUB_8x8 (iSubMBType)) {
+ if (IS_TYPE_L0 (iSubMBType) && IS_TYPE_L1 (iSubMBType)) {
+ iMVs[0] = pCurDqLayer->pMv[LIST_0][iMBXY][iIIdx][0];
+ iMVs[1] = pCurDqLayer->pMv[LIST_0][iMBXY][iIIdx][1];
+ BaseMC (&pMCRefMem, iXOffset, iYOffset, pMCFunc, 8, 8, iMVs);
+
+ iMVs[0] = pCurDqLayer->pMv[LIST_1][iMBXY][iIIdx][0];
+ iMVs[1] = pCurDqLayer->pMv[LIST_1][iMBXY][iIIdx][1];
+ BaseMC (&pTempMCRefMem, iXOffset, iYOffset, pMCFunc, 8, 8, iMVs);
+
+ if (pCurDqLayer->bUseWeightedBiPredIdc) {
+ BiWeightPrediction (pCurDqLayer, &pMCRefMem, &pTempMCRefMem, iRefIndex1, iRefIndex2, bWeightedBipredIdcIs1, 8, 8);
+ } else {
+ BiPrediction (pCurDqLayer, &pMCRefMem, &pTempMCRefMem, 8, 8);
+ }
+ } else {
+ int32_t listIdx = IS_TYPE_L0 (iSubMBType) ? LIST_0 : LIST_1;
+ iMVs[0] = pCurDqLayer->pMv[listIdx][iMBXY][iIIdx][0];
+ iMVs[1] = pCurDqLayer->pMv[listIdx][iMBXY][iIIdx][1];
+ BaseMC (&pMCRefMem, iXOffset, iYOffset, pMCFunc, 8, 8, iMVs);
+ if (bWeightedBipredIdcIs1) {
+ int32_t iRefIndex = pCurDqLayer->pRefIndex[listIdx][iMBXY][iIIdx];
+ WeightPrediction (pCurDqLayer, &pMCRefMem, listIdx, iRefIndex, 8, 8);
+ }
+ }
+ } else if (IS_SUB_8x4 (iSubMBType)) {
+ if (IS_TYPE_L0 (iSubMBType) && IS_TYPE_L1 (iSubMBType)) { //B_Bi_8x4
+ iMVs[0] = pCurDqLayer->pMv[LIST_0][iMBXY][iIIdx][0];
+ iMVs[1] = pCurDqLayer->pMv[LIST_0][iMBXY][iIIdx][1];
+ BaseMC (&pMCRefMem, iXOffset, iYOffset, pMCFunc, 8, 4, iMVs);
+ iMVs[0] = pCurDqLayer->pMv[LIST_1][iMBXY][iIIdx][0];
+ iMVs[1] = pCurDqLayer->pMv[LIST_1][iMBXY][iIIdx][1];
+ BaseMC (&pTempMCRefMem, iXOffset, iYOffset, pMCFunc, 8, 4, iMVs);
+
+ if (pCurDqLayer->bUseWeightedBiPredIdc) {
+ BiWeightPrediction (pCurDqLayer, &pMCRefMem, &pTempMCRefMem, iRefIndex1, iRefIndex2, bWeightedBipredIdcIs1, 8, 4);
+ } else {
+ BiPrediction (pCurDqLayer, &pMCRefMem, &pTempMCRefMem, 8, 4);
+ }
+
+ pMCRefMem.pDstY += (iDstLineLuma << 2);
+ pMCRefMem.pDstU += (iDstLineChroma << 1);
+ pMCRefMem.pDstV += (iDstLineChroma << 1);
+ iMVs[0] = pCurDqLayer->pMv[LIST_0][iMBXY][iIIdx + 4][0];
+ iMVs[1] = pCurDqLayer->pMv[LIST_0][iMBXY][iIIdx + 4][1];
+ BaseMC (&pMCRefMem, iXOffset, iYOffset + 4, pMCFunc, 8, 4, iMVs);
+
+ pTempMCRefMem.pDstY += (iDstLineLuma << 2);
+ pTempMCRefMem.pDstU += (iDstLineChroma << 1);
+ pTempMCRefMem.pDstV += (iDstLineChroma << 1);
+ iMVs[0] = pCurDqLayer->pMv[LIST_1][iMBXY][iIIdx + 4][0];
+ iMVs[1] = pCurDqLayer->pMv[LIST_1][iMBXY][iIIdx + 4][1];
+ BaseMC (&pTempMCRefMem, iXOffset, iYOffset + 4, pMCFunc, 8, 4, iMVs);
+
+ if (pCurDqLayer->bUseWeightedBiPredIdc) {
+ BiWeightPrediction (pCurDqLayer, &pMCRefMem, &pTempMCRefMem, iRefIndex1, iRefIndex2, bWeightedBipredIdcIs1, 8, 4);
+ } else {
+ BiPrediction (pCurDqLayer, &pMCRefMem, &pTempMCRefMem, 8, 4);
+ }
+ } else { //B_L0_8x4 B_L1_8x4
+ int32_t listIdx = IS_TYPE_L0 (iSubMBType) ? LIST_0 : LIST_1;
+ iMVs[0] = pCurDqLayer->pMv[listIdx][iMBXY][iIIdx][0];
+ iMVs[1] = pCurDqLayer->pMv[listIdx][iMBXY][iIIdx][1];
+ BaseMC (&pMCRefMem, iXOffset, iYOffset, pMCFunc, 8, 4, iMVs);
+ pMCRefMem.pDstY += (iDstLineLuma << 2);
+ pMCRefMem.pDstU += (iDstLineChroma << 1);
+ pMCRefMem.pDstV += (iDstLineChroma << 1);
+ iMVs[0] = pCurDqLayer->pMv[listIdx][iMBXY][iIIdx + 4][0];
+ iMVs[1] = pCurDqLayer->pMv[listIdx][iMBXY][iIIdx + 4][1];
+ BaseMC (&pMCRefMem, iXOffset, iYOffset + 4, pMCFunc, 8, 4, iMVs);
+ if (bWeightedBipredIdcIs1) {
+ int32_t iRefIndex = pCurDqLayer->pRefIndex[listIdx][iMBXY][iIIdx];
+ WeightPrediction (pCurDqLayer, &pMCRefMem, listIdx, iRefIndex, 8, 4);
+ }
+ }
+ } else if (IS_SUB_4x8 (iSubMBType)) {
+ if (IS_TYPE_L0 (iSubMBType) && IS_TYPE_L1 (iSubMBType)) { //B_Bi_4x8
+ iMVs[0] = pCurDqLayer->pMv[LIST_0][iMBXY][iIIdx][0];
+ iMVs[1] = pCurDqLayer->pMv[LIST_0][iMBXY][iIIdx][1];
+ BaseMC (&pMCRefMem, iXOffset, iYOffset, pMCFunc, 4, 8, iMVs);
+ iMVs[0] = pCurDqLayer->pMv[LIST_1][iMBXY][iIIdx][0];
+ iMVs[1] = pCurDqLayer->pMv[LIST_1][iMBXY][iIIdx][1];
+ BaseMC (&pTempMCRefMem, iXOffset, iYOffset, pMCFunc, 4, 8, iMVs);
+
+ if (pCurDqLayer->bUseWeightedBiPredIdc) {
+ BiWeightPrediction (pCurDqLayer, &pMCRefMem, &pTempMCRefMem, iRefIndex1, iRefIndex2, bWeightedBipredIdcIs1, 4, 8);
+ } else {
+ BiPrediction (pCurDqLayer, &pMCRefMem, &pTempMCRefMem, 4, 8);
+ }
+
+ pMCRefMem.pDstY += 4;
+ pMCRefMem.pDstU += 2;
+ pMCRefMem.pDstV += 2;
+ iMVs[0] = pCurDqLayer->pMv[LIST_0][iMBXY][iIIdx + 1][0];
+ iMVs[1] = pCurDqLayer->pMv[LIST_0][iMBXY][iIIdx + 1][1];
+ BaseMC (&pMCRefMem, iXOffset + 4, iYOffset, pMCFunc, 4, 8, iMVs);
+
+ pTempMCRefMem.pDstY += 4;
+ pTempMCRefMem.pDstU += 2;
+ pTempMCRefMem.pDstV += 2;
+ iMVs[0] = pCurDqLayer->pMv[LIST_1][iMBXY][iIIdx + 1][0];
+ iMVs[1] = pCurDqLayer->pMv[LIST_1][iMBXY][iIIdx + 1][1];
+ BaseMC (&pTempMCRefMem, iXOffset + 4, iYOffset, pMCFunc, 4, 8, iMVs);
+
+ if (pCurDqLayer->bUseWeightedBiPredIdc) {
+ BiWeightPrediction (pCurDqLayer, &pMCRefMem, &pTempMCRefMem, iRefIndex1, iRefIndex2, bWeightedBipredIdcIs1, 4, 8);
+ } else {
+ BiPrediction (pCurDqLayer, &pMCRefMem, &pTempMCRefMem, 4, 8);
+ }
+ } else { //B_L0_4x8 B_L1_4x8
+ int32_t listIdx = IS_TYPE_L0 (iSubMBType) ? LIST_0 : LIST_1;
+ iMVs[0] = pCurDqLayer->pMv[listIdx][iMBXY][iIIdx][0];
+ iMVs[1] = pCurDqLayer->pMv[listIdx][iMBXY][iIIdx][1];
+ BaseMC (&pMCRefMem, iXOffset, iYOffset, pMCFunc, 4, 8, iMVs);
+ pMCRefMem.pDstY += 4;
+ pMCRefMem.pDstU += 2;
+ pMCRefMem.pDstV += 2;
+ iMVs[0] = pCurDqLayer->pMv[listIdx][iMBXY][iIIdx + 1][0];
+ iMVs[1] = pCurDqLayer->pMv[listIdx][iMBXY][iIIdx + 1][1];
+ BaseMC (&pMCRefMem, iXOffset + 4, iYOffset, pMCFunc, 4, 8, iMVs);
+ if (bWeightedBipredIdcIs1) {
+ int32_t iRefIndex = pCurDqLayer->pRefIndex[listIdx][iMBXY][iIIdx];
+ WeightPrediction (pCurDqLayer, &pMCRefMem, listIdx, iRefIndex, 4, 8);
+ }
+ }
+ } else if (IS_SUB_4x4 (iSubMBType)) {
+ if (IS_TYPE_L0 (iSubMBType) && IS_TYPE_L1 (iSubMBType)) {
+ for (int32_t j = 0; j < 4; j++) {
+ int32_t iUVLineStride;
+ iJIdx = ((j >> 1) << 2) + (j & 1);
+
+ iBlk4X = (j & 1) << 2;
+ iBlk4Y = (j >> 1) << 2;
+
+ iUVLineStride = (iBlk4X >> 1) + (iBlk4Y >> 1) * iDstLineChroma;
+ pMCRefMem.pDstY = pDstY + iBlk4X + iBlk4Y * iDstLineLuma;
+ pMCRefMem.pDstU = pDstU + iUVLineStride;
+ pMCRefMem.pDstV = pDstV + iUVLineStride;
+
+ iMVs[0] = pCurDqLayer->pMv[LIST_0][iMBXY][iIIdx + iJIdx][0];
+ iMVs[1] = pCurDqLayer->pMv[LIST_0][iMBXY][iIIdx + iJIdx][1];
+ BaseMC (&pMCRefMem, iXOffset + iBlk4X, iYOffset + iBlk4Y, pMCFunc, 4, 4, iMVs);
+
+ pTempMCRefMem.pDstY = pDstY2 + iBlk8X + iBlk8Y * iDstLineLuma;
+ pTempMCRefMem.pDstU = pDstU2 + iUVLineStride;
+ pTempMCRefMem.pDstV = pDstV2 + iUVLineStride;;
+
+ iMVs[0] = pCurDqLayer->pMv[LIST_1][iMBXY][iIIdx + iJIdx][0];
+ iMVs[1] = pCurDqLayer->pMv[LIST_1][iMBXY][iIIdx + iJIdx][1];
+ BaseMC (&pTempMCRefMem, iXOffset + iBlk4X, iYOffset + iBlk4Y, pMCFunc, 4, 4, iMVs);
+
+ if (pCurDqLayer->bUseWeightedBiPredIdc) {
+ BiWeightPrediction (pCurDqLayer, &pMCRefMem, &pTempMCRefMem, iRefIndex1, iRefIndex2, bWeightedBipredIdcIs1, 4, 4);
+ } else {
+ BiPrediction (pCurDqLayer, &pMCRefMem, &pTempMCRefMem, 4, 4);
+ }
+ }
+ } else {
+ int32_t listIdx = IS_TYPE_L0 (iSubMBType) ? LIST_0 : LIST_1;
+ int32_t iRefIndex = pCurDqLayer->pRefIndex[listIdx][iMBXY][iIIdx];
+ for (int32_t j = 0; j < 4; j++) {
+ int32_t iUVLineStride;
+ iJIdx = ((j >> 1) << 2) + (j & 1);
+
+ iBlk4X = (j & 1) << 2;
+ iBlk4Y = (j >> 1) << 2;
+
+ iUVLineStride = (iBlk4X >> 1) + (iBlk4Y >> 1) * iDstLineChroma;
+ pMCRefMem.pDstY = pDstY + iBlk4X + iBlk4Y * iDstLineLuma;
+ pMCRefMem.pDstU = pDstU + iUVLineStride;
+ pMCRefMem.pDstV = pDstV + iUVLineStride;
+
+ iMVs[0] = pCurDqLayer->pMv[listIdx][iMBXY][iIIdx + iJIdx][0];
+ iMVs[1] = pCurDqLayer->pMv[listIdx][iMBXY][iIIdx + iJIdx][1];
+ BaseMC (&pMCRefMem, iXOffset + iBlk4X, iYOffset + iBlk4Y, pMCFunc, 4, 4, iMVs);
+ if (bWeightedBipredIdcIs1) {
+ WeightPrediction (pCurDqLayer, &pMCRefMem, listIdx, iRefIndex, 4, 4);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+int32_t RecChroma (int32_t iMBXY, PWelsDecoderContext pCtx, int16_t* pScoeffLevel, PDqLayer pDqLayer) {
+ int32_t iChromaStride = pCtx->pCurDqLayer->pDec->iLinesize[1];
+ PIdctFourResAddPredFunc pIdctFourResAddPredFunc = pCtx->pIdctFourResAddPredFunc;
+
+ uint8_t i = 0;
+ uint8_t uiCbpC = pDqLayer->pCbp[iMBXY] >> 4;
+
+ if (1 == uiCbpC || 2 == uiCbpC) {
+ for (i = 0; i < 2; i++) {
+ int16_t* pRS = pScoeffLevel + 256 + (i << 6);
+ uint8_t* pPred = pDqLayer->pPred[i + 1];
+ const int8_t* pNzc = pDqLayer->pNzc[iMBXY] + 16 + 2 * i;
+
+ /*1 chroma is divided 4 4x4_block to idct*/
+ pIdctFourResAddPredFunc (pPred, iChromaStride, pRS, pNzc);
+ }
+ }
+
+ return ERR_NONE;
+}
+
+} // namespace WelsDec
--- a/codec/decoder/plus/inc/welsDecoderExt.h
+++ b/codec/decoder/plus/inc/welsDecoderExt.h
@@ -1,147 +1,147 @@
-/*!
- * \copy
- * Copyright (c) 2009-2013, Cisco Systems
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- *
- * WelsDecoderExt.h
- *
- * Abstract
- * Cisco OpenH264 decoder extension utilization interface
- *
- * History
- * 3/12/2009 Created
- *
- *
- *************************************************************************/
-#if !defined(WELS_PLUS_WELSDECODEREXT_H)
-#define WELS_PLUS_WELSDECODEREXT_H
-
-#include "codec_api.h"
-#include "codec_app_def.h"
-#include "decoder_context.h"
-#include "welsCodecTrace.h"
-#include "cpu.h"
-
-class ISVCDecoder;
-
-namespace WelsDec {
-
-//#define OUTPUT_BIT_STREAM ////for test to output bitstream
-
-class CWelsDecoder : public ISVCDecoder {
- public:
- CWelsDecoder (void);
- virtual ~CWelsDecoder();
-
- virtual long EXTAPI Initialize (const SDecodingParam* pParam);
- virtual long EXTAPI Uninitialize();
-
- /***************************************************************************
- * Description:
- * Decompress one frame, and output I420 or RGB24(in the future) decoded stream and its length.
- * Input parameters:
- * Parameter TYPE Description
- * pSrc unsigned char* the h264 stream to decode
- * srcLength int the length of h264 steam
- * pDst unsigned char* buffer pointer of decoded data
- * pDstInfo SBufferInfo& information provided to API including width, height, SW/HW option, etc
- *
- * return: if decode frame success return 0, otherwise corresponding error returned.
- ***************************************************************************/
- virtual DECODING_STATE EXTAPI DecodeFrame (const unsigned char* kpSrc,
- const int kiSrcLen,
- unsigned char** ppDst,
- int* pStride,
- int& iWidth,
- int& iHeight);
-
- virtual DECODING_STATE EXTAPI DecodeFrameNoDelay (const unsigned char* kpSrc,
- const int kiSrcLen,
- unsigned char** ppDst,
- SBufferInfo* pDstInfo);
-
- virtual DECODING_STATE EXTAPI DecodeFrame2 (const unsigned char* kpSrc,
- const int kiSrcLen,
- unsigned char** ppDst,
- SBufferInfo* pDstInfo);
-
- virtual DECODING_STATE EXTAPI FlushFrame (unsigned char** ppDst,
- SBufferInfo* pDstInfo);
-
- virtual DECODING_STATE EXTAPI DecodeParser (const unsigned char* kpSrc,
- const int kiSrcLen,
- SParserBsInfo* pDstInfo);
- virtual DECODING_STATE EXTAPI DecodeFrameEx (const unsigned char* kpSrc,
- const int kiSrcLen,
- unsigned char* pDst,
- int iDstStride,
- int& iDstLen,
- int& iWidth,
- int& iHeight,
- int& color_format);
-
- virtual long EXTAPI SetOption (DECODER_OPTION eOptID, void* pOption);
- virtual long EXTAPI GetOption (DECODER_OPTION eOptID, void* pOption);
-
- typedef struct tagPictInfo {
- SBufferInfo sBufferInfo;
- int32_t iPOC;
- int32_t iFrameNum;
- bool bLastGOP;
- unsigned char* pData[3];
- } SPictInfo, *PPictInfo;
-
- private:
- PWelsDecoderContext m_pDecContext;
- welsCodecTrace* m_pWelsTrace;
- SPictInfo m_sPictInfoList[16];
- int32_t m_iPictInfoIndex;
- int32_t m_iMinPOC;
- int32_t m_iNumOfPicts;
- int32_t m_iLastGOPRemainPicts;
- int32_t m_LastWrittenPOC;
- int32_t m_iLargestBufferedPicIndex;
-
- int32_t InitDecoder (const SDecodingParam* pParam);
- void UninitDecoder (void);
- int32_t ResetDecoder();
-
- void OutputStatisticsLog (SDecoderStatistics& sDecoderStatistics);
- DECODING_STATE ReorderPicturesInDisplay (unsigned char** ppDst, SBufferInfo* pDstInfo);
-
-#ifdef OUTPUT_BIT_STREAM
- WelsFileHandle* m_pFBS;
- WelsFileHandle* m_pFBSSize;
-#endif//OUTPUT_BIT_STREAM
-
-};
-
-} // namespace WelsDec
-
-#endif // !defined(WELS_PLUS_WELSDECODEREXT_H)
+/*!
+ * \copy
+ * Copyright (c) 2009-2013, Cisco Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * WelsDecoderExt.h
+ *
+ * Abstract
+ * Cisco OpenH264 decoder extension utilization interface
+ *
+ * History
+ * 3/12/2009 Created
+ *
+ *
+ *************************************************************************/
+#if !defined(WELS_PLUS_WELSDECODEREXT_H)
+#define WELS_PLUS_WELSDECODEREXT_H
+
+#include "codec_api.h"
+#include "codec_app_def.h"
+#include "decoder_context.h"
+#include "welsCodecTrace.h"
+#include "cpu.h"
+
+class ISVCDecoder;
+
+namespace WelsDec {
+
+//#define OUTPUT_BIT_STREAM ////for test to output bitstream
+
+class CWelsDecoder : public ISVCDecoder {
+ public:
+ CWelsDecoder (void);
+ virtual ~CWelsDecoder();
+
+ virtual long EXTAPI Initialize (const SDecodingParam* pParam);
+ virtual long EXTAPI Uninitialize();
+
+ /***************************************************************************
+ * Description:
+ * Decompress one frame, and output I420 or RGB24(in the future) decoded stream and its length.
+ * Input parameters:
+ * Parameter TYPE Description
+ * pSrc unsigned char* the h264 stream to decode
+ * srcLength int the length of h264 steam
+ * pDst unsigned char* buffer pointer of decoded data
+ * pDstInfo SBufferInfo& information provided to API including width, height, SW/HW option, etc
+ *
+ * return: if decode frame success return 0, otherwise corresponding error returned.
+ ***************************************************************************/
+ virtual DECODING_STATE EXTAPI DecodeFrame (const unsigned char* kpSrc,
+ const int kiSrcLen,
+ unsigned char** ppDst,
+ int* pStride,
+ int& iWidth,
+ int& iHeight);
+
+ virtual DECODING_STATE EXTAPI DecodeFrameNoDelay (const unsigned char* kpSrc,
+ const int kiSrcLen,
+ unsigned char** ppDst,
+ SBufferInfo* pDstInfo);
+
+ virtual DECODING_STATE EXTAPI DecodeFrame2 (const unsigned char* kpSrc,
+ const int kiSrcLen,
+ unsigned char** ppDst,
+ SBufferInfo* pDstInfo);
+
+ virtual DECODING_STATE EXTAPI FlushFrame (unsigned char** ppDst,
+ SBufferInfo* pDstInfo);
+
+ virtual DECODING_STATE EXTAPI DecodeParser (const unsigned char* kpSrc,
+ const int kiSrcLen,
+ SParserBsInfo* pDstInfo);
+ virtual DECODING_STATE EXTAPI DecodeFrameEx (const unsigned char* kpSrc,
+ const int kiSrcLen,
+ unsigned char* pDst,
+ int iDstStride,
+ int& iDstLen,
+ int& iWidth,
+ int& iHeight,
+ int& color_format);
+
+ virtual long EXTAPI SetOption (DECODER_OPTION eOptID, void* pOption);
+ virtual long EXTAPI GetOption (DECODER_OPTION eOptID, void* pOption);
+
+ typedef struct tagPictInfo {
+ SBufferInfo sBufferInfo;
+ int32_t iPOC;
+ int32_t iFrameNum;
+ bool bLastGOP;
+ unsigned char* pData[3];
+ } SPictInfo, *PPictInfo;
+
+ private:
+ PWelsDecoderContext m_pDecContext;
+ welsCodecTrace* m_pWelsTrace;
+ SPictInfo m_sPictInfoList[16];
+ int32_t m_iPictInfoIndex;
+ int32_t m_iMinPOC;
+ int32_t m_iNumOfPicts;
+ int32_t m_iLastGOPRemainPicts;
+ int32_t m_LastWrittenPOC;
+ int32_t m_iLargestBufferedPicIndex;
+
+ int32_t InitDecoder (const SDecodingParam* pParam);
+ void UninitDecoder (void);
+ int32_t ResetDecoder();
+
+ void OutputStatisticsLog (SDecoderStatistics& sDecoderStatistics);
+ DECODING_STATE ReorderPicturesInDisplay (unsigned char** ppDst, SBufferInfo* pDstInfo);
+
+#ifdef OUTPUT_BIT_STREAM
+ WelsFileHandle* m_pFBS;
+ WelsFileHandle* m_pFBSSize;
+#endif//OUTPUT_BIT_STREAM
+
+};
+
+} // namespace WelsDec
+
+#endif // !defined(WELS_PLUS_WELSDECODEREXT_H)
--- a/codec/decoder/plus/src/welsDecoderExt.cpp
+++ b/codec/decoder/plus/src/welsDecoderExt.cpp
@@ -1,1016 +1,1016 @@
-/*!
- * \copy
- * Copyright (c) 2009-2013, Cisco Systems
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- *
- * welsDecoderExt.cpp
- *
- * Abstract
- * Cisco OpenH264 decoder extension utilization
- *
- * History
- * 3/12/2009 Created
- *
- *
- ************************************************************************/
-//#include <assert.h>
-#include "welsDecoderExt.h"
-#include "welsCodecTrace.h"
-#include "codec_def.h"
-#include "typedefs.h"
-#include "memory_align.h"
-#include "utils.h"
-#include "version.h"
-
-//#include "macros.h"
-#include "decoder.h"
-#include "decoder_core.h"
-#include "error_concealment.h"
-
-#include "measure_time.h"
-extern "C" {
-#include "decoder_core.h"
-#include "manage_dec_ref.h"
-}
-#include "error_code.h"
-#include "crt_util_safe_x.h" // Safe CRT routines like util for cross platforms
-#include <time.h>
-#if defined(_WIN32) /*&& defined(_DEBUG)*/
-
-#include <windows.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <sys/types.h>
-#else
-#include <sys/time.h>
-#endif
-
-#define _PICTURE_REORDERING_ 1
-
-static int32_t sIMinInt32 = -0x7FFFFFFF;
-
-namespace WelsDec {
-
-//////////////////////////////////////////////////////////////////////
-// Construction/Destruction
-//////////////////////////////////////////////////////////////////////
-
-/***************************************************************************
-* Description:
-* class CWelsDecoder constructor function, do initialization and
-* alloc memory required
-*
-* Input parameters: none
-*
-* return: none
-***************************************************************************/
-CWelsDecoder::CWelsDecoder (void)
- : m_pDecContext (NULL),
- m_pWelsTrace (NULL),
- m_iPictInfoIndex (0),
- m_iMinPOC (sIMinInt32),
- m_iNumOfPicts (0),
- m_iLastGOPRemainPicts (0),
- m_LastWrittenPOC (sIMinInt32),
- m_iLargestBufferedPicIndex (0) {
-#ifdef OUTPUT_BIT_STREAM
- char chFileName[1024] = { 0 }; //for .264
- int iBufUsed = 0;
- int iBufLeft = 1023;
- int iCurUsed;
-
- char chFileNameSize[1024] = { 0 }; //for .len
- int iBufUsedSize = 0;
- int iBufLeftSize = 1023;
- int iCurUsedSize;
-#endif//OUTPUT_BIT_STREAM
-
-
- m_pWelsTrace = new welsCodecTrace();
- if (m_pWelsTrace != NULL) {
- m_pWelsTrace->SetCodecInstance (this);
- m_pWelsTrace->SetTraceLevel (WELS_LOG_ERROR);
-
- WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::CWelsDecoder() entry");
- }
-
- for (int32_t i = 0; i < 16; ++i) {
- m_sPictInfoList[i].bLastGOP = false;
- m_sPictInfoList[i].iPOC = sIMinInt32;
- }
-
-#ifdef OUTPUT_BIT_STREAM
- SWelsTime sCurTime;
-
- WelsGetTimeOfDay (&sCurTime);
-
- iCurUsed = WelsSnprintf (chFileName, iBufLeft, "bs_0x%p_", (void*)this);
- iCurUsedSize = WelsSnprintf (chFileNameSize, iBufLeftSize, "size_0x%p_", (void*)this);
-
- iBufUsed += iCurUsed;
- iBufLeft -= iCurUsed;
- if (iBufLeft > 0) {
- iCurUsed = WelsStrftime (&chFileName[iBufUsed], iBufLeft, "%y%m%d%H%M%S", &sCurTime);
- iBufUsed += iCurUsed;
- iBufLeft -= iCurUsed;
- }
-
- iBufUsedSize += iCurUsedSize;
- iBufLeftSize -= iCurUsedSize;
- if (iBufLeftSize > 0) {
- iCurUsedSize = WelsStrftime (&chFileNameSize[iBufUsedSize], iBufLeftSize, "%y%m%d%H%M%S", &sCurTime);
- iBufUsedSize += iCurUsedSize;
- iBufLeftSize -= iCurUsedSize;
- }
-
- if (iBufLeft > 0) {
- iCurUsed = WelsSnprintf (&chFileName[iBufUsed], iBufLeft, ".%03.3u.264", WelsGetMillisecond (&sCurTime));
- iBufUsed += iCurUsed;
- iBufLeft -= iCurUsed;
- }
-
- if (iBufLeftSize > 0) {
- iCurUsedSize = WelsSnprintf (&chFileNameSize[iBufUsedSize], iBufLeftSize, ".%03.3u.len",
- WelsGetMillisecond (&sCurTime));
- iBufUsedSize += iCurUsedSize;
- iBufLeftSize -= iCurUsedSize;
- }
-
-
- m_pFBS = WelsFopen (chFileName, "wb");
- m_pFBSSize = WelsFopen (chFileNameSize, "wb");
-#endif//OUTPUT_BIT_STREAM
-}
-
-/***************************************************************************
-* Description:
-* class CWelsDecoder destructor function, destroy allocced memory
-*
-* Input parameters: none
-*
-* return: none
-***************************************************************************/
-CWelsDecoder::~CWelsDecoder() {
- if (m_pWelsTrace != NULL) {
- WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::~CWelsDecoder()");
- }
-
- UninitDecoder();
-
-#ifdef OUTPUT_BIT_STREAM
- if (m_pFBS) {
- WelsFclose (m_pFBS);
- m_pFBS = NULL;
- }
- if (m_pFBSSize) {
- WelsFclose (m_pFBSSize);
- m_pFBSSize = NULL;
- }
-#endif//OUTPUT_BIT_STREAM
-
- if (m_pWelsTrace != NULL) {
- delete m_pWelsTrace;
- m_pWelsTrace = NULL;
- }
-}
-
-long CWelsDecoder::Initialize (const SDecodingParam* pParam) {
- int iRet = ERR_NONE;
- if (m_pWelsTrace == NULL) {
- return cmMallocMemeError;
- }
-
- if (pParam == NULL) {
- WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "CWelsDecoder::Initialize(), invalid input argument.");
- return cmInitParaError;
- }
-
- // H.264 decoder initialization,including memory allocation,then open it ready to decode
- iRet = InitDecoder (pParam);
- if (iRet)
- return iRet;
-
- return cmResultSuccess;
-}
-
-long CWelsDecoder::Uninitialize() {
- UninitDecoder();
-
- return ERR_NONE;
-}
-
-void CWelsDecoder::UninitDecoder (void) {
- if (NULL == m_pDecContext)
- return;
-
- WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::UninitDecoder(), openh264 codec version = %s.",
- VERSION_NUMBER);
-
- WelsEndDecoder (m_pDecContext);
-
- if (m_pDecContext->pMemAlign != NULL) {
- WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
- "CWelsDecoder::UninitDecoder(), verify memory usage (%d bytes) after free..",
- m_pDecContext->pMemAlign->WelsGetMemoryUsage());
- delete m_pDecContext->pMemAlign;
- m_pDecContext->pMemAlign = NULL;
- }
-
- if (NULL != m_pDecContext) {
- WelsFree (m_pDecContext, "m_pDecContext");
-
- m_pDecContext = NULL;
- }
-}
-
-// the return value of this function is not suitable, it need report failure info to upper layer.
-int32_t CWelsDecoder::InitDecoder (const SDecodingParam* pParam) {
-
- WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
- "CWelsDecoder::init_decoder(), openh264 codec version = %s, ParseOnly = %d",
- VERSION_NUMBER, (int32_t)pParam->bParseOnly);
-
- //reset decoder context
- if (m_pDecContext) //free
- UninitDecoder();
- m_pDecContext = (PWelsDecoderContext)WelsMallocz (sizeof (SWelsDecoderContext), "m_pDecContext");
- if (NULL == m_pDecContext)
- return cmMallocMemeError;
- int32_t iCacheLineSize = 16; // on chip cache line size in byte
- m_pDecContext->pMemAlign = new CMemoryAlign (iCacheLineSize);
- WELS_VERIFY_RETURN_PROC_IF (cmMallocMemeError, (NULL == m_pDecContext->pMemAlign), UninitDecoder())
-
- //fill in default value into context
- WelsDecoderDefaults (m_pDecContext, &m_pWelsTrace->m_sLogCtx);
-
- //check param and update decoder context
- m_pDecContext->pParam = (SDecodingParam*)m_pDecContext->pMemAlign->WelsMallocz (sizeof (SDecodingParam),
- "SDecodingParam");
- WELS_VERIFY_RETURN_PROC_IF (cmMallocMemeError, (NULL == m_pDecContext->pParam), UninitDecoder());
- int32_t iRet = DecoderConfigParam (m_pDecContext, pParam);
- WELS_VERIFY_RETURN_IFNEQ (iRet, cmResultSuccess);
-
- //init decoder
- WELS_VERIFY_RETURN_PROC_IF (cmMallocMemeError, WelsInitDecoder (m_pDecContext, &m_pWelsTrace->m_sLogCtx),
- UninitDecoder())
-
- return cmResultSuccess;
-}
-
-int32_t CWelsDecoder::ResetDecoder() {
- // TBC: need to be modified when context and trace point are null
- if (m_pDecContext != NULL && m_pWelsTrace != NULL) {
- WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "ResetDecoder(), context error code is %d",
- m_pDecContext->iErrorCode);
- SDecodingParam sPrevParam;
- memcpy (&sPrevParam, m_pDecContext->pParam, sizeof (SDecodingParam));
-
- WELS_VERIFY_RETURN_PROC_IF (cmInitParaError, InitDecoder (&sPrevParam), UninitDecoder());
- } else if (m_pWelsTrace != NULL) {
- WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "ResetDecoder() failed as decoder context null");
- }
- return ERR_INFO_UNINIT;
-}
-
-/*
- * Set Option
- */
-long CWelsDecoder::SetOption (DECODER_OPTION eOptID, void* pOption) {
- int iVal = 0;
-
- if (m_pDecContext == NULL && eOptID != DECODER_OPTION_TRACE_LEVEL &&
- eOptID != DECODER_OPTION_TRACE_CALLBACK && eOptID != DECODER_OPTION_TRACE_CALLBACK_CONTEXT)
- return dsInitialOptExpected;
- if (eOptID == DECODER_OPTION_END_OF_STREAM) { // Indicate bit-stream of the final frame to be decoded
- if (pOption == NULL)
- return cmInitParaError;
-
- iVal = * ((int*)pOption); // boolean value for whether enabled End Of Stream flag
-
- m_pDecContext->bEndOfStreamFlag = iVal ? true : false;
-
- return cmResultSuccess;
- } else if (eOptID == DECODER_OPTION_ERROR_CON_IDC) { // Indicate error concealment status
- if (pOption == NULL)
- return cmInitParaError;
-
- iVal = * ((int*)pOption); // int value for error concealment idc
- iVal = WELS_CLIP3 (iVal, (int32_t)ERROR_CON_DISABLE, (int32_t)ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE);
- if ((m_pDecContext->pParam->bParseOnly) && (iVal != (int32_t)ERROR_CON_DISABLE)) {
- WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
- "CWelsDecoder::SetOption for ERROR_CON_IDC = %d not allowd for parse only!.", iVal);
- return cmInitParaError;
- }
-
- m_pDecContext->pParam->eEcActiveIdc = (ERROR_CON_IDC)iVal;
- InitErrorCon (m_pDecContext);
- WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
- "CWelsDecoder::SetOption for ERROR_CON_IDC = %d.", iVal);
-
- return cmResultSuccess;
- } else if (eOptID == DECODER_OPTION_TRACE_LEVEL) {
- if (m_pWelsTrace) {
- uint32_t level = * ((uint32_t*)pOption);
- m_pWelsTrace->SetTraceLevel (level);
- }
- return cmResultSuccess;
- } else if (eOptID == DECODER_OPTION_TRACE_CALLBACK) {
- if (m_pWelsTrace) {
- WelsTraceCallback callback = * ((WelsTraceCallback*)pOption);
- m_pWelsTrace->SetTraceCallback (callback);
- WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
- "CWelsDecoder::SetOption():DECODER_OPTION_TRACE_CALLBACK callback = %p.",
- callback);
- }
- return cmResultSuccess;
- } else if (eOptID == DECODER_OPTION_TRACE_CALLBACK_CONTEXT) {
- if (m_pWelsTrace) {
- void* ctx = * ((void**)pOption);
- m_pWelsTrace->SetTraceCallbackContext (ctx);
- }
- return cmResultSuccess;
- } else if (eOptID == DECODER_OPTION_GET_STATISTICS) {
- WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING,
- "CWelsDecoder::SetOption():DECODER_OPTION_GET_STATISTICS: this option is get-only!");
- return cmInitParaError;
- } else if (eOptID == DECODER_OPTION_STATISTICS_LOG_INTERVAL) {
- if (pOption) {
- m_pDecContext->sDecoderStatistics.iStatisticsLogInterval = (* ((unsigned int*)pOption));
- return cmResultSuccess;
- }
- } else if (eOptID == DECODER_OPTION_GET_SAR_INFO) {
- WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING,
- "CWelsDecoder::SetOption():DECODER_OPTION_GET_SAR_INFO: this option is get-only!");
- return cmInitParaError;
- }
- return cmInitParaError;
-}
-
-/*
- * Get Option
- */
-long CWelsDecoder::GetOption (DECODER_OPTION eOptID, void* pOption) {
- int iVal = 0;
-
- if (m_pDecContext == NULL)
- return cmInitExpected;
-
- if (pOption == NULL)
- return cmInitParaError;
-
- if (DECODER_OPTION_END_OF_STREAM == eOptID) {
- iVal = m_pDecContext->bEndOfStreamFlag;
- * ((int*)pOption) = iVal;
- return cmResultSuccess;
- }
-#ifdef LONG_TERM_REF
- else if (DECODER_OPTION_IDR_PIC_ID == eOptID) {
- iVal = m_pDecContext->uiCurIdrPicId;
- * ((int*)pOption) = iVal;
- return cmResultSuccess;
- } else if (DECODER_OPTION_FRAME_NUM == eOptID) {
- iVal = m_pDecContext->iFrameNum;
- * ((int*)pOption) = iVal;
- return cmResultSuccess;
- } else if (DECODER_OPTION_LTR_MARKING_FLAG == eOptID) {
- iVal = m_pDecContext->bCurAuContainLtrMarkSeFlag;
- * ((int*)pOption) = iVal;
- return cmResultSuccess;
- } else if (DECODER_OPTION_LTR_MARKED_FRAME_NUM == eOptID) {
- iVal = m_pDecContext->iFrameNumOfAuMarkedLtr;
- * ((int*)pOption) = iVal;
- return cmResultSuccess;
- }
-#endif
- else if (DECODER_OPTION_VCL_NAL == eOptID) { //feedback whether or not have VCL NAL in current AU
- iVal = m_pDecContext->iFeedbackVclNalInAu;
- * ((int*)pOption) = iVal;
- return cmResultSuccess;
- } else if (DECODER_OPTION_TEMPORAL_ID == eOptID) { //if have VCL NAL in current AU, then feedback the temporal ID
- iVal = m_pDecContext->iFeedbackTidInAu;
- * ((int*)pOption) = iVal;
- return cmResultSuccess;
- } else if (DECODER_OPTION_IS_REF_PIC == eOptID) {
- iVal = m_pDecContext->iFeedbackNalRefIdc;
- if (iVal > 0)
- iVal = 1;
- * ((int*)pOption) = iVal;
- return cmResultSuccess;
- } else if (DECODER_OPTION_ERROR_CON_IDC == eOptID) {
- iVal = (int)m_pDecContext->pParam->eEcActiveIdc;
- * ((int*)pOption) = iVal;
- return cmResultSuccess;
- } else if (DECODER_OPTION_GET_STATISTICS == eOptID) { // get decoder statistics info for real time debugging
- SDecoderStatistics* pDecoderStatistics = (static_cast<SDecoderStatistics*> (pOption));
-
- memcpy (pDecoderStatistics, &m_pDecContext->sDecoderStatistics, sizeof (SDecoderStatistics));
-
- if (m_pDecContext->sDecoderStatistics.uiDecodedFrameCount != 0) { //not original status
- pDecoderStatistics->fAverageFrameSpeedInMs = (float) (m_pDecContext->dDecTime) /
- (m_pDecContext->sDecoderStatistics.uiDecodedFrameCount);
- pDecoderStatistics->fActualAverageFrameSpeedInMs = (float) (m_pDecContext->dDecTime) /
- (m_pDecContext->sDecoderStatistics.uiDecodedFrameCount + m_pDecContext->sDecoderStatistics.uiFreezingIDRNum +
- m_pDecContext->sDecoderStatistics.uiFreezingNonIDRNum);
- }
- return cmResultSuccess;
- } else if (eOptID == DECODER_OPTION_STATISTICS_LOG_INTERVAL) {
- if (pOption) {
- iVal = m_pDecContext->sDecoderStatistics.iStatisticsLogInterval;
- * ((unsigned int*)pOption) = iVal;
- return cmResultSuccess;
- }
- } else if (DECODER_OPTION_GET_SAR_INFO == eOptID) { //get decoder SAR info in VUI
- PVuiSarInfo pVuiSarInfo = (static_cast<PVuiSarInfo> (pOption));
- memset (pVuiSarInfo, 0, sizeof (SVuiSarInfo));
- if (!m_pDecContext->pSps) {
- return cmInitExpected;
- } else {
- pVuiSarInfo->uiSarWidth = m_pDecContext->pSps->sVui.uiSarWidth;
- pVuiSarInfo->uiSarHeight = m_pDecContext->pSps->sVui.uiSarHeight;
- pVuiSarInfo->bOverscanAppropriateFlag = m_pDecContext->pSps->sVui.bOverscanAppropriateFlag;
- return cmResultSuccess;
- }
- } else if (DECODER_OPTION_PROFILE == eOptID) {
- if (!m_pDecContext->pSps) {
- return cmInitExpected;
- }
- iVal = (int)m_pDecContext->pSps->uiProfileIdc;
- * ((int*)pOption) = iVal;
- return cmResultSuccess;
- } else if (DECODER_OPTION_LEVEL == eOptID) {
- if (!m_pDecContext->pSps) {
- return cmInitExpected;
- }
- iVal = (int)m_pDecContext->pSps->uiLevelIdc;
- * ((int*)pOption) = iVal;
- return cmResultSuccess;
- } else if (DECODER_OPTION_NUM_OF_FRAMES_REMAINING_IN_BUFFER == eOptID) {
- if (m_pDecContext->pSps && m_pDecContext->pSps->uiProfileIdc != 66 && m_pDecContext->pPps->bEntropyCodingModeFlag) {
- * ((int*)pOption) = m_iNumOfPicts > 0 ? m_iNumOfPicts : 0;
- }
- return cmResultSuccess;
- }
-
- return cmInitParaError;
-}
-
-DECODING_STATE CWelsDecoder::DecodeFrameNoDelay (const unsigned char* kpSrc,
- const int kiSrcLen,
- unsigned char** ppDst,
- SBufferInfo* pDstInfo) {
- int iRet;
- //SBufferInfo sTmpBufferInfo;
- //unsigned char* ppTmpDst[3] = {NULL, NULL, NULL};
- iRet = (int)DecodeFrame2 (kpSrc, kiSrcLen, ppDst, pDstInfo);
- //memcpy (&sTmpBufferInfo, pDstInfo, sizeof (SBufferInfo));
- //ppTmpDst[0] = ppDst[0];
- //ppTmpDst[1] = ppDst[1];
- //ppTmpDst[2] = ppDst[2];
- iRet |= DecodeFrame2 (NULL, 0, ppDst, pDstInfo);
- //if ((pDstInfo->iBufferStatus == 0) && (sTmpBufferInfo.iBufferStatus == 1)) {
- //memcpy (pDstInfo, &sTmpBufferInfo, sizeof (SBufferInfo));
- //ppDst[0] = ppTmpDst[0];
- //ppDst[1] = ppTmpDst[1];
- //ppDst[2] = ppTmpDst[2];
- //}
- return (DECODING_STATE)iRet;
-}
-
-DECODING_STATE CWelsDecoder::DecodeFrame2 (const unsigned char* kpSrc,
- const int kiSrcLen,
- unsigned char** ppDst,
- SBufferInfo* pDstInfo) {
- if (m_pDecContext == NULL || m_pDecContext->pParam == NULL) {
- if (m_pWelsTrace != NULL) {
- WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "Call DecodeFrame2 without Initialize.\n");
- }
- return dsInitialOptExpected;
- }
-
- if (m_pDecContext->pParam->bParseOnly) {
- WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "bParseOnly should be false for this API calling! \n");
- m_pDecContext->iErrorCode |= dsInvalidArgument;
- return dsInvalidArgument;
- }
- if (CheckBsBuffer (m_pDecContext, kiSrcLen)) {
- if (ResetDecoder())
- return dsOutOfMemory;
-
- return dsErrorFree;
- }
- if (kiSrcLen > 0 && kpSrc != NULL) {
-#ifdef OUTPUT_BIT_STREAM
- if (m_pFBS) {
- WelsFwrite (kpSrc, sizeof (unsigned char), kiSrcLen, m_pFBS);
- WelsFflush (m_pFBS);
- }
- if (m_pFBSSize) {
- WelsFwrite (&kiSrcLen, sizeof (int), 1, m_pFBSSize);
- WelsFflush (m_pFBSSize);
- }
-#endif//OUTPUT_BIT_STREAM
- m_pDecContext->bEndOfStreamFlag = false;
- } else {
- //For application MODE, the error detection should be added for safe.
- //But for CONSOLE MODE, when decoding LAST AU, kiSrcLen==0 && kpSrc==NULL.
- m_pDecContext->bEndOfStreamFlag = true;
- m_pDecContext->bInstantDecFlag = true;
- }
-
- int64_t iStart, iEnd;
- iStart = WelsTime();
-
- ppDst[0] = ppDst[1] = ppDst[2] = NULL;
- m_pDecContext->iErrorCode = dsErrorFree; //initialize at the starting of AU decoding.
- m_pDecContext->iFeedbackVclNalInAu = FEEDBACK_UNKNOWN_NAL; //initialize
- unsigned long long uiInBsTimeStamp = pDstInfo->uiInBsTimeStamp;
- memset (pDstInfo, 0, sizeof (SBufferInfo));
- pDstInfo->uiInBsTimeStamp = uiInBsTimeStamp;
-#ifdef LONG_TERM_REF
- m_pDecContext->bReferenceLostAtT0Flag = false; //initialize for LTR
- m_pDecContext->bCurAuContainLtrMarkSeFlag = false;
- m_pDecContext->iFrameNumOfAuMarkedLtr = 0;
- m_pDecContext->iFrameNum = -1; //initialize
-#endif
-
- m_pDecContext->iFeedbackTidInAu = -1; //initialize
- m_pDecContext->iFeedbackNalRefIdc = -1; //initialize
- if (pDstInfo) {
- pDstInfo->uiOutYuvTimeStamp = 0;
- m_pDecContext->uiTimeStamp = pDstInfo->uiInBsTimeStamp;
- } else {
- m_pDecContext->uiTimeStamp = 0;
- }
- WelsDecodeBs (m_pDecContext, kpSrc, kiSrcLen, ppDst,
- pDstInfo, NULL); //iErrorCode has been modified in this function
- m_pDecContext->bInstantDecFlag = false; //reset no-delay flag
- if (m_pDecContext->iErrorCode) {
- EWelsNalUnitType eNalType =
- NAL_UNIT_UNSPEC_0; //for NBR, IDR frames are expected to decode as followed if error decoding an IDR currently
-
- eNalType = m_pDecContext->sCurNalHead.eNalUnitType;
-
- if (m_pDecContext->iErrorCode & dsOutOfMemory) {
- if (ResetDecoder())
- return dsOutOfMemory;
-
- return dsErrorFree;
- }
- //for AVC bitstream (excluding AVC with temporal scalability, including TP), as long as error occur, SHOULD notify upper layer key frame loss.
- if ((IS_PARAM_SETS_NALS (eNalType) || NAL_UNIT_CODED_SLICE_IDR == eNalType) ||
- (VIDEO_BITSTREAM_AVC == m_pDecContext->eVideoType)) {
- if (m_pDecContext->pParam->eEcActiveIdc == ERROR_CON_DISABLE) {
-#ifdef LONG_TERM_REF
- m_pDecContext->bParamSetsLostFlag = true;
-#else
- m_pDecContext->bReferenceLostAtT0Flag = true;
-#endif
- }
- }
-
- if (m_pDecContext->bPrintFrameErrorTraceFlag) {
- WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "decode failed, failure type:%d \n",
- m_pDecContext->iErrorCode);
- m_pDecContext->bPrintFrameErrorTraceFlag = false;
- } else {
- m_pDecContext->iIgnoredErrorInfoPacketCount++;
- if (m_pDecContext->iIgnoredErrorInfoPacketCount == INT_MAX) {
- WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING, "continuous error reached INT_MAX! Restart as 0.");
- m_pDecContext->iIgnoredErrorInfoPacketCount = 0;
- }
- }
- if ((m_pDecContext->pParam->eEcActiveIdc != ERROR_CON_DISABLE) && (pDstInfo->iBufferStatus == 1)) {
- //TODO after dec status updated
- m_pDecContext->iErrorCode |= dsDataErrorConcealed;
-
- m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++;
- if (m_pDecContext->sDecoderStatistics.uiDecodedFrameCount == 0) { //exceed max value of uint32_t
- ResetDecStatNums (&m_pDecContext->sDecoderStatistics);
- m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++;
- }
- int32_t iMbConcealedNum = m_pDecContext->iMbEcedNum + m_pDecContext->iMbEcedPropNum;
- m_pDecContext->sDecoderStatistics.uiAvgEcRatio = m_pDecContext->iMbNum == 0 ?
- (m_pDecContext->sDecoderStatistics.uiAvgEcRatio * m_pDecContext->sDecoderStatistics.uiEcFrameNum) : ((
- m_pDecContext->sDecoderStatistics.uiAvgEcRatio * m_pDecContext->sDecoderStatistics.uiEcFrameNum) + ((
- iMbConcealedNum * 100) / m_pDecContext->iMbNum));
- m_pDecContext->sDecoderStatistics.uiAvgEcPropRatio = m_pDecContext->iMbNum == 0 ?
- (m_pDecContext->sDecoderStatistics.uiAvgEcPropRatio * m_pDecContext->sDecoderStatistics.uiEcFrameNum) : ((
- m_pDecContext->sDecoderStatistics.uiAvgEcPropRatio * m_pDecContext->sDecoderStatistics.uiEcFrameNum) + ((
- m_pDecContext->iMbEcedPropNum * 100) / m_pDecContext->iMbNum));
- m_pDecContext->sDecoderStatistics.uiEcFrameNum += (iMbConcealedNum == 0 ? 0 : 1);
- m_pDecContext->sDecoderStatistics.uiAvgEcRatio = m_pDecContext->sDecoderStatistics.uiEcFrameNum == 0 ? 0 :
- m_pDecContext->sDecoderStatistics.uiAvgEcRatio / m_pDecContext->sDecoderStatistics.uiEcFrameNum;
- m_pDecContext->sDecoderStatistics.uiAvgEcPropRatio = m_pDecContext->sDecoderStatistics.uiEcFrameNum == 0 ? 0 :
- m_pDecContext->sDecoderStatistics.uiAvgEcPropRatio / m_pDecContext->sDecoderStatistics.uiEcFrameNum;
- }
- iEnd = WelsTime();
- m_pDecContext->dDecTime += (iEnd - iStart) / 1e3;
-
- OutputStatisticsLog (m_pDecContext->sDecoderStatistics);
-
-#ifdef _PICTURE_REORDERING_
- ReorderPicturesInDisplay (ppDst, pDstInfo);
-#endif
-
- return (DECODING_STATE)m_pDecContext->iErrorCode;
- }
- // else Error free, the current codec works well
-
- if (pDstInfo->iBufferStatus == 1) {
-
- m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++;
- if (m_pDecContext->sDecoderStatistics.uiDecodedFrameCount == 0) { //exceed max value of uint32_t
- ResetDecStatNums (&m_pDecContext->sDecoderStatistics);
- m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++;
- }
-
- OutputStatisticsLog (m_pDecContext->sDecoderStatistics);
- }
- iEnd = WelsTime();
- m_pDecContext->dDecTime += (iEnd - iStart) / 1e3;
-
-#ifdef _PICTURE_REORDERING_
- ReorderPicturesInDisplay (ppDst, pDstInfo);
-#endif
- return dsErrorFree;
-}
-
-DECODING_STATE CWelsDecoder::FlushFrame (unsigned char** ppDst,
- SBufferInfo* pDstInfo) {
- if (m_pDecContext->bEndOfStreamFlag && m_iNumOfPicts > 0) {
- m_iMinPOC = sIMinInt32;
- for (int32_t i = 0; i <= m_iLargestBufferedPicIndex; ++i) {
- if (m_iMinPOC == sIMinInt32 && m_sPictInfoList[i].iPOC > sIMinInt32) {
- m_iMinPOC = m_sPictInfoList[i].iPOC;
- m_iPictInfoIndex = i;
- }
- if (m_sPictInfoList[i].iPOC > sIMinInt32 && m_sPictInfoList[i].iPOC < m_iMinPOC) {
- m_iMinPOC = m_sPictInfoList[i].iPOC;
- m_iPictInfoIndex = i;
- }
- }
- }
- if (m_iMinPOC > sIMinInt32) {
- m_LastWrittenPOC = m_iMinPOC;
-#if defined (_DEBUG)
-#ifdef _MOTION_VECTOR_DUMP_
- fprintf (stderr, "Output POC: #%d\n", m_LastWrittenPOC);
-#endif
-#endif
- memcpy (pDstInfo, &m_sPictInfoList[m_iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo));
- ppDst[0] = m_sPictInfoList[m_iPictInfoIndex].pData[0];
- ppDst[1] = m_sPictInfoList[m_iPictInfoIndex].pData[1];
- ppDst[2] = m_sPictInfoList[m_iPictInfoIndex].pData[2];
- m_sPictInfoList[m_iPictInfoIndex].iPOC = sIMinInt32;
- m_sPictInfoList[m_iPictInfoIndex].bLastGOP = false;
- m_iMinPOC = sIMinInt32;
- --m_iNumOfPicts;
- }
- return dsErrorFree;
-}
-
-void CWelsDecoder::OutputStatisticsLog (SDecoderStatistics& sDecoderStatistics) {
- if ((sDecoderStatistics.uiDecodedFrameCount > 0) && (sDecoderStatistics.iStatisticsLogInterval > 0)
- && ((sDecoderStatistics.uiDecodedFrameCount % sDecoderStatistics.iStatisticsLogInterval) == 0)) {
- WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
- "DecoderStatistics: uiWidth=%d, uiHeight=%d, fAverageFrameSpeedInMs=%.1f, fActualAverageFrameSpeedInMs=%.1f, \
- uiDecodedFrameCount=%d, uiResolutionChangeTimes=%d, uiIDRCorrectNum=%d, \
- uiAvgEcRatio=%d, uiAvgEcPropRatio=%d, uiEcIDRNum=%d, uiEcFrameNum=%d, \
- uiIDRLostNum=%d, uiFreezingIDRNum=%d, uiFreezingNonIDRNum=%d, iAvgLumaQp=%d, \
- iSpsReportErrorNum=%d, iSubSpsReportErrorNum=%d, iPpsReportErrorNum=%d, iSpsNoExistNalNum=%d, iSubSpsNoExistNalNum=%d, iPpsNoExistNalNum=%d, \
- uiProfile=%d, uiLevel=%d, \
- iCurrentActiveSpsId=%d, iCurrentActivePpsId=%d,",
- sDecoderStatistics.uiWidth,
- sDecoderStatistics.uiHeight,
- sDecoderStatistics.fAverageFrameSpeedInMs,
- sDecoderStatistics.fActualAverageFrameSpeedInMs,
-
- sDecoderStatistics.uiDecodedFrameCount,
- sDecoderStatistics.uiResolutionChangeTimes,
- sDecoderStatistics.uiIDRCorrectNum,
-
- sDecoderStatistics.uiAvgEcRatio,
- sDecoderStatistics.uiAvgEcPropRatio,
- sDecoderStatistics.uiEcIDRNum,
- sDecoderStatistics.uiEcFrameNum,
-
- sDecoderStatistics.uiIDRLostNum,
- sDecoderStatistics.uiFreezingIDRNum,
- sDecoderStatistics.uiFreezingNonIDRNum,
- sDecoderStatistics.iAvgLumaQp,
-
- sDecoderStatistics.iSpsReportErrorNum,
- sDecoderStatistics.iSubSpsReportErrorNum,
- sDecoderStatistics.iPpsReportErrorNum,
- sDecoderStatistics.iSpsNoExistNalNum,
- sDecoderStatistics.iSubSpsNoExistNalNum,
- sDecoderStatistics.iPpsNoExistNalNum,
-
- sDecoderStatistics.uiProfile,
- sDecoderStatistics.uiLevel,
-
- sDecoderStatistics.iCurrentActiveSpsId,
- sDecoderStatistics.iCurrentActivePpsId);
- }
-}
-
-DECODING_STATE CWelsDecoder::ReorderPicturesInDisplay (unsigned char** ppDst, SBufferInfo* pDstInfo) {
- if (pDstInfo->iBufferStatus == 1 && m_pDecContext->pSps->uiProfileIdc != 66
- && m_pDecContext->pPps->bEntropyCodingModeFlag) {
- if (m_pDecContext->pSliceHeader->iPicOrderCntLsb == 0) {
- if (m_iNumOfPicts > 0) {
- m_iLastGOPRemainPicts = m_iNumOfPicts;
- for (int32_t i = 0; i <= m_iLargestBufferedPicIndex; ++i) {
- if (m_sPictInfoList[i].iPOC > sIMinInt32) {
- m_sPictInfoList[i].bLastGOP = true;
- }
- }
- }
- }
- for (int32_t i = 0; i < 16; ++i) {
- if (m_sPictInfoList[i].iPOC == sIMinInt32) {
- memcpy (&m_sPictInfoList[i].sBufferInfo, pDstInfo, sizeof (SBufferInfo));
- m_sPictInfoList[i].pData[0] = ppDst[0];
- m_sPictInfoList[i].pData[1] = ppDst[1];
- m_sPictInfoList[i].pData[2] = ppDst[2];
- m_sPictInfoList[i].iPOC = m_pDecContext->pSliceHeader->iPicOrderCntLsb;
- m_sPictInfoList[i].iFrameNum = m_pDecContext->pSliceHeader->iFrameNum;
- m_sPictInfoList[i].bLastGOP = false;
- pDstInfo->iBufferStatus = 0;
- ++m_iNumOfPicts;
- if (i > m_iLargestBufferedPicIndex) {
- m_iLargestBufferedPicIndex = i;
- }
- break;
- }
- }
- if (m_iLastGOPRemainPicts > 0) {
- m_iMinPOC = sIMinInt32;
- for (int32_t i = 0; i <= m_iLargestBufferedPicIndex; ++i) {
- if (m_iMinPOC == sIMinInt32 && m_sPictInfoList[i].iPOC > sIMinInt32 && m_sPictInfoList[i].bLastGOP) {
- m_iMinPOC = m_sPictInfoList[i].iPOC;
- m_iPictInfoIndex = i;
- }
- if (m_sPictInfoList[i].iPOC > sIMinInt32 && m_sPictInfoList[i].iPOC < m_iMinPOC && m_sPictInfoList[i].bLastGOP) {
- m_iMinPOC = m_sPictInfoList[i].iPOC;
- m_iPictInfoIndex = i;
- }
- }
- m_LastWrittenPOC = m_iMinPOC;
-#if defined (_DEBUG)
-#ifdef _MOTION_VECTOR_DUMP_
- fprintf (stderr, "Output POC: #%d\n", m_LastWrittenPOC);
-#endif
-#endif
- memcpy (pDstInfo, &m_sPictInfoList[m_iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo));
- ppDst[0] = m_sPictInfoList[m_iPictInfoIndex].pData[0];
- ppDst[1] = m_sPictInfoList[m_iPictInfoIndex].pData[1];
- ppDst[2] = m_sPictInfoList[m_iPictInfoIndex].pData[2];
- m_sPictInfoList[m_iPictInfoIndex].iPOC = sIMinInt32;
- m_sPictInfoList[m_iPictInfoIndex].bLastGOP = false;
- m_iMinPOC = sIMinInt32;
- --m_iNumOfPicts;
- --m_iLastGOPRemainPicts;
- if (m_iLastGOPRemainPicts == 0) {
- m_LastWrittenPOC = sIMinInt32;
- }
- return dsErrorFree;
- }
- if (m_iNumOfPicts > 0) {
- m_iMinPOC = sIMinInt32;
- for (int32_t i = 0; i <= m_iLargestBufferedPicIndex; ++i) {
- if (m_iMinPOC == sIMinInt32 && m_sPictInfoList[i].iPOC > sIMinInt32) {
- m_iMinPOC = m_sPictInfoList[i].iPOC;
- m_iPictInfoIndex = i;
- }
- if (m_sPictInfoList[i].iPOC > sIMinInt32 && m_sPictInfoList[i].iPOC < m_iMinPOC) {
- m_iMinPOC = m_sPictInfoList[i].iPOC;
- m_iPictInfoIndex = i;
- }
- }
- }
- if (m_iMinPOC > sIMinInt32) {
- if ((m_LastWrittenPOC > sIMinInt32 && m_iMinPOC - m_LastWrittenPOC <= 1)
- || m_iMinPOC < m_pDecContext->pSliceHeader->iPicOrderCntLsb) {
- m_LastWrittenPOC = m_iMinPOC;
-#if defined (_DEBUG)
-#ifdef _MOTION_VECTOR_DUMP_
- fprintf (stderr, "Output POC: #%d\n", m_LastWrittenPOC);
-#endif
-#endif
- memcpy (pDstInfo, &m_sPictInfoList[m_iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo));
- ppDst[0] = m_sPictInfoList[m_iPictInfoIndex].pData[0];
- ppDst[1] = m_sPictInfoList[m_iPictInfoIndex].pData[1];
- ppDst[2] = m_sPictInfoList[m_iPictInfoIndex].pData[2];
- m_sPictInfoList[m_iPictInfoIndex].iPOC = sIMinInt32;
- m_sPictInfoList[m_iPictInfoIndex].bLastGOP = false;
- m_iMinPOC = sIMinInt32;
- --m_iNumOfPicts;
- return dsErrorFree;
- }
- }
- }
-
- return dsErrorFree;
-}
-
-DECODING_STATE CWelsDecoder::DecodeParser (const unsigned char* kpSrc,
- const int kiSrcLen,
- SParserBsInfo* pDstInfo) {
- if (m_pDecContext == NULL || m_pDecContext->pParam == NULL) {
- if (m_pWelsTrace != NULL) {
- WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "Call DecodeParser without Initialize.\n");
- }
- return dsInitialOptExpected;
- }
-
- if (!m_pDecContext->pParam->bParseOnly) {
- WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "bParseOnly should be true for this API calling! \n");
- m_pDecContext->iErrorCode |= dsInvalidArgument;
- return dsInvalidArgument;
- }
- int64_t iEnd, iStart = WelsTime();
- if (CheckBsBuffer (m_pDecContext, kiSrcLen)) {
- if (ResetDecoder())
- return dsOutOfMemory;
-
- return dsErrorFree;
- }
- if (kiSrcLen > 0 && kpSrc != NULL) {
-#ifdef OUTPUT_BITSTREAM
- if (m_pFBS) {
- WelsFwrite (kpSrc, sizeof (unsigned char), kiSrcLen, m_pFBS);
- WelsFflush (m_pFBS);
- }
-#endif//OUTPUT_BIT_STREAM
- m_pDecContext->bEndOfStreamFlag = false;
- } else {
- //For application MODE, the error detection should be added for safe.
- //But for CONSOLE MODE, when decoding LAST AU, kiSrcLen==0 && kpSrc==NULL.
- m_pDecContext->bEndOfStreamFlag = true;
- m_pDecContext->bInstantDecFlag = true;
- }
-
- m_pDecContext->iErrorCode = dsErrorFree; //initialize at the starting of AU decoding.
- m_pDecContext->pParam->eEcActiveIdc = ERROR_CON_DISABLE; //add protection to disable EC here.
- m_pDecContext->iFeedbackNalRefIdc = -1; //initialize
- if (!m_pDecContext->bFramePending) { //frame complete
- m_pDecContext->pParserBsInfo->iNalNum = 0;
- memset (m_pDecContext->pParserBsInfo->pNalLenInByte, 0, MAX_NAL_UNITS_IN_LAYER);
- }
- pDstInfo->iNalNum = 0;
- pDstInfo->iSpsWidthInPixel = pDstInfo->iSpsHeightInPixel = 0;
- if (pDstInfo) {
- m_pDecContext->uiTimeStamp = pDstInfo->uiInBsTimeStamp;
- pDstInfo->uiOutBsTimeStamp = 0;
- } else {
- m_pDecContext->uiTimeStamp = 0;
- }
- WelsDecodeBs (m_pDecContext, kpSrc, kiSrcLen, NULL, NULL, pDstInfo);
- if (m_pDecContext->iErrorCode & dsOutOfMemory) {
- if (ResetDecoder())
- return dsOutOfMemory;
- return dsErrorFree;
- }
-
- if (!m_pDecContext->bFramePending && m_pDecContext->pParserBsInfo->iNalNum) {
- memcpy (pDstInfo, m_pDecContext->pParserBsInfo, sizeof (SParserBsInfo));
-
- if (m_pDecContext->iErrorCode == ERR_NONE) { //update statistics: decoding frame count
- m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++;
- if (m_pDecContext->sDecoderStatistics.uiDecodedFrameCount == 0) { //exceed max value of uint32_t
- ResetDecStatNums (&m_pDecContext->sDecoderStatistics);
- m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++;
- }
- }
- }
-
- m_pDecContext->bInstantDecFlag = false; //reset no-delay flag
-
- if (m_pDecContext->iErrorCode && m_pDecContext->bPrintFrameErrorTraceFlag) {
- WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "decode failed, failure type:%d \n", m_pDecContext->iErrorCode);
- m_pDecContext->bPrintFrameErrorTraceFlag = false;
- }
- iEnd = WelsTime();
- m_pDecContext->dDecTime += (iEnd - iStart) / 1e3;
-
- return (DECODING_STATE) m_pDecContext->iErrorCode;
-}
-
-DECODING_STATE CWelsDecoder::DecodeFrame (const unsigned char* kpSrc,
- const int kiSrcLen,
- unsigned char** ppDst,
- int* pStride,
- int& iWidth,
- int& iHeight) {
- DECODING_STATE eDecState = dsErrorFree;
- SBufferInfo DstInfo;
-
- memset (&DstInfo, 0, sizeof (SBufferInfo));
- DstInfo.UsrData.sSystemBuffer.iStride[0] = pStride[0];
- DstInfo.UsrData.sSystemBuffer.iStride[1] = pStride[1];
- DstInfo.UsrData.sSystemBuffer.iWidth = iWidth;
- DstInfo.UsrData.sSystemBuffer.iHeight = iHeight;
-
- eDecState = DecodeFrame2 (kpSrc, kiSrcLen, ppDst, &DstInfo);
- if (eDecState == dsErrorFree) {
- pStride[0] = DstInfo.UsrData.sSystemBuffer.iStride[0];
- pStride[1] = DstInfo.UsrData.sSystemBuffer.iStride[1];
- iWidth = DstInfo.UsrData.sSystemBuffer.iWidth;
- iHeight = DstInfo.UsrData.sSystemBuffer.iHeight;
- }
-
- return eDecState;
-}
-
-DECODING_STATE CWelsDecoder::DecodeFrameEx (const unsigned char* kpSrc,
- const int kiSrcLen,
- unsigned char* pDst,
- int iDstStride,
- int& iDstLen,
- int& iWidth,
- int& iHeight,
- int& iColorFormat) {
- DECODING_STATE state = dsErrorFree;
-
- return state;
-}
-
-
-} // namespace WelsDec
-
-
-using namespace WelsDec;
-/*
-* WelsGetDecoderCapability
-* @return: DecCapability information
-*/
-int WelsGetDecoderCapability (SDecoderCapability* pDecCapability) {
- memset (pDecCapability, 0, sizeof (SDecoderCapability));
- pDecCapability->iProfileIdc = 66; //Baseline
- pDecCapability->iProfileIop = 0xE0; //11100000b
- pDecCapability->iLevelIdc = 32; //level_idc = 3.2
- pDecCapability->iMaxMbps = 216000; //from level_idc = 3.2
- pDecCapability->iMaxFs = 5120; //from level_idc = 3.2
- pDecCapability->iMaxCpb = 20000; //from level_idc = 3.2
- pDecCapability->iMaxDpb = 20480; //from level_idc = 3.2
- pDecCapability->iMaxBr = 20000; //from level_idc = 3.2
- pDecCapability->bRedPicCap = 0; //not support redundant pic
-
- return ERR_NONE;
-}
-/* WINAPI is indeed in prefix due to sync to application layer callings!! */
-
-/*
-* WelsCreateDecoder
-* @return: success in return 0, otherwise failed.
-*/
-long WelsCreateDecoder (ISVCDecoder** ppDecoder) {
-
- if (NULL == ppDecoder) {
- return ERR_INVALID_PARAMETERS;
- }
-
- *ppDecoder = new CWelsDecoder();
-
- if (NULL == *ppDecoder) {
- return ERR_MALLOC_FAILED;
- }
-
- return ERR_NONE;
-}
-
-/*
-* WelsDestroyDecoder
-*/
-void WelsDestroyDecoder (ISVCDecoder* pDecoder) {
- if (NULL != pDecoder) {
- delete (CWelsDecoder*)pDecoder;
- }
-}
+/*!
+ * \copy
+ * Copyright (c) 2009-2013, Cisco Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * welsDecoderExt.cpp
+ *
+ * Abstract
+ * Cisco OpenH264 decoder extension utilization
+ *
+ * History
+ * 3/12/2009 Created
+ *
+ *
+ ************************************************************************/
+//#include <assert.h>
+#include "welsDecoderExt.h"
+#include "welsCodecTrace.h"
+#include "codec_def.h"
+#include "typedefs.h"
+#include "memory_align.h"
+#include "utils.h"
+#include "version.h"
+
+//#include "macros.h"
+#include "decoder.h"
+#include "decoder_core.h"
+#include "error_concealment.h"
+
+#include "measure_time.h"
+extern "C" {
+#include "decoder_core.h"
+#include "manage_dec_ref.h"
+}
+#include "error_code.h"
+#include "crt_util_safe_x.h" // Safe CRT routines like util for cross platforms
+#include <time.h>
+#if defined(_WIN32) /*&& defined(_DEBUG)*/
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#else
+#include <sys/time.h>
+#endif
+
+#define _PICTURE_REORDERING_ 1
+
+static int32_t sIMinInt32 = -0x7FFFFFFF;
+
+namespace WelsDec {
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+/***************************************************************************
+* Description:
+* class CWelsDecoder constructor function, do initialization and
+* alloc memory required
+*
+* Input parameters: none
+*
+* return: none
+***************************************************************************/
+CWelsDecoder::CWelsDecoder (void)
+ : m_pDecContext (NULL),
+ m_pWelsTrace (NULL),
+ m_iPictInfoIndex (0),
+ m_iMinPOC (sIMinInt32),
+ m_iNumOfPicts (0),
+ m_iLastGOPRemainPicts (0),
+ m_LastWrittenPOC (sIMinInt32),
+ m_iLargestBufferedPicIndex (0) {
+#ifdef OUTPUT_BIT_STREAM
+ char chFileName[1024] = { 0 }; //for .264
+ int iBufUsed = 0;
+ int iBufLeft = 1023;
+ int iCurUsed;
+
+ char chFileNameSize[1024] = { 0 }; //for .len
+ int iBufUsedSize = 0;
+ int iBufLeftSize = 1023;
+ int iCurUsedSize;
+#endif//OUTPUT_BIT_STREAM
+
+
+ m_pWelsTrace = new welsCodecTrace();
+ if (m_pWelsTrace != NULL) {
+ m_pWelsTrace->SetCodecInstance (this);
+ m_pWelsTrace->SetTraceLevel (WELS_LOG_ERROR);
+
+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::CWelsDecoder() entry");
+ }
+
+ for (int32_t i = 0; i < 16; ++i) {
+ m_sPictInfoList[i].bLastGOP = false;
+ m_sPictInfoList[i].iPOC = sIMinInt32;
+ }
+
+#ifdef OUTPUT_BIT_STREAM
+ SWelsTime sCurTime;
+
+ WelsGetTimeOfDay (&sCurTime);
+
+ iCurUsed = WelsSnprintf (chFileName, iBufLeft, "bs_0x%p_", (void*)this);
+ iCurUsedSize = WelsSnprintf (chFileNameSize, iBufLeftSize, "size_0x%p_", (void*)this);
+
+ iBufUsed += iCurUsed;
+ iBufLeft -= iCurUsed;
+ if (iBufLeft > 0) {
+ iCurUsed = WelsStrftime (&chFileName[iBufUsed], iBufLeft, "%y%m%d%H%M%S", &sCurTime);
+ iBufUsed += iCurUsed;
+ iBufLeft -= iCurUsed;
+ }
+
+ iBufUsedSize += iCurUsedSize;
+ iBufLeftSize -= iCurUsedSize;
+ if (iBufLeftSize > 0) {
+ iCurUsedSize = WelsStrftime (&chFileNameSize[iBufUsedSize], iBufLeftSize, "%y%m%d%H%M%S", &sCurTime);
+ iBufUsedSize += iCurUsedSize;
+ iBufLeftSize -= iCurUsedSize;
+ }
+
+ if (iBufLeft > 0) {
+ iCurUsed = WelsSnprintf (&chFileName[iBufUsed], iBufLeft, ".%03.3u.264", WelsGetMillisecond (&sCurTime));
+ iBufUsed += iCurUsed;
+ iBufLeft -= iCurUsed;
+ }
+
+ if (iBufLeftSize > 0) {
+ iCurUsedSize = WelsSnprintf (&chFileNameSize[iBufUsedSize], iBufLeftSize, ".%03.3u.len",
+ WelsGetMillisecond (&sCurTime));
+ iBufUsedSize += iCurUsedSize;
+ iBufLeftSize -= iCurUsedSize;
+ }
+
+
+ m_pFBS = WelsFopen (chFileName, "wb");
+ m_pFBSSize = WelsFopen (chFileNameSize, "wb");
+#endif//OUTPUT_BIT_STREAM
+}
+
+/***************************************************************************
+* Description:
+* class CWelsDecoder destructor function, destroy allocced memory
+*
+* Input parameters: none
+*
+* return: none
+***************************************************************************/
+CWelsDecoder::~CWelsDecoder() {
+ if (m_pWelsTrace != NULL) {
+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::~CWelsDecoder()");
+ }
+
+ UninitDecoder();
+
+#ifdef OUTPUT_BIT_STREAM
+ if (m_pFBS) {
+ WelsFclose (m_pFBS);
+ m_pFBS = NULL;
+ }
+ if (m_pFBSSize) {
+ WelsFclose (m_pFBSSize);
+ m_pFBSSize = NULL;
+ }
+#endif//OUTPUT_BIT_STREAM
+
+ if (m_pWelsTrace != NULL) {
+ delete m_pWelsTrace;
+ m_pWelsTrace = NULL;
+ }
+}
+
+long CWelsDecoder::Initialize (const SDecodingParam* pParam) {
+ int iRet = ERR_NONE;
+ if (m_pWelsTrace == NULL) {
+ return cmMallocMemeError;
+ }
+
+ if (pParam == NULL) {
+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "CWelsDecoder::Initialize(), invalid input argument.");
+ return cmInitParaError;
+ }
+
+ // H.264 decoder initialization,including memory allocation,then open it ready to decode
+ iRet = InitDecoder (pParam);
+ if (iRet)
+ return iRet;
+
+ return cmResultSuccess;
+}
+
+long CWelsDecoder::Uninitialize() {
+ UninitDecoder();
+
+ return ERR_NONE;
+}
+
+void CWelsDecoder::UninitDecoder (void) {
+ if (NULL == m_pDecContext)
+ return;
+
+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::UninitDecoder(), openh264 codec version = %s.",
+ VERSION_NUMBER);
+
+ WelsEndDecoder (m_pDecContext);
+
+ if (m_pDecContext->pMemAlign != NULL) {
+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
+ "CWelsDecoder::UninitDecoder(), verify memory usage (%d bytes) after free..",
+ m_pDecContext->pMemAlign->WelsGetMemoryUsage());
+ delete m_pDecContext->pMemAlign;
+ m_pDecContext->pMemAlign = NULL;
+ }
+
+ if (NULL != m_pDecContext) {
+ WelsFree (m_pDecContext, "m_pDecContext");
+
+ m_pDecContext = NULL;
+ }
+}
+
+// the return value of this function is not suitable, it need report failure info to upper layer.
+int32_t CWelsDecoder::InitDecoder (const SDecodingParam* pParam) {
+
+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
+ "CWelsDecoder::init_decoder(), openh264 codec version = %s, ParseOnly = %d",
+ VERSION_NUMBER, (int32_t)pParam->bParseOnly);
+
+ //reset decoder context
+ if (m_pDecContext) //free
+ UninitDecoder();
+ m_pDecContext = (PWelsDecoderContext)WelsMallocz (sizeof (SWelsDecoderContext), "m_pDecContext");
+ if (NULL == m_pDecContext)
+ return cmMallocMemeError;
+ int32_t iCacheLineSize = 16; // on chip cache line size in byte
+ m_pDecContext->pMemAlign = new CMemoryAlign (iCacheLineSize);
+ WELS_VERIFY_RETURN_PROC_IF (cmMallocMemeError, (NULL == m_pDecContext->pMemAlign), UninitDecoder())
+
+ //fill in default value into context
+ WelsDecoderDefaults (m_pDecContext, &m_pWelsTrace->m_sLogCtx);
+
+ //check param and update decoder context
+ m_pDecContext->pParam = (SDecodingParam*)m_pDecContext->pMemAlign->WelsMallocz (sizeof (SDecodingParam),
+ "SDecodingParam");
+ WELS_VERIFY_RETURN_PROC_IF (cmMallocMemeError, (NULL == m_pDecContext->pParam), UninitDecoder());
+ int32_t iRet = DecoderConfigParam (m_pDecContext, pParam);
+ WELS_VERIFY_RETURN_IFNEQ (iRet, cmResultSuccess);
+
+ //init decoder
+ WELS_VERIFY_RETURN_PROC_IF (cmMallocMemeError, WelsInitDecoder (m_pDecContext, &m_pWelsTrace->m_sLogCtx),
+ UninitDecoder())
+
+ return cmResultSuccess;
+}
+
+int32_t CWelsDecoder::ResetDecoder() {
+ // TBC: need to be modified when context and trace point are null
+ if (m_pDecContext != NULL && m_pWelsTrace != NULL) {
+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "ResetDecoder(), context error code is %d",
+ m_pDecContext->iErrorCode);
+ SDecodingParam sPrevParam;
+ memcpy (&sPrevParam, m_pDecContext->pParam, sizeof (SDecodingParam));
+
+ WELS_VERIFY_RETURN_PROC_IF (cmInitParaError, InitDecoder (&sPrevParam), UninitDecoder());
+ } else if (m_pWelsTrace != NULL) {
+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "ResetDecoder() failed as decoder context null");
+ }
+ return ERR_INFO_UNINIT;
+}
+
+/*
+ * Set Option
+ */
+long CWelsDecoder::SetOption (DECODER_OPTION eOptID, void* pOption) {
+ int iVal = 0;
+
+ if (m_pDecContext == NULL && eOptID != DECODER_OPTION_TRACE_LEVEL &&
+ eOptID != DECODER_OPTION_TRACE_CALLBACK && eOptID != DECODER_OPTION_TRACE_CALLBACK_CONTEXT)
+ return dsInitialOptExpected;
+ if (eOptID == DECODER_OPTION_END_OF_STREAM) { // Indicate bit-stream of the final frame to be decoded
+ if (pOption == NULL)
+ return cmInitParaError;
+
+ iVal = * ((int*)pOption); // boolean value for whether enabled End Of Stream flag
+
+ m_pDecContext->bEndOfStreamFlag = iVal ? true : false;
+
+ return cmResultSuccess;
+ } else if (eOptID == DECODER_OPTION_ERROR_CON_IDC) { // Indicate error concealment status
+ if (pOption == NULL)
+ return cmInitParaError;
+
+ iVal = * ((int*)pOption); // int value for error concealment idc
+ iVal = WELS_CLIP3 (iVal, (int32_t)ERROR_CON_DISABLE, (int32_t)ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE);
+ if ((m_pDecContext->pParam->bParseOnly) && (iVal != (int32_t)ERROR_CON_DISABLE)) {
+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
+ "CWelsDecoder::SetOption for ERROR_CON_IDC = %d not allowd for parse only!.", iVal);
+ return cmInitParaError;
+ }
+
+ m_pDecContext->pParam->eEcActiveIdc = (ERROR_CON_IDC)iVal;
+ InitErrorCon (m_pDecContext);
+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
+ "CWelsDecoder::SetOption for ERROR_CON_IDC = %d.", iVal);
+
+ return cmResultSuccess;
+ } else if (eOptID == DECODER_OPTION_TRACE_LEVEL) {
+ if (m_pWelsTrace) {
+ uint32_t level = * ((uint32_t*)pOption);
+ m_pWelsTrace->SetTraceLevel (level);
+ }
+ return cmResultSuccess;
+ } else if (eOptID == DECODER_OPTION_TRACE_CALLBACK) {
+ if (m_pWelsTrace) {
+ WelsTraceCallback callback = * ((WelsTraceCallback*)pOption);
+ m_pWelsTrace->SetTraceCallback (callback);
+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
+ "CWelsDecoder::SetOption():DECODER_OPTION_TRACE_CALLBACK callback = %p.",
+ callback);
+ }
+ return cmResultSuccess;
+ } else if (eOptID == DECODER_OPTION_TRACE_CALLBACK_CONTEXT) {
+ if (m_pWelsTrace) {
+ void* ctx = * ((void**)pOption);
+ m_pWelsTrace->SetTraceCallbackContext (ctx);
+ }
+ return cmResultSuccess;
+ } else if (eOptID == DECODER_OPTION_GET_STATISTICS) {
+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING,
+ "CWelsDecoder::SetOption():DECODER_OPTION_GET_STATISTICS: this option is get-only!");
+ return cmInitParaError;
+ } else if (eOptID == DECODER_OPTION_STATISTICS_LOG_INTERVAL) {
+ if (pOption) {
+ m_pDecContext->sDecoderStatistics.iStatisticsLogInterval = (* ((unsigned int*)pOption));
+ return cmResultSuccess;
+ }
+ } else if (eOptID == DECODER_OPTION_GET_SAR_INFO) {
+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING,
+ "CWelsDecoder::SetOption():DECODER_OPTION_GET_SAR_INFO: this option is get-only!");
+ return cmInitParaError;
+ }
+ return cmInitParaError;
+}
+
+/*
+ * Get Option
+ */
+long CWelsDecoder::GetOption (DECODER_OPTION eOptID, void* pOption) {
+ int iVal = 0;
+
+ if (m_pDecContext == NULL)
+ return cmInitExpected;
+
+ if (pOption == NULL)
+ return cmInitParaError;
+
+ if (DECODER_OPTION_END_OF_STREAM == eOptID) {
+ iVal = m_pDecContext->bEndOfStreamFlag;
+ * ((int*)pOption) = iVal;
+ return cmResultSuccess;
+ }
+#ifdef LONG_TERM_REF
+ else if (DECODER_OPTION_IDR_PIC_ID == eOptID) {
+ iVal = m_pDecContext->uiCurIdrPicId;
+ * ((int*)pOption) = iVal;
+ return cmResultSuccess;
+ } else if (DECODER_OPTION_FRAME_NUM == eOptID) {
+ iVal = m_pDecContext->iFrameNum;
+ * ((int*)pOption) = iVal;
+ return cmResultSuccess;
+ } else if (DECODER_OPTION_LTR_MARKING_FLAG == eOptID) {
+ iVal = m_pDecContext->bCurAuContainLtrMarkSeFlag;
+ * ((int*)pOption) = iVal;
+ return cmResultSuccess;
+ } else if (DECODER_OPTION_LTR_MARKED_FRAME_NUM == eOptID) {
+ iVal = m_pDecContext->iFrameNumOfAuMarkedLtr;
+ * ((int*)pOption) = iVal;
+ return cmResultSuccess;
+ }
+#endif
+ else if (DECODER_OPTION_VCL_NAL == eOptID) { //feedback whether or not have VCL NAL in current AU
+ iVal = m_pDecContext->iFeedbackVclNalInAu;
+ * ((int*)pOption) = iVal;
+ return cmResultSuccess;
+ } else if (DECODER_OPTION_TEMPORAL_ID == eOptID) { //if have VCL NAL in current AU, then feedback the temporal ID
+ iVal = m_pDecContext->iFeedbackTidInAu;
+ * ((int*)pOption) = iVal;
+ return cmResultSuccess;
+ } else if (DECODER_OPTION_IS_REF_PIC == eOptID) {
+ iVal = m_pDecContext->iFeedbackNalRefIdc;
+ if (iVal > 0)
+ iVal = 1;
+ * ((int*)pOption) = iVal;
+ return cmResultSuccess;
+ } else if (DECODER_OPTION_ERROR_CON_IDC == eOptID) {
+ iVal = (int)m_pDecContext->pParam->eEcActiveIdc;
+ * ((int*)pOption) = iVal;
+ return cmResultSuccess;
+ } else if (DECODER_OPTION_GET_STATISTICS == eOptID) { // get decoder statistics info for real time debugging
+ SDecoderStatistics* pDecoderStatistics = (static_cast<SDecoderStatistics*> (pOption));
+
+ memcpy (pDecoderStatistics, &m_pDecContext->sDecoderStatistics, sizeof (SDecoderStatistics));
+
+ if (m_pDecContext->sDecoderStatistics.uiDecodedFrameCount != 0) { //not original status
+ pDecoderStatistics->fAverageFrameSpeedInMs = (float) (m_pDecContext->dDecTime) /
+ (m_pDecContext->sDecoderStatistics.uiDecodedFrameCount);
+ pDecoderStatistics->fActualAverageFrameSpeedInMs = (float) (m_pDecContext->dDecTime) /
+ (m_pDecContext->sDecoderStatistics.uiDecodedFrameCount + m_pDecContext->sDecoderStatistics.uiFreezingIDRNum +
+ m_pDecContext->sDecoderStatistics.uiFreezingNonIDRNum);
+ }
+ return cmResultSuccess;
+ } else if (eOptID == DECODER_OPTION_STATISTICS_LOG_INTERVAL) {
+ if (pOption) {
+ iVal = m_pDecContext->sDecoderStatistics.iStatisticsLogInterval;
+ * ((unsigned int*)pOption) = iVal;
+ return cmResultSuccess;
+ }
+ } else if (DECODER_OPTION_GET_SAR_INFO == eOptID) { //get decoder SAR info in VUI
+ PVuiSarInfo pVuiSarInfo = (static_cast<PVuiSarInfo> (pOption));
+ memset (pVuiSarInfo, 0, sizeof (SVuiSarInfo));
+ if (!m_pDecContext->pSps) {
+ return cmInitExpected;
+ } else {
+ pVuiSarInfo->uiSarWidth = m_pDecContext->pSps->sVui.uiSarWidth;
+ pVuiSarInfo->uiSarHeight = m_pDecContext->pSps->sVui.uiSarHeight;
+ pVuiSarInfo->bOverscanAppropriateFlag = m_pDecContext->pSps->sVui.bOverscanAppropriateFlag;
+ return cmResultSuccess;
+ }
+ } else if (DECODER_OPTION_PROFILE == eOptID) {
+ if (!m_pDecContext->pSps) {
+ return cmInitExpected;
+ }
+ iVal = (int)m_pDecContext->pSps->uiProfileIdc;
+ * ((int*)pOption) = iVal;
+ return cmResultSuccess;
+ } else if (DECODER_OPTION_LEVEL == eOptID) {
+ if (!m_pDecContext->pSps) {
+ return cmInitExpected;
+ }
+ iVal = (int)m_pDecContext->pSps->uiLevelIdc;
+ * ((int*)pOption) = iVal;
+ return cmResultSuccess;
+ } else if (DECODER_OPTION_NUM_OF_FRAMES_REMAINING_IN_BUFFER == eOptID) {
+ if (m_pDecContext->pSps && m_pDecContext->pSps->uiProfileIdc != 66 && m_pDecContext->pPps->bEntropyCodingModeFlag) {
+ * ((int*)pOption) = m_iNumOfPicts > 0 ? m_iNumOfPicts : 0;
+ }
+ return cmResultSuccess;
+ }
+
+ return cmInitParaError;
+}
+
+DECODING_STATE CWelsDecoder::DecodeFrameNoDelay (const unsigned char* kpSrc,
+ const int kiSrcLen,
+ unsigned char** ppDst,
+ SBufferInfo* pDstInfo) {
+ int iRet;
+ //SBufferInfo sTmpBufferInfo;
+ //unsigned char* ppTmpDst[3] = {NULL, NULL, NULL};
+ iRet = (int)DecodeFrame2 (kpSrc, kiSrcLen, ppDst, pDstInfo);
+ //memcpy (&sTmpBufferInfo, pDstInfo, sizeof (SBufferInfo));
+ //ppTmpDst[0] = ppDst[0];
+ //ppTmpDst[1] = ppDst[1];
+ //ppTmpDst[2] = ppDst[2];
+ iRet |= DecodeFrame2 (NULL, 0, ppDst, pDstInfo);
+ //if ((pDstInfo->iBufferStatus == 0) && (sTmpBufferInfo.iBufferStatus == 1)) {
+ //memcpy (pDstInfo, &sTmpBufferInfo, sizeof (SBufferInfo));
+ //ppDst[0] = ppTmpDst[0];
+ //ppDst[1] = ppTmpDst[1];
+ //ppDst[2] = ppTmpDst[2];
+ //}
+ return (DECODING_STATE)iRet;
+}
+
+DECODING_STATE CWelsDecoder::DecodeFrame2 (const unsigned char* kpSrc,
+ const int kiSrcLen,
+ unsigned char** ppDst,
+ SBufferInfo* pDstInfo) {
+ if (m_pDecContext == NULL || m_pDecContext->pParam == NULL) {
+ if (m_pWelsTrace != NULL) {
+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "Call DecodeFrame2 without Initialize.\n");
+ }
+ return dsInitialOptExpected;
+ }
+
+ if (m_pDecContext->pParam->bParseOnly) {
+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "bParseOnly should be false for this API calling! \n");
+ m_pDecContext->iErrorCode |= dsInvalidArgument;
+ return dsInvalidArgument;
+ }
+ if (CheckBsBuffer (m_pDecContext, kiSrcLen)) {
+ if (ResetDecoder())
+ return dsOutOfMemory;
+
+ return dsErrorFree;
+ }
+ if (kiSrcLen > 0 && kpSrc != NULL) {
+#ifdef OUTPUT_BIT_STREAM
+ if (m_pFBS) {
+ WelsFwrite (kpSrc, sizeof (unsigned char), kiSrcLen, m_pFBS);
+ WelsFflush (m_pFBS);
+ }
+ if (m_pFBSSize) {
+ WelsFwrite (&kiSrcLen, sizeof (int), 1, m_pFBSSize);
+ WelsFflush (m_pFBSSize);
+ }
+#endif//OUTPUT_BIT_STREAM
+ m_pDecContext->bEndOfStreamFlag = false;
+ } else {
+ //For application MODE, the error detection should be added for safe.
+ //But for CONSOLE MODE, when decoding LAST AU, kiSrcLen==0 && kpSrc==NULL.
+ m_pDecContext->bEndOfStreamFlag = true;
+ m_pDecContext->bInstantDecFlag = true;
+ }
+
+ int64_t iStart, iEnd;
+ iStart = WelsTime();
+
+ ppDst[0] = ppDst[1] = ppDst[2] = NULL;
+ m_pDecContext->iErrorCode = dsErrorFree; //initialize at the starting of AU decoding.
+ m_pDecContext->iFeedbackVclNalInAu = FEEDBACK_UNKNOWN_NAL; //initialize
+ unsigned long long uiInBsTimeStamp = pDstInfo->uiInBsTimeStamp;
+ memset (pDstInfo, 0, sizeof (SBufferInfo));
+ pDstInfo->uiInBsTimeStamp = uiInBsTimeStamp;
+#ifdef LONG_TERM_REF
+ m_pDecContext->bReferenceLostAtT0Flag = false; //initialize for LTR
+ m_pDecContext->bCurAuContainLtrMarkSeFlag = false;
+ m_pDecContext->iFrameNumOfAuMarkedLtr = 0;
+ m_pDecContext->iFrameNum = -1; //initialize
+#endif
+
+ m_pDecContext->iFeedbackTidInAu = -1; //initialize
+ m_pDecContext->iFeedbackNalRefIdc = -1; //initialize
+ if (pDstInfo) {
+ pDstInfo->uiOutYuvTimeStamp = 0;
+ m_pDecContext->uiTimeStamp = pDstInfo->uiInBsTimeStamp;
+ } else {
+ m_pDecContext->uiTimeStamp = 0;
+ }
+ WelsDecodeBs (m_pDecContext, kpSrc, kiSrcLen, ppDst,
+ pDstInfo, NULL); //iErrorCode has been modified in this function
+ m_pDecContext->bInstantDecFlag = false; //reset no-delay flag
+ if (m_pDecContext->iErrorCode) {
+ EWelsNalUnitType eNalType =
+ NAL_UNIT_UNSPEC_0; //for NBR, IDR frames are expected to decode as followed if error decoding an IDR currently
+
+ eNalType = m_pDecContext->sCurNalHead.eNalUnitType;
+
+ if (m_pDecContext->iErrorCode & dsOutOfMemory) {
+ if (ResetDecoder())
+ return dsOutOfMemory;
+
+ return dsErrorFree;
+ }
+ //for AVC bitstream (excluding AVC with temporal scalability, including TP), as long as error occur, SHOULD notify upper layer key frame loss.
+ if ((IS_PARAM_SETS_NALS (eNalType) || NAL_UNIT_CODED_SLICE_IDR == eNalType) ||
+ (VIDEO_BITSTREAM_AVC == m_pDecContext->eVideoType)) {
+ if (m_pDecContext->pParam->eEcActiveIdc == ERROR_CON_DISABLE) {
+#ifdef LONG_TERM_REF
+ m_pDecContext->bParamSetsLostFlag = true;
+#else
+ m_pDecContext->bReferenceLostAtT0Flag = true;
+#endif
+ }
+ }
+
+ if (m_pDecContext->bPrintFrameErrorTraceFlag) {
+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "decode failed, failure type:%d \n",
+ m_pDecContext->iErrorCode);
+ m_pDecContext->bPrintFrameErrorTraceFlag = false;
+ } else {
+ m_pDecContext->iIgnoredErrorInfoPacketCount++;
+ if (m_pDecContext->iIgnoredErrorInfoPacketCount == INT_MAX) {
+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING, "continuous error reached INT_MAX! Restart as 0.");
+ m_pDecContext->iIgnoredErrorInfoPacketCount = 0;
+ }
+ }
+ if ((m_pDecContext->pParam->eEcActiveIdc != ERROR_CON_DISABLE) && (pDstInfo->iBufferStatus == 1)) {
+ //TODO after dec status updated
+ m_pDecContext->iErrorCode |= dsDataErrorConcealed;
+
+ m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++;
+ if (m_pDecContext->sDecoderStatistics.uiDecodedFrameCount == 0) { //exceed max value of uint32_t
+ ResetDecStatNums (&m_pDecContext->sDecoderStatistics);
+ m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++;
+ }
+ int32_t iMbConcealedNum = m_pDecContext->iMbEcedNum + m_pDecContext->iMbEcedPropNum;
+ m_pDecContext->sDecoderStatistics.uiAvgEcRatio = m_pDecContext->iMbNum == 0 ?
+ (m_pDecContext->sDecoderStatistics.uiAvgEcRatio * m_pDecContext->sDecoderStatistics.uiEcFrameNum) : ((
+ m_pDecContext->sDecoderStatistics.uiAvgEcRatio * m_pDecContext->sDecoderStatistics.uiEcFrameNum) + ((
+ iMbConcealedNum * 100) / m_pDecContext->iMbNum));
+ m_pDecContext->sDecoderStatistics.uiAvgEcPropRatio = m_pDecContext->iMbNum == 0 ?
+ (m_pDecContext->sDecoderStatistics.uiAvgEcPropRatio * m_pDecContext->sDecoderStatistics.uiEcFrameNum) : ((
+ m_pDecContext->sDecoderStatistics.uiAvgEcPropRatio * m_pDecContext->sDecoderStatistics.uiEcFrameNum) + ((
+ m_pDecContext->iMbEcedPropNum * 100) / m_pDecContext->iMbNum));
+ m_pDecContext->sDecoderStatistics.uiEcFrameNum += (iMbConcealedNum == 0 ? 0 : 1);
+ m_pDecContext->sDecoderStatistics.uiAvgEcRatio = m_pDecContext->sDecoderStatistics.uiEcFrameNum == 0 ? 0 :
+ m_pDecContext->sDecoderStatistics.uiAvgEcRatio / m_pDecContext->sDecoderStatistics.uiEcFrameNum;
+ m_pDecContext->sDecoderStatistics.uiAvgEcPropRatio = m_pDecContext->sDecoderStatistics.uiEcFrameNum == 0 ? 0 :
+ m_pDecContext->sDecoderStatistics.uiAvgEcPropRatio / m_pDecContext->sDecoderStatistics.uiEcFrameNum;
+ }
+ iEnd = WelsTime();
+ m_pDecContext->dDecTime += (iEnd - iStart) / 1e3;
+
+ OutputStatisticsLog (m_pDecContext->sDecoderStatistics);
+
+#ifdef _PICTURE_REORDERING_
+ ReorderPicturesInDisplay (ppDst, pDstInfo);
+#endif
+
+ return (DECODING_STATE)m_pDecContext->iErrorCode;
+ }
+ // else Error free, the current codec works well
+
+ if (pDstInfo->iBufferStatus == 1) {
+
+ m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++;
+ if (m_pDecContext->sDecoderStatistics.uiDecodedFrameCount == 0) { //exceed max value of uint32_t
+ ResetDecStatNums (&m_pDecContext->sDecoderStatistics);
+ m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++;
+ }
+
+ OutputStatisticsLog (m_pDecContext->sDecoderStatistics);
+ }
+ iEnd = WelsTime();
+ m_pDecContext->dDecTime += (iEnd - iStart) / 1e3;
+
+#ifdef _PICTURE_REORDERING_
+ ReorderPicturesInDisplay (ppDst, pDstInfo);
+#endif
+ return dsErrorFree;
+}
+
+DECODING_STATE CWelsDecoder::FlushFrame (unsigned char** ppDst,
+ SBufferInfo* pDstInfo) {
+ if (m_pDecContext->bEndOfStreamFlag && m_iNumOfPicts > 0) {
+ m_iMinPOC = sIMinInt32;
+ for (int32_t i = 0; i <= m_iLargestBufferedPicIndex; ++i) {
+ if (m_iMinPOC == sIMinInt32 && m_sPictInfoList[i].iPOC > sIMinInt32) {
+ m_iMinPOC = m_sPictInfoList[i].iPOC;
+ m_iPictInfoIndex = i;
+ }
+ if (m_sPictInfoList[i].iPOC > sIMinInt32 && m_sPictInfoList[i].iPOC < m_iMinPOC) {
+ m_iMinPOC = m_sPictInfoList[i].iPOC;
+ m_iPictInfoIndex = i;
+ }
+ }
+ }
+ if (m_iMinPOC > sIMinInt32) {
+ m_LastWrittenPOC = m_iMinPOC;
+#if defined (_DEBUG)
+#ifdef _MOTION_VECTOR_DUMP_
+ fprintf (stderr, "Output POC: #%d\n", m_LastWrittenPOC);
+#endif
+#endif
+ memcpy (pDstInfo, &m_sPictInfoList[m_iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo));
+ ppDst[0] = m_sPictInfoList[m_iPictInfoIndex].pData[0];
+ ppDst[1] = m_sPictInfoList[m_iPictInfoIndex].pData[1];
+ ppDst[2] = m_sPictInfoList[m_iPictInfoIndex].pData[2];
+ m_sPictInfoList[m_iPictInfoIndex].iPOC = sIMinInt32;
+ m_sPictInfoList[m_iPictInfoIndex].bLastGOP = false;
+ m_iMinPOC = sIMinInt32;
+ --m_iNumOfPicts;
+ }
+ return dsErrorFree;
+}
+
+void CWelsDecoder::OutputStatisticsLog (SDecoderStatistics& sDecoderStatistics) {
+ if ((sDecoderStatistics.uiDecodedFrameCount > 0) && (sDecoderStatistics.iStatisticsLogInterval > 0)
+ && ((sDecoderStatistics.uiDecodedFrameCount % sDecoderStatistics.iStatisticsLogInterval) == 0)) {
+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
+ "DecoderStatistics: uiWidth=%d, uiHeight=%d, fAverageFrameSpeedInMs=%.1f, fActualAverageFrameSpeedInMs=%.1f, \
+ uiDecodedFrameCount=%d, uiResolutionChangeTimes=%d, uiIDRCorrectNum=%d, \
+ uiAvgEcRatio=%d, uiAvgEcPropRatio=%d, uiEcIDRNum=%d, uiEcFrameNum=%d, \
+ uiIDRLostNum=%d, uiFreezingIDRNum=%d, uiFreezingNonIDRNum=%d, iAvgLumaQp=%d, \
+ iSpsReportErrorNum=%d, iSubSpsReportErrorNum=%d, iPpsReportErrorNum=%d, iSpsNoExistNalNum=%d, iSubSpsNoExistNalNum=%d, iPpsNoExistNalNum=%d, \
+ uiProfile=%d, uiLevel=%d, \
+ iCurrentActiveSpsId=%d, iCurrentActivePpsId=%d,",
+ sDecoderStatistics.uiWidth,
+ sDecoderStatistics.uiHeight,
+ sDecoderStatistics.fAverageFrameSpeedInMs,
+ sDecoderStatistics.fActualAverageFrameSpeedInMs,
+
+ sDecoderStatistics.uiDecodedFrameCount,
+ sDecoderStatistics.uiResolutionChangeTimes,
+ sDecoderStatistics.uiIDRCorrectNum,
+
+ sDecoderStatistics.uiAvgEcRatio,
+ sDecoderStatistics.uiAvgEcPropRatio,
+ sDecoderStatistics.uiEcIDRNum,
+ sDecoderStatistics.uiEcFrameNum,
+
+ sDecoderStatistics.uiIDRLostNum,
+ sDecoderStatistics.uiFreezingIDRNum,
+ sDecoderStatistics.uiFreezingNonIDRNum,
+ sDecoderStatistics.iAvgLumaQp,
+
+ sDecoderStatistics.iSpsReportErrorNum,
+ sDecoderStatistics.iSubSpsReportErrorNum,
+ sDecoderStatistics.iPpsReportErrorNum,
+ sDecoderStatistics.iSpsNoExistNalNum,
+ sDecoderStatistics.iSubSpsNoExistNalNum,
+ sDecoderStatistics.iPpsNoExistNalNum,
+
+ sDecoderStatistics.uiProfile,
+ sDecoderStatistics.uiLevel,
+
+ sDecoderStatistics.iCurrentActiveSpsId,
+ sDecoderStatistics.iCurrentActivePpsId);
+ }
+}
+
+DECODING_STATE CWelsDecoder::ReorderPicturesInDisplay (unsigned char** ppDst, SBufferInfo* pDstInfo) {
+ if (pDstInfo->iBufferStatus == 1 && m_pDecContext->pSps->uiProfileIdc != 66
+ && m_pDecContext->pPps->bEntropyCodingModeFlag) {
+ if (m_pDecContext->pSliceHeader->iPicOrderCntLsb == 0) {
+ if (m_iNumOfPicts > 0) {
+ m_iLastGOPRemainPicts = m_iNumOfPicts;
+ for (int32_t i = 0; i <= m_iLargestBufferedPicIndex; ++i) {
+ if (m_sPictInfoList[i].iPOC > sIMinInt32) {
+ m_sPictInfoList[i].bLastGOP = true;
+ }
+ }
+ }
+ }
+ for (int32_t i = 0; i < 16; ++i) {
+ if (m_sPictInfoList[i].iPOC == sIMinInt32) {
+ memcpy (&m_sPictInfoList[i].sBufferInfo, pDstInfo, sizeof (SBufferInfo));
+ m_sPictInfoList[i].pData[0] = ppDst[0];
+ m_sPictInfoList[i].pData[1] = ppDst[1];
+ m_sPictInfoList[i].pData[2] = ppDst[2];
+ m_sPictInfoList[i].iPOC = m_pDecContext->pSliceHeader->iPicOrderCntLsb;
+ m_sPictInfoList[i].iFrameNum = m_pDecContext->pSliceHeader->iFrameNum;
+ m_sPictInfoList[i].bLastGOP = false;
+ pDstInfo->iBufferStatus = 0;
+ ++m_iNumOfPicts;
+ if (i > m_iLargestBufferedPicIndex) {
+ m_iLargestBufferedPicIndex = i;
+ }
+ break;
+ }
+ }
+ if (m_iLastGOPRemainPicts > 0) {
+ m_iMinPOC = sIMinInt32;
+ for (int32_t i = 0; i <= m_iLargestBufferedPicIndex; ++i) {
+ if (m_iMinPOC == sIMinInt32 && m_sPictInfoList[i].iPOC > sIMinInt32 && m_sPictInfoList[i].bLastGOP) {
+ m_iMinPOC = m_sPictInfoList[i].iPOC;
+ m_iPictInfoIndex = i;
+ }
+ if (m_sPictInfoList[i].iPOC > sIMinInt32 && m_sPictInfoList[i].iPOC < m_iMinPOC && m_sPictInfoList[i].bLastGOP) {
+ m_iMinPOC = m_sPictInfoList[i].iPOC;
+ m_iPictInfoIndex = i;
+ }
+ }
+ m_LastWrittenPOC = m_iMinPOC;
+#if defined (_DEBUG)
+#ifdef _MOTION_VECTOR_DUMP_
+ fprintf (stderr, "Output POC: #%d\n", m_LastWrittenPOC);
+#endif
+#endif
+ memcpy (pDstInfo, &m_sPictInfoList[m_iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo));
+ ppDst[0] = m_sPictInfoList[m_iPictInfoIndex].pData[0];
+ ppDst[1] = m_sPictInfoList[m_iPictInfoIndex].pData[1];
+ ppDst[2] = m_sPictInfoList[m_iPictInfoIndex].pData[2];
+ m_sPictInfoList[m_iPictInfoIndex].iPOC = sIMinInt32;
+ m_sPictInfoList[m_iPictInfoIndex].bLastGOP = false;
+ m_iMinPOC = sIMinInt32;
+ --m_iNumOfPicts;
+ --m_iLastGOPRemainPicts;
+ if (m_iLastGOPRemainPicts == 0) {
+ m_LastWrittenPOC = sIMinInt32;
+ }
+ return dsErrorFree;
+ }
+ if (m_iNumOfPicts > 0) {
+ m_iMinPOC = sIMinInt32;
+ for (int32_t i = 0; i <= m_iLargestBufferedPicIndex; ++i) {
+ if (m_iMinPOC == sIMinInt32 && m_sPictInfoList[i].iPOC > sIMinInt32) {
+ m_iMinPOC = m_sPictInfoList[i].iPOC;
+ m_iPictInfoIndex = i;
+ }
+ if (m_sPictInfoList[i].iPOC > sIMinInt32 && m_sPictInfoList[i].iPOC < m_iMinPOC) {
+ m_iMinPOC = m_sPictInfoList[i].iPOC;
+ m_iPictInfoIndex = i;
+ }
+ }
+ }
+ if (m_iMinPOC > sIMinInt32) {
+ if ((m_LastWrittenPOC > sIMinInt32 && m_iMinPOC - m_LastWrittenPOC <= 1)
+ || m_iMinPOC < m_pDecContext->pSliceHeader->iPicOrderCntLsb) {
+ m_LastWrittenPOC = m_iMinPOC;
+#if defined (_DEBUG)
+#ifdef _MOTION_VECTOR_DUMP_
+ fprintf (stderr, "Output POC: #%d\n", m_LastWrittenPOC);
+#endif
+#endif
+ memcpy (pDstInfo, &m_sPictInfoList[m_iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo));
+ ppDst[0] = m_sPictInfoList[m_iPictInfoIndex].pData[0];
+ ppDst[1] = m_sPictInfoList[m_iPictInfoIndex].pData[1];
+ ppDst[2] = m_sPictInfoList[m_iPictInfoIndex].pData[2];
+ m_sPictInfoList[m_iPictInfoIndex].iPOC = sIMinInt32;
+ m_sPictInfoList[m_iPictInfoIndex].bLastGOP = false;
+ m_iMinPOC = sIMinInt32;
+ --m_iNumOfPicts;
+ return dsErrorFree;
+ }
+ }
+ }
+
+ return dsErrorFree;
+}
+
+DECODING_STATE CWelsDecoder::DecodeParser (const unsigned char* kpSrc,
+ const int kiSrcLen,
+ SParserBsInfo* pDstInfo) {
+ if (m_pDecContext == NULL || m_pDecContext->pParam == NULL) {
+ if (m_pWelsTrace != NULL) {
+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "Call DecodeParser without Initialize.\n");
+ }
+ return dsInitialOptExpected;
+ }
+
+ if (!m_pDecContext->pParam->bParseOnly) {
+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "bParseOnly should be true for this API calling! \n");
+ m_pDecContext->iErrorCode |= dsInvalidArgument;
+ return dsInvalidArgument;
+ }
+ int64_t iEnd, iStart = WelsTime();
+ if (CheckBsBuffer (m_pDecContext, kiSrcLen)) {
+ if (ResetDecoder())
+ return dsOutOfMemory;
+
+ return dsErrorFree;
+ }
+ if (kiSrcLen > 0 && kpSrc != NULL) {
+#ifdef OUTPUT_BITSTREAM
+ if (m_pFBS) {
+ WelsFwrite (kpSrc, sizeof (unsigned char), kiSrcLen, m_pFBS);
+ WelsFflush (m_pFBS);
+ }
+#endif//OUTPUT_BIT_STREAM
+ m_pDecContext->bEndOfStreamFlag = false;
+ } else {
+ //For application MODE, the error detection should be added for safe.
+ //But for CONSOLE MODE, when decoding LAST AU, kiSrcLen==0 && kpSrc==NULL.
+ m_pDecContext->bEndOfStreamFlag = true;
+ m_pDecContext->bInstantDecFlag = true;
+ }
+
+ m_pDecContext->iErrorCode = dsErrorFree; //initialize at the starting of AU decoding.
+ m_pDecContext->pParam->eEcActiveIdc = ERROR_CON_DISABLE; //add protection to disable EC here.
+ m_pDecContext->iFeedbackNalRefIdc = -1; //initialize
+ if (!m_pDecContext->bFramePending) { //frame complete
+ m_pDecContext->pParserBsInfo->iNalNum = 0;
+ memset (m_pDecContext->pParserBsInfo->pNalLenInByte, 0, MAX_NAL_UNITS_IN_LAYER);
+ }
+ pDstInfo->iNalNum = 0;
+ pDstInfo->iSpsWidthInPixel = pDstInfo->iSpsHeightInPixel = 0;
+ if (pDstInfo) {
+ m_pDecContext->uiTimeStamp = pDstInfo->uiInBsTimeStamp;
+ pDstInfo->uiOutBsTimeStamp = 0;
+ } else {
+ m_pDecContext->uiTimeStamp = 0;
+ }
+ WelsDecodeBs (m_pDecContext, kpSrc, kiSrcLen, NULL, NULL, pDstInfo);
+ if (m_pDecContext->iErrorCode & dsOutOfMemory) {
+ if (ResetDecoder())
+ return dsOutOfMemory;
+ return dsErrorFree;
+ }
+
+ if (!m_pDecContext->bFramePending && m_pDecContext->pParserBsInfo->iNalNum) {
+ memcpy (pDstInfo, m_pDecContext->pParserBsInfo, sizeof (SParserBsInfo));
+
+ if (m_pDecContext->iErrorCode == ERR_NONE) { //update statistics: decoding frame count
+ m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++;
+ if (m_pDecContext->sDecoderStatistics.uiDecodedFrameCount == 0) { //exceed max value of uint32_t
+ ResetDecStatNums (&m_pDecContext->sDecoderStatistics);
+ m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++;
+ }
+ }
+ }
+
+ m_pDecContext->bInstantDecFlag = false; //reset no-delay flag
+
+ if (m_pDecContext->iErrorCode && m_pDecContext->bPrintFrameErrorTraceFlag) {
+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "decode failed, failure type:%d \n", m_pDecContext->iErrorCode);
+ m_pDecContext->bPrintFrameErrorTraceFlag = false;
+ }
+ iEnd = WelsTime();
+ m_pDecContext->dDecTime += (iEnd - iStart) / 1e3;
+
+ return (DECODING_STATE) m_pDecContext->iErrorCode;
+}
+
+DECODING_STATE CWelsDecoder::DecodeFrame (const unsigned char* kpSrc,
+ const int kiSrcLen,
+ unsigned char** ppDst,
+ int* pStride,
+ int& iWidth,
+ int& iHeight) {
+ DECODING_STATE eDecState = dsErrorFree;
+ SBufferInfo DstInfo;
+
+ memset (&DstInfo, 0, sizeof (SBufferInfo));
+ DstInfo.UsrData.sSystemBuffer.iStride[0] = pStride[0];
+ DstInfo.UsrData.sSystemBuffer.iStride[1] = pStride[1];
+ DstInfo.UsrData.sSystemBuffer.iWidth = iWidth;
+ DstInfo.UsrData.sSystemBuffer.iHeight = iHeight;
+
+ eDecState = DecodeFrame2 (kpSrc, kiSrcLen, ppDst, &DstInfo);
+ if (eDecState == dsErrorFree) {
+ pStride[0] = DstInfo.UsrData.sSystemBuffer.iStride[0];
+ pStride[1] = DstInfo.UsrData.sSystemBuffer.iStride[1];
+ iWidth = DstInfo.UsrData.sSystemBuffer.iWidth;
+ iHeight = DstInfo.UsrData.sSystemBuffer.iHeight;
+ }
+
+ return eDecState;
+}
+
+DECODING_STATE CWelsDecoder::DecodeFrameEx (const unsigned char* kpSrc,
+ const int kiSrcLen,
+ unsigned char* pDst,
+ int iDstStride,
+ int& iDstLen,
+ int& iWidth,
+ int& iHeight,
+ int& iColorFormat) {
+ DECODING_STATE state = dsErrorFree;
+
+ return state;
+}
+
+
+} // namespace WelsDec
+
+
+using namespace WelsDec;
+/*
+* WelsGetDecoderCapability
+* @return: DecCapability information
+*/
+int WelsGetDecoderCapability (SDecoderCapability* pDecCapability) {
+ memset (pDecCapability, 0, sizeof (SDecoderCapability));
+ pDecCapability->iProfileIdc = 66; //Baseline
+ pDecCapability->iProfileIop = 0xE0; //11100000b
+ pDecCapability->iLevelIdc = 32; //level_idc = 3.2
+ pDecCapability->iMaxMbps = 216000; //from level_idc = 3.2
+ pDecCapability->iMaxFs = 5120; //from level_idc = 3.2
+ pDecCapability->iMaxCpb = 20000; //from level_idc = 3.2
+ pDecCapability->iMaxDpb = 20480; //from level_idc = 3.2
+ pDecCapability->iMaxBr = 20000; //from level_idc = 3.2
+ pDecCapability->bRedPicCap = 0; //not support redundant pic
+
+ return ERR_NONE;
+}
+/* WINAPI is indeed in prefix due to sync to application layer callings!! */
+
+/*
+* WelsCreateDecoder
+* @return: success in return 0, otherwise failed.
+*/
+long WelsCreateDecoder (ISVCDecoder** ppDecoder) {
+
+ if (NULL == ppDecoder) {
+ return ERR_INVALID_PARAMETERS;
+ }
+
+ *ppDecoder = new CWelsDecoder();
+
+ if (NULL == *ppDecoder) {
+ return ERR_MALLOC_FAILED;
+ }
+
+ return ERR_NONE;
+}
+
+/*
+* WelsDestroyDecoder
+*/
+void WelsDestroyDecoder (ISVCDecoder* pDecoder) {
+ if (NULL != pDecoder) {
+ delete (CWelsDecoder*)pDecoder;
+ }
+}
--- a/test/BaseDecoderTest.h
+++ b/test/BaseDecoderTest.h
@@ -1,53 +1,53 @@
-#ifndef __BASEDECODERTEST_H__
-#define __BASEDECODERTEST_H__
-
-#include "test_stdint.h"
-#include <limits.h>
-#include <fstream>
-#include "codec_api.h"
-
-#include "utils/BufferedData.h"
-
-class BaseDecoderTest {
- public:
- struct Plane {
- const uint8_t* data;
- int width;
- int height;
- int stride;
- };
-
- struct Frame {
- Plane y;
- Plane u;
- Plane v;
- };
-
- struct Callback {
- virtual void onDecodeFrame (const Frame& frame) = 0;
- };
-
- BaseDecoderTest();
- int32_t SetUp();
- void TearDown();
- void DecodeFile (const char* fileName, Callback* cbk);
-
- bool Open (const char* fileName);
- bool DecodeNextFrame (Callback* cbk);
- ISVCDecoder* decoder_;
-
- private:
- void DecodeFrame (const uint8_t* src, size_t sliceSize, Callback* cbk);
- void FlushFrame (Callback* cbk);
-
- std::ifstream file_;
- BufferedData buf_;
- enum {
- OpenFile,
- Decoding,
- EndOfStream,
- End
- } decodeStatus_;
-};
-
-#endif //__BASEDECODERTEST_H__
+#ifndef __BASEDECODERTEST_H__
+#define __BASEDECODERTEST_H__
+
+#include "test_stdint.h"
+#include <limits.h>
+#include <fstream>
+#include "codec_api.h"
+
+#include "utils/BufferedData.h"
+
+class BaseDecoderTest {
+ public:
+ struct Plane {
+ const uint8_t* data;
+ int width;
+ int height;
+ int stride;
+ };
+
+ struct Frame {
+ Plane y;
+ Plane u;
+ Plane v;
+ };
+
+ struct Callback {
+ virtual void onDecodeFrame (const Frame& frame) = 0;
+ };
+
+ BaseDecoderTest();
+ int32_t SetUp();
+ void TearDown();
+ void DecodeFile (const char* fileName, Callback* cbk);
+
+ bool Open (const char* fileName);
+ bool DecodeNextFrame (Callback* cbk);
+ ISVCDecoder* decoder_;
+
+ private:
+ void DecodeFrame (const uint8_t* src, size_t sliceSize, Callback* cbk);
+ void FlushFrame (Callback* cbk);
+
+ std::ifstream file_;
+ BufferedData buf_;
+ enum {
+ OpenFile,
+ Decoding,
+ EndOfStream,
+ End
+ } decodeStatus_;
+};
+
+#endif //__BASEDECODERTEST_H__
--- a/test/api/BaseDecoderTest.cpp
+++ b/test/api/BaseDecoderTest.cpp
@@ -1,219 +1,219 @@
-#include <fstream>
-#include <gtest/gtest.h>
-#include "codec_def.h"
-#include "codec_app_def.h"
-#include "utils/BufferedData.h"
-#include "BaseDecoderTest.h"
-
-static void ReadFrame (std::ifstream* file, BufferedData* buf) {
- // start code of a frame is {0, 0, 0, 1}
- int zeroCount = 0;
- char b;
-
- buf->Clear();
- for (;;) {
- file->read (&b, 1);
- if (file->gcount() != 1) { // end of file
- return;
- }
- if (!buf->PushBack (b)) {
- FAIL() << "unable to allocate memory";
- }
-
- if (buf->Length() <= 4) {
- continue;
- }
-
- if (zeroCount < 3) {
- zeroCount = b != 0 ? 0 : zeroCount + 1;
- } else {
- if (b == 1) {
- if (file->seekg (-4, file->cur).good()) {
- buf->SetLength (buf->Length() - 4);
- return;
- } else {
- FAIL() << "unable to seek file";
- }
- } else if (b == 0) {
- zeroCount = 3;
- } else {
- zeroCount = 0;
- }
- }
- }
-}
-
-BaseDecoderTest::BaseDecoderTest()
- : decoder_ (NULL), decodeStatus_ (OpenFile) {}
-
-int32_t BaseDecoderTest::SetUp() {
- long rv = WelsCreateDecoder (&decoder_);
- EXPECT_EQ (0, rv);
- EXPECT_TRUE (decoder_ != NULL);
- if (decoder_ == NULL) {
- return rv;
- }
-
- SDecodingParam decParam;
- memset (&decParam, 0, sizeof (SDecodingParam));
- decParam.uiTargetDqLayer = UCHAR_MAX;
- decParam.eEcActiveIdc = ERROR_CON_SLICE_COPY;
- decParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT;
-
- rv = decoder_->Initialize (&decParam);
- EXPECT_EQ (0, rv);
- return (int32_t)rv;
-}
-
-void BaseDecoderTest::TearDown() {
- if (decoder_ != NULL) {
- decoder_->Uninitialize();
- WelsDestroyDecoder (decoder_);
- }
-}
-
-
-void BaseDecoderTest::DecodeFrame (const uint8_t* src, size_t sliceSize, Callback* cbk) {
- uint8_t* data[3];
- SBufferInfo bufInfo;
- memset (data, 0, sizeof (data));
- memset (&bufInfo, 0, sizeof (SBufferInfo));
-
- DECODING_STATE rv = decoder_->DecodeFrame2 (src, (int) sliceSize, data, &bufInfo);
- ASSERT_TRUE (rv == dsErrorFree);
-
- if (bufInfo.iBufferStatus == 1 && cbk != NULL) {
- const Frame frame = {
- {
- // y plane
- data[0],
- bufInfo.UsrData.sSystemBuffer.iWidth,
- bufInfo.UsrData.sSystemBuffer.iHeight,
- bufInfo.UsrData.sSystemBuffer.iStride[0]
- },
- {
- // u plane
- data[1],
- bufInfo.UsrData.sSystemBuffer.iWidth / 2,
- bufInfo.UsrData.sSystemBuffer.iHeight / 2,
- bufInfo.UsrData.sSystemBuffer.iStride[1]
- },
- {
- // v plane
- data[2],
- bufInfo.UsrData.sSystemBuffer.iWidth / 2,
- bufInfo.UsrData.sSystemBuffer.iHeight / 2,
- bufInfo.UsrData.sSystemBuffer.iStride[1]
- },
- };
- cbk->onDecodeFrame (frame);
- }
-}
-void BaseDecoderTest::FlushFrame (Callback* cbk) {
- uint8_t* data[3];
- SBufferInfo bufInfo;
- memset (data, 0, sizeof (data));
- memset (&bufInfo, 0, sizeof (SBufferInfo));
-
- DECODING_STATE rv = decoder_->FlushFrame (data, &bufInfo);
- ASSERT_TRUE (rv == dsErrorFree);
-
- if (bufInfo.iBufferStatus == 1 && cbk != NULL) {
- const Frame frame = {
- {
- // y plane
- data[0],
- bufInfo.UsrData.sSystemBuffer.iWidth,
- bufInfo.UsrData.sSystemBuffer.iHeight,
- bufInfo.UsrData.sSystemBuffer.iStride[0]
- },
- {
- // u plane
- data[1],
- bufInfo.UsrData.sSystemBuffer.iWidth / 2,
- bufInfo.UsrData.sSystemBuffer.iHeight / 2,
- bufInfo.UsrData.sSystemBuffer.iStride[1]
- },
- {
- // v plane
- data[2],
- bufInfo.UsrData.sSystemBuffer.iWidth / 2,
- bufInfo.UsrData.sSystemBuffer.iHeight / 2,
- bufInfo.UsrData.sSystemBuffer.iStride[1]
- },
- };
- cbk->onDecodeFrame (frame);
- }
-}
-void BaseDecoderTest::DecodeFile (const char* fileName, Callback* cbk) {
- std::ifstream file (fileName, std::ios::in | std::ios::binary);
- ASSERT_TRUE (file.is_open());
-
- BufferedData buf;
- while (true) {
- ReadFrame (&file, &buf);
- if (::testing::Test::HasFatalFailure()) {
- return;
- }
- if (buf.Length() == 0) {
- break;
- }
- DecodeFrame (buf.data(), buf.Length(), cbk);
- if (::testing::Test::HasFatalFailure()) {
- return;
- }
- }
-
- int32_t iEndOfStreamFlag = 1;
- decoder_->SetOption (DECODER_OPTION_END_OF_STREAM, &iEndOfStreamFlag);
-
- // Get pending last frame
- DecodeFrame (NULL, 0, cbk);
- // Flush out last frames in decoder buffer
- int32_t num_of_frames_in_buffer = 0;
- decoder_->GetOption (DECODER_OPTION_NUM_OF_FRAMES_REMAINING_IN_BUFFER, &num_of_frames_in_buffer);
- for (int32_t i = 0; i < num_of_frames_in_buffer; ++i) {
- FlushFrame (cbk);
- }
-}
-
-bool BaseDecoderTest::Open (const char* fileName) {
- if (decodeStatus_ == OpenFile) {
- file_.open (fileName, std::ios_base::out | std::ios_base::binary);
- if (file_.is_open()) {
- decodeStatus_ = Decoding;
- return true;
- }
- }
- return false;
-}
-
-bool BaseDecoderTest::DecodeNextFrame (Callback* cbk) {
- switch (decodeStatus_) {
- case Decoding:
- ReadFrame (&file_, &buf_);
- if (::testing::Test::HasFatalFailure()) {
- return false;
- }
- if (buf_.Length() == 0) {
- decodeStatus_ = EndOfStream;
- return true;
- }
- DecodeFrame (buf_.data(), buf_.Length(), cbk);
- if (::testing::Test::HasFatalFailure()) {
- return false;
- }
- return true;
- case EndOfStream: {
- int32_t iEndOfStreamFlag = 1;
- decoder_->SetOption (DECODER_OPTION_END_OF_STREAM, &iEndOfStreamFlag);
- DecodeFrame (NULL, 0, cbk);
- decodeStatus_ = End;
- break;
- }
- case OpenFile:
- case End:
- break;
- }
- return false;
-}
+#include <fstream>
+#include <gtest/gtest.h>
+#include "codec_def.h"
+#include "codec_app_def.h"
+#include "utils/BufferedData.h"
+#include "BaseDecoderTest.h"
+
+static void ReadFrame (std::ifstream* file, BufferedData* buf) {
+ // start code of a frame is {0, 0, 0, 1}
+ int zeroCount = 0;
+ char b;
+
+ buf->Clear();
+ for (;;) {
+ file->read (&b, 1);
+ if (file->gcount() != 1) { // end of file
+ return;
+ }
+ if (!buf->PushBack (b)) {
+ FAIL() << "unable to allocate memory";
+ }
+
+ if (buf->Length() <= 4) {
+ continue;
+ }
+
+ if (zeroCount < 3) {
+ zeroCount = b != 0 ? 0 : zeroCount + 1;
+ } else {
+ if (b == 1) {
+ if (file->seekg (-4, file->cur).good()) {
+ buf->SetLength (buf->Length() - 4);
+ return;
+ } else {
+ FAIL() << "unable to seek file";
+ }
+ } else if (b == 0) {
+ zeroCount = 3;
+ } else {
+ zeroCount = 0;
+ }
+ }
+ }
+}
+
+BaseDecoderTest::BaseDecoderTest()
+ : decoder_ (NULL), decodeStatus_ (OpenFile) {}
+
+int32_t BaseDecoderTest::SetUp() {
+ long rv = WelsCreateDecoder (&decoder_);
+ EXPECT_EQ (0, rv);
+ EXPECT_TRUE (decoder_ != NULL);
+ if (decoder_ == NULL) {
+ return rv;
+ }
+
+ SDecodingParam decParam;
+ memset (&decParam, 0, sizeof (SDecodingParam));
+ decParam.uiTargetDqLayer = UCHAR_MAX;
+ decParam.eEcActiveIdc = ERROR_CON_SLICE_COPY;
+ decParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT;
+
+ rv = decoder_->Initialize (&decParam);
+ EXPECT_EQ (0, rv);
+ return (int32_t)rv;
+}
+
+void BaseDecoderTest::TearDown() {
+ if (decoder_ != NULL) {
+ decoder_->Uninitialize();
+ WelsDestroyDecoder (decoder_);
+ }
+}
+
+
+void BaseDecoderTest::DecodeFrame (const uint8_t* src, size_t sliceSize, Callback* cbk) {
+ uint8_t* data[3];
+ SBufferInfo bufInfo;
+ memset (data, 0, sizeof (data));
+ memset (&bufInfo, 0, sizeof (SBufferInfo));
+
+ DECODING_STATE rv = decoder_->DecodeFrame2 (src, (int) sliceSize, data, &bufInfo);
+ ASSERT_TRUE (rv == dsErrorFree);
+
+ if (bufInfo.iBufferStatus == 1 && cbk != NULL) {
+ const Frame frame = {
+ {
+ // y plane
+ data[0],
+ bufInfo.UsrData.sSystemBuffer.iWidth,
+ bufInfo.UsrData.sSystemBuffer.iHeight,
+ bufInfo.UsrData.sSystemBuffer.iStride[0]
+ },
+ {
+ // u plane
+ data[1],
+ bufInfo.UsrData.sSystemBuffer.iWidth / 2,
+ bufInfo.UsrData.sSystemBuffer.iHeight / 2,
+ bufInfo.UsrData.sSystemBuffer.iStride[1]
+ },
+ {
+ // v plane
+ data[2],
+ bufInfo.UsrData.sSystemBuffer.iWidth / 2,
+ bufInfo.UsrData.sSystemBuffer.iHeight / 2,
+ bufInfo.UsrData.sSystemBuffer.iStride[1]
+ },
+ };
+ cbk->onDecodeFrame (frame);
+ }
+}
+void BaseDecoderTest::FlushFrame (Callback* cbk) {
+ uint8_t* data[3];
+ SBufferInfo bufInfo;
+ memset (data, 0, sizeof (data));
+ memset (&bufInfo, 0, sizeof (SBufferInfo));
+
+ DECODING_STATE rv = decoder_->FlushFrame (data, &bufInfo);
+ ASSERT_TRUE (rv == dsErrorFree);
+
+ if (bufInfo.iBufferStatus == 1 && cbk != NULL) {
+ const Frame frame = {
+ {
+ // y plane
+ data[0],
+ bufInfo.UsrData.sSystemBuffer.iWidth,
+ bufInfo.UsrData.sSystemBuffer.iHeight,
+ bufInfo.UsrData.sSystemBuffer.iStride[0]
+ },
+ {
+ // u plane
+ data[1],
+ bufInfo.UsrData.sSystemBuffer.iWidth / 2,
+ bufInfo.UsrData.sSystemBuffer.iHeight / 2,
+ bufInfo.UsrData.sSystemBuffer.iStride[1]
+ },
+ {
+ // v plane
+ data[2],
+ bufInfo.UsrData.sSystemBuffer.iWidth / 2,
+ bufInfo.UsrData.sSystemBuffer.iHeight / 2,
+ bufInfo.UsrData.sSystemBuffer.iStride[1]
+ },
+ };
+ cbk->onDecodeFrame (frame);
+ }
+}
+void BaseDecoderTest::DecodeFile (const char* fileName, Callback* cbk) {
+ std::ifstream file (fileName, std::ios::in | std::ios::binary);
+ ASSERT_TRUE (file.is_open());
+
+ BufferedData buf;
+ while (true) {
+ ReadFrame (&file, &buf);
+ if (::testing::Test::HasFatalFailure()) {
+ return;
+ }
+ if (buf.Length() == 0) {
+ break;
+ }
+ DecodeFrame (buf.data(), buf.Length(), cbk);
+ if (::testing::Test::HasFatalFailure()) {
+ return;
+ }
+ }
+
+ int32_t iEndOfStreamFlag = 1;
+ decoder_->SetOption (DECODER_OPTION_END_OF_STREAM, &iEndOfStreamFlag);
+
+ // Get pending last frame
+ DecodeFrame (NULL, 0, cbk);
+ // Flush out last frames in decoder buffer
+ int32_t num_of_frames_in_buffer = 0;
+ decoder_->GetOption (DECODER_OPTION_NUM_OF_FRAMES_REMAINING_IN_BUFFER, &num_of_frames_in_buffer);
+ for (int32_t i = 0; i < num_of_frames_in_buffer; ++i) {
+ FlushFrame (cbk);
+ }
+}
+
+bool BaseDecoderTest::Open (const char* fileName) {
+ if (decodeStatus_ == OpenFile) {
+ file_.open (fileName, std::ios_base::out | std::ios_base::binary);
+ if (file_.is_open()) {
+ decodeStatus_ = Decoding;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool BaseDecoderTest::DecodeNextFrame (Callback* cbk) {
+ switch (decodeStatus_) {
+ case Decoding:
+ ReadFrame (&file_, &buf_);
+ if (::testing::Test::HasFatalFailure()) {
+ return false;
+ }
+ if (buf_.Length() == 0) {
+ decodeStatus_ = EndOfStream;
+ return true;
+ }
+ DecodeFrame (buf_.data(), buf_.Length(), cbk);
+ if (::testing::Test::HasFatalFailure()) {
+ return false;
+ }
+ return true;
+ case EndOfStream: {
+ int32_t iEndOfStreamFlag = 1;
+ decoder_->SetOption (DECODER_OPTION_END_OF_STREAM, &iEndOfStreamFlag);
+ DecodeFrame (NULL, 0, cbk);
+ decodeStatus_ = End;
+ break;
+ }
+ case OpenFile:
+ case End:
+ break;
+ }
+ return false;
+}
--- a/test/api/cpp_interface_test.cpp
+++ b/test/api/cpp_interface_test.cpp
@@ -1,138 +1,138 @@
-#include <gtest/gtest.h>
-#include "codec_api.h"
-#include <stddef.h>
-
-static void CheckFunctionOrder (int expect, int actual, const char* name) {
- EXPECT_EQ (expect, actual) << "Wrong function order: " << name;
-}
-
-typedef void (*CheckFunc) (int, int, const char*);
-extern "C" void CheckEncoderInterface (ISVCEncoder* p, CheckFunc);
-extern "C" void CheckDecoderInterface (ISVCDecoder* p, CheckFunc);
-extern "C" size_t GetBoolSize (void);
-extern "C" size_t GetBoolOffset (void);
-extern "C" size_t GetBoolStructSize (void);
-
-// Store the 'this' pointer to verify 'this' is received as expected from C code.
-static void* gThis;
-
-/**
- * Return a unique number for each virtual function so that we are able to
- * check if the order of functions in the virtual table is as expected.
- */
-struct SVCEncoderImpl : public ISVCEncoder {
- virtual ~SVCEncoderImpl() {}
- virtual int EXTAPI Initialize (const SEncParamBase* pParam) {
- EXPECT_TRUE (gThis == this);
- return 1;
- }
- virtual int EXTAPI InitializeExt (const SEncParamExt* pParam) {
- EXPECT_TRUE (gThis == this);
- return 2;
- }
- virtual int EXTAPI GetDefaultParams (SEncParamExt* pParam) {
- EXPECT_TRUE (gThis == this);
- return 3;
- }
- virtual int EXTAPI Uninitialize() {
- EXPECT_TRUE (gThis == this);
- return 4;
- }
- virtual int EXTAPI EncodeFrame (const SSourcePicture* kpSrcPic,
- SFrameBSInfo* pBsInfo) {
- EXPECT_TRUE (gThis == this);
- return 5;
- }
- virtual int EXTAPI EncodeParameterSets (SFrameBSInfo* pBsInfo) {
- EXPECT_TRUE (gThis == this);
- return 6;
- }
- virtual int EXTAPI ForceIntraFrame (bool bIDR, int iLayerId = -1) {
- EXPECT_TRUE (gThis == this);
- return 7;
- }
- virtual int EXTAPI SetOption (ENCODER_OPTION eOptionId, void* pOption) {
- EXPECT_TRUE (gThis == this);
- return 8;
- }
- virtual int EXTAPI GetOption (ENCODER_OPTION eOptionId, void* pOption) {
- EXPECT_TRUE (gThis == this);
- return 9;
- }
-};
-
-struct SVCDecoderImpl : public ISVCDecoder {
- virtual ~SVCDecoderImpl() {}
- virtual long EXTAPI Initialize (const SDecodingParam* pParam) {
- EXPECT_TRUE (gThis == this);
- return 1;
- }
- virtual long EXTAPI Uninitialize() {
- EXPECT_TRUE (gThis == this);
- return 2;
- }
- virtual DECODING_STATE EXTAPI DecodeFrame (const unsigned char* pSrc,
- const int iSrcLen, unsigned char** ppDst, int* pStride,
- int& iWidth, int& iHeight) {
- EXPECT_TRUE (gThis == this);
- return static_cast<DECODING_STATE> (3);
- }
- virtual DECODING_STATE EXTAPI DecodeFrameNoDelay (const unsigned char* pSrc,
- const int iSrcLen, unsigned char** ppDst, SBufferInfo* pDstInfo) {
- EXPECT_TRUE (gThis == this);
- return static_cast<DECODING_STATE> (4);
- }
- virtual DECODING_STATE EXTAPI DecodeFrame2 (const unsigned char* pSrc,
- const int iSrcLen, unsigned char** ppDst, SBufferInfo* pDstInfo) {
- EXPECT_TRUE (gThis == this);
- return static_cast<DECODING_STATE> (5);
- }
- virtual DECODING_STATE EXTAPI FlushFrame (unsigned char** ppDst, SBufferInfo* pDstInfo) {
- EXPECT_TRUE (gThis == this);
- return static_cast<DECODING_STATE> (5);
- }
- virtual DECODING_STATE EXTAPI DecodeFrameEx (const unsigned char* pSrc,
- const int iSrcLen, unsigned char* pDst, int iDstStride,
- int& iDstLen, int& iWidth, int& iHeight, int& iColorFormat) {
- EXPECT_TRUE (gThis == this);
- return static_cast<DECODING_STATE> (6);
- }
- virtual DECODING_STATE EXTAPI DecodeParser (const unsigned char* pSrc,
- const int iSrcLen, SParserBsInfo* pDstInfo) {
- EXPECT_TRUE (gThis == this);
- return static_cast<DECODING_STATE> (7);
- }
- virtual long EXTAPI SetOption (DECODER_OPTION eOptionId, void* pOption) {
- EXPECT_TRUE (gThis == this);
- return static_cast<DECODING_STATE> (8);
- }
- virtual long EXTAPI GetOption (DECODER_OPTION eOptionId, void* pOption) {
- EXPECT_TRUE (gThis == this);
- return static_cast<DECODING_STATE> (9);
- }
-};
-
-TEST (ISVCEncoderTest, CheckFunctionOrder) {
- SVCEncoderImpl* p = new SVCEncoderImpl;
- gThis = p;
- CheckEncoderInterface (p, CheckFunctionOrder);
- delete p;
-}
-
-TEST (ISVCDecoderTest, CheckFunctionOrder) {
- SVCDecoderImpl* p = new SVCDecoderImpl;
- gThis = p;
- CheckDecoderInterface (p, CheckFunctionOrder);
- delete p;
-}
-
-struct bool_test_struct {
- char c;
- bool b;
-};
-
-TEST (ISVCDecoderEncoderTest, CheckCAbi) {
- EXPECT_EQ (sizeof (bool), GetBoolSize()) << "Wrong size of bool type";
- EXPECT_EQ (offsetof (bool_test_struct, b), GetBoolOffset()) << "Wrong alignment of bool in a struct";
- EXPECT_EQ (sizeof (bool_test_struct), GetBoolStructSize()) << "Wrong size of struct with a bool";
-}
+#include <gtest/gtest.h>
+#include "codec_api.h"
+#include <stddef.h>
+
+static void CheckFunctionOrder (int expect, int actual, const char* name) {
+ EXPECT_EQ (expect, actual) << "Wrong function order: " << name;
+}
+
+typedef void (*CheckFunc) (int, int, const char*);
+extern "C" void CheckEncoderInterface (ISVCEncoder* p, CheckFunc);
+extern "C" void CheckDecoderInterface (ISVCDecoder* p, CheckFunc);
+extern "C" size_t GetBoolSize (void);
+extern "C" size_t GetBoolOffset (void);
+extern "C" size_t GetBoolStructSize (void);
+
+// Store the 'this' pointer to verify 'this' is received as expected from C code.
+static void* gThis;
+
+/**
+ * Return a unique number for each virtual function so that we are able to
+ * check if the order of functions in the virtual table is as expected.
+ */
+struct SVCEncoderImpl : public ISVCEncoder {
+ virtual ~SVCEncoderImpl() {}
+ virtual int EXTAPI Initialize (const SEncParamBase* pParam) {
+ EXPECT_TRUE (gThis == this);
+ return 1;
+ }
+ virtual int EXTAPI InitializeExt (const SEncParamExt* pParam) {
+ EXPECT_TRUE (gThis == this);
+ return 2;
+ }
+ virtual int EXTAPI GetDefaultParams (SEncParamExt* pParam) {
+ EXPECT_TRUE (gThis == this);
+ return 3;
+ }
+ virtual int EXTAPI Uninitialize() {
+ EXPECT_TRUE (gThis == this);
+ return 4;
+ }
+ virtual int EXTAPI EncodeFrame (const SSourcePicture* kpSrcPic,
+ SFrameBSInfo* pBsInfo) {
+ EXPECT_TRUE (gThis == this);
+ return 5;
+ }
+ virtual int EXTAPI EncodeParameterSets (SFrameBSInfo* pBsInfo) {
+ EXPECT_TRUE (gThis == this);
+ return 6;
+ }
+ virtual int EXTAPI ForceIntraFrame (bool bIDR, int iLayerId = -1) {
+ EXPECT_TRUE (gThis == this);
+ return 7;
+ }
+ virtual int EXTAPI SetOption (ENCODER_OPTION eOptionId, void* pOption) {
+ EXPECT_TRUE (gThis == this);
+ return 8;
+ }
+ virtual int EXTAPI GetOption (ENCODER_OPTION eOptionId, void* pOption) {
+ EXPECT_TRUE (gThis == this);
+ return 9;
+ }
+};
+
+struct SVCDecoderImpl : public ISVCDecoder {
+ virtual ~SVCDecoderImpl() {}
+ virtual long EXTAPI Initialize (const SDecodingParam* pParam) {
+ EXPECT_TRUE (gThis == this);
+ return 1;
+ }
+ virtual long EXTAPI Uninitialize() {
+ EXPECT_TRUE (gThis == this);
+ return 2;
+ }
+ virtual DECODING_STATE EXTAPI DecodeFrame (const unsigned char* pSrc,
+ const int iSrcLen, unsigned char** ppDst, int* pStride,
+ int& iWidth, int& iHeight) {
+ EXPECT_TRUE (gThis == this);
+ return static_cast<DECODING_STATE> (3);
+ }
+ virtual DECODING_STATE EXTAPI DecodeFrameNoDelay (const unsigned char* pSrc,
+ const int iSrcLen, unsigned char** ppDst, SBufferInfo* pDstInfo) {
+ EXPECT_TRUE (gThis == this);
+ return static_cast<DECODING_STATE> (4);
+ }
+ virtual DECODING_STATE EXTAPI DecodeFrame2 (const unsigned char* pSrc,
+ const int iSrcLen, unsigned char** ppDst, SBufferInfo* pDstInfo) {
+ EXPECT_TRUE (gThis == this);
+ return static_cast<DECODING_STATE> (5);
+ }
+ virtual DECODING_STATE EXTAPI FlushFrame (unsigned char** ppDst, SBufferInfo* pDstInfo) {
+ EXPECT_TRUE (gThis == this);
+ return static_cast<DECODING_STATE> (5);
+ }
+ virtual DECODING_STATE EXTAPI DecodeFrameEx (const unsigned char* pSrc,
+ const int iSrcLen, unsigned char* pDst, int iDstStride,
+ int& iDstLen, int& iWidth, int& iHeight, int& iColorFormat) {
+ EXPECT_TRUE (gThis == this);
+ return static_cast<DECODING_STATE> (6);
+ }
+ virtual DECODING_STATE EXTAPI DecodeParser (const unsigned char* pSrc,
+ const int iSrcLen, SParserBsInfo* pDstInfo) {
+ EXPECT_TRUE (gThis == this);
+ return static_cast<DECODING_STATE> (7);
+ }
+ virtual long EXTAPI SetOption (DECODER_OPTION eOptionId, void* pOption) {
+ EXPECT_TRUE (gThis == this);
+ return static_cast<DECODING_STATE> (8);
+ }
+ virtual long EXTAPI GetOption (DECODER_OPTION eOptionId, void* pOption) {
+ EXPECT_TRUE (gThis == this);
+ return static_cast<DECODING_STATE> (9);
+ }
+};
+
+TEST (ISVCEncoderTest, CheckFunctionOrder) {
+ SVCEncoderImpl* p = new SVCEncoderImpl;
+ gThis = p;
+ CheckEncoderInterface (p, CheckFunctionOrder);
+ delete p;
+}
+
+TEST (ISVCDecoderTest, CheckFunctionOrder) {
+ SVCDecoderImpl* p = new SVCDecoderImpl;
+ gThis = p;
+ CheckDecoderInterface (p, CheckFunctionOrder);
+ delete p;
+}
+
+struct bool_test_struct {
+ char c;
+ bool b;
+};
+
+TEST (ISVCDecoderEncoderTest, CheckCAbi) {
+ EXPECT_EQ (sizeof (bool), GetBoolSize()) << "Wrong size of bool type";
+ EXPECT_EQ (offsetof (bool_test_struct, b), GetBoolOffset()) << "Wrong alignment of bool in a struct";
+ EXPECT_EQ (sizeof (bool_test_struct), GetBoolStructSize()) << "Wrong size of struct with a bool";
+}
--- a/test/api/decode_api_test.cpp
+++ b/test/api/decode_api_test.cpp
@@ -1,1276 +1,1276 @@
-#include <gtest/gtest.h>
-#include "codec_def.h"
-#include "utils/BufferedData.h"
-#include "utils/FileInputStream.h"
-#include "BaseDecoderTest.h"
-#include "BaseEncoderTest.h"
-#include "wels_common_defs.h"
-#include "utils/HashFunctions.h"
-#include <string>
-#include <vector>
-#include "encode_decode_api_test.h"
-using namespace WelsCommon;
-
-static void TestOutPutTrace (void* ctx, int level, const char* string) {
- STraceUnit* pTraceUnit = (STraceUnit*) ctx;
- EXPECT_LE (level, pTraceUnit->iTarLevel);
-}
-
-TEST_P (EncodeDecodeTestAPI, DecoderVclNal) {
- EncodeDecodeFileParamBase p = GetParam();
- prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
- encoder_->Uninitialize();
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
-
- int32_t iTraceLevel = WELS_LOG_QUIET;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
-
- ASSERT_TRUE (InitialEncDec (p.width, p.height));
-
- int iIdx = 0;
- while (iIdx <= p.numframes) {
-
- EncodeOneFrame (0);
-
- //decoding after each encoding frame
- int vclNal, len = 0;
- encToDecData (info, len);
- unsigned char* pData[3] = { NULL };
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- ASSERT_TRUE (rv == cmResultSuccess);
- rv = decoder_->GetOption (DECODER_OPTION_VCL_NAL, &vclNal);
- EXPECT_EQ (vclNal, FEEDBACK_UNKNOWN_NAL); //no reconstruction, unknown return
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- ASSERT_TRUE (rv == cmResultSuccess);
- rv = decoder_->GetOption (DECODER_OPTION_VCL_NAL, &vclNal);
- EXPECT_EQ (vclNal, FEEDBACK_VCL_NAL);
- iIdx++;
- } //while
- //ignore last frame
-}
-
-TEST_P (EncodeDecodeTestAPI, GetOptionFramenum) {
- EncodeDecodeFileParamBase p = GetParam();
- prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
- encoder_->Uninitialize();
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
-
- int32_t iTraceLevel = WELS_LOG_QUIET;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
-
- ASSERT_TRUE (InitialEncDec (p.width, p.height));
-
- int32_t iEncFrameNum = -1;
- int32_t iDecFrameNum;
- int iIdx = 0;
- while (iIdx <= p.numframes) {
- EncodeOneFrame (0);
- //decoding after each encoding frame
- int len = 0;
- encToDecData (info, len);
- unsigned char* pData[3] = { NULL };
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- ASSERT_TRUE (rv == cmResultSuccess);
- decoder_->GetOption (DECODER_OPTION_FRAME_NUM, &iDecFrameNum);
- EXPECT_EQ (iDecFrameNum, -1);
- iEncFrameNum++;
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- ASSERT_TRUE (rv == cmResultSuccess);
- decoder_->GetOption (DECODER_OPTION_FRAME_NUM, &iDecFrameNum);
- EXPECT_EQ (iEncFrameNum, iDecFrameNum);
- iIdx++;
- } //while
- //ignore last frame
-}
-
-TEST_P (EncodeDecodeTestAPI, GetOptionIDR) {
- EncodeDecodeFileParamBase p = GetParam();
- prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
- encoder_->Uninitialize();
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
-
- //init for encoder
- // I420: 1(Y) + 1/4(U) + 1/4(V)
- int32_t iTraceLevel = WELS_LOG_QUIET;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
-
- ASSERT_TRUE (InitialEncDec (p.width, p.height));
-
- int32_t iEncCurIdrPicId = 0;
- int32_t iDecCurIdrPicId;
- int32_t iIDRPeriod = 1;
- int32_t iSpsPpsIdAddition = 0;
- int iIdx = 0;
- while (iIdx <= p.numframes) {
- iSpsPpsIdAddition = rand() %
- 2; //the current strategy supports more than 2 modes, but the switch between the modes>2 is not allowed
- iIDRPeriod = (rand() % 150) + 1;
- encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
- encoder_->SetOption (ENCODER_OPTION_SPS_PPS_ID_STRATEGY, &iSpsPpsIdAddition);
-
- EncodeOneFrame (0);
-
- if (info.eFrameType == videoFrameTypeIDR) {
- iEncCurIdrPicId = iEncCurIdrPicId + 1;
- }
- //decoding after each encoding frame
- int len = 0;
- encToDecData (info, len);
- unsigned char* pData[3] = { NULL };
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- ASSERT_TRUE (rv == cmResultSuccess);
- decoder_->GetOption (DECODER_OPTION_IDR_PIC_ID, &iDecCurIdrPicId);
- EXPECT_EQ (iDecCurIdrPicId, iEncCurIdrPicId);
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- ASSERT_TRUE (rv == cmResultSuccess);
- decoder_->GetOption (DECODER_OPTION_IDR_PIC_ID, &iDecCurIdrPicId);
- EXPECT_EQ (iDecCurIdrPicId, iEncCurIdrPicId);
- iIdx++;
- } //while
- //ignore last frame
-}
-
-TEST_P (EncodeDecodeTestAPI, InOutTimeStamp) {
- EncodeDecodeFileParamBase p = GetParam();
- prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
- encoder_->Uninitialize();
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
-
- ASSERT_TRUE (InitialEncDec (p.width, p.height));
- int32_t iTraceLevel = WELS_LOG_QUIET;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- int32_t iSpsPpsIdAddition = 1;
- encoder_->SetOption (ENCODER_OPTION_SPS_PPS_ID_STRATEGY, &iSpsPpsIdAddition);
- int32_t iIDRPeriod = 60;
- encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
- SLTRConfig sLtrConfigVal;
- sLtrConfigVal.bEnableLongTermReference = 1;
- sLtrConfigVal.iLTRRefNum = 1;
- encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
- int32_t iLtrPeriod = 2;
- encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
- int iIdx = 0;
- int iSkipedBytes;
- unsigned long long uiEncTimeStamp = 100;
- while (iIdx <= p.numframes) {
- EncodeOneFrame (1);
- //decoding after each encoding frame
- int len = 0;
- encToDecData (info, len);
- unsigned char* pData[3] = { NULL };
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- uint32_t uiEcIdc = ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE;
- decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
- dstBufInfo_.uiInBsTimeStamp = uiEncTimeStamp;
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- dstBufInfo_.uiInBsTimeStamp = uiEncTimeStamp;
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- if (dstBufInfo_.iBufferStatus == 1) {
- EXPECT_EQ (uiEncTimeStamp, dstBufInfo_.uiOutYuvTimeStamp);
- }
- iIdx++;
- uiEncTimeStamp++;
- }
- (void) iSkipedBytes;
-}
-
-TEST_P (EncodeDecodeTestAPI, GetOptionIsRefPic) {
- EncodeDecodeFileParamBase p = GetParam();
- prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
- encoder_->Uninitialize();
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
-
- ASSERT_TRUE (InitialEncDec (p.width, p.height));
- int32_t iTraceLevel = WELS_LOG_QUIET;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- int iIdx = 0;
- int iSkipedBytes;
- int iIsRefPic;
- decoder_->GetOption (DECODER_OPTION_IS_REF_PIC, &iIsRefPic);
- ASSERT_EQ (iIsRefPic, -1);
-
- while (iIdx <= p.numframes) {
- EncodeOneFrame (1);
- //decoding after each encoding frame
- int len = 0;
- encToDecData (info, len);
- unsigned char* pData[3] = { NULL };
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- decoder_->GetOption (DECODER_OPTION_IS_REF_PIC, &iIsRefPic);
- ASSERT_EQ (iIsRefPic, -1);
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- if (dstBufInfo_.iBufferStatus == 1) {
- decoder_->GetOption (DECODER_OPTION_IS_REF_PIC, &iIsRefPic);
- ASSERT_TRUE (iIsRefPic >= 0);
- }
- iIdx++;
- }
- (void)iSkipedBytes;
-}
-
-TEST_P (EncodeDecodeTestAPI, GetOptionTid_AVC_NOPREFIX) {
- SLTRMarkingFeedback m_LTR_Marking_Feedback;
- SLTRRecoverRequest m_LTR_Recover_Request;
- m_LTR_Recover_Request.uiIDRPicId = 0;
- m_LTR_Recover_Request.iLayerId = 0;
- m_LTR_Marking_Feedback.iLayerId = 0;
- EncodeDecodeFileParamBase p = GetParam();
- prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
- param_.bPrefixNalAddingCtrl = false;
- param_.iTemporalLayerNum = (rand() % 4) + 1;
- encoder_->Uninitialize();
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
- m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
- ASSERT_TRUE (InitialEncDec (p.width, p.height));
- int32_t iTraceLevel = WELS_LOG_QUIET;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- int32_t iSpsPpsIdAddition = 1;
- encoder_->SetOption (ENCODER_OPTION_SPS_PPS_ID_STRATEGY, &iSpsPpsIdAddition);
- int32_t iIDRPeriod = 60;
- encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
- SLTRConfig sLtrConfigVal;
- sLtrConfigVal.bEnableLongTermReference = 1;
- sLtrConfigVal.iLTRRefNum = 1;
- encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
- int32_t iLtrPeriod = 2;
- encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
- int iIdx = 0;
- int iLossIdx = 0;
- bool bVCLLoss = false;
- while (iIdx <= p.numframes) {
- EncodeOneFrame (1);
- if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) {
- ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
- }
- //decoding after each encoding frame
- int len = 0;
- encToDecData (info, len);
- unsigned char* pData[3] = { NULL };
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- SimulateNALLoss (info.sLayerInfo[0].pBsBuf, len, &m_SLostSim, p.pLossSequence, p.bLostPara, iLossIdx, bVCLLoss);
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- int iTid = -1;
- decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid);
- if (iTid != -1) {
- ASSERT_EQ (iTid, 0);
- }
- m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
- LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid);
- std::vector<SLostSim>::iterator iter = m_SLostSim.begin();
- bool bHasVCL = false;
- for (unsigned int k = 0; k < m_SLostSim.size(); k++) {
- if (IS_VCL_NAL (iter->eNalType, 0) && iter->isLost == false) {
- bHasVCL = true;
- break;
- }
- iter++;
- }
- (void) bHasVCL;
- if (iTid != -1) {
- ASSERT_EQ (iTid, 0);
- }
- LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
- LTRMarkFeedback (decoder_, encoder_, &m_LTR_Marking_Feedback, rv);
- iIdx++;
- }
-}
-
-TEST_P (EncodeDecodeTestAPI, GetOptionTid_AVC_WITH_PREFIX_NOLOSS) {
- SLTRMarkingFeedback m_LTR_Marking_Feedback;
- SLTRRecoverRequest m_LTR_Recover_Request;
- m_LTR_Recover_Request.uiIDRPicId = 0;
- m_LTR_Recover_Request.iLayerId = 0;
- m_LTR_Marking_Feedback.iLayerId = 0;
- EncodeDecodeFileParamBase p = GetParam();
- prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
- param_.bPrefixNalAddingCtrl = true;
- param_.iTemporalLayerNum = (rand() % 4) + 1;
- param_.iSpatialLayerNum = 1;
- encoder_->Uninitialize();
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
- m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
-
- ASSERT_TRUE (InitialEncDec (p.width, p.height));
- int32_t iTraceLevel = WELS_LOG_QUIET;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- int32_t iSpsPpsIdAddition = 1;
- encoder_->SetOption (ENCODER_OPTION_SPS_PPS_ID_STRATEGY, &iSpsPpsIdAddition);
- int32_t iIDRPeriod = 60;
- encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
- SLTRConfig sLtrConfigVal;
- sLtrConfigVal.bEnableLongTermReference = 1;
- sLtrConfigVal.iLTRRefNum = 1;
- encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
- int32_t iLtrPeriod = 2;
- encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
- int iIdx = 0;
- while (iIdx <= p.numframes) {
- EncodeOneFrame (1);
- if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) {
- ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
- }
- //decoding after each encoding frame
- int len = 0;
- encToDecData (info, len);
- unsigned char* pData[3] = { NULL };
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- ExtractDidNal (&info, len, &m_SLostSim, 0);
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- int iTid = -1;
- decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid);
- ASSERT_EQ (iTid, -1);
- m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
- LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid);
- ASSERT_EQ (iTid, info.sLayerInfo[0].uiTemporalId);
- LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
- LTRMarkFeedback (decoder_, encoder_, &m_LTR_Marking_Feedback, rv);
- iIdx++;
- }
-}
-
-TEST_P (EncodeDecodeTestAPI, GetOptionTid_SVC_L1_NOLOSS) {
- SLTRMarkingFeedback m_LTR_Marking_Feedback;
- SLTRRecoverRequest m_LTR_Recover_Request;
- m_LTR_Recover_Request.uiIDRPicId = 0;
- m_LTR_Recover_Request.iLayerId = 0;
- m_LTR_Marking_Feedback.iLayerId = 0;
- EncodeDecodeFileParamBase p = GetParam();
- prepareParamDefault (2, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
- param_.iTemporalLayerNum = (rand() % 4) + 1;
- param_.iSpatialLayerNum = 2;
- encoder_->Uninitialize();
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
- m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
-
- ASSERT_TRUE (InitialEncDec (p.width, p.height));
- int32_t iTraceLevel = WELS_LOG_QUIET;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- int32_t iSpsPpsIdAddition = 1;
- encoder_->SetOption (ENCODER_OPTION_SPS_PPS_ID_STRATEGY, &iSpsPpsIdAddition);
- int32_t iIDRPeriod = 60;
- encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
- SLTRConfig sLtrConfigVal;
- sLtrConfigVal.bEnableLongTermReference = 1;
- sLtrConfigVal.iLTRRefNum = 1;
- encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
- int32_t iLtrPeriod = 2;
- encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
- int iIdx = 0;
- while (iIdx <= p.numframes) {
- EncodeOneFrame (1);
- if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) {
- ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
- }
- //decoding after each encoding frame
- int len = 0;
- encToDecData (info, len);
- unsigned char* pData[3] = { NULL };
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- ExtractDidNal (&info, len, &m_SLostSim, 1);
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- int iTid = -1;
- decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid);
- ASSERT_EQ (iTid, -1);
- m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
- LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid);
- ASSERT_EQ (iTid, info.sLayerInfo[0].uiTemporalId);
- LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
- LTRMarkFeedback (decoder_, encoder_, &m_LTR_Marking_Feedback, rv);
- iIdx++;
- }
-}
-
-
-
-TEST_P (EncodeDecodeTestAPI, SetOption_Trace) {
- SLTRMarkingFeedback m_LTR_Marking_Feedback;
- SLTRRecoverRequest m_LTR_Recover_Request;
- m_LTR_Recover_Request.uiIDRPicId = 0;
- m_LTR_Recover_Request.iLayerId = 0;
- m_LTR_Marking_Feedback.iLayerId = 0;
- EncodeDecodeFileParamBase p = GetParam();
- prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
- param_.iSpatialLayerNum = 1;
-
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
- m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
-
- ASSERT_TRUE (InitialEncDec (p.width, p.height));
- int32_t iTraceLevel = WELS_LOG_QUIET;
- pFunc = TestOutPutTrace;
- pTraceInfo = &sTrace;
- sTrace.iTarLevel = iTraceLevel;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- encoder_->SetOption (ENCODER_OPTION_TRACE_CALLBACK, &pFunc);
- encoder_->SetOption (ENCODER_OPTION_TRACE_CALLBACK_CONTEXT, &pTraceInfo);
- decoder_->SetOption (DECODER_OPTION_TRACE_CALLBACK, &pFunc);
- decoder_->SetOption (DECODER_OPTION_TRACE_CALLBACK_CONTEXT, &pTraceInfo);
-
-
- int32_t iSpsPpsIdAddition = 1;
- encoder_->SetOption (ENCODER_OPTION_SPS_PPS_ID_STRATEGY, &iSpsPpsIdAddition);
- int32_t iIDRPeriod = 60;
- encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
- SLTRConfig sLtrConfigVal;
- sLtrConfigVal.bEnableLongTermReference = 1;
- sLtrConfigVal.iLTRRefNum = 1;
- encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
- int32_t iLtrPeriod = 2;
- encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
- int iIdx = 0;
- int iLossIdx = 0;
- bool bVCLLoss = false;
- while (iIdx <= p.numframes) {
- iTraceLevel = rand() % 33;
- sTrace.iTarLevel = iTraceLevel;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- EncodeOneFrame (1);
- if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) {
- ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
- }
- //decoding after each encoding frame
- int len = 0;
- encToDecData (info, len);
- unsigned char* pData[3] = { NULL };
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- ExtractDidNal (&info, len, &m_SLostSim, 0);
- SimulateNALLoss (info.sLayerInfo[0].pBsBuf, len, &m_SLostSim, p.pLossSequence, p.bLostPara, iLossIdx, bVCLLoss);
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
- LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
- LTRMarkFeedback (decoder_, encoder_, &m_LTR_Marking_Feedback, rv);
- iIdx++;
- }
-}
-
-TEST_P (EncodeDecodeTestAPI, SetOption_Trace_NULL) {
- SLTRMarkingFeedback m_LTR_Marking_Feedback;
- SLTRRecoverRequest m_LTR_Recover_Request;
- m_LTR_Recover_Request.uiIDRPicId = 0;
- m_LTR_Recover_Request.iLayerId = 0;
- m_LTR_Marking_Feedback.iLayerId = 0;
- EncodeDecodeFileParamBase p = GetParam();
- prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
- param_.iSpatialLayerNum = 1;
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
- m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
-
- ASSERT_TRUE (InitialEncDec (p.width, p.height));
-
- int32_t iTraceLevel = WELS_LOG_QUIET;
- pFunc = NULL;
- pTraceInfo = NULL;
- encoder_->SetOption (ENCODER_OPTION_TRACE_CALLBACK, &pFunc);
- encoder_->SetOption (ENCODER_OPTION_TRACE_CALLBACK_CONTEXT, &pTraceInfo);
- decoder_->SetOption (DECODER_OPTION_TRACE_CALLBACK, &pFunc);
- decoder_->SetOption (DECODER_OPTION_TRACE_CALLBACK_CONTEXT, &pTraceInfo);
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
-
- int32_t iSpsPpsIdAddition = 1;
- encoder_->SetOption (ENCODER_OPTION_SPS_PPS_ID_STRATEGY, &iSpsPpsIdAddition);
- int32_t iIDRPeriod = 60;
- encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
- SLTRConfig sLtrConfigVal;
- sLtrConfigVal.bEnableLongTermReference = 1;
- sLtrConfigVal.iLTRRefNum = 1;
- encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
- int32_t iLtrPeriod = 2;
- encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
- int iIdx = 0;
- int iLossIdx = 0;
- bool bVCLLoss = false;
- while (iIdx <= p.numframes) {
- iTraceLevel = rand() % 33;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- EncodeOneFrame (1);
- if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) {
- ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
- }
- //decoding after each encoding frame
- int len = 0;
- encToDecData (info, len);
- unsigned char* pData[3] = { NULL };
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
- ExtractDidNal (&info, len, &m_SLostSim, 0);
- SimulateNALLoss (info.sLayerInfo[0].pBsBuf, len, &m_SLostSim, p.pLossSequence, p.bLostPara, iLossIdx, bVCLLoss);
- rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
- m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
- LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
- LTRMarkFeedback (decoder_, encoder_, &m_LTR_Marking_Feedback, rv);
- iIdx++;
- }
-}
-
-
-
-
-class DecodeCrashTestAPI : public ::testing::TestWithParam<EncodeDecodeFileParamBase>, public EncodeDecodeTestBase {
- public:
- void SetUp() {
- EncodeDecodeTestBase::SetUp();
- ucBuf_ = NULL;
- ucBuf_ = new unsigned char [1000000];
- ASSERT_TRUE (ucBuf_ != NULL);
- }
-
- void TearDown() {
- EncodeDecodeTestBase::TearDown();
- if (NULL != ucBuf_) {
- delete[] ucBuf_;
- ucBuf_ = NULL;
- }
- ASSERT_TRUE (ucBuf_ == NULL);
- }
-
- void prepareParam (int iLayerNum, int iSliceNum, int width, int height, float framerate, SEncParamExt* pParam) {
- memset (pParam, 0, sizeof (SEncParamExt));
- EncodeDecodeTestBase::prepareParam (iLayerNum, iSliceNum, width, height, framerate, pParam);
- }
-
- void EncodeOneFrame() {
- int frameSize = EncPic.iPicWidth * EncPic.iPicHeight * 3 / 2;
- memset (buf_.data(), iRandValue, (frameSize >> 2));
- memset (buf_.data() + (frameSize >> 2), rand() % 256, (frameSize - (frameSize >> 2)));
- int rv = encoder_->EncodeFrame (&EncPic, &info);
- ASSERT_TRUE (rv == cmResultSuccess || rv == cmUnknownReason);
- }
- protected:
- unsigned char* ucBuf_;
-};
-
-struct EncodeDecodeParamBase {
- int width;
- int height;
- float frameRate;
- int iTarBitrate;
-};
-
-#define NUM_OF_POSSIBLE_RESOLUTION (9)
-static const EncodeDecodeParamBase kParamArray[] = {
- {160, 90, 6.0f, 250000},
- {90, 160, 6.0f, 250000},
- {320, 180, 12.0f, 500000},
- {180, 320, 12.0f, 500000},
- {480, 270, 12.0f, 600000},
- {270, 480, 12.0f, 600000},
- {640, 360, 24.0f, 800000},
- {360, 640, 24.0f, 800000},
- {1280, 720, 24.0f, 1000000},
-};
-
-//#define DEBUG_FILE_SAVE_CRA
-TEST_F (DecodeCrashTestAPI, DecoderCrashTest) {
- uint32_t uiGet;
- encoder_->Uninitialize();
-
- //do tests until crash
- unsigned int uiLoopRound = 0;
- unsigned char* pucBuf = ucBuf_;
- int iDecAuSize;
-#ifdef DEBUG_FILE_SAVE_CRA
- //open file to save tested BS
- FILE* fDataFile = fopen ("test_crash.264", "wb");
- FILE* fLenFile = fopen ("test_crash_len.log", "w");
- int iFileSize = 0;
-#endif
-
- //set eCurStrategy for one test
- EParameterSetStrategy eCurStrategy = CONSTANT_ID;
- switch (rand() % 7) {
- case 1:
- eCurStrategy = INCREASING_ID;
- break;
- case 2:
- eCurStrategy = SPS_LISTING;
- break;
- case 3:
- eCurStrategy = SPS_LISTING_AND_PPS_INCREASING;
- break;
- case 6:
- eCurStrategy = SPS_PPS_LISTING;
- break;
- default:
- //using the initial value
- break;
- }
-
- do {
- int iTotalFrameNum = (rand() % 100) + 1;
- int iSeed = rand() % NUM_OF_POSSIBLE_RESOLUTION;
- EncodeDecodeParamBase p = kParamArray[iSeed];
-#ifdef DEBUG_FILE_SAVE_CRA
- printf ("using param set %d in loop %d\n", iSeed, uiLoopRound);
-#endif
- //Initialize Encoder
- prepareParam (1, 1, p.width, p.height, p.frameRate, ¶m_);
- param_.iRCMode = RC_TIMESTAMP_MODE;
- param_.iTargetBitrate = p.iTarBitrate;
- param_.uiIntraPeriod = 0;
- param_.eSpsPpsIdStrategy = eCurStrategy;
- param_.bEnableBackgroundDetection = true;
- param_.bEnableSceneChangeDetect = (rand() % 3) ? true : false;
- param_.bPrefixNalAddingCtrl = (rand() % 2) ? true : false;
- param_.iEntropyCodingModeFlag = 0;
- param_.bEnableFrameSkip = true;
- param_.iMultipleThreadIdc = 0;
- param_.sSpatialLayers[0].iSpatialBitrate = p.iTarBitrate;
- param_.sSpatialLayers[0].iMaxSpatialBitrate = p.iTarBitrate << 1;
- param_.sSpatialLayers[0].sSliceArgument.uiSliceMode = (rand() % 2) ? SM_SIZELIMITED_SLICE : SM_SINGLE_SLICE;
- if (param_.sSpatialLayers[0].sSliceArgument.uiSliceMode == SM_SIZELIMITED_SLICE) {
- param_.sSpatialLayers[0].sSliceArgument.uiSliceSizeConstraint = 1400;
- param_.uiMaxNalSize = 1400;
- } else {
- param_.sSpatialLayers[0].sSliceArgument.uiSliceSizeConstraint = 0;
- param_.uiMaxNalSize = 0;
- }
-
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_SLICE_COPY); //default value should be ERROR_CON_SLICE_COPY
- int32_t iTraceLevel = WELS_LOG_QUIET;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
-
- //Start for enc/dec
- int iIdx = 0;
- unsigned char* pData[3] = { NULL };
-
- EncodeDecodeFileParamBase pInput; //to conform with old functions
- pInput.width = p.width;
- pInput.height = p.height;
- pInput.frameRate = p.frameRate;
- ASSERT_TRUE (prepareEncDecParam (pInput));
- while (iIdx++ < iTotalFrameNum) { // loop in frame
- EncodeOneFrame();
-#ifdef DEBUG_FILE_SAVE_CRA
- //reset file if file size large
- if ((info.eFrameType == videoFrameTypeIDR) && (iFileSize >= (1 << 25))) {
- fclose (fDataFile);
- fDataFile = fopen ("test_crash.264", "wb");
- iFileSize = 0;
- decoder_->Uninitialize();
-
- SDecodingParam decParam;
- memset (&decParam, 0, sizeof (SDecodingParam));
- decParam.uiTargetDqLayer = UCHAR_MAX;
- decParam.eEcActiveIdc = ERROR_CON_SLICE_COPY;
- decParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT;
-
- rv = decoder_->Initialize (&decParam);
- ASSERT_EQ (0, rv);
- }
-#endif
- if (info.eFrameType == videoFrameTypeSkip)
- continue;
- //deal with packets
- unsigned char* pBsBuf;
- iDecAuSize = 0;
- pucBuf = ucBuf_; //init buf start pos for decoder usage
- for (int iLayerNum = 0; iLayerNum < info.iLayerNum; iLayerNum++) {
- SLayerBSInfo* pLayerBsInfo = &info.sLayerInfo[iLayerNum];
- pBsBuf = info.sLayerInfo[iLayerNum].pBsBuf;
- int iTotalNalCnt = pLayerBsInfo->iNalCount;
- for (int iNalCnt = 0; iNalCnt < iTotalNalCnt; iNalCnt++) { //loop in NAL
- int iPacketSize = pLayerBsInfo->pNalLengthInByte[iNalCnt];
- //packet loss
- int iLossRateRange = (uiLoopRound % 100) + 1; //1-100
- int iLossRate = (rand() % iLossRateRange);
- bool bPacketLost = (rand() % 101) > (100 -
- iLossRate); // [0, (100-iLossRate)] indicates NO LOSS, (100-iLossRate, 100] indicates LOSS
- if (!bPacketLost) { //no loss
- memcpy (pucBuf, pBsBuf, iPacketSize);
- pucBuf += iPacketSize;
- iDecAuSize += iPacketSize;
- }
-#ifdef DEBUG_FILE_SAVE_CRA
- else {
- printf ("lost packet size=%d at frame-type=%d at loss rate %d (%d)\n", iPacketSize, info.eFrameType, iLossRate,
- iLossRateRange);
- }
-#endif
- //update bs info
- pBsBuf += iPacketSize;
- } //nal
- } //layer
-
-#ifdef DEBUG_FILE_SAVE_CRA
- //save to file
- fwrite (ucBuf_, 1, iDecAuSize, fDataFile);
- fflush (fDataFile);
- iFileSize += iDecAuSize;
-
- //save to len file
- unsigned long ulTmp[4];
- ulTmp[0] = ulTmp[1] = ulTmp[2] = iIdx;
- ulTmp[3] = iDecAuSize;
- fwrite (ulTmp, sizeof (unsigned long), 4, fLenFile); // index, timeStamp, data size
- fflush (fLenFile);
-#endif
-
- //decode
- pData[0] = pData[1] = pData[2] = 0;
- memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
-
- rv = decoder_->DecodeFrame2 (ucBuf_, iDecAuSize, pData, &dstBufInfo_);
- rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
- //guarantee decoder EC status
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_SLICE_COPY);
- } //frame
- uiLoopRound ++;
- if (uiLoopRound >= (1 << 30))
- uiLoopRound = 0;
-#ifdef DEBUG_FILE_SAVE_CRA
- if (uiLoopRound % 100 == 0)
- printf ("run %d times.\n", uiLoopRound);
- } while (1); //while (iLoopRound<100);
- fclose (fDataFile);
- fclose (fLenFile);
-#else
- }
- while (uiLoopRound < 10);
-#endif
-
-}
-
-const uint32_t kiTotalLayer = 3; //DO NOT CHANGE!
-const uint32_t kiSliceNum = 2; //DO NOT CHANGE!
-const uint32_t kiWidth = 160; //DO NOT CHANGE!
-const uint32_t kiHeight = 96; //DO NOT CHANGE!
-const uint32_t kiFrameRate = 12; //DO NOT CHANGE!
-const uint32_t kiFrameNum = 100; //DO NOT CHANGE!
-const char* const pHashStr[][2] = { //DO NOT CHANGE!
- // Allow for different output depending on whether averaging is done
- // vertically or horizontally first when downsampling.
- { "caaaa3352ab8614e3a35836f5d7c9a528294e953", "326cc236e9ba5277aedc5cf0865dd4cbd2f89fe0" },
- { "2dc97661e94515d9947a344127062f82814afc2a", "72f36bb33d190979be88077c6166a09767dd2992" },
- { "106ec96a90412aabea5c0cfa6bfc654a0b5db33e", "998c2947bccf140bde1e43e29376614038eb7c71" }
-};
-
-class DecodeParseAPI : public ::testing::TestWithParam<EncodeDecodeFileParamBase>, public EncodeDecodeTestBase {
- public:
- DecodeParseAPI() {
- memset (&BsInfo_, 0, sizeof (SParserBsInfo));
- fYuv_ = NULL;
- iWidth_ = 0;
- iHeight_ = 0;
- memset (&ctx_, 0, sizeof (SHA1Context));
- }
- void SetUp() {
- SHA1Reset (&ctx_);
- EncodeDecodeTestBase::SetUp();
-
- if (decoder_)
- decoder_->Uninitialize();
- SDecodingParam decParam;
- memset (&decParam, 0, sizeof (SDecodingParam));
- decParam.uiTargetDqLayer = UCHAR_MAX;
- decParam.eEcActiveIdc = ERROR_CON_SLICE_COPY;
- decParam.bParseOnly = true;
- decParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT;
-
- int rv = decoder_->Initialize (&decParam);
- ASSERT_EQ (0, rv);
- memset (&BsInfo_, 0, sizeof (SParserBsInfo));
- const char* sFileName = "res/CiscoVT2people_160x96_6fps.yuv";
-#if defined(ANDROID_NDK)
- std::string filename = std::string ("/sdcard/") + sFileName;
- ASSERT_TRUE ((fYuv_ = fopen (filename.c_str(), "rb")) != NULL);
-#else
- ASSERT_TRUE ((fYuv_ = fopen (sFileName, "rb")) != NULL);
-#endif
- iWidth_ = kiWidth;
- iHeight_ = kiHeight;
- }
- void TearDown() {
- EncodeDecodeTestBase::TearDown();
- if (fYuv_ != NULL) {
- fclose (fYuv_);
- fYuv_ = NULL;
- }
- }
-
- bool prepareEncDecParam (const EncodeDecodeFileParamBase p) {
- if (!EncodeDecodeTestBase::prepareEncDecParam (p))
- return false;
- unsigned char* pTmpPtr = BsInfo_.pDstBuff; //store for restore
- memset (&BsInfo_, 0, sizeof (SParserBsInfo));
- BsInfo_.pDstBuff = pTmpPtr;
- return true;
- }
-
- void MockInputData (uint8_t* pData, int32_t iSize) {
- int32_t iCurr = 0;
- while (iCurr < iSize) {
- * (pData + iCurr) = (* (pData + iCurr) + (rand() % 20) + 256) & 0x00ff;
- iCurr++;
- }
- }
-
- void EncodeOneFrame (bool bMock) {
- int iFrameSize = iWidth_ * iHeight_ * 3 / 2;
- int iSize = (int) fread (buf_.data(), sizeof (char), iFrameSize, fYuv_);
- if (feof (fYuv_) || iSize != iFrameSize) {
- rewind (fYuv_);
- iSize = (int) fread (buf_.data(), sizeof (char), iFrameSize, fYuv_);
- ASSERT_TRUE (iSize == iFrameSize);
- }
- if (bMock) {
- MockInputData (buf_.data(), iWidth_ * iHeight_);
- }
- int rv = encoder_->EncodeFrame (&EncPic, &info);
- ASSERT_TRUE (rv == cmResultSuccess || rv == cmUnknownReason);
- }
-
- void prepareParam (int iLayerNum, int iSliceNum, int width, int height, float framerate, SEncParamExt* pParam) {
- memset (pParam, 0, sizeof (SEncParamExt));
- EncodeDecodeTestBase::prepareParam (iLayerNum, iSliceNum, width, height, framerate, pParam);
- }
-
- protected:
- SParserBsInfo BsInfo_;
- FILE* fYuv_;
- int iWidth_;
- int iHeight_;
- SHA1Context ctx_;
-};
-
-//#define DEBUG_FILE_SAVE_PARSEONLY_GENERAL
-TEST_F (DecodeParseAPI, ParseOnly_General) {
- EncodeDecodeFileParamBase p;
- p.width = iWidth_;
- p.height = iHeight_;
- p.frameRate = kiFrameRate;
- p.numframes = kiFrameNum;
- prepareParam (kiTotalLayer, kiSliceNum, p.width, p.height, p.frameRate, ¶m_);
- param_.iSpatialLayerNum = kiTotalLayer;
- encoder_->Uninitialize();
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == 0);
- int32_t iTraceLevel = WELS_LOG_QUIET;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- uint32_t uiTargetLayerId = rand() % kiTotalLayer; //run only once
-#ifdef DEBUG_FILE_SAVE_PARSEONLY_GENERAL
- FILE* fDec = fopen ("output.264", "wb");
- FILE* fEnc = fopen ("enc.264", "wb");
- FILE* fExtract = fopen ("extract.264", "wb");
-#endif
- if (uiTargetLayerId < kiTotalLayer) { //should always be true
- //Start for enc
- int iLen = 0;
- ASSERT_TRUE (prepareEncDecParam (p));
- int iFrame = 0;
-
- while (iFrame < p.numframes) {
- //encode
- EncodeOneFrame (0);
- //extract target layer data
- encToDecData (info, iLen);
-#ifdef DEBUG_FILE_SAVE_PARSEONLY_GENERAL
- fwrite (info.sLayerInfo[0].pBsBuf, iLen, 1, fEnc);
-#endif
- ExtractDidNal (&info, iLen, &m_SLostSim, uiTargetLayerId);
-#ifdef DEBUG_FILE_SAVE_PARSEONLY_GENERAL
- fwrite (info.sLayerInfo[0].pBsBuf, iLen, 1, fExtract);
-#endif
- //parseonly
- //BsInfo_.pDstBuff = new unsigned char [1000000];
- rv = decoder_->DecodeParser (info.sLayerInfo[0].pBsBuf, iLen, &BsInfo_);
- EXPECT_TRUE (rv == 0);
- EXPECT_TRUE (BsInfo_.iNalNum == 0);
- rv = decoder_->DecodeParser (NULL, 0, &BsInfo_);
- EXPECT_TRUE (rv == 0);
- EXPECT_TRUE (BsInfo_.iNalNum != 0);
- //get final output bs
- iLen = 0;
- int i = 0;
- while (i < BsInfo_.iNalNum) {
- iLen += BsInfo_.pNalLenInByte[i];
- i++;
- }
-#ifdef DEBUG_FILE_SAVE_PARSEONLY_GENERAL
- fwrite (BsInfo_.pDstBuff, iLen, 1, fDec);
-#endif
- SHA1Input (&ctx_, BsInfo_.pDstBuff, iLen);
- iFrame++;
- }
- //calculate final SHA1 value
- unsigned char digest[SHA_DIGEST_LENGTH];
- SHA1Result (&ctx_, digest);
- if (!HasFatalFailure()) {
- CompareHashAnyOf (digest, pHashStr[uiTargetLayerId], sizeof * pHashStr / sizeof** pHashStr);
- }
- } //while
-#ifdef DEBUG_FILE_SAVE_PARSEONLY_GENERAL
- fclose (fEnc);
- fclose (fExtract);
- fclose (fDec);
-#endif
-}
-
-//This case is for one layer only, for incomplete frame input
-//First slice is loss for random one picture with 2 slices per pic
-TEST_F (DecodeParseAPI, ParseOnly_SpecSliceLoss) {
- int32_t iLayerNum = 1;
- int32_t iSliceNum = 2;
- EncodeDecodeFileParamBase p;
- p.width = iWidth_;
- p.height = iHeight_;
- p.frameRate = kiFrameRate;
- p.numframes = 5;
- prepareParam (iLayerNum, iSliceNum, p.width, p.height, p.frameRate, ¶m_);
- param_.iSpatialLayerNum = iLayerNum;
- encoder_->Uninitialize();
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == 0);
- int32_t iTraceLevel = WELS_LOG_QUIET;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
-
- int32_t iMissedPicNum = rand() % (p.numframes - 1) + 1; //IDR no loss
- //Start for enc
- int iLen = 0;
- uint32_t uiGet;
- ASSERT_TRUE (prepareEncDecParam (p));
- int iFrame = 0;
-
- while (iFrame < p.numframes) {
- //encode
- EncodeOneFrame (0);
- //parseonly
- if (iFrame == iMissedPicNum) { //make current frame partly missing
- //Frame: P, first slice loss
- int32_t iTotalSliceSize = 0;
- encToDecSliceData (0, 0, info, iTotalSliceSize); //slice 1 lost
- encToDecSliceData (0, 1, info, iLen); //slice 2
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_DISABLE);
- rv = decoder_->DecodeParser (info.sLayerInfo[0].pBsBuf + iTotalSliceSize, iLen, &BsInfo_);
- EXPECT_TRUE (rv == 0);
- EXPECT_TRUE (BsInfo_.iNalNum == 0);
- rv = decoder_->DecodeParser (NULL, 0, &BsInfo_);
- EXPECT_TRUE (rv != 0);
- } else { //normal frame, complete
- encToDecData (info, iLen);
- rv = decoder_->DecodeParser (info.sLayerInfo[0].pBsBuf, iLen, &BsInfo_);
- EXPECT_TRUE (rv == 0); //parse correct
- EXPECT_TRUE (BsInfo_.iNalNum == 0);
- rv = decoder_->DecodeParser (NULL, 0, &BsInfo_);
- if (iFrame < iMissedPicNum) { //correct frames, all OK with output
- EXPECT_TRUE (rv == 0);
- EXPECT_TRUE (BsInfo_.iNalNum != 0);
- } else { //(iFrame > iMissedPicNum), should output nothing as error
- EXPECT_TRUE (rv != 0);
- EXPECT_TRUE (BsInfo_.iNalNum == 0);
- }
- }
- iFrame++;
- } //while
-}
-
-TEST_F (DecodeParseAPI, ParseOnly_SpecStatistics) {
- //set params
- int32_t iLayerNum = 1;
- int32_t iSliceNum = 1;
- EncodeDecodeFileParamBase p;
- const int iLoopNum = 10;
- p.frameRate = kiFrameRate;
- p.numframes = 2; //encode 2 frames in each test
- p.width = iWidth_ = 16;
- p.height = iHeight_ = 16; //default start width/height = 16, will be modified each time
- int iTotalFrmCnt = 0;
- for (int i = 0; i < iLoopNum; ++i) {
- prepareParam (iLayerNum, iSliceNum, p.width, p.height, p.frameRate, ¶m_);
- param_.iSpatialLayerNum = iLayerNum;
- param_.sSpatialLayers[0].iDLayerQp = 40; //to revent size too limited to encoding fail
- encoder_->Uninitialize();
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == 0);
- int32_t iTraceLevel = WELS_LOG_QUIET;
- rv = encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- ASSERT_TRUE (rv == 0);
- rv = decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- ASSERT_TRUE (rv == 0);
- //Start for enc
- int iLen = 0;
- ASSERT_TRUE (prepareEncDecParam (p));
- int iFrame = 0;
- while (iFrame < p.numframes) {
- EncodeOneFrame (0);
- encToDecData (info, iLen);
- iFrame++;
- iTotalFrmCnt++;
- rv = decoder_->DecodeParser (info.sLayerInfo[0].pBsBuf, iLen, &BsInfo_);
- ASSERT_TRUE (rv == 0);
- ASSERT_TRUE (BsInfo_.iNalNum == 0);
- rv = decoder_->DecodeParser (NULL, 0, &BsInfo_);
- ASSERT_TRUE (rv == 0);
- ASSERT_TRUE (BsInfo_.iNalNum != 0);
- SDecoderStatistics sDecStat;
- rv = decoder_->GetOption (DECODER_OPTION_GET_STATISTICS, &sDecStat);
- ASSERT_TRUE (rv == 0);
- uint32_t uiProfile, uiLevel;
- rv = decoder_->GetOption (DECODER_OPTION_PROFILE, &uiProfile);
- ASSERT_TRUE (rv == 0);
- rv = decoder_->GetOption (DECODER_OPTION_LEVEL, &uiLevel);
- ASSERT_TRUE (rv == 0);
-
- ASSERT_EQ (sDecStat.uiWidth, (unsigned int) p.width);
- ASSERT_EQ (sDecStat.uiHeight, (unsigned int) p.height);
- ASSERT_EQ (sDecStat.uiResolutionChangeTimes, (unsigned int) (i + 1));
- EXPECT_EQ (sDecStat.iCurrentActiveSpsId, 0);
- EXPECT_EQ (sDecStat.iCurrentActivePpsId, 0);
- ASSERT_EQ (sDecStat.uiDecodedFrameCount, (unsigned int) iTotalFrmCnt);
- ASSERT_EQ (sDecStat.uiProfile, uiProfile);
- ASSERT_EQ (sDecStat.uiLevel, uiLevel);
- EXPECT_TRUE (sDecStat.fActualAverageFrameSpeedInMs != 0.);
- EXPECT_TRUE (sDecStat.fAverageFrameSpeedInMs != 0.);
- EXPECT_TRUE (sDecStat.iAvgLumaQp != 0);
- EXPECT_EQ (sDecStat.uiIDRCorrectNum, (unsigned int) (i + 1));
- }
- //set next width & height
- p.width += 16;
- p.height += 16;
- if ((unsigned int) p.width > kiWidth) //exceeds max frame size
- p.width = 16;
- if ((unsigned int) p.height > kiHeight)
- p.height = 16;
- iWidth_ = p.width;
- iHeight_ = p.height;
- }
-}
-
-
-//Test parseonly crash cases
-class DecodeParseCrashAPI : public DecodeParseAPI {
- public:
- DecodeParseCrashAPI() {
- }
- void SetUp() {
- DecodeParseAPI::SetUp();
- iWidth_ = 1280;
- iHeight_ = 720;
-
- ucBuf_ = NULL;
- ucBuf_ = new unsigned char[1000000];
- ASSERT_TRUE (ucBuf_ != NULL);
-
- }
- void TearDown() {
- DecodeParseAPI::TearDown();
- if (NULL != ucBuf_) {
- delete[] ucBuf_;
- ucBuf_ = NULL;
- }
- ASSERT_TRUE (ucBuf_ == NULL);
- }
-
- protected:
- unsigned char* ucBuf_;
-};
-
-//#define DEBUG_FILE_SAVE_PARSE_CRA1
-TEST_F (DecodeParseCrashAPI, ParseOnlyCrash_General) {
- if (fYuv_)
- fclose (fYuv_);
- const char* sFileName = "res/Cisco_Absolute_Power_1280x720_30fps.yuv";
-#if defined(ANDROID_NDK)
- std::string filename = std::string ("/sdcard/") + sFileName;
- ASSERT_TRUE ((fYuv_ = fopen (filename.c_str(), "rb")) != NULL);
-#else
- ASSERT_TRUE ((fYuv_ = fopen (sFileName, "rb")) != NULL);
-#endif
- uint32_t uiGet;
- encoder_->Uninitialize();
- //do tests until crash
- unsigned int uiLoopRound = 0;
- unsigned char* pucBuf = ucBuf_;
- int iDecAuSize;
-#ifdef DEBUG_FILE_SAVE_PARSE_CRA1
- //open file to save tested BS
- FILE* fDataFile = fopen ("test_parseonly_crash.264", "wb");
- FILE* fLenFile = fopen ("test_parseonly_crash_len.log", "w");
- int iFileSize = 0;
-#endif
-
- do {
-#ifdef DEBUG_FILE_SAVE_PARSE_CRA1
- int iTotalFrameNum = (rand() % 1200) + 1;
-#else
- int iTotalFrameNum = (rand() % 100) + 1;
-#endif
- EncodeDecodeParamBase p = kParamArray[8]; //720p by default
-
- //Initialize Encoder
- prepareParam (1, 4, p.width, p.height, p.frameRate, ¶m_);
- param_.iRCMode = RC_TIMESTAMP_MODE;
- param_.iTargetBitrate = p.iTarBitrate;
- param_.uiIntraPeriod = 0;
- param_.eSpsPpsIdStrategy = CONSTANT_ID;
- param_.bEnableBackgroundDetection = true;
- param_.bEnableSceneChangeDetect = (rand() % 3) ? true : false;
- param_.bPrefixNalAddingCtrl = 0;// (rand() % 2) ? true : false;
- param_.iEntropyCodingModeFlag = 0;
- param_.bEnableFrameSkip = true;
- param_.iMultipleThreadIdc = 0;
- param_.sSpatialLayers[0].iSpatialBitrate = p.iTarBitrate;
- param_.sSpatialLayers[0].iMaxSpatialBitrate = p.iTarBitrate << 1;
- param_.sSpatialLayers[0].sSliceArgument.uiSliceMode =
- SM_FIXEDSLCNUM_SLICE; // (rand() % 2) ? SM_SIZELIMITED_SLICE : SM_SINGLE_SLICE;
- if (param_.sSpatialLayers[0].sSliceArgument.uiSliceMode == SM_SIZELIMITED_SLICE) {
- param_.sSpatialLayers[0].sSliceArgument.uiSliceSizeConstraint = 1400;
- param_.uiMaxNalSize = 1400;
- } else {
- param_.sSpatialLayers[0].sSliceArgument.uiSliceSizeConstraint = 0;
- param_.uiMaxNalSize = 0;
- }
-
- int rv = encoder_->InitializeExt (¶m_);
- ASSERT_TRUE (rv == cmResultSuccess);
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, (uint32_t)ERROR_CON_DISABLE); //default value should be ERROR_CON_SLICE_COPY
- int32_t iTraceLevel = WELS_LOG_QUIET;
- encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
- decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
-
- //Start for enc/dec
- int iIdx = 0;
- unsigned char* pData[3] = { NULL };
-
- EncodeDecodeFileParamBase pInput; //to conform with old functions
- pInput.width = p.width;
- pInput.height = p.height;
- pInput.frameRate = p.frameRate;
- prepareEncDecParam (pInput);
- while (iIdx++ < iTotalFrameNum) { // loop in frame
- EncodeOneFrame (1);
-#ifdef DEBUG_FILE_SAVE_PARSE_CRA1
- //reset file if file size large
- if ((info.eFrameType == videoFrameTypeIDR) && (iFileSize >= (1 << 25))) {
- fclose (fDataFile);
- fclose (fLenFile);
- fDataFile = fopen ("test_parseonly_crash.264", "wb");
- fLenFile = fopen ("test_parseonly_crash_len.log", "w");
- iFileSize = 0;
- decoder_->Uninitialize();
-
- SDecodingParam decParam;
- memset (&decParam, 0, sizeof (SDecodingParam));
- decParam.uiTargetDqLayer = UCHAR_MAX;
- decParam.eEcActiveIdc = ERROR_CON_DISABLE;
- decParam.bParseOnly = true;
- decParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT;
-
- rv = decoder_->Initialize (&decParam);
- ASSERT_EQ (0, rv);
- }
-#endif
- if (info.eFrameType == videoFrameTypeSkip)
- continue;
- //deal with packets
- unsigned char* pBsBuf;
- iDecAuSize = 0;
- pucBuf = ucBuf_; //init buf start pos for decoder usage
- for (int iLayerNum = 0; iLayerNum < info.iLayerNum; iLayerNum++) {
- SLayerBSInfo* pLayerBsInfo = &info.sLayerInfo[iLayerNum];
- pBsBuf = info.sLayerInfo[iLayerNum].pBsBuf;
- int iTotalNalCnt = pLayerBsInfo->iNalCount;
- for (int iNalCnt = 0; iNalCnt < iTotalNalCnt; iNalCnt++) { //loop in NAL
- int iPacketSize = pLayerBsInfo->pNalLengthInByte[iNalCnt];
- //packet loss
- int iLossRateRange = (uiLoopRound % 20) + 1; //1-100
- int iLossRate = (rand() % iLossRateRange);
- bool bPacketLost = (rand() % 101) > (100 -
- iLossRate); // [0, (100-iLossRate)] indicates NO LOSS, (100-iLossRate, 100] indicates LOSS
- if (!bPacketLost) { //no loss
- memcpy (pucBuf, pBsBuf, iPacketSize);
- pucBuf += iPacketSize;
- iDecAuSize += iPacketSize;
- }
- //update bs info
- pBsBuf += iPacketSize;
- } //nal
- } //layer
-
-#ifdef DEBUG_FILE_SAVE_PARSE_CRA1
- //save to file
- if (iDecAuSize != 0) {
- fwrite (ucBuf_, 1, iDecAuSize, fDataFile);
- fflush (fDataFile);
- iFileSize += iDecAuSize;
- }
-
- //save to len file
- unsigned long ulTmp[4];
- ulTmp[0] = ulTmp[1] = ulTmp[2] = iIdx;
- ulTmp[3] = iDecAuSize;
- fwrite (ulTmp, sizeof (unsigned long), 4, fLenFile); // index, timeStamp, data size
- fflush (fLenFile);
-#endif
-
- //decode
- pData[0] = pData[1] = pData[2] = 0;
- memset (&BsInfo_, 0, sizeof (SParserBsInfo));
-
- rv = decoder_->DecodeParser (ucBuf_, iDecAuSize, &BsInfo_);
- rv = decoder_->DecodeParser (NULL, 0, &BsInfo_); //reconstruction
- //guarantee decoder EC status
- decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
- EXPECT_EQ (uiGet, (uint32_t)ERROR_CON_DISABLE);
- } //frame
- uiLoopRound++;
- if (uiLoopRound >= (1 << 30))
- uiLoopRound = 0;
-#ifdef DEBUG_FILE_SAVE_PARSE_CRA1
- if (uiLoopRound % 10 == 0)
- printf ("run %d times.\n", uiLoopRound);
- } while (1);
- fclose (fDataFile);
- fclose (fLenFile);
-#else
- }
- while (0);
-#endif
-
-}
-
+#include <gtest/gtest.h>
+#include "codec_def.h"
+#include "utils/BufferedData.h"
+#include "utils/FileInputStream.h"
+#include "BaseDecoderTest.h"
+#include "BaseEncoderTest.h"
+#include "wels_common_defs.h"
+#include "utils/HashFunctions.h"
+#include <string>
+#include <vector>
+#include "encode_decode_api_test.h"
+using namespace WelsCommon;
+
+static void TestOutPutTrace (void* ctx, int level, const char* string) {
+ STraceUnit* pTraceUnit = (STraceUnit*) ctx;
+ EXPECT_LE (level, pTraceUnit->iTarLevel);
+}
+
+TEST_P (EncodeDecodeTestAPI, DecoderVclNal) {
+ EncodeDecodeFileParamBase p = GetParam();
+ prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
+ encoder_->Uninitialize();
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+
+ ASSERT_TRUE (InitialEncDec (p.width, p.height));
+
+ int iIdx = 0;
+ while (iIdx <= p.numframes) {
+
+ EncodeOneFrame (0);
+
+ //decoding after each encoding frame
+ int vclNal, len = 0;
+ encToDecData (info, len);
+ unsigned char* pData[3] = { NULL };
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+ rv = decoder_->GetOption (DECODER_OPTION_VCL_NAL, &vclNal);
+ EXPECT_EQ (vclNal, FEEDBACK_UNKNOWN_NAL); //no reconstruction, unknown return
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ ASSERT_TRUE (rv == cmResultSuccess);
+ rv = decoder_->GetOption (DECODER_OPTION_VCL_NAL, &vclNal);
+ EXPECT_EQ (vclNal, FEEDBACK_VCL_NAL);
+ iIdx++;
+ } //while
+ //ignore last frame
+}
+
+TEST_P (EncodeDecodeTestAPI, GetOptionFramenum) {
+ EncodeDecodeFileParamBase p = GetParam();
+ prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
+ encoder_->Uninitialize();
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+
+ ASSERT_TRUE (InitialEncDec (p.width, p.height));
+
+ int32_t iEncFrameNum = -1;
+ int32_t iDecFrameNum;
+ int iIdx = 0;
+ while (iIdx <= p.numframes) {
+ EncodeOneFrame (0);
+ //decoding after each encoding frame
+ int len = 0;
+ encToDecData (info, len);
+ unsigned char* pData[3] = { NULL };
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+ decoder_->GetOption (DECODER_OPTION_FRAME_NUM, &iDecFrameNum);
+ EXPECT_EQ (iDecFrameNum, -1);
+ iEncFrameNum++;
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ ASSERT_TRUE (rv == cmResultSuccess);
+ decoder_->GetOption (DECODER_OPTION_FRAME_NUM, &iDecFrameNum);
+ EXPECT_EQ (iEncFrameNum, iDecFrameNum);
+ iIdx++;
+ } //while
+ //ignore last frame
+}
+
+TEST_P (EncodeDecodeTestAPI, GetOptionIDR) {
+ EncodeDecodeFileParamBase p = GetParam();
+ prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
+ encoder_->Uninitialize();
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+
+ //init for encoder
+ // I420: 1(Y) + 1/4(U) + 1/4(V)
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+
+ ASSERT_TRUE (InitialEncDec (p.width, p.height));
+
+ int32_t iEncCurIdrPicId = 0;
+ int32_t iDecCurIdrPicId;
+ int32_t iIDRPeriod = 1;
+ int32_t iSpsPpsIdAddition = 0;
+ int iIdx = 0;
+ while (iIdx <= p.numframes) {
+ iSpsPpsIdAddition = rand() %
+ 2; //the current strategy supports more than 2 modes, but the switch between the modes>2 is not allowed
+ iIDRPeriod = (rand() % 150) + 1;
+ encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
+ encoder_->SetOption (ENCODER_OPTION_SPS_PPS_ID_STRATEGY, &iSpsPpsIdAddition);
+
+ EncodeOneFrame (0);
+
+ if (info.eFrameType == videoFrameTypeIDR) {
+ iEncCurIdrPicId = iEncCurIdrPicId + 1;
+ }
+ //decoding after each encoding frame
+ int len = 0;
+ encToDecData (info, len);
+ unsigned char* pData[3] = { NULL };
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+ decoder_->GetOption (DECODER_OPTION_IDR_PIC_ID, &iDecCurIdrPicId);
+ EXPECT_EQ (iDecCurIdrPicId, iEncCurIdrPicId);
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ ASSERT_TRUE (rv == cmResultSuccess);
+ decoder_->GetOption (DECODER_OPTION_IDR_PIC_ID, &iDecCurIdrPicId);
+ EXPECT_EQ (iDecCurIdrPicId, iEncCurIdrPicId);
+ iIdx++;
+ } //while
+ //ignore last frame
+}
+
+TEST_P (EncodeDecodeTestAPI, InOutTimeStamp) {
+ EncodeDecodeFileParamBase p = GetParam();
+ prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
+ encoder_->Uninitialize();
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+
+ ASSERT_TRUE (InitialEncDec (p.width, p.height));
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ int32_t iSpsPpsIdAddition = 1;
+ encoder_->SetOption (ENCODER_OPTION_SPS_PPS_ID_STRATEGY, &iSpsPpsIdAddition);
+ int32_t iIDRPeriod = 60;
+ encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
+ SLTRConfig sLtrConfigVal;
+ sLtrConfigVal.bEnableLongTermReference = 1;
+ sLtrConfigVal.iLTRRefNum = 1;
+ encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
+ int32_t iLtrPeriod = 2;
+ encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
+ int iIdx = 0;
+ int iSkipedBytes;
+ unsigned long long uiEncTimeStamp = 100;
+ while (iIdx <= p.numframes) {
+ EncodeOneFrame (1);
+ //decoding after each encoding frame
+ int len = 0;
+ encToDecData (info, len);
+ unsigned char* pData[3] = { NULL };
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ uint32_t uiEcIdc = ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE;
+ decoder_->SetOption (DECODER_OPTION_ERROR_CON_IDC, &uiEcIdc);
+ dstBufInfo_.uiInBsTimeStamp = uiEncTimeStamp;
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ dstBufInfo_.uiInBsTimeStamp = uiEncTimeStamp;
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ if (dstBufInfo_.iBufferStatus == 1) {
+ EXPECT_EQ (uiEncTimeStamp, dstBufInfo_.uiOutYuvTimeStamp);
+ }
+ iIdx++;
+ uiEncTimeStamp++;
+ }
+ (void) iSkipedBytes;
+}
+
+TEST_P (EncodeDecodeTestAPI, GetOptionIsRefPic) {
+ EncodeDecodeFileParamBase p = GetParam();
+ prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
+ encoder_->Uninitialize();
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+
+ ASSERT_TRUE (InitialEncDec (p.width, p.height));
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ int iIdx = 0;
+ int iSkipedBytes;
+ int iIsRefPic;
+ decoder_->GetOption (DECODER_OPTION_IS_REF_PIC, &iIsRefPic);
+ ASSERT_EQ (iIsRefPic, -1);
+
+ while (iIdx <= p.numframes) {
+ EncodeOneFrame (1);
+ //decoding after each encoding frame
+ int len = 0;
+ encToDecData (info, len);
+ unsigned char* pData[3] = { NULL };
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ decoder_->GetOption (DECODER_OPTION_IS_REF_PIC, &iIsRefPic);
+ ASSERT_EQ (iIsRefPic, -1);
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ if (dstBufInfo_.iBufferStatus == 1) {
+ decoder_->GetOption (DECODER_OPTION_IS_REF_PIC, &iIsRefPic);
+ ASSERT_TRUE (iIsRefPic >= 0);
+ }
+ iIdx++;
+ }
+ (void)iSkipedBytes;
+}
+
+TEST_P (EncodeDecodeTestAPI, GetOptionTid_AVC_NOPREFIX) {
+ SLTRMarkingFeedback m_LTR_Marking_Feedback;
+ SLTRRecoverRequest m_LTR_Recover_Request;
+ m_LTR_Recover_Request.uiIDRPicId = 0;
+ m_LTR_Recover_Request.iLayerId = 0;
+ m_LTR_Marking_Feedback.iLayerId = 0;
+ EncodeDecodeFileParamBase p = GetParam();
+ prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
+ param_.bPrefixNalAddingCtrl = false;
+ param_.iTemporalLayerNum = (rand() % 4) + 1;
+ encoder_->Uninitialize();
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+ m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
+ ASSERT_TRUE (InitialEncDec (p.width, p.height));
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ int32_t iSpsPpsIdAddition = 1;
+ encoder_->SetOption (ENCODER_OPTION_SPS_PPS_ID_STRATEGY, &iSpsPpsIdAddition);
+ int32_t iIDRPeriod = 60;
+ encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
+ SLTRConfig sLtrConfigVal;
+ sLtrConfigVal.bEnableLongTermReference = 1;
+ sLtrConfigVal.iLTRRefNum = 1;
+ encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
+ int32_t iLtrPeriod = 2;
+ encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
+ int iIdx = 0;
+ int iLossIdx = 0;
+ bool bVCLLoss = false;
+ while (iIdx <= p.numframes) {
+ EncodeOneFrame (1);
+ if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) {
+ ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
+ }
+ //decoding after each encoding frame
+ int len = 0;
+ encToDecData (info, len);
+ unsigned char* pData[3] = { NULL };
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ SimulateNALLoss (info.sLayerInfo[0].pBsBuf, len, &m_SLostSim, p.pLossSequence, p.bLostPara, iLossIdx, bVCLLoss);
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ int iTid = -1;
+ decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid);
+ if (iTid != -1) {
+ ASSERT_EQ (iTid, 0);
+ }
+ m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
+ LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid);
+ std::vector<SLostSim>::iterator iter = m_SLostSim.begin();
+ bool bHasVCL = false;
+ for (unsigned int k = 0; k < m_SLostSim.size(); k++) {
+ if (IS_VCL_NAL (iter->eNalType, 0) && iter->isLost == false) {
+ bHasVCL = true;
+ break;
+ }
+ iter++;
+ }
+ (void) bHasVCL;
+ if (iTid != -1) {
+ ASSERT_EQ (iTid, 0);
+ }
+ LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
+ LTRMarkFeedback (decoder_, encoder_, &m_LTR_Marking_Feedback, rv);
+ iIdx++;
+ }
+}
+
+TEST_P (EncodeDecodeTestAPI, GetOptionTid_AVC_WITH_PREFIX_NOLOSS) {
+ SLTRMarkingFeedback m_LTR_Marking_Feedback;
+ SLTRRecoverRequest m_LTR_Recover_Request;
+ m_LTR_Recover_Request.uiIDRPicId = 0;
+ m_LTR_Recover_Request.iLayerId = 0;
+ m_LTR_Marking_Feedback.iLayerId = 0;
+ EncodeDecodeFileParamBase p = GetParam();
+ prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
+ param_.bPrefixNalAddingCtrl = true;
+ param_.iTemporalLayerNum = (rand() % 4) + 1;
+ param_.iSpatialLayerNum = 1;
+ encoder_->Uninitialize();
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+ m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
+
+ ASSERT_TRUE (InitialEncDec (p.width, p.height));
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ int32_t iSpsPpsIdAddition = 1;
+ encoder_->SetOption (ENCODER_OPTION_SPS_PPS_ID_STRATEGY, &iSpsPpsIdAddition);
+ int32_t iIDRPeriod = 60;
+ encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
+ SLTRConfig sLtrConfigVal;
+ sLtrConfigVal.bEnableLongTermReference = 1;
+ sLtrConfigVal.iLTRRefNum = 1;
+ encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
+ int32_t iLtrPeriod = 2;
+ encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
+ int iIdx = 0;
+ while (iIdx <= p.numframes) {
+ EncodeOneFrame (1);
+ if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) {
+ ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
+ }
+ //decoding after each encoding frame
+ int len = 0;
+ encToDecData (info, len);
+ unsigned char* pData[3] = { NULL };
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ ExtractDidNal (&info, len, &m_SLostSim, 0);
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ int iTid = -1;
+ decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid);
+ ASSERT_EQ (iTid, -1);
+ m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
+ LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid);
+ ASSERT_EQ (iTid, info.sLayerInfo[0].uiTemporalId);
+ LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
+ LTRMarkFeedback (decoder_, encoder_, &m_LTR_Marking_Feedback, rv);
+ iIdx++;
+ }
+}
+
+TEST_P (EncodeDecodeTestAPI, GetOptionTid_SVC_L1_NOLOSS) {
+ SLTRMarkingFeedback m_LTR_Marking_Feedback;
+ SLTRRecoverRequest m_LTR_Recover_Request;
+ m_LTR_Recover_Request.uiIDRPicId = 0;
+ m_LTR_Recover_Request.iLayerId = 0;
+ m_LTR_Marking_Feedback.iLayerId = 0;
+ EncodeDecodeFileParamBase p = GetParam();
+ prepareParamDefault (2, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
+ param_.iTemporalLayerNum = (rand() % 4) + 1;
+ param_.iSpatialLayerNum = 2;
+ encoder_->Uninitialize();
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+ m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
+
+ ASSERT_TRUE (InitialEncDec (p.width, p.height));
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ int32_t iSpsPpsIdAddition = 1;
+ encoder_->SetOption (ENCODER_OPTION_SPS_PPS_ID_STRATEGY, &iSpsPpsIdAddition);
+ int32_t iIDRPeriod = 60;
+ encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
+ SLTRConfig sLtrConfigVal;
+ sLtrConfigVal.bEnableLongTermReference = 1;
+ sLtrConfigVal.iLTRRefNum = 1;
+ encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
+ int32_t iLtrPeriod = 2;
+ encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
+ int iIdx = 0;
+ while (iIdx <= p.numframes) {
+ EncodeOneFrame (1);
+ if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) {
+ ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
+ }
+ //decoding after each encoding frame
+ int len = 0;
+ encToDecData (info, len);
+ unsigned char* pData[3] = { NULL };
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ ExtractDidNal (&info, len, &m_SLostSim, 1);
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ int iTid = -1;
+ decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid);
+ ASSERT_EQ (iTid, -1);
+ m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
+ LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ decoder_->GetOption (DECODER_OPTION_TEMPORAL_ID, &iTid);
+ ASSERT_EQ (iTid, info.sLayerInfo[0].uiTemporalId);
+ LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
+ LTRMarkFeedback (decoder_, encoder_, &m_LTR_Marking_Feedback, rv);
+ iIdx++;
+ }
+}
+
+
+
+TEST_P (EncodeDecodeTestAPI, SetOption_Trace) {
+ SLTRMarkingFeedback m_LTR_Marking_Feedback;
+ SLTRRecoverRequest m_LTR_Recover_Request;
+ m_LTR_Recover_Request.uiIDRPicId = 0;
+ m_LTR_Recover_Request.iLayerId = 0;
+ m_LTR_Marking_Feedback.iLayerId = 0;
+ EncodeDecodeFileParamBase p = GetParam();
+ prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
+ param_.iSpatialLayerNum = 1;
+
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+ m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
+
+ ASSERT_TRUE (InitialEncDec (p.width, p.height));
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ pFunc = TestOutPutTrace;
+ pTraceInfo = &sTrace;
+ sTrace.iTarLevel = iTraceLevel;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ encoder_->SetOption (ENCODER_OPTION_TRACE_CALLBACK, &pFunc);
+ encoder_->SetOption (ENCODER_OPTION_TRACE_CALLBACK_CONTEXT, &pTraceInfo);
+ decoder_->SetOption (DECODER_OPTION_TRACE_CALLBACK, &pFunc);
+ decoder_->SetOption (DECODER_OPTION_TRACE_CALLBACK_CONTEXT, &pTraceInfo);
+
+
+ int32_t iSpsPpsIdAddition = 1;
+ encoder_->SetOption (ENCODER_OPTION_SPS_PPS_ID_STRATEGY, &iSpsPpsIdAddition);
+ int32_t iIDRPeriod = 60;
+ encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
+ SLTRConfig sLtrConfigVal;
+ sLtrConfigVal.bEnableLongTermReference = 1;
+ sLtrConfigVal.iLTRRefNum = 1;
+ encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
+ int32_t iLtrPeriod = 2;
+ encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
+ int iIdx = 0;
+ int iLossIdx = 0;
+ bool bVCLLoss = false;
+ while (iIdx <= p.numframes) {
+ iTraceLevel = rand() % 33;
+ sTrace.iTarLevel = iTraceLevel;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ EncodeOneFrame (1);
+ if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) {
+ ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
+ }
+ //decoding after each encoding frame
+ int len = 0;
+ encToDecData (info, len);
+ unsigned char* pData[3] = { NULL };
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ ExtractDidNal (&info, len, &m_SLostSim, 0);
+ SimulateNALLoss (info.sLayerInfo[0].pBsBuf, len, &m_SLostSim, p.pLossSequence, p.bLostPara, iLossIdx, bVCLLoss);
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
+ LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
+ LTRMarkFeedback (decoder_, encoder_, &m_LTR_Marking_Feedback, rv);
+ iIdx++;
+ }
+}
+
+TEST_P (EncodeDecodeTestAPI, SetOption_Trace_NULL) {
+ SLTRMarkingFeedback m_LTR_Marking_Feedback;
+ SLTRRecoverRequest m_LTR_Recover_Request;
+ m_LTR_Recover_Request.uiIDRPicId = 0;
+ m_LTR_Recover_Request.iLayerId = 0;
+ m_LTR_Marking_Feedback.iLayerId = 0;
+ EncodeDecodeFileParamBase p = GetParam();
+ prepareParamDefault (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
+ param_.iSpatialLayerNum = 1;
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+ m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
+
+ ASSERT_TRUE (InitialEncDec (p.width, p.height));
+
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ pFunc = NULL;
+ pTraceInfo = NULL;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_CALLBACK, &pFunc);
+ encoder_->SetOption (ENCODER_OPTION_TRACE_CALLBACK_CONTEXT, &pTraceInfo);
+ decoder_->SetOption (DECODER_OPTION_TRACE_CALLBACK, &pFunc);
+ decoder_->SetOption (DECODER_OPTION_TRACE_CALLBACK_CONTEXT, &pTraceInfo);
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+
+ int32_t iSpsPpsIdAddition = 1;
+ encoder_->SetOption (ENCODER_OPTION_SPS_PPS_ID_STRATEGY, &iSpsPpsIdAddition);
+ int32_t iIDRPeriod = 60;
+ encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
+ SLTRConfig sLtrConfigVal;
+ sLtrConfigVal.bEnableLongTermReference = 1;
+ sLtrConfigVal.iLTRRefNum = 1;
+ encoder_->SetOption (ENCODER_OPTION_LTR, &sLtrConfigVal);
+ int32_t iLtrPeriod = 2;
+ encoder_->SetOption (ENCODER_LTR_MARKING_PERIOD, &iLtrPeriod);
+ int iIdx = 0;
+ int iLossIdx = 0;
+ bool bVCLLoss = false;
+ while (iIdx <= p.numframes) {
+ iTraceLevel = rand() % 33;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ EncodeOneFrame (1);
+ if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) {
+ ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
+ }
+ //decoding after each encoding frame
+ int len = 0;
+ encToDecData (info, len);
+ unsigned char* pData[3] = { NULL };
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ ExtractDidNal (&info, len, &m_SLostSim, 0);
+ SimulateNALLoss (info.sLayerInfo[0].pBsBuf, len, &m_SLostSim, p.pLossSequence, p.bLostPara, iLossIdx, bVCLLoss);
+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
+ m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
+ LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ LTRRecoveryRequest (decoder_, encoder_, &m_LTR_Recover_Request, rv, true);
+ LTRMarkFeedback (decoder_, encoder_, &m_LTR_Marking_Feedback, rv);
+ iIdx++;
+ }
+}
+
+
+
+
+class DecodeCrashTestAPI : public ::testing::TestWithParam<EncodeDecodeFileParamBase>, public EncodeDecodeTestBase {
+ public:
+ void SetUp() {
+ EncodeDecodeTestBase::SetUp();
+ ucBuf_ = NULL;
+ ucBuf_ = new unsigned char [1000000];
+ ASSERT_TRUE (ucBuf_ != NULL);
+ }
+
+ void TearDown() {
+ EncodeDecodeTestBase::TearDown();
+ if (NULL != ucBuf_) {
+ delete[] ucBuf_;
+ ucBuf_ = NULL;
+ }
+ ASSERT_TRUE (ucBuf_ == NULL);
+ }
+
+ void prepareParam (int iLayerNum, int iSliceNum, int width, int height, float framerate, SEncParamExt* pParam) {
+ memset (pParam, 0, sizeof (SEncParamExt));
+ EncodeDecodeTestBase::prepareParam (iLayerNum, iSliceNum, width, height, framerate, pParam);
+ }
+
+ void EncodeOneFrame() {
+ int frameSize = EncPic.iPicWidth * EncPic.iPicHeight * 3 / 2;
+ memset (buf_.data(), iRandValue, (frameSize >> 2));
+ memset (buf_.data() + (frameSize >> 2), rand() % 256, (frameSize - (frameSize >> 2)));
+ int rv = encoder_->EncodeFrame (&EncPic, &info);
+ ASSERT_TRUE (rv == cmResultSuccess || rv == cmUnknownReason);
+ }
+ protected:
+ unsigned char* ucBuf_;
+};
+
+struct EncodeDecodeParamBase {
+ int width;
+ int height;
+ float frameRate;
+ int iTarBitrate;
+};
+
+#define NUM_OF_POSSIBLE_RESOLUTION (9)
+static const EncodeDecodeParamBase kParamArray[] = {
+ {160, 90, 6.0f, 250000},
+ {90, 160, 6.0f, 250000},
+ {320, 180, 12.0f, 500000},
+ {180, 320, 12.0f, 500000},
+ {480, 270, 12.0f, 600000},
+ {270, 480, 12.0f, 600000},
+ {640, 360, 24.0f, 800000},
+ {360, 640, 24.0f, 800000},
+ {1280, 720, 24.0f, 1000000},
+};
+
+//#define DEBUG_FILE_SAVE_CRA
+TEST_F (DecodeCrashTestAPI, DecoderCrashTest) {
+ uint32_t uiGet;
+ encoder_->Uninitialize();
+
+ //do tests until crash
+ unsigned int uiLoopRound = 0;
+ unsigned char* pucBuf = ucBuf_;
+ int iDecAuSize;
+#ifdef DEBUG_FILE_SAVE_CRA
+ //open file to save tested BS
+ FILE* fDataFile = fopen ("test_crash.264", "wb");
+ FILE* fLenFile = fopen ("test_crash_len.log", "w");
+ int iFileSize = 0;
+#endif
+
+ //set eCurStrategy for one test
+ EParameterSetStrategy eCurStrategy = CONSTANT_ID;
+ switch (rand() % 7) {
+ case 1:
+ eCurStrategy = INCREASING_ID;
+ break;
+ case 2:
+ eCurStrategy = SPS_LISTING;
+ break;
+ case 3:
+ eCurStrategy = SPS_LISTING_AND_PPS_INCREASING;
+ break;
+ case 6:
+ eCurStrategy = SPS_PPS_LISTING;
+ break;
+ default:
+ //using the initial value
+ break;
+ }
+
+ do {
+ int iTotalFrameNum = (rand() % 100) + 1;
+ int iSeed = rand() % NUM_OF_POSSIBLE_RESOLUTION;
+ EncodeDecodeParamBase p = kParamArray[iSeed];
+#ifdef DEBUG_FILE_SAVE_CRA
+ printf ("using param set %d in loop %d\n", iSeed, uiLoopRound);
+#endif
+ //Initialize Encoder
+ prepareParam (1, 1, p.width, p.height, p.frameRate, ¶m_);
+ param_.iRCMode = RC_TIMESTAMP_MODE;
+ param_.iTargetBitrate = p.iTarBitrate;
+ param_.uiIntraPeriod = 0;
+ param_.eSpsPpsIdStrategy = eCurStrategy;
+ param_.bEnableBackgroundDetection = true;
+ param_.bEnableSceneChangeDetect = (rand() % 3) ? true : false;
+ param_.bPrefixNalAddingCtrl = (rand() % 2) ? true : false;
+ param_.iEntropyCodingModeFlag = 0;
+ param_.bEnableFrameSkip = true;
+ param_.iMultipleThreadIdc = 0;
+ param_.sSpatialLayers[0].iSpatialBitrate = p.iTarBitrate;
+ param_.sSpatialLayers[0].iMaxSpatialBitrate = p.iTarBitrate << 1;
+ param_.sSpatialLayers[0].sSliceArgument.uiSliceMode = (rand() % 2) ? SM_SIZELIMITED_SLICE : SM_SINGLE_SLICE;
+ if (param_.sSpatialLayers[0].sSliceArgument.uiSliceMode == SM_SIZELIMITED_SLICE) {
+ param_.sSpatialLayers[0].sSliceArgument.uiSliceSizeConstraint = 1400;
+ param_.uiMaxNalSize = 1400;
+ } else {
+ param_.sSpatialLayers[0].sSliceArgument.uiSliceSizeConstraint = 0;
+ param_.uiMaxNalSize = 0;
+ }
+
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_SLICE_COPY); //default value should be ERROR_CON_SLICE_COPY
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+
+ //Start for enc/dec
+ int iIdx = 0;
+ unsigned char* pData[3] = { NULL };
+
+ EncodeDecodeFileParamBase pInput; //to conform with old functions
+ pInput.width = p.width;
+ pInput.height = p.height;
+ pInput.frameRate = p.frameRate;
+ ASSERT_TRUE (prepareEncDecParam (pInput));
+ while (iIdx++ < iTotalFrameNum) { // loop in frame
+ EncodeOneFrame();
+#ifdef DEBUG_FILE_SAVE_CRA
+ //reset file if file size large
+ if ((info.eFrameType == videoFrameTypeIDR) && (iFileSize >= (1 << 25))) {
+ fclose (fDataFile);
+ fDataFile = fopen ("test_crash.264", "wb");
+ iFileSize = 0;
+ decoder_->Uninitialize();
+
+ SDecodingParam decParam;
+ memset (&decParam, 0, sizeof (SDecodingParam));
+ decParam.uiTargetDqLayer = UCHAR_MAX;
+ decParam.eEcActiveIdc = ERROR_CON_SLICE_COPY;
+ decParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT;
+
+ rv = decoder_->Initialize (&decParam);
+ ASSERT_EQ (0, rv);
+ }
+#endif
+ if (info.eFrameType == videoFrameTypeSkip)
+ continue;
+ //deal with packets
+ unsigned char* pBsBuf;
+ iDecAuSize = 0;
+ pucBuf = ucBuf_; //init buf start pos for decoder usage
+ for (int iLayerNum = 0; iLayerNum < info.iLayerNum; iLayerNum++) {
+ SLayerBSInfo* pLayerBsInfo = &info.sLayerInfo[iLayerNum];
+ pBsBuf = info.sLayerInfo[iLayerNum].pBsBuf;
+ int iTotalNalCnt = pLayerBsInfo->iNalCount;
+ for (int iNalCnt = 0; iNalCnt < iTotalNalCnt; iNalCnt++) { //loop in NAL
+ int iPacketSize = pLayerBsInfo->pNalLengthInByte[iNalCnt];
+ //packet loss
+ int iLossRateRange = (uiLoopRound % 100) + 1; //1-100
+ int iLossRate = (rand() % iLossRateRange);
+ bool bPacketLost = (rand() % 101) > (100 -
+ iLossRate); // [0, (100-iLossRate)] indicates NO LOSS, (100-iLossRate, 100] indicates LOSS
+ if (!bPacketLost) { //no loss
+ memcpy (pucBuf, pBsBuf, iPacketSize);
+ pucBuf += iPacketSize;
+ iDecAuSize += iPacketSize;
+ }
+#ifdef DEBUG_FILE_SAVE_CRA
+ else {
+ printf ("lost packet size=%d at frame-type=%d at loss rate %d (%d)\n", iPacketSize, info.eFrameType, iLossRate,
+ iLossRateRange);
+ }
+#endif
+ //update bs info
+ pBsBuf += iPacketSize;
+ } //nal
+ } //layer
+
+#ifdef DEBUG_FILE_SAVE_CRA
+ //save to file
+ fwrite (ucBuf_, 1, iDecAuSize, fDataFile);
+ fflush (fDataFile);
+ iFileSize += iDecAuSize;
+
+ //save to len file
+ unsigned long ulTmp[4];
+ ulTmp[0] = ulTmp[1] = ulTmp[2] = iIdx;
+ ulTmp[3] = iDecAuSize;
+ fwrite (ulTmp, sizeof (unsigned long), 4, fLenFile); // index, timeStamp, data size
+ fflush (fLenFile);
+#endif
+
+ //decode
+ pData[0] = pData[1] = pData[2] = 0;
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+
+ rv = decoder_->DecodeFrame2 (ucBuf_, iDecAuSize, pData, &dstBufInfo_);
+ rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
+ //guarantee decoder EC status
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_SLICE_COPY);
+ } //frame
+ uiLoopRound ++;
+ if (uiLoopRound >= (1 << 30))
+ uiLoopRound = 0;
+#ifdef DEBUG_FILE_SAVE_CRA
+ if (uiLoopRound % 100 == 0)
+ printf ("run %d times.\n", uiLoopRound);
+ } while (1); //while (iLoopRound<100);
+ fclose (fDataFile);
+ fclose (fLenFile);
+#else
+ }
+ while (uiLoopRound < 10);
+#endif
+
+}
+
+const uint32_t kiTotalLayer = 3; //DO NOT CHANGE!
+const uint32_t kiSliceNum = 2; //DO NOT CHANGE!
+const uint32_t kiWidth = 160; //DO NOT CHANGE!
+const uint32_t kiHeight = 96; //DO NOT CHANGE!
+const uint32_t kiFrameRate = 12; //DO NOT CHANGE!
+const uint32_t kiFrameNum = 100; //DO NOT CHANGE!
+const char* const pHashStr[][2] = { //DO NOT CHANGE!
+ // Allow for different output depending on whether averaging is done
+ // vertically or horizontally first when downsampling.
+ { "caaaa3352ab8614e3a35836f5d7c9a528294e953", "326cc236e9ba5277aedc5cf0865dd4cbd2f89fe0" },
+ { "2dc97661e94515d9947a344127062f82814afc2a", "72f36bb33d190979be88077c6166a09767dd2992" },
+ { "106ec96a90412aabea5c0cfa6bfc654a0b5db33e", "998c2947bccf140bde1e43e29376614038eb7c71" }
+};
+
+class DecodeParseAPI : public ::testing::TestWithParam<EncodeDecodeFileParamBase>, public EncodeDecodeTestBase {
+ public:
+ DecodeParseAPI() {
+ memset (&BsInfo_, 0, sizeof (SParserBsInfo));
+ fYuv_ = NULL;
+ iWidth_ = 0;
+ iHeight_ = 0;
+ memset (&ctx_, 0, sizeof (SHA1Context));
+ }
+ void SetUp() {
+ SHA1Reset (&ctx_);
+ EncodeDecodeTestBase::SetUp();
+
+ if (decoder_)
+ decoder_->Uninitialize();
+ SDecodingParam decParam;
+ memset (&decParam, 0, sizeof (SDecodingParam));
+ decParam.uiTargetDqLayer = UCHAR_MAX;
+ decParam.eEcActiveIdc = ERROR_CON_SLICE_COPY;
+ decParam.bParseOnly = true;
+ decParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT;
+
+ int rv = decoder_->Initialize (&decParam);
+ ASSERT_EQ (0, rv);
+ memset (&BsInfo_, 0, sizeof (SParserBsInfo));
+ const char* sFileName = "res/CiscoVT2people_160x96_6fps.yuv";
+#if defined(ANDROID_NDK)
+ std::string filename = std::string ("/sdcard/") + sFileName;
+ ASSERT_TRUE ((fYuv_ = fopen (filename.c_str(), "rb")) != NULL);
+#else
+ ASSERT_TRUE ((fYuv_ = fopen (sFileName, "rb")) != NULL);
+#endif
+ iWidth_ = kiWidth;
+ iHeight_ = kiHeight;
+ }
+ void TearDown() {
+ EncodeDecodeTestBase::TearDown();
+ if (fYuv_ != NULL) {
+ fclose (fYuv_);
+ fYuv_ = NULL;
+ }
+ }
+
+ bool prepareEncDecParam (const EncodeDecodeFileParamBase p) {
+ if (!EncodeDecodeTestBase::prepareEncDecParam (p))
+ return false;
+ unsigned char* pTmpPtr = BsInfo_.pDstBuff; //store for restore
+ memset (&BsInfo_, 0, sizeof (SParserBsInfo));
+ BsInfo_.pDstBuff = pTmpPtr;
+ return true;
+ }
+
+ void MockInputData (uint8_t* pData, int32_t iSize) {
+ int32_t iCurr = 0;
+ while (iCurr < iSize) {
+ * (pData + iCurr) = (* (pData + iCurr) + (rand() % 20) + 256) & 0x00ff;
+ iCurr++;
+ }
+ }
+
+ void EncodeOneFrame (bool bMock) {
+ int iFrameSize = iWidth_ * iHeight_ * 3 / 2;
+ int iSize = (int) fread (buf_.data(), sizeof (char), iFrameSize, fYuv_);
+ if (feof (fYuv_) || iSize != iFrameSize) {
+ rewind (fYuv_);
+ iSize = (int) fread (buf_.data(), sizeof (char), iFrameSize, fYuv_);
+ ASSERT_TRUE (iSize == iFrameSize);
+ }
+ if (bMock) {
+ MockInputData (buf_.data(), iWidth_ * iHeight_);
+ }
+ int rv = encoder_->EncodeFrame (&EncPic, &info);
+ ASSERT_TRUE (rv == cmResultSuccess || rv == cmUnknownReason);
+ }
+
+ void prepareParam (int iLayerNum, int iSliceNum, int width, int height, float framerate, SEncParamExt* pParam) {
+ memset (pParam, 0, sizeof (SEncParamExt));
+ EncodeDecodeTestBase::prepareParam (iLayerNum, iSliceNum, width, height, framerate, pParam);
+ }
+
+ protected:
+ SParserBsInfo BsInfo_;
+ FILE* fYuv_;
+ int iWidth_;
+ int iHeight_;
+ SHA1Context ctx_;
+};
+
+//#define DEBUG_FILE_SAVE_PARSEONLY_GENERAL
+TEST_F (DecodeParseAPI, ParseOnly_General) {
+ EncodeDecodeFileParamBase p;
+ p.width = iWidth_;
+ p.height = iHeight_;
+ p.frameRate = kiFrameRate;
+ p.numframes = kiFrameNum;
+ prepareParam (kiTotalLayer, kiSliceNum, p.width, p.height, p.frameRate, ¶m_);
+ param_.iSpatialLayerNum = kiTotalLayer;
+ encoder_->Uninitialize();
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == 0);
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ uint32_t uiTargetLayerId = rand() % kiTotalLayer; //run only once
+#ifdef DEBUG_FILE_SAVE_PARSEONLY_GENERAL
+ FILE* fDec = fopen ("output.264", "wb");
+ FILE* fEnc = fopen ("enc.264", "wb");
+ FILE* fExtract = fopen ("extract.264", "wb");
+#endif
+ if (uiTargetLayerId < kiTotalLayer) { //should always be true
+ //Start for enc
+ int iLen = 0;
+ ASSERT_TRUE (prepareEncDecParam (p));
+ int iFrame = 0;
+
+ while (iFrame < p.numframes) {
+ //encode
+ EncodeOneFrame (0);
+ //extract target layer data
+ encToDecData (info, iLen);
+#ifdef DEBUG_FILE_SAVE_PARSEONLY_GENERAL
+ fwrite (info.sLayerInfo[0].pBsBuf, iLen, 1, fEnc);
+#endif
+ ExtractDidNal (&info, iLen, &m_SLostSim, uiTargetLayerId);
+#ifdef DEBUG_FILE_SAVE_PARSEONLY_GENERAL
+ fwrite (info.sLayerInfo[0].pBsBuf, iLen, 1, fExtract);
+#endif
+ //parseonly
+ //BsInfo_.pDstBuff = new unsigned char [1000000];
+ rv = decoder_->DecodeParser (info.sLayerInfo[0].pBsBuf, iLen, &BsInfo_);
+ EXPECT_TRUE (rv == 0);
+ EXPECT_TRUE (BsInfo_.iNalNum == 0);
+ rv = decoder_->DecodeParser (NULL, 0, &BsInfo_);
+ EXPECT_TRUE (rv == 0);
+ EXPECT_TRUE (BsInfo_.iNalNum != 0);
+ //get final output bs
+ iLen = 0;
+ int i = 0;
+ while (i < BsInfo_.iNalNum) {
+ iLen += BsInfo_.pNalLenInByte[i];
+ i++;
+ }
+#ifdef DEBUG_FILE_SAVE_PARSEONLY_GENERAL
+ fwrite (BsInfo_.pDstBuff, iLen, 1, fDec);
+#endif
+ SHA1Input (&ctx_, BsInfo_.pDstBuff, iLen);
+ iFrame++;
+ }
+ //calculate final SHA1 value
+ unsigned char digest[SHA_DIGEST_LENGTH];
+ SHA1Result (&ctx_, digest);
+ if (!HasFatalFailure()) {
+ CompareHashAnyOf (digest, pHashStr[uiTargetLayerId], sizeof * pHashStr / sizeof** pHashStr);
+ }
+ } //while
+#ifdef DEBUG_FILE_SAVE_PARSEONLY_GENERAL
+ fclose (fEnc);
+ fclose (fExtract);
+ fclose (fDec);
+#endif
+}
+
+//This case is for one layer only, for incomplete frame input
+//First slice is loss for random one picture with 2 slices per pic
+TEST_F (DecodeParseAPI, ParseOnly_SpecSliceLoss) {
+ int32_t iLayerNum = 1;
+ int32_t iSliceNum = 2;
+ EncodeDecodeFileParamBase p;
+ p.width = iWidth_;
+ p.height = iHeight_;
+ p.frameRate = kiFrameRate;
+ p.numframes = 5;
+ prepareParam (iLayerNum, iSliceNum, p.width, p.height, p.frameRate, ¶m_);
+ param_.iSpatialLayerNum = iLayerNum;
+ encoder_->Uninitialize();
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == 0);
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+
+ int32_t iMissedPicNum = rand() % (p.numframes - 1) + 1; //IDR no loss
+ //Start for enc
+ int iLen = 0;
+ uint32_t uiGet;
+ ASSERT_TRUE (prepareEncDecParam (p));
+ int iFrame = 0;
+
+ while (iFrame < p.numframes) {
+ //encode
+ EncodeOneFrame (0);
+ //parseonly
+ if (iFrame == iMissedPicNum) { //make current frame partly missing
+ //Frame: P, first slice loss
+ int32_t iTotalSliceSize = 0;
+ encToDecSliceData (0, 0, info, iTotalSliceSize); //slice 1 lost
+ encToDecSliceData (0, 1, info, iLen); //slice 2
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_DISABLE);
+ rv = decoder_->DecodeParser (info.sLayerInfo[0].pBsBuf + iTotalSliceSize, iLen, &BsInfo_);
+ EXPECT_TRUE (rv == 0);
+ EXPECT_TRUE (BsInfo_.iNalNum == 0);
+ rv = decoder_->DecodeParser (NULL, 0, &BsInfo_);
+ EXPECT_TRUE (rv != 0);
+ } else { //normal frame, complete
+ encToDecData (info, iLen);
+ rv = decoder_->DecodeParser (info.sLayerInfo[0].pBsBuf, iLen, &BsInfo_);
+ EXPECT_TRUE (rv == 0); //parse correct
+ EXPECT_TRUE (BsInfo_.iNalNum == 0);
+ rv = decoder_->DecodeParser (NULL, 0, &BsInfo_);
+ if (iFrame < iMissedPicNum) { //correct frames, all OK with output
+ EXPECT_TRUE (rv == 0);
+ EXPECT_TRUE (BsInfo_.iNalNum != 0);
+ } else { //(iFrame > iMissedPicNum), should output nothing as error
+ EXPECT_TRUE (rv != 0);
+ EXPECT_TRUE (BsInfo_.iNalNum == 0);
+ }
+ }
+ iFrame++;
+ } //while
+}
+
+TEST_F (DecodeParseAPI, ParseOnly_SpecStatistics) {
+ //set params
+ int32_t iLayerNum = 1;
+ int32_t iSliceNum = 1;
+ EncodeDecodeFileParamBase p;
+ const int iLoopNum = 10;
+ p.frameRate = kiFrameRate;
+ p.numframes = 2; //encode 2 frames in each test
+ p.width = iWidth_ = 16;
+ p.height = iHeight_ = 16; //default start width/height = 16, will be modified each time
+ int iTotalFrmCnt = 0;
+ for (int i = 0; i < iLoopNum; ++i) {
+ prepareParam (iLayerNum, iSliceNum, p.width, p.height, p.frameRate, ¶m_);
+ param_.iSpatialLayerNum = iLayerNum;
+ param_.sSpatialLayers[0].iDLayerQp = 40; //to revent size too limited to encoding fail
+ encoder_->Uninitialize();
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == 0);
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ rv = encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ ASSERT_TRUE (rv == 0);
+ rv = decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ ASSERT_TRUE (rv == 0);
+ //Start for enc
+ int iLen = 0;
+ ASSERT_TRUE (prepareEncDecParam (p));
+ int iFrame = 0;
+ while (iFrame < p.numframes) {
+ EncodeOneFrame (0);
+ encToDecData (info, iLen);
+ iFrame++;
+ iTotalFrmCnt++;
+ rv = decoder_->DecodeParser (info.sLayerInfo[0].pBsBuf, iLen, &BsInfo_);
+ ASSERT_TRUE (rv == 0);
+ ASSERT_TRUE (BsInfo_.iNalNum == 0);
+ rv = decoder_->DecodeParser (NULL, 0, &BsInfo_);
+ ASSERT_TRUE (rv == 0);
+ ASSERT_TRUE (BsInfo_.iNalNum != 0);
+ SDecoderStatistics sDecStat;
+ rv = decoder_->GetOption (DECODER_OPTION_GET_STATISTICS, &sDecStat);
+ ASSERT_TRUE (rv == 0);
+ uint32_t uiProfile, uiLevel;
+ rv = decoder_->GetOption (DECODER_OPTION_PROFILE, &uiProfile);
+ ASSERT_TRUE (rv == 0);
+ rv = decoder_->GetOption (DECODER_OPTION_LEVEL, &uiLevel);
+ ASSERT_TRUE (rv == 0);
+
+ ASSERT_EQ (sDecStat.uiWidth, (unsigned int) p.width);
+ ASSERT_EQ (sDecStat.uiHeight, (unsigned int) p.height);
+ ASSERT_EQ (sDecStat.uiResolutionChangeTimes, (unsigned int) (i + 1));
+ EXPECT_EQ (sDecStat.iCurrentActiveSpsId, 0);
+ EXPECT_EQ (sDecStat.iCurrentActivePpsId, 0);
+ ASSERT_EQ (sDecStat.uiDecodedFrameCount, (unsigned int) iTotalFrmCnt);
+ ASSERT_EQ (sDecStat.uiProfile, uiProfile);
+ ASSERT_EQ (sDecStat.uiLevel, uiLevel);
+ EXPECT_TRUE (sDecStat.fActualAverageFrameSpeedInMs != 0.);
+ EXPECT_TRUE (sDecStat.fAverageFrameSpeedInMs != 0.);
+ EXPECT_TRUE (sDecStat.iAvgLumaQp != 0);
+ EXPECT_EQ (sDecStat.uiIDRCorrectNum, (unsigned int) (i + 1));
+ }
+ //set next width & height
+ p.width += 16;
+ p.height += 16;
+ if ((unsigned int) p.width > kiWidth) //exceeds max frame size
+ p.width = 16;
+ if ((unsigned int) p.height > kiHeight)
+ p.height = 16;
+ iWidth_ = p.width;
+ iHeight_ = p.height;
+ }
+}
+
+
+//Test parseonly crash cases
+class DecodeParseCrashAPI : public DecodeParseAPI {
+ public:
+ DecodeParseCrashAPI() {
+ }
+ void SetUp() {
+ DecodeParseAPI::SetUp();
+ iWidth_ = 1280;
+ iHeight_ = 720;
+
+ ucBuf_ = NULL;
+ ucBuf_ = new unsigned char[1000000];
+ ASSERT_TRUE (ucBuf_ != NULL);
+
+ }
+ void TearDown() {
+ DecodeParseAPI::TearDown();
+ if (NULL != ucBuf_) {
+ delete[] ucBuf_;
+ ucBuf_ = NULL;
+ }
+ ASSERT_TRUE (ucBuf_ == NULL);
+ }
+
+ protected:
+ unsigned char* ucBuf_;
+};
+
+//#define DEBUG_FILE_SAVE_PARSE_CRA1
+TEST_F (DecodeParseCrashAPI, ParseOnlyCrash_General) {
+ if (fYuv_)
+ fclose (fYuv_);
+ const char* sFileName = "res/Cisco_Absolute_Power_1280x720_30fps.yuv";
+#if defined(ANDROID_NDK)
+ std::string filename = std::string ("/sdcard/") + sFileName;
+ ASSERT_TRUE ((fYuv_ = fopen (filename.c_str(), "rb")) != NULL);
+#else
+ ASSERT_TRUE ((fYuv_ = fopen (sFileName, "rb")) != NULL);
+#endif
+ uint32_t uiGet;
+ encoder_->Uninitialize();
+ //do tests until crash
+ unsigned int uiLoopRound = 0;
+ unsigned char* pucBuf = ucBuf_;
+ int iDecAuSize;
+#ifdef DEBUG_FILE_SAVE_PARSE_CRA1
+ //open file to save tested BS
+ FILE* fDataFile = fopen ("test_parseonly_crash.264", "wb");
+ FILE* fLenFile = fopen ("test_parseonly_crash_len.log", "w");
+ int iFileSize = 0;
+#endif
+
+ do {
+#ifdef DEBUG_FILE_SAVE_PARSE_CRA1
+ int iTotalFrameNum = (rand() % 1200) + 1;
+#else
+ int iTotalFrameNum = (rand() % 100) + 1;
+#endif
+ EncodeDecodeParamBase p = kParamArray[8]; //720p by default
+
+ //Initialize Encoder
+ prepareParam (1, 4, p.width, p.height, p.frameRate, ¶m_);
+ param_.iRCMode = RC_TIMESTAMP_MODE;
+ param_.iTargetBitrate = p.iTarBitrate;
+ param_.uiIntraPeriod = 0;
+ param_.eSpsPpsIdStrategy = CONSTANT_ID;
+ param_.bEnableBackgroundDetection = true;
+ param_.bEnableSceneChangeDetect = (rand() % 3) ? true : false;
+ param_.bPrefixNalAddingCtrl = 0;// (rand() % 2) ? true : false;
+ param_.iEntropyCodingModeFlag = 0;
+ param_.bEnableFrameSkip = true;
+ param_.iMultipleThreadIdc = 0;
+ param_.sSpatialLayers[0].iSpatialBitrate = p.iTarBitrate;
+ param_.sSpatialLayers[0].iMaxSpatialBitrate = p.iTarBitrate << 1;
+ param_.sSpatialLayers[0].sSliceArgument.uiSliceMode =
+ SM_FIXEDSLCNUM_SLICE; // (rand() % 2) ? SM_SIZELIMITED_SLICE : SM_SINGLE_SLICE;
+ if (param_.sSpatialLayers[0].sSliceArgument.uiSliceMode == SM_SIZELIMITED_SLICE) {
+ param_.sSpatialLayers[0].sSliceArgument.uiSliceSizeConstraint = 1400;
+ param_.uiMaxNalSize = 1400;
+ } else {
+ param_.sSpatialLayers[0].sSliceArgument.uiSliceSizeConstraint = 0;
+ param_.uiMaxNalSize = 0;
+ }
+
+ int rv = encoder_->InitializeExt (¶m_);
+ ASSERT_TRUE (rv == cmResultSuccess);
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, (uint32_t)ERROR_CON_DISABLE); //default value should be ERROR_CON_SLICE_COPY
+ int32_t iTraceLevel = WELS_LOG_QUIET;
+ encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+ decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
+
+ //Start for enc/dec
+ int iIdx = 0;
+ unsigned char* pData[3] = { NULL };
+
+ EncodeDecodeFileParamBase pInput; //to conform with old functions
+ pInput.width = p.width;
+ pInput.height = p.height;
+ pInput.frameRate = p.frameRate;
+ prepareEncDecParam (pInput);
+ while (iIdx++ < iTotalFrameNum) { // loop in frame
+ EncodeOneFrame (1);
+#ifdef DEBUG_FILE_SAVE_PARSE_CRA1
+ //reset file if file size large
+ if ((info.eFrameType == videoFrameTypeIDR) && (iFileSize >= (1 << 25))) {
+ fclose (fDataFile);
+ fclose (fLenFile);
+ fDataFile = fopen ("test_parseonly_crash.264", "wb");
+ fLenFile = fopen ("test_parseonly_crash_len.log", "w");
+ iFileSize = 0;
+ decoder_->Uninitialize();
+
+ SDecodingParam decParam;
+ memset (&decParam, 0, sizeof (SDecodingParam));
+ decParam.uiTargetDqLayer = UCHAR_MAX;
+ decParam.eEcActiveIdc = ERROR_CON_DISABLE;
+ decParam.bParseOnly = true;
+ decParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT;
+
+ rv = decoder_->Initialize (&decParam);
+ ASSERT_EQ (0, rv);
+ }
+#endif
+ if (info.eFrameType == videoFrameTypeSkip)
+ continue;
+ //deal with packets
+ unsigned char* pBsBuf;
+ iDecAuSize = 0;
+ pucBuf = ucBuf_; //init buf start pos for decoder usage
+ for (int iLayerNum = 0; iLayerNum < info.iLayerNum; iLayerNum++) {
+ SLayerBSInfo* pLayerBsInfo = &info.sLayerInfo[iLayerNum];
+ pBsBuf = info.sLayerInfo[iLayerNum].pBsBuf;
+ int iTotalNalCnt = pLayerBsInfo->iNalCount;
+ for (int iNalCnt = 0; iNalCnt < iTotalNalCnt; iNalCnt++) { //loop in NAL
+ int iPacketSize = pLayerBsInfo->pNalLengthInByte[iNalCnt];
+ //packet loss
+ int iLossRateRange = (uiLoopRound % 20) + 1; //1-100
+ int iLossRate = (rand() % iLossRateRange);
+ bool bPacketLost = (rand() % 101) > (100 -
+ iLossRate); // [0, (100-iLossRate)] indicates NO LOSS, (100-iLossRate, 100] indicates LOSS
+ if (!bPacketLost) { //no loss
+ memcpy (pucBuf, pBsBuf, iPacketSize);
+ pucBuf += iPacketSize;
+ iDecAuSize += iPacketSize;
+ }
+ //update bs info
+ pBsBuf += iPacketSize;
+ } //nal
+ } //layer
+
+#ifdef DEBUG_FILE_SAVE_PARSE_CRA1
+ //save to file
+ if (iDecAuSize != 0) {
+ fwrite (ucBuf_, 1, iDecAuSize, fDataFile);
+ fflush (fDataFile);
+ iFileSize += iDecAuSize;
+ }
+
+ //save to len file
+ unsigned long ulTmp[4];
+ ulTmp[0] = ulTmp[1] = ulTmp[2] = iIdx;
+ ulTmp[3] = iDecAuSize;
+ fwrite (ulTmp, sizeof (unsigned long), 4, fLenFile); // index, timeStamp, data size
+ fflush (fLenFile);
+#endif
+
+ //decode
+ pData[0] = pData[1] = pData[2] = 0;
+ memset (&BsInfo_, 0, sizeof (SParserBsInfo));
+
+ rv = decoder_->DecodeParser (ucBuf_, iDecAuSize, &BsInfo_);
+ rv = decoder_->DecodeParser (NULL, 0, &BsInfo_); //reconstruction
+ //guarantee decoder EC status
+ decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
+ EXPECT_EQ (uiGet, (uint32_t)ERROR_CON_DISABLE);
+ } //frame
+ uiLoopRound++;
+ if (uiLoopRound >= (1 << 30))
+ uiLoopRound = 0;
+#ifdef DEBUG_FILE_SAVE_PARSE_CRA1
+ if (uiLoopRound % 10 == 0)
+ printf ("run %d times.\n", uiLoopRound);
+ } while (1);
+ fclose (fDataFile);
+ fclose (fLenFile);
+#else
+ }
+ while (0);
+#endif
+
+}
+
--- a/test/api/decoder_test.cpp
+++ b/test/api/decoder_test.cpp
@@ -1,140 +1,140 @@
-#include <gtest/gtest.h>
-#include "utils/HashFunctions.h"
-#include "BaseDecoderTest.h"
-#include <string>
-
-static void UpdateHashFromPlane (SHA1Context* ctx, const uint8_t* plane,
- int width, int height, int stride) {
- for (int i = 0; i < height; i++) {
- SHA1Input (ctx, plane, width);
- plane += stride;
- }
-}
-
-class DecoderCapabilityTest : public ::testing::Test {
- public:
- virtual void SetUp() {}
- virtual void TearDown() {}
-};
-
-TEST_F (DecoderCapabilityTest, JustInit) {
- SDecoderCapability sDecCap;
- int iRet = WelsGetDecoderCapability (&sDecCap);
- ASSERT_TRUE (iRet == 0);
- EXPECT_EQ (sDecCap.iProfileIdc, 66);
- EXPECT_EQ (sDecCap.iProfileIop, 0xE0);
- EXPECT_EQ (sDecCap.iLevelIdc, 32);
- EXPECT_EQ (sDecCap.iMaxMbps, 216000);
- EXPECT_EQ (sDecCap.iMaxFs, 5120);
- EXPECT_EQ (sDecCap.iMaxCpb, 20000);
- EXPECT_EQ (sDecCap.iMaxDpb, 20480);
- EXPECT_EQ (sDecCap.iMaxBr, 20000);
- EXPECT_EQ (sDecCap.bRedPicCap, false);
-}
-
-
-class DecoderInitTest : public ::testing::Test, public BaseDecoderTest {
- public:
- virtual void SetUp() {
- BaseDecoderTest::SetUp();
- }
- virtual void TearDown() {
- BaseDecoderTest::TearDown();
- }
-};
-
-TEST_F (DecoderInitTest, JustInit) {}
-
-struct FileParam {
- const char* fileName;
- const char* hashStr;
-};
-
-class DecoderOutputTest : public ::testing::WithParamInterface<FileParam>,
- public DecoderInitTest, public BaseDecoderTest::Callback {
- public:
- virtual void SetUp() {
- DecoderInitTest::SetUp();
- if (HasFatalFailure()) {
- return;
- }
- SHA1Reset (&ctx_);
- }
- virtual void onDecodeFrame (const Frame& frame) {
- const Plane& y = frame.y;
- const Plane& u = frame.u;
- const Plane& v = frame.v;
- UpdateHashFromPlane (&ctx_, y.data, y.width, y.height, y.stride);
- UpdateHashFromPlane (&ctx_, u.data, u.width, u.height, u.stride);
- UpdateHashFromPlane (&ctx_, v.data, v.width, v.height, v.stride);
- }
- protected:
- SHA1Context ctx_;
-};
-
-TEST_P (DecoderOutputTest, CompareOutput) {
- FileParam p = GetParam();
-#if defined(ANDROID_NDK)
- std::string filename = std::string ("/sdcard/") + p.fileName;
- DecodeFile (filename.c_str(), this);
-#else
- DecodeFile (p.fileName, this);
-#endif
-
- unsigned char digest[SHA_DIGEST_LENGTH];
- SHA1Result (&ctx_, digest);
- if (!HasFatalFailure()) {
- CompareHash (digest, p.hashStr);
- }
-}
-static const FileParam kFileParamArray[] = {
- {"res/Adobe_PDF_sample_a_1024x768_50Frms.264", "9aa9a4d9598eb3e1093311826844f37c43e4c521"},
- {"res/BA1_FT_C.264", "418d152fb85709b6f172799dcb239038df437cfa"},
- {"res/BA1_Sony_D.jsv", "d94b5ceed5686a03ea682b53d415dee999d27eb6"},
- {"res/BAMQ1_JVC_C.264", "613cf662c23e5d9e1d7da7fe880a3c427411d171"},
- {"res/BAMQ2_JVC_C.264", "11bcf3713f520e606a8326d37e00e5fd6c9fd4a0"},
- {"res/BA_MW_D.264", "afd7a9765961ca241bb4bdf344b31397bec7465a"},
- {"res/BANM_MW_D.264", "92d924a857a1a7d7d9b224eaa3887830f15dee7f"},
- {"res/BASQP1_Sony_C.jsv", "3986c8c9d2876d2f0748b925101b152c6ec8b811"},
- {"res/CI1_FT_B.264", "cbfec15e17a504678b19a1191992131c92a1ac26"},
- {"res/CI_MW_D.264", "289f29a103c8d95adf2909c646466904be8b06d7"},
- {"res/CVFC1_Sony_C.jsv", "4641abd7419a5580b97f16e83fd1d566339229d0"},
- {"res/CVPCMNL1_SVA_C.264", "c2b0d964de727c64b9fccb58f63b567c82bda95a"},
- {"res/LS_SVA_D.264", "72118f4d1674cf14e58bed7e67cb3aeed3df62b9"},
- {"res/MIDR_MW_D.264", "9467030f4786f75644bf06a7fc809c36d1959827"},
- {"res/MPS_MW_A.264", "67f1cfbef0e8025ed60dedccf8d9558d0636be5f"},
- {"res/MR1_BT_A.h264", "6e585f8359667a16b03e5f49a06f5ceae8d991e0"},
- {"res/MR1_MW_A.264", "d9e2bf34e9314dcc171ddaea2c5015d0421479f2"},
- {"res/MR2_MW_A.264", "628b1d4eff04c2d277f7144e23484957dad63cbe"},
- {"res/MR2_TANDBERG_E.264", "74d618bc7d9d41998edf4c85d51aa06111db6609"},
- {"res/NL1_Sony_D.jsv", "e401e30669938443c2f02522fd4d5aa1382931a0"},
- {"res/NLMQ1_JVC_C.264", "f3265c6ddf8db1b2bf604d8a2954f75532e28cda"},
- {"res/NLMQ2_JVC_C.264", "350ae86ef9ba09390d63a09b7f9ff54184109ca8"},
- {"res/NRF_MW_E.264", "20732198c04cd2591350a361e4510892f6eed3f0"},
- {"res/QCIF_2P_I_allIPCM.264", "8724c0866ebdba7ebb7209a0c0c3ae3ae38a0240"},
- {"res/SVA_BA1_B.264", "c4543b24823b16c424c673616c36c7f537089b2d"},
- {"res/SVA_BA2_D.264", "98ff2d67860462d8d8bcc9352097c06cc401d97e"},
- {"res/SVA_Base_B.264", "91f514d81cd33de9f6fbf5dbefdb189cc2e7ecf4"},
- {"res/SVA_CL1_E.264", "4fe09ab6cdc965ea10a20f1d6dd38aca954412bb"},
- {"res/SVA_FM1_E.264", "fad08c4ff7cf2307b6579853d0f4652fc26645d3"},
- {"res/SVA_NL1_B.264", "6d63f72a0c0d833b1db0ba438afff3b4180fb3e6"},
- {"res/SVA_NL2_E.264", "70453ef8097c94dd190d6d2d1d5cb83c67e66238"},
- {"res/SarVui.264", "98ff2d67860462d8d8bcc9352097c06cc401d97e"},
- {"res/Static.264", "91dd4a7a796805b2cd015cae8fd630d96c663f42"},
- {"res/Zhling_1280x720.264", "ad99f5eaa2d73ae3840e7da67313de8cfc866ce6"},
- {"res/sps_subsetsps_bothVUI.264", "d3a47032eb5dcc1963343a68e9bea12435bf1e4c"},
- {"res/test_cif_I_CABAC_PCM.264", "95fdf21470d3bbcf95505abb2164042063a79d98"},
- {"res/test_cif_I_CABAC_slice.264", "19121bc67f2b13fb8f030504fc0827e1ac6d0fdb"},
- {"res/test_cif_P_CABAC_slice.264", "521bbd0ba2422369b724c7054545cf107a56f959"},
- {"res/test_qcif_cabac.264", "587d1d05943f3cd416bf69469975fdee05361e69"},
- {"res/test_scalinglist_jm.264", "f690a3af2896a53360215fb5d35016bfd41499b3"},
- {"res/test_vd_1d.264", "5827d2338b79ff82cd091c707823e466197281d3"},
- {"res/test_vd_rc.264", "eea02e97bfec89d0418593a8abaaf55d02eaa1ca"},
- {"res/HighProfile_B_Frame_1920x1080p_30fps.h264", "50c5b8d175598c1d9e604542c4160fa1c6639adc"},
- {"res/HighProfile_B_Frame_1920x1080p_2397fps.h264", "16967cc21b6853b651cfd0a1a858eeec8565836a"},
- {"res/HighProfile_B_Frame_1280x544_2397p.h264", "8567f85b1162b70bb2ccc49fd16d8aa27523efcf"},
- {"res/HighProfile_B_Frame_1280x720_2397p.h264", "5a3176bd9bc1af2a5d58e880088434ee57c57602"},
-};
-
-INSTANTIATE_TEST_CASE_P (DecodeFile, DecoderOutputTest,
- ::testing::ValuesIn (kFileParamArray));
+#include <gtest/gtest.h>
+#include "utils/HashFunctions.h"
+#include "BaseDecoderTest.h"
+#include <string>
+
+static void UpdateHashFromPlane (SHA1Context* ctx, const uint8_t* plane,
+ int width, int height, int stride) {
+ for (int i = 0; i < height; i++) {
+ SHA1Input (ctx, plane, width);
+ plane += stride;
+ }
+}
+
+class DecoderCapabilityTest : public ::testing::Test {
+ public:
+ virtual void SetUp() {}
+ virtual void TearDown() {}
+};
+
+TEST_F (DecoderCapabilityTest, JustInit) {
+ SDecoderCapability sDecCap;
+ int iRet = WelsGetDecoderCapability (&sDecCap);
+ ASSERT_TRUE (iRet == 0);
+ EXPECT_EQ (sDecCap.iProfileIdc, 66);
+ EXPECT_EQ (sDecCap.iProfileIop, 0xE0);
+ EXPECT_EQ (sDecCap.iLevelIdc, 32);
+ EXPECT_EQ (sDecCap.iMaxMbps, 216000);
+ EXPECT_EQ (sDecCap.iMaxFs, 5120);
+ EXPECT_EQ (sDecCap.iMaxCpb, 20000);
+ EXPECT_EQ (sDecCap.iMaxDpb, 20480);
+ EXPECT_EQ (sDecCap.iMaxBr, 20000);
+ EXPECT_EQ (sDecCap.bRedPicCap, false);
+}
+
+
+class DecoderInitTest : public ::testing::Test, public BaseDecoderTest {
+ public:
+ virtual void SetUp() {
+ BaseDecoderTest::SetUp();
+ }
+ virtual void TearDown() {
+ BaseDecoderTest::TearDown();
+ }
+};
+
+TEST_F (DecoderInitTest, JustInit) {}
+
+struct FileParam {
+ const char* fileName;
+ const char* hashStr;
+};
+
+class DecoderOutputTest : public ::testing::WithParamInterface<FileParam>,
+ public DecoderInitTest, public BaseDecoderTest::Callback {
+ public:
+ virtual void SetUp() {
+ DecoderInitTest::SetUp();
+ if (HasFatalFailure()) {
+ return;
+ }
+ SHA1Reset (&ctx_);
+ }
+ virtual void onDecodeFrame (const Frame& frame) {
+ const Plane& y = frame.y;
+ const Plane& u = frame.u;
+ const Plane& v = frame.v;
+ UpdateHashFromPlane (&ctx_, y.data, y.width, y.height, y.stride);
+ UpdateHashFromPlane (&ctx_, u.data, u.width, u.height, u.stride);
+ UpdateHashFromPlane (&ctx_, v.data, v.width, v.height, v.stride);
+ }
+ protected:
+ SHA1Context ctx_;
+};
+
+TEST_P (DecoderOutputTest, CompareOutput) {
+ FileParam p = GetParam();
+#if defined(ANDROID_NDK)
+ std::string filename = std::string ("/sdcard/") + p.fileName;
+ DecodeFile (filename.c_str(), this);
+#else
+ DecodeFile (p.fileName, this);
+#endif
+
+ unsigned char digest[SHA_DIGEST_LENGTH];
+ SHA1Result (&ctx_, digest);
+ if (!HasFatalFailure()) {
+ CompareHash (digest, p.hashStr);
+ }
+}
+static const FileParam kFileParamArray[] = {
+ {"res/Adobe_PDF_sample_a_1024x768_50Frms.264", "9aa9a4d9598eb3e1093311826844f37c43e4c521"},
+ {"res/BA1_FT_C.264", "418d152fb85709b6f172799dcb239038df437cfa"},
+ {"res/BA1_Sony_D.jsv", "d94b5ceed5686a03ea682b53d415dee999d27eb6"},
+ {"res/BAMQ1_JVC_C.264", "613cf662c23e5d9e1d7da7fe880a3c427411d171"},
+ {"res/BAMQ2_JVC_C.264", "11bcf3713f520e606a8326d37e00e5fd6c9fd4a0"},
+ {"res/BA_MW_D.264", "afd7a9765961ca241bb4bdf344b31397bec7465a"},
+ {"res/BANM_MW_D.264", "92d924a857a1a7d7d9b224eaa3887830f15dee7f"},
+ {"res/BASQP1_Sony_C.jsv", "3986c8c9d2876d2f0748b925101b152c6ec8b811"},
+ {"res/CI1_FT_B.264", "cbfec15e17a504678b19a1191992131c92a1ac26"},
+ {"res/CI_MW_D.264", "289f29a103c8d95adf2909c646466904be8b06d7"},
+ {"res/CVFC1_Sony_C.jsv", "4641abd7419a5580b97f16e83fd1d566339229d0"},
+ {"res/CVPCMNL1_SVA_C.264", "c2b0d964de727c64b9fccb58f63b567c82bda95a"},
+ {"res/LS_SVA_D.264", "72118f4d1674cf14e58bed7e67cb3aeed3df62b9"},
+ {"res/MIDR_MW_D.264", "9467030f4786f75644bf06a7fc809c36d1959827"},
+ {"res/MPS_MW_A.264", "67f1cfbef0e8025ed60dedccf8d9558d0636be5f"},
+ {"res/MR1_BT_A.h264", "6e585f8359667a16b03e5f49a06f5ceae8d991e0"},
+ {"res/MR1_MW_A.264", "d9e2bf34e9314dcc171ddaea2c5015d0421479f2"},
+ {"res/MR2_MW_A.264", "628b1d4eff04c2d277f7144e23484957dad63cbe"},
+ {"res/MR2_TANDBERG_E.264", "74d618bc7d9d41998edf4c85d51aa06111db6609"},
+ {"res/NL1_Sony_D.jsv", "e401e30669938443c2f02522fd4d5aa1382931a0"},
+ {"res/NLMQ1_JVC_C.264", "f3265c6ddf8db1b2bf604d8a2954f75532e28cda"},
+ {"res/NLMQ2_JVC_C.264", "350ae86ef9ba09390d63a09b7f9ff54184109ca8"},
+ {"res/NRF_MW_E.264", "20732198c04cd2591350a361e4510892f6eed3f0"},
+ {"res/QCIF_2P_I_allIPCM.264", "8724c0866ebdba7ebb7209a0c0c3ae3ae38a0240"},
+ {"res/SVA_BA1_B.264", "c4543b24823b16c424c673616c36c7f537089b2d"},
+ {"res/SVA_BA2_D.264", "98ff2d67860462d8d8bcc9352097c06cc401d97e"},
+ {"res/SVA_Base_B.264", "91f514d81cd33de9f6fbf5dbefdb189cc2e7ecf4"},
+ {"res/SVA_CL1_E.264", "4fe09ab6cdc965ea10a20f1d6dd38aca954412bb"},
+ {"res/SVA_FM1_E.264", "fad08c4ff7cf2307b6579853d0f4652fc26645d3"},
+ {"res/SVA_NL1_B.264", "6d63f72a0c0d833b1db0ba438afff3b4180fb3e6"},
+ {"res/SVA_NL2_E.264", "70453ef8097c94dd190d6d2d1d5cb83c67e66238"},
+ {"res/SarVui.264", "98ff2d67860462d8d8bcc9352097c06cc401d97e"},
+ {"res/Static.264", "91dd4a7a796805b2cd015cae8fd630d96c663f42"},
+ {"res/Zhling_1280x720.264", "ad99f5eaa2d73ae3840e7da67313de8cfc866ce6"},
+ {"res/sps_subsetsps_bothVUI.264", "d3a47032eb5dcc1963343a68e9bea12435bf1e4c"},
+ {"res/test_cif_I_CABAC_PCM.264", "95fdf21470d3bbcf95505abb2164042063a79d98"},
+ {"res/test_cif_I_CABAC_slice.264", "19121bc67f2b13fb8f030504fc0827e1ac6d0fdb"},
+ {"res/test_cif_P_CABAC_slice.264", "521bbd0ba2422369b724c7054545cf107a56f959"},
+ {"res/test_qcif_cabac.264", "587d1d05943f3cd416bf69469975fdee05361e69"},
+ {"res/test_scalinglist_jm.264", "f690a3af2896a53360215fb5d35016bfd41499b3"},
+ {"res/test_vd_1d.264", "5827d2338b79ff82cd091c707823e466197281d3"},
+ {"res/test_vd_rc.264", "eea02e97bfec89d0418593a8abaaf55d02eaa1ca"},
+ {"res/HighProfile_B_Frame_1920x1080p_30fps.h264", "50c5b8d175598c1d9e604542c4160fa1c6639adc"},
+ {"res/HighProfile_B_Frame_1920x1080p_2397fps.h264", "16967cc21b6853b651cfd0a1a858eeec8565836a"},
+ {"res/HighProfile_B_Frame_1280x544_2397p.h264", "8567f85b1162b70bb2ccc49fd16d8aa27523efcf"},
+ {"res/HighProfile_B_Frame_1280x720_2397p.h264", "5a3176bd9bc1af2a5d58e880088434ee57c57602"},
+};
+
+INSTANTIATE_TEST_CASE_P (DecodeFile, DecoderOutputTest,
+ ::testing::ValuesIn (kFileParamArray));