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

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

Powered by Google App Engine
This is Rietveld 408576698