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 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 Loading... |
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 Loading... |
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 Loading... |
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 CheckOnCodecThread(); |
| 316 |
| 317 key_frame_required_ = true; |
| 318 frames_received_ = 0; |
| 319 frames_decoded_ = 0; |
| 320 frames_decoded_logged_ = kMaxDecodedLogFrames; |
| 321 start_time_ms_ = GetCurrentTimeMs(); |
| 322 current_frames_ = 0; |
| 323 current_bytes_ = 0; |
| 324 current_decoding_time_ms_ = 0; |
| 325 current_delay_time_ms_ = 0; |
| 326 } |
| 327 |
309 int32_t MediaCodecVideoDecoder::InitDecodeOnCodecThread() { | 328 int32_t MediaCodecVideoDecoder::InitDecodeOnCodecThread() { |
310 CheckOnCodecThread(); | 329 CheckOnCodecThread(); |
311 JNIEnv* jni = AttachCurrentThreadIfNeeded(); | 330 JNIEnv* jni = AttachCurrentThreadIfNeeded(); |
312 ScopedLocalRefFrame local_ref_frame(jni); | 331 ScopedLocalRefFrame local_ref_frame(jni); |
313 ALOGD << "InitDecodeOnCodecThread Type: " << (int)codecType_ << ". " | 332 ALOGD << "InitDecodeOnCodecThread Type: " << (int)codecType_ << ". " |
314 << codec_.width << " x " << codec_.height << ". Fps: " << | 333 << codec_.width << " x " << codec_.height << ". Fps: " << |
315 (int)codec_.maxFramerate; | 334 (int)codec_.maxFramerate; |
316 | 335 |
317 // Release previous codec first if it was allocated before. | 336 // Release previous codec first if it was allocated before. |
318 int ret_val = ReleaseOnCodecThread(); | 337 int ret_val = ReleaseOnCodecThread(); |
319 if (ret_val < 0) { | 338 if (ret_val < 0) { |
320 ALOGE << "Release failure: " << ret_val << " - fallback to SW codec"; | 339 ALOGE << "Release failure: " << ret_val << " - fallback to SW codec"; |
321 sw_fallback_required_ = true; | 340 sw_fallback_required_ = true; |
322 return WEBRTC_VIDEO_CODEC_ERROR; | 341 return WEBRTC_VIDEO_CODEC_ERROR; |
323 } | 342 } |
324 | 343 |
325 // Always start with a complete key frame. | 344 ResetVariables(); |
326 key_frame_required_ = true; | |
327 frames_received_ = 0; | |
328 frames_decoded_ = 0; | |
329 frames_decoded_logged_ = kMaxDecodedLogFrames; | |
330 | 345 |
331 jobject java_surface_texture_helper_ = nullptr; | 346 jobject java_surface_texture_helper_ = nullptr; |
332 if (use_surface_) { | 347 if (use_surface_) { |
333 java_surface_texture_helper_ = jni->CallStaticObjectMethod( | 348 java_surface_texture_helper_ = jni->CallStaticObjectMethod( |
334 FindClass(jni, "org/webrtc/SurfaceTextureHelper"), | 349 FindClass(jni, "org/webrtc/SurfaceTextureHelper"), |
335 GetStaticMethodID(jni, | 350 GetStaticMethodID(jni, |
336 FindClass(jni, "org/webrtc/SurfaceTextureHelper"), | 351 FindClass(jni, "org/webrtc/SurfaceTextureHelper"), |
337 "create", | 352 "create", |
338 "(Lorg/webrtc/EglBase$Context;)" | 353 "(Lorg/webrtc/EglBase$Context;)" |
339 "Lorg/webrtc/SurfaceTextureHelper;"), | 354 "Lorg/webrtc/SurfaceTextureHelper;"), |
340 render_egl_context_); | 355 render_egl_context_); |
341 RTC_CHECK(java_surface_texture_helper_ != nullptr); | 356 RTC_CHECK(java_surface_texture_helper_ != nullptr); |
342 surface_texture_helper_ = new rtc::RefCountedObject<SurfaceTextureHelper>( | 357 surface_texture_helper_ = new rtc::RefCountedObject<SurfaceTextureHelper>( |
343 jni, java_surface_texture_helper_); | 358 jni, java_surface_texture_helper_); |
344 } | 359 } |
345 | 360 |
346 jobject j_video_codec_enum = JavaEnumFromIndexAndClassName( | 361 jobject j_video_codec_enum = JavaEnumFromIndexAndClassName( |
347 jni, "MediaCodecVideoDecoder$VideoCodecType", codecType_); | 362 jni, "MediaCodecVideoDecoder$VideoCodecType", codecType_); |
348 bool success = jni->CallBooleanMethod( | 363 bool success = jni->CallBooleanMethod( |
349 *j_media_codec_video_decoder_, | 364 *j_media_codec_video_decoder_, |
350 j_init_decode_method_, | 365 j_init_decode_method_, |
351 j_video_codec_enum, | 366 j_video_codec_enum, |
352 codec_.width, | 367 codec_.width, |
353 codec_.height, | 368 codec_.height, |
354 java_surface_texture_helper_); | 369 java_surface_texture_helper_); |
| 370 |
355 if (CheckException(jni) || !success) { | 371 if (CheckException(jni) || !success) { |
356 ALOGE << "Codec initialization error - fallback to SW codec."; | 372 ALOGE << "Codec initialization error - fallback to SW codec."; |
357 sw_fallback_required_ = true; | 373 sw_fallback_required_ = true; |
358 return WEBRTC_VIDEO_CODEC_ERROR; | 374 return WEBRTC_VIDEO_CODEC_ERROR; |
359 } | 375 } |
360 inited_ = true; | 376 inited_ = true; |
361 | 377 |
362 switch (codecType_) { | 378 switch (codecType_) { |
363 case kVideoCodecVP8: | 379 case kVideoCodecVP8: |
364 max_pending_frames_ = kMaxPendingFramesVp8; | 380 max_pending_frames_ = kMaxPendingFramesVp8; |
365 break; | 381 break; |
366 case kVideoCodecVP9: | 382 case kVideoCodecVP9: |
367 max_pending_frames_ = kMaxPendingFramesVp9; | 383 max_pending_frames_ = kMaxPendingFramesVp9; |
368 break; | 384 break; |
369 case kVideoCodecH264: | 385 case kVideoCodecH264: |
370 max_pending_frames_ = kMaxPendingFramesH264; | 386 max_pending_frames_ = kMaxPendingFramesH264; |
371 break; | 387 break; |
372 default: | 388 default: |
373 max_pending_frames_ = 0; | 389 max_pending_frames_ = 0; |
374 } | 390 } |
375 start_time_ms_ = GetCurrentTimeMs(); | 391 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 | 392 |
381 jobjectArray input_buffers = (jobjectArray)GetObjectField( | 393 jobjectArray input_buffers = (jobjectArray)GetObjectField( |
382 jni, *j_media_codec_video_decoder_, j_input_buffers_field_); | 394 jni, *j_media_codec_video_decoder_, j_input_buffers_field_); |
383 size_t num_input_buffers = jni->GetArrayLength(input_buffers); | 395 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); | 396 input_buffers_.resize(num_input_buffers); |
386 for (size_t i = 0; i < num_input_buffers; ++i) { | 397 for (size_t i = 0; i < num_input_buffers; ++i) { |
387 input_buffers_[i] = | 398 input_buffers_[i] = |
388 jni->NewGlobalRef(jni->GetObjectArrayElement(input_buffers, i)); | 399 jni->NewGlobalRef(jni->GetObjectArrayElement(input_buffers, i)); |
389 if (CheckException(jni)) { | 400 if (CheckException(jni)) { |
390 ALOGE << "NewGlobalRef error - fallback to SW codec."; | 401 ALOGE << "NewGlobalRef error - fallback to SW codec."; |
391 sw_fallback_required_ = true; | 402 sw_fallback_required_ = true; |
392 return WEBRTC_VIDEO_CODEC_ERROR; | 403 return WEBRTC_VIDEO_CODEC_ERROR; |
393 } | 404 } |
394 } | 405 } |
395 | 406 |
396 codec_thread_->PostDelayed(kMediaCodecPollMs, this); | 407 codec_thread_->PostDelayed(kMediaCodecPollMs, this); |
397 | 408 |
398 return WEBRTC_VIDEO_CODEC_OK; | 409 return WEBRTC_VIDEO_CODEC_OK; |
399 } | 410 } |
400 | 411 |
| 412 int32_t MediaCodecVideoDecoder::ResetDecodeOnCodecThread() { |
| 413 CheckOnCodecThread(); |
| 414 JNIEnv* jni = AttachCurrentThreadIfNeeded(); |
| 415 ScopedLocalRefFrame local_ref_frame(jni); |
| 416 ALOGD << "ResetDecodeOnCodecThread Type: " << (int)codecType_ << ". " |
| 417 << codec_.width << " x " << codec_.height; |
| 418 ALOGD << " Frames received: " << frames_received_ << |
| 419 ". Frames decoded: " << frames_decoded_; |
| 420 |
| 421 inited_ = false; |
| 422 rtc::MessageQueueManager::Clear(this); |
| 423 ResetVariables(); |
| 424 |
| 425 jni->CallVoidMethod( |
| 426 *j_media_codec_video_decoder_, |
| 427 j_reset_method_, |
| 428 codec_.width, |
| 429 codec_.height); |
| 430 |
| 431 if (CheckException(jni)) { |
| 432 ALOGE << "Soft reset error - fallback to SW codec."; |
| 433 sw_fallback_required_ = true; |
| 434 return WEBRTC_VIDEO_CODEC_ERROR; |
| 435 } |
| 436 inited_ = true; |
| 437 |
| 438 codec_thread_->PostDelayed(kMediaCodecPollMs, this); |
| 439 |
| 440 return WEBRTC_VIDEO_CODEC_OK; |
| 441 } |
| 442 |
401 int32_t MediaCodecVideoDecoder::Release() { | 443 int32_t MediaCodecVideoDecoder::Release() { |
402 ALOGD << "DecoderRelease request"; | 444 ALOGD << "DecoderRelease request"; |
403 return codec_thread_->Invoke<int32_t>( | 445 return codec_thread_->Invoke<int32_t>( |
404 Bind(&MediaCodecVideoDecoder::ReleaseOnCodecThread, this)); | 446 Bind(&MediaCodecVideoDecoder::ReleaseOnCodecThread, this)); |
405 } | 447 } |
406 | 448 |
407 int32_t MediaCodecVideoDecoder::ReleaseOnCodecThread() { | 449 int32_t MediaCodecVideoDecoder::ReleaseOnCodecThread() { |
408 if (!inited_) { | 450 if (!inited_) { |
409 return WEBRTC_VIDEO_CODEC_OK; | 451 return WEBRTC_VIDEO_CODEC_OK; |
410 } | 452 } |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
486 } | 528 } |
487 if (!inited_) { | 529 if (!inited_) { |
488 ALOGE << "Decode() - decoder is not initialized"; | 530 ALOGE << "Decode() - decoder is not initialized"; |
489 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | 531 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; |
490 } | 532 } |
491 | 533 |
492 // Check if encoded frame dimension has changed. | 534 // Check if encoded frame dimension has changed. |
493 if ((inputImage._encodedWidth * inputImage._encodedHeight > 0) && | 535 if ((inputImage._encodedWidth * inputImage._encodedHeight > 0) && |
494 (inputImage._encodedWidth != codec_.width || | 536 (inputImage._encodedWidth != codec_.width || |
495 inputImage._encodedHeight != codec_.height)) { | 537 inputImage._encodedHeight != codec_.height)) { |
| 538 ALOGW << "Input resolution changed from " << |
| 539 codec_.width << " x " << codec_.height << " to " << |
| 540 inputImage._encodedWidth << " x " << inputImage._encodedHeight; |
496 codec_.width = inputImage._encodedWidth; | 541 codec_.width = inputImage._encodedWidth; |
497 codec_.height = inputImage._encodedHeight; | 542 codec_.height = inputImage._encodedHeight; |
498 int32_t ret = InitDecode(&codec_, 1); | 543 int32_t ret; |
| 544 if (use_surface_ && codecType_ == kVideoCodecVP8) { |
| 545 // Soft codec reset - only for VP8 and surface decoding. |
| 546 // TODO(glaznev): try to use similar approach for H.264 |
| 547 // and buffer decoding. |
| 548 ret = codec_thread_->Invoke<int32_t>(Bind( |
| 549 &MediaCodecVideoDecoder::ResetDecodeOnCodecThread, this)); |
| 550 } else { |
| 551 // Hard codec reset. |
| 552 ret = InitDecode(&codec_, 1); |
| 553 } |
499 if (ret < 0) { | 554 if (ret < 0) { |
500 ALOGE << "InitDecode failure: " << ret << " - fallback to SW codec"; | 555 ALOGE << "InitDecode failure: " << ret << " - fallback to SW codec"; |
501 sw_fallback_required_ = true; | 556 sw_fallback_required_ = true; |
502 return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE; | 557 return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE; |
503 } | 558 } |
504 } | 559 } |
505 | 560 |
506 // Always start with a complete key frame. | 561 // Always start with a complete key frame. |
507 if (key_frame_required_) { | 562 if (key_frame_required_) { |
508 if (inputImage._frameType != webrtc::kVideoFrameKey) { | 563 if (inputImage._frameType != webrtc::kVideoFrameKey) { |
(...skipping 15 matching lines...) Expand all Loading... |
524 } | 579 } |
525 | 580 |
526 int32_t MediaCodecVideoDecoder::DecodeOnCodecThread( | 581 int32_t MediaCodecVideoDecoder::DecodeOnCodecThread( |
527 const EncodedImage& inputImage) { | 582 const EncodedImage& inputImage) { |
528 CheckOnCodecThread(); | 583 CheckOnCodecThread(); |
529 JNIEnv* jni = AttachCurrentThreadIfNeeded(); | 584 JNIEnv* jni = AttachCurrentThreadIfNeeded(); |
530 ScopedLocalRefFrame local_ref_frame(jni); | 585 ScopedLocalRefFrame local_ref_frame(jni); |
531 | 586 |
532 // Try to drain the decoder and wait until output is not too | 587 // Try to drain the decoder and wait until output is not too |
533 // much behind the input. | 588 // much behind the input. |
534 if (frames_received_ > frames_decoded_ + max_pending_frames_) { | 589 if (codecType_ == kVideoCodecH264 && |
| 590 frames_received_ > frames_decoded_ + max_pending_frames_) { |
| 591 // Print warning for H.264 only - for VP8/VP9 one frame delay is ok. |
535 ALOGW << "Decoder is too far behind. Try to drain. Received: " << | 592 ALOGW << "Decoder is too far behind. Try to drain. Received: " << |
536 frames_received_ << ". Decoded: " << frames_decoded_; | 593 frames_received_ << ". Decoded: " << frames_decoded_; |
537 EnableFrameLogOnWarning(); | 594 EnableFrameLogOnWarning(); |
538 } | 595 } |
539 const int64 drain_start = GetCurrentTimeMs(); | 596 const int64 drain_start = GetCurrentTimeMs(); |
540 while ((frames_received_ > frames_decoded_ + max_pending_frames_) && | 597 while ((frames_received_ > frames_decoded_ + max_pending_frames_) && |
541 (GetCurrentTimeMs() - drain_start) < kMediaCodecTimeoutMs) { | 598 (GetCurrentTimeMs() - drain_start) < kMediaCodecTimeoutMs) { |
542 if (!DeliverPendingOutputs(jni, kMediaCodecPollMs)) { | 599 if (!DeliverPendingOutputs(jni, kMediaCodecPollMs)) { |
543 ALOGE << "DeliverPendingOutputs error. Frames received: " << | 600 ALOGE << "DeliverPendingOutputs error. Frames received: " << |
544 frames_received_ << ". Frames decoded: " << frames_decoded_; | 601 frames_received_ << ". Frames decoded: " << frames_decoded_; |
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
928 ALOGD << "Destroy video decoder."; | 985 ALOGD << "Destroy video decoder."; |
929 delete decoder; | 986 delete decoder; |
930 } | 987 } |
931 | 988 |
932 const char* MediaCodecVideoDecoder::ImplementationName() const { | 989 const char* MediaCodecVideoDecoder::ImplementationName() const { |
933 return "MediaCodec"; | 990 return "MediaCodec"; |
934 } | 991 } |
935 | 992 |
936 } // namespace webrtc_jni | 993 } // namespace webrtc_jni |
937 | 994 |
OLD | NEW |