📄 maimpadec.c
字号:
/* <LIC_AMD_STD> * Copyright (c) 2005 Advanced Micro Devices, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * The full GNU General Public License is included in this distribution in the * file called COPYING * </LIC_AMD_STD> *//* <CTL_AMD_STD> * </CTL_AMD_STD> *//* <DOC_AMD_STD> * Filename: maimpadec.c - MPEG Audio decoder interfaces for MAIengine * </DOC_AMD_STD> */#if defined(WIN32) || defined(UNDER_CE) #include <windows.h> #include <winbase.h> #if defined(UNDER_CE) #include <windev.h> #endif#endif#include <stdio.h>#include <stdlib.h>#include "mai_osal.h" /* needed for threads */#include "mai_component.h" /* was mai_def.h, mai_readandparse.h */#include "mai_compbase.h"#include "mpegaudiodec.h"#ifdef TRACE_BUILD #define DPRINTF(_args_) MAIOSDebugPrint _args_ #define APIPRINTF(_args_) MAIOSDebugPrint _args_ #define ERRORPRINTF(_args_) MAIOSDebugPrint _args_#else #define DPRINTF(_args_) /* MAIOSDebugPrint _args_ */ #define APIPRINTF(_args_) /* MAIOSDebugPrint _args_ */ #define ERRORPRINTF(_args_) /* MAIOSDebugPrint _args_ */#endif#define DEFAULT_INBUFSIZE 4*1024 /* 4KB buffer can hold 250ms @ 128kbit/sec (gives time for thread context switch) */#define DEFAULT_INBUFCOUNT 64//#define DUMP_TO_FILE //#define DUMP_AUDIO_TO_FILE#ifdef DUMP_AUDIO_TO_FILE #define DUMPAUDIO(bb, ss) dump_audio((unsigned char *)bb, ss) void dump_audio(unsigned char *buf, unsigned int size) { static FILE *ofp = NULL; #if defined(UNDER_CE) if (ofp == NULL) ofp = fopen("\\Hard Disk\\cedumpmpa.pcm", "wb"); #elif defined(WIN32) if (ofp == NULL) ofp = fopen("c:\\temp\\windumpmpa.pcm", "wb"); #else if (ofp == NULL) ofp = fopen("dumpmpa.pcm", "wb"); #endif if (ofp != NULL) fwrite(buf, 1, size, ofp); }#else #define DUMPAUDIO(bb, ss) #endif/* Decoder State Definitions: MAI_RUNSTATE_NONE - decoder not initialized MAI_RUNSTATE_INIT - decoder initialized, decodes not started yet MAI_RUNSTATE_PLAYING - decoder initialized, decodes active MAI_RUNSTATE_PAUSED - decoder initialized, decodes paused MAI_RUNSTATE_DESTROYING - MAICompEnd() in progress - destroying decoder*//* Our component's private processor variables are stored here */typedef struct ProcessorInfo_s { unsigned int m_uiProcessLoops; unsigned int m_uiStreamPosition; unsigned int m_bNewFormat; unsigned int m_uiPrevSRate; unsigned int m_nPrevChannels; unsigned char *m_pucAudioInBuf; MPEG_codec *m_codec; MPEG_codecContext *m_cc; MPADecodeContext *m_sc;} ProcessorInfo_t;static MAIStatus_e open_mpadec(MAICompHandle_t hComp){ ProcessorInfo_t *pPInfo=(ProcessorInfo_t *)HCOMP_TO_USERINFO(hComp); pPInfo->m_uiProcessLoops = 0; if (pPInfo->m_cc != NULL) avcodec_close(pPInfo->m_cc); memset(&mpeg_decoder, 0, sizeof(MPEG_codec)); APIPRINTF((M_TEXT("MPADEC: open_mpadec() Init codec\n"))); pPInfo->m_codec = &mpeg_decoder; // does layers 1, 2, and 3 pPInfo->m_cc = &pPInfo->m_codec->context; /* open the MPA audio decoder */ if (avcodec_open(pPInfo->m_cc, pPInfo->m_codec) < 0) { ERRORPRINTF((M_TEXT("MPADEC: open_mpadec() Could not open codec\n"))); return MAI_STATUS_EXECFAILED; } pPInfo->m_sc = pPInfo->m_cc->priv_data; pPInfo->m_uiPrevSRate=0; pPInfo->m_nPrevChannels=0; pPInfo->m_bNewFormat = 1; return MAI_STATUS_OK;}MAIStatus_e _startprocessing(MAICompHandle_t hComp){ #if defined(UNDER_CE) int ThreadPriority; #endif MAIStatus_e eStatus = MAI_STATUS_OK; APIPRINTF((M_TEXT("MPADEC: _startprocessing() enter\n"))); #if defined(UNDER_CE) ThreadPriority = CeGetThreadPriority(GetCurrentThread()); DPRINTF((M_TEXT("MPADEC: ThreadPriority %d\n"), ThreadPriority)); CeSetThreadPriority(GetCurrentThread(),ThreadPriority - 10); #endif if (!MAICompBase_IsState(hComp, MAI_RUNSTATE_NONE)) eStatus=MAI_STATUS_WRONGSTATE; else { APIPRINTF((M_TEXT("MPADEC: _startprocessing() Init codec\n"))); open_mpadec(hComp); /* Register output setup (needed for Read/WriteBuffer) */ MAICompBase_RegisterOutput(hComp, 0, M_NULL /* pfOutputGetBuffer */, M_NULL /* pfOutputPutBuffer */, hComp, 8*1024, 64); } if (eStatus==MAI_STATUS_OK) { MAICompHandleInfo_t *pCompInfo=HCOMP_TO_HANDLEINFO(hComp); /* update codec name in Component info */ if (mpeg_decoder.decode_context.mpeg25) strncpy(pCompInfo->Info.pszDesc, "MPEG2.5 layer 3", 16); else if (mpeg_decoder.decode_context.lsf || (mpeg_decoder.decode_context.nb_channels > 2)) sprintf(pCompInfo->Info.pszDesc, "MPEG 2 layer %d", mpeg_decoder.decode_context.layer); else sprintf(pCompInfo->Info.pszDesc, "MPEG 1 layer %d", mpeg_decoder.decode_context.layer); /* call default StartProcessing */ MAICompBase_StartProcessing(hComp); } APIPRINTF((M_TEXT("MPADEC: _startprocessing() exit: status=0x%X\n"), eStatus)); return eStatus;}static void close_mpadec(MAICompHandle_t hComp){ ProcessorInfo_t *pPInfo=(ProcessorInfo_t *)HCOMP_TO_USERINFO(hComp); APIPRINTF((M_TEXT("MPADEC: close_mpadec(cc=%p)\n"), pPInfo->m_cc)); if (pPInfo->m_cc != NULL) avcodec_close(pPInfo->m_cc); pPInfo->m_cc = NULL; pPInfo->m_uiProcessLoops = 0;}MAIStatus_e _endprocessing(MAICompHandle_t hComp){ ProcessorInfo_t *pPInfo=(ProcessorInfo_t *)HCOMP_TO_USERINFO(hComp); MAIStatus_e eStatus = MAI_STATUS_OK; APIPRINTF((M_TEXT("MPADEC: _endprocessing() enter\n"))); if (MAICompBase_IsState(hComp, MAI_RUNSTATE_NONE)) eStatus=MAI_STATUS_WRONGSTATE; else { close_mpadec(hComp); } MAICompBase_EndProcessing(hComp); APIPRINTF((M_TEXT("MPADEC: _endprocessing() exit: status=0x%X\n"), eStatus)); return eStatus;}MAIStatus_e _processbuffer(MAICompHandle_t hComp, MAICompBuffer_t *pInBufferInfo){ ProcessorInfo_t *pPInfo=(ProcessorInfo_t *)HCOMP_TO_USERINFO(hComp); MAIStatus_e eStatus = MAI_STATUS_OK; int insize = pInBufferInfo->uiDataSize; uint8_t *inbuf = pInBufferInfo->pBuffer; uint8_t *inbuf_ptr = inbuf; unsigned int uiBufFlags=pInBufferInfo->dwFlags; MAICompBuffer_t BufferInfo; DPRINTF((M_TEXT("MPADEC: _processbuffer() enter: uiDataSize=%d flags=0x%08X\n"), pInBufferInfo->uiDataSize, pInBufferInfo->dwFlags)); #ifdef DUMP_TO_FILE { static FILE *ofp = NULL; DPRINTF((M_TEXT("MPEG dump to file\n"))); #if defined(UNDER_CE) if (ofp == NULL) ofp = fopen("\\Hard Disk\\cedump.mpa", "wb"); #elif defined(WIN32) if (ofp == NULL) ofp = fopen("c:\\temp\\windump.mpa", "wb"); #else if (ofp == NULL) ofp = fopen("dump.mpa", "wb"); #endif if (ofp != NULL) fwrite(pInBufferInfo->pBuffer, 1, pInBufferInfo->uiDataSize, ofp); } #endif if (pInBufferInfo->uiDataSize) /* we got actual input data */ { /* we are playing again, ensure we are not in IDLE state */ if (MAICompBase_IsState(hComp, MAI_RUNSTATE_IDLE|MAI_RUNSTATE_STARTING)) MAICompBase_ChangeState(hComp, MAI_RUNSTATE_PLAYING); } while ((insize > 0) && (eStatus==MAI_STATUS_OK)) { int out_size; int bytesdecoded; if (pPInfo->m_cc == NULL) open_mpadec(hComp); bytesdecoded = avcodec_decode_audio(pPInfo->m_cc, (short *)pPInfo->m_sc->outbuf, &out_size, inbuf_ptr, insize); if (bytesdecoded < 0) { ERRORPRINTF((M_TEXT("MPADEC: _processbuffer() Error while decoding: bytesdecoded=%d\n"), bytesdecoded)); return MAI_STATUS_ERROR; } if (out_size > 0) { if (pPInfo->m_uiPrevSRate != (unsigned int)pPInfo->m_sc->sample_rate) { pPInfo->m_uiPrevSRate = (unsigned int)pPInfo->m_sc->sample_rate; pPInfo->m_bNewFormat = 1; } if (pPInfo->m_nPrevChannels != (unsigned int)pPInfo->m_sc->nb_channels) { pPInfo->m_nPrevChannels = (unsigned int)pPInfo->m_sc->nb_channels; pPInfo->m_bNewFormat = 1; } if (pPInfo->m_bNewFormat) { MAIMediaTypeAudio_t AudioInfo; MAIMediaTypeAudio_t *pAudioInfo=&AudioInfo; DPRINTF((M_TEXT("MPADEC: _processbuffer() New Format\n"))); pPInfo->m_bNewFormat = 0; /* clear EOS flag, we're on a new stream */ MAICompBase_SetEOS(hComp, EOS_NONE); MAICompBase_SetFormatState(hComp, FORMAT_STATE_KNOWN); memset(pAudioInfo, 0, sizeof(MAIMediaTypeAudio_t)); pAudioInfo->MediaTypeInfo.uiSize=sizeof(MAIMediaTypeAudio_t); pAudioInfo->MediaTypeInfo.eMType=MAI_MTYPE_AUDIO; pAudioInfo->MediaTypeInfo.eMSubtype=MAI_MSUBTYPE_PCM; pAudioInfo->MediaTypeInfo.uiFlags=0; pAudioInfo->uiFlags = 0; pAudioInfo->uiModeFlags = 0; pAudioInfo->uiBitsPerSample = 16; pAudioInfo->uiMaxBufSize = 8192; pAudioInfo->uiChannels = pPInfo->m_sc->nb_channels; pAudioInfo->uiSamplesPerSec = pPInfo->m_sc->sample_rate; APIPRINTF((M_TEXT("MPADEC: _processbuffer() NEWFORMAT: %d ch, %d rate, %d bits, %d bufsize\n"), pAudioInfo->uiChannels, pAudioInfo->uiSamplesPerSec, pAudioInfo->uiBitsPerSample, pAudioInfo->uiMaxBufSize)); BufferInfo.dwFlags = MAICOMPBUF_FLAG_NEWFORMAT|MAICOMPBUF_FLAG_AUDIO; BufferInfo.tTimeStamp = 0; BufferInfo.pBuffer = (unsigned char *)pAudioInfo; BufferInfo.uiBufSize = 0; BufferInfo.uiDataSize = sizeof(MAIMediaTypeAudio_t); MAICompBase_OutputPutBuf(hComp, 0, &BufferInfo); } /* if a frame has been decoded, output it */ DPRINTF((M_TEXT("MPADEC: _processbuffer() OutputPutBuf(%d)\n"), out_size)); BufferInfo.dwFlags = 0; /* default - no special flags */ BufferInfo.tTimeStamp = 0; if (pInBufferInfo && (uiBufFlags&MAICOMPBUF_FLAG_PTS)!=0) /* input buffer was timestamped */ { MAITIME_ASSIGN(BufferInfo.tTimeStamp, pInBufferInfo->tTimeStamp); MAICompBase_UpdateTime(hComp, 0, BufferInfo.tTimeStamp); DPRINTF((M_TEXT("MPADEC: _processbuffer() pass PTS=%u\n"), (unsigned int)(BufferInfo.tTimeStamp))); BufferInfo.dwFlags |= MAICOMPBUF_FLAG_PTS; MAICompBase_ReportTime(hComp, 0); uiBufFlags&=~MAICOMPBUF_FLAG_PTS; /* clear PTS flag, report only once for this buffer */ } if ((uiBufFlags&MAICOMPBUF_FLAG_DATADISCON)!=0) /* check for discontinuity */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -