OLD | NEW |
---|---|
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 Loading... | |
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 SoftResetDecodeOnCodecThread(); | |
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(); |
109 | 110 |
110 // Type of video codec. | 111 // Type of video codec. |
111 VideoCodecType codecType_; | 112 VideoCodecType codecType_; |
(...skipping 20 matching lines...) Expand all Loading... | |
132 int current_decoding_time_ms_; // Overall decoding time in the current second | 133 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. | 134 int current_delay_time_ms_; // Overall delay time in the current second. |
134 uint32_t max_pending_frames_; // Maximum number of pending input frames. | 135 uint32_t max_pending_frames_; // Maximum number of pending input frames. |
135 | 136 |
136 // State that is constant for the lifetime of this object once the ctor | 137 // State that is constant for the lifetime of this object once the ctor |
137 // returns. | 138 // returns. |
138 scoped_ptr<Thread> codec_thread_; // Thread on which to operate MediaCodec. | 139 scoped_ptr<Thread> codec_thread_; // Thread on which to operate MediaCodec. |
139 ScopedGlobalRef<jclass> j_media_codec_video_decoder_class_; | 140 ScopedGlobalRef<jclass> j_media_codec_video_decoder_class_; |
140 ScopedGlobalRef<jobject> j_media_codec_video_decoder_; | 141 ScopedGlobalRef<jobject> j_media_codec_video_decoder_; |
141 jmethodID j_init_decode_method_; | 142 jmethodID j_init_decode_method_; |
143 jmethodID j_soft_reset_decode_method_; | |
142 jmethodID j_release_method_; | 144 jmethodID j_release_method_; |
143 jmethodID j_dequeue_input_buffer_method_; | 145 jmethodID j_dequeue_input_buffer_method_; |
144 jmethodID j_queue_input_buffer_method_; | 146 jmethodID j_queue_input_buffer_method_; |
145 jmethodID j_dequeue_byte_buffer_method_; | 147 jmethodID j_dequeue_byte_buffer_method_; |
146 jmethodID j_dequeue_texture_buffer_method_; | 148 jmethodID j_dequeue_texture_buffer_method_; |
147 jmethodID j_return_decoded_byte_buffer_method_; | 149 jmethodID j_return_decoded_byte_buffer_method_; |
148 // MediaCodecVideoDecoder fields. | 150 // MediaCodecVideoDecoder fields. |
149 jfieldID j_input_buffers_field_; | 151 jfieldID j_input_buffers_field_; |
150 jfieldID j_output_buffers_field_; | 152 jfieldID j_output_buffers_field_; |
151 jfieldID j_color_format_field_; | 153 jfieldID j_color_format_field_; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
193 "<init>", | 195 "<init>", |
194 "()V"))) { | 196 "()V"))) { |
195 ScopedLocalRefFrame local_ref_frame(jni); | 197 ScopedLocalRefFrame local_ref_frame(jni); |
196 codec_thread_->SetName("MediaCodecVideoDecoder", NULL); | 198 codec_thread_->SetName("MediaCodecVideoDecoder", NULL); |
197 RTC_CHECK(codec_thread_->Start()) << "Failed to start MediaCodecVideoDecoder"; | 199 RTC_CHECK(codec_thread_->Start()) << "Failed to start MediaCodecVideoDecoder"; |
198 | 200 |
199 j_init_decode_method_ = GetMethodID( | 201 j_init_decode_method_ = GetMethodID( |
200 jni, *j_media_codec_video_decoder_class_, "initDecode", | 202 jni, *j_media_codec_video_decoder_class_, "initDecode", |
201 "(Lorg/webrtc/MediaCodecVideoDecoder$VideoCodecType;" | 203 "(Lorg/webrtc/MediaCodecVideoDecoder$VideoCodecType;" |
202 "IILorg/webrtc/SurfaceTextureHelper;)Z"); | 204 "IILorg/webrtc/SurfaceTextureHelper;)Z"); |
205 j_soft_reset_decode_method_ = GetMethodID( | |
206 jni, *j_media_codec_video_decoder_class_, "softResetDecode", "(II)V"); | |
203 j_release_method_ = | 207 j_release_method_ = |
204 GetMethodID(jni, *j_media_codec_video_decoder_class_, "release", "()V"); | 208 GetMethodID(jni, *j_media_codec_video_decoder_class_, "release", "()V"); |
205 j_dequeue_input_buffer_method_ = GetMethodID( | 209 j_dequeue_input_buffer_method_ = GetMethodID( |
206 jni, *j_media_codec_video_decoder_class_, "dequeueInputBuffer", "()I"); | 210 jni, *j_media_codec_video_decoder_class_, "dequeueInputBuffer", "()I"); |
207 j_queue_input_buffer_method_ = GetMethodID( | 211 j_queue_input_buffer_method_ = GetMethodID( |
208 jni, *j_media_codec_video_decoder_class_, "queueInputBuffer", "(IIJJJ)Z"); | 212 jni, *j_media_codec_video_decoder_class_, "queueInputBuffer", "(IIJJJ)Z"); |
209 j_dequeue_byte_buffer_method_ = GetMethodID( | 213 j_dequeue_byte_buffer_method_ = GetMethodID( |
210 jni, *j_media_codec_video_decoder_class_, "dequeueOutputBuffer", | 214 jni, *j_media_codec_video_decoder_class_, "dequeueOutputBuffer", |
211 "(I)Lorg/webrtc/MediaCodecVideoDecoder$DecodedOutputBuffer;"); | 215 "(I)Lorg/webrtc/MediaCodecVideoDecoder$DecodedOutputBuffer;"); |
212 j_dequeue_texture_buffer_method_ = GetMethodID( | 216 j_dequeue_texture_buffer_method_ = GetMethodID( |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
365 break; | 369 break; |
366 case kVideoCodecVP9: | 370 case kVideoCodecVP9: |
367 max_pending_frames_ = kMaxPendingFramesVp9; | 371 max_pending_frames_ = kMaxPendingFramesVp9; |
368 break; | 372 break; |
369 case kVideoCodecH264: | 373 case kVideoCodecH264: |
370 max_pending_frames_ = kMaxPendingFramesH264; | 374 max_pending_frames_ = kMaxPendingFramesH264; |
371 break; | 375 break; |
372 default: | 376 default: |
373 max_pending_frames_ = 0; | 377 max_pending_frames_ = 0; |
374 } | 378 } |
379 ALOGD << "Maximum amount of pending frames: " << max_pending_frames_; | |
380 | |
375 start_time_ms_ = GetCurrentTimeMs(); | 381 start_time_ms_ = GetCurrentTimeMs(); |
376 current_frames_ = 0; | 382 current_frames_ = 0; |
377 current_bytes_ = 0; | 383 current_bytes_ = 0; |
378 current_decoding_time_ms_ = 0; | 384 current_decoding_time_ms_ = 0; |
379 current_delay_time_ms_ = 0; | 385 current_delay_time_ms_ = 0; |
380 | 386 |
381 jobjectArray input_buffers = (jobjectArray)GetObjectField( | 387 jobjectArray input_buffers = (jobjectArray)GetObjectField( |
382 jni, *j_media_codec_video_decoder_, j_input_buffers_field_); | 388 jni, *j_media_codec_video_decoder_, j_input_buffers_field_); |
383 size_t num_input_buffers = jni->GetArrayLength(input_buffers); | 389 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); | 390 input_buffers_.resize(num_input_buffers); |
386 for (size_t i = 0; i < num_input_buffers; ++i) { | 391 for (size_t i = 0; i < num_input_buffers; ++i) { |
387 input_buffers_[i] = | 392 input_buffers_[i] = |
388 jni->NewGlobalRef(jni->GetObjectArrayElement(input_buffers, i)); | 393 jni->NewGlobalRef(jni->GetObjectArrayElement(input_buffers, i)); |
389 if (CheckException(jni)) { | 394 if (CheckException(jni)) { |
390 ALOGE << "NewGlobalRef error - fallback to SW codec."; | 395 ALOGE << "NewGlobalRef error - fallback to SW codec."; |
391 sw_fallback_required_ = true; | 396 sw_fallback_required_ = true; |
392 return WEBRTC_VIDEO_CODEC_ERROR; | 397 return WEBRTC_VIDEO_CODEC_ERROR; |
393 } | 398 } |
394 } | 399 } |
395 | 400 |
396 codec_thread_->PostDelayed(kMediaCodecPollMs, this); | 401 codec_thread_->PostDelayed(kMediaCodecPollMs, this); |
397 | 402 |
398 return WEBRTC_VIDEO_CODEC_OK; | 403 return WEBRTC_VIDEO_CODEC_OK; |
399 } | 404 } |
400 | 405 |
perkj_webrtc
2016/03/02 12:33:22
ResetDecodeOnCodecThread?
AlexG
2016/03/04 01:20:20
Done.
| |
406 int32_t MediaCodecVideoDecoder::SoftResetDecodeOnCodecThread() { | |
407 CheckOnCodecThread(); | |
408 JNIEnv* jni = AttachCurrentThreadIfNeeded(); | |
409 ScopedLocalRefFrame local_ref_frame(jni); | |
410 ALOGD << "SoftResetDecodeOnCodecThread Type: " << (int)codecType_ << ". " | |
411 << codec_.width << " x " << codec_.height; | |
412 ALOGD << " Frames received: " << frames_received_ << | |
413 ". Frames decoded: " << frames_decoded_; | |
414 | |
415 inited_ = false; | |
416 rtc::MessageQueueManager::Clear(this); | |
417 | |
418 // Always start with a complete key frame. | |
419 key_frame_required_ = true; | |
perkj_webrtc
2016/03/02 12:33:22
Move all these to a helper method and call from In
AlexG
2016/03/04 01:20:20
Done.
| |
420 frames_received_ = 0; | |
421 frames_decoded_ = 0; | |
422 frames_decoded_logged_ = kMaxDecodedLogFrames; | |
423 start_time_ms_ = GetCurrentTimeMs(); | |
424 current_frames_ = 0; | |
425 current_bytes_ = 0; | |
426 current_decoding_time_ms_ = 0; | |
427 current_delay_time_ms_ = 0; | |
428 | |
429 jni->CallVoidMethod( | |
430 *j_media_codec_video_decoder_, | |
431 j_soft_reset_decode_method_, | |
432 codec_.width, | |
433 codec_.height); | |
434 | |
435 if (CheckException(jni)) { | |
436 ALOGE << "Soft reset error - fallback to SW codec."; | |
437 sw_fallback_required_ = true; | |
438 return WEBRTC_VIDEO_CODEC_ERROR; | |
439 } | |
440 inited_ = true; | |
441 | |
442 codec_thread_->PostDelayed(kMediaCodecPollMs, this); | |
443 | |
444 return WEBRTC_VIDEO_CODEC_OK; | |
445 } | |
446 | |
401 int32_t MediaCodecVideoDecoder::Release() { | 447 int32_t MediaCodecVideoDecoder::Release() { |
402 ALOGD << "DecoderRelease request"; | 448 ALOGD << "DecoderRelease request"; |
403 return codec_thread_->Invoke<int32_t>( | 449 return codec_thread_->Invoke<int32_t>( |
404 Bind(&MediaCodecVideoDecoder::ReleaseOnCodecThread, this)); | 450 Bind(&MediaCodecVideoDecoder::ReleaseOnCodecThread, this)); |
405 } | 451 } |
406 | 452 |
407 int32_t MediaCodecVideoDecoder::ReleaseOnCodecThread() { | 453 int32_t MediaCodecVideoDecoder::ReleaseOnCodecThread() { |
408 if (!inited_) { | 454 if (!inited_) { |
409 return WEBRTC_VIDEO_CODEC_OK; | 455 return WEBRTC_VIDEO_CODEC_OK; |
410 } | 456 } |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
486 } | 532 } |
487 if (!inited_) { | 533 if (!inited_) { |
488 ALOGE << "Decode() - decoder is not initialized"; | 534 ALOGE << "Decode() - decoder is not initialized"; |
489 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | 535 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; |
490 } | 536 } |
491 | 537 |
492 // Check if encoded frame dimension has changed. | 538 // Check if encoded frame dimension has changed. |
493 if ((inputImage._encodedWidth * inputImage._encodedHeight > 0) && | 539 if ((inputImage._encodedWidth * inputImage._encodedHeight > 0) && |
494 (inputImage._encodedWidth != codec_.width || | 540 (inputImage._encodedWidth != codec_.width || |
495 inputImage._encodedHeight != codec_.height)) { | 541 inputImage._encodedHeight != codec_.height)) { |
542 ALOGW << "Input resolution changed from " << | |
543 codec_.width << " x " << codec_.height << " to " << | |
544 inputImage._encodedWidth << " x " << inputImage._encodedHeight; | |
496 codec_.width = inputImage._encodedWidth; | 545 codec_.width = inputImage._encodedWidth; |
497 codec_.height = inputImage._encodedHeight; | 546 codec_.height = inputImage._encodedHeight; |
498 int32_t ret = InitDecode(&codec_, 1); | 547 int32_t ret; |
548 if (use_surface_ && codecType_ == kVideoCodecVP8) { | |
549 // Soft codec reset - only for VP8 and surface decoding. | |
550 // TODO(glaznev): try to use similar approach for H.264. | |
551 ret = codec_thread_->Invoke<int32_t>(Bind( | |
552 &MediaCodecVideoDecoder::SoftResetDecodeOnCodecThread, this)); | |
553 } else { | |
554 // Hard codec reset. | |
555 ret = InitDecode(&codec_, 1); | |
556 } | |
499 if (ret < 0) { | 557 if (ret < 0) { |
500 ALOGE << "InitDecode failure: " << ret << " - fallback to SW codec"; | 558 ALOGE << "InitDecode failure: " << ret << " - fallback to SW codec"; |
501 sw_fallback_required_ = true; | 559 sw_fallback_required_ = true; |
502 return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE; | 560 return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE; |
503 } | 561 } |
504 } | 562 } |
505 | 563 |
506 // Always start with a complete key frame. | 564 // Always start with a complete key frame. |
507 if (key_frame_required_) { | 565 if (key_frame_required_) { |
508 if (inputImage._frameType != webrtc::kVideoFrameKey) { | 566 if (inputImage._frameType != webrtc::kVideoFrameKey) { |
(...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
928 ALOGD << "Destroy video decoder."; | 986 ALOGD << "Destroy video decoder."; |
929 delete decoder; | 987 delete decoder; |
930 } | 988 } |
931 | 989 |
932 const char* MediaCodecVideoDecoder::ImplementationName() const { | 990 const char* MediaCodecVideoDecoder::ImplementationName() const { |
933 return "MediaCodec"; | 991 return "MediaCodec"; |
934 } | 992 } |
935 | 993 |
936 } // namespace webrtc_jni | 994 } // namespace webrtc_jni |
937 | 995 |
OLD | NEW |