|
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/. */ |
|
6 |
|
7 #include "SampleSink.h" |
|
8 #include "AudioSinkFilter.h" |
|
9 #include "AudioSinkInputPin.h" |
|
10 #include "VideoUtils.h" |
|
11 #include "prlog.h" |
|
12 |
|
13 using namespace mozilla::media; |
|
14 |
|
15 namespace mozilla { |
|
16 |
|
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 |
|
23 |
|
24 SampleSink::SampleSink() |
|
25 : mMonitor("SampleSink"), |
|
26 mIsFlushing(false), |
|
27 mAtEOS(false) |
|
28 { |
|
29 MOZ_COUNT_CTOR(SampleSink); |
|
30 } |
|
31 |
|
32 SampleSink::~SampleSink() |
|
33 { |
|
34 MOZ_COUNT_DTOR(SampleSink); |
|
35 } |
|
36 |
|
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 } |
|
44 |
|
45 void |
|
46 SampleSink::GetAudioFormat(WAVEFORMATEX* aOutFormat) |
|
47 { |
|
48 MOZ_ASSERT(aOutFormat); |
|
49 ReentrantMonitorAutoEnter mon(mMonitor); |
|
50 memcpy(aOutFormat, &mAudioFormat, sizeof(WAVEFORMATEX)); |
|
51 } |
|
52 |
|
53 HRESULT |
|
54 SampleSink::Receive(IMediaSample* aSample) |
|
55 { |
|
56 ReentrantMonitorAutoEnter mon(mMonitor); |
|
57 |
|
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 } |
|
71 |
|
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 |
|
79 |
|
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 } |
|
86 |
|
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; |
|
108 |
|
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 |
|
116 |
|
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 } |
|
123 |
|
124 void |
|
125 SampleSink::Flush() |
|
126 { |
|
127 LOG("SampleSink::Flush()"); |
|
128 ReentrantMonitorAutoEnter mon(mMonitor); |
|
129 mIsFlushing = true; |
|
130 mSample = nullptr; |
|
131 mon.NotifyAll(); |
|
132 } |
|
133 |
|
134 void |
|
135 SampleSink::Reset() |
|
136 { |
|
137 LOG("SampleSink::Reset()"); |
|
138 ReentrantMonitorAutoEnter mon(mMonitor); |
|
139 mIsFlushing = false; |
|
140 mAtEOS = false; |
|
141 } |
|
142 |
|
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 } |
|
154 |
|
155 bool |
|
156 SampleSink::AtEOS() |
|
157 { |
|
158 ReentrantMonitorAutoEnter mon(mMonitor); |
|
159 return mAtEOS && !mSample; |
|
160 } |
|
161 |
|
162 } // namespace mozilla |
|
163 |