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

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

Issue 1403713002: MediaCodecVideoEncoder add support to encode from textures (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Fixed tests Created 5 years, 1 month 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 11 matching lines...) Expand all
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 * 26 *
27 */ 27 */
28 28
29 #include "talk/app/webrtc/java/jni/androidmediaencoder_jni.h" 29 #include "talk/app/webrtc/java/jni/androidmediaencoder_jni.h"
30 #include "talk/app/webrtc/java/jni/classreferenceholder.h" 30 #include "talk/app/webrtc/java/jni/classreferenceholder.h"
31 #include "talk/app/webrtc/java/jni/androidmediacodeccommon.h" 31 #include "talk/app/webrtc/java/jni/androidmediacodeccommon.h"
32 #include "talk/app/webrtc/java/jni/native_handle_impl.h"
32 #include "webrtc/base/bind.h" 33 #include "webrtc/base/bind.h"
33 #include "webrtc/base/checks.h" 34 #include "webrtc/base/checks.h"
34 #include "webrtc/base/logging.h" 35 #include "webrtc/base/logging.h"
35 #include "webrtc/base/thread.h" 36 #include "webrtc/base/thread.h"
36 #include "webrtc/base/thread_checker.h" 37 #include "webrtc/base/thread_checker.h"
37 #include "webrtc/modules/rtp_rtcp/source/h264_bitstream_parser.h" 38 #include "webrtc/modules/rtp_rtcp/source/h264_bitstream_parser.h"
38 #include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h" 39 #include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h"
39 #include "webrtc/modules/video_coding/utility/include/quality_scaler.h" 40 #include "webrtc/modules/video_coding/utility/include/quality_scaler.h"
40 #include "webrtc/modules/video_coding/utility/include/vp8_header_parser.h" 41 #include "webrtc/modules/video_coding/utility/include/vp8_header_parser.h"
41 #include "webrtc/system_wrappers/include/field_trial.h" 42 #include "webrtc/system_wrappers/include/field_trial.h"
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 // Android's MediaCodec SDK API behind the scenes to implement (hopefully) 75 // Android's MediaCodec SDK API behind the scenes to implement (hopefully)
75 // HW-backed video encode. This C++ class is implemented as a very thin shim, 76 // HW-backed video encode. This C++ class is implemented as a very thin shim,
76 // delegating all of the interesting work to org.webrtc.MediaCodecVideoEncoder. 77 // delegating all of the interesting work to org.webrtc.MediaCodecVideoEncoder.
77 // MediaCodecVideoEncoder is created, operated, and destroyed on a single 78 // MediaCodecVideoEncoder is created, operated, and destroyed on a single
78 // thread, currently the libjingle Worker thread. 79 // thread, currently the libjingle Worker thread.
79 class MediaCodecVideoEncoder : public webrtc::VideoEncoder, 80 class MediaCodecVideoEncoder : public webrtc::VideoEncoder,
80 public rtc::MessageHandler { 81 public rtc::MessageHandler {
81 public: 82 public:
82 virtual ~MediaCodecVideoEncoder(); 83 virtual ~MediaCodecVideoEncoder();
83 MediaCodecVideoEncoder(JNIEnv* jni, 84 MediaCodecVideoEncoder(JNIEnv* jni,
84 VideoCodecType codecType); 85 VideoCodecType codecType,
86 jobject egl_context);
85 87
86 // webrtc::VideoEncoder implementation. Everything trampolines to 88 // webrtc::VideoEncoder implementation. Everything trampolines to
87 // |codec_thread_| for execution. 89 // |codec_thread_| for execution.
88 int32_t InitEncode(const webrtc::VideoCodec* codec_settings, 90 int32_t InitEncode(const webrtc::VideoCodec* codec_settings,
89 int32_t /* number_of_cores */, 91 int32_t /* number_of_cores */,
90 size_t /* max_payload_size */) override; 92 size_t /* max_payload_size */) override;
91 int32_t Encode(const webrtc::VideoFrame& input_image, 93 int32_t Encode(const webrtc::VideoFrame& input_image,
92 const webrtc::CodecSpecificInfo* /* codec_specific_info */, 94 const webrtc::CodecSpecificInfo* /* codec_specific_info */,
93 const std::vector<webrtc::FrameType>* frame_types) override; 95 const std::vector<webrtc::FrameType>* frame_types) override;
94 int32_t RegisterEncodeCompleteCallback( 96 int32_t RegisterEncodeCompleteCallback(
95 webrtc::EncodedImageCallback* callback) override; 97 webrtc::EncodedImageCallback* callback) override;
96 int32_t Release() override; 98 int32_t Release() override;
97 int32_t SetChannelParameters(uint32_t /* packet_loss */, 99 int32_t SetChannelParameters(uint32_t /* packet_loss */,
98 int64_t /* rtt */) override; 100 int64_t /* rtt */) override;
99 int32_t SetRates(uint32_t new_bit_rate, uint32_t frame_rate) override; 101 int32_t SetRates(uint32_t new_bit_rate, uint32_t frame_rate) override;
100 102
101 // rtc::MessageHandler implementation. 103 // rtc::MessageHandler implementation.
102 void OnMessage(rtc::Message* msg) override; 104 void OnMessage(rtc::Message* msg) override;
103 105
104 void OnDroppedFrame() override; 106 void OnDroppedFrame() override;
105 107
106 int GetTargetFramerate() override; 108 int GetTargetFramerate() override;
107 109
110 bool SupportsNativeHandle() const override { return true; }
111
108 private: 112 private:
109 // ResetCodecOnCodecThread() calls ReleaseOnCodecThread() and 113 // ResetCodecOnCodecThread() calls ReleaseOnCodecThread() and
110 // InitEncodeOnCodecThread() in an attempt to restore the codec to an 114 // InitEncodeOnCodecThread() in an attempt to restore the codec to an
111 // operable state. Necessary after all manner of OMX-layer errors. 115 // operable state. Necessary after all manner of OMX-layer errors.
112 bool ResetCodecOnCodecThread(); 116 bool ResetCodecOnCodecThread();
113 117
114 // Implementation of webrtc::VideoEncoder methods above, all running on the 118 // Implementation of webrtc::VideoEncoder methods above, all running on the
115 // codec thread exclusively. 119 // codec thread exclusively.
116 // 120 //
117 // If width==0 then this is assumed to be a re-initialization and the 121 // If width==0 then this is assumed to be a re-initialization and the
118 // previously-current values are reused instead of the passed parameters 122 // previously-current values are reused instead of the passed parameters
119 // (makes it easier to reason about thread-safety). 123 // (makes it easier to reason about thread-safety).
120 int32_t InitEncodeOnCodecThread(int width, int height, int kbps, int fps); 124 int32_t InitEncodeOnCodecThread(int width, int height, int kbps, int fps,
121 // Reconfigure to match |frame| in width, height. Returns false if 125 bool use_surface);
122 // reconfiguring fails. 126 // Reconfigure to match |frame| in width, height. Also reconfigures the
127 // encoder if |frame| is a texture/byte buffer and the encoder is initialized
128 // for byte buffer/texture. Returns false if reconfiguring fails.
123 bool MaybeReconfigureEncoderOnCodecThread(const webrtc::VideoFrame& frame); 129 bool MaybeReconfigureEncoderOnCodecThread(const webrtc::VideoFrame& frame);
124 int32_t EncodeOnCodecThread( 130 int32_t EncodeOnCodecThread(
125 const webrtc::VideoFrame& input_image, 131 const webrtc::VideoFrame& input_image,
126 const std::vector<webrtc::FrameType>* frame_types); 132 const std::vector<webrtc::FrameType>* frame_types);
127 bool EncodeByteBufferOnCodecThread(JNIEnv* jni, 133 bool EncodeByteBufferOnCodecThread(JNIEnv* jni,
128 bool key_frame, const webrtc::VideoFrame& frame, int input_buffer_index); 134 bool key_frame, const webrtc::VideoFrame& frame, int input_buffer_index);
135 bool EncodeTextureOnCodecThread(JNIEnv* jni,
136 bool key_frame, const webrtc::VideoFrame& frame);
129 137
130 int32_t RegisterEncodeCompleteCallbackOnCodecThread( 138 int32_t RegisterEncodeCompleteCallbackOnCodecThread(
131 webrtc::EncodedImageCallback* callback); 139 webrtc::EncodedImageCallback* callback);
132 int32_t ReleaseOnCodecThread(); 140 int32_t ReleaseOnCodecThread();
133 int32_t SetRatesOnCodecThread(uint32_t new_bit_rate, uint32_t frame_rate); 141 int32_t SetRatesOnCodecThread(uint32_t new_bit_rate, uint32_t frame_rate);
134 142
135 // Helper accessors for MediaCodecVideoEncoder$OutputBufferInfo members. 143 // Helper accessors for MediaCodecVideoEncoder$OutputBufferInfo members.
136 int GetOutputBufferInfoIndex(JNIEnv* jni, jobject j_output_buffer_info); 144 int GetOutputBufferInfoIndex(JNIEnv* jni, jobject j_output_buffer_info);
137 jobject GetOutputBufferInfoBuffer(JNIEnv* jni, jobject j_output_buffer_info); 145 jobject GetOutputBufferInfoBuffer(JNIEnv* jni, jobject j_output_buffer_info);
138 bool GetOutputBufferInfoIsKeyFrame(JNIEnv* jni, jobject j_output_buffer_info); 146 bool GetOutputBufferInfoIsKeyFrame(JNIEnv* jni, jobject j_output_buffer_info);
(...skipping 17 matching lines...) Expand all
156 // State that is constant for the lifetime of this object once the ctor 164 // State that is constant for the lifetime of this object once the ctor
157 // returns. 165 // returns.
158 scoped_ptr<Thread> codec_thread_; // Thread on which to operate MediaCodec. 166 scoped_ptr<Thread> codec_thread_; // Thread on which to operate MediaCodec.
159 rtc::ThreadChecker codec_thread_checker_; 167 rtc::ThreadChecker codec_thread_checker_;
160 ScopedGlobalRef<jclass> j_media_codec_video_encoder_class_; 168 ScopedGlobalRef<jclass> j_media_codec_video_encoder_class_;
161 ScopedGlobalRef<jobject> j_media_codec_video_encoder_; 169 ScopedGlobalRef<jobject> j_media_codec_video_encoder_;
162 jmethodID j_init_encode_method_; 170 jmethodID j_init_encode_method_;
163 jmethodID j_get_input_buffers_method_; 171 jmethodID j_get_input_buffers_method_;
164 jmethodID j_dequeue_input_buffer_method_; 172 jmethodID j_dequeue_input_buffer_method_;
165 jmethodID j_encode_buffer_method_; 173 jmethodID j_encode_buffer_method_;
174 jmethodID j_encode_texture_method_;
166 jmethodID j_release_method_; 175 jmethodID j_release_method_;
167 jmethodID j_set_rates_method_; 176 jmethodID j_set_rates_method_;
168 jmethodID j_dequeue_output_buffer_method_; 177 jmethodID j_dequeue_output_buffer_method_;
169 jmethodID j_release_output_buffer_method_; 178 jmethodID j_release_output_buffer_method_;
170 jfieldID j_color_format_field_; 179 jfieldID j_color_format_field_;
171 jfieldID j_info_index_field_; 180 jfieldID j_info_index_field_;
172 jfieldID j_info_buffer_field_; 181 jfieldID j_info_buffer_field_;
173 jfieldID j_info_is_key_frame_field_; 182 jfieldID j_info_is_key_frame_field_;
174 jfieldID j_info_presentation_timestamp_us_field_; 183 jfieldID j_info_presentation_timestamp_us_field_;
175 184
176 // State that is valid only between InitEncode() and the next Release(). 185 // State that is valid only between InitEncode() and the next Release().
177 // Touched only on codec_thread_ so no explicit synchronization necessary. 186 // Touched only on codec_thread_ so no explicit synchronization necessary.
178 int width_; // Frame width in pixels. 187 int width_; // Frame width in pixels.
179 int height_; // Frame height in pixels. 188 int height_; // Frame height in pixels.
180 bool inited_; 189 bool inited_;
190 bool use_surface_;
181 uint16_t picture_id_; 191 uint16_t picture_id_;
182 enum libyuv::FourCC encoder_fourcc_; // Encoder color space format. 192 enum libyuv::FourCC encoder_fourcc_; // Encoder color space format.
183 int last_set_bitrate_kbps_; // Last-requested bitrate in kbps. 193 int last_set_bitrate_kbps_; // Last-requested bitrate in kbps.
184 int last_set_fps_; // Last-requested frame rate. 194 int last_set_fps_; // Last-requested frame rate.
185 int64_t current_timestamp_us_; // Current frame timestamps in us. 195 int64_t current_timestamp_us_; // Current frame timestamps in us.
186 int frames_received_; // Number of frames received by encoder. 196 int frames_received_; // Number of frames received by encoder.
187 int frames_encoded_; // Number of frames encoded by encoder. 197 int frames_encoded_; // Number of frames encoded by encoder.
188 int frames_dropped_; // Number of frames dropped by encoder. 198 int frames_dropped_; // Number of frames dropped by encoder.
189 int frames_in_queue_; // Number of frames in encoder queue. 199 int frames_in_queue_; // Number of frames in encoder queue.
190 int64_t start_time_ms_; // Start time for statistics. 200 int64_t start_time_ms_; // Start time for statistics.
(...skipping 15 matching lines...) Expand all
206 // and the next Encode() call being ignored. 216 // and the next Encode() call being ignored.
207 bool drop_next_input_frame_; 217 bool drop_next_input_frame_;
208 // Global references; must be deleted in Release(). 218 // Global references; must be deleted in Release().
209 std::vector<jobject> input_buffers_; 219 std::vector<jobject> input_buffers_;
210 webrtc::QualityScaler quality_scaler_; 220 webrtc::QualityScaler quality_scaler_;
211 // Dynamic resolution change, off by default. 221 // Dynamic resolution change, off by default.
212 bool scale_; 222 bool scale_;
213 223
214 // H264 bitstream parser, used to extract QP from encoded bitstreams. 224 // H264 bitstream parser, used to extract QP from encoded bitstreams.
215 webrtc::H264BitstreamParser h264_bitstream_parser_; 225 webrtc::H264BitstreamParser h264_bitstream_parser_;
226
227 // EGL context - owned by factory, should not be allocated/destroyed
228 // by MediaCodecVideoEncoder.
229 jobject egl_context_;
216 }; 230 };
217 231
218 MediaCodecVideoEncoder::~MediaCodecVideoEncoder() { 232 MediaCodecVideoEncoder::~MediaCodecVideoEncoder() {
219 // Call Release() to ensure no more callbacks to us after we are deleted. 233 // Call Release() to ensure no more callbacks to us after we are deleted.
220 Release(); 234 Release();
221 } 235 }
222 236
223 MediaCodecVideoEncoder::MediaCodecVideoEncoder( 237 MediaCodecVideoEncoder::MediaCodecVideoEncoder(
224 JNIEnv* jni, VideoCodecType codecType) : 238 JNIEnv* jni, VideoCodecType codecType, jobject egl_context) :
225 codecType_(codecType), 239 codecType_(codecType),
226 callback_(NULL), 240 callback_(NULL),
227 inited_(false), 241 inited_(false),
242 use_surface_(false),
228 picture_id_(0), 243 picture_id_(0),
229 codec_thread_(new Thread()), 244 codec_thread_(new Thread()),
230 j_media_codec_video_encoder_class_( 245 j_media_codec_video_encoder_class_(
231 jni, 246 jni,
232 FindClass(jni, "org/webrtc/MediaCodecVideoEncoder")), 247 FindClass(jni, "org/webrtc/MediaCodecVideoEncoder")),
233 j_media_codec_video_encoder_( 248 j_media_codec_video_encoder_(
234 jni, 249 jni,
235 jni->NewObject(*j_media_codec_video_encoder_class_, 250 jni->NewObject(*j_media_codec_video_encoder_class_,
236 GetMethodID(jni, 251 GetMethodID(jni,
237 *j_media_codec_video_encoder_class_, 252 *j_media_codec_video_encoder_class_,
238 "<init>", 253 "<init>",
239 "()V"))) { 254 "()V"))),
255 egl_context_(egl_context) {
240 ScopedLocalRefFrame local_ref_frame(jni); 256 ScopedLocalRefFrame local_ref_frame(jni);
241 // It would be nice to avoid spinning up a new thread per MediaCodec, and 257 // It would be nice to avoid spinning up a new thread per MediaCodec, and
242 // instead re-use e.g. the PeerConnectionFactory's |worker_thread_|, but bug 258 // instead re-use e.g. the PeerConnectionFactory's |worker_thread_|, but bug
243 // 2732 means that deadlocks abound. This class synchronously trampolines 259 // 2732 means that deadlocks abound. This class synchronously trampolines
244 // to |codec_thread_|, so if anything else can be coming to _us_ from 260 // to |codec_thread_|, so if anything else can be coming to _us_ from
245 // |codec_thread_|, or from any thread holding the |_sendCritSect| described 261 // |codec_thread_|, or from any thread holding the |_sendCritSect| described
246 // in the bug, we have a problem. For now work around that with a dedicated 262 // in the bug, we have a problem. For now work around that with a dedicated
247 // thread. 263 // thread.
248 codec_thread_->SetName("MediaCodecVideoEncoder", NULL); 264 codec_thread_->SetName("MediaCodecVideoEncoder", NULL);
249 RTC_CHECK(codec_thread_->Start()) << "Failed to start MediaCodecVideoEncoder"; 265 RTC_CHECK(codec_thread_->Start()) << "Failed to start MediaCodecVideoEncoder";
250 codec_thread_checker_.DetachFromThread(); 266 codec_thread_checker_.DetachFromThread();
251 jclass j_output_buffer_info_class = 267 jclass j_output_buffer_info_class =
252 FindClass(jni, "org/webrtc/MediaCodecVideoEncoder$OutputBufferInfo"); 268 FindClass(jni, "org/webrtc/MediaCodecVideoEncoder$OutputBufferInfo");
253 j_init_encode_method_ = GetMethodID( 269 j_init_encode_method_ = GetMethodID(
254 jni, 270 jni,
255 *j_media_codec_video_encoder_class_, 271 *j_media_codec_video_encoder_class_,
256 "initEncode", 272 "initEncode",
257 "(Lorg/webrtc/MediaCodecVideoEncoder$VideoCodecType;IIII)Z"); 273 "(Lorg/webrtc/MediaCodecVideoEncoder$VideoCodecType;"
274 "IIIILjavax/microedition/khronos/egl/EGLContext;)Z");
258 j_get_input_buffers_method_ = GetMethodID( 275 j_get_input_buffers_method_ = GetMethodID(
259 jni, 276 jni,
260 *j_media_codec_video_encoder_class_, 277 *j_media_codec_video_encoder_class_,
261 "getInputBuffers", 278 "getInputBuffers",
262 "()[Ljava/nio/ByteBuffer;"); 279 "()[Ljava/nio/ByteBuffer;");
263 j_dequeue_input_buffer_method_ = GetMethodID( 280 j_dequeue_input_buffer_method_ = GetMethodID(
264 jni, *j_media_codec_video_encoder_class_, "dequeueInputBuffer", "()I"); 281 jni, *j_media_codec_video_encoder_class_, "dequeueInputBuffer", "()I");
265 j_encode_buffer_method_ = GetMethodID( 282 j_encode_buffer_method_ = GetMethodID(
266 jni, *j_media_codec_video_encoder_class_, "encodeBuffer", "(ZIIJ)Z"); 283 jni, *j_media_codec_video_encoder_class_, "encodeBuffer", "(ZIIJ)Z");
284 j_encode_texture_method_ = GetMethodID(
285 jni, *j_media_codec_video_encoder_class_, "encodeTexture",
286 "(ZI[FJ)Z");
267 j_release_method_ = 287 j_release_method_ =
268 GetMethodID(jni, *j_media_codec_video_encoder_class_, "release", "()V"); 288 GetMethodID(jni, *j_media_codec_video_encoder_class_, "release", "()V");
269 j_set_rates_method_ = GetMethodID( 289 j_set_rates_method_ = GetMethodID(
270 jni, *j_media_codec_video_encoder_class_, "setRates", "(II)Z"); 290 jni, *j_media_codec_video_encoder_class_, "setRates", "(II)Z");
271 j_dequeue_output_buffer_method_ = GetMethodID( 291 j_dequeue_output_buffer_method_ = GetMethodID(
272 jni, 292 jni,
273 *j_media_codec_video_encoder_class_, 293 *j_media_codec_video_encoder_class_,
274 "dequeueOutputBuffer", 294 "dequeueOutputBuffer",
275 "()Lorg/webrtc/MediaCodecVideoEncoder$OutputBufferInfo;"); 295 "()Lorg/webrtc/MediaCodecVideoEncoder$OutputBufferInfo;");
276 j_release_output_buffer_method_ = GetMethodID( 296 j_release_output_buffer_method_ = GetMethodID(
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
336 } 356 }
337 quality_scaler_.SetMinResolution(kMinWidth, kMinHeight); 357 quality_scaler_.SetMinResolution(kMinWidth, kMinHeight);
338 quality_scaler_.ReportFramerate(codec_settings->maxFramerate); 358 quality_scaler_.ReportFramerate(codec_settings->maxFramerate);
339 } 359 }
340 return codec_thread_->Invoke<int32_t>( 360 return codec_thread_->Invoke<int32_t>(
341 Bind(&MediaCodecVideoEncoder::InitEncodeOnCodecThread, 361 Bind(&MediaCodecVideoEncoder::InitEncodeOnCodecThread,
342 this, 362 this,
343 codec_settings->width, 363 codec_settings->width,
344 codec_settings->height, 364 codec_settings->height,
345 codec_settings->startBitrate, 365 codec_settings->startBitrate,
346 codec_settings->maxFramerate)); 366 codec_settings->maxFramerate,
367 false /*use_surface*/));
magjed_webrtc 2015/11/18 13:12:52 /* use_surface */
perkj_webrtc 2015/11/18 14:51:21 Done.
347 } 368 }
348 369
349 int32_t MediaCodecVideoEncoder::Encode( 370 int32_t MediaCodecVideoEncoder::Encode(
350 const webrtc::VideoFrame& frame, 371 const webrtc::VideoFrame& frame,
351 const webrtc::CodecSpecificInfo* /* codec_specific_info */, 372 const webrtc::CodecSpecificInfo* /* codec_specific_info */,
352 const std::vector<webrtc::FrameType>* frame_types) { 373 const std::vector<webrtc::FrameType>* frame_types) {
353 return codec_thread_->Invoke<int32_t>(Bind( 374 return codec_thread_->Invoke<int32_t>(Bind(
354 &MediaCodecVideoEncoder::EncodeOnCodecThread, this, frame, frame_types)); 375 &MediaCodecVideoEncoder::EncodeOnCodecThread, this, frame, frame_types));
355 } 376 }
356 377
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
402 // unclear how to signal such a failure to the app, so instead we stay silent 423 // unclear how to signal such a failure to the app, so instead we stay silent
403 // about it and let the next app-called API method reveal the borkedness. 424 // about it and let the next app-called API method reveal the borkedness.
404 DeliverPendingOutputs(jni); 425 DeliverPendingOutputs(jni);
405 codec_thread_->PostDelayed(kMediaCodecPollMs, this); 426 codec_thread_->PostDelayed(kMediaCodecPollMs, this);
406 } 427 }
407 428
408 bool MediaCodecVideoEncoder::ResetCodecOnCodecThread() { 429 bool MediaCodecVideoEncoder::ResetCodecOnCodecThread() {
409 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); 430 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread());
410 ALOGE << "ResetOnCodecThread"; 431 ALOGE << "ResetOnCodecThread";
411 if (ReleaseOnCodecThread() != WEBRTC_VIDEO_CODEC_OK || 432 if (ReleaseOnCodecThread() != WEBRTC_VIDEO_CODEC_OK ||
412 InitEncodeOnCodecThread(width_, height_, 0, 0) 433 InitEncodeOnCodecThread(width_, height_, 0, 0, false) !=
413 != WEBRTC_VIDEO_CODEC_OK) { 434 WEBRTC_VIDEO_CODEC_OK) {
414 // TODO(fischman): wouldn't it be nice if there was a way to gracefully 435 // TODO(fischman): wouldn't it be nice if there was a way to gracefully
415 // degrade to a SW encoder at this point? There isn't one AFAICT :( 436 // degrade to a SW encoder at this point? There isn't one AFAICT :(
416 // https://code.google.com/p/webrtc/issues/detail?id=2920 437 // https://code.google.com/p/webrtc/issues/detail?id=2920
417 return false; 438 return false;
418 } 439 }
419 return true; 440 return true;
420 } 441 }
421 442
422 int32_t MediaCodecVideoEncoder::InitEncodeOnCodecThread( 443 int32_t MediaCodecVideoEncoder::InitEncodeOnCodecThread(
423 int width, int height, int kbps, int fps) { 444 int width, int height, int kbps, int fps, bool use_surface) {
424 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); 445 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread());
446 RTC_CHECK(!use_surface || egl_context_ != nullptr) << "EGL context not set.";
425 JNIEnv* jni = AttachCurrentThreadIfNeeded(); 447 JNIEnv* jni = AttachCurrentThreadIfNeeded();
426 ScopedLocalRefFrame local_ref_frame(jni); 448 ScopedLocalRefFrame local_ref_frame(jni);
427 449
428 ALOGD << "InitEncodeOnCodecThread Type: " << (int)codecType_ << ", " << 450 ALOGD << "InitEncodeOnCodecThread Type: " << (int)codecType_ << ", " <<
429 width << " x " << height << ". Bitrate: " << kbps << 451 width << " x " << height << ". Bitrate: " << kbps <<
430 " kbps. Fps: " << fps; 452 " kbps. Fps: " << fps;
431 if (kbps == 0) { 453 if (kbps == 0) {
432 kbps = last_set_bitrate_kbps_; 454 kbps = last_set_bitrate_kbps_;
433 } 455 }
434 if (fps == 0) { 456 if (fps == 0) {
(...skipping 22 matching lines...) Expand all
457 render_times_ms_.clear(); 479 render_times_ms_.clear();
458 frame_rtc_times_ms_.clear(); 480 frame_rtc_times_ms_.clear();
459 drop_next_input_frame_ = false; 481 drop_next_input_frame_ = false;
460 picture_id_ = static_cast<uint16_t>(rand()) & 0x7FFF; 482 picture_id_ = static_cast<uint16_t>(rand()) & 0x7FFF;
461 483
462 // We enforce no extra stride/padding in the format creation step. 484 // We enforce no extra stride/padding in the format creation step.
463 jobject j_video_codec_enum = JavaEnumFromIndex( 485 jobject j_video_codec_enum = JavaEnumFromIndex(
464 jni, "MediaCodecVideoEncoder$VideoCodecType", codecType_); 486 jni, "MediaCodecVideoEncoder$VideoCodecType", codecType_);
465 const bool encode_status = jni->CallBooleanMethod( 487 const bool encode_status = jni->CallBooleanMethod(
466 *j_media_codec_video_encoder_, j_init_encode_method_, 488 *j_media_codec_video_encoder_, j_init_encode_method_,
467 j_video_codec_enum, width, height, kbps, fps); 489 j_video_codec_enum, width, height, kbps, fps,
490 (use_surface ? egl_context_ : nullptr));
468 if (!encode_status) { 491 if (!encode_status) {
469 ALOGE << "Failed to configure encoder."; 492 ALOGE << "Failed to configure encoder.";
470 return WEBRTC_VIDEO_CODEC_ERROR; 493 return WEBRTC_VIDEO_CODEC_ERROR;
471 } 494 }
472 CHECK_EXCEPTION(jni); 495 CHECK_EXCEPTION(jni);
473 496
474 jobjectArray input_buffers = reinterpret_cast<jobjectArray>( 497 if (use_surface) {
475 jni->CallObjectMethod(*j_media_codec_video_encoder_, 498 scale_ = false; // TODO(perkj): Implement scaling when using textures.
476 j_get_input_buffers_method_)); 499 use_surface_ = true;
magjed_webrtc 2015/11/18 13:12:52 This looks strange, can you only enable surface en
perkj_webrtc 2015/11/18 14:51:21 that is strange - but works. I reset in Reset... A
477 CHECK_EXCEPTION(jni); 500 } else {
478 if (IsNull(jni, input_buffers)) { 501 jobjectArray input_buffers = reinterpret_cast<jobjectArray>(
479 return WEBRTC_VIDEO_CODEC_ERROR; 502 jni->CallObjectMethod(*j_media_codec_video_encoder_,
503 j_get_input_buffers_method_));
504 CHECK_EXCEPTION(jni);
505 if (IsNull(jni, input_buffers)) {
506 return WEBRTC_VIDEO_CODEC_ERROR;
507 }
508
509 switch (GetIntField(jni, *j_media_codec_video_encoder_,
510 j_color_format_field_)) {
511 case COLOR_FormatYUV420Planar:
512 encoder_fourcc_ = libyuv::FOURCC_YU12;
513 break;
514 case COLOR_FormatYUV420SemiPlanar:
515 case COLOR_QCOM_FormatYUV420SemiPlanar:
516 case COLOR_QCOM_FORMATYUV420PackedSemiPlanar32m:
517 encoder_fourcc_ = libyuv::FOURCC_NV12;
518 break;
519 default:
520 LOG(LS_ERROR) << "Wrong color format.";
521 return WEBRTC_VIDEO_CODEC_ERROR;
522 }
523 size_t num_input_buffers = jni->GetArrayLength(input_buffers);
524 RTC_CHECK(input_buffers_.empty())
525 << "Unexpected double InitEncode without Release";
526 input_buffers_.resize(num_input_buffers);
527 for (size_t i = 0; i < num_input_buffers; ++i) {
528 input_buffers_[i] =
529 jni->NewGlobalRef(jni->GetObjectArrayElement(input_buffers, i));
530 int64_t yuv_buffer_capacity =
531 jni->GetDirectBufferCapacity(input_buffers_[i]);
532 CHECK_EXCEPTION(jni);
533 RTC_CHECK(yuv_buffer_capacity >= yuv_size_) << "Insufficient capacity";
534 }
480 } 535 }
481 536
482 switch (GetIntField(jni, *j_media_codec_video_encoder_,
483 j_color_format_field_)) {
484 case COLOR_FormatYUV420Planar:
485 encoder_fourcc_ = libyuv::FOURCC_YU12;
486 break;
487 case COLOR_FormatYUV420SemiPlanar:
488 case COLOR_QCOM_FormatYUV420SemiPlanar:
489 case COLOR_QCOM_FORMATYUV420PackedSemiPlanar32m:
490 encoder_fourcc_ = libyuv::FOURCC_NV12;
491 break;
492 default:
493 LOG(LS_ERROR) << "Wrong color format.";
494 return WEBRTC_VIDEO_CODEC_ERROR;
495 }
496 size_t num_input_buffers = jni->GetArrayLength(input_buffers);
497 RTC_CHECK(input_buffers_.empty())
498 << "Unexpected double InitEncode without Release";
499 input_buffers_.resize(num_input_buffers);
500 for (size_t i = 0; i < num_input_buffers; ++i) {
501 input_buffers_[i] =
502 jni->NewGlobalRef(jni->GetObjectArrayElement(input_buffers, i));
503 int64_t yuv_buffer_capacity =
504 jni->GetDirectBufferCapacity(input_buffers_[i]);
505 CHECK_EXCEPTION(jni);
506 RTC_CHECK(yuv_buffer_capacity >= yuv_size_) << "Insufficient capacity";
507 }
508 CHECK_EXCEPTION(jni);
509
510
511 inited_ = true; 537 inited_ = true;
512 codec_thread_->PostDelayed(kMediaCodecPollMs, this); 538 codec_thread_->PostDelayed(kMediaCodecPollMs, this);
513 return WEBRTC_VIDEO_CODEC_OK; 539 return WEBRTC_VIDEO_CODEC_OK;
514 } 540 }
515 541
516 int32_t MediaCodecVideoEncoder::EncodeOnCodecThread( 542 int32_t MediaCodecVideoEncoder::EncodeOnCodecThread(
517 const webrtc::VideoFrame& frame, 543 const webrtc::VideoFrame& frame,
518 const std::vector<webrtc::FrameType>* frame_types) { 544 const std::vector<webrtc::FrameType>* frame_types) {
519 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); 545 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread());
520 JNIEnv* jni = AttachCurrentThreadIfNeeded(); 546 JNIEnv* jni = AttachCurrentThreadIfNeeded();
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
557 if (frames_in_queue_ > 2 || encoder_latency_ms > 70) { 583 if (frames_in_queue_ > 2 || encoder_latency_ms > 70) {
558 ALOGD << "Drop frame - encoder is behind by " << encoder_latency_ms << 584 ALOGD << "Drop frame - encoder is behind by " << encoder_latency_ms <<
559 " ms. Q size: " << frames_in_queue_; 585 " ms. Q size: " << frames_in_queue_;
560 frames_dropped_++; 586 frames_dropped_++;
561 // Report dropped frame to quality_scaler_. 587 // Report dropped frame to quality_scaler_.
562 OnDroppedFrame(); 588 OnDroppedFrame();
563 return WEBRTC_VIDEO_CODEC_OK; 589 return WEBRTC_VIDEO_CODEC_OK;
564 } 590 }
565 } 591 }
566 592
567 int j_input_buffer_index = jni->CallIntMethod(*j_media_codec_video_encoder_, 593 const bool key_frame = frame_types->front() != webrtc::kVideoFrameDelta;
568 j_dequeue_input_buffer_method_); 594 bool encode_status = true;
569 CHECK_EXCEPTION(jni); 595 if (!input_frame.native_handle()) {
570 if (j_input_buffer_index == -1) { 596 int j_input_buffer_index = jni->CallIntMethod(*j_media_codec_video_encoder_,
571 // Video codec falls behind - no input buffer available. 597 j_dequeue_input_buffer_method_);
572 ALOGW << "Encoder drop frame - no input buffers available"; 598 CHECK_EXCEPTION(jni);
573 frames_dropped_++; 599 if (j_input_buffer_index == -1) {
574 // Report dropped frame to quality_scaler_. 600 // Video codec falls behind - no input buffer available.
575 OnDroppedFrame(); 601 ALOGW << "Encoder drop frame - no input buffers available";
576 return WEBRTC_VIDEO_CODEC_OK; // TODO(fischman): see webrtc bug 2887. 602 frames_dropped_++;
603 // Report dropped frame to quality_scaler_.
604 OnDroppedFrame();
605 return WEBRTC_VIDEO_CODEC_OK; // TODO(fischman): see webrtc bug 2887.
606 }
607 if (j_input_buffer_index == -2) {
608 ResetCodecOnCodecThread();
609 return WEBRTC_VIDEO_CODEC_ERROR;
610 }
611 encode_status = EncodeByteBufferOnCodecThread(jni, key_frame, input_frame,
612 j_input_buffer_index);
613 } else {
614 encode_status = EncodeTextureOnCodecThread(jni, key_frame, input_frame);
577 } 615 }
578 if (j_input_buffer_index == -2) { 616
617 if (!encode_status) {
618 ALOGE << "Failed encode frame with timestamp: " << input_frame.timestamp();
579 ResetCodecOnCodecThread(); 619 ResetCodecOnCodecThread();
580 return WEBRTC_VIDEO_CODEC_ERROR; 620 return WEBRTC_VIDEO_CODEC_ERROR;
581 } 621 }
582 622
583 last_input_timestamp_ms_ = 623 last_input_timestamp_ms_ =
584 current_timestamp_us_ / rtc::kNumMicrosecsPerMillisec; 624 current_timestamp_us_ / rtc::kNumMicrosecsPerMillisec;
585 frames_in_queue_++; 625 frames_in_queue_++;
586 626
587 // Save input image timestamps for later output 627 // Save input image timestamps for later output
588 timestamps_.push_back(input_frame.timestamp()); 628 timestamps_.push_back(input_frame.timestamp());
589 render_times_ms_.push_back(input_frame.render_time_ms()); 629 render_times_ms_.push_back(input_frame.render_time_ms());
590 frame_rtc_times_ms_.push_back(GetCurrentTimeMs()); 630 frame_rtc_times_ms_.push_back(GetCurrentTimeMs());
591
592 const bool key_frame = frame_types->front() != webrtc::kVideoFrameDelta;
593 const bool encode_status =
594 EncodeByteBufferOnCodecThread(jni, key_frame, input_frame,
595 j_input_buffer_index);
596
597 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; 631 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_;
598 632
599 if (!encode_status || !DeliverPendingOutputs(jni)) { 633 if (!DeliverPendingOutputs(jni)) {
600 ALOGE << "Failed deliver pending outputs."; 634 ALOGE << "Failed deliver pending outputs.";
601 ResetCodecOnCodecThread(); 635 ResetCodecOnCodecThread();
602 return WEBRTC_VIDEO_CODEC_ERROR; 636 return WEBRTC_VIDEO_CODEC_ERROR;
603 } 637 }
604 return WEBRTC_VIDEO_CODEC_OK; 638 return WEBRTC_VIDEO_CODEC_OK;
605 } 639 }
606 640
607 bool MediaCodecVideoEncoder::MaybeReconfigureEncoderOnCodecThread( 641 bool MediaCodecVideoEncoder::MaybeReconfigureEncoderOnCodecThread(
608 const webrtc::VideoFrame& frame) { 642 const webrtc::VideoFrame& frame) {
609 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); 643 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread());
610 644
611 const bool reconfigure_due_to_size = 645 const bool is_texture_frame = frame.native_handle() != nullptr;
646 const bool reconfigure_due_to_format = is_texture_frame != use_surface_;
647 bool reconfigure_due_to_size =
magjed_webrtc 2015/11/18 13:12:52 Why did you make |reconfigure_due_to_size| mutable
perkj_webrtc 2015/11/18 14:51:21 ....
612 frame.width() != width_ || frame.height() != height_; 648 frame.width() != width_ || frame.height() != height_;
613 649
650 if (reconfigure_due_to_format) {
651 ALOGD << "Reconfigure encoder due to format change. "
652 << (use_surface_ ?
653 "Reconfiguring to encode from byte buffer." :
654 "Reconfiguring to encode from texture.");
655 }
614 if (reconfigure_due_to_size) { 656 if (reconfigure_due_to_size) {
615 ALOGD << "Reconfigure encoder due to frame resolution change from " 657 ALOGD << "Reconfigure encoder due to frame resolution change from "
616 << width_ << " x " << height_ << " to " << frame.width() << " x " 658 << width_ << " x " << height_ << " to " << frame.width() << " x "
617 << frame.height(); 659 << frame.height();
618 width_ = frame.width(); 660 width_ = frame.width();
619 height_ = frame.height(); 661 height_ = frame.height();
620 } 662 }
621 663
622 if (!reconfigure_due_to_size) 664 if (!reconfigure_due_to_format && !reconfigure_due_to_size)
623 return true; 665 return true;
624 666
625 ReleaseOnCodecThread(); 667 ReleaseOnCodecThread();
626 668
627 return InitEncodeOnCodecThread(width_, height_, 0, 0) == 669 return InitEncodeOnCodecThread(width_, height_, 0, 0 , is_texture_frame) ==
628 WEBRTC_VIDEO_CODEC_OK; 670 WEBRTC_VIDEO_CODEC_OK;
629 } 671 }
630 672
631 bool MediaCodecVideoEncoder::EncodeByteBufferOnCodecThread(JNIEnv* jni, 673 bool MediaCodecVideoEncoder::EncodeByteBufferOnCodecThread(JNIEnv* jni,
632 bool key_frame, const webrtc::VideoFrame& frame, int input_buffer_index) { 674 bool key_frame, const webrtc::VideoFrame& frame, int input_buffer_index) {
633 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); 675 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread());
676 RTC_CHECK(!use_surface_);
634 677
635 ALOGV("Encoder frame in # %d. TS: %lld. Q: %d", 678 ALOGV("Encoder frame in # %d. TS: %lld. Q: %d",
636 frames_received_ - 1, current_timestamp_us_ / 1000, frames_in_queue_); 679 frames_received_ - 1, current_timestamp_us_ / 1000, frames_in_queue_);
637 680
638 jobject j_input_buffer = input_buffers_[input_buffer_index]; 681 jobject j_input_buffer = input_buffers_[input_buffer_index];
639 uint8_t* yuv_buffer = 682 uint8_t* yuv_buffer =
640 reinterpret_cast<uint8_t*>(jni->GetDirectBufferAddress(j_input_buffer)); 683 reinterpret_cast<uint8_t*>(jni->GetDirectBufferAddress(j_input_buffer));
641 CHECK_EXCEPTION(jni); 684 CHECK_EXCEPTION(jni);
642 RTC_CHECK(yuv_buffer) << "Indirect buffer??"; 685 RTC_CHECK(yuv_buffer) << "Indirect buffer??";
643 RTC_CHECK(!libyuv::ConvertFromI420( 686 RTC_CHECK(!libyuv::ConvertFromI420(
644 frame.buffer(webrtc::kYPlane), frame.stride(webrtc::kYPlane), 687 frame.buffer(webrtc::kYPlane), frame.stride(webrtc::kYPlane),
645 frame.buffer(webrtc::kUPlane), frame.stride(webrtc::kUPlane), 688 frame.buffer(webrtc::kUPlane), frame.stride(webrtc::kUPlane),
646 frame.buffer(webrtc::kVPlane), frame.stride(webrtc::kVPlane), 689 frame.buffer(webrtc::kVPlane), frame.stride(webrtc::kVPlane),
647 yuv_buffer, width_, width_, height_, encoder_fourcc_)) 690 yuv_buffer, width_, width_, height_, encoder_fourcc_))
648 << "ConvertFromI420 failed"; 691 << "ConvertFromI420 failed";
649 692
650 bool encode_status = jni->CallBooleanMethod(*j_media_codec_video_encoder_, 693 bool encode_status = jni->CallBooleanMethod(*j_media_codec_video_encoder_,
651 j_encode_buffer_method_, 694 j_encode_buffer_method_,
652 key_frame, 695 key_frame,
653 input_buffer_index, 696 input_buffer_index,
654 yuv_size_, 697 yuv_size_,
655 current_timestamp_us_); 698 current_timestamp_us_);
656 CHECK_EXCEPTION(jni); 699 CHECK_EXCEPTION(jni);
657 return encode_status; 700 return encode_status;
658 } 701 }
659 702
703 bool MediaCodecVideoEncoder::EncodeTextureOnCodecThread(JNIEnv* jni,
704 bool key_frame, const webrtc::VideoFrame& frame) {
705 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread());
706 RTC_CHECK(use_surface_);
707 NativeHandleImpl* handle =
708 static_cast<NativeHandleImpl*>(frame.native_handle());
709 jfloatArray sampling_matrix = jni->NewFloatArray(16);
710 jni->SetFloatArrayRegion(sampling_matrix, 0, 16, handle->sampling_matrix);
711
712 bool encode_status = jni->CallBooleanMethod(*j_media_codec_video_encoder_,
713 j_encode_texture_method_,
714 key_frame,
715 handle->oes_texture_id,
716 sampling_matrix,
717 current_timestamp_us_);
718 CHECK_EXCEPTION(jni);
719 return encode_status;
720 }
721
660 int32_t MediaCodecVideoEncoder::RegisterEncodeCompleteCallbackOnCodecThread( 722 int32_t MediaCodecVideoEncoder::RegisterEncodeCompleteCallbackOnCodecThread(
661 webrtc::EncodedImageCallback* callback) { 723 webrtc::EncodedImageCallback* callback) {
662 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); 724 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread());
663 JNIEnv* jni = AttachCurrentThreadIfNeeded(); 725 JNIEnv* jni = AttachCurrentThreadIfNeeded();
664 ScopedLocalRefFrame local_ref_frame(jni); 726 ScopedLocalRefFrame local_ref_frame(jni);
665 callback_ = callback; 727 callback_ = callback;
666 return WEBRTC_VIDEO_CODEC_OK; 728 return WEBRTC_VIDEO_CODEC_OK;
667 } 729 }
668 730
669 int32_t MediaCodecVideoEncoder::ReleaseOnCodecThread() { 731 int32_t MediaCodecVideoEncoder::ReleaseOnCodecThread() {
670 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); 732 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread());
671 if (!inited_) { 733 if (!inited_) {
672 return WEBRTC_VIDEO_CODEC_OK; 734 return WEBRTC_VIDEO_CODEC_OK;
673 } 735 }
674 JNIEnv* jni = AttachCurrentThreadIfNeeded(); 736 JNIEnv* jni = AttachCurrentThreadIfNeeded();
675 ALOGD << "EncoderReleaseOnCodecThread: Frames received: " << 737 ALOGD << "EncoderReleaseOnCodecThread: Frames received: " <<
676 frames_received_ << ". Encoded: " << frames_encoded_ << 738 frames_received_ << ". Encoded: " << frames_encoded_ <<
677 ". Dropped: " << frames_dropped_; 739 ". Dropped: " << frames_dropped_;
678 ScopedLocalRefFrame local_ref_frame(jni); 740 ScopedLocalRefFrame local_ref_frame(jni);
679 for (size_t i = 0; i < input_buffers_.size(); ++i) 741 for (size_t i = 0; i < input_buffers_.size(); ++i)
680 jni->DeleteGlobalRef(input_buffers_[i]); 742 jni->DeleteGlobalRef(input_buffers_[i]);
681 input_buffers_.clear(); 743 input_buffers_.clear();
682 jni->CallVoidMethod(*j_media_codec_video_encoder_, j_release_method_); 744 jni->CallVoidMethod(*j_media_codec_video_encoder_, j_release_method_);
683 CHECK_EXCEPTION(jni); 745 CHECK_EXCEPTION(jni);
684 rtc::MessageQueueManager::Clear(this); 746 rtc::MessageQueueManager::Clear(this);
685 inited_ = false; 747 inited_ = false;
748 use_surface_ = false;
686 ALOGD << "EncoderReleaseOnCodecThread done."; 749 ALOGD << "EncoderReleaseOnCodecThread done.";
687 return WEBRTC_VIDEO_CODEC_OK; 750 return WEBRTC_VIDEO_CODEC_OK;
688 } 751 }
689 752
690 int32_t MediaCodecVideoEncoder::SetRatesOnCodecThread(uint32_t new_bit_rate, 753 int32_t MediaCodecVideoEncoder::SetRatesOnCodecThread(uint32_t new_bit_rate,
691 uint32_t frame_rate) { 754 uint32_t frame_rate) {
692 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); 755 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread());
693 if (last_set_bitrate_kbps_ == new_bit_rate && 756 if (last_set_bitrate_kbps_ == new_bit_rate &&
694 last_set_fps_ == frame_rate) { 757 last_set_fps_ == frame_rate) {
695 return WEBRTC_VIDEO_CODEC_OK; 758 return WEBRTC_VIDEO_CODEC_OK;
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after
950 1013
951 void MediaCodecVideoEncoder::OnDroppedFrame() { 1014 void MediaCodecVideoEncoder::OnDroppedFrame() {
952 if (scale_) 1015 if (scale_)
953 quality_scaler_.ReportDroppedFrame(); 1016 quality_scaler_.ReportDroppedFrame();
954 } 1017 }
955 1018
956 int MediaCodecVideoEncoder::GetTargetFramerate() { 1019 int MediaCodecVideoEncoder::GetTargetFramerate() {
957 return scale_ ? quality_scaler_.GetTargetFramerate() : -1; 1020 return scale_ ? quality_scaler_.GetTargetFramerate() : -1;
958 } 1021 }
959 1022
960 MediaCodecVideoEncoderFactory::MediaCodecVideoEncoderFactory() { 1023 MediaCodecVideoEncoderFactory::MediaCodecVideoEncoderFactory()
1024 : egl_context_ (nullptr) {
961 JNIEnv* jni = AttachCurrentThreadIfNeeded(); 1025 JNIEnv* jni = AttachCurrentThreadIfNeeded();
962 ScopedLocalRefFrame local_ref_frame(jni); 1026 ScopedLocalRefFrame local_ref_frame(jni);
963 jclass j_encoder_class = FindClass(jni, "org/webrtc/MediaCodecVideoEncoder"); 1027 jclass j_encoder_class = FindClass(jni, "org/webrtc/MediaCodecVideoEncoder");
964 supported_codecs_.clear(); 1028 supported_codecs_.clear();
965 1029
966 bool is_vp8_hw_supported = jni->CallStaticBooleanMethod( 1030 bool is_vp8_hw_supported = jni->CallStaticBooleanMethod(
967 j_encoder_class, 1031 j_encoder_class,
968 GetStaticMethodID(jni, j_encoder_class, "isVp8HwSupported", "()Z")); 1032 GetStaticMethodID(jni, j_encoder_class, "isVp8HwSupported", "()Z"));
969 CHECK_EXCEPTION(jni); 1033 CHECK_EXCEPTION(jni);
970 if (is_vp8_hw_supported) { 1034 if (is_vp8_hw_supported) {
971 ALOGD << "VP8 HW Encoder supported."; 1035 ALOGD << "VP8 HW Encoder supported.";
972 supported_codecs_.push_back(VideoCodec(kVideoCodecVP8, "VP8", 1036 supported_codecs_.push_back(VideoCodec(kVideoCodecVP8, "VP8",
973 MAX_VIDEO_WIDTH, MAX_VIDEO_HEIGHT, MAX_VIDEO_FPS)); 1037 MAX_VIDEO_WIDTH, MAX_VIDEO_HEIGHT, MAX_VIDEO_FPS));
974 } 1038 }
975 1039
976 bool is_h264_hw_supported = jni->CallStaticBooleanMethod( 1040 bool is_h264_hw_supported = jni->CallStaticBooleanMethod(
977 j_encoder_class, 1041 j_encoder_class,
978 GetStaticMethodID(jni, j_encoder_class, "isH264HwSupported", "()Z")); 1042 GetStaticMethodID(jni, j_encoder_class, "isH264HwSupported", "()Z"));
979 CHECK_EXCEPTION(jni); 1043 CHECK_EXCEPTION(jni);
980 if (is_h264_hw_supported) { 1044 if (is_h264_hw_supported) {
981 ALOGD << "H.264 HW Encoder supported."; 1045 ALOGD << "H.264 HW Encoder supported.";
982 supported_codecs_.push_back(VideoCodec(kVideoCodecH264, "H264", 1046 supported_codecs_.push_back(VideoCodec(kVideoCodecH264, "H264",
983 MAX_VIDEO_WIDTH, MAX_VIDEO_HEIGHT, MAX_VIDEO_FPS)); 1047 MAX_VIDEO_WIDTH, MAX_VIDEO_HEIGHT, MAX_VIDEO_FPS));
984 } 1048 }
985 } 1049 }
986 1050
987 MediaCodecVideoEncoderFactory::~MediaCodecVideoEncoderFactory() {} 1051 MediaCodecVideoEncoderFactory::~MediaCodecVideoEncoderFactory() {}
988 1052
1053 void MediaCodecVideoEncoderFactory::SetEGLContext(
1054 JNIEnv* jni, jobject render_egl_context) {
1055 ALOGD << "MediaCodecVideoEncoderFactory::SetEGLContext";
1056 if (egl_context_) {
1057 jni->DeleteGlobalRef(egl_context_);
1058 egl_context_ = NULL;
1059 }
1060 if (!IsNull(jni, render_egl_context)) {
1061 egl_context_ = jni->NewGlobalRef(render_egl_context);
1062 if (CheckException(jni)) {
1063 ALOGE << "error calling NewGlobalRef for EGL Context.";
1064 egl_context_ = NULL;
1065 } else {
1066 jclass j_egl_context_class =
1067 FindClass(jni, "javax/microedition/khronos/egl/EGLContext");
1068 if (!jni->IsInstanceOf(egl_context_, j_egl_context_class)) {
1069 ALOGE << "Wrong EGL Context.";
1070 jni->DeleteGlobalRef(egl_context_);
1071 egl_context_ = NULL;
1072 }
1073 }
1074 }
1075 if (egl_context_ == NULL) {
1076 ALOGW << "NULL VideoDecoder EGL context - HW surface encoding is disabled.";
1077 }
1078 }
1079
989 webrtc::VideoEncoder* MediaCodecVideoEncoderFactory::CreateVideoEncoder( 1080 webrtc::VideoEncoder* MediaCodecVideoEncoderFactory::CreateVideoEncoder(
990 VideoCodecType type) { 1081 VideoCodecType type) {
991 if (supported_codecs_.empty()) { 1082 if (supported_codecs_.empty()) {
992 return NULL; 1083 return NULL;
993 } 1084 }
994 for (std::vector<VideoCodec>::const_iterator it = supported_codecs_.begin(); 1085 for (std::vector<VideoCodec>::const_iterator it = supported_codecs_.begin();
995 it != supported_codecs_.end(); ++it) { 1086 it != supported_codecs_.end(); ++it) {
996 if (it->type == type) { 1087 if (it->type == type) {
997 ALOGD << "Create HW video encoder for type " << (int)type << 1088 ALOGD << "Create HW video encoder for type " << (int)type <<
998 " (" << it->name << ")."; 1089 " (" << it->name << ").";
999 return new MediaCodecVideoEncoder(AttachCurrentThreadIfNeeded(), type); 1090 return new MediaCodecVideoEncoder(AttachCurrentThreadIfNeeded(), type,
1091 egl_context_);
1000 } 1092 }
1001 } 1093 }
1002 return NULL; 1094 return NULL;
1003 } 1095 }
1004 1096
1005 const std::vector<MediaCodecVideoEncoderFactory::VideoCodec>& 1097 const std::vector<MediaCodecVideoEncoderFactory::VideoCodec>&
1006 MediaCodecVideoEncoderFactory::codecs() const { 1098 MediaCodecVideoEncoderFactory::codecs() const {
1007 return supported_codecs_; 1099 return supported_codecs_;
1008 } 1100 }
1009 1101
1010 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder( 1102 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder(
1011 webrtc::VideoEncoder* encoder) { 1103 webrtc::VideoEncoder* encoder) {
1012 ALOGD << "Destroy video encoder."; 1104 ALOGD << "Destroy video encoder.";
1013 delete encoder; 1105 delete encoder;
1014 } 1106 }
1015 1107
1016 } // namespace webrtc_jni 1108 } // namespace webrtc_jni
1017 1109
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698