Home | History | Annotate | Download | only in jni
      1 /*
      2  * libjingle
      3  * Copyright 2015 Google Inc.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are met:
      7  *
      8  *  1. Redistributions of source code must retain the above copyright notice,
      9  *     this list of conditions and the following disclaimer.
     10  *  2. Redistributions in binary form must reproduce the above copyright notice,
     11  *     this list of conditions and the following disclaimer in the documentation
     12  *     and/or other materials provided with the distribution.
     13  *  3. The name of the author may not be used to endorse or promote products
     14  *     derived from this software without specific prior written permission.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
     17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
     19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     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
     25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  *
     27  */
     28 
     29 #include <algorithm>
     30 #include <vector>
     31 
     32 #include "talk/app/webrtc/java/jni/androidmediadecoder_jni.h"
     33 #include "talk/app/webrtc/java/jni/androidmediacodeccommon.h"
     34 #include "talk/app/webrtc/java/jni/classreferenceholder.h"
     35 #include "talk/app/webrtc/java/jni/native_handle_impl.h"
     36 #include "talk/app/webrtc/java/jni/surfacetexturehelper_jni.h"
     37 #include "webrtc/base/bind.h"
     38 #include "webrtc/base/checks.h"
     39 #include "webrtc/base/logging.h"
     40 #include "webrtc/base/scoped_ref_ptr.h"
     41 #include "webrtc/base/thread.h"
     42 #include "webrtc/base/timeutils.h"
     43 #include "webrtc/common_video/include/i420_buffer_pool.h"
     44 #include "webrtc/modules/video_coding/include/video_codec_interface.h"
     45 #include "webrtc/system_wrappers/include/logcat_trace_context.h"
     46 #include "webrtc/system_wrappers/include/tick_util.h"
     47 #include "third_party/libyuv/include/libyuv/convert.h"
     48 #include "third_party/libyuv/include/libyuv/convert_from.h"
     49 #include "third_party/libyuv/include/libyuv/video_common.h"
     50 
     51 using rtc::Bind;
     52 using rtc::Thread;
     53 using rtc::ThreadManager;
     54 using rtc::scoped_ptr;
     55 
     56 using webrtc::CodecSpecificInfo;
     57 using webrtc::DecodedImageCallback;
     58 using webrtc::EncodedImage;
     59 using webrtc::VideoFrame;
     60 using webrtc::RTPFragmentationHeader;
     61 using webrtc::TickTime;
     62 using webrtc::VideoCodec;
     63 using webrtc::VideoCodecType;
     64 using webrtc::kVideoCodecH264;
     65 using webrtc::kVideoCodecVP8;
     66 using webrtc::kVideoCodecVP9;
     67 
     68 namespace webrtc_jni {
     69 
     70 class MediaCodecVideoDecoder : public webrtc::VideoDecoder,
     71                                public rtc::MessageHandler {
     72  public:
     73   explicit MediaCodecVideoDecoder(
     74       JNIEnv* jni, VideoCodecType codecType, jobject render_egl_context);
     75   virtual ~MediaCodecVideoDecoder();
     76 
     77   int32_t InitDecode(const VideoCodec* codecSettings, int32_t numberOfCores)
     78       override;
     79 
     80   int32_t Decode(
     81       const EncodedImage& inputImage, bool missingFrames,
     82       const RTPFragmentationHeader* fragmentation,
     83       const CodecSpecificInfo* codecSpecificInfo = NULL,
     84       int64_t renderTimeMs = -1) override;
     85 
     86   int32_t RegisterDecodeCompleteCallback(DecodedImageCallback* callback)
     87       override;
     88 
     89   int32_t Release() override;
     90 
     91   int32_t Reset() override;
     92 
     93   bool PrefersLateDecoding() const override { return true; }
     94 
     95   // rtc::MessageHandler implementation.
     96   void OnMessage(rtc::Message* msg) override;
     97 
     98   const char* ImplementationName() const override;
     99 
    100  private:
    101   // CHECK-fail if not running on |codec_thread_|.
    102   void CheckOnCodecThread();
    103 
    104   int32_t InitDecodeOnCodecThread();
    105   int32_t ReleaseOnCodecThread();
    106   int32_t DecodeOnCodecThread(const EncodedImage& inputImage);
    107   // Deliver any outputs pending in the MediaCodec to our |callback_| and return
    108   // true on success.
    109   bool DeliverPendingOutputs(JNIEnv* jni, int dequeue_timeout_us);
    110   int32_t ProcessHWErrorOnCodecThread();
    111 
    112   // Type of video codec.
    113   VideoCodecType codecType_;
    114 
    115   // Render EGL context - owned by factory, should not be allocated/destroyed
    116   // by VideoDecoder.
    117   jobject render_egl_context_;
    118 
    119   bool key_frame_required_;
    120   bool inited_;
    121   bool sw_fallback_required_;
    122   bool use_surface_;
    123   VideoCodec codec_;
    124   webrtc::I420BufferPool decoded_frame_pool_;
    125   rtc::scoped_refptr<SurfaceTextureHelper> surface_texture_helper_;
    126   DecodedImageCallback* callback_;
    127   int frames_received_;  // Number of frames received by decoder.
    128   int frames_decoded_;  // Number of frames decoded by decoder.
    129   int64_t start_time_ms_;  // Start time for statistics.
    130   int current_frames_;  // Number of frames in the current statistics interval.
    131   int current_bytes_;  // Encoded bytes in the current statistics interval.
    132   int current_decoding_time_ms_;  // Overall decoding time in the current second
    133   uint32_t max_pending_frames_;  // Maximum number of pending input frames
    134 
    135   // State that is constant for the lifetime of this object once the ctor
    136   // returns.
    137   scoped_ptr<Thread> codec_thread_;  // Thread on which to operate MediaCodec.
    138   ScopedGlobalRef<jclass> j_media_codec_video_decoder_class_;
    139   ScopedGlobalRef<jobject> j_media_codec_video_decoder_;
    140   jmethodID j_init_decode_method_;
    141   jmethodID j_release_method_;
    142   jmethodID j_dequeue_input_buffer_method_;
    143   jmethodID j_queue_input_buffer_method_;
    144   jmethodID j_dequeue_byte_buffer_method_;
    145   jmethodID j_dequeue_texture_buffer_method_;
    146   jmethodID j_return_decoded_byte_buffer_method_;
    147   // MediaCodecVideoDecoder fields.
    148   jfieldID j_input_buffers_field_;
    149   jfieldID j_output_buffers_field_;
    150   jfieldID j_color_format_field_;
    151   jfieldID j_width_field_;
    152   jfieldID j_height_field_;
    153   jfieldID j_stride_field_;
    154   jfieldID j_slice_height_field_;
    155   // MediaCodecVideoDecoder.DecodedTextureBuffer fields.
    156   jfieldID j_texture_id_field_;
    157   jfieldID j_transform_matrix_field_;
    158   jfieldID j_texture_timestamp_ms_field_;
    159   jfieldID j_texture_ntp_timestamp_ms_field_;
    160   jfieldID j_texture_decode_time_ms_field_;
    161   jfieldID j_texture_frame_delay_ms_field_;
    162   // MediaCodecVideoDecoder.DecodedOutputBuffer fields.
    163   jfieldID j_info_index_field_;
    164   jfieldID j_info_offset_field_;
    165   jfieldID j_info_size_field_;
    166   jfieldID j_info_timestamp_ms_field_;
    167   jfieldID j_info_ntp_timestamp_ms_field_;
    168   jfieldID j_byte_buffer_decode_time_ms_field_;
    169 
    170   // Global references; must be deleted in Release().
    171   std::vector<jobject> input_buffers_;
    172 };
    173 
    174 MediaCodecVideoDecoder::MediaCodecVideoDecoder(
    175     JNIEnv* jni, VideoCodecType codecType, jobject render_egl_context) :
    176     codecType_(codecType),
    177     render_egl_context_(render_egl_context),
    178     key_frame_required_(true),
    179     inited_(false),
    180     sw_fallback_required_(false),
    181     codec_thread_(new Thread()),
    182     j_media_codec_video_decoder_class_(
    183         jni,
    184         FindClass(jni, "org/webrtc/MediaCodecVideoDecoder")),
    185           j_media_codec_video_decoder_(
    186               jni,
    187               jni->NewObject(*j_media_codec_video_decoder_class_,
    188                    GetMethodID(jni,
    189                               *j_media_codec_video_decoder_class_,
    190                               "<init>",
    191                               "()V"))) {
    192   ScopedLocalRefFrame local_ref_frame(jni);
    193   codec_thread_->SetName("MediaCodecVideoDecoder", NULL);
    194   RTC_CHECK(codec_thread_->Start()) << "Failed to start MediaCodecVideoDecoder";
    195 
    196   j_init_decode_method_ = GetMethodID(
    197       jni, *j_media_codec_video_decoder_class_, "initDecode",
    198       "(Lorg/webrtc/MediaCodecVideoDecoder$VideoCodecType;"
    199       "IILorg/webrtc/SurfaceTextureHelper;)Z");
    200   j_release_method_ =
    201       GetMethodID(jni, *j_media_codec_video_decoder_class_, "release", "()V");
    202   j_dequeue_input_buffer_method_ = GetMethodID(
    203       jni, *j_media_codec_video_decoder_class_, "dequeueInputBuffer", "()I");
    204   j_queue_input_buffer_method_ = GetMethodID(
    205       jni, *j_media_codec_video_decoder_class_, "queueInputBuffer", "(IIJJJ)Z");
    206   j_dequeue_byte_buffer_method_ = GetMethodID(
    207       jni, *j_media_codec_video_decoder_class_, "dequeueOutputBuffer",
    208       "(I)Lorg/webrtc/MediaCodecVideoDecoder$DecodedOutputBuffer;");
    209   j_dequeue_texture_buffer_method_ = GetMethodID(
    210       jni, *j_media_codec_video_decoder_class_, "dequeueTextureBuffer",
    211       "(I)Lorg/webrtc/MediaCodecVideoDecoder$DecodedTextureBuffer;");
    212   j_return_decoded_byte_buffer_method_ =
    213       GetMethodID(jni, *j_media_codec_video_decoder_class_,
    214                   "returnDecodedOutputBuffer", "(I)V");
    215 
    216   j_input_buffers_field_ = GetFieldID(
    217       jni, *j_media_codec_video_decoder_class_,
    218       "inputBuffers", "[Ljava/nio/ByteBuffer;");
    219   j_output_buffers_field_ = GetFieldID(
    220       jni, *j_media_codec_video_decoder_class_,
    221       "outputBuffers", "[Ljava/nio/ByteBuffer;");
    222   j_color_format_field_ = GetFieldID(
    223       jni, *j_media_codec_video_decoder_class_, "colorFormat", "I");
    224   j_width_field_ = GetFieldID(
    225       jni, *j_media_codec_video_decoder_class_, "width", "I");
    226   j_height_field_ = GetFieldID(
    227       jni, *j_media_codec_video_decoder_class_, "height", "I");
    228   j_stride_field_ = GetFieldID(
    229       jni, *j_media_codec_video_decoder_class_, "stride", "I");
    230   j_slice_height_field_ = GetFieldID(
    231       jni, *j_media_codec_video_decoder_class_, "sliceHeight", "I");
    232 
    233   jclass j_decoded_texture_buffer_class = FindClass(jni,
    234       "org/webrtc/MediaCodecVideoDecoder$DecodedTextureBuffer");
    235   j_texture_id_field_ = GetFieldID(
    236       jni, j_decoded_texture_buffer_class, "textureID", "I");
    237   j_transform_matrix_field_ = GetFieldID(
    238       jni, j_decoded_texture_buffer_class, "transformMatrix", "[F");
    239   j_texture_timestamp_ms_field_ = GetFieldID(
    240       jni, j_decoded_texture_buffer_class, "timeStampMs", "J");
    241   j_texture_ntp_timestamp_ms_field_ = GetFieldID(
    242       jni, j_decoded_texture_buffer_class, "ntpTimeStampMs", "J");
    243   j_texture_decode_time_ms_field_ = GetFieldID(
    244       jni, j_decoded_texture_buffer_class, "decodeTimeMs", "J");
    245   j_texture_frame_delay_ms_field_ = GetFieldID(
    246       jni, j_decoded_texture_buffer_class, "frameDelayMs", "J");
    247 
    248   jclass j_decoded_output_buffer_class = FindClass(jni,
    249       "org/webrtc/MediaCodecVideoDecoder$DecodedOutputBuffer");
    250   j_info_index_field_ = GetFieldID(
    251       jni, j_decoded_output_buffer_class, "index", "I");
    252   j_info_offset_field_ = GetFieldID(
    253       jni, j_decoded_output_buffer_class, "offset", "I");
    254   j_info_size_field_ = GetFieldID(
    255       jni, j_decoded_output_buffer_class, "size", "I");
    256   j_info_timestamp_ms_field_ = GetFieldID(
    257       jni, j_decoded_output_buffer_class, "timeStampMs", "J");
    258   j_info_ntp_timestamp_ms_field_ = GetFieldID(
    259       jni, j_decoded_output_buffer_class, "ntpTimeStampMs", "J");
    260   j_byte_buffer_decode_time_ms_field_ = GetFieldID(
    261       jni, j_decoded_output_buffer_class, "decodeTimeMs", "J");
    262 
    263   CHECK_EXCEPTION(jni) << "MediaCodecVideoDecoder ctor failed";
    264   use_surface_ = (render_egl_context_ != NULL);
    265   ALOGD << "MediaCodecVideoDecoder ctor. Use surface: " << use_surface_;
    266   memset(&codec_, 0, sizeof(codec_));
    267   AllowBlockingCalls();
    268 }
    269 
    270 MediaCodecVideoDecoder::~MediaCodecVideoDecoder() {
    271   // Call Release() to ensure no more callbacks to us after we are deleted.
    272   Release();
    273 }
    274 
    275 int32_t MediaCodecVideoDecoder::InitDecode(const VideoCodec* inst,
    276     int32_t numberOfCores) {
    277   ALOGD << "InitDecode.";
    278   if (inst == NULL) {
    279     ALOGE << "NULL VideoCodec instance";
    280     return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
    281   }
    282   // Factory should guard against other codecs being used with us.
    283   RTC_CHECK(inst->codecType == codecType_)
    284       << "Unsupported codec " << inst->codecType << " for " << codecType_;
    285 
    286   if (sw_fallback_required_) {
    287     ALOGE << "InitDecode() - fallback to SW decoder";
    288     return WEBRTC_VIDEO_CODEC_OK;
    289   }
    290   // Save VideoCodec instance for later.
    291   if (&codec_ != inst) {
    292     codec_ = *inst;
    293   }
    294   // If maxFramerate is not set then assume 30 fps.
    295   codec_.maxFramerate = (codec_.maxFramerate >= 1) ? codec_.maxFramerate : 30;
    296 
    297   // Call Java init.
    298   return codec_thread_->Invoke<int32_t>(
    299       Bind(&MediaCodecVideoDecoder::InitDecodeOnCodecThread, this));
    300 }
    301 
    302 int32_t MediaCodecVideoDecoder::InitDecodeOnCodecThread() {
    303   CheckOnCodecThread();
    304   JNIEnv* jni = AttachCurrentThreadIfNeeded();
    305   ScopedLocalRefFrame local_ref_frame(jni);
    306   ALOGD << "InitDecodeOnCodecThread Type: " << (int)codecType_ << ". "
    307       << codec_.width << " x " << codec_.height << ". Fps: " <<
    308       (int)codec_.maxFramerate;
    309 
    310   // Release previous codec first if it was allocated before.
    311   int ret_val = ReleaseOnCodecThread();
    312   if (ret_val < 0) {
    313     ALOGE << "Release failure: " << ret_val << " - fallback to SW codec";
    314     sw_fallback_required_ = true;
    315     return WEBRTC_VIDEO_CODEC_ERROR;
    316   }
    317 
    318   // Always start with a complete key frame.
    319   key_frame_required_ = true;
    320   frames_received_ = 0;
    321   frames_decoded_ = 0;
    322 
    323   jobject java_surface_texture_helper_ = nullptr;
    324   if (use_surface_) {
    325     java_surface_texture_helper_ = jni->CallStaticObjectMethod(
    326         FindClass(jni, "org/webrtc/SurfaceTextureHelper"),
    327         GetStaticMethodID(jni,
    328                           FindClass(jni, "org/webrtc/SurfaceTextureHelper"),
    329                           "create",
    330                           "(Lorg/webrtc/EglBase$Context;)"
    331                           "Lorg/webrtc/SurfaceTextureHelper;"),
    332         render_egl_context_);
    333     RTC_CHECK(java_surface_texture_helper_ != nullptr);
    334     surface_texture_helper_ = new rtc::RefCountedObject<SurfaceTextureHelper>(
    335         jni, java_surface_texture_helper_);
    336   }
    337 
    338   jobject j_video_codec_enum = JavaEnumFromIndex(
    339       jni, "MediaCodecVideoDecoder$VideoCodecType", codecType_);
    340   bool success = jni->CallBooleanMethod(
    341       *j_media_codec_video_decoder_,
    342       j_init_decode_method_,
    343       j_video_codec_enum,
    344       codec_.width,
    345       codec_.height,
    346       java_surface_texture_helper_);
    347   if (CheckException(jni) || !success) {
    348     ALOGE << "Codec initialization error - fallback to SW codec.";
    349     sw_fallback_required_ = true;
    350     return WEBRTC_VIDEO_CODEC_ERROR;
    351   }
    352   inited_ = true;
    353 
    354   switch (codecType_) {
    355     case kVideoCodecVP8:
    356       max_pending_frames_ = kMaxPendingFramesVp8;
    357       break;
    358     case kVideoCodecVP9:
    359       max_pending_frames_ = kMaxPendingFramesVp9;
    360       break;
    361     case kVideoCodecH264:
    362       max_pending_frames_ = kMaxPendingFramesH264;
    363       break;
    364     default:
    365       max_pending_frames_ = 0;
    366   }
    367   start_time_ms_ = GetCurrentTimeMs();
    368   current_frames_ = 0;
    369   current_bytes_ = 0;
    370   current_decoding_time_ms_ = 0;
    371 
    372   jobjectArray input_buffers = (jobjectArray)GetObjectField(
    373       jni, *j_media_codec_video_decoder_, j_input_buffers_field_);
    374   size_t num_input_buffers = jni->GetArrayLength(input_buffers);
    375   ALOGD << "Maximum amount of pending frames: " << max_pending_frames_;
    376   input_buffers_.resize(num_input_buffers);
    377   for (size_t i = 0; i < num_input_buffers; ++i) {
    378     input_buffers_[i] =
    379         jni->NewGlobalRef(jni->GetObjectArrayElement(input_buffers, i));
    380     if (CheckException(jni)) {
    381       ALOGE << "NewGlobalRef error - fallback to SW codec.";
    382       sw_fallback_required_ = true;
    383       return WEBRTC_VIDEO_CODEC_ERROR;
    384     }
    385   }
    386 
    387   codec_thread_->PostDelayed(kMediaCodecPollMs, this);
    388 
    389   return WEBRTC_VIDEO_CODEC_OK;
    390 }
    391 
    392 int32_t MediaCodecVideoDecoder::Release() {
    393   ALOGD << "DecoderRelease request";
    394   return codec_thread_->Invoke<int32_t>(
    395         Bind(&MediaCodecVideoDecoder::ReleaseOnCodecThread, this));
    396 }
    397 
    398 int32_t MediaCodecVideoDecoder::ReleaseOnCodecThread() {
    399   if (!inited_) {
    400     return WEBRTC_VIDEO_CODEC_OK;
    401   }
    402   CheckOnCodecThread();
    403   JNIEnv* jni = AttachCurrentThreadIfNeeded();
    404   ALOGD << "DecoderReleaseOnCodecThread: Frames received: " <<
    405       frames_received_ << ". Frames decoded: " << frames_decoded_;
    406   ScopedLocalRefFrame local_ref_frame(jni);
    407   for (size_t i = 0; i < input_buffers_.size(); i++) {
    408     jni->DeleteGlobalRef(input_buffers_[i]);
    409   }
    410   input_buffers_.clear();
    411   jni->CallVoidMethod(*j_media_codec_video_decoder_, j_release_method_);
    412   surface_texture_helper_ = nullptr;
    413   inited_ = false;
    414   rtc::MessageQueueManager::Clear(this);
    415   if (CheckException(jni)) {
    416     ALOGE << "Decoder release exception";
    417     return WEBRTC_VIDEO_CODEC_ERROR;
    418   }
    419   ALOGD << "DecoderReleaseOnCodecThread done";
    420   return WEBRTC_VIDEO_CODEC_OK;
    421 }
    422 
    423 void MediaCodecVideoDecoder::CheckOnCodecThread() {
    424   RTC_CHECK(codec_thread_ == ThreadManager::Instance()->CurrentThread())
    425       << "Running on wrong thread!";
    426 }
    427 
    428 int32_t MediaCodecVideoDecoder::ProcessHWErrorOnCodecThread() {
    429   CheckOnCodecThread();
    430   int ret_val = ReleaseOnCodecThread();
    431   if (ret_val < 0) {
    432     ALOGE << "ProcessHWError: Release failure";
    433   }
    434   if (codecType_ == kVideoCodecH264) {
    435     // For now there is no SW H.264 which can be used as fallback codec.
    436     // So try to restart hw codec for now.
    437     ret_val = InitDecodeOnCodecThread();
    438     ALOGE << "Reset H.264 codec done. Status: " << ret_val;
    439     if (ret_val == WEBRTC_VIDEO_CODEC_OK) {
    440       // H.264 codec was succesfully reset - return regular error code.
    441       return WEBRTC_VIDEO_CODEC_ERROR;
    442     } else {
    443       // Fail to restart H.264 codec - return error code which should stop the
    444       // call.
    445       return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
    446     }
    447   } else {
    448     sw_fallback_required_ = true;
    449     ALOGE << "Return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE";
    450     return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
    451   }
    452 }
    453 
    454 int32_t MediaCodecVideoDecoder::Decode(
    455     const EncodedImage& inputImage,
    456     bool missingFrames,
    457     const RTPFragmentationHeader* fragmentation,
    458     const CodecSpecificInfo* codecSpecificInfo,
    459     int64_t renderTimeMs) {
    460   if (sw_fallback_required_) {
    461     ALOGE << "Decode() - fallback to SW codec";
    462     return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
    463   }
    464   if (callback_ == NULL) {
    465     ALOGE << "Decode() - callback_ is NULL";
    466     return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
    467   }
    468   if (inputImage._buffer == NULL && inputImage._length > 0) {
    469     ALOGE << "Decode() - inputImage is incorrect";
    470     return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
    471   }
    472   if (!inited_) {
    473     ALOGE << "Decode() - decoder is not initialized";
    474     return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
    475   }
    476 
    477   // Check if encoded frame dimension has changed.
    478   if ((inputImage._encodedWidth * inputImage._encodedHeight > 0) &&
    479       (inputImage._encodedWidth != codec_.width ||
    480       inputImage._encodedHeight != codec_.height)) {
    481     codec_.width = inputImage._encodedWidth;
    482     codec_.height = inputImage._encodedHeight;
    483     int32_t ret = InitDecode(&codec_, 1);
    484     if (ret < 0) {
    485       ALOGE << "InitDecode failure: " << ret << " - fallback to SW codec";
    486       sw_fallback_required_ = true;
    487       return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
    488     }
    489   }
    490 
    491   // Always start with a complete key frame.
    492   if (key_frame_required_) {
    493     if (inputImage._frameType != webrtc::kVideoFrameKey) {
    494       ALOGE << "Decode() - key frame is required";
    495       return WEBRTC_VIDEO_CODEC_ERROR;
    496     }
    497     if (!inputImage._completeFrame) {
    498       ALOGE << "Decode() - complete frame is required";
    499       return WEBRTC_VIDEO_CODEC_ERROR;
    500     }
    501     key_frame_required_ = false;
    502   }
    503   if (inputImage._length == 0) {
    504     return WEBRTC_VIDEO_CODEC_ERROR;
    505   }
    506 
    507   return codec_thread_->Invoke<int32_t>(Bind(
    508       &MediaCodecVideoDecoder::DecodeOnCodecThread, this, inputImage));
    509 }
    510 
    511 int32_t MediaCodecVideoDecoder::DecodeOnCodecThread(
    512     const EncodedImage& inputImage) {
    513   CheckOnCodecThread();
    514   JNIEnv* jni = AttachCurrentThreadIfNeeded();
    515   ScopedLocalRefFrame local_ref_frame(jni);
    516 
    517   // Try to drain the decoder and wait until output is not too
    518   // much behind the input.
    519   const int64 drain_start = GetCurrentTimeMs();
    520   while ((frames_received_ > frames_decoded_ + max_pending_frames_) &&
    521          (GetCurrentTimeMs() - drain_start) < kMediaCodecTimeoutMs) {
    522     ALOGV("Received: %d. Decoded: %d. Wait for output...",
    523         frames_received_, frames_decoded_);
    524     if (!DeliverPendingOutputs(jni, kMediaCodecPollMs)) {
    525       ALOGE << "DeliverPendingOutputs error. Frames received: " <<
    526           frames_received_ << ". Frames decoded: " << frames_decoded_;
    527       return ProcessHWErrorOnCodecThread();
    528     }
    529   }
    530   if (frames_received_ > frames_decoded_ + max_pending_frames_) {
    531     ALOGE << "Output buffer dequeue timeout. Frames received: " <<
    532         frames_received_ << ". Frames decoded: " << frames_decoded_;
    533     return ProcessHWErrorOnCodecThread();
    534   }
    535 
    536   // Get input buffer.
    537   int j_input_buffer_index = jni->CallIntMethod(*j_media_codec_video_decoder_,
    538                                                 j_dequeue_input_buffer_method_);
    539   if (CheckException(jni) || j_input_buffer_index < 0) {
    540     ALOGE << "dequeueInputBuffer error";
    541     return ProcessHWErrorOnCodecThread();
    542   }
    543 
    544   // Copy encoded data to Java ByteBuffer.
    545   jobject j_input_buffer = input_buffers_[j_input_buffer_index];
    546   uint8_t* buffer =
    547       reinterpret_cast<uint8_t*>(jni->GetDirectBufferAddress(j_input_buffer));
    548   RTC_CHECK(buffer) << "Indirect buffer??";
    549   int64_t buffer_capacity = jni->GetDirectBufferCapacity(j_input_buffer);
    550   if (CheckException(jni) || buffer_capacity < inputImage._length) {
    551     ALOGE << "Input frame size "<<  inputImage._length <<
    552         " is bigger than buffer size " << buffer_capacity;
    553     return ProcessHWErrorOnCodecThread();
    554   }
    555   jlong presentation_timestamp_us =
    556       (frames_received_ * 1000000) / codec_.maxFramerate;
    557   if (frames_decoded_ < kMaxDecodedLogFrames) {
    558     ALOGD << "Decoder frame in # " << frames_received_ << ". Type: "
    559         << inputImage._frameType << ". Buffer # " <<
    560         j_input_buffer_index << ". pTS: "
    561         << (int)(presentation_timestamp_us / 1000)
    562         << ". TS: " << inputImage._timeStamp
    563         << ". Size: " << inputImage._length;
    564   }
    565   memcpy(buffer, inputImage._buffer, inputImage._length);
    566 
    567   // Save input image timestamps for later output.
    568   frames_received_++;
    569   current_bytes_ += inputImage._length;
    570 
    571   // Feed input to decoder.
    572   bool success = jni->CallBooleanMethod(
    573       *j_media_codec_video_decoder_,
    574       j_queue_input_buffer_method_,
    575       j_input_buffer_index,
    576       inputImage._length,
    577       presentation_timestamp_us,
    578       static_cast<int64_t> (inputImage._timeStamp),
    579       inputImage.ntp_time_ms_);
    580   if (CheckException(jni) || !success) {
    581     ALOGE << "queueInputBuffer error";
    582     return ProcessHWErrorOnCodecThread();
    583   }
    584 
    585   // Try to drain the decoder
    586   if (!DeliverPendingOutputs(jni, 0)) {
    587     ALOGE << "DeliverPendingOutputs error";
    588     return ProcessHWErrorOnCodecThread();
    589   }
    590 
    591   return WEBRTC_VIDEO_CODEC_OK;
    592 }
    593 
    594 bool MediaCodecVideoDecoder::DeliverPendingOutputs(
    595     JNIEnv* jni, int dequeue_timeout_ms) {
    596   if (frames_received_ <= frames_decoded_) {
    597     // No need to query for output buffers - decoder is drained.
    598     return true;
    599   }
    600   // Get decoder output.
    601   jobject j_decoder_output_buffer =
    602       jni->CallObjectMethod(*j_media_codec_video_decoder_,
    603           use_surface_ ? j_dequeue_texture_buffer_method_
    604                        : j_dequeue_byte_buffer_method_,
    605           dequeue_timeout_ms);
    606 
    607   if (CheckException(jni)) {
    608     ALOGE << "dequeueOutputBuffer() error";
    609     return false;
    610   }
    611   if (IsNull(jni, j_decoder_output_buffer)) {
    612     // No decoded frame ready.
    613     return true;
    614   }
    615 
    616   // Get decoded video frame properties.
    617   int color_format = GetIntField(jni, *j_media_codec_video_decoder_,
    618       j_color_format_field_);
    619   int width = GetIntField(jni, *j_media_codec_video_decoder_, j_width_field_);
    620   int height = GetIntField(jni, *j_media_codec_video_decoder_, j_height_field_);
    621   int stride = GetIntField(jni, *j_media_codec_video_decoder_, j_stride_field_);
    622   int slice_height = GetIntField(jni, *j_media_codec_video_decoder_,
    623       j_slice_height_field_);
    624 
    625   rtc::scoped_refptr<webrtc::VideoFrameBuffer> frame_buffer;
    626   int64_t output_timestamps_ms = 0;
    627   int64_t output_ntp_timestamps_ms = 0;
    628   int decode_time_ms = 0;
    629   int64_t frame_delayed_ms = 0;
    630   if (use_surface_) {
    631     // Extract data from Java DecodedTextureBuffer.
    632     const int texture_id =
    633         GetIntField(jni, j_decoder_output_buffer, j_texture_id_field_);
    634     if (texture_id != 0) {  // |texture_id| == 0 represents a dropped frame.
    635       const jfloatArray j_transform_matrix =
    636           reinterpret_cast<jfloatArray>(GetObjectField(
    637               jni, j_decoder_output_buffer, j_transform_matrix_field_));
    638       const int64_t timestamp_us =
    639           GetLongField(jni, j_decoder_output_buffer,
    640               j_texture_timestamp_ms_field_);
    641       output_timestamps_ms = GetLongField(jni, j_decoder_output_buffer,
    642                                           j_texture_timestamp_ms_field_);
    643       output_ntp_timestamps_ms =
    644           GetLongField(jni, j_decoder_output_buffer,
    645                        j_texture_ntp_timestamp_ms_field_);
    646       decode_time_ms = GetLongField(jni, j_decoder_output_buffer,
    647           j_texture_decode_time_ms_field_);
    648       frame_delayed_ms = GetLongField(jni, j_decoder_output_buffer,
    649           j_texture_frame_delay_ms_field_);
    650 
    651       // Create webrtc::VideoFrameBuffer with native texture handle.
    652       frame_buffer = surface_texture_helper_->CreateTextureFrame(
    653           width, height, NativeHandleImpl(jni, texture_id, j_transform_matrix));
    654     }
    655   } else {
    656     // Extract data from Java ByteBuffer and create output yuv420 frame -
    657     // for non surface decoding only.
    658     const int output_buffer_index =
    659         GetIntField(jni, j_decoder_output_buffer, j_info_index_field_);
    660     const int output_buffer_offset =
    661         GetIntField(jni, j_decoder_output_buffer, j_info_offset_field_);
    662     const int output_buffer_size =
    663         GetIntField(jni, j_decoder_output_buffer, j_info_size_field_);
    664     output_timestamps_ms = GetLongField(jni, j_decoder_output_buffer,
    665                                         j_info_timestamp_ms_field_);
    666     output_ntp_timestamps_ms =
    667         GetLongField(jni, j_decoder_output_buffer,
    668                      j_info_ntp_timestamp_ms_field_);
    669 
    670     decode_time_ms = GetLongField(jni, j_decoder_output_buffer,
    671                                   j_byte_buffer_decode_time_ms_field_);
    672 
    673     if (output_buffer_size < width * height * 3 / 2) {
    674       ALOGE << "Insufficient output buffer size: " << output_buffer_size;
    675       return false;
    676     }
    677     jobjectArray output_buffers = reinterpret_cast<jobjectArray>(GetObjectField(
    678         jni, *j_media_codec_video_decoder_, j_output_buffers_field_));
    679     jobject output_buffer =
    680         jni->GetObjectArrayElement(output_buffers, output_buffer_index);
    681     uint8_t* payload = reinterpret_cast<uint8_t*>(jni->GetDirectBufferAddress(
    682         output_buffer));
    683     if (CheckException(jni)) {
    684       return false;
    685     }
    686     payload += output_buffer_offset;
    687 
    688     // Create yuv420 frame.
    689     frame_buffer = decoded_frame_pool_.CreateBuffer(width, height);
    690     if (color_format == COLOR_FormatYUV420Planar) {
    691       RTC_CHECK_EQ(0, stride % 2);
    692       RTC_CHECK_EQ(0, slice_height % 2);
    693       const int uv_stride = stride / 2;
    694       const int u_slice_height = slice_height / 2;
    695       const uint8_t* y_ptr = payload;
    696       const uint8_t* u_ptr = y_ptr + stride * slice_height;
    697       const uint8_t* v_ptr = u_ptr + uv_stride * u_slice_height;
    698       libyuv::I420Copy(y_ptr, stride,
    699                        u_ptr, uv_stride,
    700                        v_ptr, uv_stride,
    701                        frame_buffer->MutableData(webrtc::kYPlane),
    702                        frame_buffer->stride(webrtc::kYPlane),
    703                        frame_buffer->MutableData(webrtc::kUPlane),
    704                        frame_buffer->stride(webrtc::kUPlane),
    705                        frame_buffer->MutableData(webrtc::kVPlane),
    706                        frame_buffer->stride(webrtc::kVPlane),
    707                        width, height);
    708     } else {
    709       // All other supported formats are nv12.
    710       const uint8_t* y_ptr = payload;
    711       const uint8_t* uv_ptr = y_ptr + stride * slice_height;
    712       libyuv::NV12ToI420(
    713           y_ptr, stride,
    714           uv_ptr, stride,
    715           frame_buffer->MutableData(webrtc::kYPlane),
    716           frame_buffer->stride(webrtc::kYPlane),
    717           frame_buffer->MutableData(webrtc::kUPlane),
    718           frame_buffer->stride(webrtc::kUPlane),
    719           frame_buffer->MutableData(webrtc::kVPlane),
    720           frame_buffer->stride(webrtc::kVPlane),
    721           width, height);
    722     }
    723     // Return output byte buffer back to codec.
    724     jni->CallVoidMethod(
    725         *j_media_codec_video_decoder_,
    726         j_return_decoded_byte_buffer_method_,
    727         output_buffer_index);
    728     if (CheckException(jni)) {
    729       ALOGE << "returnDecodedOutputBuffer error";
    730       return false;
    731     }
    732   }
    733   VideoFrame decoded_frame(frame_buffer, 0, 0, webrtc::kVideoRotation_0);
    734   decoded_frame.set_timestamp(output_timestamps_ms);
    735   decoded_frame.set_ntp_time_ms(output_ntp_timestamps_ms);
    736 
    737   if (frames_decoded_ < kMaxDecodedLogFrames) {
    738     ALOGD << "Decoder frame out # " << frames_decoded_ << ". " << width <<
    739         " x " << height << ". " << stride << " x " <<  slice_height <<
    740         ". Color: " << color_format << ". TS:" << decoded_frame.timestamp() <<
    741         ". DecTime: " << (int)decode_time_ms <<
    742         ". DelayTime: " << (int)frame_delayed_ms;
    743   }
    744 
    745   // Calculate and print decoding statistics - every 3 seconds.
    746   frames_decoded_++;
    747   current_frames_++;
    748   current_decoding_time_ms_ += decode_time_ms;
    749   int statistic_time_ms = GetCurrentTimeMs() - start_time_ms_;
    750   if (statistic_time_ms >= kMediaCodecStatisticsIntervalMs &&
    751       current_frames_ > 0) {
    752     ALOGD << "Decoded frames: " << frames_decoded_ <<  ". Received frames: "
    753         <<  frames_received_ << ".  Bitrate: " <<
    754         (current_bytes_ * 8 / statistic_time_ms) << " kbps, fps: " <<
    755         ((current_frames_ * 1000 + statistic_time_ms / 2) / statistic_time_ms)
    756         << ". decTime: " << (current_decoding_time_ms_ / current_frames_) <<
    757         " for last " << statistic_time_ms << " ms.";
    758     start_time_ms_ = GetCurrentTimeMs();
    759     current_frames_ = 0;
    760     current_bytes_ = 0;
    761     current_decoding_time_ms_ = 0;
    762   }
    763 
    764   // |.IsZeroSize())| returns true when a frame has been dropped.
    765   if (!decoded_frame.IsZeroSize()) {
    766     // Callback - output decoded frame.
    767     const int32_t callback_status =
    768         callback_->Decoded(decoded_frame, decode_time_ms);
    769     if (callback_status > 0) {
    770       ALOGE << "callback error";
    771     }
    772   }
    773   return true;
    774 }
    775 
    776 int32_t MediaCodecVideoDecoder::RegisterDecodeCompleteCallback(
    777     DecodedImageCallback* callback) {
    778   callback_ = callback;
    779   return WEBRTC_VIDEO_CODEC_OK;
    780 }
    781 
    782 int32_t MediaCodecVideoDecoder::Reset() {
    783   ALOGD << "DecoderReset";
    784   if (!inited_) {
    785     return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
    786   }
    787   return InitDecode(&codec_, 1);
    788 }
    789 
    790 void MediaCodecVideoDecoder::OnMessage(rtc::Message* msg) {
    791   JNIEnv* jni = AttachCurrentThreadIfNeeded();
    792   ScopedLocalRefFrame local_ref_frame(jni);
    793   if (!inited_) {
    794     return;
    795   }
    796   // We only ever send one message to |this| directly (not through a Bind()'d
    797   // functor), so expect no ID/data.
    798   RTC_CHECK(!msg->message_id) << "Unexpected message!";
    799   RTC_CHECK(!msg->pdata) << "Unexpected message!";
    800   CheckOnCodecThread();
    801 
    802   if (!DeliverPendingOutputs(jni, 0)) {
    803     ALOGE << "OnMessage: DeliverPendingOutputs error";
    804     ProcessHWErrorOnCodecThread();
    805     return;
    806   }
    807   codec_thread_->PostDelayed(kMediaCodecPollMs, this);
    808 }
    809 
    810 MediaCodecVideoDecoderFactory::MediaCodecVideoDecoderFactory() :
    811     render_egl_context_(NULL) {
    812   ALOGD << "MediaCodecVideoDecoderFactory ctor";
    813   JNIEnv* jni = AttachCurrentThreadIfNeeded();
    814   ScopedLocalRefFrame local_ref_frame(jni);
    815   jclass j_decoder_class = FindClass(jni, "org/webrtc/MediaCodecVideoDecoder");
    816   supported_codec_types_.clear();
    817 
    818   bool is_vp8_hw_supported = jni->CallStaticBooleanMethod(
    819       j_decoder_class,
    820       GetStaticMethodID(jni, j_decoder_class, "isVp8HwSupported", "()Z"));
    821   if (CheckException(jni)) {
    822     is_vp8_hw_supported = false;
    823   }
    824   if (is_vp8_hw_supported) {
    825     ALOGD << "VP8 HW Decoder supported.";
    826     supported_codec_types_.push_back(kVideoCodecVP8);
    827   }
    828 
    829   bool is_vp9_hw_supported = jni->CallStaticBooleanMethod(
    830       j_decoder_class,
    831       GetStaticMethodID(jni, j_decoder_class, "isVp9HwSupported", "()Z"));
    832   if (CheckException(jni)) {
    833     is_vp9_hw_supported = false;
    834   }
    835   if (is_vp9_hw_supported) {
    836     ALOGD << "VP9 HW Decoder supported.";
    837     supported_codec_types_.push_back(kVideoCodecVP9);
    838   }
    839 
    840   bool is_h264_hw_supported = jni->CallStaticBooleanMethod(
    841       j_decoder_class,
    842       GetStaticMethodID(jni, j_decoder_class, "isH264HwSupported", "()Z"));
    843   if (CheckException(jni)) {
    844     is_h264_hw_supported = false;
    845   }
    846   if (is_h264_hw_supported) {
    847     ALOGD << "H264 HW Decoder supported.";
    848     supported_codec_types_.push_back(kVideoCodecH264);
    849   }
    850 }
    851 
    852 MediaCodecVideoDecoderFactory::~MediaCodecVideoDecoderFactory() {
    853   ALOGD << "MediaCodecVideoDecoderFactory dtor";
    854   if (render_egl_context_) {
    855     JNIEnv* jni = AttachCurrentThreadIfNeeded();
    856     jni->DeleteGlobalRef(render_egl_context_);
    857     render_egl_context_ = NULL;
    858   }
    859 }
    860 
    861 void MediaCodecVideoDecoderFactory::SetEGLContext(
    862     JNIEnv* jni, jobject render_egl_context) {
    863   ALOGD << "MediaCodecVideoDecoderFactory::SetEGLContext";
    864   if (render_egl_context_) {
    865     jni->DeleteGlobalRef(render_egl_context_);
    866     render_egl_context_ = NULL;
    867   }
    868   if (!IsNull(jni, render_egl_context)) {
    869     render_egl_context_ = jni->NewGlobalRef(render_egl_context);
    870     if (CheckException(jni)) {
    871       ALOGE << "error calling NewGlobalRef for EGL Context.";
    872       render_egl_context_ = NULL;
    873     } else {
    874       jclass j_egl_context_class =
    875           FindClass(jni, "org/webrtc/EglBase$Context");
    876       if (!jni->IsInstanceOf(render_egl_context_, j_egl_context_class)) {
    877         ALOGE << "Wrong EGL Context.";
    878         jni->DeleteGlobalRef(render_egl_context_);
    879         render_egl_context_ = NULL;
    880       }
    881     }
    882   }
    883   if (render_egl_context_ == NULL) {
    884     ALOGW << "NULL VideoDecoder EGL context - HW surface decoding is disabled.";
    885   }
    886 }
    887 
    888 webrtc::VideoDecoder* MediaCodecVideoDecoderFactory::CreateVideoDecoder(
    889     VideoCodecType type) {
    890   if (supported_codec_types_.empty()) {
    891     ALOGW << "No HW video decoder for type " << (int)type;
    892     return NULL;
    893   }
    894   for (VideoCodecType codec_type : supported_codec_types_) {
    895     if (codec_type == type) {
    896       ALOGD << "Create HW video decoder for type " << (int)type;
    897       return new MediaCodecVideoDecoder(
    898           AttachCurrentThreadIfNeeded(), type, render_egl_context_);
    899     }
    900   }
    901   ALOGW << "Can not find HW video decoder for type " << (int)type;
    902   return NULL;
    903 }
    904 
    905 void MediaCodecVideoDecoderFactory::DestroyVideoDecoder(
    906     webrtc::VideoDecoder* decoder) {
    907   ALOGD << "Destroy video decoder.";
    908   delete decoder;
    909 }
    910 
    911 const char* MediaCodecVideoDecoder::ImplementationName() const {
    912   return "MediaCodec";
    913 }
    914 
    915 }  // namespace webrtc_jni
    916 
    917