www.pudn.com > avi_file_source.rar > AVI_FileSource.cpp


//------------------------------------------------------------------------------ 
// File: AsyncFlt.cpp 
// 
// Desc: DirectShow sample code - implementation of CAsyncFilter. 
// 
// Copyright (c) Microsoft Corporation.  All rights reserved. 
//------------------------------------------------------------------------------ 
 
#include "stdafx.h" 
#include  
 
 
#include "asyncio.h" 
#include "asyncrdr.h" 
 
#include "AVI_FileSource.h" 
 
// 
// Setup data for filter registration 
// 
const AMOVIESETUP_MEDIATYPE sudOpPinTypes[] = 
{  
	{ &MEDIATYPE_Stream,     // clsMajorType 
	  &MEDIASUBTYPE_Avi // clsMinorType 
	}, 
	{ &MEDIATYPE_Stream,     // clsMajorType 
	  &MEDIASUBTYPE_NULL // clsMinorType 
	} 
};  
 
const AMOVIESETUP_PIN sudOpPin = 
{ L"Output"          // strName 
, FALSE              // bRendered 
, TRUE               // bOutput 
, FALSE              // bZero 
, FALSE              // bMany 
, &CLSID_NULL        // clsConnectsToFilter 
, L"Input"           // strConnectsToPin 
, 2                  // nTypes 
, &sudOpPinTypes[0] };  // lpTypes 
 
const AMOVIESETUP_FILTER sudAsync = 
{ &CLSID_AVI_File_Source              // clsID 
, L"AVI_File_Source"  // strName 
, MERIT_UNLIKELY                  // dwMerit 
, 1                               // nPins 
, &sudOpPin };                    // lpPin 
 
 
// 
//  Object creation template 
// 
CFactoryTemplate g_Templates[1] = { 
    { L"AVI_File_Source" 
    , &CLSID_AVI_File_Source 
    , CAsyncFilter::CreateInstance 
    , NULL 
    , &sudAsync } 
}; 
 
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]); 
 
 
//////////////////////////////////////////////////////////////////////// 
// 
// Exported entry points for registration and unregistration  
// (in this case they only call through to default implementations). 
// 
//////////////////////////////////////////////////////////////////////// 
 
STDAPI DllRegisterServer() 
{ 
    return AMovieDllRegisterServer2(TRUE); 
} 
 
STDAPI DllUnregisterServer() 
{ 
    return AMovieDllRegisterServer2(FALSE); 
} 
 
// 
// DllEntryPoint 
// 
extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID); 
 
BOOL APIENTRY DllMain(HANDLE hModule,  
                      DWORD  dwReason,  
                      LPVOID lpReserved) 
{ 
	return DllEntryPoint((HINSTANCE)(hModule), dwReason, lpReserved); 
} 
 
 
//* Create a new instance of this class 
CUnknown * WINAPI CAsyncFilter::CreateInstance(LPUNKNOWN pUnk, HRESULT *phr) 
{ 
    ASSERT(phr); 
 
    //  DLLEntry does the right thing with the return code and 
    //  the returned value on failure 
 
    return new CAsyncFilter(pUnk, phr); 
} 
 
 
/**************CAsyncFilter class implementation**********************/ 
CAsyncFilter::CAsyncFilter(LPUNKNOWN pUnk, HRESULT *phr) : 
        CAsyncReader(NAME("Mem Reader"), pUnk, &m_Stream, phr), 
        m_pFileName(NULL), 
        m_pbData(NULL) 
{ 
	RETAILMSG(1,(TEXT("AVI_File_Source_Filter: constructor\n"))); 
} 
 
CAsyncFilter::~CAsyncFilter() 
{ 
    delete [] m_pbData; 
    delete [] m_pFileName; 
} 
 
STDMETHODIMP CAsyncFilter::NonDelegatingQueryInterface(REFIID riid, void **ppv) 
{ 
    if (riid == IID_IFileSourceFilter) { 
        return GetInterface((IFileSourceFilter *)this, ppv); 
    } else { 
        return CAsyncReader::NonDelegatingQueryInterface(riid, ppv); 
    } 
} 
 
/*  IFileSourceFilter methods */ 
//  Load a (new) file 
STDMETHODIMP CAsyncFilter::Load(LPCOLESTR lpwszFileName, const AM_MEDIA_TYPE *pmt) 
{ 
    CheckPointer(lpwszFileName, E_POINTER); 
 
    // lstrlenW is one of the few Unicode functions that works on win95 
    int cch = lstrlenW(lpwszFileName) + 1; 
 
#ifndef UNICODE 
    TCHAR *lpszFileName=0; 
    lpszFileName = new char[cch * 2]; 
    if (!lpszFileName) { 
      	return E_OUTOFMEMORY; 
    } 
    WideCharToMultiByte(GetACP(), 0, lpwszFileName, -1, 
    		lpszFileName, cch, NULL, NULL); 
#else 
    TCHAR lpszFileName[MAX_PATH]={0}; 
    lstrcpy(lpszFileName, lpwszFileName); 
#endif 
    CAutoLock lck(&m_csFilter); 
 
    /*  Check the file type */ 
    CMediaType cmt; 
 
	/****Anil on 01-02-2007 - check the filename extension and set the mediaType accordingly****/ 
	/*  Find the extension */ 
	LPTSTR lpType; 
	int len = lstrlen(lpszFileName); 
	if(len >= 4 && lpszFileName[len - 4] == TEXT('.')) 
	{ 
		lpType = lpszFileName + len - 3; 
	 
		/* Set subtype based on file extension */ 
		if(lstrcmpi(lpType, TEXT("avi")) == 0) { 
			cmt.SetType(&MEDIATYPE_Stream); 
			cmt.SetSubtype(&MEDIASUBTYPE_Avi); 
			RETAILMSG(1,(TEXT("AVI_File_Source_Filter: Configuring SUBTYPE to AVI\n"))); 
		} 
		else 
		{ 
			cmt.SetType(&MEDIATYPE_Stream); 
			cmt.SetSubtype(&MEDIASUBTYPE_NULL); 
		} 
	} 
	else 
	{ 
	    if (NULL == pmt) { 
		    cmt.SetType(&MEDIATYPE_Stream); 
			cmt.SetSubtype(&MEDIASUBTYPE_NULL); 
	    } else { 
		    cmt = *pmt; 
		} 
	} 
 
 
    if (!ReadTheFile(lpszFileName)) { 
#ifndef UNICODE 
        delete [] lpszFileName; 
#endif 
        return E_FAIL; 
    } 
 
    m_Stream.Init(m_pbData, m_llSize,lpszFileName); 
 
    m_pFileName = new WCHAR[cch]; 
 
    if (m_pFileName!=NULL) 
    	CopyMemory(m_pFileName, lpwszFileName, cch*sizeof(WCHAR)); 
 
    // this is not a simple assignment... pointers and format 
    // block (if any) are intelligently copied 
    m_mt = cmt; 
 
    /*  Work out file type */ 
    cmt.bTemporalCompression = TRUE;	       //??? 
    cmt.lSampleSize = 1; 
 
    return S_OK; 
} 
 
// Modeled on IPersistFile::Load 
// Caller needs to CoTaskMemFree or equivalent. 
STDMETHODIMP CAsyncFilter::GetCurFile(LPOLESTR * ppszFileName, AM_MEDIA_TYPE *pmt) 
{ 
    CheckPointer(ppszFileName, E_POINTER); 
    *ppszFileName = NULL; 
 
    if (m_pFileName!=NULL) { 
        DWORD n = sizeof(WCHAR)*(1+lstrlenW(m_pFileName)); 
 
        *ppszFileName = (LPOLESTR) CoTaskMemAlloc( n ); 
        if (*ppszFileName!=NULL) { 
              CopyMemory(*ppszFileName, m_pFileName, n); 
        } 
    } 
 
    if (pmt!=NULL) { 
        CopyMediaType(pmt, &m_mt); 
    } 
 
    return NOERROR; 
} 
 
BOOL CAsyncFilter::ReadTheFile(LPCTSTR lpszFileName) 
{ 
    // Open the requested file 
    HANDLE hFile = CreateFile(lpszFileName, 
                              GENERIC_READ, 
                              FILE_SHARE_READ, 
                              NULL, 
                              OPEN_EXISTING, 
                              0, 
                              NULL); 
    if (hFile == INVALID_HANDLE_VALUE)  
    { 
        DbgLog((LOG_TRACE, 2, TEXT("Could not open %s\n"), lpszFileName)); 
        return FALSE; 
    } 
 
    // Determine the file size 
    ULARGE_INTEGER uliSize; 
    uliSize.LowPart = GetFileSize(hFile, &uliSize.HighPart); 
 
#if 0 
    PBYTE pbMem = new BYTE[uliSize.LowPart]; 
    if (pbMem == NULL)  
    { 
        CloseHandle(hFile); 
        return FALSE; 
    } 
 
 
    // Read the data from the file 
    if (!ReadFile(hFile, 
                  (LPVOID) pbMem, 
                  uliSize.LowPart, 
                  &dwBytesRead, 
                  NULL) || 
        (dwBytesRead != uliSize.LowPart)) 
    { 
        DbgLog((LOG_TRACE, 1, TEXT("Could not read file\n"))); 
 
        delete [] pbMem; 
        CloseHandle(hFile); 
        return FALSE; 
    } 
 
    // Save a pointer to the data that was read from the file 
    m_pbData = pbMem; 
#endif 
 
    m_llSize = (LONGLONG)uliSize.QuadPart; 
 
    // Close the file 
    CloseHandle(hFile); 
 
    return TRUE; 
} 
 
 
 
 
/*****************CMemStream class implementation*********************/ 
CMemStream::CMemStream() 
{ 
	this->m_llPosition = 0; 
	this->m_FileHandle = 0; 
} 
 
CMemStream::~CMemStream() 
{ 
	if(this->m_FileHandle) 
	{ 
		CloseHandle(this->m_FileHandle); 
	} 
} 
 
/*  Initialization */ 
HRESULT CMemStream::Init(LPBYTE pbData, LONGLONG llLength, LPCTSTR lpszFileName, DWORD dwKBPerSec) 
{ 
    m_pbData = pbData; 
    m_llLength = llLength; 
    m_dwKBPerSec = dwKBPerSec; 
    m_dwTimeStart = timeGetTime(); 
 
	/*****Anil on 10-02-2007****/ 
	m_FileHandle = CreateFile(lpszFileName, 
                              GENERIC_READ, 
                              FILE_SHARE_READ, 
                              NULL, 
                              OPEN_EXISTING, 
                              0, 
                              NULL); 
    if (m_FileHandle == INVALID_HANDLE_VALUE)  
    { 
        DbgLog((LOG_TRACE, 2, TEXT("Could not open %s\n"), lpszFileName)); 
        return S_FALSE; 
    } 
	return S_OK; 
} 
 
HRESULT CMemStream::SetPointer(LONGLONG llPos) 
{ 
    if (llPos < 0 || llPos > m_llLength) { 
        return S_FALSE; 
    } else { 
        m_llPosition = llPos; 
        return S_OK; 
    } 
} 
 
HRESULT CMemStream::Read(PBYTE pbBuffer, 
             DWORD dwBytesToRead, 
             BOOL bAlign, 
             LPDWORD pdwBytesRead) 
{ 
    CAutoLock lck(&m_csLock); 
    DWORD dwReadLength; 
	DWORD dwBytesRead; 
 
    /*  Wait until the bytes are here! */ 
    DWORD dwTime = timeGetTime(); 
 
    if (m_llPosition + dwBytesToRead > m_llLength) { 
        dwReadLength = (DWORD)(m_llLength - m_llPosition); 
    } else { 
        dwReadLength = dwBytesToRead; 
    } 
    DWORD dwTimeToArrive = 
        ((DWORD)m_llPosition + dwReadLength) / m_dwKBPerSec; 
 
    if (dwTime - m_dwTimeStart < dwTimeToArrive) { 
        Sleep(dwTimeToArrive - dwTime + m_dwTimeStart); 
    } 
 
	/****Anil on 10-02-2007 - Lets not do the buffering ....perform I/O for every Read call****/ 
#if 0 
	CopyMemory((PVOID)pbBuffer, (PVOID)(m_pbData + m_llPosition), 
               dwReadLength); 
#endif 
	 
	DWORD retVal; 
	retVal = (DWORD) SetFilePointer(m_FileHandle, (LONG)m_llPosition, NULL, FILE_BEGIN); 
	if(retVal == 0xFFFFFFFF) 
	{ 
		if(GetLastError() != NO_ERROR) 
		{ 
			RETAILMSG(1,(TEXT("CMemStream::Read-> SetFilePointer Failed")));	 
			return FALSE; 
		} 
	} 
 
	// Read the data from the file 
    if (!ReadFile(m_FileHandle, 
                  (LPVOID) pbBuffer, 
                  dwReadLength, 
                  &dwBytesRead, 
                  NULL) || 
        (dwBytesRead != dwReadLength)) 
    { 
        RETAILMSG(1,(TEXT("CMemStream::Read-> ReadFile Failed"))); 
        CloseHandle(m_FileHandle); 
        return FALSE; 
    } 
 
    m_llPosition += dwReadLength; 
    *pdwBytesRead = dwReadLength; 
    return S_OK; 
} 
 
LONGLONG CMemStream::Size(LONGLONG *pSizeAvailable) 
{ 
    LONGLONG llCurrentAvailable = 
        static_cast  (UInt32x32To64((timeGetTime() - m_dwTimeStart),m_dwKBPerSec)); 
 
   *pSizeAvailable =  min(m_llLength, llCurrentAvailable); 
    return m_llLength; 
} 
 
DWORD CMemStream::Alignment() 
{ 
    return 1; 
} 
 
void CMemStream::Lock() 
{ 
    m_csLock.Lock(); 
} 
 
void CMemStream::Unlock() 
{ 
    m_csLock.Unlock(); 
}