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

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

Issue 2811963004: Deliver video frames on Android, on the decode thread.
Patch Set: Rebase Created 3 years, 4 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
(...skipping 10 matching lines...) Expand all
21 #include "webrtc/system_wrappers/include/clock.h" 21 #include "webrtc/system_wrappers/include/clock.h"
22 22
23 namespace webrtc { 23 namespace webrtc {
24 24
25 VCMDecodedFrameCallback::VCMDecodedFrameCallback(VCMTiming* timing, 25 VCMDecodedFrameCallback::VCMDecodedFrameCallback(VCMTiming* timing,
26 Clock* clock) 26 Clock* clock)
27 : _clock(clock), 27 : _clock(clock),
28 _timing(timing), 28 _timing(timing),
29 _timestampMap(kDecoderFrameMemoryLength), 29 _timestampMap(kDecoderFrameMemoryLength),
30 _lastReceivedPictureID(0) { 30 _lastReceivedPictureID(0) {
31 decoder_thread_.DetachFromThread();
31 ntp_offset_ = 32 ntp_offset_ =
32 _clock->CurrentNtpInMilliseconds() - _clock->TimeInMilliseconds(); 33 _clock->CurrentNtpInMilliseconds() - _clock->TimeInMilliseconds();
33 } 34 }
34 35
35 VCMDecodedFrameCallback::~VCMDecodedFrameCallback() { 36 VCMDecodedFrameCallback::~VCMDecodedFrameCallback() {
37 RTC_DCHECK(construction_thread_.CalledOnValidThread());
36 } 38 }
37 39
38 void VCMDecodedFrameCallback::SetUserReceiveCallback( 40 void VCMDecodedFrameCallback::SetUserReceiveCallback(
39 VCMReceiveCallback* receiveCallback) { 41 VCMReceiveCallback* receiveCallback) {
40 RTC_DCHECK(construction_thread_.CalledOnValidThread()); 42 RTC_DCHECK(construction_thread_.CalledOnValidThread());
41 RTC_DCHECK((!_receiveCallback && receiveCallback) || 43 RTC_DCHECK((!_receiveCallback && receiveCallback) ||
42 (_receiveCallback && !receiveCallback)); 44 (_receiveCallback && !receiveCallback));
43 _receiveCallback = receiveCallback; 45 _receiveCallback = receiveCallback;
46 // When the callback is cleared, it signals to us that the decoder thread
47 // is no longer running. Another decoder thread might be started, so it's
48 // important to reset the thread checker first.
49 if (!receiveCallback)
50 decoder_thread_.DetachFromThread();
44 } 51 }
45 52
46 VCMReceiveCallback* VCMDecodedFrameCallback::UserReceiveCallback() { 53 VCMReceiveCallback* VCMDecodedFrameCallback::UserReceiveCallback() {
54 RTC_DCHECK_RUN_ON(&decoder_thread_);
47 // Called on the decode thread via VCMCodecDataBase::GetDecoder. 55 // Called on the decode thread via VCMCodecDataBase::GetDecoder.
48 // The callback must always have been set before this happens. 56 // The callback must always have been set before this happens.
49 RTC_DCHECK(_receiveCallback); 57 RTC_DCHECK(_receiveCallback);
50 return _receiveCallback; 58 return _receiveCallback;
51 } 59 }
52 60
53 int32_t VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage) { 61 int32_t VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage) {
54 return Decoded(decodedImage, -1); 62 return Decoded(decodedImage, -1);
55 } 63 }
56 64
57 int32_t VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage, 65 int32_t VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage,
58 int64_t decode_time_ms) { 66 int64_t decode_time_ms) {
59 Decoded(decodedImage, 67 Decoded(decodedImage,
60 decode_time_ms >= 0 ? rtc::Optional<int32_t>(decode_time_ms) 68 decode_time_ms >= 0 ? rtc::Optional<int32_t>(decode_time_ms)
61 : rtc::Optional<int32_t>(), 69 : rtc::Optional<int32_t>(),
62 rtc::Optional<uint8_t>()); 70 rtc::Optional<uint8_t>());
63 return WEBRTC_VIDEO_CODEC_OK; 71 return WEBRTC_VIDEO_CODEC_OK;
64 } 72 }
65 73
66 void VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage, 74 void VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage,
67 rtc::Optional<int32_t> decode_time_ms, 75 rtc::Optional<int32_t> decode_time_ms,
68 rtc::Optional<uint8_t> qp) { 76 rtc::Optional<uint8_t> qp) {
77 RTC_DCHECK_RUN_ON(&decoder_thread_);
69 RTC_DCHECK(_receiveCallback) << "Callback must not be null at this point"; 78 RTC_DCHECK(_receiveCallback) << "Callback must not be null at this point";
79
70 TRACE_EVENT_INSTANT1("webrtc", "VCMDecodedFrameCallback::Decoded", 80 TRACE_EVENT_INSTANT1("webrtc", "VCMDecodedFrameCallback::Decoded",
71 "timestamp", decodedImage.timestamp()); 81 "timestamp", decodedImage.timestamp());
72 // TODO(holmer): We should improve this so that we can handle multiple 82 // TODO(holmer): We should improve this so that we can handle multiple
73 // callbacks from one call to Decode(). 83 // callbacks from one call to Decode().
74 VCMFrameInformation* frameInfo; 84 VCMFrameInformation* frameInfo = _timestampMap.Pop(decodedImage.timestamp());
75 {
76 rtc::CritScope cs(&lock_);
77 frameInfo = _timestampMap.Pop(decodedImage.timestamp());
78 }
79 85
80 if (frameInfo == NULL) { 86 if (frameInfo == NULL) {
81 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 "
82 "this one."; 88 "this one.";
83 return; 89 return;
84 } 90 }
85 91
86 const int64_t now_ms = _clock->TimeInMilliseconds(); 92 const int64_t now_ms = _clock->TimeInMilliseconds();
87 if (!decode_time_ms) { 93 if (!decode_time_ms) {
88 decode_time_ms = 94 decode_time_ms =
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 } 148 }
143 149
144 decodedImage.set_timestamp_us( 150 decodedImage.set_timestamp_us(
145 frameInfo->renderTimeMs * rtc::kNumMicrosecsPerMillisec); 151 frameInfo->renderTimeMs * rtc::kNumMicrosecsPerMillisec);
146 decodedImage.set_rotation(frameInfo->rotation); 152 decodedImage.set_rotation(frameInfo->rotation);
147 _receiveCallback->FrameToRender(decodedImage, qp, frameInfo->content_type); 153 _receiveCallback->FrameToRender(decodedImage, qp, frameInfo->content_type);
148 } 154 }
149 155
150 int32_t VCMDecodedFrameCallback::ReceivedDecodedReferenceFrame( 156 int32_t VCMDecodedFrameCallback::ReceivedDecodedReferenceFrame(
151 const uint64_t pictureId) { 157 const uint64_t pictureId) {
158 RTC_DCHECK_RUN_ON(&decoder_thread_);
152 return _receiveCallback->ReceivedDecodedReferenceFrame(pictureId); 159 return _receiveCallback->ReceivedDecodedReferenceFrame(pictureId);
153 } 160 }
154 161
155 int32_t VCMDecodedFrameCallback::ReceivedDecodedFrame( 162 int32_t VCMDecodedFrameCallback::ReceivedDecodedFrame(
156 const uint64_t pictureId) { 163 const uint64_t pictureId) {
164 RTC_DCHECK_RUN_ON(&decoder_thread_);
157 _lastReceivedPictureID = pictureId; 165 _lastReceivedPictureID = pictureId;
158 return 0; 166 return 0;
159 } 167 }
160 168
161 uint64_t VCMDecodedFrameCallback::LastReceivedPictureID() const { 169 uint64_t VCMDecodedFrameCallback::LastReceivedPictureID() const {
170 RTC_DCHECK_RUN_ON(&decoder_thread_);
162 return _lastReceivedPictureID; 171 return _lastReceivedPictureID;
163 } 172 }
164 173
165 void VCMDecodedFrameCallback::OnDecoderImplementationName( 174 void VCMDecodedFrameCallback::OnDecoderImplementationName(
166 const char* implementation_name) { 175 const char* implementation_name) {
176 RTC_DCHECK_RUN_ON(&decoder_thread_);
167 _receiveCallback->OnDecoderImplementationName(implementation_name); 177 _receiveCallback->OnDecoderImplementationName(implementation_name);
168 } 178 }
169 179
170 void VCMDecodedFrameCallback::Map(uint32_t timestamp, 180 void VCMDecodedFrameCallback::Map(uint32_t timestamp,
171 VCMFrameInformation* frameInfo) { 181 VCMFrameInformation* frameInfo) {
172 rtc::CritScope cs(&lock_); 182 RTC_DCHECK_RUN_ON(&decoder_thread_);
173 _timestampMap.Add(timestamp, frameInfo); 183 _timestampMap.Add(timestamp, frameInfo);
174 } 184 }
175 185
176 int32_t VCMDecodedFrameCallback::Pop(uint32_t timestamp) { 186 int32_t VCMDecodedFrameCallback::Pop(uint32_t timestamp) {
177 rtc::CritScope cs(&lock_); 187 RTC_DCHECK_RUN_ON(&decoder_thread_);
178 if (_timestampMap.Pop(timestamp) == NULL) { 188 return _timestampMap.Pop(timestamp) == nullptr ? VCM_GENERAL_ERROR : VCM_OK;
179 return VCM_GENERAL_ERROR;
180 }
181 return VCM_OK;
182 } 189 }
183 190
184 VCMGenericDecoder::VCMGenericDecoder(VideoDecoder* decoder, bool isExternal) 191 VCMGenericDecoder::VCMGenericDecoder(VideoDecoder* decoder, bool isExternal)
185 : _callback(NULL), 192 : _callback(NULL),
186 _frameInfos(), 193 _frameInfos(),
187 _nextFrameInfoIdx(0), 194 _nextFrameInfoIdx(0),
188 decoder_(decoder), 195 decoder_(decoder),
189 _codecType(kVideoCodecUnknown), 196 _codecType(kVideoCodecUnknown),
190 _isExternal(isExternal), 197 _isExternal(isExternal),
191 _last_keyframe_content_type(VideoContentType::UNSPECIFIED) { 198 _last_keyframe_content_type(VideoContentType::UNSPECIFIED) {
192 RTC_DCHECK(decoder_); 199 RTC_DCHECK(decoder_);
193 } 200 }
194 201
195 VCMGenericDecoder::~VCMGenericDecoder() { 202 VCMGenericDecoder::~VCMGenericDecoder() {
196 decoder_->Release(); 203 decoder_->Release();
197 if (_isExternal) 204 if (_isExternal)
198 decoder_.release(); 205 decoder_.release();
199 RTC_DCHECK(_isExternal || decoder_); 206 RTC_DCHECK(_isExternal || decoder_);
200 } 207 }
201 208
202 int32_t VCMGenericDecoder::InitDecode(const VideoCodec* settings, 209 int32_t VCMGenericDecoder::InitDecode(const VideoCodec* settings,
203 int32_t numberOfCores) { 210 int32_t numberOfCores) {
211 RTC_DCHECK_RUN_ON(&decoder_thread_);
204 TRACE_EVENT0("webrtc", "VCMGenericDecoder::InitDecode"); 212 TRACE_EVENT0("webrtc", "VCMGenericDecoder::InitDecode");
205 _codecType = settings->codecType; 213 _codecType = settings->codecType;
206 214
207 return decoder_->InitDecode(settings, numberOfCores); 215 return decoder_->InitDecode(settings, numberOfCores);
208 } 216 }
209 217
210 int32_t VCMGenericDecoder::Decode(const VCMEncodedFrame& frame, int64_t nowMs) { 218 int32_t VCMGenericDecoder::Decode(const VCMEncodedFrame& frame, int64_t nowMs) {
211 TRACE_EVENT1("webrtc", "VCMGenericDecoder::Decode", "timestamp", 219 RTC_DCHECK_RUN_ON(&decoder_thread_);
212 frame.EncodedImage()._timeStamp); 220 TRACE_EVENT2("webrtc", "VCMGenericDecoder::Decode", "timestamp",
213 _frameInfos[_nextFrameInfoIdx].decodeStartTimeMs = nowMs; 221 frame.EncodedImage()._timeStamp, "decoder",
214 _frameInfos[_nextFrameInfoIdx].renderTimeMs = frame.RenderTimeMs(); 222 decoder_->ImplementationName());
215 _frameInfos[_nextFrameInfoIdx].rotation = frame.rotation(); 223 _frameInfos[_nextFrameInfoIdx].decodeStartTimeMs = nowMs;
216 _frameInfos[_nextFrameInfoIdx].timing = frame.video_timing(); 224 _frameInfos[_nextFrameInfoIdx].renderTimeMs = frame.RenderTimeMs();
217 // Set correctly only for key frames. Thus, use latest key frame 225 _frameInfos[_nextFrameInfoIdx].rotation = frame.rotation();
218 // content type. If the corresponding key frame was lost, decode will fail 226 _frameInfos[_nextFrameInfoIdx].timing = frame.video_timing();
219 // and content type will be ignored. 227 // Set correctly only for key frames. Thus, use latest key frame
220 if (frame.FrameType() == kVideoFrameKey) { 228 // content type. If the corresponding key frame was lost, decode will fail
221 _frameInfos[_nextFrameInfoIdx].content_type = frame.contentType(); 229 // and content type will be ignored.
222 _last_keyframe_content_type = frame.contentType(); 230 if (frame.FrameType() == kVideoFrameKey) {
223 } else { 231 _frameInfos[_nextFrameInfoIdx].content_type = frame.contentType();
224 _frameInfos[_nextFrameInfoIdx].content_type = _last_keyframe_content_type; 232 _last_keyframe_content_type = frame.contentType();
233 } else {
234 _frameInfos[_nextFrameInfoIdx].content_type = _last_keyframe_content_type;
235 }
236 _callback->Map(frame.TimeStamp(), &_frameInfos[_nextFrameInfoIdx]);
237
238 _nextFrameInfoIdx = (_nextFrameInfoIdx + 1) % kDecoderFrameMemoryLength;
239 const RTPFragmentationHeader dummy_header;
240 int32_t ret = decoder_->Decode(frame.EncodedImage(), frame.MissingFrame(),
241 &dummy_header, frame.CodecSpecific(),
242 frame.RenderTimeMs());
243
244 // TODO(tommi): Necessary every time?
245 // Maybe this should be the first thing the function does, and only the first
246 // time around?
247 _callback->OnDecoderImplementationName(decoder_->ImplementationName());
248
249 if (ret != WEBRTC_VIDEO_CODEC_OK) {
250 if (ret < WEBRTC_VIDEO_CODEC_OK) {
251 LOG(LS_WARNING) << "Failed to decode frame with timestamp "
252 << frame.TimeStamp() << ", error code: " << ret;
225 } 253 }
226 _callback->Map(frame.TimeStamp(), &_frameInfos[_nextFrameInfoIdx]); 254 // We pop the frame for all non-'OK', failure or success codes such as
255 // WEBRTC_VIDEO_CODEC_NO_OUTPUT and WEBRTC_VIDEO_CODEC_REQUEST_SLI.
256 _callback->Pop(frame.TimeStamp());
257 }
227 258
228 _nextFrameInfoIdx = (_nextFrameInfoIdx + 1) % kDecoderFrameMemoryLength; 259 return ret;
229 const RTPFragmentationHeader dummy_header;
230 int32_t ret = decoder_->Decode(frame.EncodedImage(), frame.MissingFrame(),
231 &dummy_header,
232 frame.CodecSpecific(), frame.RenderTimeMs());
233
234 _callback->OnDecoderImplementationName(decoder_->ImplementationName());
235 if (ret < WEBRTC_VIDEO_CODEC_OK) {
236 LOG(LS_WARNING) << "Failed to decode frame with timestamp "
237 << frame.TimeStamp() << ", error code: " << ret;
238 _callback->Pop(frame.TimeStamp());
239 return ret;
240 } else if (ret == WEBRTC_VIDEO_CODEC_NO_OUTPUT ||
241 ret == WEBRTC_VIDEO_CODEC_REQUEST_SLI) {
242 // No output
243 _callback->Pop(frame.TimeStamp());
244 }
245 return ret;
246 } 260 }
247 261
248 int32_t VCMGenericDecoder::RegisterDecodeCompleteCallback( 262 int32_t VCMGenericDecoder::RegisterDecodeCompleteCallback(
249 VCMDecodedFrameCallback* callback) { 263 VCMDecodedFrameCallback* callback) {
264 RTC_DCHECK_RUN_ON(&decoder_thread_);
250 _callback = callback; 265 _callback = callback;
251 return decoder_->RegisterDecodeCompleteCallback(callback); 266 return decoder_->RegisterDecodeCompleteCallback(callback);
252 } 267 }
253 268
254 bool VCMGenericDecoder::PrefersLateDecoding() const { 269 bool VCMGenericDecoder::PrefersLateDecoding() const {
270 RTC_DCHECK_RUN_ON(&decoder_thread_);
255 return decoder_->PrefersLateDecoding(); 271 return decoder_->PrefersLateDecoding();
256 } 272 }
257 273
274 #if defined(WEBRTC_ANDROID)
275 void VCMGenericDecoder::PollDecodedFrames() {
276 RTC_DCHECK_RUN_ON(&decoder_thread_);
277 decoder_->PollDecodedFrames();
278 }
279 #endif
280
258 } // namespace webrtc 281 } // 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