windows-nt/Source/XPSP1/NT/multimedia/dshow/vidctl/msvidctl/msvidfileplayback.cpp
2020-09-26 16:20:57 +08:00

307 lines
10 KiB
C++

//==========================================================================;
//
// Copyright (c) Microsoft Corporation 1999-2000.
//
//--------------------------------------------------------------------------;
//
// MSVidFilePlayback.cpp : Implementation of CMSVidFilePlayback
//
#include "stdafx.h"
#ifndef TUNING_MODEL_ONLY
#include "atltmp.h"
#include "MSVidCtl.h"
#include "MSVidFilePlayback.h"
#include <nserror.h>
#include <wmsdkidl.h>
#define FILE_BEGINNING 0
#define LOCAL_OATRUE -1
DEFINE_EXTERN_OBJECT_ENTRY(CLSID_MSVidFilePlaybackDevice, CMSVidFilePlayback)
/////////////////////////////////////////////////////////////////////////////
// CMSVidFilePlayback
STDMETHODIMP CMSVidFilePlayback::PostRun(){
if(m_fGraphInit){
InitGraph();
m_fGraphInit = false;
}
return IMSVidPBGraphSegmentImpl<CMSVidFilePlayback, MSVidSEG_SOURCE, &GUID_NULL>::PostRun();
}
STDMETHODIMP CMSVidFilePlayback::put_Rate(double lRate){
HRESULT hr = S_OK;
try{
/*** Checking args and init'ing interfaces ***/
if (!m_pGraph) {
// graph not valid
return Error(IDS_INVALID_STATE, __uuidof(IMSVidFilePlayback), HRESULT_FROM_WIN32(ERROR_INVALID_STATE));
}
// Attempt to set the rate using IMediaSeeking
DSFilter Reader = m_Filters[m_iReader];
PQMediaSeeking PQIMSeeking;
if(Reader){
for(DSFilter::iterator iPin = Reader.begin(); iPin != Reader.end(); ++iPin){
PQIMSeeking = (*iPin);
if(PQIMSeeking){
TRACELSM(TRACE_DETAIL, (dbgDump << "MSVidFilePlayback::put_Rate found Pin"), "");
break;
}
}
}
if(!PQIMSeeking){
TRACELSM(TRACE_DETAIL, (dbgDump << "MSVidFilePlayback::put_Rate using graph"), "");
PQIMSeeking = m_pGraph;
}
if(PQIMSeeking){
TRACELSM(TRACE_DETAIL, (dbgDump << "MSVidFilePlayback::put_Rate using Imediaseeking"), "");
return PQIMSeeking->SetRate(lRate);
}
// If IMediaSeeking FAILS try IMediaPostion
PQMediaPosition PQIMPos(m_pGraph);
if(PQIMPos){
// Change rate
TRACELSM(TRACE_DETAIL, (dbgDump << "MSVidFilePlayback::put_Rate using Imediaposition"), "");
return PQIMPos->put_Rate((double)lRate);
}
// Could Not QI Either one set the error
return Error(IDS_E_CANTQI , __uuidof(IMSVidFilePlayback), E_NOINTERFACE);
}
catch(HRESULT hrTmp){
// Something went bad, threw a HRESULT
return Error(IDS_INVALID_STATE , __uuidof(IMSVidFilePlayback), hrTmp);
}
catch(...){
// Something went bad, dont know what it threw
return E_UNEXPECTED;
}
}
STDMETHODIMP CMSVidFilePlayback::get_Rate(double *lRate){
HRESULT hr = S_OK;
try{
/*** Checking args and init'ing interfaces ***/
if (!m_pGraph) {
// graph not valid
return Error(IDS_INVALID_STATE, __uuidof(IMSVidFilePlayback), HRESULT_FROM_WIN32(ERROR_INVALID_STATE));
}
// Attempt to set the rate using IMediaSeeking
DSFilter Reader = m_Filters[m_iReader];
PQMediaSeeking PQIMSeeking;
if(Reader){
for(DSFilter::iterator iPin = Reader.begin(); iPin != Reader.end(); ++iPin){
PQIMSeeking = (*iPin);
if(PQIMSeeking){
break;
}
}
}
if(!PQIMSeeking){
PQIMSeeking = m_pGraph;
}
if(PQIMSeeking){
return PQIMSeeking->GetRate(lRate);
}
// If IMediaSeeking FAILS try IMediaPostion
PQMediaPosition PQIMPos(m_pGraph);
if(PQIMPos){
// Change rate
return PQIMPos->get_Rate(lRate);
}
// Could Not QI Either one set the error
return Error(IDS_E_CANTQI , __uuidof(IMSVidFilePlayback), E_NOINTERFACE);
}
catch(HRESULT hrTmp){
// Something went bad, threw a HRESULT
return Error(IDS_INVALID_STATE , __uuidof(IMSVidFilePlayback), hrTmp);
}
catch(...){
// Something went bad, dont know what it threw
return E_UNEXPECTED;
}
}
STDMETHODIMP CMSVidFilePlayback::PreStop(){
TRACELSM(TRACE_DETAIL, (dbgDump << "MSVidFilePlayback::PreStop()"), "");
double curRate = 0;
HRESULT hr = get_Rate(&curRate);
if(SUCCEEDED(hr) && curRate != 1){
hr = IMSVidFilePlaybackImpl<CMSVidFilePlayback, &LIBID_MSVidCtlLib, &GUID_NULL, IMSVidFilePlayback>::put_Rate(1);
if(FAILED(hr)){
TRACELSM(TRACE_ERROR, (dbgDump << "MSVidFilePlayback::PreStop() base put_Rate 1 failed"), "");
}
hr = put_Rate(1);
if(FAILED(hr)){
TRACELSM(TRACE_ERROR, (dbgDump << "MSVidFilePlayback::PreStop() put_Rate 1 failed"), "");
}
}
else{
TRACELSM(TRACE_ERROR, (dbgDump << "MSVidFilePlayback::PreStop() get_Rate failed"), "");
}
return NOERROR;
}
STDMETHODIMP CMSVidFilePlayback::PostStop(){
HRESULT hr = S_OK;
TRACELSM(TRACE_DETAIL, (dbgDump << "MSVidFilePlayback::PostStop()"), "");
try {
#if 0
// If the graph is not is stopped state
// we make sure it is
if (!m_pGraph.IsStopped()) {
HRESULT hr = PQVidCtl(m_pContainer)->Stop();
}
#endif
// If m_fEnableResetOnStop is true then we need to reset
// the postion back to the beggining
// else do nothing
// If it fails file cannot be reset to beginning
if(m_fEnableResetOnStop){
put_CurrentPosition(0);
}
}
catch(HRESULT hrTmp){
hr = hrTmp;
}
catch(...){
hr = E_UNEXPECTED;
}
return hr;
}
STDMETHODIMP CMSVidFilePlayback::InterfaceSupportsErrorInfo(REFIID riid)
{
static const IID* arr[] =
{
&IID_IMSVidFilePlayback
};
for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
if (InlineIsEqualGUID(*arr[i],riid))
return S_OK;
}
return S_FALSE;
}
STDMETHODIMP CMSVidFilePlayback::put_Container(IMSVidGraphSegmentContainer *pCtl)
{
try {
if (!m_fInit) {
return Error(IDS_OBJ_NO_INIT, __uuidof(IMSVidFilePlayback), CO_E_NOTINITIALIZED);
}
if (!pCtl) {
return Unload();
}
if (m_pContainer) {
if (!m_pContainer.IsEqualObject(VWSegmentContainer(pCtl))) {
return Error(IDS_OBJ_ALREADY_INIT, __uuidof(IMSVidFilePlayback), CO_E_ALREADYINITIALIZED);
} else {
return NO_ERROR;
}
}
// DON'T addref the container. we're guaranteed nested lifetimes
// and an addref creates circular refcounts so we never unload.
m_pContainer.p = pCtl;
m_pGraph = m_pContainer.GetGraph();
return NOERROR;
} catch (ComException &e) {
return e;
} catch (...) {
return E_UNEXPECTED;
}
}
STDMETHODIMP CMSVidFilePlayback::Build() {
if (!m_FileName) {
return Error(IDS_INVALID_STATE, __uuidof(IMSVidFilePlayback), HRESULT_FROM_WIN32(ERROR_INVALID_STATE));
}
if(m_Filters.size() > 0){
return NOERROR;
}
USES_CONVERSION;
CString csName(_T("File Playback"));
DSFilter pfr;
HRESULT hr = pfr.CoCreateInstance(CLSID_WMAsfReader,0, CLSCTX_INPROC_SERVER);
if(SUCCEEDED(hr)){
CComQIPtr<IFileSourceFilter> pqFS(pfr);
if(!!pqFS){
// set the target ASF filename
hr = pqFS->Load(m_FileName, NULL);
if(FAILED(hr)){
if(hr == (HRESULT)NS_E_LICENSE_REQUIRED){
CComQIPtr<IWMDRMReader> pq_DRMReader(pqFS);
if(pq_DRMReader){
hr = pq_DRMReader->AcquireLicense(1); // 1 == attempt silently
if(SUCCEEDED(hr)){
hr = pqFS->Load(m_FileName, NULL);
}
else{
TRACELSM(TRACE_ERROR, (dbgDump << "MSVidFilePlayback::Build() Could not acquire license"), "");
}
}
else{
TRACELSM(TRACE_ERROR, (dbgDump << "MSVidFilePlayback::Build() Could not qi for IWMDRMReader "), "");
}
}
}
if(SUCCEEDED(hr)){
// add the ASF writer filter to the graph
hr = m_pGraph->AddFilter(pfr, csName);
if(SUCCEEDED(hr)){
TRACELSM(TRACE_ERROR, (dbgDump << "MSVidFilePlayback::Build() added WMV filter to graph hr = " << std::hex << hr), "");
}
else{
TRACELSM(TRACE_ERROR, (dbgDump << "MSVidFilePlayback::Build() could not add filter to graph hr = " << std::hex << hr), "");
}
}
else{
TRACELSM(TRACE_ERROR, (dbgDump << "MSVidFilePlayback::Build() Could not set file name, hr = " << std::hex << hr), "");
}
}
else{
TRACELSM(TRACE_ERROR, (dbgDump << "MSVidFilePlayback::Build() Could not get IFileSourceFilter interface, hr = " << std::hex << hr), "");
}
}
else{
TRACELSM(TRACE_ERROR, (dbgDump << "MSVidFilePlayback::Build() CreateFilter AsfReader failed, hr = " << std::hex << hr), "");
}
if (FAILED(hr)) {
hr = m_pGraph->AddSourceFilter(m_FileName, csName, &pfr);
if(FAILED(hr)){
TRACELSM(TRACE_ERROR, (dbgDump << "MSVidFilePlayback::Build() Add Source Filter Failed, hr = " << std::hex << hr), "");
return Error(IDS_CANT_PLAY_FILE, __uuidof(IMSVidFilePlayback), hr);
}
}
m_Filters.clear();
m_Filters.push_back(pfr);
m_iReader = m_Filters.size() - 1;
return NOERROR;
}
STDMETHODIMP CMSVidFilePlayback::OnEventNotify(long lEvent, LONG_PTR lParam1, LONG_PTR lParam2) {
return IMSVidPBGraphSegmentImpl<CMSVidFilePlayback, MSVidSEG_SOURCE, &GUID_NULL>::OnEventNotify(lEvent, lParam1, lParam2);
}
#endif //TUNING_MODEL_ONLY
// end of file - MSVidFilePlayback.cpp