content/media/directshow/AudioSinkInputPin.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #include "AudioSinkInputPin.h"
michael@0 8 #include "AudioSinkFilter.h"
michael@0 9 #include "SampleSink.h"
michael@0 10 #include "prlog.h"
michael@0 11
michael@0 12 #include <wmsdkidl.h>
michael@0 13
michael@0 14 using namespace mozilla::media;
michael@0 15
michael@0 16 namespace mozilla {
michael@0 17
michael@0 18 #ifdef PR_LOGGING
michael@0 19 PRLogModuleInfo* GetDirectShowLog();
michael@0 20 #define LOG(...) PR_LOG(GetDirectShowLog(), PR_LOG_DEBUG, (__VA_ARGS__))
michael@0 21 #else
michael@0 22 #define LOG(...)
michael@0 23 #endif
michael@0 24
michael@0 25 AudioSinkInputPin::AudioSinkInputPin(wchar_t* aObjectName,
michael@0 26 AudioSinkFilter* aFilter,
michael@0 27 mozilla::CriticalSection* aLock,
michael@0 28 HRESULT* aOutResult)
michael@0 29 : BaseInputPin(aObjectName, aFilter, aLock, aOutResult, aObjectName),
michael@0 30 mSegmentStartTime(0)
michael@0 31 {
michael@0 32 MOZ_COUNT_CTOR(AudioSinkInputPin);
michael@0 33 mSampleSink = new SampleSink();
michael@0 34 }
michael@0 35
michael@0 36 AudioSinkInputPin::~AudioSinkInputPin()
michael@0 37 {
michael@0 38 MOZ_COUNT_DTOR(AudioSinkInputPin);
michael@0 39 }
michael@0 40
michael@0 41 HRESULT
michael@0 42 AudioSinkInputPin::GetMediaType(int aPosition, MediaType* aOutMediaType)
michael@0 43 {
michael@0 44 NS_ENSURE_TRUE(aPosition >= 0, E_INVALIDARG);
michael@0 45 NS_ENSURE_TRUE(aOutMediaType, E_POINTER);
michael@0 46
michael@0 47 if (aPosition > 0) {
michael@0 48 return S_FALSE;
michael@0 49 }
michael@0 50
michael@0 51 // Note: We set output as PCM, as IEEE_FLOAT only works when using the
michael@0 52 // MP3 decoder as an MFT, and we can't do that while using DirectShow.
michael@0 53 aOutMediaType->SetType(&MEDIATYPE_Audio);
michael@0 54 aOutMediaType->SetSubtype(&MEDIASUBTYPE_PCM);
michael@0 55 aOutMediaType->SetType(&FORMAT_WaveFormatEx);
michael@0 56 aOutMediaType->SetTemporalCompression(FALSE);
michael@0 57
michael@0 58 return S_OK;
michael@0 59 }
michael@0 60
michael@0 61 HRESULT
michael@0 62 AudioSinkInputPin::CheckMediaType(const MediaType* aMediaType)
michael@0 63 {
michael@0 64 if (!aMediaType) {
michael@0 65 return E_INVALIDARG;
michael@0 66 }
michael@0 67
michael@0 68 GUID majorType = *aMediaType->Type();
michael@0 69 if (majorType != MEDIATYPE_Audio && majorType != WMMEDIATYPE_Audio) {
michael@0 70 return E_INVALIDARG;
michael@0 71 }
michael@0 72
michael@0 73 if (*aMediaType->Subtype() != MEDIASUBTYPE_PCM) {
michael@0 74 return E_INVALIDARG;
michael@0 75 }
michael@0 76
michael@0 77 if (*aMediaType->FormatType() != FORMAT_WaveFormatEx) {
michael@0 78 return E_INVALIDARG;
michael@0 79 }
michael@0 80
michael@0 81 // We accept the media type, stash its layout format!
michael@0 82 WAVEFORMATEX* wfx = (WAVEFORMATEX*)(aMediaType->pbFormat);
michael@0 83 GetSampleSink()->SetAudioFormat(wfx);
michael@0 84
michael@0 85 return S_OK;
michael@0 86 }
michael@0 87
michael@0 88 AudioSinkFilter*
michael@0 89 AudioSinkInputPin::GetAudioSinkFilter()
michael@0 90 {
michael@0 91 return reinterpret_cast<AudioSinkFilter*>(mFilter);
michael@0 92 }
michael@0 93
michael@0 94 SampleSink*
michael@0 95 AudioSinkInputPin::GetSampleSink()
michael@0 96 {
michael@0 97 return mSampleSink;
michael@0 98 }
michael@0 99
michael@0 100 HRESULT
michael@0 101 AudioSinkInputPin::SetAbsoluteMediaTime(IMediaSample* aSample)
michael@0 102 {
michael@0 103 HRESULT hr;
michael@0 104 REFERENCE_TIME start = 0, end = 0;
michael@0 105 hr = aSample->GetTime(&start, &end);
michael@0 106 NS_ENSURE_TRUE(SUCCEEDED(hr), E_FAIL);
michael@0 107 {
michael@0 108 CriticalSectionAutoEnter lock(*mLock);
michael@0 109 start += mSegmentStartTime;
michael@0 110 end += mSegmentStartTime;
michael@0 111 }
michael@0 112 hr = aSample->SetMediaTime(&start, &end);
michael@0 113 NS_ENSURE_TRUE(SUCCEEDED(hr), E_FAIL);
michael@0 114 return S_OK;
michael@0 115 }
michael@0 116
michael@0 117 HRESULT
michael@0 118 AudioSinkInputPin::Receive(IMediaSample* aSample )
michael@0 119 {
michael@0 120 HRESULT hr;
michael@0 121 NS_ENSURE_TRUE(aSample, E_POINTER);
michael@0 122
michael@0 123 hr = BaseInputPin::Receive(aSample);
michael@0 124 if (SUCCEEDED(hr) && hr != S_FALSE) { // S_FALSE == flushing
michael@0 125 // Set the timestamp of the sample after being adjusted for
michael@0 126 // seeking/segments in the "media time" attribute. When we seek,
michael@0 127 // DirectShow starts a new "segment", and starts labeling samples
michael@0 128 // from time=0 again, so we need to correct for this to get the
michael@0 129 // actual timestamps after seeking.
michael@0 130 hr = SetAbsoluteMediaTime(aSample);
michael@0 131 NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
michael@0 132 hr = GetSampleSink()->Receive(aSample);
michael@0 133 NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
michael@0 134 }
michael@0 135 return S_OK;
michael@0 136 }
michael@0 137
michael@0 138 TemporaryRef<IMediaSeeking>
michael@0 139 AudioSinkInputPin::GetConnectedPinSeeking()
michael@0 140 {
michael@0 141 RefPtr<IPin> peer = GetConnected();
michael@0 142 if (!peer)
michael@0 143 return nullptr;
michael@0 144 RefPtr<IMediaSeeking> seeking;
michael@0 145 peer->QueryInterface(static_cast<IMediaSeeking**>(byRef(seeking)));
michael@0 146 return seeking;
michael@0 147 }
michael@0 148
michael@0 149 HRESULT
michael@0 150 AudioSinkInputPin::BeginFlush()
michael@0 151 {
michael@0 152 HRESULT hr = media::BaseInputPin::BeginFlush();
michael@0 153 NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
michael@0 154
michael@0 155 GetSampleSink()->Flush();
michael@0 156
michael@0 157 return S_OK;
michael@0 158 }
michael@0 159
michael@0 160 HRESULT
michael@0 161 AudioSinkInputPin::EndFlush()
michael@0 162 {
michael@0 163 HRESULT hr = media::BaseInputPin::EndFlush();
michael@0 164 NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
michael@0 165
michael@0 166 // Reset the EOS flag, so that if we're called after a seek we still work.
michael@0 167 GetSampleSink()->Reset();
michael@0 168
michael@0 169 return S_OK;
michael@0 170 }
michael@0 171
michael@0 172 HRESULT
michael@0 173 AudioSinkInputPin::EndOfStream(void)
michael@0 174 {
michael@0 175 HRESULT hr = media::BaseInputPin::EndOfStream();
michael@0 176 if (FAILED(hr) || hr == S_FALSE) {
michael@0 177 // Pin is stil flushing.
michael@0 178 return hr;
michael@0 179 }
michael@0 180 GetSampleSink()->SetEOS();
michael@0 181
michael@0 182 return S_OK;
michael@0 183 }
michael@0 184
michael@0 185
michael@0 186 HRESULT
michael@0 187 AudioSinkInputPin::NewSegment(REFERENCE_TIME tStart,
michael@0 188 REFERENCE_TIME tStop,
michael@0 189 double dRate)
michael@0 190 {
michael@0 191 CriticalSectionAutoEnter lock(*mLock);
michael@0 192 // Record the start time of the new segment, so that we can store the
michael@0 193 // correct absolute timestamp in the "media time" each incoming sample.
michael@0 194 mSegmentStartTime = tStart;
michael@0 195 return S_OK;
michael@0 196 }
michael@0 197
michael@0 198 } // namespace mozilla
michael@0 199

mercurial