2013-12-09 13:51:09 +01:00
|
|
|
/*!
|
|
|
|
* \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 "mem_align.h"
|
|
|
|
#include "utils.h"
|
|
|
|
|
|
|
|
//#include "macros.h"
|
|
|
|
#include "decoder.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>
|
2013-12-15 08:18:19 +01:00
|
|
|
#if defined(_WIN32) /*&& defined(_DEBUG)*/
|
2013-12-09 13:51:09 +01:00
|
|
|
|
|
|
|
#include <windows.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/timeb.h>
|
|
|
|
#else
|
|
|
|
#include <sys/time.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
namespace WelsDec {
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
// Construction/Destruction
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
* Description:
|
2013-12-12 23:21:12 +01:00
|
|
|
* class CWelsDecoder constructor function, do initialization and
|
2013-12-09 13:51:09 +01:00
|
|
|
* alloc memory required
|
|
|
|
*
|
|
|
|
* Input parameters: none
|
|
|
|
*
|
|
|
|
* return: none
|
2013-12-13 21:03:38 +01:00
|
|
|
***************************************************************************/
|
2013-12-12 23:21:12 +01:00
|
|
|
CWelsDecoder::CWelsDecoder (void_t)
|
|
|
|
: m_pDecContext (NULL),
|
|
|
|
m_pTrace (NULL) {
|
2013-12-09 13:51:09 +01:00
|
|
|
#ifdef OUTPUT_BIT_STREAM
|
2013-12-12 23:21:12 +01:00
|
|
|
str_t chFileName[1024] = { 0 }; //for .264
|
|
|
|
int iBufUsed = 0;
|
|
|
|
int iBufLeft = 1023;
|
Fix calculating buffer positions when appending with SNPRINTF/WelsSnprintf
This fixes two separate issues.
First, with the MSVC _snprintf implementations, the return value
is negative if the buffer wasn't large enough - this would in
the worst case lead to making iBufferUsed negative, writing before
the start of the buffer.
Secondly, when both iBufferUsed and iBufferLeft are accumulated,
one can't do "iBufferLeft -= iBufferUsed;". As an example,
say the buffer is 100 bytes in total and iBufferLeft is 40 and
iBufferUsed is 60. If SNPRINTF then writes 5 more bytes to the
buffer, iBufferUsed would be 65, but if we now do
"iBufferLeft -= iBufferUsed;" then iBufferLeft would end up as
-25 even though there's 35 bytes left in the buffer to use.
Therefore, we use a separate variable to store the return value
from the latest SNPRINTF call. This is checked to make sure it
wasn't negative, and only this amount is added to iBufferUsed
and subtracted from iBufferLeft.
This is the same pattern used in codec/encoder/core/src/utils.cpp.
strftime never returns negative numbers, so those calls don't
need as much checking.
2014-01-26 10:35:19 +01:00
|
|
|
int iCurUsed;
|
2013-12-09 13:51:09 +01:00
|
|
|
|
2013-12-12 23:21:12 +01:00
|
|
|
str_t chFileNameSize[1024] = { 0 }; //for .len
|
|
|
|
int iBufUsedSize = 0;
|
|
|
|
int iBufLeftSize = 1023;
|
Fix calculating buffer positions when appending with SNPRINTF/WelsSnprintf
This fixes two separate issues.
First, with the MSVC _snprintf implementations, the return value
is negative if the buffer wasn't large enough - this would in
the worst case lead to making iBufferUsed negative, writing before
the start of the buffer.
Secondly, when both iBufferUsed and iBufferLeft are accumulated,
one can't do "iBufferLeft -= iBufferUsed;". As an example,
say the buffer is 100 bytes in total and iBufferLeft is 40 and
iBufferUsed is 60. If SNPRINTF then writes 5 more bytes to the
buffer, iBufferUsed would be 65, but if we now do
"iBufferLeft -= iBufferUsed;" then iBufferLeft would end up as
-25 even though there's 35 bytes left in the buffer to use.
Therefore, we use a separate variable to store the return value
from the latest SNPRINTF call. This is checked to make sure it
wasn't negative, and only this amount is added to iBufferUsed
and subtracted from iBufferLeft.
This is the same pattern used in codec/encoder/core/src/utils.cpp.
strftime never returns negative numbers, so those calls don't
need as much checking.
2014-01-26 10:35:19 +01:00
|
|
|
int iCurUsedSize;
|
2014-01-05 13:35:37 +01:00
|
|
|
#endif//OUTPUT_BIT_STREAM
|
2013-12-09 13:51:09 +01:00
|
|
|
|
2013-12-12 23:21:12 +01:00
|
|
|
m_pTrace = CreateWelsTrace (Wels_Trace_Type);
|
|
|
|
|
|
|
|
IWelsTrace::WelsVTrace (m_pTrace, IWelsTrace::WELS_LOG_INFO, "CWelsDecoder::CWelsDecoder() entry");
|
2014-01-23 04:01:51 +01:00
|
|
|
XMMREG_PROTECT_INIT(CWelsH264Decoder);
|
2013-12-09 13:51:09 +01:00
|
|
|
|
|
|
|
#ifdef OUTPUT_BIT_STREAM
|
2013-12-12 23:21:12 +01:00
|
|
|
SWelsTime sCurTime;
|
|
|
|
|
|
|
|
WelsGetTimeOfDay (&sCurTime);
|
|
|
|
|
Fix calculating buffer positions when appending with SNPRINTF/WelsSnprintf
This fixes two separate issues.
First, with the MSVC _snprintf implementations, the return value
is negative if the buffer wasn't large enough - this would in
the worst case lead to making iBufferUsed negative, writing before
the start of the buffer.
Secondly, when both iBufferUsed and iBufferLeft are accumulated,
one can't do "iBufferLeft -= iBufferUsed;". As an example,
say the buffer is 100 bytes in total and iBufferLeft is 40 and
iBufferUsed is 60. If SNPRINTF then writes 5 more bytes to the
buffer, iBufferUsed would be 65, but if we now do
"iBufferLeft -= iBufferUsed;" then iBufferLeft would end up as
-25 even though there's 35 bytes left in the buffer to use.
Therefore, we use a separate variable to store the return value
from the latest SNPRINTF call. This is checked to make sure it
wasn't negative, and only this amount is added to iBufferUsed
and subtracted from iBufferLeft.
This is the same pattern used in codec/encoder/core/src/utils.cpp.
strftime never returns negative numbers, so those calls don't
need as much checking.
2014-01-26 10:35:19 +01:00
|
|
|
iCurUsed = WelsSnprintf (chFileName, iBufLeft, "bs_0x%p_", (void_t*)this);
|
|
|
|
iCurUsedSize = WelsSnprintf (chFileNameSize, iBufLeftSize, "size_0x%p_", (void_t*)this);
|
2013-12-12 23:21:12 +01:00
|
|
|
|
Fix calculating buffer positions when appending with SNPRINTF/WelsSnprintf
This fixes two separate issues.
First, with the MSVC _snprintf implementations, the return value
is negative if the buffer wasn't large enough - this would in
the worst case lead to making iBufferUsed negative, writing before
the start of the buffer.
Secondly, when both iBufferUsed and iBufferLeft are accumulated,
one can't do "iBufferLeft -= iBufferUsed;". As an example,
say the buffer is 100 bytes in total and iBufferLeft is 40 and
iBufferUsed is 60. If SNPRINTF then writes 5 more bytes to the
buffer, iBufferUsed would be 65, but if we now do
"iBufferLeft -= iBufferUsed;" then iBufferLeft would end up as
-25 even though there's 35 bytes left in the buffer to use.
Therefore, we use a separate variable to store the return value
from the latest SNPRINTF call. This is checked to make sure it
wasn't negative, and only this amount is added to iBufferUsed
and subtracted from iBufferLeft.
This is the same pattern used in codec/encoder/core/src/utils.cpp.
strftime never returns negative numbers, so those calls don't
need as much checking.
2014-01-26 10:35:19 +01:00
|
|
|
if (iCurUsed > 0) {
|
|
|
|
iBufUsed += iCurUsed;
|
|
|
|
iBufLeft -= iCurUsed;
|
|
|
|
}
|
2014-01-25 23:40:22 +01:00
|
|
|
if (iBufLeft > 0) {
|
Fix calculating buffer positions when appending with SNPRINTF/WelsSnprintf
This fixes two separate issues.
First, with the MSVC _snprintf implementations, the return value
is negative if the buffer wasn't large enough - this would in
the worst case lead to making iBufferUsed negative, writing before
the start of the buffer.
Secondly, when both iBufferUsed and iBufferLeft are accumulated,
one can't do "iBufferLeft -= iBufferUsed;". As an example,
say the buffer is 100 bytes in total and iBufferLeft is 40 and
iBufferUsed is 60. If SNPRINTF then writes 5 more bytes to the
buffer, iBufferUsed would be 65, but if we now do
"iBufferLeft -= iBufferUsed;" then iBufferLeft would end up as
-25 even though there's 35 bytes left in the buffer to use.
Therefore, we use a separate variable to store the return value
from the latest SNPRINTF call. This is checked to make sure it
wasn't negative, and only this amount is added to iBufferUsed
and subtracted from iBufferLeft.
This is the same pattern used in codec/encoder/core/src/utils.cpp.
strftime never returns negative numbers, so those calls don't
need as much checking.
2014-01-26 10:35:19 +01:00
|
|
|
iCurUsed = WelsStrftime (&chFileName[iBufUsed], iBufLeft, "%y%m%d%H%M%S", &sCurTime);
|
|
|
|
iBufUsed += iCurUsed;
|
|
|
|
iBufLeft -= iCurUsed;
|
2013-12-12 23:21:12 +01:00
|
|
|
}
|
|
|
|
|
Fix calculating buffer positions when appending with SNPRINTF/WelsSnprintf
This fixes two separate issues.
First, with the MSVC _snprintf implementations, the return value
is negative if the buffer wasn't large enough - this would in
the worst case lead to making iBufferUsed negative, writing before
the start of the buffer.
Secondly, when both iBufferUsed and iBufferLeft are accumulated,
one can't do "iBufferLeft -= iBufferUsed;". As an example,
say the buffer is 100 bytes in total and iBufferLeft is 40 and
iBufferUsed is 60. If SNPRINTF then writes 5 more bytes to the
buffer, iBufferUsed would be 65, but if we now do
"iBufferLeft -= iBufferUsed;" then iBufferLeft would end up as
-25 even though there's 35 bytes left in the buffer to use.
Therefore, we use a separate variable to store the return value
from the latest SNPRINTF call. This is checked to make sure it
wasn't negative, and only this amount is added to iBufferUsed
and subtracted from iBufferLeft.
This is the same pattern used in codec/encoder/core/src/utils.cpp.
strftime never returns negative numbers, so those calls don't
need as much checking.
2014-01-26 10:35:19 +01:00
|
|
|
if (iCurUsedSize > 0) {
|
|
|
|
iBufUsedSize += iCurUsedSize;
|
|
|
|
iBufLeftSize -= iCurUsedSize;
|
|
|
|
}
|
2014-01-25 23:40:22 +01:00
|
|
|
if (iBufLeftSize > 0) {
|
Fix calculating buffer positions when appending with SNPRINTF/WelsSnprintf
This fixes two separate issues.
First, with the MSVC _snprintf implementations, the return value
is negative if the buffer wasn't large enough - this would in
the worst case lead to making iBufferUsed negative, writing before
the start of the buffer.
Secondly, when both iBufferUsed and iBufferLeft are accumulated,
one can't do "iBufferLeft -= iBufferUsed;". As an example,
say the buffer is 100 bytes in total and iBufferLeft is 40 and
iBufferUsed is 60. If SNPRINTF then writes 5 more bytes to the
buffer, iBufferUsed would be 65, but if we now do
"iBufferLeft -= iBufferUsed;" then iBufferLeft would end up as
-25 even though there's 35 bytes left in the buffer to use.
Therefore, we use a separate variable to store the return value
from the latest SNPRINTF call. This is checked to make sure it
wasn't negative, and only this amount is added to iBufferUsed
and subtracted from iBufferLeft.
This is the same pattern used in codec/encoder/core/src/utils.cpp.
strftime never returns negative numbers, so those calls don't
need as much checking.
2014-01-26 10:35:19 +01:00
|
|
|
iCurUsedSize = WelsStrftime (&chFileNameSize[iBufUsedSize], iBufLeftSize, "%y%m%d%H%M%S", &sCurTime);
|
|
|
|
iBufUsedSize += iCurUsedSize;
|
|
|
|
iBufLeftSize -= iCurUsedSize;
|
2013-12-12 23:21:12 +01:00
|
|
|
}
|
|
|
|
|
2014-01-25 23:40:22 +01:00
|
|
|
if (iBufLeft > 0) {
|
2014-01-26 14:38:49 +01:00
|
|
|
iCurUsed = WelsSnprintf (&chFileName[iBufUsed], iBufLeft, ".%03.3u.264", WelsGetMillisecond (&sCurTime));
|
Fix calculating buffer positions when appending with SNPRINTF/WelsSnprintf
This fixes two separate issues.
First, with the MSVC _snprintf implementations, the return value
is negative if the buffer wasn't large enough - this would in
the worst case lead to making iBufferUsed negative, writing before
the start of the buffer.
Secondly, when both iBufferUsed and iBufferLeft are accumulated,
one can't do "iBufferLeft -= iBufferUsed;". As an example,
say the buffer is 100 bytes in total and iBufferLeft is 40 and
iBufferUsed is 60. If SNPRINTF then writes 5 more bytes to the
buffer, iBufferUsed would be 65, but if we now do
"iBufferLeft -= iBufferUsed;" then iBufferLeft would end up as
-25 even though there's 35 bytes left in the buffer to use.
Therefore, we use a separate variable to store the return value
from the latest SNPRINTF call. This is checked to make sure it
wasn't negative, and only this amount is added to iBufferUsed
and subtracted from iBufferLeft.
This is the same pattern used in codec/encoder/core/src/utils.cpp.
strftime never returns negative numbers, so those calls don't
need as much checking.
2014-01-26 10:35:19 +01:00
|
|
|
if (iCurUsed > 0) {
|
|
|
|
iBufUsed += iCurUsed;
|
|
|
|
iBufLeft -= iCurUsed;
|
|
|
|
}
|
2013-12-12 23:21:12 +01:00
|
|
|
}
|
|
|
|
|
2014-01-25 23:40:22 +01:00
|
|
|
if (iBufLeftSize > 0) {
|
Fix calculating buffer positions when appending with SNPRINTF/WelsSnprintf
This fixes two separate issues.
First, with the MSVC _snprintf implementations, the return value
is negative if the buffer wasn't large enough - this would in
the worst case lead to making iBufferUsed negative, writing before
the start of the buffer.
Secondly, when both iBufferUsed and iBufferLeft are accumulated,
one can't do "iBufferLeft -= iBufferUsed;". As an example,
say the buffer is 100 bytes in total and iBufferLeft is 40 and
iBufferUsed is 60. If SNPRINTF then writes 5 more bytes to the
buffer, iBufferUsed would be 65, but if we now do
"iBufferLeft -= iBufferUsed;" then iBufferLeft would end up as
-25 even though there's 35 bytes left in the buffer to use.
Therefore, we use a separate variable to store the return value
from the latest SNPRINTF call. This is checked to make sure it
wasn't negative, and only this amount is added to iBufferUsed
and subtracted from iBufferLeft.
This is the same pattern used in codec/encoder/core/src/utils.cpp.
strftime never returns negative numbers, so those calls don't
need as much checking.
2014-01-26 10:35:19 +01:00
|
|
|
iCurUsedSize = WelsSnprintf (&chFileNameSize[iBufUsedSize], iBufLeftSize, ".%03.3u.len",
|
2014-01-26 14:38:49 +01:00
|
|
|
WelsGetMillisecond (&sCurTime));
|
Fix calculating buffer positions when appending with SNPRINTF/WelsSnprintf
This fixes two separate issues.
First, with the MSVC _snprintf implementations, the return value
is negative if the buffer wasn't large enough - this would in
the worst case lead to making iBufferUsed negative, writing before
the start of the buffer.
Secondly, when both iBufferUsed and iBufferLeft are accumulated,
one can't do "iBufferLeft -= iBufferUsed;". As an example,
say the buffer is 100 bytes in total and iBufferLeft is 40 and
iBufferUsed is 60. If SNPRINTF then writes 5 more bytes to the
buffer, iBufferUsed would be 65, but if we now do
"iBufferLeft -= iBufferUsed;" then iBufferLeft would end up as
-25 even though there's 35 bytes left in the buffer to use.
Therefore, we use a separate variable to store the return value
from the latest SNPRINTF call. This is checked to make sure it
wasn't negative, and only this amount is added to iBufferUsed
and subtracted from iBufferLeft.
This is the same pattern used in codec/encoder/core/src/utils.cpp.
strftime never returns negative numbers, so those calls don't
need as much checking.
2014-01-26 10:35:19 +01:00
|
|
|
if (iCurUsedSize > 0) {
|
|
|
|
iBufUsedSize += iCurUsedSize;
|
|
|
|
iBufLeftSize -= iCurUsedSize;
|
|
|
|
}
|
2013-12-12 23:21:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
m_pFBS = WelsFopen (chFileName, "wb");
|
|
|
|
m_pFBSSize = WelsFopen (chFileNameSize, "wb");
|
2013-12-09 13:51:09 +01:00
|
|
|
#endif//OUTPUT_BIT_STREAM
|
2013-12-12 23:21:12 +01:00
|
|
|
|
2013-12-09 13:51:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
* Description:
|
|
|
|
* class CWelsDecoder destructor function, destroy allocced memory
|
2013-12-12 23:21:12 +01:00
|
|
|
*
|
2013-12-09 13:51:09 +01:00
|
|
|
* Input parameters: none
|
|
|
|
*
|
|
|
|
* return: none
|
2013-12-13 21:03:38 +01:00
|
|
|
***************************************************************************/
|
2013-12-12 23:21:12 +01:00
|
|
|
CWelsDecoder::~CWelsDecoder() {
|
|
|
|
IWelsTrace::WelsVTrace (m_pTrace, IWelsTrace::WELS_LOG_INFO, "CWelsDecoder::~CWelsDecoder()");
|
2013-12-09 13:51:09 +01:00
|
|
|
|
2013-12-12 23:21:12 +01:00
|
|
|
UninitDecoder();
|
2014-01-23 04:01:51 +01:00
|
|
|
XMMREG_PROTECT_UNINIT(CWelsH264Decoder);
|
2013-12-09 13:51:09 +01:00
|
|
|
|
|
|
|
#ifdef OUTPUT_BIT_STREAM
|
2013-12-12 23:21:12 +01:00
|
|
|
if (m_pFBS) {
|
|
|
|
WelsFclose (m_pFBS);
|
|
|
|
m_pFBS = NULL;
|
|
|
|
}
|
|
|
|
if (m_pFBSSize) {
|
|
|
|
WelsFclose (m_pFBSSize);
|
|
|
|
m_pFBSSize = NULL;
|
|
|
|
}
|
2013-12-09 13:51:09 +01:00
|
|
|
#endif//OUTPUT_BIT_STREAM
|
|
|
|
|
2013-12-12 23:21:12 +01:00
|
|
|
if (NULL != m_pTrace) {
|
|
|
|
delete m_pTrace;
|
|
|
|
m_pTrace = NULL;
|
|
|
|
}
|
2013-12-09 13:51:09 +01:00
|
|
|
}
|
|
|
|
|
2013-12-12 23:21:12 +01:00
|
|
|
long CWelsDecoder::Initialize (void_t* pParam, const INIT_TYPE keInitType) {
|
|
|
|
if (pParam == NULL || keInitType != INIT_TYPE_PARAMETER_BASED) {
|
|
|
|
IWelsTrace::WelsVTrace (m_pTrace, IWelsTrace::WELS_LOG_INFO, "CWelsDecoder::Initialize(), invalid input argument.");
|
|
|
|
return cmInitParaError;
|
|
|
|
}
|
2013-12-09 13:51:09 +01:00
|
|
|
|
2013-12-12 23:21:12 +01:00
|
|
|
// H.264 decoder initialization,including memory allocation,then open it ready to decode
|
|
|
|
InitDecoder();
|
2013-12-09 13:51:09 +01:00
|
|
|
|
2013-12-12 23:21:12 +01:00
|
|
|
DecoderConfigParam (m_pDecContext, pParam);
|
|
|
|
|
|
|
|
return cmResultSuccess;
|
2013-12-09 13:51:09 +01:00
|
|
|
}
|
|
|
|
|
2013-12-12 23:21:12 +01:00
|
|
|
long CWelsDecoder::Uninitialize() {
|
|
|
|
UninitDecoder();
|
|
|
|
|
|
|
|
return ERR_NONE;
|
2013-12-09 13:51:09 +01:00
|
|
|
}
|
|
|
|
|
2013-12-12 23:21:12 +01:00
|
|
|
void_t CWelsDecoder::UninitDecoder (void_t) {
|
|
|
|
if (NULL == m_pDecContext)
|
|
|
|
return;
|
2013-12-09 13:51:09 +01:00
|
|
|
|
2013-12-12 23:21:12 +01:00
|
|
|
IWelsTrace::WelsVTrace (m_pTrace, IWelsTrace::WELS_LOG_INFO, "into CWelsDecoder::uninit_decoder()..");
|
2013-12-09 13:51:09 +01:00
|
|
|
|
2013-12-12 23:21:12 +01:00
|
|
|
WelsEndDecoder (m_pDecContext);
|
2013-12-09 13:51:09 +01:00
|
|
|
|
2013-12-12 23:21:12 +01:00
|
|
|
if (NULL != m_pDecContext) {
|
|
|
|
WelsFree (m_pDecContext, "m_pDecContext");
|
2013-12-09 13:51:09 +01:00
|
|
|
|
2013-12-12 23:21:12 +01:00
|
|
|
m_pDecContext = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
IWelsTrace::WelsVTrace (m_pTrace, IWelsTrace::WELS_LOG_INFO, "left CWelsDecoder::uninit_decoder()..");
|
2013-12-09 13:51:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// the return value of this function is not suitable, it need report failure info to upper layer.
|
2013-12-12 23:21:12 +01:00
|
|
|
void_t CWelsDecoder::InitDecoder (void_t) {
|
|
|
|
IWelsTrace::WelsVTrace (m_pTrace, IWelsTrace::WELS_LOG_INFO, "CWelsDecoder::init_decoder()..");
|
|
|
|
|
|
|
|
m_pDecContext = (PWelsDecoderContext)WelsMalloc (sizeof (SWelsDecoderContext), "m_pDecContext");
|
2013-12-09 13:51:09 +01:00
|
|
|
|
2013-12-12 23:21:12 +01:00
|
|
|
WelsInitDecoder (m_pDecContext, m_pTrace, IWelsTrace::WelsTrace);
|
2013-12-09 13:51:09 +01:00
|
|
|
|
2013-12-12 23:21:12 +01:00
|
|
|
IWelsTrace::WelsVTrace (m_pTrace, IWelsTrace::WELS_LOG_INFO, "CWelsDecoder::init_decoder().. left");
|
2013-12-09 13:51:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2013-12-12 23:21:12 +01:00
|
|
|
* Set Option
|
2013-12-09 13:51:09 +01:00
|
|
|
*/
|
2013-12-12 23:21:12 +01:00
|
|
|
long CWelsDecoder::SetOption (DECODER_OPTION eOptID, void_t* pOption) {
|
|
|
|
int iVal = 0;
|
|
|
|
|
|
|
|
if (m_pDecContext == NULL)
|
|
|
|
return dsInitialOptExpected;
|
|
|
|
|
|
|
|
if (eOptID == DECODER_OPTION_DATAFORMAT) { // Set color space of decoding output frame
|
|
|
|
if (pOption == NULL)
|
|
|
|
return cmInitParaError;
|
|
|
|
|
|
|
|
iVal = * ((int*)pOption); // is_rgb
|
|
|
|
|
|
|
|
return DecoderSetCsp (m_pDecContext, iVal);
|
|
|
|
} else 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_MODE) {
|
|
|
|
if (pOption == NULL)
|
|
|
|
return cmInitParaError;
|
|
|
|
|
|
|
|
iVal = * ((int*)pOption);
|
|
|
|
|
|
|
|
m_pDecContext->iSetMode = iVal;
|
|
|
|
if (iVal == SW_MODE) {
|
|
|
|
m_pDecContext->iDecoderOutputProperty = BUFFER_HOST;
|
|
|
|
} else {
|
2013-12-09 13:51:09 +01:00
|
|
|
#if !defined(__APPLE__)
|
2013-12-12 23:21:12 +01:00
|
|
|
m_pDecContext->iDecoderOutputProperty = BUFFER_DEVICE;
|
2013-12-09 13:51:09 +01:00
|
|
|
#else
|
2013-12-12 23:21:12 +01:00
|
|
|
m_pDecContext->iDecoderOutputProperty = BUFFER_HOST;//BUFFER_HOST;//BUFFER_DEVICE;
|
2013-12-09 13:51:09 +01:00
|
|
|
#endif
|
2013-12-12 23:21:12 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return cmResultSuccess;
|
|
|
|
} else if (eOptID == DECODER_OPTION_OUTPUT_PROPERTY) {
|
|
|
|
if (pOption == NULL)
|
|
|
|
return cmInitParaError;
|
|
|
|
|
|
|
|
iVal = * ((int*)pOption);
|
|
|
|
if (m_pDecContext->iSetMode != SW_MODE)
|
|
|
|
m_pDecContext->iDecoderOutputProperty = iVal;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return cmInitParaError;
|
2013-12-09 13:51:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get Option
|
|
|
|
*/
|
2013-12-12 23:21:12 +01:00
|
|
|
long CWelsDecoder::GetOption (DECODER_OPTION eOptID, void_t* pOption) {
|
|
|
|
int iVal = 0;
|
|
|
|
|
|
|
|
if (m_pDecContext == NULL)
|
|
|
|
return cmInitExpected;
|
|
|
|
|
|
|
|
if (pOption == NULL)
|
|
|
|
return cmInitParaError;
|
|
|
|
|
|
|
|
if (DECODER_OPTION_DATAFORMAT == eOptID) {
|
|
|
|
iVal = m_pDecContext->iOutputColorFormat;
|
|
|
|
* ((int*)pOption) = iVal;
|
|
|
|
return cmResultSuccess;
|
|
|
|
} else if (DECODER_OPTION_END_OF_STREAM == eOptID) {
|
|
|
|
iVal = m_pDecContext->bEndOfStreamFlag;
|
|
|
|
* ((int*)pOption) = iVal;
|
|
|
|
return cmResultSuccess;
|
|
|
|
}
|
2013-12-09 13:51:09 +01:00
|
|
|
#ifdef LONG_TERM_REF
|
2013-12-12 23:21:12 +01:00
|
|
|
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;
|
|
|
|
}
|
2013-12-09 13:51:09 +01:00
|
|
|
#endif
|
2013-12-12 23:21:12 +01:00
|
|
|
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_MODE == eOptID) {
|
|
|
|
if (pOption == NULL)
|
|
|
|
return cmInitParaError;
|
|
|
|
|
|
|
|
iVal = m_pDecContext->iSetMode;
|
|
|
|
|
|
|
|
* ((int*)pOption) = iVal;
|
|
|
|
return cmResultSuccess;
|
|
|
|
} else if (DECODER_OPTION_DEVICE_INFO == eOptID) {
|
|
|
|
if (pOption == NULL)
|
|
|
|
return cmInitParaError;
|
|
|
|
|
|
|
|
return cmResultSuccess;
|
|
|
|
}
|
|
|
|
|
|
|
|
return cmInitParaError;
|
2013-12-09 13:51:09 +01:00
|
|
|
}
|
|
|
|
|
2014-01-21 19:37:03 +01:00
|
|
|
DECODING_STATE CWelsDecoder::DecodeFrame2 (const unsigned char* kpSrc,
|
2013-12-12 23:21:12 +01:00
|
|
|
const int kiSrcLen,
|
|
|
|
void_t** ppDst,
|
|
|
|
SBufferInfo* pDstInfo) {
|
2014-01-09 09:28:13 +01:00
|
|
|
if (kiSrcLen > MAX_ACCESS_UNIT_CAPACITY) {
|
|
|
|
m_pDecContext->iErrorCode |= dsOutOfMemory;
|
|
|
|
IWelsTrace::WelsVTrace (m_pTrace, IWelsTrace::WELS_LOG_INFO,
|
|
|
|
"max AU size exceeded. Allowed size = %d, current size = %d",
|
|
|
|
MAX_ACCESS_UNIT_CAPACITY, kiSrcLen);
|
|
|
|
return dsOutOfMemory;
|
|
|
|
}
|
2013-12-12 23:21:12 +01:00
|
|
|
if (kiSrcLen > 0 && kpSrc != NULL) {
|
2013-12-09 13:51:09 +01:00
|
|
|
#ifdef OUTPUT_BIT_STREAM
|
2013-12-12 23:21:12 +01:00
|
|
|
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);
|
|
|
|
}
|
2013-12-09 13:51:09 +01:00
|
|
|
#endif//OUTPUT_BIT_STREAM
|
2013-12-12 23:21:12 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
memset (pDstInfo, 0, sizeof (SBufferInfo));
|
|
|
|
pDstInfo->eBufferProperty = (EBufferProperty)m_pDecContext->iDecoderOutputProperty;
|
2013-12-09 13:51:09 +01:00
|
|
|
|
|
|
|
#ifdef LONG_TERM_REF
|
2013-12-12 23:21:12 +01:00
|
|
|
m_pDecContext->bReferenceLostAtT0Flag = false; //initialize for LTR
|
|
|
|
m_pDecContext->bCurAuContainLtrMarkSeFlag = false;
|
|
|
|
m_pDecContext->iFrameNumOfAuMarkedLtr = 0;
|
|
|
|
m_pDecContext->iFrameNum = -1; //initialize
|
2013-12-09 13:51:09 +01:00
|
|
|
#endif
|
|
|
|
|
2013-12-12 23:21:12 +01:00
|
|
|
m_pDecContext->iFeedbackTidInAu = -1; //initialize
|
|
|
|
|
2014-01-23 04:01:51 +01:00
|
|
|
XMMREG_PROTECT_STORE(CWelsH264Decoder);
|
2013-12-12 23:21:12 +01:00
|
|
|
WelsDecodeBs (m_pDecContext, kpSrc, kiSrcLen, (unsigned char**)ppDst,
|
|
|
|
pDstInfo); //iErrorCode has been modified in this function
|
2014-01-23 04:01:51 +01:00
|
|
|
XMMREG_PROTECT_LOAD(CWelsH264Decoder);
|
2013-12-12 23:21:12 +01:00
|
|
|
|
|
|
|
pDstInfo->eWorkMode = (EDecodeMode)m_pDecContext->iDecoderMode;
|
|
|
|
|
|
|
|
if (m_pDecContext->iErrorCode) {
|
|
|
|
ENalUnitType 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;
|
|
|
|
|
|
|
|
//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)) {
|
2013-12-09 13:51:09 +01:00
|
|
|
#ifdef LONG_TERM_REF
|
2013-12-12 23:21:12 +01:00
|
|
|
m_pDecContext->bParamSetsLostFlag = true;
|
2013-12-09 13:51:09 +01:00
|
|
|
#else
|
2013-12-12 23:21:12 +01:00
|
|
|
m_pDecContext->bReferenceLostAtT0Flag = true;
|
2013-12-09 13:51:09 +01:00
|
|
|
#endif
|
2013-12-12 23:21:12 +01:00
|
|
|
ResetParameterSetsState (m_pDecContext); //initial SPS&PPS ready flag
|
|
|
|
}
|
2013-12-09 13:51:09 +01:00
|
|
|
|
2013-12-12 23:21:12 +01:00
|
|
|
IWelsTrace::WelsVTrace (m_pTrace, IWelsTrace::WELS_LOG_INFO, "decode failed, failure type:%d \n",
|
|
|
|
m_pDecContext->iErrorCode);
|
|
|
|
return (DECODING_STATE)m_pDecContext->iErrorCode;
|
|
|
|
}
|
2013-12-09 13:51:09 +01:00
|
|
|
|
2013-12-12 23:21:12 +01:00
|
|
|
return dsErrorFree;
|
2013-12-09 13:51:09 +01:00
|
|
|
}
|
|
|
|
|
2013-12-12 23:21:12 +01:00
|
|
|
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;
|
|
|
|
DstInfo.eBufferProperty = BUFFER_HOST;
|
|
|
|
|
2014-01-21 19:37:03 +01:00
|
|
|
eDecState = DecodeFrame2 (kpSrc, kiSrcLen, (void_t**)ppDst, &DstInfo);
|
2013-12-12 23:21:12 +01:00
|
|
|
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;
|
2013-12-09 13:51:09 +01:00
|
|
|
}
|
|
|
|
|
2013-12-12 23:21:12 +01:00
|
|
|
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;
|
2013-12-09 13:51:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace WelsDec
|
|
|
|
|
|
|
|
|
|
|
|
using namespace WelsDec;
|
|
|
|
|
|
|
|
/* WINAPI is indeed in prefix due to sync to application layer callings!! */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* CreateDecoder
|
|
|
|
* @return: success in return 0, otherwise failed.
|
|
|
|
*/
|
2013-12-12 23:21:12 +01:00
|
|
|
long CreateDecoder (ISVCDecoder** ppDecoder) {
|
2013-12-09 13:51:09 +01:00
|
|
|
|
2013-12-12 23:21:12 +01:00
|
|
|
if (NULL == ppDecoder) {
|
|
|
|
return ERR_INVALID_PARAMETERS;
|
|
|
|
}
|
2013-12-09 13:51:09 +01:00
|
|
|
|
2013-12-12 23:21:12 +01:00
|
|
|
*ppDecoder = new CWelsDecoder();
|
2013-12-09 13:51:09 +01:00
|
|
|
|
2013-12-12 23:21:12 +01:00
|
|
|
if (NULL == *ppDecoder) {
|
|
|
|
return ERR_MALLOC_FAILED;
|
|
|
|
}
|
2013-12-09 13:51:09 +01:00
|
|
|
|
2013-12-12 23:21:12 +01:00
|
|
|
return ERR_NONE;
|
2013-12-09 13:51:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* DestroyDecoder
|
|
|
|
*/
|
2013-12-12 23:21:12 +01:00
|
|
|
void_t DestroyDecoder (ISVCDecoder* pDecoder) {
|
|
|
|
if (NULL != pDecoder) {
|
|
|
|
delete (CWelsDecoder*)pDecoder;
|
|
|
|
}
|
2013-12-09 13:51:09 +01:00
|
|
|
}
|