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

📄 maimp4demux.c

📁 mpeg4 demux 代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* <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>
 * File: maimp4demux.c
 * Date: 03/14/05
 * </DOC_AMD_STD>  */

#define FILESOURCE /* use direct file reads */

// Windows Header Files:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <memory.h> /* for memset */
#include <string.h> /* for strcpy */

#include "mp4parse.h"
#include "mai_osal.h"
#include "mai_component.h"
#include "mai_param.h"

#ifdef TRACE_BUILD
#define DPRINTF(_args_)     MAIOSDebugPrint _args_
#define APIPRINTF(_args_)   MAIOSDebugPrint _args_
#define PUTPRINTF(_args_)   //MAIOSDebugPrint _args_
#define GETPRINTF(_args_)   //MAIOSDebugPrint _args_
#define ERRORPRINTF(_args_) MAIOSDebugPrint _args_
#else
#define DPRINTF(_args_)     /* MAIOSDebugPrint _args_ */
#define APIPRINTF(_args_)   /* MAIOSDebugPrint _args_ */
#define PUTPRINTF(_args_)   /* MAIOSDebugPrint _args_ */
#define GETPRINTF(_args_)   /* MAIOSDebugPrint _args_ */
#define ERRORPRINTF(_args_) /* MAIOSDebugPrint _args_ */
#endif

#define AUDIO_READ_AHEAD   500  /* max audio in millisecs to read ahead of audio (help prevent audio gaps) */
#define MAX_READ_PERSTREAM 500  /* max data in millisecs to read from a stream per loop (larger reduces seeks) */

/* Global Variables */
static pfMAICompGetBufferCB_t   g_pfOutputVideoGetBuf = NULL;
static pfMAICompPutBufferCB_t   g_pfOutputVideoPutBuf = NULL;
static MAICompHandle_t          g_hOutputVideoOwner=M_HANDLE_INVALID;
static pfMAICompGetBufferCB_t   g_pfOutputAudioGetBuf = NULL;
static pfMAICompPutBufferCB_t   g_pfOutputAudioPutBuf = NULL;
static MAICompHandle_t          g_hOutputAudioOwner=M_HANDLE_INVALID;
static MAICompBufferPool_t      g_hInBufferPool=M_HANDLE_INVALID;

/* local */
static MAICompHandle_t          g_hReaderComp = M_HANDLE_INVALID; /* this is a handle to the FileReader component */
static MAIRunState_e            g_eCompState=MAI_RUNSTATE_NONE;
static MAIOSThread_t            g_hThread=M_HANDLE_INVALID;
static unsigned int             g_uiThreadPriority=MAICOMP_DEFAULT_THREAD_PRIORITY;
m_bool		                      g_bTerminate=0;
static unsigned int             g_uiInBufferSize=64*1024;
static unsigned int             g_uiInMaxBuffers=2;
static pfMAICompErrorCB_t       g_pfErrorCB = NULL;
static pfMAICompProgressCB_t    g_pfProgressCB = NULL;
static unsigned int             g_uiProgressSelectFlags = 0; /* flags enabling progress calls */
static MAIMediaTypeStream_t     g_StreamInfo;
static MAITimeStamp_t           g_tLastPTS = 0;
static m_bool                   g_bLooping = M_FALSE;
static m_bool                   g_bSeekPending = M_FALSE;
static m_s32                    g_lSeekValue = 0;
static MAISeekType_e            g_eSeekType = MAI_SEEKTYPE_NONE; /* MAI_SEEKTYPE_ABS, _ABSPCT, _REL, _RELPCT */
static m_bool                   g_bInit = M_FALSE; /* is the file open and demux successfully initialized */
static m_bool                   g_bVDiscon; /* video stream discontinuity (i.e. seek, loop) */
static m_bool                   g_bADiscon; /* audio stream discontinuity (i.e. seek, loop) */
static m_bool                   g_bFirstRead;  /* TRUE if we have not read first buffer at the stream starting position */
static unsigned int             g_eEOS;

static MAISpeed_e               g_uiCurrentSpeed = MAI_SPEED_NORMAL;
static MAISpeed_e               g_uiNextSpeed = 0;
static m_bool                   g_bSpeedChange = M_FALSE;  /* TRUE if speed is being changed */
static unsigned int             g_uiPlaySleep = 0; /* time to sleep between each segment that's delivered */

/* End-Of-Stream states */
#define EOS_NONE                   0x0000
#define EOS_ON_INPUT               0x0001  /* an EOS has been reported on a input buffer */
#define EOS_ON_INPUT_WITH_BUFFERS  0x0002  /* an EOS has been reported on an input buffer, but data is still queued */
#define EOS_DELIVERED              0x8000  /* EOS has been reported to app */

static m_tchar                  m_pszFilePath[300]; /* current file (if not connected to filereader) */

static m_bool                   g_bFileOpen=M_FALSE;

static m_u32 g_uiAudioSampleCount=0; /* total Audio samples */
static m_u32 g_uiVideoSampleCount=0; /* total Video samples */
static m_u32 g_uiAudioSampleNum=0; /* current Audio sample */
static m_u32 g_uiVideoSampleNum=0; /* current Video sample */

MAIOSFile_t						g_hFile;

// Main Thread
static m_u32 DemuxThread(MAIOSThread_t hThread, void *pUserData);
MAIStatus_e _startprocessing(MAICompHandle_t hComp);
MAIStatus_e _endprocessing(MAICompHandle_t hComp);

static MAIStatus_e MAIMP4Demux_GetBuffer(MAICompHandle_t hComp,MAICompBuffer_t **ppBufferInfo);
static MAIStatus_e MAIMP4Demux_PutBuffer(MAICompHandle_t hComp,MAICompBuffer_t *pBufferInfo);

void _SendProgressCB(MAICompHandle_t hComp, unsigned int uiFlags)
{
  APIPRINTF((M_TEXT("MP4DEMUX: _SendProgressCB(Flags=0x%X)\n"), uiFlags));
  if (g_pfProgressCB)
  {
    MAIProgressStream_t SProgressInfo;
    memset(&SProgressInfo, 0, sizeof(MAIProgressStream_t));
    SProgressInfo.hComp=hComp;
    SProgressInfo.uiFlags=uiFlags;
    //if (pCompInfo->m_ePTSState==PTS_STATE_KNOWN)
    //{
    //  SProgressInfo.uiFlags |= MAICOMPBUF_FLAG_PTS;
    //  MAITIME_ASSIGN(SProgressInfo.tCurrentTime, pCompInfo->m_tLastPTS);
    //}
    g_pfProgressCB(hComp, MAI_PROGRESS_STREAM, &SProgressInfo, sizeof(MAIProgressStream_t));
  }
}

/* HWG - file wrapper routines to allow streaming input */
static unsigned int g_uiOffset=0;
static unsigned int g_bInputEOS=0;

static MAIStatus_e inputopen()
{
  MAIStatus_e eStatus = MAI_STATUS_OK;
  APIPRINTF((M_TEXT("MP4DEMUX: inputopen()\n")));
  if (!g_bFileOpen)
  {
    if (g_hReaderComp!=M_HANDLE_INVALID)
    {
      APIPRINTF((M_TEXT("MP4DEMUX: inputopen() Using Reader Comp: %p\n"), g_hReaderComp));
      g_uiOffset=0;
      g_bInputEOS=0;
      g_bFileOpen=M_TRUE;
    }
    else
    {
#ifdef FILESOURCE
	    g_hFile = MAIOSFileOpenForRead(m_pszFilePath);
	    if(g_hFile == NULL)
	    {
		    eStatus=MAI_STATUS_OPENERROR;
		    ERRORPRINTF((M_TEXT("MP4DEMUX: inputopen() Error opening input file [%s].\n"),m_pszFilePath));
		    g_bFileOpen=M_FALSE;
        g_uiOffset=0;
        g_bInputEOS=1;
	    }
      else
        g_bFileOpen=M_TRUE;
#else
      g_bFileOpen=M_TRUE;
#endif
      if (g_bFileOpen) /* successfully opened */
      {
        APIPRINTF( M_TEXT(("MP4DEMUX: inputopen() File opened\n")) );
        g_uiOffset=0;
        g_bInputEOS=0;
        g_StreamInfo.LenInBytes=0; //_streamlength(hComp);
        g_bFirstRead=M_TRUE;
        //_newposition(pPInfo, 0);  /* assume file starts at zero timestamp */
        //pPInfo->m_bFormatChange=M_TRUE;
        g_bVDiscon=M_FALSE;
        g_bADiscon=M_FALSE;
      }
    }
  }
  return eStatus;
}

static void inputclose(MAICompHandle_t hComp)
{
  APIPRINTF((M_TEXT("MP4DEMUX: inputclose()\n")));
	if (g_bFileOpen) /* close old file if open */
	{
        APIPRINTF( (M_TEXT("MP4DEMUX: inputclose() Send EOS\n")) );
        _SendProgressCB(hComp, MAI_PROGRESSFLAG_EOS);

		MAIOSFileClose(g_hFile);
		g_bFileOpen=M_FALSE;
	}
}

MAIStatus_e inputread(unsigned char *pucData, unsigned int uiSize, unsigned int *puiBytesRead)
{
  unsigned int uiTotalRead=0;
  MAIStatus_e eStatus=MAI_STATUS_NOBUFAVAIL;
  GETPRINTF((M_TEXT("MP4DEMUX: inputread(size=%d) actualoffset=%d\n"), uiSize, g_uiOffset));

  if (!g_bTerminate)
  {
    if (g_hReaderComp!=M_HANDLE_INVALID)
    {
      MAICompBuffer_t BufferInfo;
      MAICompBuffer_t *pBufferInfo=&BufferInfo;
      BufferInfo.dwFlags=0;
      BufferInfo.uiBufSize=uiSize;
      BufferInfo.uiDataSize=0;
      BufferInfo.pBuffer=pucData;
      eStatus=MAIComp_ReadBuffer(g_hReaderComp, 0, &pBufferInfo, MAI_TIMEOUT_INFINITE);
      uiTotalRead+=BufferInfo.uiDataSize;
    }
    else
    {
#ifdef FILESOURCE
		  eStatus=MAIOSFileRead(g_hFile, pucData, uiSize, &uiTotalRead);
#else
      MAICompBuffer_t BufferInfo;
      BufferInfo.dwFlags=0;
      /* get an empty buffer from the buffer pool */
      do
      {
        BufferInfo.uiBufSize=uiSize-uiTotalRead;
        BufferInfo.pBuffer=pucData+uiTotalRead;
        eStatus=MAICompBufferPoolRead(g_hInBufferPool, &BufferInfo, g_bInputEOS?MAI_TIMEOUT_NONE:MAI_TIMEOUT_INFINITE);
        uiTotalRead+=BufferInfo.uiDataSize;
        if ((BufferInfo.dwFlags&MAICOMPBUF_FLAG_EOS)!=0)
          g_bInputEOS=1;
      } while (eStatus==MAI_STATUS_OK && uiTotalRead<uiSize && !g_bInputEOS);
#endif
    }
    GETPRINTF((M_TEXT("MP4DEMUX: inputread(size=%d) return %d bytes: 0x%02X 0x%02X\n"), uiSize, uiTotalRead, pucData[0], pucData[1]));
  }
  if (puiBytesRead)
    *puiBytesRead=uiTotalRead;
  g_uiOffset+=uiTotalRead;
  return eStatus;
}

MAIStatus_e inputseek(unsigned int uiOffset)
{
  MAIStatus_e eStatus=MAI_STATUS_OK;
  GETPRINTF((M_TEXT("MP4DEMUX: inputseek(offset=%d) actualoffset=%d\n"), uiOffset, g_uiOffset));
  if (g_hReaderComp!=M_HANDLE_INVALID)
  {
    eStatus=MAIComp_SendCommand(g_hReaderComp, MAICOMP_CMD_SEEK, MAI_SEEKTYPE_ABS, uiOffset);
    g_uiOffset=uiOffset;
  }
  else
  {
#ifdef FILESOURCE
	  eStatus=MAIOSFileSeek(g_hFile, uiOffset);
    g_uiOffset=uiOffset;
#else
    if (uiOffset>g_uiOffset)
      inputadvance(uiOffset-g_uiOffset);
    if (uiOffset!=g_uiOffset)
    {
      ERRORPRINTF((M_TEXT("MP4DEMUX: inputseek(offset=%d) actualoffset=%d: SEEK backwards\n"), uiOffset, g_uiOffset));
      eStatus=MAI_STATUS_UNSUPPORTED;
    }
#endif
  }
  return eStatus;
}

static unsigned int inputpeek(unsigned char *pucData, unsigned int uiSize, unsigned int *puiBytesRead)
{
  unsigned int uiTotalRead=0;
  MAIStatus_e eStatus=MAI_STATUS_NOBUFAVAIL;
  GETPRINTF((M_TEXT("MP4DEMUX: inputpeek(size=%d) actualoffset=%d\n"), uiSize, g_uiOffset));

  if (!g_bTerminate)
  {
#ifdef FILESOURCE
		eStatus=inputread(pucData, uiSize, &uiTotalRead);
  	eStatus=inputseek(g_uiOffset);
#else
    MAICompBuffer_t BufferInfo;
    MAICompBuffer_t *pBufferInfo=&BufferInfo;
    BufferInfo.dwFlags=0;
    BufferInfo.uiBufSize=uiSize;
    BufferInfo.uiDataSize=0;
    BufferInfo.pBuffer=pucData;
    eStatus=MAICompBufferPoolPeek(g_hInBufferPool, &pBufferInfo, MAI_TIMEOUT_INFINITE);
    if (pBufferInfo!=&BufferInfo) /* if peek returned a different buffer, copy the data to ours */
    {
      uiTotalRead=(pBufferInfo->uiDataSize<uiSize)?pBufferInfo->uiDataSize:uiSize;
      memcpy(pucData, pBufferInfo->pBuffer, uiTotalRead);
    }
    else
      uiTotalRead=BufferInfo.uiDataSize;
#endif
    GETPRINTF((M_TEXT("MP4DEMUX: inputpeek(size=%d) return %d bytes: 0x%02X 0x%02X\n"), uiSize, uiTotalRead, pucData[0], pucData[1]));
  }
  if (puiBytesRead)
    *puiBytesRead=uiTotalRead;
  return uiTotalRead;
}

/* advance the file position (seek forward) */
static unsigned int inputadvance(unsigned int uiBytes)
{
  unsigned char pucDummyBuf[4*1024];
  unsigned int uiTotalSkipped=0;
  /* we just issue dummy reads to advance to file position */
  while (uiBytes>0)
  {
    unsigned int uiRead=0;
    inputread(pucDummyBuf, (uiBytes>sizeof(pucDummyBuf))?sizeof(pucDummyBuf):uiBytes, &uiRead);
    uiBytes-=uiRead;
  }
  return uiTotalSkipped;
}

static int inputpos()
{
  return g_uiOffset;
}

MAIStatus_e _streamseek(MAICompHandle_t hComp, long lSeekValue, MAISeekType_e eSeekType)
{
  //ProcessorInfo_t *pPInfo=(ProcessorInfo_t *)HCOMP_TO_USERINFO(hComp);
	MAIStatus_e eStatus = MAI_STATUS_NOTOPEN;
  GETPRINTF( (M_TEXT("MP4DEMUX: _streamseek(SeekValue=%d, SeekType=%d)\n"), (unsigned int)lSeekValue, eSeekType) );
  if (g_bFileOpen)
  {
    unsigned int uiNewVSamplePosition=0, uiNewASamplePosition=0;
    if (eSeekType==MAI_SEEKTYPE_ABSTIME)
    {
      if (!g_bInit)
      {
        /* stream is not open yet, allow only to start */
        if (!lSeekValue) /* seek to start allowed */
          eStatus=inputseek((m_u32)lSeekValue);
        else

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -