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

Side by Side Diff: talk/app/webrtc/java/jni/androidmediadecoder_jni.cc

Issue 1374153003: Android MediaDecoder: Use frame pool to avoid allocations for non-surface decoding (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 5 years, 2 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * libjingle 2 * libjingle
3 * Copyright 2015 Google Inc. 3 * Copyright 2015 Google Inc.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright notice, 8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer. 9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice, 10 * 2. Redistributions in binary form must reproduce the above copyright notice,
(...skipping 17 matching lines...) Expand all
28 28
29 #include <vector> 29 #include <vector>
30 30
31 #include "talk/app/webrtc/java/jni/androidmediadecoder_jni.h" 31 #include "talk/app/webrtc/java/jni/androidmediadecoder_jni.h"
32 #include "talk/app/webrtc/java/jni/androidmediacodeccommon.h" 32 #include "talk/app/webrtc/java/jni/androidmediacodeccommon.h"
33 #include "talk/app/webrtc/java/jni/classreferenceholder.h" 33 #include "talk/app/webrtc/java/jni/classreferenceholder.h"
34 #include "talk/app/webrtc/java/jni/native_handle_impl.h" 34 #include "talk/app/webrtc/java/jni/native_handle_impl.h"
35 #include "webrtc/base/bind.h" 35 #include "webrtc/base/bind.h"
36 #include "webrtc/base/checks.h" 36 #include "webrtc/base/checks.h"
37 #include "webrtc/base/logging.h" 37 #include "webrtc/base/logging.h"
38 #include "webrtc/base/scoped_ref_ptr.h"
38 #include "webrtc/base/thread.h" 39 #include "webrtc/base/thread.h"
40 #include "webrtc/common_video/interface/i420_buffer_pool.h"
39 #include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h" 41 #include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h"
40 #include "webrtc/system_wrappers/interface/logcat_trace_context.h" 42 #include "webrtc/system_wrappers/interface/logcat_trace_context.h"
41 #include "webrtc/system_wrappers/interface/tick_util.h" 43 #include "webrtc/system_wrappers/interface/tick_util.h"
42 #include "third_party/libyuv/include/libyuv/convert.h" 44 #include "third_party/libyuv/include/libyuv/convert.h"
43 #include "third_party/libyuv/include/libyuv/convert_from.h" 45 #include "third_party/libyuv/include/libyuv/convert_from.h"
44 #include "third_party/libyuv/include/libyuv/video_common.h" 46 #include "third_party/libyuv/include/libyuv/video_common.h"
45 47
46 using rtc::Bind; 48 using rtc::Bind;
47 using rtc::Thread; 49 using rtc::Thread;
48 using rtc::ThreadManager; 50 using rtc::ThreadManager;
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 int32_t ProcessHWErrorOnCodecThread(); 101 int32_t ProcessHWErrorOnCodecThread();
100 102
101 // Type of video codec. 103 // Type of video codec.
102 VideoCodecType codecType_; 104 VideoCodecType codecType_;
103 105
104 bool key_frame_required_; 106 bool key_frame_required_;
105 bool inited_; 107 bool inited_;
106 bool sw_fallback_required_; 108 bool sw_fallback_required_;
107 bool use_surface_; 109 bool use_surface_;
108 VideoCodec codec_; 110 VideoCodec codec_;
109 VideoFrame decoded_image_; 111 webrtc::I420BufferPool decoded_frame_pool_;
110 NativeHandleImpl native_handle_; 112 NativeHandleImpl native_handle_;
111 DecodedImageCallback* callback_; 113 DecodedImageCallback* callback_;
112 int frames_received_; // Number of frames received by decoder. 114 int frames_received_; // Number of frames received by decoder.
113 int frames_decoded_; // Number of frames decoded by decoder. 115 int frames_decoded_; // Number of frames decoded by decoder.
114 int64_t start_time_ms_; // Start time for statistics. 116 int64_t start_time_ms_; // Start time for statistics.
115 int current_frames_; // Number of frames in the current statistics interval. 117 int current_frames_; // Number of frames in the current statistics interval.
116 int current_bytes_; // Encoded bytes in the current statistics interval. 118 int current_bytes_; // Encoded bytes in the current statistics interval.
117 int current_decoding_time_ms_; // Overall decoding time in the current second 119 int current_decoding_time_ms_; // Overall decoding time in the current second
118 uint32_t max_pending_frames_; // Maximum number of pending input frames 120 uint32_t max_pending_frames_; // Maximum number of pending input frames
119 std::vector<int32_t> timestamps_; 121 std::vector<int32_t> timestamps_;
120 std::vector<int64_t> ntp_times_ms_; 122 std::vector<int64_t> ntp_times_ms_;
121 std::vector<int64_t> frame_rtc_times_ms_; // Time when video frame is sent to 123 std::vector<int64_t> frame_rtc_times_ms_; // Time when video frame is sent to
122 // decoder input. 124 // decoder input.
123 int32_t output_timestamp_; // Last output frame timestamp from timestamps_ Q.
124 int64_t output_ntp_time_ms_; // Last output frame ntp time from
125 // ntp_times_ms_ queue.
126 125
127 // State that is constant for the lifetime of this object once the ctor 126 // State that is constant for the lifetime of this object once the ctor
128 // returns. 127 // returns.
129 scoped_ptr<Thread> codec_thread_; // Thread on which to operate MediaCodec. 128 scoped_ptr<Thread> codec_thread_; // Thread on which to operate MediaCodec.
130 ScopedGlobalRef<jclass> j_media_codec_video_decoder_class_; 129 ScopedGlobalRef<jclass> j_media_codec_video_decoder_class_;
131 ScopedGlobalRef<jobject> j_media_codec_video_decoder_; 130 ScopedGlobalRef<jobject> j_media_codec_video_decoder_;
132 jmethodID j_init_decode_method_; 131 jmethodID j_init_decode_method_;
133 jmethodID j_release_method_; 132 jmethodID j_release_method_;
134 jmethodID j_dequeue_input_buffer_method_; 133 jmethodID j_dequeue_input_buffer_method_;
135 jmethodID j_queue_input_buffer_method_; 134 jmethodID j_queue_input_buffer_method_;
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
324 case kVideoCodecH264: 323 case kVideoCodecH264:
325 max_pending_frames_ = kMaxPendingFramesH264; 324 max_pending_frames_ = kMaxPendingFramesH264;
326 break; 325 break;
327 default: 326 default:
328 max_pending_frames_ = 0; 327 max_pending_frames_ = 0;
329 } 328 }
330 start_time_ms_ = GetCurrentTimeMs(); 329 start_time_ms_ = GetCurrentTimeMs();
331 current_frames_ = 0; 330 current_frames_ = 0;
332 current_bytes_ = 0; 331 current_bytes_ = 0;
333 current_decoding_time_ms_ = 0; 332 current_decoding_time_ms_ = 0;
334 output_timestamp_ = 0;
335 output_ntp_time_ms_ = 0;
336 timestamps_.clear(); 333 timestamps_.clear();
337 ntp_times_ms_.clear(); 334 ntp_times_ms_.clear();
338 frame_rtc_times_ms_.clear(); 335 frame_rtc_times_ms_.clear();
339 336
340 jobjectArray input_buffers = (jobjectArray)GetObjectField( 337 jobjectArray input_buffers = (jobjectArray)GetObjectField(
341 jni, *j_media_codec_video_decoder_, j_input_buffers_field_); 338 jni, *j_media_codec_video_decoder_, j_input_buffers_field_);
342 size_t num_input_buffers = jni->GetArrayLength(input_buffers); 339 size_t num_input_buffers = jni->GetArrayLength(input_buffers);
343 input_buffers_.resize(num_input_buffers); 340 input_buffers_.resize(num_input_buffers);
344 for (size_t i = 0; i < num_input_buffers; ++i) { 341 for (size_t i = 0; i < num_input_buffers; ++i) {
345 input_buffers_[i] = 342 input_buffers_[i] =
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
593 int color_format = GetIntField(jni, *j_media_codec_video_decoder_, 590 int color_format = GetIntField(jni, *j_media_codec_video_decoder_,
594 j_color_format_field_); 591 j_color_format_field_);
595 int width = GetIntField(jni, *j_media_codec_video_decoder_, j_width_field_); 592 int width = GetIntField(jni, *j_media_codec_video_decoder_, j_width_field_);
596 int height = GetIntField(jni, *j_media_codec_video_decoder_, j_height_field_); 593 int height = GetIntField(jni, *j_media_codec_video_decoder_, j_height_field_);
597 int stride = GetIntField(jni, *j_media_codec_video_decoder_, j_stride_field_); 594 int stride = GetIntField(jni, *j_media_codec_video_decoder_, j_stride_field_);
598 int slice_height = GetIntField(jni, *j_media_codec_video_decoder_, 595 int slice_height = GetIntField(jni, *j_media_codec_video_decoder_,
599 j_slice_height_field_); 596 j_slice_height_field_);
600 int texture_id = GetIntField(jni, *j_media_codec_video_decoder_, 597 int texture_id = GetIntField(jni, *j_media_codec_video_decoder_,
601 j_textureID_field_); 598 j_textureID_field_);
602 599
603 // Extract data from Java ByteBuffer and create output yuv420 frame - 600 rtc::scoped_refptr<webrtc::VideoFrameBuffer> frame_buffer;
604 // for non surface decoding only. 601 if (use_surface_) {
605 if (!use_surface_) { 602 native_handle_.SetTextureObject(surface_texture_, texture_id);
603 frame_buffer = new rtc::RefCountedObject<JniNativeHandleBuffer>(
604 &native_handle_, width, height);
605 } else {
606 // Extract data from Java ByteBuffer and create output yuv420 frame -
607 // for non surface decoding only.
606 if (output_buffer_size < width * height * 3 / 2) { 608 if (output_buffer_size < width * height * 3 / 2) {
607 ALOGE("Insufficient output buffer size: %d", output_buffer_size); 609 ALOGE("Insufficient output buffer size: %d", output_buffer_size);
608 return false; 610 return false;
609 } 611 }
610 jobjectArray output_buffers = reinterpret_cast<jobjectArray>(GetObjectField( 612 jobjectArray output_buffers = reinterpret_cast<jobjectArray>(GetObjectField(
611 jni, *j_media_codec_video_decoder_, j_output_buffers_field_)); 613 jni, *j_media_codec_video_decoder_, j_output_buffers_field_));
612 jobject output_buffer = 614 jobject output_buffer =
613 jni->GetObjectArrayElement(output_buffers, output_buffer_index); 615 jni->GetObjectArrayElement(output_buffers, output_buffer_index);
614 uint8_t* payload = reinterpret_cast<uint8_t*>(jni->GetDirectBufferAddress( 616 uint8_t* payload = reinterpret_cast<uint8_t*>(jni->GetDirectBufferAddress(
615 output_buffer)); 617 output_buffer));
616 if (CheckException(jni)) { 618 if (CheckException(jni)) {
617 return false; 619 return false;
618 } 620 }
619 payload += output_buffer_offset; 621 payload += output_buffer_offset;
620 622
621 // Create yuv420 frame. 623 // Create yuv420 frame.
624 frame_buffer = decoded_frame_pool_.CreateBuffer(width, height);
622 if (color_format == COLOR_FormatYUV420Planar) { 625 if (color_format == COLOR_FormatYUV420Planar) {
623 decoded_image_.CreateFrame( 626 RTC_CHECK_EQ(0, stride % 2);
624 payload, 627 RTC_CHECK_EQ(0, slice_height % 2);
625 payload + (stride * slice_height), 628 const int uv_stride = stride / 2;
626 payload + (5 * stride * slice_height / 4), 629 const int u_slice_height = slice_height / 2;
627 width, height, 630 const uint8_t* y_ptr = payload;
628 stride, stride / 2, stride / 2); 631 const uint8_t* u_ptr = y_ptr + stride * slice_height;
632 const uint8_t* v_ptr = u_ptr + uv_stride * u_slice_height;
633 libyuv::I420Copy(y_ptr, stride,
634 u_ptr, uv_stride,
635 v_ptr, uv_stride,
636 frame_buffer->MutableData(webrtc::kYPlane),
637 frame_buffer->stride(webrtc::kYPlane),
638 frame_buffer->MutableData(webrtc::kUPlane),
639 frame_buffer->stride(webrtc::kUPlane),
640 frame_buffer->MutableData(webrtc::kVPlane),
641 frame_buffer->stride(webrtc::kVPlane),
642 width, height);
629 } else { 643 } else {
630 // All other supported formats are nv12. 644 // All other supported formats are nv12.
631 decoded_image_.CreateEmptyFrame(width, height, width, 645 const uint8_t* y_ptr = payload;
632 width / 2, width / 2); 646 const uint8_t* uv_ptr = y_ptr + stride * slice_height;
633 libyuv::NV12ToI420( 647 libyuv::NV12ToI420(
634 payload, stride, 648 y_ptr, stride,
635 payload + stride * slice_height, stride, 649 uv_ptr, stride,
636 decoded_image_.buffer(webrtc::kYPlane), 650 frame_buffer->MutableData(webrtc::kYPlane),
637 decoded_image_.stride(webrtc::kYPlane), 651 frame_buffer->stride(webrtc::kYPlane),
638 decoded_image_.buffer(webrtc::kUPlane), 652 frame_buffer->MutableData(webrtc::kUPlane),
639 decoded_image_.stride(webrtc::kUPlane), 653 frame_buffer->stride(webrtc::kUPlane),
640 decoded_image_.buffer(webrtc::kVPlane), 654 frame_buffer->MutableData(webrtc::kVPlane),
641 decoded_image_.stride(webrtc::kVPlane), 655 frame_buffer->stride(webrtc::kVPlane),
642 width, height); 656 width, height);
643 } 657 }
644 } 658 }
659 VideoFrame decoded_frame(frame_buffer, 0, 0, webrtc::kVideoRotation_0);
645 660
646 // Get frame timestamps from a queue. 661 // Get frame timestamps from a queue.
647 if (timestamps_.size() > 0) { 662 if (timestamps_.size() > 0) {
648 output_timestamp_ = timestamps_.front(); 663 decoded_frame.set_timestamp(timestamps_.front());
649 timestamps_.erase(timestamps_.begin()); 664 timestamps_.erase(timestamps_.begin());
650 } 665 }
651 if (ntp_times_ms_.size() > 0) { 666 if (ntp_times_ms_.size() > 0) {
652 output_ntp_time_ms_ = ntp_times_ms_.front(); 667 decoded_frame.set_ntp_time_ms(ntp_times_ms_.front());
653 ntp_times_ms_.erase(ntp_times_ms_.begin()); 668 ntp_times_ms_.erase(ntp_times_ms_.begin());
654 } 669 }
655 int64_t frame_decoding_time_ms = 0; 670 int64_t frame_decoding_time_ms = 0;
656 if (frame_rtc_times_ms_.size() > 0) { 671 if (frame_rtc_times_ms_.size() > 0) {
657 frame_decoding_time_ms = GetCurrentTimeMs() - frame_rtc_times_ms_.front(); 672 frame_decoding_time_ms = GetCurrentTimeMs() - frame_rtc_times_ms_.front();
658 frame_rtc_times_ms_.erase(frame_rtc_times_ms_.begin()); 673 frame_rtc_times_ms_.erase(frame_rtc_times_ms_.begin());
659 } 674 }
660 ALOGV("Decoder frame out # %d. %d x %d. %d x %d. Color: 0x%x. TS: %ld." 675 ALOGV("Decoder frame out # %d. %d x %d. %d x %d. Color: 0x%x. TS: %ld."
661 " DecTime: %lld", frames_decoded_, width, height, stride, slice_height, 676 " DecTime: %lld", frames_decoded_, width, height, stride, slice_height,
662 color_format, output_timestamps_ms, frame_decoding_time_ms); 677 color_format, output_timestamps_ms, frame_decoding_time_ms);
(...skipping 19 matching lines...) Expand all
682 current_bytes_ * 8 / statistic_time_ms, 697 current_bytes_ * 8 / statistic_time_ms,
683 (current_frames_ * 1000 + statistic_time_ms / 2) / statistic_time_ms, 698 (current_frames_ * 1000 + statistic_time_ms / 2) / statistic_time_ms,
684 current_decoding_time_ms_ / current_frames_, statistic_time_ms); 699 current_decoding_time_ms_ / current_frames_, statistic_time_ms);
685 start_time_ms_ = GetCurrentTimeMs(); 700 start_time_ms_ = GetCurrentTimeMs();
686 current_frames_ = 0; 701 current_frames_ = 0;
687 current_bytes_ = 0; 702 current_bytes_ = 0;
688 current_decoding_time_ms_ = 0; 703 current_decoding_time_ms_ = 0;
689 } 704 }
690 705
691 // Callback - output decoded frame. 706 // Callback - output decoded frame.
692 int32_t callback_status = WEBRTC_VIDEO_CODEC_OK; 707 const int32_t callback_status = callback_->Decoded(decoded_frame);
693 if (use_surface_) {
694 native_handle_.SetTextureObject(surface_texture_, texture_id);
695 VideoFrame texture_image(new rtc::RefCountedObject<JniNativeHandleBuffer>(
696 &native_handle_, width, height),
697 output_timestamp_, 0, webrtc::kVideoRotation_0);
698 texture_image.set_ntp_time_ms(output_ntp_time_ms_);
699 callback_status = callback_->Decoded(texture_image);
700 } else {
701 decoded_image_.set_timestamp(output_timestamp_);
702 decoded_image_.set_ntp_time_ms(output_ntp_time_ms_);
703 callback_status = callback_->Decoded(decoded_image_);
704 }
705 if (callback_status > 0) { 708 if (callback_status > 0) {
706 ALOGE("callback error"); 709 ALOGE("callback error");
707 } 710 }
708 711
709 return true; 712 return true;
710 } 713 }
711 714
712 int32_t MediaCodecVideoDecoder::RegisterDecodeCompleteCallback( 715 int32_t MediaCodecVideoDecoder::RegisterDecodeCompleteCallback(
713 DecodedImageCallback* callback) { 716 DecodedImageCallback* callback) {
714 callback_ = callback; 717 callback_ = callback;
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
826 return NULL; 829 return NULL;
827 } 830 }
828 831
829 void MediaCodecVideoDecoderFactory::DestroyVideoDecoder( 832 void MediaCodecVideoDecoderFactory::DestroyVideoDecoder(
830 webrtc::VideoDecoder* decoder) { 833 webrtc::VideoDecoder* decoder) {
831 delete decoder; 834 delete decoder;
832 } 835 }
833 836
834 } // namespace webrtc_jni 837 } // namespace webrtc_jni
835 838
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698