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

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

Issue 1379383002: Android MediaCodecVideoDecoder: Split DecoderOutputBufferInfo into DecodedByteBuffer and DecodedTex… (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
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 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
127 // State that is constant for the lifetime of this object once the ctor 127 // State that is constant for the lifetime of this object once the ctor
128 // returns. 128 // returns.
129 scoped_ptr<Thread> codec_thread_; // Thread on which to operate MediaCodec. 129 scoped_ptr<Thread> codec_thread_; // Thread on which to operate MediaCodec.
130 ScopedGlobalRef<jclass> j_media_codec_video_decoder_class_; 130 ScopedGlobalRef<jclass> j_media_codec_video_decoder_class_;
131 ScopedGlobalRef<jobject> j_media_codec_video_decoder_; 131 ScopedGlobalRef<jobject> j_media_codec_video_decoder_;
132 jmethodID j_init_decode_method_; 132 jmethodID j_init_decode_method_;
133 jmethodID j_release_method_; 133 jmethodID j_release_method_;
134 jmethodID j_dequeue_input_buffer_method_; 134 jmethodID j_dequeue_input_buffer_method_;
135 jmethodID j_queue_input_buffer_method_; 135 jmethodID j_queue_input_buffer_method_;
136 jmethodID j_dequeue_output_buffer_method_; 136 jmethodID j_dequeue_output_buffer_method_;
137 jmethodID j_release_output_buffer_method_; 137 jmethodID j_return_decoded_byte_buffer_method_;
138 // MediaCodecVideoDecoder fields. 138 // MediaCodecVideoDecoder fields.
139 jfieldID j_input_buffers_field_; 139 jfieldID j_input_buffers_field_;
140 jfieldID j_output_buffers_field_; 140 jfieldID j_output_buffers_field_;
141 jfieldID j_color_format_field_; 141 jfieldID j_color_format_field_;
142 jfieldID j_width_field_; 142 jfieldID j_width_field_;
143 jfieldID j_height_field_; 143 jfieldID j_height_field_;
144 jfieldID j_stride_field_; 144 jfieldID j_stride_field_;
145 jfieldID j_slice_height_field_; 145 jfieldID j_slice_height_field_;
146 jfieldID j_surface_texture_field_; 146 jfieldID j_surface_texture_field_;
147 // MediaCodecVideoDecoder.DecodedTextureBuffer fields.
147 jfieldID j_textureID_field_; 148 jfieldID j_textureID_field_;
148 // MediaCodecVideoDecoder.DecoderOutputBufferInfo fields. 149 jfieldID j_texture_presentation_timestamp_us_field_;
150 // MediaCodecVideoDecoder.DecodedByteBuffer fields.
149 jfieldID j_info_index_field_; 151 jfieldID j_info_index_field_;
150 jfieldID j_info_offset_field_; 152 jfieldID j_info_offset_field_;
151 jfieldID j_info_size_field_; 153 jfieldID j_info_size_field_;
152 jfieldID j_info_presentation_timestamp_us_field_; 154 jfieldID j_info_presentation_timestamp_us_field_;
153 155
154 // Global references; must be deleted in Release(). 156 // Global references; must be deleted in Release().
155 std::vector<jobject> input_buffers_; 157 std::vector<jobject> input_buffers_;
156 jobject surface_texture_; 158 jobject surface_texture_;
157 jobject previous_surface_texture_; 159 jobject previous_surface_texture_;
158 160
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 "(Lorg/webrtc/MediaCodecVideoDecoder$VideoCodecType;" 192 "(Lorg/webrtc/MediaCodecVideoDecoder$VideoCodecType;"
191 "IILandroid/opengl/EGLContext;)Z"); 193 "IILandroid/opengl/EGLContext;)Z");
192 j_release_method_ = 194 j_release_method_ =
193 GetMethodID(jni, *j_media_codec_video_decoder_class_, "release", "()V"); 195 GetMethodID(jni, *j_media_codec_video_decoder_class_, "release", "()V");
194 j_dequeue_input_buffer_method_ = GetMethodID( 196 j_dequeue_input_buffer_method_ = GetMethodID(
195 jni, *j_media_codec_video_decoder_class_, "dequeueInputBuffer", "()I"); 197 jni, *j_media_codec_video_decoder_class_, "dequeueInputBuffer", "()I");
196 j_queue_input_buffer_method_ = GetMethodID( 198 j_queue_input_buffer_method_ = GetMethodID(
197 jni, *j_media_codec_video_decoder_class_, "queueInputBuffer", "(IIJ)Z"); 199 jni, *j_media_codec_video_decoder_class_, "queueInputBuffer", "(IIJ)Z");
198 j_dequeue_output_buffer_method_ = GetMethodID( 200 j_dequeue_output_buffer_method_ = GetMethodID(
199 jni, *j_media_codec_video_decoder_class_, "dequeueOutputBuffer", 201 jni, *j_media_codec_video_decoder_class_, "dequeueOutputBuffer",
200 "(I)Lorg/webrtc/MediaCodecVideoDecoder$DecoderOutputBufferInfo;"); 202 "(I)Ljava/lang/Object;");
201 j_release_output_buffer_method_ = GetMethodID( 203 j_return_decoded_byte_buffer_method_ =
202 jni, *j_media_codec_video_decoder_class_, "releaseOutputBuffer", "(I)V"); 204 GetMethodID(jni, *j_media_codec_video_decoder_class_,
205 "returnDecodedByteBuffer", "(I)V");
203 206
204 j_input_buffers_field_ = GetFieldID( 207 j_input_buffers_field_ = GetFieldID(
205 jni, *j_media_codec_video_decoder_class_, 208 jni, *j_media_codec_video_decoder_class_,
206 "inputBuffers", "[Ljava/nio/ByteBuffer;"); 209 "inputBuffers", "[Ljava/nio/ByteBuffer;");
207 j_output_buffers_field_ = GetFieldID( 210 j_output_buffers_field_ = GetFieldID(
208 jni, *j_media_codec_video_decoder_class_, 211 jni, *j_media_codec_video_decoder_class_,
209 "outputBuffers", "[Ljava/nio/ByteBuffer;"); 212 "outputBuffers", "[Ljava/nio/ByteBuffer;");
210 j_color_format_field_ = GetFieldID( 213 j_color_format_field_ = GetFieldID(
211 jni, *j_media_codec_video_decoder_class_, "colorFormat", "I"); 214 jni, *j_media_codec_video_decoder_class_, "colorFormat", "I");
212 j_width_field_ = GetFieldID( 215 j_width_field_ = GetFieldID(
213 jni, *j_media_codec_video_decoder_class_, "width", "I"); 216 jni, *j_media_codec_video_decoder_class_, "width", "I");
214 j_height_field_ = GetFieldID( 217 j_height_field_ = GetFieldID(
215 jni, *j_media_codec_video_decoder_class_, "height", "I"); 218 jni, *j_media_codec_video_decoder_class_, "height", "I");
216 j_stride_field_ = GetFieldID( 219 j_stride_field_ = GetFieldID(
217 jni, *j_media_codec_video_decoder_class_, "stride", "I"); 220 jni, *j_media_codec_video_decoder_class_, "stride", "I");
218 j_slice_height_field_ = GetFieldID( 221 j_slice_height_field_ = GetFieldID(
219 jni, *j_media_codec_video_decoder_class_, "sliceHeight", "I"); 222 jni, *j_media_codec_video_decoder_class_, "sliceHeight", "I");
220 j_textureID_field_ = GetFieldID(
221 jni, *j_media_codec_video_decoder_class_, "textureID", "I");
222 j_surface_texture_field_ = GetFieldID( 223 j_surface_texture_field_ = GetFieldID(
223 jni, *j_media_codec_video_decoder_class_, "surfaceTexture", 224 jni, *j_media_codec_video_decoder_class_, "surfaceTexture",
224 "Landroid/graphics/SurfaceTexture;"); 225 "Landroid/graphics/SurfaceTexture;");
225 226
226 jclass j_decoder_output_buffer_info_class = FindClass(jni, 227 jclass j_decoder_decoded_texture_buffer_class = FindClass(jni,
227 "org/webrtc/MediaCodecVideoDecoder$DecoderOutputBufferInfo"); 228 "org/webrtc/MediaCodecVideoDecoder$DecodedTextureBuffer");
229 j_textureID_field_ = GetFieldID(
230 jni, j_decoder_decoded_texture_buffer_class, "textureID", "I");
231 j_texture_presentation_timestamp_us_field_ =
232 GetFieldID(jni, j_decoder_decoded_texture_buffer_class,
233 "presentationTimestampUs", "J");
234
235 jclass j_decoder_decoded_byte_buffer_class = FindClass(jni,
236 "org/webrtc/MediaCodecVideoDecoder$DecodedByteBuffer");
228 j_info_index_field_ = GetFieldID( 237 j_info_index_field_ = GetFieldID(
229 jni, j_decoder_output_buffer_info_class, "index", "I"); 238 jni, j_decoder_decoded_byte_buffer_class, "index", "I");
230 j_info_offset_field_ = GetFieldID( 239 j_info_offset_field_ = GetFieldID(
231 jni, j_decoder_output_buffer_info_class, "offset", "I"); 240 jni, j_decoder_decoded_byte_buffer_class, "offset", "I");
232 j_info_size_field_ = GetFieldID( 241 j_info_size_field_ = GetFieldID(
233 jni, j_decoder_output_buffer_info_class, "size", "I"); 242 jni, j_decoder_decoded_byte_buffer_class, "size", "I");
234 j_info_presentation_timestamp_us_field_ = GetFieldID( 243 j_info_presentation_timestamp_us_field_ = GetFieldID(
235 jni, j_decoder_output_buffer_info_class, "presentationTimestampUs", "J"); 244 jni, j_decoder_decoded_byte_buffer_class, "presentationTimestampUs", "J");
236 245
237 CHECK_EXCEPTION(jni) << "MediaCodecVideoDecoder ctor failed"; 246 CHECK_EXCEPTION(jni) << "MediaCodecVideoDecoder ctor failed";
238 use_surface_ = (render_egl_context_ != NULL); 247 use_surface_ = (render_egl_context_ != NULL);
239 ALOGD("MediaCodecVideoDecoder ctor. Use surface: %d", use_surface_); 248 ALOGD("MediaCodecVideoDecoder ctor. Use surface: %d", use_surface_);
240 memset(&codec_, 0, sizeof(codec_)); 249 memset(&codec_, 0, sizeof(codec_));
241 AllowBlockingCalls(); 250 AllowBlockingCalls();
242 } 251 }
243 252
244 MediaCodecVideoDecoder::~MediaCodecVideoDecoder() { 253 MediaCodecVideoDecoder::~MediaCodecVideoDecoder() {
245 // Call Release() to ensure no more callbacks to us after we are deleted. 254 // Call Release() to ensure no more callbacks to us after we are deleted.
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after
552 return WEBRTC_VIDEO_CODEC_OK; 561 return WEBRTC_VIDEO_CODEC_OK;
553 } 562 }
554 563
555 bool MediaCodecVideoDecoder::DeliverPendingOutputs( 564 bool MediaCodecVideoDecoder::DeliverPendingOutputs(
556 JNIEnv* jni, int dequeue_timeout_us) { 565 JNIEnv* jni, int dequeue_timeout_us) {
557 if (frames_received_ <= frames_decoded_) { 566 if (frames_received_ <= frames_decoded_) {
558 // No need to query for output buffers - decoder is drained. 567 // No need to query for output buffers - decoder is drained.
559 return true; 568 return true;
560 } 569 }
561 // Get decoder output. 570 // Get decoder output.
562 jobject j_decoder_output_buffer_info = jni->CallObjectMethod( 571 jobject j_decoder_output_buffer = jni->CallObjectMethod(
563 *j_media_codec_video_decoder_, 572 *j_media_codec_video_decoder_,
564 j_dequeue_output_buffer_method_, 573 j_dequeue_output_buffer_method_,
565 dequeue_timeout_us); 574 dequeue_timeout_us);
566 if (CheckException(jni)) { 575 if (CheckException(jni)) {
576 ALOGE("dequeueOutputBuffer() error");
567 return false; 577 return false;
568 } 578 }
569 if (IsNull(jni, j_decoder_output_buffer_info)) { 579 if (IsNull(jni, j_decoder_output_buffer)) {
580 // No decoded frame ready.
570 return true; 581 return true;
571 } 582 }
572 583
573 // Extract output buffer info from Java DecoderOutputBufferInfo.
574 int output_buffer_index =
575 GetIntField(jni, j_decoder_output_buffer_info, j_info_index_field_);
576 RTC_CHECK_GE(output_buffer_index, 0);
577 int output_buffer_offset =
578 GetIntField(jni, j_decoder_output_buffer_info, j_info_offset_field_);
579 int output_buffer_size =
580 GetIntField(jni, j_decoder_output_buffer_info, j_info_size_field_);
581 long output_timestamps_ms = GetLongField(jni, j_decoder_output_buffer_info,
582 j_info_presentation_timestamp_us_field_) / rtc::kNumMicrosecsPerMillisec;
583 if (CheckException(jni)) {
584 return false;
585 }
586
587 // Get decoded video frame properties. 584 // Get decoded video frame properties.
585 long output_timestamps_ms;
perkj_webrtc 2015/10/02 15:25:22 nit set = 0 and move just before the if statement
magjed_webrtc 2015/10/03 08:18:11 Done.
588 int color_format = GetIntField(jni, *j_media_codec_video_decoder_, 586 int color_format = GetIntField(jni, *j_media_codec_video_decoder_,
589 j_color_format_field_); 587 j_color_format_field_);
590 int width = GetIntField(jni, *j_media_codec_video_decoder_, j_width_field_); 588 int width = GetIntField(jni, *j_media_codec_video_decoder_, j_width_field_);
591 int height = GetIntField(jni, *j_media_codec_video_decoder_, j_height_field_); 589 int height = GetIntField(jni, *j_media_codec_video_decoder_, j_height_field_);
592 int stride = GetIntField(jni, *j_media_codec_video_decoder_, j_stride_field_); 590 int stride = GetIntField(jni, *j_media_codec_video_decoder_, j_stride_field_);
593 int slice_height = GetIntField(jni, *j_media_codec_video_decoder_, 591 int slice_height = GetIntField(jni, *j_media_codec_video_decoder_,
594 j_slice_height_field_); 592 j_slice_height_field_);
595 int texture_id = GetIntField(jni, *j_media_codec_video_decoder_,
596 j_textureID_field_);
597 593
598 rtc::scoped_refptr<webrtc::VideoFrameBuffer> frame_buffer; 594 rtc::scoped_refptr<webrtc::VideoFrameBuffer> frame_buffer;
599 if (use_surface_) { 595 if (use_surface_) {
596 // Extract data from Java DecodedTextureBuffer.
597 const int texture_id =
598 GetIntField(jni, j_decoder_output_buffer, j_textureID_field_);
599 const int64_t timestamp_us =
600 GetLongField(jni, j_decoder_output_buffer,
601 j_texture_presentation_timestamp_us_field_);
602 output_timestamps_ms = timestamp_us / rtc::kNumMicrosecsPerMillisec;
603 // Create webrtc::VideoFrameBuffer with native texture handle.
600 native_handle_.SetTextureObject(surface_texture_, texture_id); 604 native_handle_.SetTextureObject(surface_texture_, texture_id);
601 frame_buffer = new rtc::RefCountedObject<JniNativeHandleBuffer>( 605 frame_buffer = new rtc::RefCountedObject<JniNativeHandleBuffer>(
602 &native_handle_, width, height); 606 &native_handle_, width, height);
603 } else { 607 } else {
604 // Extract data from Java ByteBuffer and create output yuv420 frame - 608 // Extract data from Java ByteBuffer and create output yuv420 frame -
605 // for non surface decoding only. 609 // for non surface decoding only.
610 const int output_buffer_index =
611 GetIntField(jni, j_decoder_output_buffer, j_info_index_field_);
612 const int output_buffer_offset =
613 GetIntField(jni, j_decoder_output_buffer, j_info_offset_field_);
614 const int output_buffer_size =
615 GetIntField(jni, j_decoder_output_buffer, j_info_size_field_);
616 const int64_t timestamp_us = GetLongField(
617 jni, j_decoder_output_buffer, j_info_presentation_timestamp_us_field_);
618 output_timestamps_ms = timestamp_us / rtc::kNumMicrosecsPerMillisec;
619
606 if (output_buffer_size < width * height * 3 / 2) { 620 if (output_buffer_size < width * height * 3 / 2) {
607 ALOGE("Insufficient output buffer size: %d", output_buffer_size); 621 ALOGE("Insufficient output buffer size: %d", output_buffer_size);
608 return false; 622 return false;
609 } 623 }
610 jobjectArray output_buffers = reinterpret_cast<jobjectArray>(GetObjectField( 624 jobjectArray output_buffers = reinterpret_cast<jobjectArray>(GetObjectField(
611 jni, *j_media_codec_video_decoder_, j_output_buffers_field_)); 625 jni, *j_media_codec_video_decoder_, j_output_buffers_field_));
612 jobject output_buffer = 626 jobject output_buffer =
613 jni->GetObjectArrayElement(output_buffers, output_buffer_index); 627 jni->GetObjectArrayElement(output_buffers, output_buffer_index);
614 uint8_t* payload = reinterpret_cast<uint8_t*>(jni->GetDirectBufferAddress( 628 uint8_t* payload = reinterpret_cast<uint8_t*>(jni->GetDirectBufferAddress(
615 output_buffer)); 629 output_buffer));
(...skipping 30 matching lines...) Expand all
646 y_ptr, stride, 660 y_ptr, stride,
647 uv_ptr, stride, 661 uv_ptr, stride,
648 frame_buffer->MutableData(webrtc::kYPlane), 662 frame_buffer->MutableData(webrtc::kYPlane),
649 frame_buffer->stride(webrtc::kYPlane), 663 frame_buffer->stride(webrtc::kYPlane),
650 frame_buffer->MutableData(webrtc::kUPlane), 664 frame_buffer->MutableData(webrtc::kUPlane),
651 frame_buffer->stride(webrtc::kUPlane), 665 frame_buffer->stride(webrtc::kUPlane),
652 frame_buffer->MutableData(webrtc::kVPlane), 666 frame_buffer->MutableData(webrtc::kVPlane),
653 frame_buffer->stride(webrtc::kVPlane), 667 frame_buffer->stride(webrtc::kVPlane),
654 width, height); 668 width, height);
655 } 669 }
670 // Return output byte buffer back to codec.
671 jni->CallVoidMethod(
672 *j_media_codec_video_decoder_,
673 j_return_decoded_byte_buffer_method_,
674 output_buffer_index);
675 if (CheckException(jni)) {
676 ALOGE("returnDecodedByteBuffer error");
677 return false;
678 }
656 } 679 }
657 VideoFrame decoded_frame(frame_buffer, 0, 0, webrtc::kVideoRotation_0); 680 VideoFrame decoded_frame(frame_buffer, 0, 0, webrtc::kVideoRotation_0);
658 681
659 // Get frame timestamps from a queue. 682 // Get frame timestamps from a queue.
660 if (timestamps_.size() > 0) { 683 if (timestamps_.size() > 0) {
661 decoded_frame.set_timestamp(timestamps_.front()); 684 decoded_frame.set_timestamp(timestamps_.front());
662 timestamps_.erase(timestamps_.begin()); 685 timestamps_.erase(timestamps_.begin());
663 } 686 }
664 if (ntp_times_ms_.size() > 0) { 687 if (ntp_times_ms_.size() > 0) {
665 decoded_frame.set_ntp_time_ms(ntp_times_ms_.front()); 688 decoded_frame.set_ntp_time_ms(ntp_times_ms_.front());
666 ntp_times_ms_.erase(ntp_times_ms_.begin()); 689 ntp_times_ms_.erase(ntp_times_ms_.begin());
667 } 690 }
668 int64_t frame_decoding_time_ms = 0; 691 int64_t frame_decoding_time_ms = 0;
669 if (frame_rtc_times_ms_.size() > 0) { 692 if (frame_rtc_times_ms_.size() > 0) {
670 frame_decoding_time_ms = GetCurrentTimeMs() - frame_rtc_times_ms_.front(); 693 frame_decoding_time_ms = GetCurrentTimeMs() - frame_rtc_times_ms_.front();
671 frame_rtc_times_ms_.erase(frame_rtc_times_ms_.begin()); 694 frame_rtc_times_ms_.erase(frame_rtc_times_ms_.begin());
672 } 695 }
673 ALOGV("Decoder frame out # %d. %d x %d. %d x %d. Color: 0x%x. TS: %ld." 696 ALOGV("Decoder frame out # %d. %d x %d. %d x %d. Color: 0x%x. TS: %ld."
674 " DecTime: %lld", frames_decoded_, width, height, stride, slice_height, 697 " DecTime: %lld", frames_decoded_, width, height, stride, slice_height,
675 color_format, output_timestamps_ms, frame_decoding_time_ms); 698 color_format, output_timestamps_ms, frame_decoding_time_ms);
676 699
677 // Return output buffer back to codec.
678 jni->CallVoidMethod(
679 *j_media_codec_video_decoder_,
680 j_release_output_buffer_method_,
681 output_buffer_index);
682 if (CheckException(jni)) {
683 ALOGE("releaseOutputBuffer error");
684 return false;
685 }
686
687 // Calculate and print decoding statistics - every 3 seconds. 700 // Calculate and print decoding statistics - every 3 seconds.
688 frames_decoded_++; 701 frames_decoded_++;
689 current_frames_++; 702 current_frames_++;
690 current_decoding_time_ms_ += frame_decoding_time_ms; 703 current_decoding_time_ms_ += frame_decoding_time_ms;
691 int statistic_time_ms = GetCurrentTimeMs() - start_time_ms_; 704 int statistic_time_ms = GetCurrentTimeMs() - start_time_ms_;
692 if (statistic_time_ms >= kMediaCodecStatisticsIntervalMs && 705 if (statistic_time_ms >= kMediaCodecStatisticsIntervalMs &&
693 current_frames_ > 0) { 706 current_frames_ > 0) {
694 ALOGD("Decoder bitrate: %d kbps, fps: %d, decTime: %d for last %d ms", 707 ALOGD("Decoder bitrate: %d kbps, fps: %d, decTime: %d for last %d ms",
695 current_bytes_ * 8 / statistic_time_ms, 708 current_bytes_ * 8 / statistic_time_ms,
696 (current_frames_ * 1000 + statistic_time_ms / 2) / statistic_time_ms, 709 (current_frames_ * 1000 + statistic_time_ms / 2) / statistic_time_ms,
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
827 return NULL; 840 return NULL;
828 } 841 }
829 842
830 void MediaCodecVideoDecoderFactory::DestroyVideoDecoder( 843 void MediaCodecVideoDecoderFactory::DestroyVideoDecoder(
831 webrtc::VideoDecoder* decoder) { 844 webrtc::VideoDecoder* decoder) {
832 delete decoder; 845 delete decoder;
833 } 846 }
834 847
835 } // namespace webrtc_jni 848 } // namespace webrtc_jni
836 849
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698