Fri, 16 Jan 2015 04:50:19 +0100
Replace accessor implementation with direct member state manipulation, by
request https://trac.torproject.org/projects/tor/ticket/9701#comment:32
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "SampleSink.h"
8 #include "AudioSinkFilter.h"
9 #include "AudioSinkInputPin.h"
10 #include "VideoUtils.h"
11 #include "prlog.h"
13 using namespace mozilla::media;
15 namespace mozilla {
17 #ifdef PR_LOGGING
18 PRLogModuleInfo* GetDirectShowLog();
19 #define LOG(...) PR_LOG(GetDirectShowLog(), PR_LOG_DEBUG, (__VA_ARGS__))
20 #else
21 #define LOG(...)
22 #endif
24 SampleSink::SampleSink()
25 : mMonitor("SampleSink"),
26 mIsFlushing(false),
27 mAtEOS(false)
28 {
29 MOZ_COUNT_CTOR(SampleSink);
30 }
32 SampleSink::~SampleSink()
33 {
34 MOZ_COUNT_DTOR(SampleSink);
35 }
37 void
38 SampleSink::SetAudioFormat(const WAVEFORMATEX* aInFormat)
39 {
40 NS_ENSURE_TRUE(aInFormat, );
41 ReentrantMonitorAutoEnter mon(mMonitor);
42 memcpy(&mAudioFormat, aInFormat, sizeof(WAVEFORMATEX));
43 }
45 void
46 SampleSink::GetAudioFormat(WAVEFORMATEX* aOutFormat)
47 {
48 MOZ_ASSERT(aOutFormat);
49 ReentrantMonitorAutoEnter mon(mMonitor);
50 memcpy(aOutFormat, &mAudioFormat, sizeof(WAVEFORMATEX));
51 }
53 HRESULT
54 SampleSink::Receive(IMediaSample* aSample)
55 {
56 ReentrantMonitorAutoEnter mon(mMonitor);
58 while (true) {
59 if (mIsFlushing) {
60 return S_FALSE;
61 }
62 if (!mSample) {
63 break;
64 }
65 if (mAtEOS) {
66 return E_UNEXPECTED;
67 }
68 // Wait until the consumer thread consumes the sample.
69 mon.Wait();
70 }
72 #ifdef PR_LOGGING
73 REFERENCE_TIME start = 0, end = 0;
74 HRESULT hr = aSample->GetMediaTime(&start, &end);
75 LOG("SampleSink::Receive() [%4.2lf-%4.2lf]",
76 (double)RefTimeToUsecs(start) / USECS_PER_S,
77 (double)RefTimeToUsecs(end) / USECS_PER_S);
78 #endif
80 mSample = aSample;
81 // Notify the signal, to awaken the consumer thread in WaitForSample()
82 // if necessary.
83 mon.NotifyAll();
84 return S_OK;
85 }
87 HRESULT
88 SampleSink::Extract(RefPtr<IMediaSample>& aOutSample)
89 {
90 ReentrantMonitorAutoEnter mon(mMonitor);
91 // Loop until we have a sample, or we should abort.
92 while (true) {
93 if (mIsFlushing) {
94 return S_FALSE;
95 }
96 if (mSample) {
97 break;
98 }
99 if (mAtEOS) {
100 // Order is important here, if we have a sample, we should return it
101 // before reporting EOS.
102 return E_UNEXPECTED;
103 }
104 // Wait until the producer thread gives us a sample.
105 mon.Wait();
106 }
107 aOutSample = mSample;
109 #ifdef PR_LOGGING
110 int64_t start = 0, end = 0;
111 mSample->GetMediaTime(&start, &end);
112 LOG("SampleSink::Extract() [%4.2lf-%4.2lf]",
113 (double)RefTimeToUsecs(start) / USECS_PER_S,
114 (double)RefTimeToUsecs(end) / USECS_PER_S);
115 #endif
117 mSample = nullptr;
118 // Notify the signal, to awaken the producer thread in Receive()
119 // if necessary.
120 mon.NotifyAll();
121 return S_OK;
122 }
124 void
125 SampleSink::Flush()
126 {
127 LOG("SampleSink::Flush()");
128 ReentrantMonitorAutoEnter mon(mMonitor);
129 mIsFlushing = true;
130 mSample = nullptr;
131 mon.NotifyAll();
132 }
134 void
135 SampleSink::Reset()
136 {
137 LOG("SampleSink::Reset()");
138 ReentrantMonitorAutoEnter mon(mMonitor);
139 mIsFlushing = false;
140 mAtEOS = false;
141 }
143 void
144 SampleSink::SetEOS()
145 {
146 LOG("SampleSink::SetEOS()");
147 ReentrantMonitorAutoEnter mon(mMonitor);
148 mAtEOS = true;
149 // Notify to unblock any threads waiting for samples in
150 // Extract() or Receive(). Now that we're at EOS, no more samples
151 // will come!
152 mon.NotifyAll();
153 }
155 bool
156 SampleSink::AtEOS()
157 {
158 ReentrantMonitorAutoEnter mon(mMonitor);
159 return mAtEOS && !mSample;
160 }
162 } // namespace mozilla