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

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: CR comments 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 if (!RTCIsUIApplicationActive()) {
136 // Ignore all decode requests when app isn't active. In this state, the
137 // hardware decoder has been invalidated by the OS.
138 // Reset video format so that we won't process frames until the next
139 // keyframe.
140 SetVideoFormat(nullptr);
141 return WEBRTC_VIDEO_CODEC_NO_OUTPUT;
142 }
143 #endif
144 CMVideoFormatDescriptionRef input_format = nullptr;
145 if (H264AnnexBBufferHasVideoFormatDescription(input_image._buffer,
146 input_image._length)) {
147 input_format = CreateVideoFormatDescription(input_image._buffer,
148 input_image._length);
149 if (input_format) {
150 // Check if the video format has changed, and reinitialize decoder if
151 // needed.
152 if (!CMFormatDescriptionEqual(input_format, video_format_)) {
153 SetVideoFormat(input_format);
154 ResetDecompressionSession();
155 }
156 CFRelease(input_format);
157 }
158 }
159 if (!video_format_) {
160 // We received a frame but we don't have format information so we can't
161 // decode it.
162 // This can happen after backgrounding. We need to wait for the next
163 // sps/pps before we can resume so we request a keyframe by returning an
164 // error.
165 LOG(LS_WARNING) << "Missing video format. Frame with sps/pps required.";
166 return WEBRTC_VIDEO_CODEC_ERROR;
167 }
131 CMSampleBufferRef sample_buffer = nullptr; 168 CMSampleBufferRef sample_buffer = nullptr;
132 if (!H264AnnexBBufferToCMSampleBuffer(input_image._buffer, 169 if (!H264AnnexBBufferToCMSampleBuffer(input_image._buffer,
133 input_image._length, video_format_, 170 input_image._length, video_format_,
134 &sample_buffer)) { 171 &sample_buffer)) {
135 return WEBRTC_VIDEO_CODEC_ERROR; 172 return WEBRTC_VIDEO_CODEC_ERROR;
136 } 173 }
137 RTC_DCHECK(sample_buffer); 174 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 = 175 VTDecodeFrameFlags decode_flags =
146 kVTDecodeFrame_EnableAsynchronousDecompression; 176 kVTDecodeFrame_EnableAsynchronousDecompression;
147 std::unique_ptr<internal::FrameDecodeParams> frame_decode_params; 177 std::unique_ptr<internal::FrameDecodeParams> frame_decode_params;
148 frame_decode_params.reset( 178 frame_decode_params.reset(
149 new internal::FrameDecodeParams(callback_, input_image._timeStamp)); 179 new internal::FrameDecodeParams(callback_, input_image._timeStamp));
150 OSStatus status = VTDecompressionSessionDecodeFrame( 180 OSStatus status = VTDecompressionSessionDecodeFrame(
151 decompression_session_, sample_buffer, decode_flags, 181 decompression_session_, sample_buffer, decode_flags,
152 frame_decode_params.release(), nullptr); 182 frame_decode_params.release(), nullptr);
183 #if defined(WEBRTC_IOS)
184 // Re-initialize the decoder if we have an invalid session while the app is
185 // active and retry the decode request.
186 if (status == kVTInvalidSessionErr &&
187 ResetDecompressionSession() == WEBRTC_VIDEO_CODEC_OK) {
188 frame_decode_params.reset(
189 new internal::FrameDecodeParams(callback_, input_image._timeStamp));
190 status = VTDecompressionSessionDecodeFrame(
191 decompression_session_, sample_buffer, decode_flags,
192 frame_decode_params.release(), nullptr);
193 }
194 #endif
153 CFRelease(sample_buffer); 195 CFRelease(sample_buffer);
154 if (status != noErr) { 196 if (status != noErr) {
155 LOG(LS_ERROR) << "Failed to decode frame with code: " << status; 197 LOG(LS_ERROR) << "Failed to decode frame with code: " << status;
156 return WEBRTC_VIDEO_CODEC_ERROR; 198 return WEBRTC_VIDEO_CODEC_ERROR;
157 } 199 }
158 return WEBRTC_VIDEO_CODEC_OK; 200 return WEBRTC_VIDEO_CODEC_OK;
159 } 201 }
160 202
161 int H264VideoToolboxDecoder::RegisterDecodeCompleteCallback( 203 int H264VideoToolboxDecoder::RegisterDecodeCompleteCallback(
162 DecodedImageCallback* callback) { 204 DecodedImageCallback* callback) {
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 RTC_DCHECK(decompression_session_); 279 RTC_DCHECK(decompression_session_);
238 #if defined(WEBRTC_IOS) 280 #if defined(WEBRTC_IOS)
239 VTSessionSetProperty(decompression_session_, 281 VTSessionSetProperty(decompression_session_,
240 kVTDecompressionPropertyKey_RealTime, kCFBooleanTrue); 282 kVTDecompressionPropertyKey_RealTime, kCFBooleanTrue);
241 #endif 283 #endif
242 } 284 }
243 285
244 void H264VideoToolboxDecoder::DestroyDecompressionSession() { 286 void H264VideoToolboxDecoder::DestroyDecompressionSession() {
245 if (decompression_session_) { 287 if (decompression_session_) {
246 VTDecompressionSessionInvalidate(decompression_session_); 288 VTDecompressionSessionInvalidate(decompression_session_);
289 CFRelease(decompression_session_);
247 decompression_session_ = nullptr; 290 decompression_session_ = nullptr;
248 } 291 }
249 } 292 }
250 293
251 void H264VideoToolboxDecoder::SetVideoFormat( 294 void H264VideoToolboxDecoder::SetVideoFormat(
252 CMVideoFormatDescriptionRef video_format) { 295 CMVideoFormatDescriptionRef video_format) {
253 if (video_format_ == video_format) { 296 if (video_format_ == video_format) {
254 return; 297 return;
255 } 298 }
256 if (video_format_) { 299 if (video_format_) {
257 CFRelease(video_format_); 300 CFRelease(video_format_);
258 } 301 }
259 video_format_ = video_format; 302 video_format_ = video_format;
260 if (video_format_) { 303 if (video_format_) {
261 CFRetain(video_format_); 304 CFRetain(video_format_);
262 } 305 }
263 } 306 }
264 307
265 const char* H264VideoToolboxDecoder::ImplementationName() const { 308 const char* H264VideoToolboxDecoder::ImplementationName() const {
266 return "VideoToolbox"; 309 return "VideoToolbox";
267 } 310 }
268 311
269 } // namespace webrtc 312 } // namespace webrtc
270 313
271 #endif // defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED) 314 #endif // defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698