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

Side by Side Diff: webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_decoder.cc

Issue 1732953003: Fix VideoToolbox backgrounding issues (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Remove unneeded include. Created 4 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) 2015 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2015 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 11
12 #include "webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_decoder.h" 12 #include "webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_decoder.h"
13 13
14 #if defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED) 14 #if defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED)
15 15
16 #include <memory> 16 #include <memory>
17 17
18 #include "libyuv/convert.h" 18 #include "libyuv/convert.h"
19 #include "webrtc/base/checks.h" 19 #include "webrtc/base/checks.h"
20 #include "webrtc/base/logging.h" 20 #include "webrtc/base/logging.h"
21 #if defined(WEBRTC_IOS)
22 #include "webrtc/base/objc/RTCUIApplication.h"
23 #endif
21 #include "webrtc/common_video/include/video_frame_buffer.h" 24 #include "webrtc/common_video/include/video_frame_buffer.h"
22 #include "webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_nalu.h" 25 #include "webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_nalu.h"
23 #include "webrtc/video_frame.h" 26 #include "webrtc/video_frame.h"
24 27
25 namespace internal { 28 namespace internal {
26 29
27 // Convenience function for creating a dictionary. 30 // Convenience function for creating a dictionary.
28 inline CFDictionaryRef CreateCFDictionary(CFTypeRef* keys, 31 inline CFDictionaryRef CreateCFDictionary(CFTypeRef* keys,
29 CFTypeRef* values, 32 CFTypeRef* values,
30 size_t size) { 33 size_t size) {
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 } 124 }
122 125
123 int H264VideoToolboxDecoder::Decode( 126 int H264VideoToolboxDecoder::Decode(
124 const EncodedImage& input_image, 127 const EncodedImage& input_image,
125 bool missing_frames, 128 bool missing_frames,
126 const RTPFragmentationHeader* fragmentation, 129 const RTPFragmentationHeader* fragmentation,
127 const CodecSpecificInfo* codec_specific_info, 130 const CodecSpecificInfo* codec_specific_info,
128 int64_t render_time_ms) { 131 int64_t render_time_ms) {
129 RTC_DCHECK(input_image._buffer); 132 RTC_DCHECK(input_image._buffer);
130 133
134 #if defined(WEBRTC_IOS)
135 bool is_app_active = RTCIsUIApplicationActive();
136 if (!is_app_active) {
137 // Ignore all decode requests when app isn't active. In this state, the
138 // hardware decoder has been invalidated by the OS.
139 // Reset video format so that we won't process frames until the next
140 // keyframe.
141 SetVideoFormat(nullptr);
142 return WEBRTC_VIDEO_CODEC_NO_OUTPUT;
143 }
144 #endif
145 CMVideoFormatDescriptionRef input_format = nullptr;
146 if (H264AnnexBBufferHasVideoFormatDescription(input_image._buffer,
147 input_image._length)) {
148 input_format = CreateVideoFormatDescription(input_image._buffer,
149 input_image._length);
150 if (input_format) {
151 // Check if the video format has changed, and reinitialize decoder if
152 // needed.
153 if (!CMFormatDescriptionEqual(input_format, video_format_)) {
154 SetVideoFormat(input_format);
155 ResetDecompressionSession();
156 }
157 CFRelease(input_format);
158 }
159 }
160 if (!video_format_) {
161 // We received a frame but we don't have format information so we can't
162 // decode it.
163 // This can happen after backgrounding. We need to wait for the next
164 // sps/pps before we can resume so we request a keyframe by returning an
165 // error.
166 LOG(LS_WARNING) << "Key frame required.";
167 return WEBRTC_VIDEO_CODEC_ERROR;
168 }
131 CMSampleBufferRef sample_buffer = nullptr; 169 CMSampleBufferRef sample_buffer = nullptr;
132 if (!H264AnnexBBufferToCMSampleBuffer(input_image._buffer, 170 if (!H264AnnexBBufferToCMSampleBuffer(input_image._buffer,
133 input_image._length, video_format_, 171 input_image._length, video_format_,
134 &sample_buffer)) { 172 &sample_buffer)) {
135 return WEBRTC_VIDEO_CODEC_ERROR; 173 return WEBRTC_VIDEO_CODEC_ERROR;
136 } 174 }
137 RTC_DCHECK(sample_buffer); 175 RTC_DCHECK(sample_buffer);
138 // Check if the video format has changed, and reinitialize decoder if needed.
139 CMVideoFormatDescriptionRef description =
140 CMSampleBufferGetFormatDescription(sample_buffer);
141 if (!CMFormatDescriptionEqual(description, video_format_)) {
142 SetVideoFormat(description);
143 ResetDecompressionSession();
144 }
145 VTDecodeFrameFlags decode_flags = 176 VTDecodeFrameFlags decode_flags =
146 kVTDecodeFrame_EnableAsynchronousDecompression; 177 kVTDecodeFrame_EnableAsynchronousDecompression;
147 std::unique_ptr<internal::FrameDecodeParams> frame_decode_params; 178 std::unique_ptr<internal::FrameDecodeParams> frame_decode_params;
148 frame_decode_params.reset( 179 frame_decode_params.reset(
149 new internal::FrameDecodeParams(callback_, input_image._timeStamp)); 180 new internal::FrameDecodeParams(callback_, input_image._timeStamp));
150 OSStatus status = VTDecompressionSessionDecodeFrame( 181 OSStatus status = VTDecompressionSessionDecodeFrame(
151 decompression_session_, sample_buffer, decode_flags, 182 decompression_session_, sample_buffer, decode_flags,
152 frame_decode_params.release(), nullptr); 183 frame_decode_params.release(), nullptr);
184 #if defined(WEBRTC_IOS)
185 // Re-initialize the decoder if we have an invalid session while the app is
186 // active and retry the decode request.
187 if (status == kVTInvalidSessionErr &&
188 is_app_active &&
189 ResetDecompressionSession() == WEBRTC_VIDEO_CODEC_OK) {
190 frame_decode_params.reset(
191 new internal::FrameDecodeParams(callback_, input_image._timeStamp));
192 status = VTDecompressionSessionDecodeFrame(
193 decompression_session_, sample_buffer, decode_flags,
194 frame_decode_params.release(), nullptr);
195 }
196 #endif
153 CFRelease(sample_buffer); 197 CFRelease(sample_buffer);
154 if (status != noErr) { 198 if (status != noErr) {
155 LOG(LS_ERROR) << "Failed to decode frame with code: " << status; 199 LOG(LS_ERROR) << "Failed to decode frame with code: " << status;
156 return WEBRTC_VIDEO_CODEC_ERROR; 200 return WEBRTC_VIDEO_CODEC_ERROR;
157 } 201 }
158 return WEBRTC_VIDEO_CODEC_OK; 202 return WEBRTC_VIDEO_CODEC_OK;
159 } 203 }
160 204
161 int H264VideoToolboxDecoder::RegisterDecodeCompleteCallback( 205 int H264VideoToolboxDecoder::RegisterDecodeCompleteCallback(
162 DecodedImageCallback* callback) { 206 DecodedImageCallback* callback) {
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 RTC_DCHECK(decompression_session_); 281 RTC_DCHECK(decompression_session_);
238 #if defined(WEBRTC_IOS) 282 #if defined(WEBRTC_IOS)
239 VTSessionSetProperty(decompression_session_, 283 VTSessionSetProperty(decompression_session_,
240 kVTDecompressionPropertyKey_RealTime, kCFBooleanTrue); 284 kVTDecompressionPropertyKey_RealTime, kCFBooleanTrue);
241 #endif 285 #endif
242 } 286 }
243 287
244 void H264VideoToolboxDecoder::DestroyDecompressionSession() { 288 void H264VideoToolboxDecoder::DestroyDecompressionSession() {
245 if (decompression_session_) { 289 if (decompression_session_) {
246 VTDecompressionSessionInvalidate(decompression_session_); 290 VTDecompressionSessionInvalidate(decompression_session_);
291 CFRelease(decompression_session_);
247 decompression_session_ = nullptr; 292 decompression_session_ = nullptr;
248 } 293 }
249 } 294 }
250 295
251 void H264VideoToolboxDecoder::SetVideoFormat( 296 void H264VideoToolboxDecoder::SetVideoFormat(
252 CMVideoFormatDescriptionRef video_format) { 297 CMVideoFormatDescriptionRef video_format) {
253 if (video_format_ == video_format) { 298 if (video_format_ == video_format) {
254 return; 299 return;
255 } 300 }
256 if (video_format_) { 301 if (video_format_) {
257 CFRelease(video_format_); 302 CFRelease(video_format_);
258 } 303 }
259 video_format_ = video_format; 304 video_format_ = video_format;
260 if (video_format_) { 305 if (video_format_) {
261 CFRetain(video_format_); 306 CFRetain(video_format_);
262 } 307 }
263 } 308 }
264 309
265 const char* H264VideoToolboxDecoder::ImplementationName() const { 310 const char* H264VideoToolboxDecoder::ImplementationName() const {
266 return "VideoToolbox"; 311 return "VideoToolbox";
267 } 312 }
268 313
269 } // namespace webrtc 314 } // namespace webrtc
270 315
271 #endif // defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED) 316 #endif // defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698