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

Side by Side Diff: webrtc/sdk/android/src/jni/androidmediaencoder_jni.cc

Issue 2997663002: Support Java VideoFrames in MediaCodecVideoEncoder. (Closed)
Patch Set: Address comments. Created 3 years, 4 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 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
117 webrtc::EncodedImageCallback* callback) override; 117 webrtc::EncodedImageCallback* callback) override;
118 int32_t Release() override; 118 int32_t Release() override;
119 int32_t SetChannelParameters(uint32_t /* packet_loss */, 119 int32_t SetChannelParameters(uint32_t /* packet_loss */,
120 int64_t /* rtt */) override; 120 int64_t /* rtt */) override;
121 int32_t SetRateAllocation(const webrtc::BitrateAllocation& rate_allocation, 121 int32_t SetRateAllocation(const webrtc::BitrateAllocation& rate_allocation,
122 uint32_t frame_rate) override; 122 uint32_t frame_rate) override;
123 123
124 bool SupportsNativeHandle() const override { return egl_context_ != nullptr; } 124 bool SupportsNativeHandle() const override { return egl_context_ != nullptr; }
125 const char* ImplementationName() const override; 125 const char* ImplementationName() const override;
126 126
127 // Fills the input buffer with data from the buffers passed as parameters.
128 bool FillInputBuffer(JNIEnv* jni,
129 int input_buffer_index,
130 uint8_t const* buffer_y,
131 int stride_y,
132 uint8_t const* buffer_u,
133 int stride_u,
134 uint8_t const* buffer_v,
135 int stride_v);
136
127 private: 137 private:
128 class EncodeTask : public rtc::QueuedTask { 138 class EncodeTask : public rtc::QueuedTask {
129 public: 139 public:
130 explicit EncodeTask(rtc::WeakPtr<MediaCodecVideoEncoder> encoder); 140 explicit EncodeTask(rtc::WeakPtr<MediaCodecVideoEncoder> encoder);
131 bool Run() override; 141 bool Run() override;
132 142
133 private: 143 private:
134 rtc::WeakPtr<MediaCodecVideoEncoder> encoder_; 144 rtc::WeakPtr<MediaCodecVideoEncoder> encoder_;
135 }; 145 };
136 146
(...skipping 16 matching lines...) Expand all
153 // previously-current values are reused instead of the passed parameters 163 // previously-current values are reused instead of the passed parameters
154 // (makes it easier to reason about thread-safety). 164 // (makes it easier to reason about thread-safety).
155 int32_t InitEncodeInternal(int width, 165 int32_t InitEncodeInternal(int width,
156 int height, 166 int height,
157 int kbps, 167 int kbps,
158 int fps, 168 int fps,
159 bool use_surface); 169 bool use_surface);
160 // Reconfigure to match |frame| in width, height. Also reconfigures the 170 // Reconfigure to match |frame| in width, height. Also reconfigures the
161 // encoder if |frame| is a texture/byte buffer and the encoder is initialized 171 // encoder if |frame| is a texture/byte buffer and the encoder is initialized
162 // for byte buffer/texture. Returns false if reconfiguring fails. 172 // for byte buffer/texture. Returns false if reconfiguring fails.
163 bool MaybeReconfigureEncoder(const webrtc::VideoFrame& frame); 173 bool MaybeReconfigureEncoder(JNIEnv* jni, const webrtc::VideoFrame& frame);
174
175 // Returns true if the frame is a texture frame and we should use surface
176 // based encoding.
177 bool IsTextureFrame(JNIEnv* jni, const webrtc::VideoFrame& frame);
178
164 bool EncodeByteBuffer(JNIEnv* jni, 179 bool EncodeByteBuffer(JNIEnv* jni,
165 bool key_frame, 180 bool key_frame,
166 const webrtc::VideoFrame& frame, 181 const webrtc::VideoFrame& frame,
167 int input_buffer_index); 182 int input_buffer_index);
168 bool EncodeTexture(JNIEnv* jni, 183 bool EncodeTexture(JNIEnv* jni,
169 bool key_frame, 184 bool key_frame,
170 const webrtc::VideoFrame& frame); 185 const webrtc::VideoFrame& frame);
186 // Encodes a new style org.webrtc.VideoFrame. Might be a I420 or a texture
187 // frame.
188 bool EncodeJavaFrame(JNIEnv* jni,
189 bool key_frame,
190 jobject frame,
191 int input_buffer_index);
171 192
172 // Helper accessors for MediaCodecVideoEncoder$OutputBufferInfo members. 193 // Helper accessors for MediaCodecVideoEncoder$OutputBufferInfo members.
173 int GetOutputBufferInfoIndex(JNIEnv* jni, jobject j_output_buffer_info); 194 int GetOutputBufferInfoIndex(JNIEnv* jni, jobject j_output_buffer_info);
174 jobject GetOutputBufferInfoBuffer(JNIEnv* jni, jobject j_output_buffer_info); 195 jobject GetOutputBufferInfoBuffer(JNIEnv* jni, jobject j_output_buffer_info);
175 bool GetOutputBufferInfoIsKeyFrame(JNIEnv* jni, jobject j_output_buffer_info); 196 bool GetOutputBufferInfoIsKeyFrame(JNIEnv* jni, jobject j_output_buffer_info);
176 jlong GetOutputBufferInfoPresentationTimestampUs( 197 jlong GetOutputBufferInfoPresentationTimestampUs(
177 JNIEnv* jni, jobject j_output_buffer_info); 198 JNIEnv* jni, jobject j_output_buffer_info);
178 199
179 // Deliver any outputs pending in the MediaCodec to our |callback_| and return 200 // Deliver any outputs pending in the MediaCodec to our |callback_| and return
180 // true on success. 201 // true on success.
(...skipping 22 matching lines...) Expand all
203 // State that is constant for the lifetime of this object once the ctor 224 // State that is constant for the lifetime of this object once the ctor
204 // returns. 225 // returns.
205 rtc::SequencedTaskChecker encoder_queue_checker_; 226 rtc::SequencedTaskChecker encoder_queue_checker_;
206 ScopedGlobalRef<jclass> j_media_codec_video_encoder_class_; 227 ScopedGlobalRef<jclass> j_media_codec_video_encoder_class_;
207 ScopedGlobalRef<jobject> j_media_codec_video_encoder_; 228 ScopedGlobalRef<jobject> j_media_codec_video_encoder_;
208 jmethodID j_init_encode_method_; 229 jmethodID j_init_encode_method_;
209 jmethodID j_get_input_buffers_method_; 230 jmethodID j_get_input_buffers_method_;
210 jmethodID j_dequeue_input_buffer_method_; 231 jmethodID j_dequeue_input_buffer_method_;
211 jmethodID j_encode_buffer_method_; 232 jmethodID j_encode_buffer_method_;
212 jmethodID j_encode_texture_method_; 233 jmethodID j_encode_texture_method_;
234 jmethodID j_encode_frame_method_;
213 jmethodID j_release_method_; 235 jmethodID j_release_method_;
214 jmethodID j_set_rates_method_; 236 jmethodID j_set_rates_method_;
215 jmethodID j_dequeue_output_buffer_method_; 237 jmethodID j_dequeue_output_buffer_method_;
216 jmethodID j_release_output_buffer_method_; 238 jmethodID j_release_output_buffer_method_;
217 jfieldID j_color_format_field_; 239 jfieldID j_color_format_field_;
218 jfieldID j_info_index_field_; 240 jfieldID j_info_index_field_;
219 jfieldID j_info_buffer_field_; 241 jfieldID j_info_buffer_field_;
220 jfieldID j_info_is_key_frame_field_; 242 jfieldID j_info_is_key_frame_field_;
221 jfieldID j_info_presentation_timestamp_us_field_; 243 jfieldID j_info_presentation_timestamp_us_field_;
222 244
245 const JavaVideoFrameFactory video_frame_factory_;
246 ScopedGlobalRef<jclass> j_video_frame_texture_buffer_class_;
247
223 // State that is valid only between InitEncode() and the next Release(). 248 // State that is valid only between InitEncode() and the next Release().
224 int width_; // Frame width in pixels. 249 int width_; // Frame width in pixels.
225 int height_; // Frame height in pixels. 250 int height_; // Frame height in pixels.
226 bool inited_; 251 bool inited_;
227 bool use_surface_; 252 bool use_surface_;
228 enum libyuv::FourCC encoder_fourcc_; // Encoder color space format. 253 enum libyuv::FourCC encoder_fourcc_; // Encoder color space format.
229 int last_set_bitrate_kbps_; // Last-requested bitrate in kbps. 254 int last_set_bitrate_kbps_; // Last-requested bitrate in kbps.
230 int last_set_fps_; // Last-requested frame rate. 255 int last_set_fps_; // Last-requested frame rate.
231 int64_t current_timestamp_us_; // Current frame timestamps in us. 256 int64_t current_timestamp_us_; // Current frame timestamps in us.
232 int frames_received_; // Number of frames received by encoder. 257 int frames_received_; // Number of frames received by encoder.
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 j_media_codec_video_encoder_class_( 347 j_media_codec_video_encoder_class_(
323 jni, 348 jni,
324 FindClass(jni, "org/webrtc/MediaCodecVideoEncoder")), 349 FindClass(jni, "org/webrtc/MediaCodecVideoEncoder")),
325 j_media_codec_video_encoder_( 350 j_media_codec_video_encoder_(
326 jni, 351 jni,
327 jni->NewObject(*j_media_codec_video_encoder_class_, 352 jni->NewObject(*j_media_codec_video_encoder_class_,
328 GetMethodID(jni, 353 GetMethodID(jni,
329 *j_media_codec_video_encoder_class_, 354 *j_media_codec_video_encoder_class_,
330 "<init>", 355 "<init>",
331 "()V"))), 356 "()V"))),
357 video_frame_factory_(jni),
358 j_video_frame_texture_buffer_class_(
359 jni,
360 FindClass(jni, "org/webrtc/VideoFrame$TextureBuffer")),
332 inited_(false), 361 inited_(false),
333 use_surface_(false), 362 use_surface_(false),
334 egl_context_(egl_context), 363 egl_context_(egl_context),
335 sw_fallback_required_(false) { 364 sw_fallback_required_(false) {
336 encoder_queue_checker_.Detach(); 365 encoder_queue_checker_.Detach();
337 366
338 jclass j_output_buffer_info_class = 367 jclass j_output_buffer_info_class =
339 FindClass(jni, "org/webrtc/MediaCodecVideoEncoder$OutputBufferInfo"); 368 FindClass(jni, "org/webrtc/MediaCodecVideoEncoder$OutputBufferInfo");
340 j_init_encode_method_ = 369 j_init_encode_method_ =
341 GetMethodID(jni, *j_media_codec_video_encoder_class_, "initEncode", 370 GetMethodID(jni, *j_media_codec_video_encoder_class_, "initEncode",
342 "(Lorg/webrtc/MediaCodecVideoEncoder$VideoCodecType;" 371 "(Lorg/webrtc/MediaCodecVideoEncoder$VideoCodecType;"
343 "IIIIILorg/webrtc/EglBase14$Context;)Z"); 372 "IIIIILorg/webrtc/EglBase14$Context;)Z");
344 j_get_input_buffers_method_ = GetMethodID( 373 j_get_input_buffers_method_ = GetMethodID(
345 jni, 374 jni,
346 *j_media_codec_video_encoder_class_, 375 *j_media_codec_video_encoder_class_,
347 "getInputBuffers", 376 "getInputBuffers",
348 "()[Ljava/nio/ByteBuffer;"); 377 "()[Ljava/nio/ByteBuffer;");
349 j_dequeue_input_buffer_method_ = GetMethodID( 378 j_dequeue_input_buffer_method_ = GetMethodID(
350 jni, *j_media_codec_video_encoder_class_, "dequeueInputBuffer", "()I"); 379 jni, *j_media_codec_video_encoder_class_, "dequeueInputBuffer", "()I");
351 j_encode_buffer_method_ = GetMethodID( 380 j_encode_buffer_method_ = GetMethodID(
352 jni, *j_media_codec_video_encoder_class_, "encodeBuffer", "(ZIIJ)Z"); 381 jni, *j_media_codec_video_encoder_class_, "encodeBuffer", "(ZIIJ)Z");
353 j_encode_texture_method_ = GetMethodID( 382 j_encode_texture_method_ = GetMethodID(
354 jni, *j_media_codec_video_encoder_class_, "encodeTexture", 383 jni, *j_media_codec_video_encoder_class_, "encodeTexture",
355 "(ZI[FJ)Z"); 384 "(ZI[FJ)Z");
385 j_encode_frame_method_ =
386 GetMethodID(jni, *j_media_codec_video_encoder_class_, "encodeFrame",
387 "(JZLorg/webrtc/VideoFrame;I)Z");
356 j_release_method_ = 388 j_release_method_ =
357 GetMethodID(jni, *j_media_codec_video_encoder_class_, "release", "()V"); 389 GetMethodID(jni, *j_media_codec_video_encoder_class_, "release", "()V");
358 j_set_rates_method_ = GetMethodID( 390 j_set_rates_method_ = GetMethodID(
359 jni, *j_media_codec_video_encoder_class_, "setRates", "(II)Z"); 391 jni, *j_media_codec_video_encoder_class_, "setRates", "(II)Z");
360 j_dequeue_output_buffer_method_ = GetMethodID( 392 j_dequeue_output_buffer_method_ = GetMethodID(
361 jni, 393 jni,
362 *j_media_codec_video_encoder_class_, 394 *j_media_codec_video_encoder_class_,
363 "dequeueOutputBuffer", 395 "dequeueOutputBuffer",
364 "()Lorg/webrtc/MediaCodecVideoEncoder$OutputBufferInfo;"); 396 "()Lorg/webrtc/MediaCodecVideoEncoder$OutputBufferInfo;");
365 j_release_output_buffer_method_ = GetMethodID( 397 j_release_output_buffer_method_ = GetMethodID(
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after
729 return WEBRTC_VIDEO_CODEC_OK; 761 return WEBRTC_VIDEO_CODEC_OK;
730 } 762 }
731 consecutive_full_queue_frame_drops_ = 0; 763 consecutive_full_queue_frame_drops_ = 0;
732 764
733 rtc::scoped_refptr<webrtc::VideoFrameBuffer> input_buffer( 765 rtc::scoped_refptr<webrtc::VideoFrameBuffer> input_buffer(
734 frame.video_frame_buffer()); 766 frame.video_frame_buffer());
735 767
736 VideoFrame input_frame(input_buffer, frame.timestamp(), 768 VideoFrame input_frame(input_buffer, frame.timestamp(),
737 frame.render_time_ms(), frame.rotation()); 769 frame.render_time_ms(), frame.rotation());
738 770
739 if (!MaybeReconfigureEncoder(input_frame)) { 771 if (!MaybeReconfigureEncoder(jni, input_frame)) {
740 ALOGE << "Failed to reconfigure encoder."; 772 ALOGE << "Failed to reconfigure encoder.";
741 return WEBRTC_VIDEO_CODEC_ERROR; 773 return WEBRTC_VIDEO_CODEC_ERROR;
742 } 774 }
743 775
744 const bool key_frame = 776 const bool key_frame =
745 frame_types->front() != webrtc::kVideoFrameDelta || send_key_frame; 777 frame_types->front() != webrtc::kVideoFrameDelta || send_key_frame;
746 bool encode_status = true; 778 bool encode_status = true;
747 if (input_frame.video_frame_buffer()->type() != 779
748 webrtc::VideoFrameBuffer::Type::kNative) { 780 int j_input_buffer_index = -1;
749 int j_input_buffer_index = jni->CallIntMethod( 781 if (!use_surface_) {
750 *j_media_codec_video_encoder_, j_dequeue_input_buffer_method_); 782 j_input_buffer_index = jni->CallIntMethod(*j_media_codec_video_encoder_,
783 j_dequeue_input_buffer_method_);
751 if (CheckException(jni)) { 784 if (CheckException(jni)) {
752 ALOGE << "Exception in dequeu input buffer."; 785 ALOGE << "Exception in dequeu input buffer.";
753 return ProcessHWErrorOnEncode(); 786 return ProcessHWErrorOnEncode();
754 } 787 }
755 if (j_input_buffer_index == -1) { 788 if (j_input_buffer_index == -1) {
756 // Video codec falls behind - no input buffer available. 789 // Video codec falls behind - no input buffer available.
757 ALOGW << "Encoder drop frame - no input buffers available"; 790 ALOGW << "Encoder drop frame - no input buffers available";
758 if (frames_received_ > 1) { 791 if (frames_received_ > 1) {
759 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; 792 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_;
760 frames_dropped_media_encoder_++; 793 frames_dropped_media_encoder_++;
761 } else { 794 } else {
762 // Input buffers are not ready after codec initialization, HW is still 795 // Input buffers are not ready after codec initialization, HW is still
763 // allocating thme - this is expected and should not result in drop 796 // allocating thme - this is expected and should not result in drop
764 // frame report. 797 // frame report.
765 frames_received_ = 0; 798 frames_received_ = 0;
766 } 799 }
767 return WEBRTC_VIDEO_CODEC_OK; // TODO(fischman): see webrtc bug 2887. 800 return WEBRTC_VIDEO_CODEC_OK; // TODO(fischman): see webrtc bug 2887.
768 } else if (j_input_buffer_index == -2) { 801 } else if (j_input_buffer_index == -2) {
769 return ProcessHWErrorOnEncode(); 802 return ProcessHWErrorOnEncode();
770 } 803 }
804 }
805
806 if (input_frame.video_frame_buffer()->type() !=
807 webrtc::VideoFrameBuffer::Type::kNative) {
771 encode_status = 808 encode_status =
772 EncodeByteBuffer(jni, key_frame, input_frame, j_input_buffer_index); 809 EncodeByteBuffer(jni, key_frame, input_frame, j_input_buffer_index);
773 } else { 810 } else {
774 encode_status = EncodeTexture(jni, key_frame, input_frame); 811 AndroidVideoFrameBuffer* android_buffer =
812 static_cast<AndroidVideoFrameBuffer*>(
813 input_frame.video_frame_buffer().get());
814 switch (android_buffer->android_type()) {
815 case AndroidVideoFrameBuffer::AndroidType::kTextureBuffer:
816 encode_status = EncodeTexture(jni, key_frame, input_frame);
817 break;
818 case AndroidVideoFrameBuffer::AndroidType::kJavaBuffer:
819 encode_status = EncodeJavaFrame(
820 jni, key_frame, video_frame_factory_.ToJavaFrame(jni, input_frame),
821 j_input_buffer_index);
822 break;
823 default:
824 RTC_NOTREACHED();
825 return WEBRTC_VIDEO_CODEC_ERROR;
826 }
775 } 827 }
776 828
777 if (!encode_status) { 829 if (!encode_status) {
778 ALOGE << "Failed encode frame with timestamp: " << input_frame.timestamp(); 830 ALOGE << "Failed encode frame with timestamp: " << input_frame.timestamp();
779 return ProcessHWErrorOnEncode(); 831 return ProcessHWErrorOnEncode();
780 } 832 }
781 833
782 // Save input image timestamps for later output. 834 // Save input image timestamps for later output.
783 input_frame_infos_.emplace_back(frame_input_time_ms, input_frame.timestamp(), 835 input_frame_infos_.emplace_back(frame_input_time_ms, input_frame.timestamp(),
784 input_frame.render_time_ms(), 836 input_frame.render_time_ms(),
(...skipping 10 matching lines...) Expand all
795 kMediaCodecPollMs); 847 kMediaCodecPollMs);
796 } 848 }
797 849
798 if (!DeliverPendingOutputs(jni)) { 850 if (!DeliverPendingOutputs(jni)) {
799 return ProcessHWErrorOnEncode(); 851 return ProcessHWErrorOnEncode();
800 } 852 }
801 return WEBRTC_VIDEO_CODEC_OK; 853 return WEBRTC_VIDEO_CODEC_OK;
802 } 854 }
803 855
804 bool MediaCodecVideoEncoder::MaybeReconfigureEncoder( 856 bool MediaCodecVideoEncoder::MaybeReconfigureEncoder(
857 JNIEnv* jni,
805 const webrtc::VideoFrame& frame) { 858 const webrtc::VideoFrame& frame) {
806 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_checker_); 859 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_checker_);
807 860
808 const bool reconfigure_due_to_format = frame.is_texture() != use_surface_; 861 bool is_texture = IsTextureFrame(jni, frame);
862 const bool reconfigure_due_to_format = is_texture != use_surface_;
809 const bool reconfigure_due_to_size = 863 const bool reconfigure_due_to_size =
810 frame.width() != width_ || frame.height() != height_; 864 frame.width() != width_ || frame.height() != height_;
811 865
812 if (reconfigure_due_to_format) { 866 if (reconfigure_due_to_format) {
813 ALOGD << "Reconfigure encoder due to format change. " 867 ALOGD << "Reconfigure encoder due to format change. "
814 << (use_surface_ ? 868 << (use_surface_ ?
815 "Reconfiguring to encode from byte buffer." : 869 "Reconfiguring to encode from byte buffer." :
816 "Reconfiguring to encode from texture."); 870 "Reconfiguring to encode from texture.");
817 LogStatistics(true); 871 LogStatistics(true);
818 } 872 }
819 if (reconfigure_due_to_size) { 873 if (reconfigure_due_to_size) {
820 ALOGW << "Reconfigure encoder due to frame resolution change from " 874 ALOGW << "Reconfigure encoder due to frame resolution change from "
821 << width_ << " x " << height_ << " to " << frame.width() << " x " 875 << width_ << " x " << height_ << " to " << frame.width() << " x "
822 << frame.height(); 876 << frame.height();
823 LogStatistics(true); 877 LogStatistics(true);
824 width_ = frame.width(); 878 width_ = frame.width();
825 height_ = frame.height(); 879 height_ = frame.height();
826 } 880 }
827 881
828 if (!reconfigure_due_to_format && !reconfigure_due_to_size) 882 if (!reconfigure_due_to_format && !reconfigure_due_to_size)
829 return true; 883 return true;
830 884
831 Release(); 885 Release();
832 886
833 return InitEncodeInternal(width_, height_, 0, 0, frame.is_texture()) == 887 return InitEncodeInternal(width_, height_, 0, 0, is_texture) ==
834 WEBRTC_VIDEO_CODEC_OK; 888 WEBRTC_VIDEO_CODEC_OK;
835 } 889 }
836 890
891 bool MediaCodecVideoEncoder::IsTextureFrame(JNIEnv* jni,
892 const webrtc::VideoFrame& frame) {
893 if (frame.video_frame_buffer()->type() !=
894 webrtc::VideoFrameBuffer::Type::kNative) {
895 return false;
896 }
897
898 AndroidVideoFrameBuffer* android_buffer =
899 static_cast<AndroidVideoFrameBuffer*>(frame.video_frame_buffer().get());
900 switch (android_buffer->android_type()) {
901 case AndroidVideoFrameBuffer::AndroidType::kTextureBuffer:
902 return true;
903 case AndroidVideoFrameBuffer::AndroidType::kJavaBuffer:
904 return jni->IsInstanceOf(static_cast<AndroidVideoBuffer*>(android_buffer)
905 ->video_frame_buffer(),
906 *j_video_frame_texture_buffer_class_);
907 default:
908 RTC_NOTREACHED();
909 return false;
910 }
911 }
912
837 bool MediaCodecVideoEncoder::EncodeByteBuffer(JNIEnv* jni, 913 bool MediaCodecVideoEncoder::EncodeByteBuffer(JNIEnv* jni,
838 bool key_frame, 914 bool key_frame,
839 const webrtc::VideoFrame& frame, 915 const webrtc::VideoFrame& frame,
840 int input_buffer_index) { 916 int input_buffer_index) {
841 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_checker_); 917 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_checker_);
842 RTC_CHECK(!use_surface_); 918 RTC_CHECK(!use_surface_);
843 919
920 rtc::scoped_refptr<webrtc::I420BufferInterface> i420_buffer =
921 frame.video_frame_buffer()->ToI420();
922 if (!FillInputBuffer(jni, input_buffer_index, i420_buffer->DataY(),
923 i420_buffer->StrideY(), i420_buffer->DataU(),
924 i420_buffer->StrideU(), i420_buffer->DataV(),
925 i420_buffer->StrideV())) {
926 return false;
927 }
928 bool encode_status = jni->CallBooleanMethod(
929 *j_media_codec_video_encoder_, j_encode_buffer_method_, key_frame,
930 input_buffer_index, yuv_size_, current_timestamp_us_);
931 if (CheckException(jni)) {
932 ALOGE << "Exception in encode buffer.";
933 ProcessHWError(true /* reset_if_fallback_unavailable */);
934 return false;
935 }
936 return encode_status;
937 }
938
939 bool MediaCodecVideoEncoder::FillInputBuffer(JNIEnv* jni,
940 int input_buffer_index,
941 uint8_t const* buffer_y,
942 int stride_y,
943 uint8_t const* buffer_u,
944 int stride_u,
945 uint8_t const* buffer_v,
946 int stride_v) {
844 jobject j_input_buffer = input_buffers_[input_buffer_index]; 947 jobject j_input_buffer = input_buffers_[input_buffer_index];
845 uint8_t* yuv_buffer = 948 uint8_t* yuv_buffer =
846 reinterpret_cast<uint8_t*>(jni->GetDirectBufferAddress(j_input_buffer)); 949 reinterpret_cast<uint8_t*>(jni->GetDirectBufferAddress(j_input_buffer));
847 if (CheckException(jni)) { 950 if (CheckException(jni)) {
848 ALOGE << "Exception in get direct buffer address."; 951 ALOGE << "Exception in get direct buffer address.";
849 ProcessHWError(true /* reset_if_fallback_unavailable */); 952 ProcessHWError(true /* reset_if_fallback_unavailable */);
850 return false; 953 return false;
851 } 954 }
852 RTC_CHECK(yuv_buffer) << "Indirect buffer??"; 955 RTC_CHECK(yuv_buffer) << "Indirect buffer??";
853 rtc::scoped_refptr<webrtc::I420BufferInterface> i420_buffer = 956
854 frame.video_frame_buffer()->ToI420(); 957 RTC_CHECK(!libyuv::ConvertFromI420(buffer_y, stride_y, buffer_u, stride_u,
855 RTC_CHECK(!libyuv::ConvertFromI420( 958 buffer_v, stride_v, yuv_buffer, width_,
856 i420_buffer->DataY(), i420_buffer->StrideY(), i420_buffer->DataU(), 959 width_, height_, encoder_fourcc_))
857 i420_buffer->StrideU(), i420_buffer->DataV(), i420_buffer->StrideV(),
858 yuv_buffer, width_, width_, height_, encoder_fourcc_))
859 << "ConvertFromI420 failed"; 960 << "ConvertFromI420 failed";
860 961 return true;
861 bool encode_status = jni->CallBooleanMethod(*j_media_codec_video_encoder_,
862 j_encode_buffer_method_,
863 key_frame,
864 input_buffer_index,
865 yuv_size_,
866 current_timestamp_us_);
867 if (CheckException(jni)) {
868 ALOGE << "Exception in encode buffer.";
869 ProcessHWError(true /* reset_if_fallback_unavailable */);
870 return false;
871 }
872 return encode_status;
873 } 962 }
874 963
875 bool MediaCodecVideoEncoder::EncodeTexture(JNIEnv* jni, 964 bool MediaCodecVideoEncoder::EncodeTexture(JNIEnv* jni,
876 bool key_frame, 965 bool key_frame,
877 const webrtc::VideoFrame& frame) { 966 const webrtc::VideoFrame& frame) {
878 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_checker_); 967 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_checker_);
879 RTC_CHECK(use_surface_); 968 RTC_CHECK(use_surface_);
880 NativeHandleImpl handle = 969 NativeHandleImpl handle =
881 static_cast<AndroidTextureBuffer*>(frame.video_frame_buffer().get()) 970 static_cast<AndroidTextureBuffer*>(frame.video_frame_buffer().get())
882 ->native_handle_impl(); 971 ->native_handle_impl();
883 972
884 jfloatArray sampling_matrix = handle.sampling_matrix.ToJava(jni); 973 jfloatArray sampling_matrix = handle.sampling_matrix.ToJava(jni);
885 bool encode_status = jni->CallBooleanMethod( 974 bool encode_status = jni->CallBooleanMethod(
886 *j_media_codec_video_encoder_, j_encode_texture_method_, key_frame, 975 *j_media_codec_video_encoder_, j_encode_texture_method_, key_frame,
887 handle.oes_texture_id, sampling_matrix, current_timestamp_us_); 976 handle.oes_texture_id, sampling_matrix, current_timestamp_us_);
888 if (CheckException(jni)) { 977 if (CheckException(jni)) {
889 ALOGE << "Exception in encode texture."; 978 ALOGE << "Exception in encode texture.";
890 ProcessHWError(true /* reset_if_fallback_unavailable */); 979 ProcessHWError(true /* reset_if_fallback_unavailable */);
891 return false; 980 return false;
892 } 981 }
893 return encode_status; 982 return encode_status;
894 } 983 }
895 984
985 bool MediaCodecVideoEncoder::EncodeJavaFrame(JNIEnv* jni,
986 bool key_frame,
987 jobject frame,
988 int input_buffer_index) {
989 bool encode_status = jni->CallBooleanMethod(
990 *j_media_codec_video_encoder_, j_encode_frame_method_,
991 jlongFromPointer(this), key_frame, frame, input_buffer_index);
992 if (CheckException(jni)) {
993 ALOGE << "Exception in encode frame.";
994 ProcessHWError(true /* reset_if_fallback_unavailable */);
995 return false;
996 }
997 return encode_status;
998 }
999
896 int32_t MediaCodecVideoEncoder::RegisterEncodeCompleteCallback( 1000 int32_t MediaCodecVideoEncoder::RegisterEncodeCompleteCallback(
897 webrtc::EncodedImageCallback* callback) { 1001 webrtc::EncodedImageCallback* callback) {
898 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_checker_); 1002 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_checker_);
899 JNIEnv* jni = AttachCurrentThreadIfNeeded(); 1003 JNIEnv* jni = AttachCurrentThreadIfNeeded();
900 ScopedLocalRefFrame local_ref_frame(jni); 1004 ScopedLocalRefFrame local_ref_frame(jni);
901 callback_ = callback; 1005 callback_ = callback;
902 return WEBRTC_VIDEO_CODEC_OK; 1006 return WEBRTC_VIDEO_CODEC_OK;
903 } 1007 }
904 1008
905 int32_t MediaCodecVideoEncoder::Release() { 1009 int32_t MediaCodecVideoEncoder::Release() {
(...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after
1366 return supported_codecs_; 1470 return supported_codecs_;
1367 } 1471 }
1368 } 1472 }
1369 1473
1370 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder( 1474 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder(
1371 webrtc::VideoEncoder* encoder) { 1475 webrtc::VideoEncoder* encoder) {
1372 ALOGD << "Destroy video encoder."; 1476 ALOGD << "Destroy video encoder.";
1373 delete encoder; 1477 delete encoder;
1374 } 1478 }
1375 1479
1480 JOW(void, MediaCodecVideoEncoder_nativeFillBuffer)
1481 (JNIEnv* jni,
1482 jlong native_encoder,
1483 jint input_buffer,
1484 jobject j_buffer_y,
1485 jint stride_y,
1486 jobject j_buffer_u,
1487 jint stride_u,
1488 jobject j_buffer_v,
1489 jint stride_v) {
1490 uint8_t* buffer_y =
1491 static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_buffer_y));
1492 uint8_t* buffer_u =
1493 static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_buffer_u));
1494 uint8_t* buffer_v =
1495 static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_buffer_v));
1496
1497 reinterpret_cast<MediaCodecVideoEncoder*>(native_encoder)
1498 ->FillInputBuffer(jni, input_buffer, buffer_y, stride_y, buffer_u,
1499 stride_u, buffer_v, stride_v);
1500 }
1501
1376 } // namespace webrtc_jni 1502 } // namespace webrtc_jni
OLDNEW
« no previous file with comments | « webrtc/sdk/android/api/org/webrtc/MediaCodecVideoEncoder.java ('k') | webrtc/sdk/android/src/jni/classreferenceholder.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698