2025-04-27 07:49:33 -04:00

382 lines
8.3 KiB
C++

/*
Copyright (c) 1999 Microsoft Corporation
Module Name:
AVIFileReader.cpp
Abstract:
Implementation of CAVIFileReader class
*/
#include "common.h"
#include "AVIFileReader.h"
///////////////////////////////////////////////////////////////////////////////
//
// CAVIFileReader::CAVIFileReader
//
///////////////////////////////////////////////////////////////////////////////
CAVIFileReader::CAVIFileReader()
:m_pAudioStream(NULL),
m_pWaveFormat(NULL),
m_nSamplesReadSoFar(0)
{
LogMessage("CAVIFileReader::CAVIFileReader");
}
///////////////////////////////////////////////////////////////////////////////
//
// CAVIFileReader::Initialize
//
// open the first audio stream contained in file pszFileName.
// if successful, also get the stream's format
//
// if the file does not exist, is not valid, or does not contain
// any audio streams, subsequent calls to Read() will fail
//
///////////////////////////////////////////////////////////////////////////////
HRESULT CAVIFileReader::Initialize(IN char *pszFileName)
{
HRESULT hr = S_OK;
//
// would do better argument checking in a real-life application
//
_ASSERTE(pszFileName);
//
// log file name and requested wave format
//
LogMessage("CAVIFileReader::Initialize started. file [%s]",
pszFileName);
//
// initialize avi file library. AVIFileExit should be called on the same
// thread when AVI library is no longer needed
//
// AVIFileExit is called in the destructor.
//
// Assuption: instances of CAVIFileReader are initialized and destroyed on
// the same thread
//
AVIFileInit();
//
// open the first audio stream in the file
//
hr = AVIStreamOpenFromFile(&m_pAudioStream,
pszFileName,
streamtypeAUDIO,
0,
OF_READ | OF_SHARE_DENY_WRITE,
NULL);
if (FAILED(hr))
{
LogError("CAVIFileReader::Initialize "
"Failed to open stream from the file");
m_pAudioStream = NULL;
return hr;
}
//
// read the size of the stream's format
//
LONG nFormatSize = 0;
hr = AVIStreamReadFormat(m_pAudioStream, 0, NULL, &nFormatSize);
if ( FAILED(hr) || (0 == nFormatSize) )
{
LogError("CAVIFileReader::Initialize"
"Failed to get stream format's size");
m_pAudioStream->Release();
m_pAudioStream = NULL;
return E_FAIL;
}
//
// allocate memory for audio format. keep it in a waveformatex structure.
// if the structure returned is waveformat, still allocate waveformatex
//
nFormatSize = max(sizeof(WAVEFORMATEX), nFormatSize);
m_pWaveFormat = (WAVEFORMATEX*)AllocateMemory(nFormatSize);
if (NULL == m_pWaveFormat)
{
LogError("CAVIFileReader::Initialize "
"Failed to allocate memory for wave format, size %ld",
nFormatSize);
m_pAudioStream->Release();
m_pAudioStream = NULL;
return E_OUTOFMEMORY;
}
//
// read stream format into allocated structure
//
hr = AVIStreamReadFormat(m_pAudioStream, 0, m_pWaveFormat, &nFormatSize);
if (FAILED(hr))
{
LogError("CAVIFileReader::Initialize "
"Failed to read stream format");
m_pAudioStream->Release();
m_pAudioStream = NULL;
FreeMemory(m_pWaveFormat);
m_pWaveFormat = NULL;
return hr;
}
//
// log stream's format
//
LogMessage("CAVIFileReader::CAVIFileReader stream opened");
LogFormat(m_pWaveFormat);
LogMessage("CAVIFileReader::CAVIFileReader finished");
return S_OK;
}
///////////////////////////////////////////////////////////////////////////////
//
// CAVIFileReader::~CAVIFileReader
//
// if we succeeded opening the stream, close it now.
//
///////////////////////////////////////////////////////////////////////////////
CAVIFileReader::~CAVIFileReader()
{
LogMessage("CAVIFileReader::~CAVIFileReader started");
if (NULL != m_pAudioStream)
{
AVIStreamRelease(m_pAudioStream);
m_pAudioStream = NULL;
}
if (NULL != m_pWaveFormat)
{
FreeMemory(m_pWaveFormat);
m_pWaveFormat = NULL;
}
//
// AVIFileExit must be called on the same thread as AVIFileInit.
// therefore this object must be created and deleted on the same thread
//
AVIFileExit();
LogMessage("CAVIFileReader::~CAVIFileReader completed");
}
///////////////////////////////////////////////////////////////////////////////
//
// CAVIFileReader::Read
//
// read the open stream, at the current stream position,
// into the supplied buffer of specified length.
// return the number of bytes read
//
// returns: S_OK if succeded, S_FALSE if no more data, failure if failed.
//
///////////////////////////////////////////////////////////////////////////////
HRESULT CAVIFileReader::Read( IN BYTE *pBuffer,
IN LONG nBufferSize,
IN OUT LONG *pBytesRead)
{
//
// don't return garbage
//
*pBytesRead = 0;
//
// fail if the file is not open
//
if (NULL == m_pWaveFormat)
{
//
// file is not open
//
LogError("CAVIFileReader::Read file is not open");
return E_FAIL;
}
HRESULT hr = E_FAIL;
//
// read data into the user-supplied buffer, starting with the current
// stream position
//
LONG nSamplesRead = 0;
hr = AVIStreamRead(m_pAudioStream,
m_nSamplesReadSoFar,
AVISTREAMREAD_CONVENIENT,
pBuffer,
nBufferSize,
pBytesRead,
&nSamplesRead);
if (FAILED(hr))
{
LogError("CAVIFileReader::Read AVIStreamRead failed");
*pBytesRead = 0;
return hr;
}
//
// keep track of how many samples we have read, so we know where
// to start next time
//
m_nSamplesReadSoFar += nSamplesRead;
if (*pBytesRead == 0)
{
LogMessage("CAVIFileReader::Read no more data in the file");
return S_FALSE;
}
LogMessage("CAVIFileReader::Read read %ld bytes (%ld samples)",
*pBytesRead, nSamplesRead);
return S_OK;
}
///////////////////////////////////////////////////////////////////////////////
//
// CAVIFileReader::GetFormat
//
// returns the wave format structure. the caller is responsible for
// freeing the structure by calling FreeMemory()
//
// returns S_OK if success or E_FAIL if the file failed to open
//
///////////////////////////////////////////////////////////////////////////////
HRESULT CAVIFileReader::GetFormat(OUT WAVEFORMATEX **ppWaveFormat)
{
HRESULT hr = E_FAIL;
//
// don't return garbage
//
*ppWaveFormat = NULL;
//
// fail if the file is not open
//
if (NULL == m_pWaveFormat)
{
//
// file is not open
//
LogError("CAVIFileReader::GetFormat file is not open");
return E_FAIL;
}
//
// allocate memory for wave format structure
//
WAVEFORMATEX *pWaveFormat =
(WAVEFORMATEX *)AllocateMemory( sizeof(WAVEFORMATEX) +
m_pWaveFormat->cbSize);
if (NULL == pWaveFormat)
{
LogError("CAVIFileReader::GetFormat "
"failed to allocate memory for wave format structure");
return E_OUTOFMEMORY;
}
//
// copy wave format structure into allocated memory
//
CopyMemory(pWaveFormat,
m_pWaveFormat,
sizeof(WAVEFORMATEX) + m_pWaveFormat->cbSize);
*ppWaveFormat = pWaveFormat;
return S_OK;
}