michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim:set ts=2 sw=2 sts=2 et cindent: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "WMFSourceReaderCallback.h" michael@0: #include "WMFUtils.h" michael@0: michael@0: namespace mozilla { michael@0: michael@0: #ifdef PR_LOGGING michael@0: static PRLogModuleInfo* gWMFSourceReaderCallbackLog = nullptr; michael@0: #define WMF_CB_LOG(...) PR_LOG(gWMFSourceReaderCallbackLog, PR_LOG_DEBUG, (__VA_ARGS__)) michael@0: #else michael@0: #define WMF_CB_LOG(...) michael@0: #endif michael@0: michael@0: // IUnknown Methods michael@0: STDMETHODIMP michael@0: WMFSourceReaderCallback::QueryInterface(REFIID aIId, void **aInterface) michael@0: { michael@0: WMF_CB_LOG("WMFSourceReaderCallback::QueryInterface %s", GetGUIDName(aIId).get()); michael@0: michael@0: if (aIId == IID_IMFSourceReaderCallback) { michael@0: return DoGetInterface(static_cast(this), aInterface); michael@0: } michael@0: if (aIId == IID_IUnknown) { michael@0: return DoGetInterface(static_cast(this), aInterface); michael@0: } michael@0: michael@0: *aInterface = nullptr; michael@0: return E_NOINTERFACE; michael@0: } michael@0: michael@0: NS_IMPL_ADDREF(WMFSourceReaderCallback) michael@0: NS_IMPL_RELEASE(WMFSourceReaderCallback) michael@0: michael@0: WMFSourceReaderCallback::WMFSourceReaderCallback() michael@0: : mMonitor("WMFSourceReaderCallback") michael@0: , mResultStatus(S_OK) michael@0: , mStreamFlags(0) michael@0: , mTimestamp(0) michael@0: , mSample(nullptr) michael@0: , mReadFinished(false) michael@0: { michael@0: #ifdef PR_LOGGING michael@0: if (!gWMFSourceReaderCallbackLog) { michael@0: gWMFSourceReaderCallbackLog = PR_NewLogModule("WMFSourceReaderCallback"); michael@0: } michael@0: #endif michael@0: } michael@0: michael@0: HRESULT michael@0: WMFSourceReaderCallback::NotifyReadComplete(HRESULT aReadStatus, michael@0: DWORD aStreamIndex, michael@0: DWORD aStreamFlags, michael@0: LONGLONG aTimestamp, michael@0: IMFSample *aSample) michael@0: { michael@0: // Note: aSample can be nullptr on success if more data is required! michael@0: ReentrantMonitorAutoEnter mon(mMonitor); michael@0: michael@0: if (mSample) { michael@0: // The WMFReader should have called Wait() to retrieve the last michael@0: // sample returned by the last ReadSample() call, but if we're michael@0: // aborting the read before Wait() is called the sample ref michael@0: // can be non-null. michael@0: mSample->Release(); michael@0: mSample = nullptr; michael@0: } michael@0: michael@0: if (SUCCEEDED(aReadStatus)) { michael@0: if (aSample) { michael@0: mTimestamp = aTimestamp; michael@0: mSample = aSample; michael@0: mSample->AddRef(); michael@0: } michael@0: } michael@0: michael@0: mResultStatus = aReadStatus; michael@0: mStreamFlags = aStreamFlags; michael@0: michael@0: // Set the sentinal value and notify the monitor, so that threads waiting michael@0: // in Wait() are awoken. michael@0: mReadFinished = true; michael@0: mon.NotifyAll(); michael@0: michael@0: return S_OK; michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFSourceReaderCallback::OnReadSample(HRESULT aReadStatus, michael@0: DWORD aStreamIndex, michael@0: DWORD aStreamFlags, michael@0: LONGLONG aTimestamp, michael@0: IMFSample *aSample) michael@0: { michael@0: WMF_CB_LOG("WMFSourceReaderCallback::OnReadSample() hr=0x%x flags=0x%x time=%lld sample=%p", michael@0: aReadStatus, aStreamFlags, aTimestamp, aSample); michael@0: return NotifyReadComplete(aReadStatus, michael@0: aStreamIndex, michael@0: aStreamFlags, michael@0: aTimestamp, michael@0: aSample); michael@0: } michael@0: michael@0: HRESULT michael@0: WMFSourceReaderCallback::Cancel() michael@0: { michael@0: WMF_CB_LOG("WMFSourceReaderCallback::Cancel()"); michael@0: return NotifyReadComplete(E_ABORT, michael@0: 0, michael@0: 0, michael@0: 0, michael@0: nullptr); michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFSourceReaderCallback::OnEvent(DWORD, IMFMediaEvent *) michael@0: { michael@0: return S_OK; michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: WMFSourceReaderCallback::OnFlush(DWORD) michael@0: { michael@0: return S_OK; michael@0: } michael@0: michael@0: HRESULT michael@0: WMFSourceReaderCallback::Wait(DWORD* aStreamFlags, michael@0: LONGLONG* aTimeStamp, michael@0: IMFSample** aSample) michael@0: { michael@0: ReentrantMonitorAutoEnter mon(mMonitor); michael@0: WMF_CB_LOG("WMFSourceReaderCallback::Wait() starting wait"); michael@0: while (!mReadFinished) { michael@0: mon.Wait(); michael@0: } michael@0: mReadFinished = false; michael@0: WMF_CB_LOG("WMFSourceReaderCallback::Wait() done waiting"); michael@0: michael@0: *aStreamFlags = mStreamFlags; michael@0: *aTimeStamp = mTimestamp; michael@0: *aSample = mSample; michael@0: HRESULT hr = mResultStatus; michael@0: michael@0: mSample = nullptr; michael@0: mTimestamp = 0; michael@0: mStreamFlags = 0; michael@0: mResultStatus = S_OK; michael@0: michael@0: return hr; michael@0: } michael@0: michael@0: } // namespace mozilla