⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 h264dec.c

📁 This the source release kit for the following system configuration(s): - AMD Alchemy(TM) DBAu1200(
💻 C
📖 第 1 页 / 共 2 页
字号:
/* <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 + -