📄 h264dec.c
字号:
/* <LIC_AMD_STD>
* Copyright (C) 2003-2005 Advanced Micro Devices, Inc. All Rights Reserved.
*
* Unless otherwise designated in writing, this software and any related
* documentation are the confidential proprietary information of AMD.
* THESE MATERIALS ARE PROVIDED "AS IS" WITHOUT ANY
* UNLESS OTHERWISE NOTED IN WRITING, EXPRESS OR IMPLIED WARRANTY OF ANY
* KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY,
* NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE AND IN NO
* EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER.
*
* AMD does not assume any responsibility for any errors which may appear
* in the Materials nor any responsibility to support or update the
* Materials. AMD retains the right to modify the Materials at any time,
* without notice, and is not obligated to provide such modified
* Materials to you. AMD is not obligated to furnish, support, or make
* any further information available to you.
* </LIC_AMD_STD> */
/* <CTL_AMD_STD>
* </CTL_AMD_STD> */
/* <DOC_AMD_STD>
* Filename: h264dec.c -h264 video decoder interfaces
* Note: this decoder only works under MAE
* </DOC_AMD_STD> */
#include <stdio.h>
#include <stdlib.h>
#include <mediaobj.h>
#include <memory.h>
#include "diu.h"
#include "inttypes.h"
#include "debug.h"
// Include the H.264 header files
#include "decinit.h"
#define MAX_FRAME_SIZE 256*1024
//Frame skipping defines
#define MIN_SKIP_THRESHOLD 250 //minimuim to trigger frame skipping
/* Our component's private processor variables are stored here */
typedef struct ProcessorInfo_s
{
unsigned int m_uiFrameCount;
unsigned int m_uiErrorCount;
BOOL m_bFirstInput;
BOOL m_bDecoderInit; // Keeps track if we need to report init data (play/stop/play)
int m_iImageWidth;
int m_iImageHeight;
int m_iLastTime; //Keeps track of last time we made a skip adjustment
int m_iDeltaTime; //Rate of change in playback, (0)constant, (-)worse, (+)better
ibuf_t m_inbuf;
unsigned char * m_plocalbuf; /* pointer to allocated local memory buffer */
unsigned int m_nlocalbuf; /* size of allocated local memory buffer */
} ProcessorInfo_t;
// Global Variables
unsigned char g_bH264DecOpened = 0;
m_u32 g_uiWaitForIFrame = 0;
int g_nFramesSinceI = 0;
int g_nIFrameSpacing = 0;
int g_nSkipRate = 0;
int g_nSkipCount = 0;
LONG g_nH264PTS = 0;
void OSDebugPrint(m_tchar *format, ...)
{
TCHAR _pcTempTextW[256];
TCHAR _pcTempTextWout[256];
va_list argptr;
va_start(argptr, format);
vswprintf(_pcTempTextW, format, argptr);
va_end(argptr);
wcscpy(_pcTempTextWout, TEXT("H264DEC: "));
wcscat(_pcTempTextWout, _pcTempTextW);
OutputDebugString(_pcTempTextWout);
}
STATIC_FUNC void Flush_Decoder(ProcessorInfo_t *pPInfo)
{
g_nH264PTS = 0;
g_nFramesSinceI = 0;
g_nSkipRate = 0;
g_nSkipCount = 0;
g_uiWaitForIFrame = TRUE;
pPInfo->m_iLastTime=0;
pPInfo->m_iDeltaTime=0;
}
STATIC_FUNC void check_sync(ProcessorInfo_t *pPInfo, DWORD msTime)
{
int iTimeDiff = (int)(((unsigned int)g_nH264PTS)-((unsigned int)msTime));
pPInfo->m_iDeltaTime = iTimeDiff - pPInfo->m_iLastTime;
if ((iTimeDiff < -MIN_SKIP_THRESHOLD) && (pPInfo->m_iDeltaTime < -50))
{
//we are behind and falling further behind, we need to increase number of skipped frames
g_nSkipRate++;
pPInfo->m_iLastTime = iTimeDiff;
} else if (pPInfo->m_iDeltaTime > 50)
{
//we are catching up, we need to decrease the number of skipped frames
if (g_nSkipRate > 0) g_nSkipRate--;
pPInfo->m_iLastTime = iTimeDiff;
}
DP_SYNC((M_TEXT("check_sync() iTimeDiff(%d) iDeltaTime(%d) SkipRate(%d)\n"),
iTimeDiff, pPInfo->m_iDeltaTime, g_nSkipRate));
}
STATIC_FUNC int open_h264dec(DIUCompHandle_t hComp)
{
ProcessorInfo_t *pPInfo=(ProcessorInfo_t *)DIUHCOMP_TO_USERINFO(hComp);
int eStatus = DIU_STATUS_OK;
DP_API((M_TEXT("open_h264dec() enter\n")));
// create a decoder object
if (!g_bH264DecOpened)
{
g_bH264DecOpened = TRUE;
g_nH264PTS = 0;
DP_INFO((M_TEXT("Opening the MAE Driver\n")));
open_mae_driver(TEXT("H264DEC"));
pPInfo->m_uiFrameCount=0;
pPInfo->m_uiErrorCount=0;
pPInfo->m_bFirstInput=0;
pPInfo->m_iLastTime=0;
pPInfo->m_iDeltaTime=0;
}
DP_API((M_TEXT("open_H264dec() done: status=0x%X\n"), eStatus));
return eStatus;
}
STATIC_FUNC int close_h264dec(DIUCompHandle_t hComp)
{
ProcessorInfo_t *pPInfo=(ProcessorInfo_t *)DIUHCOMP_TO_USERINFO(hComp);
int eStatus = DIU_STATUS_OK;
DP_API((M_TEXT("close_H264dec() enter\n")));
// Close the decoder library
if (g_bH264DecOpened)
{
//mae_indicate_state(FALSE);
H264_Decoder_CleanUp();
// Reset to init state
pPInfo->m_bDecoderInit = FALSE;
if (g_bH264DecOpened)
g_bH264DecOpened=FALSE;
}
DP_API((M_TEXT("close_H264dec() done: status=0x%X\n"), eStatus));
return eStatus;
}
// do_process_input() processes the input buffer where:
// inbuf [in] is the input buffer
// pread [out] amount of data processed from input buffer
// poutbuf [out] is the output buffer
// poutsize [out] is the size of the output buffer
// oflags [out] is the output buffers flags
// Return values:
// if (poutsize > 0) = success, output was produced)
// DIU_STATUS_OK = still have input data to process
// DIU_STATUS_NEEDMOREINPUT = used all input data, need more
// DIU_STATUS_OPENERROR = error opening decoder
// DIU_STATUS_UNSUPPORTEDFORMAT = video type not supported
STATIC_FUNC int do_process_input(DIUCompHandle_t hComp, ibuf_t* inbuf, unsigned int *pread, unsigned char *poutbuf, unsigned int *poutsize, unsigned int *oflags)
{
ProcessorInfo_t *pPInfo=(ProcessorInfo_t *)DIUHCOMP_TO_USERINFO(hComp);
int eStatus=DIU_STATUS_OK;
static BOOL bFirstTime=TRUE;
static int eDecodeStatus = DIU_STATUS_OK;
//store our maximuim output buffer size and set current output size to 0
unsigned int uiOutputMaxSize = *poutsize;
*poutsize = 0;
/* Do a one time initialization call to decoder */
if (pPInfo->m_bDecoderInit == FALSE)
{
int rval;
m_bool bSpatialScalable = FALSE;
pPInfo->m_iImageWidth = 0;
pPInfo->m_iImageHeight = 0;
pPInfo->m_uiFrameCount = 0;
rval = H264_Decoder_Init(inbuf, &pPInfo->m_iImageWidth, &pPInfo->m_iImageHeight);
// Check for any errors
if (rval != DIU_STATUS_OK)
{
return DIU_STATUS_OPENERROR;
}
DP_API((M_TEXT("do_process_input() H264_Decoder_Init done: Width=%d Height=%d\n"), pPInfo->m_iImageWidth, pPInfo->m_iImageHeight));
pPInfo->m_bDecoderInit = TRUE;
return DIU_STATUS_NEEDMOREINPUT;
}
// If no decoder is found, then return an error
if (!g_bH264DecOpened)
return DIU_STATUS_OPENERROR;
DP_INFO((M_TEXT("do_process_input() decode()\n")));
if (inbuf->flags & DIU_FLAG_DATADISCON)
{
//clear the frame skipping settings on discontinuity
Flush_Decoder(pPInfo);
}
eDecodeStatus=h264_decode(inbuf, pread);
g_nH264PTS = (LONG)inbuf->pts;
if (eDecodeStatus == DIU_STATUS_OK)
{
//Successfully decoded a frame
// We set outsize equal to 1 to indicate it was sent to MAE directly
*poutsize = 1;
pPInfo->m_uiFrameCount++;
}
else if (eDecodeStatus == DIU_STATUS_NEEDMOREINPUT)
{
eStatus=DIU_STATUS_NEEDMOREINPUT;
}
DP_INFO((M_TEXT("do_process_input() decode() result=%d\n"), eDecodeStatus));
// All done, return success
DP_API((M_TEXT("do_process_input() done: result=0x%08X\n"), eStatus));
return eStatus;
}
STATIC_FUNC int DIUGetBuffer(DIUCompHandle_t hComp, unsigned char *pBuffer, m_u32 *size, LONGLONG *pts, unsigned int *flags)
{
ProcessorInfo_t *pPInfo = (ProcessorInfo_t *)DIUHCOMP_TO_USERINFO(hComp);
int error = DIU_STATUS_NEEDMOREINPUT;
unsigned int BytesRead = 0;
if ((pPInfo->m_inbuf.size > 0) && (pPInfo->m_inbuf.flags&DIU_FLAG_FRAMEEND))
{
//process the input buffer
DP_INFO((M_TEXT("DIUGetBuffer process size(%d)\n"), pPInfo->m_inbuf.size));
error = do_process_input(hComp, &(pPInfo->m_inbuf), &BytesRead, pBuffer, size, flags);
DP_INFO((M_TEXT("DIUGetBuffer after do_process_input status %d, osize %d, flags %x\n"), error, *size, *flags));
if (*size > 0)
{
*flags |= DMO_OUTPUT_DATA_BUFFERF_TIME;
*pts = g_nH264PTS;
DP_API((M_TEXT("DIUGetBuffer() pass PTS %d\n"), (DWORD)(*pts)));
if (pPInfo->m_inbuf.flags & DIU_FLAG_DATADISCON) /* check for discontinuity */
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -