382 lines
8.3 KiB
C++
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;
|
|
} |