diff options
Diffstat (limited to 'dom/media/directshow/SampleSink.cpp')
-rw-r--r-- | dom/media/directshow/SampleSink.cpp | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/dom/media/directshow/SampleSink.cpp b/dom/media/directshow/SampleSink.cpp new file mode 100644 index 000000000..fa5dc8d19 --- /dev/null +++ b/dom/media/directshow/SampleSink.cpp @@ -0,0 +1,159 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "SampleSink.h" +#include "AudioSinkFilter.h" +#include "AudioSinkInputPin.h" +#include "VideoUtils.h" +#include "mozilla/Logging.h" + +using namespace mozilla::media; + +namespace mozilla { + +static LazyLogModule gDirectShowLog("DirectShowDecoder"); +#define LOG(...) MOZ_LOG(gDirectShowLog, mozilla::LogLevel::Debug, (__VA_ARGS__)) + +SampleSink::SampleSink() + : mMonitor("SampleSink"), + mIsFlushing(false), + mAtEOS(false) +{ + MOZ_COUNT_CTOR(SampleSink); +} + +SampleSink::~SampleSink() +{ + MOZ_COUNT_DTOR(SampleSink); +} + +void +SampleSink::SetAudioFormat(const WAVEFORMATEX* aInFormat) +{ + NS_ENSURE_TRUE(aInFormat, ); + ReentrantMonitorAutoEnter mon(mMonitor); + memcpy(&mAudioFormat, aInFormat, sizeof(WAVEFORMATEX)); +} + +void +SampleSink::GetAudioFormat(WAVEFORMATEX* aOutFormat) +{ + MOZ_ASSERT(aOutFormat); + ReentrantMonitorAutoEnter mon(mMonitor); + memcpy(aOutFormat, &mAudioFormat, sizeof(WAVEFORMATEX)); +} + +HRESULT +SampleSink::Receive(IMediaSample* aSample) +{ + ReentrantMonitorAutoEnter mon(mMonitor); + + while (true) { + if (mIsFlushing) { + return S_FALSE; + } + if (!mSample) { + break; + } + if (mAtEOS) { + return E_UNEXPECTED; + } + // Wait until the consumer thread consumes the sample. + mon.Wait(); + } + + if (MOZ_LOG_TEST(gDirectShowLog, LogLevel::Debug)) { + REFERENCE_TIME start = 0, end = 0; + HRESULT hr = aSample->GetMediaTime(&start, &end); + LOG("SampleSink::Receive() [%4.2lf-%4.2lf]", + (double)RefTimeToUsecs(start) / USECS_PER_S, + (double)RefTimeToUsecs(end) / USECS_PER_S); + } + + mSample = aSample; + // Notify the signal, to awaken the consumer thread in WaitForSample() + // if necessary. + mon.NotifyAll(); + return S_OK; +} + +HRESULT +SampleSink::Extract(RefPtr<IMediaSample>& aOutSample) +{ + ReentrantMonitorAutoEnter mon(mMonitor); + // Loop until we have a sample, or we should abort. + while (true) { + if (mIsFlushing) { + return S_FALSE; + } + if (mSample) { + break; + } + if (mAtEOS) { + // Order is important here, if we have a sample, we should return it + // before reporting EOS. + return E_UNEXPECTED; + } + // Wait until the producer thread gives us a sample. + mon.Wait(); + } + aOutSample = mSample; + + if (MOZ_LOG_TEST(gDirectShowLog, LogLevel::Debug)) { + int64_t start = 0, end = 0; + mSample->GetMediaTime(&start, &end); + LOG("SampleSink::Extract() [%4.2lf-%4.2lf]", + (double)RefTimeToUsecs(start) / USECS_PER_S, + (double)RefTimeToUsecs(end) / USECS_PER_S); + } + + mSample = nullptr; + // Notify the signal, to awaken the producer thread in Receive() + // if necessary. + mon.NotifyAll(); + return S_OK; +} + +void +SampleSink::Flush() +{ + LOG("SampleSink::Flush()"); + ReentrantMonitorAutoEnter mon(mMonitor); + mIsFlushing = true; + mSample = nullptr; + mon.NotifyAll(); +} + +void +SampleSink::Reset() +{ + LOG("SampleSink::Reset()"); + ReentrantMonitorAutoEnter mon(mMonitor); + mIsFlushing = false; + mAtEOS = false; +} + +void +SampleSink::SetEOS() +{ + LOG("SampleSink::SetEOS()"); + ReentrantMonitorAutoEnter mon(mMonitor); + mAtEOS = true; + // Notify to unblock any threads waiting for samples in + // Extract() or Receive(). Now that we're at EOS, no more samples + // will come! + mon.NotifyAll(); +} + +bool +SampleSink::AtEOS() +{ + ReentrantMonitorAutoEnter mon(mMonitor); + return mAtEOS && !mSample; +} + +} // namespace mozilla + |