📄 maimpeg4dec.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> @doc MAI @module maimpeg4dec.c - Media Accelerator Interface, MPEG4 video decoder MAI video wrapper file. Contains wrapper interface for MPEG4 video decoder to MAI Note: this decoder only works under MAE * </DOC_AMD_STD> */#include <stdio.h>#include <stdlib.h>#include <memory.h>// Include the MAI interfaces#include "mai_osal.h"#include "mai_component.h"#include "mai_param.h" /* for Get/SetParam */#include "mai_compbase.h"#ifdef MAI_OS_LINUX#include <inttypes.h>#include <sys/time.h>#endif#ifdef MAE_HW// Make sure global variables are only defined once#ifndef __GLOBAL_VAR_#define __GLOBAL_VAR_#endif// Include the MPEG4 header files#include "typeapi.h"#include "mode.h"#include "global.h"#ifdef UNDER_CE#include "bitstrm.h"#include "huffman.h"#include "vopses.h"#include "vopsedec.h"#else#include "entropy/bitstrm.h"#include "entropy/huffman.h"#include "vopses.h"#include "decoder/vopsedec.h"#endif// Include the MAE interfaces#include "mae_pass_thru.h"#endif /* MAE_HW */#ifdef TRACE_BUILD#define DPRINTF(_args_) MAIOSDebugPrint _args_ #define APIPRINTF(_args_) MAIOSDebugPrint _args_#define SYNCPRINTF(_args_) MAIOSDebugPrint _args_#else#define DPRINTF(_args_) #define APIPRINTF(_args_)#define SYNCPRINTF(_args_) /* MAIOSDebugPrint _args_ */#endif// The decoder is extremely optimized & we are able to play very high bit-rate D1 sized// clips almost flawlessly. Adding skipping will make the playback extremly bad & far// from being user friendly. Finally, most customers complained about this. So, we are// taking it out & let the decoder handle as fast as it can (there will be momentary// loss of AVSync, if any at the most)//#define SYNC_SKIPPING_SUPPORT /* enable frame skipping if sync is falling behind */#define DECODE_MIN_BUFFERS 3 /* For Sync I/O, minimum number of buffers to be queued before processing */#define DECODE_MAX_BUFFERS 20 /* For Sync I/O, maximum number of buffers to be queued before processing */#define DECODE_MIN_DATA 76*1024 /* For Sync I/O, minimum bytes to be queued before processing */#define DEFAULT_INBUFSIZE 128*1024#define DEFAULT_INBUFCOUNT 40/* Our component's private processor variables are stored here */typedef struct ProcessorInfo_s { unsigned int m_uiFrameCount; unsigned int m_uiOutputFrameCount; unsigned int m_uiErrorCount; MAIOSCritSec_t m_hCSDecode; m_bool m_bFirstInput; m_bool m_bNeedReset; MAITimeStamp_t m_tDecodePTS; /* PTS of last frame decoded */ MAITimeStamp_t m_tInputPTS; /* PTS of last packet on input */ MAISpeed_e m_CurrentSpeed; MAISpeed_e m_NextSpeed; unsigned int m_uiCurrentDecodeMode; unsigned int m_uiNextDecodeMode; unsigned int m_uiFramesOutInMode; /* how many frames output since mode changed */ unsigned int m_uiSyncSkippingThreshold; /* threshold in millisecs to start skipping frames */ unsigned int m_uiSyncSkippingThresholdI; /* threshold in millisecs to start skipping to I-frames */ m_bool m_bDecoderInit; /* Keeps track if we need to report init data (play/stop/play) */ int m_iImageWidth; int m_iImageHeight;} ProcessorInfo_t;/* Function prototypes*/void MP4V_ResetBitStream();static void update_speed(ProcessorInfo_t *pPInfo, int bForceUpdate);MAIStatus_e _startprocessing(MAICompHandle_t hComp);MAIStatus_e _endprocessing(MAICompHandle_t hComp);MAIStatus_e _processbuffer(MAICompHandle_t hComp, MAICompBuffer_t *pInBufferInfo);/* Global Variables */MAICompBufferPool_t g_hInBufferPool=M_HANDLE_INVALID; /* decoder uses this to access input data */MAICompHandle_t g_hComp=M_HANDLE_INVALID;extern unsigned int g_bEOFReached;MAISpeed_e g_NextSpeed;m_u32 g_uiWaitForIFrame = 0;#ifndef MAE_HW /* let's emulate decoder APIs under non-MAE environments */#ifndef DECODE_NORMAL#define DECODE_NORMAL 0x00#define DECODE_I_ONLY 0x01#define DECODE_P_ONLY 0x02#define DECODE_IP_ONLY 0x03#define DECODE_WAITFORI 0x10#define DECODE_WAITFORI_IPONLY 0x20#endif#ifndef CLIP_XVID#define CLIP_MPEG4 1#define CLIP_XVID 2#endif#define MP4V_UNSUPPORTED_CODING_TYPE -3#define CVideoObjectDecoder voidCVideoObjectDecoder *g_pDecoder=(void *)0;MAITimeStamp_t g_nMP4VPTS=0;int main_short_video_header=0;unsigned int g_bEOFReached=0;unsigned int eDecodeMode=DECODE_NORMAL;unsigned int g_iClipType=CLIP_MPEG4;void MP4V_Decoder_CleanUp(){ g_pDecoder=NULL; }int MP4V_Decoder_Init (char *pszFileName, int *piImageWidth, int *piImageHeight){ g_pDecoder=(CVideoObjectDecoder *)1; g_nMP4VPTS=0; *piImageWidth=320; *piImageHeight=240; return 0;}void MP4V_ResetBitStream(){}int decode(){ int rstatus=0; MAIStatus_e eStatus; MAICompBuffer_t *pBufferInfo; /* get the next input buffer */ eStatus=MAICompBufferPoolGet(g_hInBufferPool, MAI_BUFSTATE_FILLED, &pBufferInfo, 0); if (eStatus==MAI_STATUS_OK && pBufferInfo) { if ((pBufferInfo->dwFlags&MAICOMPBUF_FLAG_EOS)!=0) rstatus=EOF; // Hit end of stream MAICompBufferPoolPut(g_hInBufferPool, MAI_BUFSTATE_EMPTY, pBufferInfo, 0); } g_nMP4VPTS+=33; //printf("MP4V: decode() PTS=%u\n", (unsigned int)g_nMP4VPTS); return rstatus;}int h263_decode(){ /* call decode(), since we're just simulating */ return decode();}void mpeg4_setmode(unsigned int eMode){ eDecodeMode=eMode; }unsigned int mpeg4_getmode(){ return DECODE_NORMAL; }#endif /* emulate decoder APIs */static void update_speed(ProcessorInfo_t *pPInfo, int bForceUpdate){ unsigned int uiNewPlayRate=pPInfo->m_NextSpeed&MAI_SPEED_RATEMASK; if ((pPInfo->m_NextSpeed!=MAI_SPEED_UNSPECIFIED && pPInfo->m_CurrentSpeed!=pPInfo->m_NextSpeed) || pPInfo->m_uiCurrentDecodeMode!=pPInfo->m_uiNextDecodeMode) bForceUpdate=1; if (bForceUpdate) { g_NextSpeed=(pPInfo->m_NextSpeed==MAI_SPEED_UNSPECIFIED)?pPInfo->m_CurrentSpeed:pPInfo->m_NextSpeed; APIPRINTF((M_TEXT("MPV4: update_speed() NextSpeed=0x%X NextMode=%d\n"), pPInfo->m_NextSpeed, pPInfo->m_uiNextDecodeMode)); if (g_NextSpeed!=MAI_SPEED_UNSPECIFIED && pPInfo->m_CurrentSpeed!=pPInfo->m_NextSpeed && pPInfo->m_uiCurrentDecodeMode==pPInfo->m_uiNextDecodeMode) { /* Speed is changing, and there has been no request to change decode mode, */ /* so just translate the new speed to the decode mode */ APIPRINTF((M_TEXT("MPV4: update_speed() 0x%X->0x%X\n"), pPInfo->m_CurrentSpeed, pPInfo->m_NextSpeed)); if ((g_NextSpeed&MAI_SPEED_REVERSEFLAG)!=0) pPInfo->m_uiNextDecodeMode=DECODE_I_ONLY; else if (uiNewPlayRate>=MAI_SPEED_4X) pPInfo->m_uiNextDecodeMode=DECODE_I_ONLY; else if (uiNewPlayRate>=MAI_SPEED_2X) pPInfo->m_uiNextDecodeMode=DECODE_IP_ONLY; else pPInfo->m_uiNextDecodeMode=DECODE_NORMAL; } /* set frame skip mode in decoder */ APIPRINTF((M_TEXT("MPV4: update_speed() mpeg4_setmode(mode=%d, speed=0x%X)\n"), pPInfo->m_uiNextDecodeMode, pPInfo->m_NextSpeed)); mpeg4_setmode(pPInfo->m_uiNextDecodeMode);#ifdef MAE_HW /* call mae wrapper */ //set_mode(pPInfo->m_uiNextDecodeMode, NextSpeed);#endif pPInfo->m_uiCurrentDecodeMode=pPInfo->m_uiNextDecodeMode; /* remember mode */ pPInfo->m_CurrentSpeed=g_NextSpeed; }}#ifdef SYNC_SKIPPING_SUPPORTstatic void check_sync(ProcessorInfo_t *pPInfo, MAIParamClock_t *pClock){ SYNCPRINTF((M_TEXT("MPV4:check_sync() CurrentSpeed=0x%08X\n"), pPInfo->m_CurrentSpeed)); if ((pClock->uiFlags&MAI_CLOCK_FLAG_SYNCTHRESHOLD)!=0) { pPInfo->m_uiSyncSkippingThreshold=pClock->uiParam1; pPInfo->m_uiSyncSkippingThresholdI=pClock->uiParam1*6; /* check for resonable I frame skipping thresholds */ if (pPInfo->m_uiSyncSkippingThresholdI>800) pPInfo->m_uiSyncSkippingThresholdI=800; else if (pPInfo->m_uiSyncSkippingThresholdI<150) pPInfo->m_uiSyncSkippingThresholdI=150; } if (pPInfo->m_CurrentSpeed==MAI_SPEED_NORMAL) { if (pPInfo->m_tDecodePTS && (pClock->uiFlags&MAI_CLOCK_FLAG_CURRENTTIME)!=0) { int iTimeDiff=(int)(((unsigned int)pClock->tCurrentTime)-((unsigned int)pPInfo->m_tDecodePTS)); SYNCPRINTF((M_TEXT("MPV4:check_sync() TimeDiff=%d Threshold=%d CurrentMode=%d\n"), iTimeDiff, pPInfo->m_uiSyncSkippingThreshold, pPInfo->m_uiCurrentDecodeMode)); if (pPInfo->m_uiFramesOutInMode>1) /* have we decoded some frames in the current decode mode? */ { unsigned int eCurrentMode=0; eCurrentMode=mpeg4_getmode(); if (iTimeDiff>(int)pPInfo->m_uiSyncSkippingThreshold) { /* video is falling behind - skip frames to maintain sync */ SYNCPRINTF((M_TEXT("MPV4:check_sync() CurrentMode=%d TimeDiff=%d Threshold=%d\n"), eCurrentMode, iTimeDiff, pPInfo->m_uiSyncSkippingThreshold)); if (iTimeDiff>(int)pPInfo->m_uiSyncSkippingThresholdI) { SYNCPRINTF((M_TEXT("MPV4:check_sync() I-Frames\n"))); mpeg4_setmode(DECODE_I_ONLY); pPInfo->m_uiFramesOutInMode=0; } else if (eCurrentMode==DECODE_NORMAL || eCurrentMode==DECODE_WAITFORI) { SYNCPRINTF((M_TEXT("MPV4:check_sync() IP-frames\n"))); mpeg4_setmode(DECODE_IP_ONLY); pPInfo->m_uiFramesOutInMode=0; } } else if (iTimeDiff<-200 /* video has caught-up */ && eCurrentMode!=DECODE_NORMAL) { SYNCPRINTF((M_TEXT("MPV4:check_sync() Play NORMAL\n"))); mpeg4_setmode(DECODE_NORMAL); pPInfo->m_uiFramesOutInMode=0; } } } }}#endifMAIStatus_e _newformat(MAICompHandle_t hComp){ ProcessorInfo_t *pPInfo=(ProcessorInfo_t *)HCOMP_TO_USERINFO(hComp);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -