Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(511)

Side by Side Diff: webrtc/modules/video_coding/generic_decoder.cc

Issue 2744813002: Start documenting the threading model (Closed)
Patch Set: Convert thread checks in Android code to DCHECKs Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/modules/video_coding/generic_decoder.h"
12
11 #include "webrtc/base/checks.h" 13 #include "webrtc/base/checks.h"
12 #include "webrtc/base/logging.h" 14 #include "webrtc/base/logging.h"
15 #include "webrtc/base/platform_thread.h"
13 #include "webrtc/base/trace_event.h" 16 #include "webrtc/base/trace_event.h"
14 #include "webrtc/modules/video_coding/include/video_coding.h" 17 #include "webrtc/modules/video_coding/include/video_coding.h"
15 #include "webrtc/modules/video_coding/generic_decoder.h"
16 #include "webrtc/modules/video_coding/internal_defines.h" 18 #include "webrtc/modules/video_coding/internal_defines.h"
17 #include "webrtc/system_wrappers/include/clock.h" 19 #include "webrtc/system_wrappers/include/clock.h"
18 20
19 namespace webrtc { 21 namespace webrtc {
20 22
21 VCMDecodedFrameCallback::VCMDecodedFrameCallback(VCMTiming* timing, 23 VCMDecodedFrameCallback::VCMDecodedFrameCallback(VCMTiming* timing,
22 Clock* clock) 24 Clock* clock)
23 : _critSect(CriticalSectionWrapper::CreateCriticalSection()), 25 : _clock(clock),
24 _clock(clock),
25 _receiveCallback(NULL), 26 _receiveCallback(NULL),
26 _timing(timing), 27 _timing(timing),
27 _timestampMap(kDecoderFrameMemoryLength), 28 _timestampMap(kDecoderFrameMemoryLength),
28 _lastReceivedPictureID(0) {} 29 _lastReceivedPictureID(0) {
30 decoder_thread_checker_.DetachFromThread();
31 }
29 32
30 VCMDecodedFrameCallback::~VCMDecodedFrameCallback() { 33 VCMDecodedFrameCallback::~VCMDecodedFrameCallback() {
31 delete _critSect; 34 RTC_DCHECK(construction_thread_checker_.CalledOnValidThread());
32 } 35 }
33 36
34 void VCMDecodedFrameCallback::SetUserReceiveCallback( 37 void VCMDecodedFrameCallback::SetUserReceiveCallback(
35 VCMReceiveCallback* receiveCallback) { 38 VCMReceiveCallback* receiveCallback) {
36 CriticalSectionScoped cs(_critSect); 39 RTC_DCHECK(construction_thread_checker_.CalledOnValidThread());
40 // TODO(tommi): Can we require that this be called before decoding starts
41 // or after it has been stopped? If so, we don't need a lock.
42 rtc::CritScope cs(&_critSect);
37 _receiveCallback = receiveCallback; 43 _receiveCallback = receiveCallback;
38 } 44 }
39 45
40 VCMReceiveCallback* VCMDecodedFrameCallback::UserReceiveCallback() { 46 VCMReceiveCallback* VCMDecodedFrameCallback::UserReceiveCallback() {
41 CriticalSectionScoped cs(_critSect); 47 RTC_DCHECK(decoder_thread_checker_.CalledOnValidThread());
48 rtc::CritScope cs(&_critSect);
49 // BUG: Returning a pointer that requires a lock to get.
50 // TODO(tommi): If we're always called on the decoder thread and that
51 // modifying this value is not allowed while the thread is running,
52 // we can remove the lock and allow returning this pointer.
42 return _receiveCallback; 53 return _receiveCallback;
43 } 54 }
44 55
45 int32_t VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage) { 56 int32_t VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage) {
46 return Decoded(decodedImage, -1); 57 return Decoded(decodedImage, -1);
47 } 58 }
48 59
49 int32_t VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage, 60 int32_t VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage,
50 int64_t decode_time_ms) { 61 int64_t decode_time_ms) {
51 Decoded(decodedImage, 62 Decoded(decodedImage,
52 decode_time_ms >= 0 ? rtc::Optional<int32_t>(decode_time_ms) 63 decode_time_ms >= 0 ? rtc::Optional<int32_t>(decode_time_ms)
53 : rtc::Optional<int32_t>(), 64 : rtc::Optional<int32_t>(),
54 rtc::Optional<uint8_t>()); 65 rtc::Optional<uint8_t>());
55 return WEBRTC_VIDEO_CODEC_OK; 66 return WEBRTC_VIDEO_CODEC_OK;
56 } 67 }
57 68
58 void VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage, 69 void VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage,
59 rtc::Optional<int32_t> decode_time_ms, 70 rtc::Optional<int32_t> decode_time_ms,
60 rtc::Optional<uint8_t> qp) { 71 rtc::Optional<uint8_t> qp) {
72 RTC_DCHECK(decoder_thread_checker_.CalledOnValidThread());
73
61 TRACE_EVENT_INSTANT1("webrtc", "VCMDecodedFrameCallback::Decoded", 74 TRACE_EVENT_INSTANT1("webrtc", "VCMDecodedFrameCallback::Decoded",
62 "timestamp", decodedImage.timestamp()); 75 "timestamp", decodedImage.timestamp());
63 // TODO(holmer): We should improve this so that we can handle multiple 76 // TODO(holmer): We should improve this so that we can handle multiple
64 // callbacks from one call to Decode(). 77 // callbacks from one call to Decode().
65 VCMFrameInformation* frameInfo; 78 VCMFrameInformation* frameInfo;
66 VCMReceiveCallback* callback; 79 VCMReceiveCallback* callback;
67 { 80 {
68 CriticalSectionScoped cs(_critSect); 81 rtc::CritScope cs(&_critSect);
69 frameInfo = _timestampMap.Pop(decodedImage.timestamp()); 82 frameInfo = _timestampMap.Pop(decodedImage.timestamp());
70 callback = _receiveCallback; 83 callback = _receiveCallback;
71 } 84 }
72 85
73 if (frameInfo == NULL) { 86 if (frameInfo == NULL) {
74 LOG(LS_WARNING) << "Too many frames backed up in the decoder, dropping " 87 LOG(LS_WARNING) << "Too many frames backed up in the decoder, dropping "
75 "this one."; 88 "this one.";
76 return; 89 return;
77 } 90 }
78 91
(...skipping 12 matching lines...) Expand all
91 // statement with a DCHECK. 104 // statement with a DCHECK.
92 if (callback) { 105 if (callback) {
93 callback->FrameToRender(decodedImage, qp); 106 callback->FrameToRender(decodedImage, qp);
94 } else { 107 } else {
95 LOG(LS_WARNING) << "No callback, dropping frame."; 108 LOG(LS_WARNING) << "No callback, dropping frame.";
96 } 109 }
97 } 110 }
98 111
99 int32_t VCMDecodedFrameCallback::ReceivedDecodedReferenceFrame( 112 int32_t VCMDecodedFrameCallback::ReceivedDecodedReferenceFrame(
100 const uint64_t pictureId) { 113 const uint64_t pictureId) {
101 CriticalSectionScoped cs(_critSect); 114 RTC_DCHECK(decoder_thread_checker_.CalledOnValidThread());
115 rtc::CritScope cs(&_critSect);
102 if (_receiveCallback != NULL) { 116 if (_receiveCallback != NULL) {
103 return _receiveCallback->ReceivedDecodedReferenceFrame(pictureId); 117 return _receiveCallback->ReceivedDecodedReferenceFrame(pictureId);
104 } 118 }
105 return -1; 119 return -1;
106 } 120 }
107 121
108 int32_t VCMDecodedFrameCallback::ReceivedDecodedFrame( 122 int32_t VCMDecodedFrameCallback::ReceivedDecodedFrame(
109 const uint64_t pictureId) { 123 const uint64_t pictureId) {
124 RTC_DCHECK(decoder_thread_checker_.CalledOnValidThread());
110 _lastReceivedPictureID = pictureId; 125 _lastReceivedPictureID = pictureId;
111 return 0; 126 return 0;
112 } 127 }
113 128
114 uint64_t VCMDecodedFrameCallback::LastReceivedPictureID() const { 129 uint64_t VCMDecodedFrameCallback::LastReceivedPictureID() const {
130 RTC_DCHECK(decoder_thread_checker_.CalledOnValidThread());
115 return _lastReceivedPictureID; 131 return _lastReceivedPictureID;
116 } 132 }
117 133
118 void VCMDecodedFrameCallback::OnDecoderImplementationName( 134 void VCMDecodedFrameCallback::OnDecoderImplementationName(
119 const char* implementation_name) { 135 const char* implementation_name) {
120 CriticalSectionScoped cs(_critSect); 136 RTC_DCHECK(decoder_thread_checker_.CalledOnValidThread());
137 rtc::CritScope cs(&_critSect);
121 if (_receiveCallback) 138 if (_receiveCallback)
122 _receiveCallback->OnDecoderImplementationName(implementation_name); 139 _receiveCallback->OnDecoderImplementationName(implementation_name);
123 } 140 }
124 141
125 void VCMDecodedFrameCallback::Map(uint32_t timestamp, 142 void VCMDecodedFrameCallback::Map(uint32_t timestamp,
126 VCMFrameInformation* frameInfo) { 143 VCMFrameInformation* frameInfo) {
127 CriticalSectionScoped cs(_critSect); 144 RTC_DCHECK(decoder_thread_checker_.CalledOnValidThread());
145 // TODO(tommi): Looks like _timestampMap is only used on the decoder thread
146 // now?
147 rtc::CritScope cs(&_critSect);
128 _timestampMap.Add(timestamp, frameInfo); 148 _timestampMap.Add(timestamp, frameInfo);
129 } 149 }
130 150
131 int32_t VCMDecodedFrameCallback::Pop(uint32_t timestamp) { 151 int32_t VCMDecodedFrameCallback::Pop(uint32_t timestamp) {
132 CriticalSectionScoped cs(_critSect); 152 RTC_DCHECK(decoder_thread_checker_.CalledOnValidThread());
153 // TODO(tommi): Looks like _timestampMap is only used on the decoder thread
154 // now?
155 rtc::CritScope cs(&_critSect);
133 if (_timestampMap.Pop(timestamp) == NULL) { 156 if (_timestampMap.Pop(timestamp) == NULL) {
134 return VCM_GENERAL_ERROR; 157 return VCM_GENERAL_ERROR;
135 } 158 }
136 return VCM_OK; 159 return VCM_OK;
137 } 160 }
138 161
139 VCMGenericDecoder::VCMGenericDecoder(VideoDecoder* decoder, bool isExternal) 162 VCMGenericDecoder::VCMGenericDecoder(VideoDecoder* decoder, bool isExternal)
140 : _callback(NULL), 163 : _callback(NULL),
141 _frameInfos(), 164 _frameInfos(),
142 _nextFrameInfoIdx(0), 165 _nextFrameInfoIdx(0),
143 _decoder(decoder), 166 _decoder(decoder),
144 _codecType(kVideoCodecUnknown), 167 _codecType(kVideoCodecUnknown),
145 _isExternal(isExternal), 168 _isExternal(isExternal),
146 _keyFrameDecoded(false) {} 169 _keyFrameDecoded(false) {}
147 170
148 VCMGenericDecoder::~VCMGenericDecoder() {} 171 VCMGenericDecoder::~VCMGenericDecoder() {
172 // Can be deleted outside of the decoder thread (which is the construction
173 // thread). Bug?
174 // See CallPerfTest.PlaysOutAudioAndVideoInSyncWithVideoNtpDrift
175
176 // In |modules_unittests|, the object can be created on the construction
177 // thread.
178 // RTC_DCHECK(!decoder_thread_checker_.CalledOnValidThread());
179 }
149 180
150 int32_t VCMGenericDecoder::InitDecode(const VideoCodec* settings, 181 int32_t VCMGenericDecoder::InitDecode(const VideoCodec* settings,
151 int32_t numberOfCores) { 182 int32_t numberOfCores) {
183 RTC_DCHECK(decoder_thread_checker_.CalledOnValidThread());
152 TRACE_EVENT0("webrtc", "VCMGenericDecoder::InitDecode"); 184 TRACE_EVENT0("webrtc", "VCMGenericDecoder::InitDecode");
153 _codecType = settings->codecType; 185 _codecType = settings->codecType;
154 186
155 return _decoder->InitDecode(settings, numberOfCores); 187 return _decoder->InitDecode(settings, numberOfCores);
156 } 188 }
157 189
158 int32_t VCMGenericDecoder::Decode(const VCMEncodedFrame& frame, int64_t nowMs) { 190 int32_t VCMGenericDecoder::Decode(const VCMEncodedFrame& frame, int64_t nowMs) {
159 TRACE_EVENT1("webrtc", "VCMGenericDecoder::Decode", "timestamp", 191 RTC_DCHECK(decoder_thread_checker_.CalledOnValidThread());
160 frame.EncodedImage()._timeStamp); 192 TRACE_EVENT1("webrtc", "VCMGenericDecoder::Decode", "timestamp",
161 _frameInfos[_nextFrameInfoIdx].decodeStartTimeMs = nowMs; 193 frame.EncodedImage()._timeStamp);
162 _frameInfos[_nextFrameInfoIdx].renderTimeMs = frame.RenderTimeMs(); 194 _frameInfos[_nextFrameInfoIdx].decodeStartTimeMs = nowMs;
163 _frameInfos[_nextFrameInfoIdx].rotation = frame.rotation(); 195 _frameInfos[_nextFrameInfoIdx].renderTimeMs = frame.RenderTimeMs();
164 _callback->Map(frame.TimeStamp(), &_frameInfos[_nextFrameInfoIdx]); 196 _frameInfos[_nextFrameInfoIdx].rotation = frame.rotation();
197 _callback->Map(frame.TimeStamp(), &_frameInfos[_nextFrameInfoIdx]);
165 198
166 _nextFrameInfoIdx = (_nextFrameInfoIdx + 1) % kDecoderFrameMemoryLength; 199 _nextFrameInfoIdx = (_nextFrameInfoIdx + 1) % kDecoderFrameMemoryLength;
167 const RTPFragmentationHeader dummy_header; 200 const RTPFragmentationHeader dummy_header;
168 int32_t ret = _decoder->Decode(frame.EncodedImage(), frame.MissingFrame(), 201 int32_t ret = _decoder->Decode(frame.EncodedImage(), frame.MissingFrame(),
169 &dummy_header, 202 &dummy_header, frame.CodecSpecific(),
170 frame.CodecSpecific(), frame.RenderTimeMs()); 203 frame.RenderTimeMs());
171 204
172 _callback->OnDecoderImplementationName(_decoder->ImplementationName()); 205 _callback->OnDecoderImplementationName(_decoder->ImplementationName());
173 if (ret < WEBRTC_VIDEO_CODEC_OK) { 206 if (ret < WEBRTC_VIDEO_CODEC_OK) {
174 LOG(LS_WARNING) << "Failed to decode frame with timestamp " 207 LOG(LS_WARNING) << "Failed to decode frame with timestamp "
175 << frame.TimeStamp() << ", error code: " << ret; 208 << frame.TimeStamp() << ", error code: " << ret;
176 _callback->Pop(frame.TimeStamp()); 209 _callback->Pop(frame.TimeStamp());
177 return ret;
178 } else if (ret == WEBRTC_VIDEO_CODEC_NO_OUTPUT ||
179 ret == WEBRTC_VIDEO_CODEC_REQUEST_SLI) {
180 // No output
181 _callback->Pop(frame.TimeStamp());
182 }
183 return ret; 210 return ret;
211 }
212
213 if (ret == WEBRTC_VIDEO_CODEC_NO_OUTPUT ||
214 ret == WEBRTC_VIDEO_CODEC_REQUEST_SLI) {
215 // No output
216 _callback->Pop(frame.TimeStamp());
217 }
218
219 return ret;
184 } 220 }
185 221
186 int32_t VCMGenericDecoder::Release() { 222 int32_t VCMGenericDecoder::Release() {
223 // Looks like this is called outside of the decoder thread.
224 // See CallPerfTest.PlaysOutAudioAndVideoInSyncWithVideoNtpDrift.
225 // TODO(tommi): This is called after the decoder thread has been stopped.
226 // Can we DCHECK that somehow?
227 // RTC_DCHECK(decoder_thread_checker_.CalledOnValidThread());
187 return _decoder->Release(); 228 return _decoder->Release();
188 } 229 }
189 230
190 int32_t VCMGenericDecoder::RegisterDecodeCompleteCallback( 231 int32_t VCMGenericDecoder::RegisterDecodeCompleteCallback(
191 VCMDecodedFrameCallback* callback) { 232 VCMDecodedFrameCallback* callback) {
233 RTC_DCHECK(decoder_thread_checker_.CalledOnValidThread());
192 _callback = callback; 234 _callback = callback;
193 return _decoder->RegisterDecodeCompleteCallback(callback); 235 return _decoder->RegisterDecodeCompleteCallback(callback);
194 } 236 }
195 237
196 bool VCMGenericDecoder::External() const { 238 bool VCMGenericDecoder::External() const {
239 // Called outside of the decoder thread.
240 // See CallPerfTest.PlaysOutAudioAndVideoInSyncWithVideoNtpDrift
241 // RTC_DCHECK(decoder_thread_checker_.CalledOnValidThread());
197 return _isExternal; 242 return _isExternal;
198 } 243 }
199 244
200 bool VCMGenericDecoder::PrefersLateDecoding() const { 245 bool VCMGenericDecoder::PrefersLateDecoding() const {
246 RTC_DCHECK(decoder_thread_checker_.CalledOnValidThread());
201 return _decoder->PrefersLateDecoding(); 247 return _decoder->PrefersLateDecoding();
202 } 248 }
203 249
250 void VCMGenericDecoder::PollDecodedFrames() {
251 RTC_DCHECK(decoder_thread_checker_.CalledOnValidThread());
252 _decoder->PollDecodedFrames();
253 }
254
204 } // namespace webrtc 255 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/video_coding/generic_decoder.h ('k') | webrtc/modules/video_coding/video_coding_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698