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

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

Issue 2764573002: Deliver video frames on Android, on the decode thread. (Closed)
Patch Set: Update comments Created 3 years, 8 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"
13 #include "webrtc/base/trace_event.h" 15 #include "webrtc/base/trace_event.h"
14 #include "webrtc/modules/video_coding/include/video_coding.h" 16 #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" 17 #include "webrtc/modules/video_coding/internal_defines.h"
17 #include "webrtc/system_wrappers/include/clock.h" 18 #include "webrtc/system_wrappers/include/clock.h"
18 19
19 namespace webrtc { 20 namespace webrtc {
20 21
21 VCMDecodedFrameCallback::VCMDecodedFrameCallback(VCMTiming* timing, 22 VCMDecodedFrameCallback::VCMDecodedFrameCallback(VCMTiming* timing,
22 Clock* clock) 23 Clock* clock)
23 : _clock(clock), 24 : _clock(clock),
24 _timing(timing), 25 _timing(timing),
25 _timestampMap(kDecoderFrameMemoryLength), 26 _timestampMap(kDecoderFrameMemoryLength),
26 _lastReceivedPictureID(0) {} 27 _lastReceivedPictureID(0) {
28 decoder_thread_.DetachFromThread();
29 }
27 30
28 VCMDecodedFrameCallback::~VCMDecodedFrameCallback() { 31 VCMDecodedFrameCallback::~VCMDecodedFrameCallback() {
32 RTC_DCHECK(construction_thread_.CalledOnValidThread());
29 } 33 }
30 34
31 void VCMDecodedFrameCallback::SetUserReceiveCallback( 35 void VCMDecodedFrameCallback::SetUserReceiveCallback(
32 VCMReceiveCallback* receiveCallback) { 36 VCMReceiveCallback* receiveCallback) {
33 RTC_DCHECK(construction_thread_.CalledOnValidThread()); 37 RTC_DCHECK(construction_thread_.CalledOnValidThread());
34 RTC_DCHECK((!_receiveCallback && receiveCallback) || 38 RTC_DCHECK((!_receiveCallback && receiveCallback) ||
35 (_receiveCallback && !receiveCallback)); 39 (_receiveCallback && !receiveCallback));
36 _receiveCallback = receiveCallback; 40 _receiveCallback = receiveCallback;
37 } 41 }
38 42
39 VCMReceiveCallback* VCMDecodedFrameCallback::UserReceiveCallback() { 43 VCMReceiveCallback* VCMDecodedFrameCallback::UserReceiveCallback() {
44 RTC_DCHECK_RUN_ON(&decoder_thread_);
40 // Called on the decode thread via VCMCodecDataBase::GetDecoder. 45 // Called on the decode thread via VCMCodecDataBase::GetDecoder.
41 // The callback must always have been set before this happens. 46 // The callback must always have been set before this happens.
42 RTC_DCHECK(_receiveCallback); 47 RTC_DCHECK(_receiveCallback);
43 return _receiveCallback; 48 return _receiveCallback;
44 } 49 }
45 50
46 int32_t VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage) { 51 int32_t VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage) {
47 return Decoded(decodedImage, -1); 52 return Decoded(decodedImage, -1);
48 } 53 }
49 54
50 int32_t VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage, 55 int32_t VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage,
51 int64_t decode_time_ms) { 56 int64_t decode_time_ms) {
52 Decoded(decodedImage, 57 Decoded(decodedImage,
53 decode_time_ms >= 0 ? rtc::Optional<int32_t>(decode_time_ms) 58 decode_time_ms >= 0 ? rtc::Optional<int32_t>(decode_time_ms)
54 : rtc::Optional<int32_t>(), 59 : rtc::Optional<int32_t>(),
55 rtc::Optional<uint8_t>()); 60 rtc::Optional<uint8_t>());
56 return WEBRTC_VIDEO_CODEC_OK; 61 return WEBRTC_VIDEO_CODEC_OK;
57 } 62 }
58 63
59 void VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage, 64 void VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage,
60 rtc::Optional<int32_t> decode_time_ms, 65 rtc::Optional<int32_t> decode_time_ms,
61 rtc::Optional<uint8_t> qp) { 66 rtc::Optional<uint8_t> qp) {
67 RTC_DCHECK_RUN_ON(&decoder_thread_);
62 RTC_DCHECK(_receiveCallback) << "Callback must not be null at this point"; 68 RTC_DCHECK(_receiveCallback) << "Callback must not be null at this point";
69
63 TRACE_EVENT_INSTANT1("webrtc", "VCMDecodedFrameCallback::Decoded", 70 TRACE_EVENT_INSTANT1("webrtc", "VCMDecodedFrameCallback::Decoded",
64 "timestamp", decodedImage.timestamp()); 71 "timestamp", decodedImage.timestamp());
65 // TODO(holmer): We should improve this so that we can handle multiple 72 // TODO(holmer): We should improve this so that we can handle multiple
66 // callbacks from one call to Decode(). 73 // callbacks from one call to Decode().
67 VCMFrameInformation* frameInfo; 74 VCMFrameInformation* frameInfo = _timestampMap.Pop(decodedImage.timestamp());
68 {
69 rtc::CritScope cs(&lock_);
70 frameInfo = _timestampMap.Pop(decodedImage.timestamp());
71 }
72 75
73 if (frameInfo == NULL) { 76 if (frameInfo == NULL) {
74 LOG(LS_WARNING) << "Too many frames backed up in the decoder, dropping " 77 LOG(LS_WARNING) << "Too many frames backed up in the decoder, dropping "
75 "this one."; 78 "this one.";
76 return; 79 return;
77 } 80 }
78 81
79 const int64_t now_ms = _clock->TimeInMilliseconds(); 82 const int64_t now_ms = _clock->TimeInMilliseconds();
80 if (!decode_time_ms) { 83 if (!decode_time_ms) {
81 decode_time_ms = 84 decode_time_ms =
82 rtc::Optional<int32_t>(now_ms - frameInfo->decodeStartTimeMs); 85 rtc::Optional<int32_t>(now_ms - frameInfo->decodeStartTimeMs);
83 } 86 }
84 _timing->StopDecodeTimer(decodedImage.timestamp(), *decode_time_ms, now_ms, 87 _timing->StopDecodeTimer(decodedImage.timestamp(), *decode_time_ms, now_ms,
85 frameInfo->renderTimeMs); 88 frameInfo->renderTimeMs);
86 89
87 decodedImage.set_timestamp_us( 90 decodedImage.set_timestamp_us(
88 frameInfo->renderTimeMs * rtc::kNumMicrosecsPerMillisec); 91 frameInfo->renderTimeMs * rtc::kNumMicrosecsPerMillisec);
89 decodedImage.set_rotation(frameInfo->rotation); 92 decodedImage.set_rotation(frameInfo->rotation);
90 _receiveCallback->FrameToRender(decodedImage, qp); 93 _receiveCallback->FrameToRender(decodedImage, qp);
91 } 94 }
92 95
93 int32_t VCMDecodedFrameCallback::ReceivedDecodedReferenceFrame( 96 int32_t VCMDecodedFrameCallback::ReceivedDecodedReferenceFrame(
94 const uint64_t pictureId) { 97 const uint64_t pictureId) {
98 RTC_DCHECK_RUN_ON(&decoder_thread_);
95 return _receiveCallback->ReceivedDecodedReferenceFrame(pictureId); 99 return _receiveCallback->ReceivedDecodedReferenceFrame(pictureId);
96 } 100 }
97 101
98 int32_t VCMDecodedFrameCallback::ReceivedDecodedFrame( 102 int32_t VCMDecodedFrameCallback::ReceivedDecodedFrame(
99 const uint64_t pictureId) { 103 const uint64_t pictureId) {
104 RTC_DCHECK_RUN_ON(&decoder_thread_);
100 _lastReceivedPictureID = pictureId; 105 _lastReceivedPictureID = pictureId;
101 return 0; 106 return 0;
102 } 107 }
103 108
104 uint64_t VCMDecodedFrameCallback::LastReceivedPictureID() const { 109 uint64_t VCMDecodedFrameCallback::LastReceivedPictureID() const {
110 RTC_DCHECK_RUN_ON(&decoder_thread_);
105 return _lastReceivedPictureID; 111 return _lastReceivedPictureID;
106 } 112 }
107 113
108 void VCMDecodedFrameCallback::OnDecoderImplementationName( 114 void VCMDecodedFrameCallback::OnDecoderImplementationName(
109 const char* implementation_name) { 115 const char* implementation_name) {
116 RTC_DCHECK_RUN_ON(&decoder_thread_);
110 _receiveCallback->OnDecoderImplementationName(implementation_name); 117 _receiveCallback->OnDecoderImplementationName(implementation_name);
111 } 118 }
112 119
113 void VCMDecodedFrameCallback::Map(uint32_t timestamp, 120 void VCMDecodedFrameCallback::Map(uint32_t timestamp,
114 VCMFrameInformation* frameInfo) { 121 VCMFrameInformation* frameInfo) {
115 rtc::CritScope cs(&lock_); 122 RTC_DCHECK_RUN_ON(&decoder_thread_);
116 _timestampMap.Add(timestamp, frameInfo); 123 _timestampMap.Add(timestamp, frameInfo);
117 } 124 }
118 125
119 int32_t VCMDecodedFrameCallback::Pop(uint32_t timestamp) { 126 int32_t VCMDecodedFrameCallback::Pop(uint32_t timestamp) {
120 rtc::CritScope cs(&lock_); 127 RTC_DCHECK_RUN_ON(&decoder_thread_);
121 if (_timestampMap.Pop(timestamp) == NULL) { 128 return _timestampMap.Pop(timestamp) == nullptr ? VCM_GENERAL_ERROR : VCM_OK;
122 return VCM_GENERAL_ERROR;
123 }
124 return VCM_OK;
125 } 129 }
126 130
127 VCMGenericDecoder::VCMGenericDecoder(VideoDecoder* decoder, bool isExternal) 131 VCMGenericDecoder::VCMGenericDecoder(VideoDecoder* decoder, bool isExternal)
128 : _callback(NULL), 132 : _callback(NULL),
129 _frameInfos(), 133 _frameInfos(),
130 _nextFrameInfoIdx(0), 134 _nextFrameInfoIdx(0),
131 _decoder(decoder), 135 decoder_(decoder),
132 _codecType(kVideoCodecUnknown), 136 _codecType(kVideoCodecUnknown),
133 _isExternal(isExternal), 137 _isExternal(isExternal) {}
134 _keyFrameDecoded(false) {}
135 138
136 VCMGenericDecoder::~VCMGenericDecoder() {} 139 VCMGenericDecoder::~VCMGenericDecoder() {
140 decoder_->Release();
141 if (_isExternal)
142 decoder_.release();
143
144 RTC_DCHECK(_isExternal || !decoder_);
145 }
137 146
138 int32_t VCMGenericDecoder::InitDecode(const VideoCodec* settings, 147 int32_t VCMGenericDecoder::InitDecode(const VideoCodec* settings,
139 int32_t numberOfCores) { 148 int32_t numberOfCores) {
149 RTC_DCHECK_RUN_ON(&decoder_thread_);
140 TRACE_EVENT0("webrtc", "VCMGenericDecoder::InitDecode"); 150 TRACE_EVENT0("webrtc", "VCMGenericDecoder::InitDecode");
141 _codecType = settings->codecType; 151 _codecType = settings->codecType;
142 152
143 return _decoder->InitDecode(settings, numberOfCores); 153 return decoder_->InitDecode(settings, numberOfCores);
144 } 154 }
145 155
146 int32_t VCMGenericDecoder::Decode(const VCMEncodedFrame& frame, int64_t nowMs) { 156 int32_t VCMGenericDecoder::Decode(const VCMEncodedFrame& frame, int64_t nowMs) {
147 TRACE_EVENT1("webrtc", "VCMGenericDecoder::Decode", "timestamp", 157 RTC_DCHECK_RUN_ON(&decoder_thread_);
148 frame.EncodedImage()._timeStamp); 158 TRACE_EVENT2("webrtc", "VCMGenericDecoder::Decode", "timestamp",
149 _frameInfos[_nextFrameInfoIdx].decodeStartTimeMs = nowMs; 159 frame.EncodedImage()._timeStamp, "decoder",
150 _frameInfos[_nextFrameInfoIdx].renderTimeMs = frame.RenderTimeMs(); 160 decoder_->ImplementationName());
151 _frameInfos[_nextFrameInfoIdx].rotation = frame.rotation(); 161 _frameInfos[_nextFrameInfoIdx].decodeStartTimeMs = nowMs;
152 _callback->Map(frame.TimeStamp(), &_frameInfos[_nextFrameInfoIdx]); 162 _frameInfos[_nextFrameInfoIdx].renderTimeMs = frame.RenderTimeMs();
163 _frameInfos[_nextFrameInfoIdx].rotation = frame.rotation();
164 _callback->Map(frame.TimeStamp(), &_frameInfos[_nextFrameInfoIdx]);
153 165
154 _nextFrameInfoIdx = (_nextFrameInfoIdx + 1) % kDecoderFrameMemoryLength; 166 _nextFrameInfoIdx = (_nextFrameInfoIdx + 1) % kDecoderFrameMemoryLength;
155 const RTPFragmentationHeader dummy_header; 167 const RTPFragmentationHeader dummy_header;
156 int32_t ret = _decoder->Decode(frame.EncodedImage(), frame.MissingFrame(), 168 int32_t ret = decoder_->Decode(frame.EncodedImage(), frame.MissingFrame(),
157 &dummy_header, 169 &dummy_header, frame.CodecSpecific(),
158 frame.CodecSpecific(), frame.RenderTimeMs()); 170 frame.RenderTimeMs());
159 171
160 _callback->OnDecoderImplementationName(_decoder->ImplementationName()); 172 // TODO(tommi): Necessary every time?
173 // Maybe this should be the first thing the function does, and only the first
174 // time around?
175 _callback->OnDecoderImplementationName(decoder_->ImplementationName());
176
177 if (ret != WEBRTC_VIDEO_CODEC_OK) {
161 if (ret < WEBRTC_VIDEO_CODEC_OK) { 178 if (ret < WEBRTC_VIDEO_CODEC_OK) {
162 LOG(LS_WARNING) << "Failed to decode frame with timestamp " 179 LOG(LS_WARNING) << "Failed to decode frame with timestamp "
163 << frame.TimeStamp() << ", error code: " << ret; 180 << frame.TimeStamp() << ", error code: " << ret;
164 _callback->Pop(frame.TimeStamp());
165 return ret;
166 } else if (ret == WEBRTC_VIDEO_CODEC_NO_OUTPUT ||
167 ret == WEBRTC_VIDEO_CODEC_REQUEST_SLI) {
168 // No output
169 _callback->Pop(frame.TimeStamp());
170 } 181 }
171 return ret; 182 // We pop the frame for all non-'OK', failure or success codes such as
172 } 183 // WEBRTC_VIDEO_CODEC_NO_OUTPUT and WEBRTC_VIDEO_CODEC_REQUEST_SLI.
184 _callback->Pop(frame.TimeStamp());
185 }
173 186
174 int32_t VCMGenericDecoder::Release() { 187 return ret;
175 return _decoder->Release();
176 } 188 }
177 189
178 int32_t VCMGenericDecoder::RegisterDecodeCompleteCallback( 190 int32_t VCMGenericDecoder::RegisterDecodeCompleteCallback(
179 VCMDecodedFrameCallback* callback) { 191 VCMDecodedFrameCallback* callback) {
192 RTC_DCHECK_RUN_ON(&decoder_thread_);
180 _callback = callback; 193 _callback = callback;
181 return _decoder->RegisterDecodeCompleteCallback(callback); 194 return decoder_->RegisterDecodeCompleteCallback(callback);
182 }
183
184 bool VCMGenericDecoder::External() const {
185 return _isExternal;
186 } 195 }
187 196
188 bool VCMGenericDecoder::PrefersLateDecoding() const { 197 bool VCMGenericDecoder::PrefersLateDecoding() const {
189 return _decoder->PrefersLateDecoding(); 198 RTC_DCHECK_RUN_ON(&decoder_thread_);
199 return decoder_->PrefersLateDecoding();
190 } 200 }
191 201
202 #if defined(WEBRTC_ANDROID)
203 void VCMGenericDecoder::PollDecodedFrames() {
204 RTC_DCHECK_RUN_ON(&decoder_thread_);
205 decoder_->PollDecodedFrames();
206 }
207 #endif
208
192 } // namespace webrtc 209 } // 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