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

Side by Side Diff: webrtc/api/java/jni/androidmediadecoder_jni.cc

Issue 1732533002: Add an option to soft reset HW decoder. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc@master
Patch Set: Address 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 2015 The WebRTC project authors. All Rights Reserved. 2 * Copyright 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
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 // rtc::MessageHandler implementation. 92 // rtc::MessageHandler implementation.
93 void OnMessage(rtc::Message* msg) override; 93 void OnMessage(rtc::Message* msg) override;
94 94
95 const char* ImplementationName() const override; 95 const char* ImplementationName() const override;
96 96
97 private: 97 private:
98 // CHECK-fail if not running on |codec_thread_|. 98 // CHECK-fail if not running on |codec_thread_|.
99 void CheckOnCodecThread(); 99 void CheckOnCodecThread();
100 100
101 int32_t InitDecodeOnCodecThread(); 101 int32_t InitDecodeOnCodecThread();
102 int32_t ResetDecodeOnCodecThread();
102 int32_t ReleaseOnCodecThread(); 103 int32_t ReleaseOnCodecThread();
103 int32_t DecodeOnCodecThread(const EncodedImage& inputImage); 104 int32_t DecodeOnCodecThread(const EncodedImage& inputImage);
104 // Deliver any outputs pending in the MediaCodec to our |callback_| and return 105 // Deliver any outputs pending in the MediaCodec to our |callback_| and return
105 // true on success. 106 // true on success.
106 bool DeliverPendingOutputs(JNIEnv* jni, int dequeue_timeout_us); 107 bool DeliverPendingOutputs(JNIEnv* jni, int dequeue_timeout_us);
107 int32_t ProcessHWErrorOnCodecThread(); 108 int32_t ProcessHWErrorOnCodecThread();
108 void EnableFrameLogOnWarning(); 109 void EnableFrameLogOnWarning();
110 void ResetVariables();
109 111
110 // Type of video codec. 112 // Type of video codec.
111 VideoCodecType codecType_; 113 VideoCodecType codecType_;
112 114
113 // Render EGL context - owned by factory, should not be allocated/destroyed 115 // Render EGL context - owned by factory, should not be allocated/destroyed
114 // by VideoDecoder. 116 // by VideoDecoder.
115 jobject render_egl_context_; 117 jobject render_egl_context_;
116 118
117 bool key_frame_required_; 119 bool key_frame_required_;
118 bool inited_; 120 bool inited_;
(...skipping 13 matching lines...) Expand all
132 int current_decoding_time_ms_; // Overall decoding time in the current second 134 int current_decoding_time_ms_; // Overall decoding time in the current second
133 int current_delay_time_ms_; // Overall delay time in the current second. 135 int current_delay_time_ms_; // Overall delay time in the current second.
134 uint32_t max_pending_frames_; // Maximum number of pending input frames. 136 uint32_t max_pending_frames_; // Maximum number of pending input frames.
135 137
136 // State that is constant for the lifetime of this object once the ctor 138 // State that is constant for the lifetime of this object once the ctor
137 // returns. 139 // returns.
138 scoped_ptr<Thread> codec_thread_; // Thread on which to operate MediaCodec. 140 scoped_ptr<Thread> codec_thread_; // Thread on which to operate MediaCodec.
139 ScopedGlobalRef<jclass> j_media_codec_video_decoder_class_; 141 ScopedGlobalRef<jclass> j_media_codec_video_decoder_class_;
140 ScopedGlobalRef<jobject> j_media_codec_video_decoder_; 142 ScopedGlobalRef<jobject> j_media_codec_video_decoder_;
141 jmethodID j_init_decode_method_; 143 jmethodID j_init_decode_method_;
144 jmethodID j_reset_method_;
142 jmethodID j_release_method_; 145 jmethodID j_release_method_;
143 jmethodID j_dequeue_input_buffer_method_; 146 jmethodID j_dequeue_input_buffer_method_;
144 jmethodID j_queue_input_buffer_method_; 147 jmethodID j_queue_input_buffer_method_;
145 jmethodID j_dequeue_byte_buffer_method_; 148 jmethodID j_dequeue_byte_buffer_method_;
146 jmethodID j_dequeue_texture_buffer_method_; 149 jmethodID j_dequeue_texture_buffer_method_;
147 jmethodID j_return_decoded_byte_buffer_method_; 150 jmethodID j_return_decoded_byte_buffer_method_;
148 // MediaCodecVideoDecoder fields. 151 // MediaCodecVideoDecoder fields.
149 jfieldID j_input_buffers_field_; 152 jfieldID j_input_buffers_field_;
150 jfieldID j_output_buffers_field_; 153 jfieldID j_output_buffers_field_;
151 jfieldID j_color_format_field_; 154 jfieldID j_color_format_field_;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 "<init>", 196 "<init>",
194 "()V"))) { 197 "()V"))) {
195 ScopedLocalRefFrame local_ref_frame(jni); 198 ScopedLocalRefFrame local_ref_frame(jni);
196 codec_thread_->SetName("MediaCodecVideoDecoder", NULL); 199 codec_thread_->SetName("MediaCodecVideoDecoder", NULL);
197 RTC_CHECK(codec_thread_->Start()) << "Failed to start MediaCodecVideoDecoder"; 200 RTC_CHECK(codec_thread_->Start()) << "Failed to start MediaCodecVideoDecoder";
198 201
199 j_init_decode_method_ = GetMethodID( 202 j_init_decode_method_ = GetMethodID(
200 jni, *j_media_codec_video_decoder_class_, "initDecode", 203 jni, *j_media_codec_video_decoder_class_, "initDecode",
201 "(Lorg/webrtc/MediaCodecVideoDecoder$VideoCodecType;" 204 "(Lorg/webrtc/MediaCodecVideoDecoder$VideoCodecType;"
202 "IILorg/webrtc/SurfaceTextureHelper;)Z"); 205 "IILorg/webrtc/SurfaceTextureHelper;)Z");
206 j_reset_method_ =
207 GetMethodID(jni, *j_media_codec_video_decoder_class_, "reset", "(II)V");
203 j_release_method_ = 208 j_release_method_ =
204 GetMethodID(jni, *j_media_codec_video_decoder_class_, "release", "()V"); 209 GetMethodID(jni, *j_media_codec_video_decoder_class_, "release", "()V");
205 j_dequeue_input_buffer_method_ = GetMethodID( 210 j_dequeue_input_buffer_method_ = GetMethodID(
206 jni, *j_media_codec_video_decoder_class_, "dequeueInputBuffer", "()I"); 211 jni, *j_media_codec_video_decoder_class_, "dequeueInputBuffer", "()I");
207 j_queue_input_buffer_method_ = GetMethodID( 212 j_queue_input_buffer_method_ = GetMethodID(
208 jni, *j_media_codec_video_decoder_class_, "queueInputBuffer", "(IIJJJ)Z"); 213 jni, *j_media_codec_video_decoder_class_, "queueInputBuffer", "(IIJJJ)Z");
209 j_dequeue_byte_buffer_method_ = GetMethodID( 214 j_dequeue_byte_buffer_method_ = GetMethodID(
210 jni, *j_media_codec_video_decoder_class_, "dequeueOutputBuffer", 215 jni, *j_media_codec_video_decoder_class_, "dequeueOutputBuffer",
211 "(I)Lorg/webrtc/MediaCodecVideoDecoder$DecodedOutputBuffer;"); 216 "(I)Lorg/webrtc/MediaCodecVideoDecoder$DecodedOutputBuffer;");
212 j_dequeue_texture_buffer_method_ = GetMethodID( 217 j_dequeue_texture_buffer_method_ = GetMethodID(
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 codec_ = *inst; 304 codec_ = *inst;
300 } 305 }
301 // If maxFramerate is not set then assume 30 fps. 306 // If maxFramerate is not set then assume 30 fps.
302 codec_.maxFramerate = (codec_.maxFramerate >= 1) ? codec_.maxFramerate : 30; 307 codec_.maxFramerate = (codec_.maxFramerate >= 1) ? codec_.maxFramerate : 30;
303 308
304 // Call Java init. 309 // Call Java init.
305 return codec_thread_->Invoke<int32_t>( 310 return codec_thread_->Invoke<int32_t>(
306 Bind(&MediaCodecVideoDecoder::InitDecodeOnCodecThread, this)); 311 Bind(&MediaCodecVideoDecoder::InitDecodeOnCodecThread, this));
307 } 312 }
308 313
314 void MediaCodecVideoDecoder::ResetVariables() {
315 key_frame_required_ = true;
pbos-webrtc 2016/03/04 10:23:13 CheckOnCodecThread?
AlexG 2016/03/04 18:44:12 Done.
316 frames_received_ = 0;
317 frames_decoded_ = 0;
318 frames_decoded_logged_ = kMaxDecodedLogFrames;
319 start_time_ms_ = GetCurrentTimeMs();
320 current_frames_ = 0;
321 current_bytes_ = 0;
322 current_decoding_time_ms_ = 0;
323 current_delay_time_ms_ = 0;
324 }
325
309 int32_t MediaCodecVideoDecoder::InitDecodeOnCodecThread() { 326 int32_t MediaCodecVideoDecoder::InitDecodeOnCodecThread() {
310 CheckOnCodecThread(); 327 CheckOnCodecThread();
311 JNIEnv* jni = AttachCurrentThreadIfNeeded(); 328 JNIEnv* jni = AttachCurrentThreadIfNeeded();
312 ScopedLocalRefFrame local_ref_frame(jni); 329 ScopedLocalRefFrame local_ref_frame(jni);
313 ALOGD << "InitDecodeOnCodecThread Type: " << (int)codecType_ << ". " 330 ALOGD << "InitDecodeOnCodecThread Type: " << (int)codecType_ << ". "
314 << codec_.width << " x " << codec_.height << ". Fps: " << 331 << codec_.width << " x " << codec_.height << ". Fps: " <<
315 (int)codec_.maxFramerate; 332 (int)codec_.maxFramerate;
316 333
317 // Release previous codec first if it was allocated before. 334 // Release previous codec first if it was allocated before.
318 int ret_val = ReleaseOnCodecThread(); 335 int ret_val = ReleaseOnCodecThread();
319 if (ret_val < 0) { 336 if (ret_val < 0) {
320 ALOGE << "Release failure: " << ret_val << " - fallback to SW codec"; 337 ALOGE << "Release failure: " << ret_val << " - fallback to SW codec";
321 sw_fallback_required_ = true; 338 sw_fallback_required_ = true;
322 return WEBRTC_VIDEO_CODEC_ERROR; 339 return WEBRTC_VIDEO_CODEC_ERROR;
323 } 340 }
324 341
325 // Always start with a complete key frame. 342 ResetVariables();
326 key_frame_required_ = true;
327 frames_received_ = 0;
328 frames_decoded_ = 0;
329 frames_decoded_logged_ = kMaxDecodedLogFrames;
330 343
331 jobject java_surface_texture_helper_ = nullptr; 344 jobject java_surface_texture_helper_ = nullptr;
332 if (use_surface_) { 345 if (use_surface_) {
333 java_surface_texture_helper_ = jni->CallStaticObjectMethod( 346 java_surface_texture_helper_ = jni->CallStaticObjectMethod(
334 FindClass(jni, "org/webrtc/SurfaceTextureHelper"), 347 FindClass(jni, "org/webrtc/SurfaceTextureHelper"),
335 GetStaticMethodID(jni, 348 GetStaticMethodID(jni,
336 FindClass(jni, "org/webrtc/SurfaceTextureHelper"), 349 FindClass(jni, "org/webrtc/SurfaceTextureHelper"),
337 "create", 350 "create",
338 "(Lorg/webrtc/EglBase$Context;)" 351 "(Lorg/webrtc/EglBase$Context;)"
339 "Lorg/webrtc/SurfaceTextureHelper;"), 352 "Lorg/webrtc/SurfaceTextureHelper;"),
340 render_egl_context_); 353 render_egl_context_);
341 RTC_CHECK(java_surface_texture_helper_ != nullptr); 354 RTC_CHECK(java_surface_texture_helper_ != nullptr);
342 surface_texture_helper_ = new rtc::RefCountedObject<SurfaceTextureHelper>( 355 surface_texture_helper_ = new rtc::RefCountedObject<SurfaceTextureHelper>(
343 jni, java_surface_texture_helper_); 356 jni, java_surface_texture_helper_);
344 } 357 }
345 358
346 jobject j_video_codec_enum = JavaEnumFromIndexAndClassName( 359 jobject j_video_codec_enum = JavaEnumFromIndexAndClassName(
347 jni, "MediaCodecVideoDecoder$VideoCodecType", codecType_); 360 jni, "MediaCodecVideoDecoder$VideoCodecType", codecType_);
348 bool success = jni->CallBooleanMethod( 361 bool success = jni->CallBooleanMethod(
349 *j_media_codec_video_decoder_, 362 *j_media_codec_video_decoder_,
350 j_init_decode_method_, 363 j_init_decode_method_,
351 j_video_codec_enum, 364 j_video_codec_enum,
352 codec_.width, 365 codec_.width,
353 codec_.height, 366 codec_.height,
354 java_surface_texture_helper_); 367 java_surface_texture_helper_);
368
355 if (CheckException(jni) || !success) { 369 if (CheckException(jni) || !success) {
356 ALOGE << "Codec initialization error - fallback to SW codec."; 370 ALOGE << "Codec initialization error - fallback to SW codec.";
357 sw_fallback_required_ = true; 371 sw_fallback_required_ = true;
358 return WEBRTC_VIDEO_CODEC_ERROR; 372 return WEBRTC_VIDEO_CODEC_ERROR;
359 } 373 }
360 inited_ = true; 374 inited_ = true;
361 375
362 switch (codecType_) { 376 switch (codecType_) {
363 case kVideoCodecVP8: 377 case kVideoCodecVP8:
364 max_pending_frames_ = kMaxPendingFramesVp8; 378 max_pending_frames_ = kMaxPendingFramesVp8;
365 break; 379 break;
366 case kVideoCodecVP9: 380 case kVideoCodecVP9:
367 max_pending_frames_ = kMaxPendingFramesVp9; 381 max_pending_frames_ = kMaxPendingFramesVp9;
368 break; 382 break;
369 case kVideoCodecH264: 383 case kVideoCodecH264:
370 max_pending_frames_ = kMaxPendingFramesH264; 384 max_pending_frames_ = kMaxPendingFramesH264;
371 break; 385 break;
372 default: 386 default:
373 max_pending_frames_ = 0; 387 max_pending_frames_ = 0;
374 } 388 }
375 start_time_ms_ = GetCurrentTimeMs(); 389 ALOGD << "Maximum amount of pending frames: " << max_pending_frames_;
376 current_frames_ = 0;
377 current_bytes_ = 0;
378 current_decoding_time_ms_ = 0;
379 current_delay_time_ms_ = 0;
380 390
381 jobjectArray input_buffers = (jobjectArray)GetObjectField( 391 jobjectArray input_buffers = (jobjectArray)GetObjectField(
382 jni, *j_media_codec_video_decoder_, j_input_buffers_field_); 392 jni, *j_media_codec_video_decoder_, j_input_buffers_field_);
383 size_t num_input_buffers = jni->GetArrayLength(input_buffers); 393 size_t num_input_buffers = jni->GetArrayLength(input_buffers);
384 ALOGD << "Maximum amount of pending frames: " << max_pending_frames_;
385 input_buffers_.resize(num_input_buffers); 394 input_buffers_.resize(num_input_buffers);
386 for (size_t i = 0; i < num_input_buffers; ++i) { 395 for (size_t i = 0; i < num_input_buffers; ++i) {
387 input_buffers_[i] = 396 input_buffers_[i] =
388 jni->NewGlobalRef(jni->GetObjectArrayElement(input_buffers, i)); 397 jni->NewGlobalRef(jni->GetObjectArrayElement(input_buffers, i));
389 if (CheckException(jni)) { 398 if (CheckException(jni)) {
390 ALOGE << "NewGlobalRef error - fallback to SW codec."; 399 ALOGE << "NewGlobalRef error - fallback to SW codec.";
391 sw_fallback_required_ = true; 400 sw_fallback_required_ = true;
392 return WEBRTC_VIDEO_CODEC_ERROR; 401 return WEBRTC_VIDEO_CODEC_ERROR;
393 } 402 }
394 } 403 }
395 404
396 codec_thread_->PostDelayed(kMediaCodecPollMs, this); 405 codec_thread_->PostDelayed(kMediaCodecPollMs, this);
397 406
398 return WEBRTC_VIDEO_CODEC_OK; 407 return WEBRTC_VIDEO_CODEC_OK;
399 } 408 }
400 409
410 int32_t MediaCodecVideoDecoder::ResetDecodeOnCodecThread() {
411 CheckOnCodecThread();
412 JNIEnv* jni = AttachCurrentThreadIfNeeded();
413 ScopedLocalRefFrame local_ref_frame(jni);
414 ALOGD << "ResetDecodeOnCodecThread Type: " << (int)codecType_ << ". "
415 << codec_.width << " x " << codec_.height;
416 ALOGD << " Frames received: " << frames_received_ <<
417 ". Frames decoded: " << frames_decoded_;
418
419 inited_ = false;
420 rtc::MessageQueueManager::Clear(this);
421 ResetVariables();
422
423 jni->CallVoidMethod(
424 *j_media_codec_video_decoder_,
425 j_reset_method_,
426 codec_.width,
427 codec_.height);
428
429 if (CheckException(jni)) {
430 ALOGE << "Soft reset error - fallback to SW codec.";
431 sw_fallback_required_ = true;
432 return WEBRTC_VIDEO_CODEC_ERROR;
433 }
434 inited_ = true;
435
436 codec_thread_->PostDelayed(kMediaCodecPollMs, this);
437
438 return WEBRTC_VIDEO_CODEC_OK;
439 }
440
401 int32_t MediaCodecVideoDecoder::Release() { 441 int32_t MediaCodecVideoDecoder::Release() {
402 ALOGD << "DecoderRelease request"; 442 ALOGD << "DecoderRelease request";
403 return codec_thread_->Invoke<int32_t>( 443 return codec_thread_->Invoke<int32_t>(
404 Bind(&MediaCodecVideoDecoder::ReleaseOnCodecThread, this)); 444 Bind(&MediaCodecVideoDecoder::ReleaseOnCodecThread, this));
405 } 445 }
406 446
407 int32_t MediaCodecVideoDecoder::ReleaseOnCodecThread() { 447 int32_t MediaCodecVideoDecoder::ReleaseOnCodecThread() {
408 if (!inited_) { 448 if (!inited_) {
409 return WEBRTC_VIDEO_CODEC_OK; 449 return WEBRTC_VIDEO_CODEC_OK;
410 } 450 }
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
486 } 526 }
487 if (!inited_) { 527 if (!inited_) {
488 ALOGE << "Decode() - decoder is not initialized"; 528 ALOGE << "Decode() - decoder is not initialized";
489 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; 529 return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
490 } 530 }
491 531
492 // Check if encoded frame dimension has changed. 532 // Check if encoded frame dimension has changed.
493 if ((inputImage._encodedWidth * inputImage._encodedHeight > 0) && 533 if ((inputImage._encodedWidth * inputImage._encodedHeight > 0) &&
494 (inputImage._encodedWidth != codec_.width || 534 (inputImage._encodedWidth != codec_.width ||
495 inputImage._encodedHeight != codec_.height)) { 535 inputImage._encodedHeight != codec_.height)) {
536 ALOGW << "Input resolution changed from " <<
537 codec_.width << " x " << codec_.height << " to " <<
538 inputImage._encodedWidth << " x " << inputImage._encodedHeight;
496 codec_.width = inputImage._encodedWidth; 539 codec_.width = inputImage._encodedWidth;
497 codec_.height = inputImage._encodedHeight; 540 codec_.height = inputImage._encodedHeight;
498 int32_t ret = InitDecode(&codec_, 1); 541 int32_t ret;
542 if (use_surface_ && codecType_ == kVideoCodecVP8) {
543 // Soft codec reset - only for VP8 and surface decoding.
544 // TODO(glaznev): try to use similar approach for H.264.
pbos-webrtc 2016/03/04 10:23:13 (and buffer decoding?)
AlexG 2016/03/04 18:44:12 Done.
545 ret = codec_thread_->Invoke<int32_t>(Bind(
546 &MediaCodecVideoDecoder::ResetDecodeOnCodecThread, this));
547 } else {
548 // Hard codec reset.
549 ret = InitDecode(&codec_, 1);
550 }
499 if (ret < 0) { 551 if (ret < 0) {
500 ALOGE << "InitDecode failure: " << ret << " - fallback to SW codec"; 552 ALOGE << "InitDecode failure: " << ret << " - fallback to SW codec";
501 sw_fallback_required_ = true; 553 sw_fallback_required_ = true;
502 return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE; 554 return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
503 } 555 }
504 } 556 }
505 557
506 // Always start with a complete key frame. 558 // Always start with a complete key frame.
507 if (key_frame_required_) { 559 if (key_frame_required_) {
508 if (inputImage._frameType != webrtc::kVideoFrameKey) { 560 if (inputImage._frameType != webrtc::kVideoFrameKey) {
(...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after
928 ALOGD << "Destroy video decoder."; 980 ALOGD << "Destroy video decoder.";
929 delete decoder; 981 delete decoder;
930 } 982 }
931 983
932 const char* MediaCodecVideoDecoder::ImplementationName() const { 984 const char* MediaCodecVideoDecoder::ImplementationName() const {
933 return "MediaCodec"; 985 return "MediaCodec";
934 } 986 }
935 987
936 } // namespace webrtc_jni 988 } // namespace webrtc_jni
937 989
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698