content/media/directshow/AudioSinkInputPin.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/content/media/directshow/AudioSinkInputPin.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,199 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* vim:set ts=2 sw=2 sts=2 et cindent: */
     1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#include "AudioSinkInputPin.h"
    1.11 +#include "AudioSinkFilter.h"
    1.12 +#include "SampleSink.h"
    1.13 +#include "prlog.h"
    1.14 +
    1.15 +#include <wmsdkidl.h>
    1.16 +
    1.17 +using namespace mozilla::media;
    1.18 +
    1.19 +namespace mozilla {
    1.20 +
    1.21 +#ifdef PR_LOGGING
    1.22 +PRLogModuleInfo* GetDirectShowLog();
    1.23 +#define LOG(...) PR_LOG(GetDirectShowLog(), PR_LOG_DEBUG, (__VA_ARGS__))
    1.24 +#else
    1.25 +#define LOG(...)
    1.26 +#endif
    1.27 +
    1.28 +AudioSinkInputPin::AudioSinkInputPin(wchar_t* aObjectName,
    1.29 +                                     AudioSinkFilter* aFilter,
    1.30 +                                     mozilla::CriticalSection* aLock,
    1.31 +                                     HRESULT* aOutResult)
    1.32 +  : BaseInputPin(aObjectName, aFilter, aLock, aOutResult, aObjectName),
    1.33 +    mSegmentStartTime(0)
    1.34 +{
    1.35 +  MOZ_COUNT_CTOR(AudioSinkInputPin);
    1.36 +  mSampleSink = new SampleSink();
    1.37 +}
    1.38 +
    1.39 +AudioSinkInputPin::~AudioSinkInputPin()
    1.40 +{
    1.41 +  MOZ_COUNT_DTOR(AudioSinkInputPin);
    1.42 +}
    1.43 +
    1.44 +HRESULT
    1.45 +AudioSinkInputPin::GetMediaType(int aPosition, MediaType* aOutMediaType)
    1.46 +{
    1.47 +  NS_ENSURE_TRUE(aPosition >= 0, E_INVALIDARG);
    1.48 +  NS_ENSURE_TRUE(aOutMediaType, E_POINTER);
    1.49 +
    1.50 +  if (aPosition > 0) {
    1.51 +    return S_FALSE;
    1.52 +  }
    1.53 +
    1.54 +  // Note: We set output as PCM, as IEEE_FLOAT only works when using the
    1.55 +  // MP3 decoder as an MFT, and we can't do that while using DirectShow.
    1.56 +  aOutMediaType->SetType(&MEDIATYPE_Audio);
    1.57 +  aOutMediaType->SetSubtype(&MEDIASUBTYPE_PCM);
    1.58 +  aOutMediaType->SetType(&FORMAT_WaveFormatEx);
    1.59 +  aOutMediaType->SetTemporalCompression(FALSE);
    1.60 +
    1.61 +  return S_OK;
    1.62 +}
    1.63 +
    1.64 +HRESULT
    1.65 +AudioSinkInputPin::CheckMediaType(const MediaType* aMediaType)
    1.66 +{
    1.67 +  if (!aMediaType) {
    1.68 +    return E_INVALIDARG;
    1.69 +  }
    1.70 +
    1.71 +  GUID majorType = *aMediaType->Type();
    1.72 +  if (majorType != MEDIATYPE_Audio && majorType != WMMEDIATYPE_Audio) {
    1.73 +    return E_INVALIDARG;
    1.74 +  }
    1.75 +
    1.76 +  if (*aMediaType->Subtype() != MEDIASUBTYPE_PCM) {
    1.77 +    return E_INVALIDARG;
    1.78 +  }
    1.79 +
    1.80 +  if (*aMediaType->FormatType() != FORMAT_WaveFormatEx) {
    1.81 +    return E_INVALIDARG;
    1.82 +  }
    1.83 +
    1.84 +  // We accept the media type, stash its layout format!
    1.85 +  WAVEFORMATEX* wfx = (WAVEFORMATEX*)(aMediaType->pbFormat);
    1.86 +  GetSampleSink()->SetAudioFormat(wfx);
    1.87 +
    1.88 +  return S_OK;
    1.89 +}
    1.90 +
    1.91 +AudioSinkFilter*
    1.92 +AudioSinkInputPin::GetAudioSinkFilter()
    1.93 +{
    1.94 +  return reinterpret_cast<AudioSinkFilter*>(mFilter);
    1.95 +}
    1.96 +
    1.97 +SampleSink*
    1.98 +AudioSinkInputPin::GetSampleSink()
    1.99 +{
   1.100 +  return mSampleSink;
   1.101 +}
   1.102 +
   1.103 +HRESULT
   1.104 +AudioSinkInputPin::SetAbsoluteMediaTime(IMediaSample* aSample)
   1.105 +{
   1.106 +  HRESULT hr;
   1.107 +  REFERENCE_TIME start = 0, end = 0;
   1.108 +  hr = aSample->GetTime(&start, &end);
   1.109 +  NS_ENSURE_TRUE(SUCCEEDED(hr), E_FAIL);
   1.110 +  {
   1.111 +    CriticalSectionAutoEnter lock(*mLock);
   1.112 +    start += mSegmentStartTime;
   1.113 +    end += mSegmentStartTime;
   1.114 +  }
   1.115 +  hr = aSample->SetMediaTime(&start, &end);
   1.116 +  NS_ENSURE_TRUE(SUCCEEDED(hr), E_FAIL);
   1.117 +  return S_OK;
   1.118 +}
   1.119 +
   1.120 +HRESULT
   1.121 +AudioSinkInputPin::Receive(IMediaSample* aSample )
   1.122 +{
   1.123 +  HRESULT hr;
   1.124 +  NS_ENSURE_TRUE(aSample, E_POINTER);
   1.125 +
   1.126 +  hr = BaseInputPin::Receive(aSample);
   1.127 +  if (SUCCEEDED(hr) && hr != S_FALSE) { // S_FALSE == flushing
   1.128 +    // Set the timestamp of the sample after being adjusted for
   1.129 +    // seeking/segments in the "media time" attribute. When we seek,
   1.130 +    // DirectShow starts a new "segment", and starts labeling samples
   1.131 +    // from time=0 again, so we need to correct for this to get the
   1.132 +    // actual timestamps after seeking.
   1.133 +    hr = SetAbsoluteMediaTime(aSample);
   1.134 +    NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
   1.135 +    hr = GetSampleSink()->Receive(aSample);
   1.136 +    NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
   1.137 +  }
   1.138 +  return S_OK;
   1.139 +}
   1.140 +
   1.141 +TemporaryRef<IMediaSeeking>
   1.142 +AudioSinkInputPin::GetConnectedPinSeeking()
   1.143 +{
   1.144 +  RefPtr<IPin> peer = GetConnected();
   1.145 +  if (!peer)
   1.146 +    return nullptr;
   1.147 +  RefPtr<IMediaSeeking> seeking;
   1.148 +  peer->QueryInterface(static_cast<IMediaSeeking**>(byRef(seeking)));
   1.149 +  return seeking;
   1.150 +}
   1.151 +
   1.152 +HRESULT
   1.153 +AudioSinkInputPin::BeginFlush()
   1.154 +{
   1.155 +  HRESULT hr = media::BaseInputPin::BeginFlush();
   1.156 +  NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
   1.157 +
   1.158 +  GetSampleSink()->Flush();
   1.159 +
   1.160 +  return S_OK;
   1.161 +}
   1.162 +
   1.163 +HRESULT
   1.164 +AudioSinkInputPin::EndFlush()
   1.165 +{
   1.166 +  HRESULT hr = media::BaseInputPin::EndFlush();
   1.167 +  NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
   1.168 +
   1.169 +  // Reset the EOS flag, so that if we're called after a seek we still work.
   1.170 +  GetSampleSink()->Reset();
   1.171 +
   1.172 +  return S_OK;
   1.173 +}
   1.174 +
   1.175 +HRESULT
   1.176 +AudioSinkInputPin::EndOfStream(void)
   1.177 +{
   1.178 +  HRESULT hr = media::BaseInputPin::EndOfStream();
   1.179 +  if (FAILED(hr) || hr == S_FALSE) {
   1.180 +    // Pin is stil flushing.
   1.181 +    return hr;
   1.182 +  }
   1.183 +  GetSampleSink()->SetEOS();
   1.184 +
   1.185 +  return S_OK;
   1.186 +}
   1.187 +
   1.188 +
   1.189 +HRESULT
   1.190 +AudioSinkInputPin::NewSegment(REFERENCE_TIME tStart,
   1.191 +                              REFERENCE_TIME tStop,
   1.192 +                              double dRate)
   1.193 +{
   1.194 +  CriticalSectionAutoEnter lock(*mLock);
   1.195 +  // Record the start time of the new segment, so that we can store the
   1.196 +  // correct absolute timestamp in the "media time" each incoming sample.
   1.197 +  mSegmentStartTime = tStart;
   1.198 +  return S_OK;
   1.199 +}
   1.200 +
   1.201 +} // namespace mozilla
   1.202 +

mercurial