Home | History | Annotate | Download | only in jni
      1 /*
      2  * libjingle
      3  * Copyright 2013, 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 // Hints for future visitors:
     29 // This entire file is an implementation detail of the org.webrtc Java package,
     30 // the most interesting bits of which are org.webrtc.PeerConnection{,Factory}.
     31 // The layout of this file is roughly:
     32 // - various helper C++ functions & classes that wrap Java counterparts and
     33 //   expose a C++ interface that can be passed to the C++ PeerConnection APIs
     34 // - implementations of methods declared "static" in the Java package (named
     35 //   things like Java_org_webrtc_OMG_Can_This_Name_Be_Any_Longer, prescribed by
     36 //   the JNI spec).
     37 //
     38 // Lifecycle notes: objects are owned where they will be called; in other words
     39 // FooObservers are owned by C++-land, and user-callable objects (e.g.
     40 // PeerConnection and VideoTrack) are owned by Java-land.
     41 // When this file allocates C++ RefCountInterfaces it AddRef()s an artificial
     42 // ref simulating the jlong held in Java-land, and then Release()s the ref in
     43 // the respective free call.  Sometimes this AddRef is implicit in the
     44 // construction of a scoped_refptr<> which is then .release()d.
     45 // Any persistent (non-local) references from C++ to Java must be global or weak
     46 // (in which case they must be checked before use)!
     47 //
     48 // Exception notes: pretty much all JNI calls can throw Java exceptions, so each
     49 // call through a JNIEnv* pointer needs to be followed by an ExceptionCheck()
     50 // call.  In this file this is done in CHECK_EXCEPTION, making for much easier
     51 // debugging in case of failure (the alternative is to wait for control to
     52 // return to the Java frame that called code in this file, at which point it's
     53 // impossible to tell which JNI call broke).
     54 
     55 #include <jni.h>
     56 #undef JNIEXPORT
     57 #define JNIEXPORT __attribute__((visibility("default")))
     58 
     59 #include <asm/unistd.h>
     60 #include <sys/prctl.h>
     61 #include <sys/syscall.h>
     62 #include <unistd.h>
     63 #include <limits>
     64 #include <map>
     65 
     66 #include "talk/app/webrtc/mediaconstraintsinterface.h"
     67 #include "talk/app/webrtc/peerconnectioninterface.h"
     68 #include "talk/app/webrtc/videosourceinterface.h"
     69 #include "talk/media/base/videocapturer.h"
     70 #include "talk/media/base/videorenderer.h"
     71 #include "talk/media/devices/videorendererfactory.h"
     72 #include "talk/media/webrtc/webrtcvideocapturer.h"
     73 #include "talk/media/webrtc/webrtcvideodecoderfactory.h"
     74 #include "talk/media/webrtc/webrtcvideoencoderfactory.h"
     75 #include "third_party/icu/source/common/unicode/unistr.h"
     76 #include "third_party/libyuv/include/libyuv/convert.h"
     77 #include "third_party/libyuv/include/libyuv/convert_from.h"
     78 #include "third_party/libyuv/include/libyuv/video_common.h"
     79 #include "webrtc/base/bind.h"
     80 #include "webrtc/base/checks.h"
     81 #include "webrtc/base/logging.h"
     82 #include "webrtc/base/messagequeue.h"
     83 #include "webrtc/base/ssladapter.h"
     84 #include "webrtc/common_video/interface/texture_video_frame.h"
     85 #include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h"
     86 #include "webrtc/system_wrappers/interface/compile_assert.h"
     87 #include "webrtc/system_wrappers/interface/trace.h"
     88 #include "webrtc/video_engine/include/vie_base.h"
     89 #include "webrtc/voice_engine/include/voe_base.h"
     90 
     91 #if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
     92 #include <android/log.h>
     93 #include "webrtc/modules/video_capture/video_capture_internal.h"
     94 #include "webrtc/modules/video_render/video_render_internal.h"
     95 #include "webrtc/system_wrappers/interface/logcat_trace_context.h"
     96 #include "webrtc/system_wrappers/interface/tick_util.h"
     97 using webrtc::CodecSpecificInfo;
     98 using webrtc::DecodedImageCallback;
     99 using webrtc::EncodedImage;
    100 using webrtc::I420VideoFrame;
    101 using webrtc::LogcatTraceContext;
    102 using webrtc::RTPFragmentationHeader;
    103 using webrtc::TextureVideoFrame;
    104 using webrtc::TickTime;
    105 using webrtc::VideoCodec;
    106 #endif
    107 
    108 using icu::UnicodeString;
    109 using rtc::Bind;
    110 using rtc::Thread;
    111 using rtc::ThreadManager;
    112 using rtc::scoped_ptr;
    113 using webrtc::AudioSourceInterface;
    114 using webrtc::AudioTrackInterface;
    115 using webrtc::AudioTrackVector;
    116 using webrtc::CreateSessionDescriptionObserver;
    117 using webrtc::DataBuffer;
    118 using webrtc::DataChannelInit;
    119 using webrtc::DataChannelInterface;
    120 using webrtc::DataChannelObserver;
    121 using webrtc::IceCandidateInterface;
    122 using webrtc::NativeHandle;
    123 using webrtc::MediaConstraintsInterface;
    124 using webrtc::MediaSourceInterface;
    125 using webrtc::MediaStreamInterface;
    126 using webrtc::MediaStreamTrackInterface;
    127 using webrtc::PeerConnectionFactoryInterface;
    128 using webrtc::PeerConnectionInterface;
    129 using webrtc::PeerConnectionObserver;
    130 using webrtc::SessionDescriptionInterface;
    131 using webrtc::SetSessionDescriptionObserver;
    132 using webrtc::StatsObserver;
    133 using webrtc::StatsReport;
    134 using webrtc::VideoRendererInterface;
    135 using webrtc::VideoSourceInterface;
    136 using webrtc::VideoTrackInterface;
    137 using webrtc::VideoTrackVector;
    138 using webrtc::kVideoCodecVP8;
    139 
    140 // Abort the process if |jni| has a Java exception pending.
    141 // This macros uses the comma operator to execute ExceptionDescribe
    142 // and ExceptionClear ignoring their return values and sending ""
    143 // to the error stream.
    144 #define CHECK_EXCEPTION(jni)    \
    145   CHECK(!jni->ExceptionCheck()) \
    146       << (jni->ExceptionDescribe(), jni->ExceptionClear(), "")
    147 
    148 // Helper that calls ptr->Release() and aborts the process with a useful
    149 // message if that didn't actually delete *ptr because of extra refcounts.
    150 #define CHECK_RELEASE(ptr) \
    151   CHECK_EQ(0, (ptr)->Release()) << "Unexpected refcount."
    152 
    153 namespace {
    154 
    155 static JavaVM* g_jvm = NULL;  // Set in JNI_OnLoad().
    156 
    157 static pthread_once_t g_jni_ptr_once = PTHREAD_ONCE_INIT;
    158 // Key for per-thread JNIEnv* data.  Non-NULL in threads attached to |g_jvm| by
    159 // AttachCurrentThreadIfNeeded(), NULL in unattached threads and threads that
    160 // were attached by the JVM because of a Java->native call.
    161 static pthread_key_t g_jni_ptr;
    162 
    163 #if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
    164 // Set in PeerConnectionFactory_initializeAndroidGlobals().
    165 static bool factory_static_initialized = false;
    166 #endif
    167 
    168 
    169 // Return thread ID as a string.
    170 static std::string GetThreadId() {
    171   char buf[21];  // Big enough to hold a kuint64max plus terminating NULL.
    172   CHECK_LT(snprintf(buf, sizeof(buf), "%llu", syscall(__NR_gettid)),
    173            sizeof(buf))
    174       << "Thread id is bigger than uint64??";
    175   return std::string(buf);
    176 }
    177 
    178 // Return the current thread's name.
    179 static std::string GetThreadName() {
    180   char name[17];
    181   CHECK_EQ(0, prctl(PR_GET_NAME, name)) << "prctl(PR_GET_NAME) failed";
    182   name[16] = '\0';
    183   return std::string(name);
    184 }
    185 
    186 // Return a |JNIEnv*| usable on this thread or NULL if this thread is detached.
    187 static JNIEnv* GetEnv() {
    188   void* env = NULL;
    189   jint status = g_jvm->GetEnv(&env, JNI_VERSION_1_6);
    190   CHECK(((env != NULL) && (status == JNI_OK)) ||
    191         ((env == NULL) && (status == JNI_EDETACHED)))
    192       << "Unexpected GetEnv return: " << status << ":" << env;
    193   return reinterpret_cast<JNIEnv*>(env);
    194 }
    195 
    196 static void ThreadDestructor(void* prev_jni_ptr) {
    197   // This function only runs on threads where |g_jni_ptr| is non-NULL, meaning
    198   // we were responsible for originally attaching the thread, so are responsible
    199   // for detaching it now.  However, because some JVM implementations (notably
    200   // Oracle's http://goo.gl/eHApYT) also use the pthread_key_create mechanism,
    201   // the JVMs accounting info for this thread may already be wiped out by the
    202   // time this is called. Thus it may appear we are already detached even though
    203   // it was our responsibility to detach!  Oh well.
    204   if (!GetEnv())
    205     return;
    206 
    207   CHECK(GetEnv() == prev_jni_ptr)
    208       << "Detaching from another thread: " << prev_jni_ptr << ":" << GetEnv();
    209   jint status = g_jvm->DetachCurrentThread();
    210   CHECK(status == JNI_OK) << "Failed to detach thread: " << status;
    211   CHECK(!GetEnv()) << "Detaching was a successful no-op???";
    212 }
    213 
    214 static void CreateJNIPtrKey() {
    215   CHECK(!pthread_key_create(&g_jni_ptr, &ThreadDestructor))
    216       << "pthread_key_create";
    217 }
    218 
    219 // Return a |JNIEnv*| usable on this thread.  Attaches to |g_jvm| if necessary.
    220 static JNIEnv* AttachCurrentThreadIfNeeded() {
    221   JNIEnv* jni = GetEnv();
    222   if (jni)
    223     return jni;
    224   CHECK(!pthread_getspecific(g_jni_ptr))
    225       << "TLS has a JNIEnv* but not attached?";
    226 
    227   char* name = strdup((GetThreadName() + " - " + GetThreadId()).c_str());
    228   JavaVMAttachArgs args;
    229   args.version = JNI_VERSION_1_6;
    230   args.name = name;
    231   args.group = NULL;
    232   // Deal with difference in signatures between Oracle's jni.h and Android's.
    233 #ifdef _JAVASOFT_JNI_H_  // Oracle's jni.h violates the JNI spec!
    234   void* env = NULL;
    235 #else
    236   JNIEnv* env = NULL;
    237 #endif
    238   CHECK(!g_jvm->AttachCurrentThread(&env, &args)) << "Failed to attach thread";
    239   free(name);
    240   CHECK(env) << "AttachCurrentThread handed back NULL!";
    241   jni = reinterpret_cast<JNIEnv*>(env);
    242   CHECK(!pthread_setspecific(g_jni_ptr, jni)) << "pthread_setspecific";
    243   return jni;
    244 }
    245 
    246 // Return a |jlong| that will correctly convert back to |ptr|.  This is needed
    247 // because the alternative (of silently passing a 32-bit pointer to a vararg
    248 // function expecting a 64-bit param) picks up garbage in the high 32 bits.
    249 static jlong jlongFromPointer(void* ptr) {
    250   COMPILE_ASSERT(sizeof(intptr_t) <= sizeof(jlong),
    251                  Time_to_rethink_the_use_of_jlongs);
    252   // Going through intptr_t to be obvious about the definedness of the
    253   // conversion from pointer to integral type.  intptr_t to jlong is a standard
    254   // widening by the COMPILE_ASSERT above.
    255   jlong ret = reinterpret_cast<intptr_t>(ptr);
    256   assert(reinterpret_cast<void*>(ret) == ptr);
    257   return ret;
    258 }
    259 
    260 // Android's FindClass() is trickier than usual because the app-specific
    261 // ClassLoader is not consulted when there is no app-specific frame on the
    262 // stack.  Consequently, we only look up classes once in JNI_OnLoad.
    263 // http://developer.android.com/training/articles/perf-jni.html#faq_FindClass
    264 class ClassReferenceHolder {
    265  public:
    266   explicit ClassReferenceHolder(JNIEnv* jni) {
    267     LoadClass(jni, "java/nio/ByteBuffer");
    268     LoadClass(jni, "org/webrtc/AudioTrack");
    269     LoadClass(jni, "org/webrtc/DataChannel");
    270     LoadClass(jni, "org/webrtc/DataChannel$Buffer");
    271     LoadClass(jni, "org/webrtc/DataChannel$Init");
    272     LoadClass(jni, "org/webrtc/DataChannel$State");
    273     LoadClass(jni, "org/webrtc/IceCandidate");
    274 #if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
    275     LoadClass(jni, "android/graphics/SurfaceTexture");
    276     LoadClass(jni, "android/opengl/EGLContext");
    277     LoadClass(jni, "org/webrtc/MediaCodecVideoEncoder");
    278     LoadClass(jni, "org/webrtc/MediaCodecVideoEncoder$OutputBufferInfo");
    279     LoadClass(jni, "org/webrtc/MediaCodecVideoDecoder");
    280     LoadClass(jni, "org/webrtc/MediaCodecVideoDecoder$DecoderOutputBufferInfo");
    281 #endif
    282     LoadClass(jni, "org/webrtc/MediaSource$State");
    283     LoadClass(jni, "org/webrtc/MediaStream");
    284     LoadClass(jni, "org/webrtc/MediaStreamTrack$State");
    285     LoadClass(jni, "org/webrtc/PeerConnection$IceConnectionState");
    286     LoadClass(jni, "org/webrtc/PeerConnection$IceGatheringState");
    287     LoadClass(jni, "org/webrtc/PeerConnection$SignalingState");
    288     LoadClass(jni, "org/webrtc/SessionDescription");
    289     LoadClass(jni, "org/webrtc/SessionDescription$Type");
    290     LoadClass(jni, "org/webrtc/StatsReport");
    291     LoadClass(jni, "org/webrtc/StatsReport$Value");
    292     LoadClass(jni, "org/webrtc/VideoRenderer$I420Frame");
    293     LoadClass(jni, "org/webrtc/VideoTrack");
    294   }
    295 
    296   ~ClassReferenceHolder() {
    297     CHECK(classes_.empty()) << "Must call FreeReferences() before dtor!";
    298   }
    299 
    300   void FreeReferences(JNIEnv* jni) {
    301     for (std::map<std::string, jclass>::const_iterator it = classes_.begin();
    302          it != classes_.end(); ++it) {
    303       jni->DeleteGlobalRef(it->second);
    304     }
    305     classes_.clear();
    306   }
    307 
    308   jclass GetClass(const std::string& name) {
    309     std::map<std::string, jclass>::iterator it = classes_.find(name);
    310     CHECK(it != classes_.end()) << "Unexpected GetClass() call for: " << name;
    311     return it->second;
    312   }
    313 
    314  private:
    315   void LoadClass(JNIEnv* jni, const std::string& name) {
    316     jclass localRef = jni->FindClass(name.c_str());
    317     CHECK_EXCEPTION(jni) << "error during FindClass: " << name;
    318     CHECK(localRef) << name;
    319     jclass globalRef = reinterpret_cast<jclass>(jni->NewGlobalRef(localRef));
    320     CHECK_EXCEPTION(jni) << "error during NewGlobalRef: " << name;
    321     CHECK(globalRef) << name;
    322     bool inserted = classes_.insert(std::make_pair(name, globalRef)).second;
    323     CHECK(inserted) << "Duplicate class name: " << name;
    324   }
    325 
    326   std::map<std::string, jclass> classes_;
    327 };
    328 
    329 // Allocated in JNI_OnLoad(), freed in JNI_OnUnLoad().
    330 static ClassReferenceHolder* g_class_reference_holder = NULL;
    331 
    332 // JNIEnv-helper methods that CHECK success: no Java exception thrown and found
    333 // object/class/method/field is non-null.
    334 jmethodID GetMethodID(
    335     JNIEnv* jni, jclass c, const std::string& name, const char* signature) {
    336   jmethodID m = jni->GetMethodID(c, name.c_str(), signature);
    337   CHECK_EXCEPTION(jni) << "error during GetMethodID: " << name << ", "
    338                        << signature;
    339   CHECK(m) << name << ", " << signature;
    340   return m;
    341 }
    342 
    343 jmethodID GetStaticMethodID(
    344     JNIEnv* jni, jclass c, const char* name, const char* signature) {
    345   jmethodID m = jni->GetStaticMethodID(c, name, signature);
    346   CHECK_EXCEPTION(jni) << "error during GetStaticMethodID: " << name << ", "
    347                        << signature;
    348   CHECK(m) << name << ", " << signature;
    349   return m;
    350 }
    351 
    352 jfieldID GetFieldID(
    353     JNIEnv* jni, jclass c, const char* name, const char* signature) {
    354   jfieldID f = jni->GetFieldID(c, name, signature);
    355   CHECK_EXCEPTION(jni) << "error during GetFieldID";
    356   CHECK(f) << name << ", " << signature;
    357   return f;
    358 }
    359 
    360 // Returns a global reference guaranteed to be valid for the lifetime of the
    361 // process.
    362 jclass FindClass(JNIEnv* jni, const char* name) {
    363   return g_class_reference_holder->GetClass(name);
    364 }
    365 
    366 jclass GetObjectClass(JNIEnv* jni, jobject object) {
    367   jclass c = jni->GetObjectClass(object);
    368   CHECK_EXCEPTION(jni) << "error during GetObjectClass";
    369   CHECK(c) << "GetObjectClass returned NULL";
    370   return c;
    371 }
    372 
    373 jobject GetObjectField(JNIEnv* jni, jobject object, jfieldID id) {
    374   jobject o = jni->GetObjectField(object, id);
    375   CHECK_EXCEPTION(jni) << "error during GetObjectField";
    376   CHECK(o) << "GetObjectField returned NULL";
    377   return o;
    378 }
    379 
    380 jstring GetStringField(JNIEnv* jni, jobject object, jfieldID id) {
    381   return static_cast<jstring>(GetObjectField(jni, object, id));
    382 }
    383 
    384 jlong GetLongField(JNIEnv* jni, jobject object, jfieldID id) {
    385   jlong l = jni->GetLongField(object, id);
    386   CHECK_EXCEPTION(jni) << "error during GetLongField";
    387   return l;
    388 }
    389 
    390 jint GetIntField(JNIEnv* jni, jobject object, jfieldID id) {
    391   jint i = jni->GetIntField(object, id);
    392   CHECK_EXCEPTION(jni) << "error during GetIntField";
    393   return i;
    394 }
    395 
    396 bool GetBooleanField(JNIEnv* jni, jobject object, jfieldID id) {
    397   jboolean b = jni->GetBooleanField(object, id);
    398   CHECK_EXCEPTION(jni) << "error during GetBooleanField";
    399   return b;
    400 }
    401 
    402 jobject NewGlobalRef(JNIEnv* jni, jobject o) {
    403   jobject ret = jni->NewGlobalRef(o);
    404   CHECK_EXCEPTION(jni) << "error during NewGlobalRef";
    405   CHECK(ret);
    406   return ret;
    407 }
    408 
    409 void DeleteGlobalRef(JNIEnv* jni, jobject o) {
    410   jni->DeleteGlobalRef(o);
    411   CHECK_EXCEPTION(jni) << "error during DeleteGlobalRef";
    412 }
    413 
    414 // Given a jweak reference, allocate a (strong) local reference scoped to the
    415 // lifetime of this object if the weak reference is still valid, or NULL
    416 // otherwise.
    417 class WeakRef {
    418  public:
    419   WeakRef(JNIEnv* jni, jweak ref)
    420       : jni_(jni), obj_(jni_->NewLocalRef(ref)) {
    421     CHECK_EXCEPTION(jni) << "error during NewLocalRef";
    422   }
    423   ~WeakRef() {
    424     if (obj_) {
    425       jni_->DeleteLocalRef(obj_);
    426       CHECK_EXCEPTION(jni_) << "error during DeleteLocalRef";
    427     }
    428   }
    429   jobject obj() { return obj_; }
    430 
    431  private:
    432   JNIEnv* const jni_;
    433   jobject const obj_;
    434 };
    435 
    436 // Scope Java local references to the lifetime of this object.  Use in all C++
    437 // callbacks (i.e. entry points that don't originate in a Java callstack
    438 // through a "native" method call).
    439 class ScopedLocalRefFrame {
    440  public:
    441   explicit ScopedLocalRefFrame(JNIEnv* jni) : jni_(jni) {
    442     CHECK(!jni_->PushLocalFrame(0)) << "Failed to PushLocalFrame";
    443   }
    444   ~ScopedLocalRefFrame() {
    445     jni_->PopLocalFrame(NULL);
    446   }
    447 
    448  private:
    449   JNIEnv* jni_;
    450 };
    451 
    452 // Scoped holder for global Java refs.
    453 template<class T>  // T is jclass, jobject, jintArray, etc.
    454 class ScopedGlobalRef {
    455  public:
    456   ScopedGlobalRef(JNIEnv* jni, T obj)
    457       : obj_(static_cast<T>(jni->NewGlobalRef(obj))) {}
    458   ~ScopedGlobalRef() {
    459     DeleteGlobalRef(AttachCurrentThreadIfNeeded(), obj_);
    460   }
    461   T operator*() const {
    462     return obj_;
    463   }
    464  private:
    465   T obj_;
    466 };
    467 
    468 // Java references to "null" can only be distinguished as such in C++ by
    469 // creating a local reference, so this helper wraps that logic.
    470 static bool IsNull(JNIEnv* jni, jobject obj) {
    471   ScopedLocalRefFrame local_ref_frame(jni);
    472   return jni->NewLocalRef(obj) == NULL;
    473 }
    474 
    475 // Return the (singleton) Java Enum object corresponding to |index|;
    476 // |state_class_fragment| is something like "MediaSource$State".
    477 jobject JavaEnumFromIndex(
    478     JNIEnv* jni, const std::string& state_class_fragment, int index) {
    479   std::string state_class_name = "org/webrtc/" + state_class_fragment;
    480   jclass state_class = FindClass(jni, state_class_name.c_str());
    481   jmethodID state_values_id = GetStaticMethodID(
    482       jni, state_class, "values", ("()[L" + state_class_name  + ";").c_str());
    483   jobjectArray state_values = static_cast<jobjectArray>(
    484       jni->CallStaticObjectMethod(state_class, state_values_id));
    485   CHECK_EXCEPTION(jni) << "error during CallStaticObjectMethod";
    486   jobject ret = jni->GetObjectArrayElement(state_values, index);
    487   CHECK_EXCEPTION(jni) << "error during GetObjectArrayElement";
    488   return ret;
    489 }
    490 
    491 // Given a UTF-8 encoded |native| string return a new (UTF-16) jstring.
    492 static jstring JavaStringFromStdString(JNIEnv* jni, const std::string& native) {
    493   UnicodeString ustr(UnicodeString::fromUTF8(native));
    494   jstring jstr = jni->NewString(ustr.getBuffer(), ustr.length());
    495   CHECK_EXCEPTION(jni) << "error during NewString";
    496   return jstr;
    497 }
    498 
    499 // Given a (UTF-16) jstring return a new UTF-8 native string.
    500 static std::string JavaToStdString(JNIEnv* jni, const jstring& j_string) {
    501   const jchar* jchars = jni->GetStringChars(j_string, NULL);
    502   CHECK_EXCEPTION(jni) << "Error during GetStringChars";
    503   UnicodeString ustr(jchars, jni->GetStringLength(j_string));
    504   CHECK_EXCEPTION(jni) << "Error during GetStringLength";
    505   jni->ReleaseStringChars(j_string, jchars);
    506   CHECK_EXCEPTION(jni) << "Error during ReleaseStringChars";
    507   std::string ret;
    508   return ustr.toUTF8String(ret);
    509 }
    510 
    511 static DataChannelInit JavaDataChannelInitToNative(
    512     JNIEnv* jni, jobject j_init) {
    513   DataChannelInit init;
    514 
    515   jclass j_init_class = FindClass(jni, "org/webrtc/DataChannel$Init");
    516   jfieldID ordered_id = GetFieldID(jni, j_init_class, "ordered", "Z");
    517   jfieldID max_retransmit_time_id =
    518       GetFieldID(jni, j_init_class, "maxRetransmitTimeMs", "I");
    519   jfieldID max_retransmits_id =
    520       GetFieldID(jni, j_init_class, "maxRetransmits", "I");
    521   jfieldID protocol_id =
    522       GetFieldID(jni, j_init_class, "protocol", "Ljava/lang/String;");
    523   jfieldID negotiated_id = GetFieldID(jni, j_init_class, "negotiated", "Z");
    524   jfieldID id_id = GetFieldID(jni, j_init_class, "id", "I");
    525 
    526   init.ordered = GetBooleanField(jni, j_init, ordered_id);
    527   init.maxRetransmitTime = GetIntField(jni, j_init, max_retransmit_time_id);
    528   init.maxRetransmits = GetIntField(jni, j_init, max_retransmits_id);
    529   init.protocol = JavaToStdString(
    530       jni, GetStringField(jni, j_init, protocol_id));
    531   init.negotiated = GetBooleanField(jni, j_init, negotiated_id);
    532   init.id = GetIntField(jni, j_init, id_id);
    533 
    534   return init;
    535 }
    536 
    537 class ConstraintsWrapper;
    538 
    539 // Adapter between the C++ PeerConnectionObserver interface and the Java
    540 // PeerConnection.Observer interface.  Wraps an instance of the Java interface
    541 // and dispatches C++ callbacks to Java.
    542 class PCOJava : public PeerConnectionObserver {
    543  public:
    544   PCOJava(JNIEnv* jni, jobject j_observer)
    545       : j_observer_global_(jni, j_observer),
    546         j_observer_class_(jni, GetObjectClass(jni, *j_observer_global_)),
    547         j_media_stream_class_(jni, FindClass(jni, "org/webrtc/MediaStream")),
    548         j_media_stream_ctor_(GetMethodID(
    549             jni, *j_media_stream_class_, "<init>", "(J)V")),
    550         j_audio_track_class_(jni, FindClass(jni, "org/webrtc/AudioTrack")),
    551         j_audio_track_ctor_(GetMethodID(
    552             jni, *j_audio_track_class_, "<init>", "(J)V")),
    553         j_video_track_class_(jni, FindClass(jni, "org/webrtc/VideoTrack")),
    554         j_video_track_ctor_(GetMethodID(
    555             jni, *j_video_track_class_, "<init>", "(J)V")),
    556         j_data_channel_class_(jni, FindClass(jni, "org/webrtc/DataChannel")),
    557         j_data_channel_ctor_(GetMethodID(
    558             jni, *j_data_channel_class_, "<init>", "(J)V")) {
    559   }
    560 
    561   virtual ~PCOJava() {}
    562 
    563   virtual void OnIceCandidate(const IceCandidateInterface* candidate) OVERRIDE {
    564     ScopedLocalRefFrame local_ref_frame(jni());
    565     std::string sdp;
    566     CHECK(candidate->ToString(&sdp)) << "got so far: " << sdp;
    567     jclass candidate_class = FindClass(jni(), "org/webrtc/IceCandidate");
    568     jmethodID ctor = GetMethodID(jni(), candidate_class,
    569         "<init>", "(Ljava/lang/String;ILjava/lang/String;)V");
    570     jstring j_mid = JavaStringFromStdString(jni(), candidate->sdp_mid());
    571     jstring j_sdp = JavaStringFromStdString(jni(), sdp);
    572     jobject j_candidate = jni()->NewObject(
    573         candidate_class, ctor, j_mid, candidate->sdp_mline_index(), j_sdp);
    574     CHECK_EXCEPTION(jni()) << "error during NewObject";
    575     jmethodID m = GetMethodID(jni(), *j_observer_class_,
    576                               "onIceCandidate", "(Lorg/webrtc/IceCandidate;)V");
    577     jni()->CallVoidMethod(*j_observer_global_, m, j_candidate);
    578     CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
    579   }
    580 
    581   virtual void OnError() OVERRIDE {
    582     ScopedLocalRefFrame local_ref_frame(jni());
    583     jmethodID m = GetMethodID(jni(), *j_observer_class_, "onError", "()V");
    584     jni()->CallVoidMethod(*j_observer_global_, m);
    585     CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
    586   }
    587 
    588   virtual void OnSignalingChange(
    589       PeerConnectionInterface::SignalingState new_state) OVERRIDE {
    590     ScopedLocalRefFrame local_ref_frame(jni());
    591     jmethodID m = GetMethodID(
    592         jni(), *j_observer_class_, "onSignalingChange",
    593         "(Lorg/webrtc/PeerConnection$SignalingState;)V");
    594     jobject new_state_enum =
    595         JavaEnumFromIndex(jni(), "PeerConnection$SignalingState", new_state);
    596     jni()->CallVoidMethod(*j_observer_global_, m, new_state_enum);
    597     CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
    598   }
    599 
    600   virtual void OnIceConnectionChange(
    601       PeerConnectionInterface::IceConnectionState new_state) OVERRIDE {
    602     ScopedLocalRefFrame local_ref_frame(jni());
    603     jmethodID m = GetMethodID(
    604         jni(), *j_observer_class_, "onIceConnectionChange",
    605         "(Lorg/webrtc/PeerConnection$IceConnectionState;)V");
    606     jobject new_state_enum = JavaEnumFromIndex(
    607         jni(), "PeerConnection$IceConnectionState", new_state);
    608     jni()->CallVoidMethod(*j_observer_global_, m, new_state_enum);
    609     CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
    610   }
    611 
    612   virtual void OnIceGatheringChange(
    613       PeerConnectionInterface::IceGatheringState new_state) OVERRIDE {
    614     ScopedLocalRefFrame local_ref_frame(jni());
    615     jmethodID m = GetMethodID(
    616         jni(), *j_observer_class_, "onIceGatheringChange",
    617         "(Lorg/webrtc/PeerConnection$IceGatheringState;)V");
    618     jobject new_state_enum = JavaEnumFromIndex(
    619         jni(), "PeerConnection$IceGatheringState", new_state);
    620     jni()->CallVoidMethod(*j_observer_global_, m, new_state_enum);
    621     CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
    622   }
    623 
    624   virtual void OnAddStream(MediaStreamInterface* stream) OVERRIDE {
    625     ScopedLocalRefFrame local_ref_frame(jni());
    626     jobject j_stream = jni()->NewObject(
    627         *j_media_stream_class_, j_media_stream_ctor_, (jlong)stream);
    628     CHECK_EXCEPTION(jni()) << "error during NewObject";
    629 
    630     AudioTrackVector audio_tracks = stream->GetAudioTracks();
    631     for (size_t i = 0; i < audio_tracks.size(); ++i) {
    632       AudioTrackInterface* track = audio_tracks[i];
    633       jstring id = JavaStringFromStdString(jni(), track->id());
    634       jobject j_track = jni()->NewObject(
    635           *j_audio_track_class_, j_audio_track_ctor_, (jlong)track, id);
    636       CHECK_EXCEPTION(jni()) << "error during NewObject";
    637       jfieldID audio_tracks_id = GetFieldID(jni(),
    638                                             *j_media_stream_class_,
    639                                             "audioTracks",
    640                                             "Ljava/util/LinkedList;");
    641       jobject audio_tracks = GetObjectField(jni(), j_stream, audio_tracks_id);
    642       jmethodID add = GetMethodID(jni(),
    643                                   GetObjectClass(jni(), audio_tracks),
    644                                   "add",
    645                                   "(Ljava/lang/Object;)Z");
    646       jboolean added = jni()->CallBooleanMethod(audio_tracks, add, j_track);
    647       CHECK_EXCEPTION(jni()) << "error during CallBooleanMethod";
    648       CHECK(added);
    649     }
    650 
    651     VideoTrackVector video_tracks = stream->GetVideoTracks();
    652     for (size_t i = 0; i < video_tracks.size(); ++i) {
    653       VideoTrackInterface* track = video_tracks[i];
    654       jstring id = JavaStringFromStdString(jni(), track->id());
    655       jobject j_track = jni()->NewObject(
    656           *j_video_track_class_, j_video_track_ctor_, (jlong)track, id);
    657       CHECK_EXCEPTION(jni()) << "error during NewObject";
    658       jfieldID video_tracks_id = GetFieldID(jni(),
    659                                             *j_media_stream_class_,
    660                                             "videoTracks",
    661                                             "Ljava/util/LinkedList;");
    662       jobject video_tracks = GetObjectField(jni(), j_stream, video_tracks_id);
    663       jmethodID add = GetMethodID(jni(),
    664                                   GetObjectClass(jni(), video_tracks),
    665                                   "add",
    666                                   "(Ljava/lang/Object;)Z");
    667       jboolean added = jni()->CallBooleanMethod(video_tracks, add, j_track);
    668       CHECK_EXCEPTION(jni()) << "error during CallBooleanMethod";
    669       CHECK(added);
    670     }
    671     streams_[stream] = jni()->NewWeakGlobalRef(j_stream);
    672     CHECK_EXCEPTION(jni()) << "error during NewWeakGlobalRef";
    673 
    674     jmethodID m = GetMethodID(jni(), *j_observer_class_, "onAddStream",
    675                               "(Lorg/webrtc/MediaStream;)V");
    676     jni()->CallVoidMethod(*j_observer_global_, m, j_stream);
    677     CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
    678   }
    679 
    680   virtual void OnRemoveStream(MediaStreamInterface* stream) OVERRIDE {
    681     ScopedLocalRefFrame local_ref_frame(jni());
    682     NativeToJavaStreamsMap::iterator it = streams_.find(stream);
    683     CHECK(it != streams_.end()) << "unexpected stream: " << std::hex << stream;
    684 
    685     WeakRef s(jni(), it->second);
    686     streams_.erase(it);
    687     if (!s.obj())
    688       return;
    689 
    690     jmethodID m = GetMethodID(jni(), *j_observer_class_, "onRemoveStream",
    691                               "(Lorg/webrtc/MediaStream;)V");
    692     jni()->CallVoidMethod(*j_observer_global_, m, s.obj());
    693     CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
    694   }
    695 
    696   virtual void OnDataChannel(DataChannelInterface* channel) OVERRIDE {
    697     ScopedLocalRefFrame local_ref_frame(jni());
    698     jobject j_channel = jni()->NewObject(
    699         *j_data_channel_class_, j_data_channel_ctor_, (jlong)channel);
    700     CHECK_EXCEPTION(jni()) << "error during NewObject";
    701 
    702     jmethodID m = GetMethodID(jni(), *j_observer_class_, "onDataChannel",
    703                               "(Lorg/webrtc/DataChannel;)V");
    704     jni()->CallVoidMethod(*j_observer_global_, m, j_channel);
    705 
    706     // Channel is now owned by Java object, and will be freed from
    707     // DataChannel.dispose().  Important that this be done _after_ the
    708     // CallVoidMethod above as Java code might call back into native code and be
    709     // surprised to see a refcount of 2.
    710     int bumped_count = channel->AddRef();
    711     CHECK(bumped_count == 2) << "Unexpected refcount OnDataChannel";
    712 
    713     CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
    714   }
    715 
    716   virtual void OnRenegotiationNeeded() OVERRIDE {
    717     ScopedLocalRefFrame local_ref_frame(jni());
    718     jmethodID m =
    719         GetMethodID(jni(), *j_observer_class_, "onRenegotiationNeeded", "()V");
    720     jni()->CallVoidMethod(*j_observer_global_, m);
    721     CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
    722   }
    723 
    724   void SetConstraints(ConstraintsWrapper* constraints) {
    725     CHECK(!constraints_.get()) << "constraints already set!";
    726     constraints_.reset(constraints);
    727   }
    728 
    729   const ConstraintsWrapper* constraints() { return constraints_.get(); }
    730 
    731  private:
    732   JNIEnv* jni() {
    733     return AttachCurrentThreadIfNeeded();
    734   }
    735 
    736   const ScopedGlobalRef<jobject> j_observer_global_;
    737   const ScopedGlobalRef<jclass> j_observer_class_;
    738   const ScopedGlobalRef<jclass> j_media_stream_class_;
    739   const jmethodID j_media_stream_ctor_;
    740   const ScopedGlobalRef<jclass> j_audio_track_class_;
    741   const jmethodID j_audio_track_ctor_;
    742   const ScopedGlobalRef<jclass> j_video_track_class_;
    743   const jmethodID j_video_track_ctor_;
    744   const ScopedGlobalRef<jclass> j_data_channel_class_;
    745   const jmethodID j_data_channel_ctor_;
    746   typedef std::map<void*, jweak> NativeToJavaStreamsMap;
    747   NativeToJavaStreamsMap streams_;  // C++ -> Java streams.
    748   scoped_ptr<ConstraintsWrapper> constraints_;
    749 };
    750 
    751 // Wrapper for a Java MediaConstraints object.  Copies all needed data so when
    752 // the constructor returns the Java object is no longer needed.
    753 class ConstraintsWrapper : public MediaConstraintsInterface {
    754  public:
    755   ConstraintsWrapper(JNIEnv* jni, jobject j_constraints) {
    756     PopulateConstraintsFromJavaPairList(
    757         jni, j_constraints, "mandatory", &mandatory_);
    758     PopulateConstraintsFromJavaPairList(
    759         jni, j_constraints, "optional", &optional_);
    760   }
    761 
    762   virtual ~ConstraintsWrapper() {}
    763 
    764   // MediaConstraintsInterface.
    765   virtual const Constraints& GetMandatory() const OVERRIDE {
    766     return mandatory_;
    767   }
    768 
    769   virtual const Constraints& GetOptional() const OVERRIDE {
    770     return optional_;
    771   }
    772 
    773  private:
    774   // Helper for translating a List<Pair<String, String>> to a Constraints.
    775   static void PopulateConstraintsFromJavaPairList(
    776       JNIEnv* jni, jobject j_constraints,
    777       const char* field_name, Constraints* field) {
    778     jfieldID j_id = GetFieldID(jni,
    779         GetObjectClass(jni, j_constraints), field_name, "Ljava/util/List;");
    780     jobject j_list = GetObjectField(jni, j_constraints, j_id);
    781     jmethodID j_iterator_id = GetMethodID(jni,
    782         GetObjectClass(jni, j_list), "iterator", "()Ljava/util/Iterator;");
    783     jobject j_iterator = jni->CallObjectMethod(j_list, j_iterator_id);
    784     CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
    785     jmethodID j_has_next = GetMethodID(jni,
    786         GetObjectClass(jni, j_iterator), "hasNext", "()Z");
    787     jmethodID j_next = GetMethodID(jni,
    788         GetObjectClass(jni, j_iterator), "next", "()Ljava/lang/Object;");
    789     while (jni->CallBooleanMethod(j_iterator, j_has_next)) {
    790       CHECK_EXCEPTION(jni) << "error during CallBooleanMethod";
    791       jobject entry = jni->CallObjectMethod(j_iterator, j_next);
    792       CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
    793       jmethodID get_key = GetMethodID(jni,
    794           GetObjectClass(jni, entry), "getKey", "()Ljava/lang/String;");
    795       jstring j_key = reinterpret_cast<jstring>(
    796           jni->CallObjectMethod(entry, get_key));
    797       CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
    798       jmethodID get_value = GetMethodID(jni,
    799           GetObjectClass(jni, entry), "getValue", "()Ljava/lang/String;");
    800       jstring j_value = reinterpret_cast<jstring>(
    801           jni->CallObjectMethod(entry, get_value));
    802       CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
    803       field->push_back(Constraint(JavaToStdString(jni, j_key),
    804                                   JavaToStdString(jni, j_value)));
    805     }
    806     CHECK_EXCEPTION(jni) << "error during CallBooleanMethod";
    807   }
    808 
    809   Constraints mandatory_;
    810   Constraints optional_;
    811 };
    812 
    813 static jobject JavaSdpFromNativeSdp(
    814     JNIEnv* jni, const SessionDescriptionInterface* desc) {
    815   std::string sdp;
    816   CHECK(desc->ToString(&sdp)) << "got so far: " << sdp;
    817   jstring j_description = JavaStringFromStdString(jni, sdp);
    818 
    819   jclass j_type_class = FindClass(
    820       jni, "org/webrtc/SessionDescription$Type");
    821   jmethodID j_type_from_canonical = GetStaticMethodID(
    822       jni, j_type_class, "fromCanonicalForm",
    823       "(Ljava/lang/String;)Lorg/webrtc/SessionDescription$Type;");
    824   jstring j_type_string = JavaStringFromStdString(jni, desc->type());
    825   jobject j_type = jni->CallStaticObjectMethod(
    826       j_type_class, j_type_from_canonical, j_type_string);
    827   CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
    828 
    829   jclass j_sdp_class = FindClass(jni, "org/webrtc/SessionDescription");
    830   jmethodID j_sdp_ctor = GetMethodID(
    831       jni, j_sdp_class, "<init>",
    832       "(Lorg/webrtc/SessionDescription$Type;Ljava/lang/String;)V");
    833   jobject j_sdp = jni->NewObject(
    834       j_sdp_class, j_sdp_ctor, j_type, j_description);
    835   CHECK_EXCEPTION(jni) << "error during NewObject";
    836   return j_sdp;
    837 }
    838 
    839 template <class T>  // T is one of {Create,Set}SessionDescriptionObserver.
    840 class SdpObserverWrapper : public T {
    841  public:
    842   SdpObserverWrapper(JNIEnv* jni, jobject j_observer,
    843                      ConstraintsWrapper* constraints)
    844       : constraints_(constraints),
    845         j_observer_global_(jni, j_observer),
    846         j_observer_class_(jni, GetObjectClass(jni, j_observer)) {
    847   }
    848 
    849   virtual ~SdpObserverWrapper() {}
    850 
    851   // Can't mark OVERRIDE because of templating.
    852   virtual void OnSuccess() {
    853     ScopedLocalRefFrame local_ref_frame(jni());
    854     jmethodID m = GetMethodID(jni(), *j_observer_class_, "onSetSuccess", "()V");
    855     jni()->CallVoidMethod(*j_observer_global_, m);
    856     CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
    857   }
    858 
    859   // Can't mark OVERRIDE because of templating.
    860   virtual void OnSuccess(SessionDescriptionInterface* desc) {
    861     ScopedLocalRefFrame local_ref_frame(jni());
    862     jmethodID m = GetMethodID(
    863         jni(), *j_observer_class_, "onCreateSuccess",
    864         "(Lorg/webrtc/SessionDescription;)V");
    865     jobject j_sdp = JavaSdpFromNativeSdp(jni(), desc);
    866     jni()->CallVoidMethod(*j_observer_global_, m, j_sdp);
    867     CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
    868   }
    869 
    870  protected:
    871   // Common implementation for failure of Set & Create types, distinguished by
    872   // |op| being "Set" or "Create".
    873   void OnFailure(const std::string& op, const std::string& error) {
    874     jmethodID m = GetMethodID(jni(), *j_observer_class_, "on" + op + "Failure",
    875                               "(Ljava/lang/String;)V");
    876     jstring j_error_string = JavaStringFromStdString(jni(), error);
    877     jni()->CallVoidMethod(*j_observer_global_, m, j_error_string);
    878     CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
    879   }
    880 
    881   JNIEnv* jni() {
    882     return AttachCurrentThreadIfNeeded();
    883   }
    884 
    885  private:
    886   scoped_ptr<ConstraintsWrapper> constraints_;
    887   const ScopedGlobalRef<jobject> j_observer_global_;
    888   const ScopedGlobalRef<jclass> j_observer_class_;
    889 };
    890 
    891 class CreateSdpObserverWrapper
    892     : public SdpObserverWrapper<CreateSessionDescriptionObserver> {
    893  public:
    894   CreateSdpObserverWrapper(JNIEnv* jni, jobject j_observer,
    895                            ConstraintsWrapper* constraints)
    896       : SdpObserverWrapper(jni, j_observer, constraints) {}
    897 
    898   virtual void OnFailure(const std::string& error) OVERRIDE {
    899     ScopedLocalRefFrame local_ref_frame(jni());
    900     SdpObserverWrapper::OnFailure(std::string("Create"), error);
    901   }
    902 };
    903 
    904 class SetSdpObserverWrapper
    905     : public SdpObserverWrapper<SetSessionDescriptionObserver> {
    906  public:
    907   SetSdpObserverWrapper(JNIEnv* jni, jobject j_observer,
    908                         ConstraintsWrapper* constraints)
    909       : SdpObserverWrapper(jni, j_observer, constraints) {}
    910 
    911   virtual void OnFailure(const std::string& error) OVERRIDE {
    912     ScopedLocalRefFrame local_ref_frame(jni());
    913     SdpObserverWrapper::OnFailure(std::string("Set"), error);
    914   }
    915 };
    916 
    917 // Adapter for a Java DataChannel$Observer presenting a C++ DataChannelObserver
    918 // and dispatching the callback from C++ back to Java.
    919 class DataChannelObserverWrapper : public DataChannelObserver {
    920  public:
    921   DataChannelObserverWrapper(JNIEnv* jni, jobject j_observer)
    922       : j_observer_global_(jni, j_observer),
    923         j_observer_class_(jni, GetObjectClass(jni, j_observer)),
    924         j_buffer_class_(jni, FindClass(jni, "org/webrtc/DataChannel$Buffer")),
    925         j_on_state_change_mid_(GetMethodID(jni, *j_observer_class_,
    926                                            "onStateChange", "()V")),
    927         j_on_message_mid_(GetMethodID(jni, *j_observer_class_, "onMessage",
    928                                       "(Lorg/webrtc/DataChannel$Buffer;)V")),
    929         j_buffer_ctor_(GetMethodID(jni, *j_buffer_class_,
    930                                    "<init>", "(Ljava/nio/ByteBuffer;Z)V")) {
    931   }
    932 
    933   virtual ~DataChannelObserverWrapper() {}
    934 
    935   virtual void OnStateChange() OVERRIDE {
    936     ScopedLocalRefFrame local_ref_frame(jni());
    937     jni()->CallVoidMethod(*j_observer_global_, j_on_state_change_mid_);
    938     CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
    939   }
    940 
    941   virtual void OnMessage(const DataBuffer& buffer) OVERRIDE {
    942     ScopedLocalRefFrame local_ref_frame(jni());
    943     jobject byte_buffer =
    944         jni()->NewDirectByteBuffer(const_cast<char*>(buffer.data.data()),
    945                                    buffer.data.length());
    946     jobject j_buffer = jni()->NewObject(*j_buffer_class_, j_buffer_ctor_,
    947                                         byte_buffer, buffer.binary);
    948     jni()->CallVoidMethod(*j_observer_global_, j_on_message_mid_, j_buffer);
    949     CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
    950   }
    951 
    952  private:
    953   JNIEnv* jni() {
    954     return AttachCurrentThreadIfNeeded();
    955   }
    956 
    957   const ScopedGlobalRef<jobject> j_observer_global_;
    958   const ScopedGlobalRef<jclass> j_observer_class_;
    959   const ScopedGlobalRef<jclass> j_buffer_class_;
    960   const jmethodID j_on_state_change_mid_;
    961   const jmethodID j_on_message_mid_;
    962   const jmethodID j_buffer_ctor_;
    963 };
    964 
    965 // Adapter for a Java StatsObserver presenting a C++ StatsObserver and
    966 // dispatching the callback from C++ back to Java.
    967 class StatsObserverWrapper : public StatsObserver {
    968  public:
    969   StatsObserverWrapper(JNIEnv* jni, jobject j_observer)
    970       : j_observer_global_(jni, j_observer),
    971         j_observer_class_(jni, GetObjectClass(jni, j_observer)),
    972         j_stats_report_class_(jni, FindClass(jni, "org/webrtc/StatsReport")),
    973         j_stats_report_ctor_(GetMethodID(
    974             jni, *j_stats_report_class_, "<init>",
    975             "(Ljava/lang/String;Ljava/lang/String;D"
    976             "[Lorg/webrtc/StatsReport$Value;)V")),
    977         j_value_class_(jni, FindClass(
    978             jni, "org/webrtc/StatsReport$Value")),
    979         j_value_ctor_(GetMethodID(
    980             jni, *j_value_class_, "<init>",
    981             "(Ljava/lang/String;Ljava/lang/String;)V")) {
    982   }
    983 
    984   virtual ~StatsObserverWrapper() {}
    985 
    986   virtual void OnComplete(const std::vector<StatsReport>& reports) OVERRIDE {
    987     ScopedLocalRefFrame local_ref_frame(jni());
    988     jobjectArray j_reports = ReportsToJava(jni(), reports);
    989     jmethodID m = GetMethodID(jni(), *j_observer_class_, "onComplete",
    990                               "([Lorg/webrtc/StatsReport;)V");
    991     jni()->CallVoidMethod(*j_observer_global_, m, j_reports);
    992     CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
    993   }
    994 
    995  private:
    996   jobjectArray ReportsToJava(
    997       JNIEnv* jni, const std::vector<StatsReport>& reports) {
    998     jobjectArray reports_array = jni->NewObjectArray(
    999         reports.size(), *j_stats_report_class_, NULL);
   1000     for (int i = 0; i < reports.size(); ++i) {
   1001       ScopedLocalRefFrame local_ref_frame(jni);
   1002       const StatsReport& report = reports[i];
   1003       jstring j_id = JavaStringFromStdString(jni, report.id);
   1004       jstring j_type = JavaStringFromStdString(jni, report.type);
   1005       jobjectArray j_values = ValuesToJava(jni, report.values);
   1006       jobject j_report = jni->NewObject(*j_stats_report_class_,
   1007                                         j_stats_report_ctor_,
   1008                                         j_id,
   1009                                         j_type,
   1010                                         report.timestamp,
   1011                                         j_values);
   1012       jni->SetObjectArrayElement(reports_array, i, j_report);
   1013     }
   1014     return reports_array;
   1015   }
   1016 
   1017   jobjectArray ValuesToJava(JNIEnv* jni, const StatsReport::Values& values) {
   1018     jobjectArray j_values = jni->NewObjectArray(
   1019         values.size(), *j_value_class_, NULL);
   1020     for (int i = 0; i < values.size(); ++i) {
   1021       ScopedLocalRefFrame local_ref_frame(jni);
   1022       const StatsReport::Value& value = values[i];
   1023       jstring j_name = JavaStringFromStdString(jni, value.name);
   1024       jstring j_value = JavaStringFromStdString(jni, value.value);
   1025       jobject j_element_value =
   1026           jni->NewObject(*j_value_class_, j_value_ctor_, j_name, j_value);
   1027       jni->SetObjectArrayElement(j_values, i, j_element_value);
   1028     }
   1029     return j_values;
   1030   }
   1031 
   1032   JNIEnv* jni() {
   1033     return AttachCurrentThreadIfNeeded();
   1034   }
   1035 
   1036   const ScopedGlobalRef<jobject> j_observer_global_;
   1037   const ScopedGlobalRef<jclass> j_observer_class_;
   1038   const ScopedGlobalRef<jclass> j_stats_report_class_;
   1039   const jmethodID j_stats_report_ctor_;
   1040   const ScopedGlobalRef<jclass> j_value_class_;
   1041   const jmethodID j_value_ctor_;
   1042 };
   1043 
   1044 // Adapter presenting a cricket::VideoRenderer as a
   1045 // webrtc::VideoRendererInterface.
   1046 class VideoRendererWrapper : public VideoRendererInterface {
   1047  public:
   1048   static VideoRendererWrapper* Create(cricket::VideoRenderer* renderer) {
   1049     if (renderer)
   1050       return new VideoRendererWrapper(renderer);
   1051     return NULL;
   1052   }
   1053 
   1054   virtual ~VideoRendererWrapper() {}
   1055 
   1056   virtual void SetSize(int width, int height) OVERRIDE {
   1057     ScopedLocalRefFrame local_ref_frame(AttachCurrentThreadIfNeeded());
   1058     const bool kNotReserved = false;  // What does this param mean??
   1059     renderer_->SetSize(width, height, kNotReserved);
   1060   }
   1061 
   1062   virtual void RenderFrame(const cricket::VideoFrame* frame) OVERRIDE {
   1063     ScopedLocalRefFrame local_ref_frame(AttachCurrentThreadIfNeeded());
   1064     renderer_->RenderFrame(frame);
   1065   }
   1066 
   1067  private:
   1068   explicit VideoRendererWrapper(cricket::VideoRenderer* renderer)
   1069       : renderer_(renderer) {}
   1070 
   1071   scoped_ptr<cricket::VideoRenderer> renderer_;
   1072 };
   1073 
   1074 // Wrapper for texture object in TextureVideoFrame.
   1075 class NativeHandleImpl : public NativeHandle {
   1076  public:
   1077   NativeHandleImpl() :
   1078     ref_count_(0), texture_object_(NULL), texture_id_(-1) {}
   1079   virtual ~NativeHandleImpl() {}
   1080   virtual int32_t AddRef() {
   1081     return ++ref_count_;
   1082   }
   1083   virtual int32_t Release() {
   1084     return --ref_count_;
   1085   }
   1086   virtual void* GetHandle() {
   1087     return texture_object_;
   1088   }
   1089   int GetTextureId() {
   1090     return texture_id_;
   1091   }
   1092   void SetTextureObject(void *texture_object, int texture_id) {
   1093     texture_object_ = reinterpret_cast<jobject>(texture_object);
   1094     texture_id_ = texture_id;
   1095   }
   1096   int32_t ref_count() {
   1097     return ref_count_;
   1098   }
   1099 
   1100  private:
   1101   int32_t ref_count_;
   1102   jobject texture_object_;
   1103   int32_t texture_id_;
   1104 };
   1105 
   1106 // Wrapper dispatching webrtc::VideoRendererInterface to a Java VideoRenderer
   1107 // instance.
   1108 class JavaVideoRendererWrapper : public VideoRendererInterface {
   1109  public:
   1110   JavaVideoRendererWrapper(JNIEnv* jni, jobject j_callbacks)
   1111       : j_callbacks_(jni, j_callbacks),
   1112         j_set_size_id_(GetMethodID(
   1113             jni, GetObjectClass(jni, j_callbacks), "setSize", "(II)V")),
   1114         j_render_frame_id_(GetMethodID(
   1115             jni, GetObjectClass(jni, j_callbacks), "renderFrame",
   1116             "(Lorg/webrtc/VideoRenderer$I420Frame;)V")),
   1117         j_frame_class_(jni,
   1118                        FindClass(jni, "org/webrtc/VideoRenderer$I420Frame")),
   1119         j_i420_frame_ctor_id_(GetMethodID(
   1120             jni, *j_frame_class_, "<init>", "(II[I[Ljava/nio/ByteBuffer;)V")),
   1121         j_texture_frame_ctor_id_(GetMethodID(
   1122             jni, *j_frame_class_, "<init>",
   1123             "(IILjava/lang/Object;I)V")),
   1124         j_byte_buffer_class_(jni, FindClass(jni, "java/nio/ByteBuffer")) {
   1125     CHECK_EXCEPTION(jni);
   1126   }
   1127 
   1128   virtual ~JavaVideoRendererWrapper() {}
   1129 
   1130   virtual void SetSize(int width, int height) OVERRIDE {
   1131     ScopedLocalRefFrame local_ref_frame(jni());
   1132     jni()->CallVoidMethod(*j_callbacks_, j_set_size_id_, width, height);
   1133     CHECK_EXCEPTION(jni());
   1134   }
   1135 
   1136   virtual void RenderFrame(const cricket::VideoFrame* frame) OVERRIDE {
   1137     ScopedLocalRefFrame local_ref_frame(jni());
   1138     if (frame->GetNativeHandle() != NULL) {
   1139       jobject j_frame = CricketToJavaTextureFrame(frame);
   1140       jni()->CallVoidMethod(*j_callbacks_, j_render_frame_id_, j_frame);
   1141       CHECK_EXCEPTION(jni());
   1142     } else {
   1143       jobject j_frame = CricketToJavaI420Frame(frame);
   1144       jni()->CallVoidMethod(*j_callbacks_, j_render_frame_id_, j_frame);
   1145       CHECK_EXCEPTION(jni());
   1146     }
   1147   }
   1148 
   1149  private:
   1150   // Return a VideoRenderer.I420Frame referring to the data in |frame|.
   1151   jobject CricketToJavaI420Frame(const cricket::VideoFrame* frame) {
   1152     jintArray strides = jni()->NewIntArray(3);
   1153     jint* strides_array = jni()->GetIntArrayElements(strides, NULL);
   1154     strides_array[0] = frame->GetYPitch();
   1155     strides_array[1] = frame->GetUPitch();
   1156     strides_array[2] = frame->GetVPitch();
   1157     jni()->ReleaseIntArrayElements(strides, strides_array, 0);
   1158     jobjectArray planes = jni()->NewObjectArray(3, *j_byte_buffer_class_, NULL);
   1159     jobject y_buffer = jni()->NewDirectByteBuffer(
   1160         const_cast<uint8*>(frame->GetYPlane()),
   1161         frame->GetYPitch() * frame->GetHeight());
   1162     jobject u_buffer = jni()->NewDirectByteBuffer(
   1163         const_cast<uint8*>(frame->GetUPlane()), frame->GetChromaSize());
   1164     jobject v_buffer = jni()->NewDirectByteBuffer(
   1165         const_cast<uint8*>(frame->GetVPlane()), frame->GetChromaSize());
   1166     jni()->SetObjectArrayElement(planes, 0, y_buffer);
   1167     jni()->SetObjectArrayElement(planes, 1, u_buffer);
   1168     jni()->SetObjectArrayElement(planes, 2, v_buffer);
   1169     return jni()->NewObject(
   1170         *j_frame_class_, j_i420_frame_ctor_id_,
   1171         frame->GetWidth(), frame->GetHeight(), strides, planes);
   1172   }
   1173 
   1174   // Return a VideoRenderer.I420Frame referring texture object in |frame|.
   1175   jobject CricketToJavaTextureFrame(const cricket::VideoFrame* frame) {
   1176     NativeHandleImpl* handle =
   1177         reinterpret_cast<NativeHandleImpl*>(frame->GetNativeHandle());
   1178     jobject texture_object = reinterpret_cast<jobject>(handle->GetHandle());
   1179     int texture_id = handle->GetTextureId();
   1180     return jni()->NewObject(
   1181         *j_frame_class_, j_texture_frame_ctor_id_,
   1182         frame->GetWidth(), frame->GetHeight(), texture_object, texture_id);
   1183   }
   1184 
   1185   JNIEnv* jni() {
   1186     return AttachCurrentThreadIfNeeded();
   1187   }
   1188 
   1189   ScopedGlobalRef<jobject> j_callbacks_;
   1190   jmethodID j_set_size_id_;
   1191   jmethodID j_render_frame_id_;
   1192   ScopedGlobalRef<jclass> j_frame_class_;
   1193   jmethodID j_i420_frame_ctor_id_;
   1194   jmethodID j_texture_frame_ctor_id_;
   1195   ScopedGlobalRef<jclass> j_byte_buffer_class_;
   1196 };
   1197 
   1198 #if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
   1199 // TODO(fischman): consider pulling MediaCodecVideoEncoder out of this file and
   1200 // into its own .h/.cc pair, if/when the JNI helper stuff above is extracted
   1201 // from this file.
   1202 
   1203 //#define TRACK_BUFFER_TIMING
   1204 #define TAG "MediaCodecVideo"
   1205 #ifdef TRACK_BUFFER_TIMING
   1206 #define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG, __VA_ARGS__)
   1207 #else
   1208 #define ALOGV(...)
   1209 #endif
   1210 #define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)
   1211 #define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)
   1212 
   1213 // Color formats supported by encoder - should mirror supportedColorList
   1214 // from MediaCodecVideoEncoder.java
   1215 enum COLOR_FORMATTYPE {
   1216   COLOR_FormatYUV420Planar = 0x13,
   1217   COLOR_FormatYUV420SemiPlanar = 0x15,
   1218   COLOR_QCOM_FormatYUV420SemiPlanar = 0x7FA30C00,
   1219   // NV12 color format supported by QCOM codec, but not declared in MediaCodec -
   1220   // see /hardware/qcom/media/mm-core/inc/OMX_QCOMExtns.h
   1221   // This format is presumably similar to COLOR_FormatYUV420SemiPlanar,
   1222   // but requires some (16, 32?) byte alignment.
   1223   COLOR_QCOM_FORMATYUV420PackedSemiPlanar32m = 0x7FA30C04
   1224 };
   1225 
   1226 // Arbitrary interval to poll the codec for new outputs.
   1227 enum { kMediaCodecPollMs = 10 };
   1228 // Media codec maximum output buffer ready timeout.
   1229 enum { kMediaCodecTimeoutMs = 500 };
   1230 // Interval to print codec statistics (bitrate, fps, encoding/decoding time).
   1231 enum { kMediaCodecStatisticsIntervalMs = 3000 };
   1232 
   1233 static int64_t GetCurrentTimeMs() {
   1234   return TickTime::Now().Ticks() / 1000000LL;
   1235 }
   1236 
   1237 // MediaCodecVideoEncoder is a webrtc::VideoEncoder implementation that uses
   1238 // Android's MediaCodec SDK API behind the scenes to implement (hopefully)
   1239 // HW-backed video encode.  This C++ class is implemented as a very thin shim,
   1240 // delegating all of the interesting work to org.webrtc.MediaCodecVideoEncoder.
   1241 // MediaCodecVideoEncoder is created, operated, and destroyed on a single
   1242 // thread, currently the libjingle Worker thread.
   1243 class MediaCodecVideoEncoder : public webrtc::VideoEncoder,
   1244                                public rtc::MessageHandler {
   1245  public:
   1246   virtual ~MediaCodecVideoEncoder();
   1247   explicit MediaCodecVideoEncoder(JNIEnv* jni);
   1248 
   1249   // webrtc::VideoEncoder implementation.  Everything trampolines to
   1250   // |codec_thread_| for execution.
   1251   virtual int32_t InitEncode(const webrtc::VideoCodec* codec_settings,
   1252                              int32_t /* number_of_cores */,
   1253                              uint32_t /* max_payload_size */) OVERRIDE;
   1254   virtual int32_t Encode(
   1255       const webrtc::I420VideoFrame& input_image,
   1256       const webrtc::CodecSpecificInfo* /* codec_specific_info */,
   1257       const std::vector<webrtc::VideoFrameType>* frame_types) OVERRIDE;
   1258   virtual int32_t RegisterEncodeCompleteCallback(
   1259       webrtc::EncodedImageCallback* callback) OVERRIDE;
   1260   virtual int32_t Release() OVERRIDE;
   1261   virtual int32_t SetChannelParameters(uint32_t /* packet_loss */,
   1262                                        int /* rtt */) OVERRIDE;
   1263   virtual int32_t SetRates(uint32_t new_bit_rate, uint32_t frame_rate) OVERRIDE;
   1264 
   1265   // rtc::MessageHandler implementation.
   1266   virtual void OnMessage(rtc::Message* msg) OVERRIDE;
   1267 
   1268  private:
   1269   // CHECK-fail if not running on |codec_thread_|.
   1270   void CheckOnCodecThread();
   1271 
   1272   // Release() and InitEncode() in an attempt to restore the codec to an
   1273   // operable state.  Necessary after all manner of OMX-layer errors.
   1274   void ResetCodec();
   1275 
   1276   // Implementation of webrtc::VideoEncoder methods above, all running on the
   1277   // codec thread exclusively.
   1278   //
   1279   // If width==0 then this is assumed to be a re-initialization and the
   1280   // previously-current values are reused instead of the passed parameters
   1281   // (makes it easier to reason about thread-safety).
   1282   int32_t InitEncodeOnCodecThread(int width, int height, int kbps, int fps);
   1283   int32_t EncodeOnCodecThread(
   1284       const webrtc::I420VideoFrame& input_image,
   1285       const std::vector<webrtc::VideoFrameType>* frame_types);
   1286   int32_t RegisterEncodeCompleteCallbackOnCodecThread(
   1287       webrtc::EncodedImageCallback* callback);
   1288   int32_t ReleaseOnCodecThread();
   1289   int32_t SetRatesOnCodecThread(uint32_t new_bit_rate, uint32_t frame_rate);
   1290 
   1291   // Helper accessors for MediaCodecVideoEncoder$OutputBufferInfo members.
   1292   int GetOutputBufferInfoIndex(JNIEnv* jni, jobject j_output_buffer_info);
   1293   jobject GetOutputBufferInfoBuffer(JNIEnv* jni, jobject j_output_buffer_info);
   1294   bool GetOutputBufferInfoIsKeyFrame(JNIEnv* jni, jobject j_output_buffer_info);
   1295   jlong GetOutputBufferInfoPresentationTimestampUs(
   1296       JNIEnv* jni,
   1297       jobject j_output_buffer_info);
   1298 
   1299   // Deliver any outputs pending in the MediaCodec to our |callback_| and return
   1300   // true on success.
   1301   bool DeliverPendingOutputs(JNIEnv* jni);
   1302 
   1303   // Valid all the time since RegisterEncodeCompleteCallback() Invoke()s to
   1304   // |codec_thread_| synchronously.
   1305   webrtc::EncodedImageCallback* callback_;
   1306 
   1307   // State that is constant for the lifetime of this object once the ctor
   1308   // returns.
   1309   scoped_ptr<Thread> codec_thread_;  // Thread on which to operate MediaCodec.
   1310   ScopedGlobalRef<jclass> j_media_codec_video_encoder_class_;
   1311   ScopedGlobalRef<jobject> j_media_codec_video_encoder_;
   1312   jmethodID j_init_encode_method_;
   1313   jmethodID j_dequeue_input_buffer_method_;
   1314   jmethodID j_encode_method_;
   1315   jmethodID j_release_method_;
   1316   jmethodID j_set_rates_method_;
   1317   jmethodID j_dequeue_output_buffer_method_;
   1318   jmethodID j_release_output_buffer_method_;
   1319   jfieldID j_color_format_field_;
   1320   jfieldID j_info_index_field_;
   1321   jfieldID j_info_buffer_field_;
   1322   jfieldID j_info_is_key_frame_field_;
   1323   jfieldID j_info_presentation_timestamp_us_field_;
   1324 
   1325   // State that is valid only between InitEncode() and the next Release().
   1326   // Touched only on codec_thread_ so no explicit synchronization necessary.
   1327   int width_;   // Frame width in pixels.
   1328   int height_;  // Frame height in pixels.
   1329   bool inited_;
   1330   enum libyuv::FourCC encoder_fourcc_; // Encoder color space format.
   1331   int last_set_bitrate_kbps_;  // Last-requested bitrate in kbps.
   1332   int last_set_fps_;  // Last-requested frame rate.
   1333   int64_t current_timestamp_us_;  // Current frame timestamps in us.
   1334   int frames_received_;  // Number of frames received by encoder.
   1335   int frames_dropped_;  // Number of frames dropped by encoder.
   1336   int frames_resolution_update_;  // Number of frames with new codec resolution.
   1337   int frames_in_queue_;  // Number of frames in encoder queue.
   1338   int64_t start_time_ms_;  // Start time for statistics.
   1339   int current_frames_;  // Number of frames in the current statistics interval.
   1340   int current_bytes_;  // Encoded bytes in the current statistics interval.
   1341   int current_encoding_time_ms_;  // Overall encoding time in the current second
   1342   int64_t last_input_timestamp_ms_;  // Timestamp of last received yuv frame.
   1343   int64_t last_output_timestamp_ms_;  // Timestamp of last encoded frame.
   1344   std::vector<int32_t> timestamps_;  // Video frames timestamp queue.
   1345   std::vector<int64_t> render_times_ms_;  // Video frames render time queue.
   1346   std::vector<int64_t> frame_rtc_times_ms_;  // Time when video frame is sent to
   1347                                              // encoder input.
   1348   // Frame size in bytes fed to MediaCodec.
   1349   int yuv_size_;
   1350   // True only when between a callback_->Encoded() call return a positive value
   1351   // and the next Encode() call being ignored.
   1352   bool drop_next_input_frame_;
   1353   // Global references; must be deleted in Release().
   1354   std::vector<jobject> input_buffers_;
   1355 };
   1356 
   1357 MediaCodecVideoEncoder::~MediaCodecVideoEncoder() {
   1358   // Call Release() to ensure no more callbacks to us after we are deleted.
   1359   Release();
   1360 }
   1361 
   1362 MediaCodecVideoEncoder::MediaCodecVideoEncoder(JNIEnv* jni)
   1363   : callback_(NULL),
   1364     inited_(false),
   1365     codec_thread_(new Thread()),
   1366     j_media_codec_video_encoder_class_(
   1367         jni,
   1368         FindClass(jni, "org/webrtc/MediaCodecVideoEncoder")),
   1369     j_media_codec_video_encoder_(
   1370         jni,
   1371         jni->NewObject(*j_media_codec_video_encoder_class_,
   1372                        GetMethodID(jni,
   1373                                    *j_media_codec_video_encoder_class_,
   1374                                    "<init>",
   1375                                    "()V"))) {
   1376   ScopedLocalRefFrame local_ref_frame(jni);
   1377   // It would be nice to avoid spinning up a new thread per MediaCodec, and
   1378   // instead re-use e.g. the PeerConnectionFactory's |worker_thread_|, but bug
   1379   // 2732 means that deadlocks abound.  This class synchronously trampolines
   1380   // to |codec_thread_|, so if anything else can be coming to _us_ from
   1381   // |codec_thread_|, or from any thread holding the |_sendCritSect| described
   1382   // in the bug, we have a problem.  For now work around that with a dedicated
   1383   // thread.
   1384   codec_thread_->SetName("MediaCodecVideoEncoder", NULL);
   1385   CHECK(codec_thread_->Start()) << "Failed to start MediaCodecVideoEncoder";
   1386 
   1387   jclass j_output_buffer_info_class =
   1388       FindClass(jni, "org/webrtc/MediaCodecVideoEncoder$OutputBufferInfo");
   1389   j_init_encode_method_ = GetMethodID(jni,
   1390                                       *j_media_codec_video_encoder_class_,
   1391                                       "initEncode",
   1392                                       "(IIII)[Ljava/nio/ByteBuffer;");
   1393   j_dequeue_input_buffer_method_ = GetMethodID(
   1394       jni, *j_media_codec_video_encoder_class_, "dequeueInputBuffer", "()I");
   1395   j_encode_method_ = GetMethodID(
   1396       jni, *j_media_codec_video_encoder_class_, "encode", "(ZIIJ)Z");
   1397   j_release_method_ =
   1398       GetMethodID(jni, *j_media_codec_video_encoder_class_, "release", "()V");
   1399   j_set_rates_method_ = GetMethodID(
   1400       jni, *j_media_codec_video_encoder_class_, "setRates", "(II)Z");
   1401   j_dequeue_output_buffer_method_ =
   1402       GetMethodID(jni,
   1403                   *j_media_codec_video_encoder_class_,
   1404                   "dequeueOutputBuffer",
   1405                   "()Lorg/webrtc/MediaCodecVideoEncoder$OutputBufferInfo;");
   1406   j_release_output_buffer_method_ = GetMethodID(
   1407       jni, *j_media_codec_video_encoder_class_, "releaseOutputBuffer", "(I)Z");
   1408 
   1409   j_color_format_field_ =
   1410       GetFieldID(jni, *j_media_codec_video_encoder_class_, "colorFormat", "I");
   1411   j_info_index_field_ =
   1412       GetFieldID(jni, j_output_buffer_info_class, "index", "I");
   1413   j_info_buffer_field_ = GetFieldID(
   1414       jni, j_output_buffer_info_class, "buffer", "Ljava/nio/ByteBuffer;");
   1415   j_info_is_key_frame_field_ =
   1416       GetFieldID(jni, j_output_buffer_info_class, "isKeyFrame", "Z");
   1417   j_info_presentation_timestamp_us_field_ = GetFieldID(
   1418       jni, j_output_buffer_info_class, "presentationTimestampUs", "J");
   1419   CHECK_EXCEPTION(jni) << "MediaCodecVideoEncoder ctor failed";
   1420 }
   1421 
   1422 int32_t MediaCodecVideoEncoder::InitEncode(
   1423     const webrtc::VideoCodec* codec_settings,
   1424     int32_t /* number_of_cores */,
   1425     uint32_t /* max_payload_size */) {
   1426   // Factory should guard against other codecs being used with us.
   1427   CHECK(codec_settings->codecType == kVideoCodecVP8) << "Unsupported codec";
   1428 
   1429   return codec_thread_->Invoke<int32_t>(
   1430       Bind(&MediaCodecVideoEncoder::InitEncodeOnCodecThread,
   1431            this,
   1432            codec_settings->width,
   1433            codec_settings->height,
   1434            codec_settings->startBitrate,
   1435            codec_settings->maxFramerate));
   1436 }
   1437 
   1438 int32_t MediaCodecVideoEncoder::Encode(
   1439     const webrtc::I420VideoFrame& frame,
   1440     const webrtc::CodecSpecificInfo* /* codec_specific_info */,
   1441     const std::vector<webrtc::VideoFrameType>* frame_types) {
   1442   return codec_thread_->Invoke<int32_t>(Bind(
   1443       &MediaCodecVideoEncoder::EncodeOnCodecThread, this, frame, frame_types));
   1444 }
   1445 
   1446 int32_t MediaCodecVideoEncoder::RegisterEncodeCompleteCallback(
   1447     webrtc::EncodedImageCallback* callback) {
   1448   return codec_thread_->Invoke<int32_t>(
   1449       Bind(&MediaCodecVideoEncoder::RegisterEncodeCompleteCallbackOnCodecThread,
   1450            this,
   1451            callback));
   1452 }
   1453 
   1454 int32_t MediaCodecVideoEncoder::Release() {
   1455   return codec_thread_->Invoke<int32_t>(
   1456       Bind(&MediaCodecVideoEncoder::ReleaseOnCodecThread, this));
   1457 }
   1458 
   1459 int32_t MediaCodecVideoEncoder::SetChannelParameters(uint32_t /* packet_loss */,
   1460                                                      int /* rtt */) {
   1461   return WEBRTC_VIDEO_CODEC_OK;
   1462 }
   1463 
   1464 int32_t MediaCodecVideoEncoder::SetRates(uint32_t new_bit_rate,
   1465                                          uint32_t frame_rate) {
   1466   return codec_thread_->Invoke<int32_t>(
   1467       Bind(&MediaCodecVideoEncoder::SetRatesOnCodecThread,
   1468            this,
   1469            new_bit_rate,
   1470            frame_rate));
   1471 }
   1472 
   1473 void MediaCodecVideoEncoder::OnMessage(rtc::Message* msg) {
   1474   JNIEnv* jni = AttachCurrentThreadIfNeeded();
   1475   ScopedLocalRefFrame local_ref_frame(jni);
   1476 
   1477   // We only ever send one message to |this| directly (not through a Bind()'d
   1478   // functor), so expect no ID/data.
   1479   CHECK(!msg->message_id) << "Unexpected message!";
   1480   CHECK(!msg->pdata) << "Unexpected message!";
   1481   CheckOnCodecThread();
   1482   if (!inited_) {
   1483     return;
   1484   }
   1485 
   1486   // It would be nice to recover from a failure here if one happened, but it's
   1487   // unclear how to signal such a failure to the app, so instead we stay silent
   1488   // about it and let the next app-called API method reveal the borkedness.
   1489   DeliverPendingOutputs(jni);
   1490   codec_thread_->PostDelayed(kMediaCodecPollMs, this);
   1491 }
   1492 
   1493 void MediaCodecVideoEncoder::CheckOnCodecThread() {
   1494   CHECK(codec_thread_ == ThreadManager::Instance()->CurrentThread())
   1495       << "Running on wrong thread!";
   1496 }
   1497 
   1498 void MediaCodecVideoEncoder::ResetCodec() {
   1499   ALOGE("ResetCodec");
   1500   if (Release() != WEBRTC_VIDEO_CODEC_OK ||
   1501       codec_thread_->Invoke<int32_t>(Bind(
   1502           &MediaCodecVideoEncoder::InitEncodeOnCodecThread, this,
   1503           width_, height_, 0, 0)) != WEBRTC_VIDEO_CODEC_OK) {
   1504     // TODO(fischman): wouldn't it be nice if there was a way to gracefully
   1505     // degrade to a SW encoder at this point?  There isn't one AFAICT :(
   1506     // https://code.google.com/p/webrtc/issues/detail?id=2920
   1507   }
   1508 }
   1509 
   1510 int32_t MediaCodecVideoEncoder::InitEncodeOnCodecThread(
   1511     int width, int height, int kbps, int fps) {
   1512   CheckOnCodecThread();
   1513   JNIEnv* jni = AttachCurrentThreadIfNeeded();
   1514   ScopedLocalRefFrame local_ref_frame(jni);
   1515 
   1516   ALOGD("InitEncodeOnCodecThread %d x %d. Bitrate: %d kbps. Fps: %d",
   1517       width, height, kbps, fps);
   1518   if (kbps == 0) {
   1519     kbps = last_set_bitrate_kbps_;
   1520   }
   1521   if (fps == 0) {
   1522     fps = last_set_fps_;
   1523   }
   1524 
   1525   width_ = width;
   1526   height_ = height;
   1527   last_set_bitrate_kbps_ = kbps;
   1528   last_set_fps_ = fps;
   1529   yuv_size_ = width_ * height_ * 3 / 2;
   1530   frames_received_ = 0;
   1531   frames_dropped_ = 0;
   1532   frames_resolution_update_ = 0;
   1533   frames_in_queue_ = 0;
   1534   current_timestamp_us_ = 0;
   1535   start_time_ms_ = GetCurrentTimeMs();
   1536   current_frames_ = 0;
   1537   current_bytes_ = 0;
   1538   current_encoding_time_ms_ = 0;
   1539   last_input_timestamp_ms_ = -1;
   1540   last_output_timestamp_ms_ = -1;
   1541   timestamps_.clear();
   1542   render_times_ms_.clear();
   1543   frame_rtc_times_ms_.clear();
   1544   drop_next_input_frame_ = false;
   1545   // We enforce no extra stride/padding in the format creation step.
   1546   jobjectArray input_buffers = reinterpret_cast<jobjectArray>(
   1547       jni->CallObjectMethod(*j_media_codec_video_encoder_,
   1548                             j_init_encode_method_,
   1549                             width_,
   1550                             height_,
   1551                             kbps,
   1552                             fps));
   1553   CHECK_EXCEPTION(jni);
   1554   if (IsNull(jni, input_buffers))
   1555     return WEBRTC_VIDEO_CODEC_ERROR;
   1556 
   1557   inited_ = true;
   1558   switch (GetIntField(jni, *j_media_codec_video_encoder_,
   1559       j_color_format_field_)) {
   1560     case COLOR_FormatYUV420Planar:
   1561       encoder_fourcc_ = libyuv::FOURCC_YU12;
   1562       break;
   1563     case COLOR_FormatYUV420SemiPlanar:
   1564     case COLOR_QCOM_FormatYUV420SemiPlanar:
   1565     case COLOR_QCOM_FORMATYUV420PackedSemiPlanar32m:
   1566       encoder_fourcc_ = libyuv::FOURCC_NV12;
   1567       break;
   1568     default:
   1569       LOG(LS_ERROR) << "Wrong color format.";
   1570       return WEBRTC_VIDEO_CODEC_ERROR;
   1571   }
   1572   size_t num_input_buffers = jni->GetArrayLength(input_buffers);
   1573   CHECK(input_buffers_.empty())
   1574       << "Unexpected double InitEncode without Release";
   1575   input_buffers_.resize(num_input_buffers);
   1576   for (size_t i = 0; i < num_input_buffers; ++i) {
   1577     input_buffers_[i] =
   1578         jni->NewGlobalRef(jni->GetObjectArrayElement(input_buffers, i));
   1579     int64 yuv_buffer_capacity =
   1580         jni->GetDirectBufferCapacity(input_buffers_[i]);
   1581     CHECK_EXCEPTION(jni);
   1582     CHECK(yuv_buffer_capacity >= yuv_size_) << "Insufficient capacity";
   1583   }
   1584   CHECK_EXCEPTION(jni);
   1585 
   1586   codec_thread_->PostDelayed(kMediaCodecPollMs, this);
   1587   return WEBRTC_VIDEO_CODEC_OK;
   1588 }
   1589 
   1590 int32_t MediaCodecVideoEncoder::EncodeOnCodecThread(
   1591     const webrtc::I420VideoFrame& frame,
   1592     const std::vector<webrtc::VideoFrameType>* frame_types) {
   1593   CheckOnCodecThread();
   1594   JNIEnv* jni = AttachCurrentThreadIfNeeded();
   1595   ScopedLocalRefFrame local_ref_frame(jni);
   1596 
   1597   if (!inited_) {
   1598     return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
   1599   }
   1600   frames_received_++;
   1601   if (!DeliverPendingOutputs(jni)) {
   1602     ResetCodec();
   1603     // Continue as if everything's fine.
   1604   }
   1605 
   1606   if (drop_next_input_frame_) {
   1607     ALOGV("Encoder drop frame - failed callback.");
   1608     drop_next_input_frame_ = false;
   1609     return WEBRTC_VIDEO_CODEC_OK;
   1610   }
   1611 
   1612   CHECK(frame_types->size() == 1) << "Unexpected stream count";
   1613   if (frame.width() != width_ || frame.height() != height_) {
   1614     frames_resolution_update_++;
   1615     ALOGD("Unexpected frame resolution change from %d x %d to %d x %d",
   1616         width_, height_, frame.width(), frame.height());
   1617     if (frames_resolution_update_ > 3) {
   1618       // Reset codec if we received more than 3 frames with new resolution.
   1619       width_ = frame.width();
   1620       height_ = frame.height();
   1621       frames_resolution_update_ = 0;
   1622       ResetCodec();
   1623     }
   1624     return WEBRTC_VIDEO_CODEC_OK;
   1625   }
   1626   frames_resolution_update_ = 0;
   1627 
   1628   bool key_frame = frame_types->front() != webrtc::kDeltaFrame;
   1629 
   1630   // Check if we accumulated too many frames in encoder input buffers
   1631   // or the encoder latency exceeds 70 ms and drop frame if so.
   1632   if (frames_in_queue_ > 0 && last_input_timestamp_ms_ >= 0) {
   1633     int encoder_latency_ms = last_input_timestamp_ms_ -
   1634         last_output_timestamp_ms_;
   1635     if (frames_in_queue_ > 2 || encoder_latency_ms > 70) {
   1636       ALOGV("Drop frame - encoder is behind by %d ms. Q size: %d",
   1637           encoder_latency_ms, frames_in_queue_);
   1638       frames_dropped_++;
   1639       return WEBRTC_VIDEO_CODEC_OK;
   1640     }
   1641   }
   1642 
   1643   int j_input_buffer_index = jni->CallIntMethod(*j_media_codec_video_encoder_,
   1644                                                 j_dequeue_input_buffer_method_);
   1645   CHECK_EXCEPTION(jni);
   1646   if (j_input_buffer_index == -1) {
   1647     // Video codec falls behind - no input buffer available.
   1648     ALOGV("Encoder drop frame - no input buffers available");
   1649     frames_dropped_++;
   1650     return WEBRTC_VIDEO_CODEC_OK;  // TODO(fischman): see webrtc bug 2887.
   1651   }
   1652   if (j_input_buffer_index == -2) {
   1653     ResetCodec();
   1654     return WEBRTC_VIDEO_CODEC_ERROR;
   1655   }
   1656 
   1657   ALOGV("Encode frame # %d. Buffer # %d. TS: %lld.",
   1658       frames_received_, j_input_buffer_index, current_timestamp_us_ / 1000);
   1659 
   1660   jobject j_input_buffer = input_buffers_[j_input_buffer_index];
   1661   uint8* yuv_buffer =
   1662       reinterpret_cast<uint8*>(jni->GetDirectBufferAddress(j_input_buffer));
   1663   CHECK_EXCEPTION(jni);
   1664   CHECK(yuv_buffer) << "Indirect buffer??";
   1665   CHECK(!libyuv::ConvertFromI420(
   1666           frame.buffer(webrtc::kYPlane), frame.stride(webrtc::kYPlane),
   1667           frame.buffer(webrtc::kUPlane), frame.stride(webrtc::kUPlane),
   1668           frame.buffer(webrtc::kVPlane), frame.stride(webrtc::kVPlane),
   1669           yuv_buffer, width_,
   1670           width_, height_,
   1671           encoder_fourcc_))
   1672       << "ConvertFromI420 failed";
   1673   last_input_timestamp_ms_ = current_timestamp_us_ / 1000;
   1674   frames_in_queue_++;
   1675 
   1676   // Save input image timestamps for later output
   1677   timestamps_.push_back(frame.timestamp());
   1678   render_times_ms_.push_back(frame.render_time_ms());
   1679   frame_rtc_times_ms_.push_back(GetCurrentTimeMs());
   1680 
   1681   bool encode_status = jni->CallBooleanMethod(*j_media_codec_video_encoder_,
   1682                                               j_encode_method_,
   1683                                               key_frame,
   1684                                               j_input_buffer_index,
   1685                                               yuv_size_,
   1686                                               current_timestamp_us_);
   1687   CHECK_EXCEPTION(jni);
   1688   current_timestamp_us_ += 1000000 / last_set_fps_;
   1689 
   1690   if (!encode_status || !DeliverPendingOutputs(jni)) {
   1691     ResetCodec();
   1692     return WEBRTC_VIDEO_CODEC_ERROR;
   1693   }
   1694 
   1695   return WEBRTC_VIDEO_CODEC_OK;
   1696 }
   1697 
   1698 int32_t MediaCodecVideoEncoder::RegisterEncodeCompleteCallbackOnCodecThread(
   1699     webrtc::EncodedImageCallback* callback) {
   1700   CheckOnCodecThread();
   1701   JNIEnv* jni = AttachCurrentThreadIfNeeded();
   1702   ScopedLocalRefFrame local_ref_frame(jni);
   1703   callback_ = callback;
   1704   return WEBRTC_VIDEO_CODEC_OK;
   1705 }
   1706 
   1707 int32_t MediaCodecVideoEncoder::ReleaseOnCodecThread() {
   1708   if (!inited_) {
   1709     return WEBRTC_VIDEO_CODEC_OK;
   1710   }
   1711   CheckOnCodecThread();
   1712   JNIEnv* jni = AttachCurrentThreadIfNeeded();
   1713   ALOGD("EncoderRelease: Frames received: %d. Frames dropped: %d.",
   1714       frames_received_,frames_dropped_);
   1715   ScopedLocalRefFrame local_ref_frame(jni);
   1716   for (size_t i = 0; i < input_buffers_.size(); ++i)
   1717     jni->DeleteGlobalRef(input_buffers_[i]);
   1718   input_buffers_.clear();
   1719   jni->CallVoidMethod(*j_media_codec_video_encoder_, j_release_method_);
   1720   CHECK_EXCEPTION(jni);
   1721   rtc::MessageQueueManager::Clear(this);
   1722   inited_ = false;
   1723   return WEBRTC_VIDEO_CODEC_OK;
   1724 }
   1725 
   1726 int32_t MediaCodecVideoEncoder::SetRatesOnCodecThread(uint32_t new_bit_rate,
   1727                                                       uint32_t frame_rate) {
   1728   CheckOnCodecThread();
   1729   if (last_set_bitrate_kbps_ == new_bit_rate &&
   1730       last_set_fps_ == frame_rate) {
   1731     return WEBRTC_VIDEO_CODEC_OK;
   1732   }
   1733   JNIEnv* jni = AttachCurrentThreadIfNeeded();
   1734   ScopedLocalRefFrame local_ref_frame(jni);
   1735   if (new_bit_rate > 0) {
   1736     last_set_bitrate_kbps_ = new_bit_rate;
   1737   }
   1738   if (frame_rate > 0) {
   1739     last_set_fps_ = frame_rate;
   1740   }
   1741   bool ret = jni->CallBooleanMethod(*j_media_codec_video_encoder_,
   1742                                        j_set_rates_method_,
   1743                                        last_set_bitrate_kbps_,
   1744                                        last_set_fps_);
   1745   CHECK_EXCEPTION(jni);
   1746   if (!ret) {
   1747     ResetCodec();
   1748     return WEBRTC_VIDEO_CODEC_ERROR;
   1749   }
   1750   return WEBRTC_VIDEO_CODEC_OK;
   1751 }
   1752 
   1753 int MediaCodecVideoEncoder::GetOutputBufferInfoIndex(
   1754     JNIEnv* jni,
   1755     jobject j_output_buffer_info) {
   1756   return GetIntField(jni, j_output_buffer_info, j_info_index_field_);
   1757 }
   1758 
   1759 jobject MediaCodecVideoEncoder::GetOutputBufferInfoBuffer(
   1760     JNIEnv* jni,
   1761     jobject j_output_buffer_info) {
   1762   return GetObjectField(jni, j_output_buffer_info, j_info_buffer_field_);
   1763 }
   1764 
   1765 bool MediaCodecVideoEncoder::GetOutputBufferInfoIsKeyFrame(
   1766     JNIEnv* jni,
   1767     jobject j_output_buffer_info) {
   1768   return GetBooleanField(jni, j_output_buffer_info, j_info_is_key_frame_field_);
   1769 }
   1770 
   1771 jlong MediaCodecVideoEncoder::GetOutputBufferInfoPresentationTimestampUs(
   1772     JNIEnv* jni,
   1773     jobject j_output_buffer_info) {
   1774   return GetLongField(
   1775       jni, j_output_buffer_info, j_info_presentation_timestamp_us_field_);
   1776 }
   1777 
   1778 bool MediaCodecVideoEncoder::DeliverPendingOutputs(JNIEnv* jni) {
   1779   while (true) {
   1780     jobject j_output_buffer_info = jni->CallObjectMethod(
   1781         *j_media_codec_video_encoder_, j_dequeue_output_buffer_method_);
   1782     CHECK_EXCEPTION(jni);
   1783     if (IsNull(jni, j_output_buffer_info)) {
   1784       break;
   1785     }
   1786 
   1787     int output_buffer_index =
   1788         GetOutputBufferInfoIndex(jni, j_output_buffer_info);
   1789     if (output_buffer_index == -1) {
   1790       ResetCodec();
   1791       return false;
   1792     }
   1793 
   1794     // Get frame timestamps from a queue.
   1795     last_output_timestamp_ms_ =
   1796         GetOutputBufferInfoPresentationTimestampUs(jni, j_output_buffer_info) /
   1797         1000;
   1798     int32_t timestamp = timestamps_.front();
   1799     timestamps_.erase(timestamps_.begin());
   1800     int64_t render_time_ms = render_times_ms_.front();
   1801     render_times_ms_.erase(render_times_ms_.begin());
   1802     int64_t frame_encoding_time_ms = GetCurrentTimeMs() -
   1803         frame_rtc_times_ms_.front();
   1804     frame_rtc_times_ms_.erase(frame_rtc_times_ms_.begin());
   1805     frames_in_queue_--;
   1806 
   1807     // Extract payload and key frame flag.
   1808     int32_t callback_status = 0;
   1809     jobject j_output_buffer =
   1810         GetOutputBufferInfoBuffer(jni, j_output_buffer_info);
   1811     bool key_frame = GetOutputBufferInfoIsKeyFrame(jni, j_output_buffer_info);
   1812     size_t payload_size = jni->GetDirectBufferCapacity(j_output_buffer);
   1813     uint8* payload = reinterpret_cast<uint8_t*>(
   1814         jni->GetDirectBufferAddress(j_output_buffer));
   1815     CHECK_EXCEPTION(jni);
   1816 
   1817     ALOGV("Encoder got output buffer # %d. Size: %d. TS: %lld. Latency: %lld."
   1818         " EncTime: %lld",
   1819         output_buffer_index, payload_size, last_output_timestamp_ms_,
   1820         last_input_timestamp_ms_ - last_output_timestamp_ms_,
   1821         frame_encoding_time_ms);
   1822 
   1823     // Calculate and print encoding statistics - every 3 seconds.
   1824     current_frames_++;
   1825     current_bytes_ += payload_size;
   1826     current_encoding_time_ms_ += frame_encoding_time_ms;
   1827     int statistic_time_ms = GetCurrentTimeMs() - start_time_ms_;
   1828     if (statistic_time_ms >= kMediaCodecStatisticsIntervalMs &&
   1829         current_frames_ > 0) {
   1830       ALOGD("Encoder bitrate: %d, target: %d kbps, fps: %d,"
   1831           " encTime: %d for last %d ms",
   1832           current_bytes_ * 8 / statistic_time_ms,
   1833           last_set_bitrate_kbps_,
   1834           (current_frames_ * 1000 + statistic_time_ms / 2) / statistic_time_ms,
   1835           current_encoding_time_ms_ / current_frames_, statistic_time_ms);
   1836       start_time_ms_ = GetCurrentTimeMs();
   1837       current_frames_ = 0;
   1838       current_bytes_= 0;
   1839       current_encoding_time_ms_ = 0;
   1840     }
   1841 
   1842     // Callback - return encoded frame.
   1843     if (callback_) {
   1844       scoped_ptr<webrtc::EncodedImage> image(
   1845           new webrtc::EncodedImage(payload, payload_size, payload_size));
   1846       image->_encodedWidth = width_;
   1847       image->_encodedHeight = height_;
   1848       image->_timeStamp = timestamp;
   1849       image->capture_time_ms_ = render_time_ms;
   1850       image->_frameType = (key_frame ? webrtc::kKeyFrame : webrtc::kDeltaFrame);
   1851       image->_completeFrame = true;
   1852 
   1853       webrtc::CodecSpecificInfo info;
   1854       memset(&info, 0, sizeof(info));
   1855       info.codecType = kVideoCodecVP8;
   1856       info.codecSpecific.VP8.pictureId = webrtc::kNoPictureId;
   1857       info.codecSpecific.VP8.tl0PicIdx = webrtc::kNoTl0PicIdx;
   1858       info.codecSpecific.VP8.keyIdx = webrtc::kNoKeyIdx;
   1859 
   1860       // Generate a header describing a single fragment.
   1861       webrtc::RTPFragmentationHeader header;
   1862       memset(&header, 0, sizeof(header));
   1863       header.VerifyAndAllocateFragmentationHeader(1);
   1864       header.fragmentationOffset[0] = 0;
   1865       header.fragmentationLength[0] = image->_length;
   1866       header.fragmentationPlType[0] = 0;
   1867       header.fragmentationTimeDiff[0] = 0;
   1868 
   1869       callback_status = callback_->Encoded(*image, &info, &header);
   1870     }
   1871 
   1872     // Return output buffer back to the encoder.
   1873     bool success = jni->CallBooleanMethod(*j_media_codec_video_encoder_,
   1874                                           j_release_output_buffer_method_,
   1875                                           output_buffer_index);
   1876     CHECK_EXCEPTION(jni);
   1877     if (!success) {
   1878       ResetCodec();
   1879       return false;
   1880     }
   1881 
   1882     if (callback_status > 0) {
   1883       drop_next_input_frame_ = true;
   1884     // Theoretically could handle callback_status<0 here, but unclear what that
   1885     // would mean for us.
   1886     }
   1887   }
   1888 
   1889   return true;
   1890 }
   1891 
   1892 // Simplest-possible implementation of an encoder factory, churns out
   1893 // MediaCodecVideoEncoders on demand (or errors, if that's not possible).
   1894 class MediaCodecVideoEncoderFactory
   1895     : public cricket::WebRtcVideoEncoderFactory {
   1896  public:
   1897   MediaCodecVideoEncoderFactory();
   1898   virtual ~MediaCodecVideoEncoderFactory();
   1899 
   1900   // WebRtcVideoEncoderFactory implementation.
   1901   virtual webrtc::VideoEncoder* CreateVideoEncoder(webrtc::VideoCodecType type)
   1902       OVERRIDE;
   1903   virtual void AddObserver(Observer* observer) OVERRIDE;
   1904   virtual void RemoveObserver(Observer* observer) OVERRIDE;
   1905   virtual const std::vector<VideoCodec>& codecs() const OVERRIDE;
   1906   virtual void DestroyVideoEncoder(webrtc::VideoEncoder* encoder) OVERRIDE;
   1907 
   1908  private:
   1909   // Empty if platform support is lacking, const after ctor returns.
   1910   std::vector<VideoCodec> supported_codecs_;
   1911 };
   1912 
   1913 MediaCodecVideoEncoderFactory::MediaCodecVideoEncoderFactory() {
   1914   JNIEnv* jni = AttachCurrentThreadIfNeeded();
   1915   ScopedLocalRefFrame local_ref_frame(jni);
   1916   jclass j_encoder_class = FindClass(jni, "org/webrtc/MediaCodecVideoEncoder");
   1917   bool is_platform_supported = jni->CallStaticBooleanMethod(
   1918       j_encoder_class,
   1919       GetStaticMethodID(jni, j_encoder_class, "isPlatformSupported", "()Z"));
   1920   CHECK_EXCEPTION(jni);
   1921   if (!is_platform_supported)
   1922     return;
   1923 
   1924   // Wouldn't it be nice if MediaCodec exposed the maximum capabilities of the
   1925   // encoder?  Sure would be.  Too bad it doesn't.  So we hard-code some
   1926   // reasonable defaults.
   1927   supported_codecs_.push_back(
   1928       VideoCodec(kVideoCodecVP8, "VP8", 1280, 1280, 30));
   1929 }
   1930 
   1931 MediaCodecVideoEncoderFactory::~MediaCodecVideoEncoderFactory() {}
   1932 
   1933 webrtc::VideoEncoder* MediaCodecVideoEncoderFactory::CreateVideoEncoder(
   1934     webrtc::VideoCodecType type) {
   1935   if (type != kVideoCodecVP8 || supported_codecs_.empty())
   1936     return NULL;
   1937   return new MediaCodecVideoEncoder(AttachCurrentThreadIfNeeded());
   1938 }
   1939 
   1940 // Since the available codec list is never going to change, we ignore the
   1941 // Observer-related interface here.
   1942 void MediaCodecVideoEncoderFactory::AddObserver(Observer* observer) {}
   1943 void MediaCodecVideoEncoderFactory::RemoveObserver(Observer* observer) {}
   1944 
   1945 const std::vector<MediaCodecVideoEncoderFactory::VideoCodec>&
   1946 MediaCodecVideoEncoderFactory::codecs() const {
   1947   return supported_codecs_;
   1948 }
   1949 
   1950 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder(
   1951     webrtc::VideoEncoder* encoder) {
   1952   delete encoder;
   1953 }
   1954 
   1955 class MediaCodecVideoDecoder : public webrtc::VideoDecoder,
   1956                                public rtc::MessageHandler {
   1957  public:
   1958   explicit MediaCodecVideoDecoder(JNIEnv* jni);
   1959   virtual ~MediaCodecVideoDecoder();
   1960 
   1961   static int SetAndroidObjects(JNIEnv* jni, jobject render_egl_context);
   1962 
   1963   virtual int32_t InitDecode(const VideoCodec* codecSettings,
   1964       int32_t numberOfCores) OVERRIDE;
   1965 
   1966   virtual int32_t
   1967   Decode(const EncodedImage& inputImage, bool missingFrames,
   1968          const RTPFragmentationHeader* fragmentation,
   1969          const CodecSpecificInfo* codecSpecificInfo = NULL,
   1970          int64_t renderTimeMs = -1) OVERRIDE;
   1971 
   1972   virtual int32_t RegisterDecodeCompleteCallback(
   1973       DecodedImageCallback* callback) OVERRIDE;
   1974 
   1975   virtual int32_t Release() OVERRIDE;
   1976 
   1977   virtual int32_t Reset() OVERRIDE;
   1978   // rtc::MessageHandler implementation.
   1979   virtual void OnMessage(rtc::Message* msg) OVERRIDE;
   1980 
   1981  private:
   1982   // CHECK-fail if not running on |codec_thread_|.
   1983   void CheckOnCodecThread();
   1984 
   1985   int32_t InitDecodeOnCodecThread();
   1986   int32_t ReleaseOnCodecThread();
   1987   int32_t DecodeOnCodecThread(const EncodedImage& inputImage);
   1988   // Deliver any outputs pending in the MediaCodec to our |callback_| and return
   1989   // true on success.
   1990   bool DeliverPendingOutputs(JNIEnv* jni, int dequeue_timeout_us);
   1991 
   1992 
   1993   bool key_frame_required_;
   1994   bool inited_;
   1995   bool use_surface_;
   1996   VideoCodec codec_;
   1997   I420VideoFrame decoded_image_;
   1998   NativeHandleImpl native_handle_;
   1999   DecodedImageCallback* callback_;
   2000   int frames_received_;  // Number of frames received by decoder.
   2001   int frames_decoded_;  // Number of frames decoded by decoder
   2002   int64_t start_time_ms_;  // Start time for statistics.
   2003   int current_frames_;  // Number of frames in the current statistics interval.
   2004   int current_bytes_;  // Encoded bytes in the current statistics interval.
   2005   int current_decoding_time_ms_;  // Overall decoding time in the current second
   2006   uint32_t max_pending_frames_;  // Maximum number of pending input frames
   2007   std::vector<int32_t> timestamps_;
   2008   std::vector<int64_t> ntp_times_ms_;
   2009   std::vector<int64_t> frame_rtc_times_ms_;  // Time when video frame is sent to
   2010                                              // decoder input.
   2011 
   2012   // State that is constant for the lifetime of this object once the ctor
   2013   // returns.
   2014   scoped_ptr<Thread> codec_thread_;  // Thread on which to operate MediaCodec.
   2015   ScopedGlobalRef<jclass> j_media_codec_video_decoder_class_;
   2016   ScopedGlobalRef<jobject> j_media_codec_video_decoder_;
   2017   jmethodID j_init_decode_method_;
   2018   jmethodID j_release_method_;
   2019   jmethodID j_dequeue_input_buffer_method_;
   2020   jmethodID j_queue_input_buffer_method_;
   2021   jmethodID j_dequeue_output_buffer_method_;
   2022   jmethodID j_release_output_buffer_method_;
   2023   // MediaCodecVideoDecoder fields.
   2024   jfieldID j_input_buffers_field_;
   2025   jfieldID j_output_buffers_field_;
   2026   jfieldID j_color_format_field_;
   2027   jfieldID j_width_field_;
   2028   jfieldID j_height_field_;
   2029   jfieldID j_stride_field_;
   2030   jfieldID j_slice_height_field_;
   2031   jfieldID j_surface_texture_field_;
   2032   jfieldID j_textureID_field_;
   2033   // MediaCodecVideoDecoder.DecoderOutputBufferInfo fields.
   2034   jfieldID j_info_index_field_;
   2035   jfieldID j_info_offset_field_;
   2036   jfieldID j_info_size_field_;
   2037   jfieldID j_info_presentation_timestamp_us_field_;
   2038 
   2039   // Global references; must be deleted in Release().
   2040   std::vector<jobject> input_buffers_;
   2041   jobject surface_texture_;
   2042 
   2043   // Render EGL context.
   2044   static jobject render_egl_context_;
   2045 };
   2046 
   2047 jobject MediaCodecVideoDecoder::render_egl_context_ = NULL;
   2048 
   2049 int MediaCodecVideoDecoder::SetAndroidObjects(JNIEnv* jni,
   2050     jobject render_egl_context) {
   2051   if (render_egl_context_) {
   2052     jni->DeleteGlobalRef(render_egl_context_);
   2053   }
   2054   if (IsNull(jni, render_egl_context)) {
   2055     render_egl_context_ = NULL;
   2056   } else {
   2057     render_egl_context_ = jni->NewGlobalRef(render_egl_context);
   2058   }
   2059   ALOGD("VideoDecoder EGL context set.");
   2060   return 0;
   2061 }
   2062 
   2063 MediaCodecVideoDecoder::MediaCodecVideoDecoder(JNIEnv* jni)
   2064   : key_frame_required_(true),
   2065     inited_(false),
   2066     codec_thread_(new Thread()),
   2067     j_media_codec_video_decoder_class_(
   2068         jni,
   2069         FindClass(jni, "org/webrtc/MediaCodecVideoDecoder")),
   2070           j_media_codec_video_decoder_(
   2071               jni,
   2072               jni->NewObject(*j_media_codec_video_decoder_class_,
   2073                    GetMethodID(jni,
   2074                               *j_media_codec_video_decoder_class_,
   2075                               "<init>",
   2076                               "()V"))) {
   2077   ScopedLocalRefFrame local_ref_frame(jni);
   2078   codec_thread_->SetName("MediaCodecVideoDecoder", NULL);
   2079   CHECK(codec_thread_->Start()) << "Failed to start MediaCodecVideoDecoder";
   2080 
   2081   j_init_decode_method_ = GetMethodID(
   2082       jni, *j_media_codec_video_decoder_class_, "initDecode",
   2083       "(IIZLandroid/opengl/EGLContext;)Z");
   2084   j_release_method_ =
   2085       GetMethodID(jni, *j_media_codec_video_decoder_class_, "release", "()V");
   2086   j_dequeue_input_buffer_method_ = GetMethodID(
   2087       jni, *j_media_codec_video_decoder_class_, "dequeueInputBuffer", "()I");
   2088   j_queue_input_buffer_method_ = GetMethodID(
   2089       jni, *j_media_codec_video_decoder_class_, "queueInputBuffer", "(IIJ)Z");
   2090   j_dequeue_output_buffer_method_ = GetMethodID(
   2091       jni, *j_media_codec_video_decoder_class_, "dequeueOutputBuffer",
   2092       "(I)Lorg/webrtc/MediaCodecVideoDecoder$DecoderOutputBufferInfo;");
   2093   j_release_output_buffer_method_ = GetMethodID(
   2094       jni, *j_media_codec_video_decoder_class_, "releaseOutputBuffer", "(IZ)Z");
   2095 
   2096   j_input_buffers_field_ = GetFieldID(
   2097       jni, *j_media_codec_video_decoder_class_,
   2098       "inputBuffers", "[Ljava/nio/ByteBuffer;");
   2099   j_output_buffers_field_ = GetFieldID(
   2100       jni, *j_media_codec_video_decoder_class_,
   2101       "outputBuffers", "[Ljava/nio/ByteBuffer;");
   2102   j_color_format_field_ = GetFieldID(
   2103       jni, *j_media_codec_video_decoder_class_, "colorFormat", "I");
   2104   j_width_field_ = GetFieldID(
   2105       jni, *j_media_codec_video_decoder_class_, "width", "I");
   2106   j_height_field_ = GetFieldID(
   2107       jni, *j_media_codec_video_decoder_class_, "height", "I");
   2108   j_stride_field_ = GetFieldID(
   2109       jni, *j_media_codec_video_decoder_class_, "stride", "I");
   2110   j_slice_height_field_ = GetFieldID(
   2111       jni, *j_media_codec_video_decoder_class_, "sliceHeight", "I");
   2112   j_textureID_field_ = GetFieldID(
   2113       jni, *j_media_codec_video_decoder_class_, "textureID", "I");
   2114   j_surface_texture_field_ = GetFieldID(
   2115       jni, *j_media_codec_video_decoder_class_, "surfaceTexture",
   2116       "Landroid/graphics/SurfaceTexture;");
   2117 
   2118   jclass j_decoder_output_buffer_info_class = FindClass(jni,
   2119       "org/webrtc/MediaCodecVideoDecoder$DecoderOutputBufferInfo");
   2120   j_info_index_field_ = GetFieldID(
   2121       jni, j_decoder_output_buffer_info_class, "index", "I");
   2122   j_info_offset_field_ = GetFieldID(
   2123       jni, j_decoder_output_buffer_info_class, "offset", "I");
   2124   j_info_size_field_ = GetFieldID(
   2125       jni, j_decoder_output_buffer_info_class, "size", "I");
   2126   j_info_presentation_timestamp_us_field_ = GetFieldID(
   2127       jni, j_decoder_output_buffer_info_class, "presentationTimestampUs", "J");
   2128 
   2129   CHECK_EXCEPTION(jni) << "MediaCodecVideoDecoder ctor failed";
   2130   use_surface_ = true;
   2131   if (render_egl_context_ == NULL)
   2132     use_surface_ = false;
   2133   memset(&codec_, 0, sizeof(codec_));
   2134 }
   2135 
   2136 MediaCodecVideoDecoder::~MediaCodecVideoDecoder() {
   2137   // Call Release() to ensure no more callbacks to us after we are deleted.
   2138   Release();
   2139 }
   2140 
   2141 int32_t MediaCodecVideoDecoder::InitDecode(const VideoCodec* inst,
   2142     int32_t numberOfCores) {
   2143   if (inst == NULL) {
   2144     return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
   2145   }
   2146   int ret_val = Release();
   2147   if (ret_val < 0) {
   2148     return ret_val;
   2149   }
   2150   // Save VideoCodec instance for later.
   2151   if (&codec_ != inst) {
   2152     codec_ = *inst;
   2153   }
   2154   codec_.maxFramerate = (codec_.maxFramerate >= 1) ? codec_.maxFramerate : 1;
   2155 
   2156   // Always start with a complete key frame.
   2157   key_frame_required_ = true;
   2158   frames_received_ = 0;
   2159   frames_decoded_ = 0;
   2160 
   2161   // Call Java init.
   2162   return codec_thread_->Invoke<int32_t>(
   2163       Bind(&MediaCodecVideoDecoder::InitDecodeOnCodecThread, this));
   2164 }
   2165 
   2166 int32_t MediaCodecVideoDecoder::InitDecodeOnCodecThread() {
   2167   CheckOnCodecThread();
   2168   JNIEnv* jni = AttachCurrentThreadIfNeeded();
   2169   ScopedLocalRefFrame local_ref_frame(jni);
   2170   ALOGD("InitDecodeOnCodecThread: %d x %d. fps: %d",
   2171       codec_.width, codec_.height, codec_.maxFramerate);
   2172 
   2173   bool success = jni->CallBooleanMethod(*j_media_codec_video_decoder_,
   2174                                        j_init_decode_method_,
   2175                                        codec_.width,
   2176                                        codec_.height,
   2177                                        use_surface_,
   2178                                        render_egl_context_);
   2179   CHECK_EXCEPTION(jni);
   2180   if (!success) {
   2181     return WEBRTC_VIDEO_CODEC_ERROR;
   2182   }
   2183   inited_ = true;
   2184 
   2185   max_pending_frames_ = 0;
   2186   if (use_surface_) {
   2187     max_pending_frames_ = 1;
   2188   }
   2189   start_time_ms_ = GetCurrentTimeMs();
   2190   current_frames_ = 0;
   2191   current_bytes_ = 0;
   2192   current_decoding_time_ms_ = 0;
   2193   timestamps_.clear();
   2194   ntp_times_ms_.clear();
   2195   frame_rtc_times_ms_.clear();
   2196 
   2197   jobjectArray input_buffers = (jobjectArray)GetObjectField(
   2198       jni, *j_media_codec_video_decoder_, j_input_buffers_field_);
   2199   size_t num_input_buffers = jni->GetArrayLength(input_buffers);
   2200   input_buffers_.resize(num_input_buffers);
   2201   for (size_t i = 0; i < num_input_buffers; ++i) {
   2202     input_buffers_[i] =
   2203         jni->NewGlobalRef(jni->GetObjectArrayElement(input_buffers, i));
   2204     CHECK_EXCEPTION(jni);
   2205   }
   2206 
   2207   if (use_surface_) {
   2208     jobject surface_texture = GetObjectField(
   2209         jni, *j_media_codec_video_decoder_, j_surface_texture_field_);
   2210     surface_texture_ = jni->NewGlobalRef(surface_texture);
   2211   }
   2212   codec_thread_->PostDelayed(kMediaCodecPollMs, this);
   2213 
   2214   return WEBRTC_VIDEO_CODEC_OK;
   2215 }
   2216 
   2217 int32_t MediaCodecVideoDecoder::Release() {
   2218   return codec_thread_->Invoke<int32_t>(
   2219         Bind(&MediaCodecVideoDecoder::ReleaseOnCodecThread, this));
   2220 }
   2221 
   2222 int32_t MediaCodecVideoDecoder::ReleaseOnCodecThread() {
   2223   if (!inited_) {
   2224     return WEBRTC_VIDEO_CODEC_OK;
   2225   }
   2226   CheckOnCodecThread();
   2227   JNIEnv* jni = AttachCurrentThreadIfNeeded();
   2228   ALOGD("DecoderRelease: Frames received: %d.", frames_received_);
   2229   ScopedLocalRefFrame local_ref_frame(jni);
   2230   for (size_t i = 0; i < input_buffers_.size(); i++) {
   2231     jni->DeleteGlobalRef(input_buffers_[i]);
   2232   }
   2233   input_buffers_.clear();
   2234   if (use_surface_) {
   2235     // Before deleting texture object make sure it is no longer referenced
   2236     // by any TextureVideoFrame.
   2237     int32_t waitTimeoutUs = 3000000;  // 3 second wait
   2238     while (waitTimeoutUs > 0 && native_handle_.ref_count() > 0) {
   2239       ALOGD("Current Texture RefCnt: %d", native_handle_.ref_count());
   2240       usleep(30000);
   2241       waitTimeoutUs -= 30000;
   2242     }
   2243     ALOGD("TextureRefCnt: %d", native_handle_.ref_count());
   2244     jni->DeleteGlobalRef(surface_texture_);
   2245   }
   2246   jni->CallVoidMethod(*j_media_codec_video_decoder_, j_release_method_);
   2247   CHECK_EXCEPTION(jni);
   2248   rtc::MessageQueueManager::Clear(this);
   2249   inited_ = false;
   2250   return WEBRTC_VIDEO_CODEC_OK;
   2251 }
   2252 
   2253 
   2254 void MediaCodecVideoDecoder::CheckOnCodecThread() {
   2255   CHECK(codec_thread_ == ThreadManager::Instance()->CurrentThread())
   2256       << "Running on wrong thread!";
   2257 }
   2258 
   2259 int32_t MediaCodecVideoDecoder::Decode(
   2260     const EncodedImage& inputImage,
   2261     bool missingFrames,
   2262     const RTPFragmentationHeader* fragmentation,
   2263     const CodecSpecificInfo* codecSpecificInfo,
   2264     int64_t renderTimeMs) {
   2265   if (!inited_) {
   2266     return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
   2267   }
   2268   if (callback_ == NULL) {
   2269     return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
   2270   }
   2271   if (inputImage._buffer == NULL && inputImage._length > 0) {
   2272     return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
   2273   }
   2274   // Check if encoded frame dimension has changed.
   2275   if ((inputImage._encodedWidth * inputImage._encodedHeight > 0) &&
   2276       (inputImage._encodedWidth != codec_.width ||
   2277       inputImage._encodedHeight != codec_.height)) {
   2278     codec_.width = inputImage._encodedWidth;
   2279     codec_.height = inputImage._encodedHeight;
   2280     InitDecode(&codec_, 1);
   2281   }
   2282 
   2283   // Always start with a complete key frame.
   2284   if (key_frame_required_) {
   2285     if (inputImage._frameType != webrtc::kKeyFrame) {
   2286       return WEBRTC_VIDEO_CODEC_ERROR;
   2287     }
   2288     if (!inputImage._completeFrame) {
   2289       return WEBRTC_VIDEO_CODEC_ERROR;
   2290     }
   2291     key_frame_required_ = false;
   2292   }
   2293   if (inputImage._length == 0) {
   2294     return WEBRTC_VIDEO_CODEC_ERROR;
   2295   }
   2296 
   2297   return codec_thread_->Invoke<int32_t>(Bind(
   2298       &MediaCodecVideoDecoder::DecodeOnCodecThread, this, inputImage));
   2299 }
   2300 
   2301 int32_t MediaCodecVideoDecoder::DecodeOnCodecThread(
   2302     const EncodedImage& inputImage) {
   2303   static uint8_t yVal_ = 0x7f;
   2304 
   2305   CheckOnCodecThread();
   2306   JNIEnv* jni = AttachCurrentThreadIfNeeded();
   2307   ScopedLocalRefFrame local_ref_frame(jni);
   2308 
   2309   // Try to drain the decoder and wait until output is not too
   2310   // much behind the input.
   2311   if (frames_received_ > frames_decoded_ + max_pending_frames_) {
   2312     ALOGV("Wait for output...");
   2313     if (!DeliverPendingOutputs(jni, kMediaCodecTimeoutMs * 1000)) {
   2314       Reset();
   2315       return WEBRTC_VIDEO_CODEC_ERROR;
   2316     }
   2317     if (frames_received_ > frames_decoded_ + max_pending_frames_) {
   2318       ALOGE("Output buffer dequeue timeout");
   2319       Reset();
   2320       return WEBRTC_VIDEO_CODEC_ERROR;
   2321     }
   2322   }
   2323 
   2324   // Get input buffer.
   2325   int j_input_buffer_index = jni->CallIntMethod(*j_media_codec_video_decoder_,
   2326                                                 j_dequeue_input_buffer_method_);
   2327   CHECK_EXCEPTION(jni);
   2328   if (j_input_buffer_index < 0) {
   2329     ALOGE("dequeueInputBuffer error");
   2330     Reset();
   2331     return WEBRTC_VIDEO_CODEC_ERROR;
   2332   }
   2333 
   2334   // Copy encoded data to Java ByteBuffer.
   2335   jobject j_input_buffer = input_buffers_[j_input_buffer_index];
   2336   uint8* buffer =
   2337       reinterpret_cast<uint8*>(jni->GetDirectBufferAddress(j_input_buffer));
   2338   CHECK(buffer) << "Indirect buffer??";
   2339   int64 buffer_capacity = jni->GetDirectBufferCapacity(j_input_buffer);
   2340   CHECK_EXCEPTION(jni);
   2341   if (buffer_capacity < inputImage._length) {
   2342     ALOGE("Input frame size %d is bigger than buffer size %d.",
   2343         inputImage._length, buffer_capacity);
   2344     Reset();
   2345     return WEBRTC_VIDEO_CODEC_ERROR;
   2346   }
   2347   ALOGV("Decoder frame in # %d. Buffer # %d. Size: %d",
   2348       frames_received_, j_input_buffer_index, inputImage._length);
   2349   memcpy(buffer, inputImage._buffer, inputImage._length);
   2350 
   2351   // Save input image timestamps for later output.
   2352   frames_received_++;
   2353   current_bytes_ += inputImage._length;
   2354   timestamps_.push_back(inputImage._timeStamp);
   2355   ntp_times_ms_.push_back(inputImage.ntp_time_ms_);
   2356   frame_rtc_times_ms_.push_back(GetCurrentTimeMs());
   2357 
   2358   // Feed input to decoder.
   2359   jlong timestamp_us = (frames_received_ * 1000000) / codec_.maxFramerate;
   2360   bool success = jni->CallBooleanMethod(*j_media_codec_video_decoder_,
   2361                                         j_queue_input_buffer_method_,
   2362                                         j_input_buffer_index,
   2363                                         inputImage._length,
   2364                                         timestamp_us);
   2365   CHECK_EXCEPTION(jni);
   2366   if (!success) {
   2367     ALOGE("queueInputBuffer error");
   2368     Reset();
   2369     return WEBRTC_VIDEO_CODEC_ERROR;
   2370   }
   2371 
   2372   // Try to drain the decoder
   2373   if (!DeliverPendingOutputs(jni, 0)) {
   2374     ALOGE("DeliverPendingOutputs error");
   2375     Reset();
   2376     return WEBRTC_VIDEO_CODEC_ERROR;
   2377   }
   2378 
   2379   return WEBRTC_VIDEO_CODEC_OK;
   2380 }
   2381 
   2382 bool MediaCodecVideoDecoder::DeliverPendingOutputs(
   2383     JNIEnv* jni, int dequeue_timeout_us) {
   2384   if (frames_received_ <= frames_decoded_) {
   2385     // No need to query for output buffers - decoder is drained.
   2386     return true;
   2387   }
   2388   // Get decoder output.
   2389   jobject j_decoder_output_buffer_info = jni->CallObjectMethod(
   2390       *j_media_codec_video_decoder_,
   2391       j_dequeue_output_buffer_method_,
   2392       dequeue_timeout_us);
   2393 
   2394   CHECK_EXCEPTION(jni);
   2395   if (IsNull(jni, j_decoder_output_buffer_info)) {
   2396     return true;
   2397   }
   2398 
   2399   // Extract output buffer info from Java DecoderOutputBufferInfo.
   2400   int output_buffer_index =
   2401       GetIntField(jni, j_decoder_output_buffer_info, j_info_index_field_);
   2402   if (output_buffer_index < 0) {
   2403     ALOGE("dequeueOutputBuffer error : %d", output_buffer_index);
   2404     Reset();
   2405     return false;
   2406   }
   2407   int output_buffer_offset =
   2408       GetIntField(jni, j_decoder_output_buffer_info, j_info_offset_field_);
   2409   int output_buffer_size =
   2410       GetIntField(jni, j_decoder_output_buffer_info, j_info_size_field_);
   2411   CHECK_EXCEPTION(jni);
   2412 
   2413   // Get decoded video frame properties.
   2414   int color_format = GetIntField(jni, *j_media_codec_video_decoder_,
   2415       j_color_format_field_);
   2416   int width = GetIntField(jni, *j_media_codec_video_decoder_, j_width_field_);
   2417   int height = GetIntField(jni, *j_media_codec_video_decoder_, j_height_field_);
   2418   int stride = GetIntField(jni, *j_media_codec_video_decoder_, j_stride_field_);
   2419   int slice_height = GetIntField(jni, *j_media_codec_video_decoder_,
   2420       j_slice_height_field_);
   2421   int texture_id = GetIntField(jni, *j_media_codec_video_decoder_,
   2422       j_textureID_field_);
   2423 
   2424   // Extract data from Java ByteBuffer and create output yuv420 frame -
   2425   // for non surface decoding only.
   2426   if (!use_surface_) {
   2427     if (output_buffer_size < width * height * 3 / 2) {
   2428       ALOGE("Insufficient output buffer size: %d", output_buffer_size);
   2429       Reset();
   2430       return false;
   2431     }
   2432     jobjectArray output_buffers = reinterpret_cast<jobjectArray>(GetObjectField(
   2433         jni, *j_media_codec_video_decoder_, j_output_buffers_field_));
   2434     jobject output_buffer =
   2435         jni->GetObjectArrayElement(output_buffers, output_buffer_index);
   2436     uint8_t* payload = reinterpret_cast<uint8_t*>(jni->GetDirectBufferAddress(
   2437         output_buffer));
   2438     CHECK_EXCEPTION(jni);
   2439     payload += output_buffer_offset;
   2440 
   2441     // Create yuv420 frame.
   2442     if (color_format == COLOR_FormatYUV420Planar) {
   2443       decoded_image_.CreateFrame(
   2444           stride * slice_height, payload,
   2445           (stride * slice_height) / 4, payload + (stride * slice_height),
   2446           (stride * slice_height) / 4, payload + (5 * stride * slice_height / 4),
   2447           width, height,
   2448           stride, stride / 2, stride / 2);
   2449     } else {
   2450       // All other supported formats are nv12.
   2451       decoded_image_.CreateEmptyFrame(width, height, width,
   2452           width / 2, width / 2);
   2453       libyuv::NV12ToI420(
   2454           payload, stride,
   2455           payload + stride * slice_height, stride,
   2456           decoded_image_.buffer(webrtc::kYPlane),
   2457           decoded_image_.stride(webrtc::kYPlane),
   2458           decoded_image_.buffer(webrtc::kUPlane),
   2459           decoded_image_.stride(webrtc::kUPlane),
   2460           decoded_image_.buffer(webrtc::kVPlane),
   2461           decoded_image_.stride(webrtc::kVPlane),
   2462           width, height);
   2463     }
   2464   }
   2465 
   2466   // Get frame timestamps from a queue.
   2467   int32_t timestamp = timestamps_.front();
   2468   timestamps_.erase(timestamps_.begin());
   2469   int64_t ntp_time_ms = ntp_times_ms_.front();
   2470   ntp_times_ms_.erase(ntp_times_ms_.begin());
   2471   int64_t frame_decoding_time_ms = GetCurrentTimeMs() -
   2472       frame_rtc_times_ms_.front();
   2473   frame_rtc_times_ms_.erase(frame_rtc_times_ms_.begin());
   2474 
   2475   ALOGV("Decoder frame out # %d. %d x %d. %d x %d. Color: 0x%x. Size: %d."
   2476       " DecTime: %lld", frames_decoded_, width, height, stride, slice_height,
   2477       color_format, output_buffer_size, frame_decoding_time_ms);
   2478 
   2479   // Return output buffer back to codec.
   2480   bool success = jni->CallBooleanMethod(
   2481       *j_media_codec_video_decoder_,
   2482       j_release_output_buffer_method_,
   2483       output_buffer_index,
   2484       use_surface_);
   2485   CHECK_EXCEPTION(jni);
   2486   if (!success) {
   2487     ALOGE("releaseOutputBuffer error");
   2488     Reset();
   2489     return false;
   2490   }
   2491 
   2492   // Calculate and print decoding statistics - every 3 seconds.
   2493   frames_decoded_++;
   2494   current_frames_++;
   2495   current_decoding_time_ms_ += frame_decoding_time_ms;
   2496   int statistic_time_ms = GetCurrentTimeMs() - start_time_ms_;
   2497   if (statistic_time_ms >= kMediaCodecStatisticsIntervalMs &&
   2498       current_frames_ > 0) {
   2499     ALOGD("Decoder bitrate: %d kbps, fps: %d, decTime: %d for last %d ms",
   2500         current_bytes_ * 8 / statistic_time_ms,
   2501         (current_frames_ * 1000 + statistic_time_ms / 2) / statistic_time_ms,
   2502         current_decoding_time_ms_ / current_frames_, statistic_time_ms);
   2503     start_time_ms_ = GetCurrentTimeMs();
   2504     current_frames_ = 0;
   2505     current_bytes_= 0;
   2506     current_decoding_time_ms_ = 0;
   2507   }
   2508 
   2509   // Callback - output decoded frame.
   2510   int32_t callback_status = WEBRTC_VIDEO_CODEC_OK;
   2511   if (use_surface_) {
   2512     native_handle_.SetTextureObject(surface_texture_, texture_id);
   2513     TextureVideoFrame texture_image(
   2514         &native_handle_, width, height, timestamp, 0);
   2515     texture_image.set_ntp_time_ms(ntp_time_ms);
   2516     callback_status = callback_->Decoded(texture_image);
   2517   } else {
   2518     decoded_image_.set_timestamp(timestamp);
   2519     decoded_image_.set_ntp_time_ms(ntp_time_ms);
   2520     callback_status = callback_->Decoded(decoded_image_);
   2521   }
   2522   if (callback_status > 0) {
   2523     ALOGE("callback error");
   2524   }
   2525 
   2526   return true;
   2527 }
   2528 
   2529 int32_t MediaCodecVideoDecoder::RegisterDecodeCompleteCallback(
   2530     DecodedImageCallback* callback) {
   2531   callback_ = callback;
   2532   return WEBRTC_VIDEO_CODEC_OK;
   2533 }
   2534 
   2535 int32_t MediaCodecVideoDecoder::Reset() {
   2536   ALOGD("DecoderReset");
   2537   if (!inited_) {
   2538     return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
   2539   }
   2540   return InitDecode(&codec_, 1);
   2541 }
   2542 
   2543 void MediaCodecVideoDecoder::OnMessage(rtc::Message* msg) {
   2544   JNIEnv* jni = AttachCurrentThreadIfNeeded();
   2545   ScopedLocalRefFrame local_ref_frame(jni);
   2546   if (!inited_) {
   2547     return;
   2548   }
   2549   // We only ever send one message to |this| directly (not through a Bind()'d
   2550   // functor), so expect no ID/data.
   2551   CHECK(!msg->message_id) << "Unexpected message!";
   2552   CHECK(!msg->pdata) << "Unexpected message!";
   2553   CheckOnCodecThread();
   2554 
   2555   DeliverPendingOutputs(jni, 0);
   2556   codec_thread_->PostDelayed(kMediaCodecPollMs, this);
   2557 }
   2558 
   2559 class MediaCodecVideoDecoderFactory
   2560     : public cricket::WebRtcVideoDecoderFactory {
   2561  public:
   2562   MediaCodecVideoDecoderFactory();
   2563   virtual ~MediaCodecVideoDecoderFactory();
   2564   // WebRtcVideoDecoderFactory implementation.
   2565   virtual webrtc::VideoDecoder* CreateVideoDecoder(
   2566       webrtc::VideoCodecType type) OVERRIDE;
   2567 
   2568   virtual void DestroyVideoDecoder(webrtc::VideoDecoder* decoder) OVERRIDE;
   2569 
   2570  private:
   2571   bool is_platform_supported_;
   2572 };
   2573 
   2574 MediaCodecVideoDecoderFactory::MediaCodecVideoDecoderFactory() {
   2575   JNIEnv* jni = AttachCurrentThreadIfNeeded();
   2576   ScopedLocalRefFrame local_ref_frame(jni);
   2577   jclass j_decoder_class = FindClass(jni, "org/webrtc/MediaCodecVideoDecoder");
   2578   is_platform_supported_ = jni->CallStaticBooleanMethod(
   2579       j_decoder_class,
   2580       GetStaticMethodID(jni, j_decoder_class, "isPlatformSupported", "()Z"));
   2581   CHECK_EXCEPTION(jni);
   2582 }
   2583 
   2584 MediaCodecVideoDecoderFactory::~MediaCodecVideoDecoderFactory() {}
   2585 
   2586 webrtc::VideoDecoder* MediaCodecVideoDecoderFactory::CreateVideoDecoder(
   2587     webrtc::VideoCodecType type) {
   2588   if (type != kVideoCodecVP8 || !is_platform_supported_) {
   2589     return NULL;
   2590   }
   2591   return new MediaCodecVideoDecoder(AttachCurrentThreadIfNeeded());
   2592 }
   2593 
   2594 
   2595 void MediaCodecVideoDecoderFactory::DestroyVideoDecoder(
   2596     webrtc::VideoDecoder* decoder) {
   2597   delete decoder;
   2598 }
   2599 
   2600 #endif  // #if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
   2601 
   2602 }  // anonymous namespace
   2603 
   2604 // Convenience macro defining JNI-accessible methods in the org.webrtc package.
   2605 // Eliminates unnecessary boilerplate and line-wraps, reducing visual clutter.
   2606 #define JOW(rettype, name) extern "C" rettype JNIEXPORT JNICALL \
   2607   Java_org_webrtc_##name
   2608 
   2609 extern "C" jint JNIEXPORT JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
   2610   CHECK(!g_jvm) << "JNI_OnLoad called more than once!";
   2611   g_jvm = jvm;
   2612   CHECK(g_jvm) << "JNI_OnLoad handed NULL?";
   2613 
   2614   CHECK(!pthread_once(&g_jni_ptr_once, &CreateJNIPtrKey)) << "pthread_once";
   2615 
   2616   CHECK(rtc::InitializeSSL()) << "Failed to InitializeSSL()";
   2617 
   2618   JNIEnv* jni;
   2619   if (jvm->GetEnv(reinterpret_cast<void**>(&jni), JNI_VERSION_1_6) != JNI_OK)
   2620     return -1;
   2621   g_class_reference_holder = new ClassReferenceHolder(jni);
   2622 
   2623   return JNI_VERSION_1_6;
   2624 }
   2625 
   2626 extern "C" void JNIEXPORT JNICALL JNI_OnUnLoad(JavaVM *jvm, void *reserved) {
   2627   g_class_reference_holder->FreeReferences(AttachCurrentThreadIfNeeded());
   2628   delete g_class_reference_holder;
   2629   g_class_reference_holder = NULL;
   2630   CHECK(rtc::CleanupSSL()) << "Failed to CleanupSSL()";
   2631   g_jvm = NULL;
   2632 }
   2633 
   2634 static DataChannelInterface* ExtractNativeDC(JNIEnv* jni, jobject j_dc) {
   2635   jfieldID native_dc_id = GetFieldID(jni,
   2636       GetObjectClass(jni, j_dc), "nativeDataChannel", "J");
   2637   jlong j_d = GetLongField(jni, j_dc, native_dc_id);
   2638   return reinterpret_cast<DataChannelInterface*>(j_d);
   2639 }
   2640 
   2641 JOW(jlong, DataChannel_registerObserverNative)(
   2642     JNIEnv* jni, jobject j_dc, jobject j_observer) {
   2643   scoped_ptr<DataChannelObserverWrapper> observer(
   2644       new DataChannelObserverWrapper(jni, j_observer));
   2645   ExtractNativeDC(jni, j_dc)->RegisterObserver(observer.get());
   2646   return jlongFromPointer(observer.release());
   2647 }
   2648 
   2649 JOW(void, DataChannel_unregisterObserverNative)(
   2650     JNIEnv* jni, jobject j_dc, jlong native_observer) {
   2651   ExtractNativeDC(jni, j_dc)->UnregisterObserver();
   2652   delete reinterpret_cast<DataChannelObserverWrapper*>(native_observer);
   2653 }
   2654 
   2655 JOW(jstring, DataChannel_label)(JNIEnv* jni, jobject j_dc) {
   2656   return JavaStringFromStdString(jni, ExtractNativeDC(jni, j_dc)->label());
   2657 }
   2658 
   2659 JOW(jobject, DataChannel_state)(JNIEnv* jni, jobject j_dc) {
   2660   return JavaEnumFromIndex(
   2661       jni, "DataChannel$State", ExtractNativeDC(jni, j_dc)->state());
   2662 }
   2663 
   2664 JOW(jlong, DataChannel_bufferedAmount)(JNIEnv* jni, jobject j_dc) {
   2665   uint64 buffered_amount = ExtractNativeDC(jni, j_dc)->buffered_amount();
   2666   CHECK_LE(buffered_amount, std::numeric_limits<int64>::max())
   2667       << "buffered_amount overflowed jlong!";
   2668   return static_cast<jlong>(buffered_amount);
   2669 }
   2670 
   2671 JOW(void, DataChannel_close)(JNIEnv* jni, jobject j_dc) {
   2672   ExtractNativeDC(jni, j_dc)->Close();
   2673 }
   2674 
   2675 JOW(jboolean, DataChannel_sendNative)(JNIEnv* jni, jobject j_dc,
   2676                                       jbyteArray data, jboolean binary) {
   2677   jbyte* bytes = jni->GetByteArrayElements(data, NULL);
   2678   bool ret = ExtractNativeDC(jni, j_dc)->Send(DataBuffer(
   2679       rtc::Buffer(bytes, jni->GetArrayLength(data)),
   2680       binary));
   2681   jni->ReleaseByteArrayElements(data, bytes, JNI_ABORT);
   2682   return ret;
   2683 }
   2684 
   2685 JOW(void, DataChannel_dispose)(JNIEnv* jni, jobject j_dc) {
   2686   CHECK_RELEASE(ExtractNativeDC(jni, j_dc));
   2687 }
   2688 
   2689 JOW(void, Logging_nativeEnableTracing)(
   2690     JNIEnv* jni, jclass, jstring j_path, jint nativeLevels,
   2691     jint nativeSeverity) {
   2692   std::string path = JavaToStdString(jni, j_path);
   2693   if (nativeLevels != webrtc::kTraceNone) {
   2694     webrtc::Trace::set_level_filter(nativeLevels);
   2695 #if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
   2696     if (path != "logcat:") {
   2697 #endif
   2698       CHECK_EQ(0, webrtc::Trace::SetTraceFile(path.c_str(), false))
   2699           << "SetTraceFile failed";
   2700 #if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
   2701     } else {
   2702       // Intentionally leak this to avoid needing to reason about its lifecycle.
   2703       // It keeps no state and functions only as a dispatch point.
   2704       static LogcatTraceContext* g_trace_callback = new LogcatTraceContext();
   2705     }
   2706 #endif
   2707   }
   2708   rtc::LogMessage::LogToDebug(nativeSeverity);
   2709 }
   2710 
   2711 JOW(void, PeerConnection_freePeerConnection)(JNIEnv*, jclass, jlong j_p) {
   2712   CHECK_RELEASE(reinterpret_cast<PeerConnectionInterface*>(j_p));
   2713 }
   2714 
   2715 JOW(void, PeerConnection_freeObserver)(JNIEnv*, jclass, jlong j_p) {
   2716   PCOJava* p = reinterpret_cast<PCOJava*>(j_p);
   2717   delete p;
   2718 }
   2719 
   2720 JOW(void, MediaSource_free)(JNIEnv*, jclass, jlong j_p) {
   2721   CHECK_RELEASE(reinterpret_cast<MediaSourceInterface*>(j_p));
   2722 }
   2723 
   2724 JOW(void, VideoCapturer_free)(JNIEnv*, jclass, jlong j_p) {
   2725   delete reinterpret_cast<cricket::VideoCapturer*>(j_p);
   2726 }
   2727 
   2728 JOW(void, VideoRenderer_freeGuiVideoRenderer)(JNIEnv*, jclass, jlong j_p) {
   2729   delete reinterpret_cast<VideoRendererWrapper*>(j_p);
   2730 }
   2731 
   2732 JOW(void, VideoRenderer_freeWrappedVideoRenderer)(JNIEnv*, jclass, jlong j_p) {
   2733   delete reinterpret_cast<JavaVideoRendererWrapper*>(j_p);
   2734 }
   2735 
   2736 JOW(void, MediaStreamTrack_free)(JNIEnv*, jclass, jlong j_p) {
   2737   CHECK_RELEASE(reinterpret_cast<MediaStreamTrackInterface*>(j_p));
   2738 }
   2739 
   2740 JOW(jboolean, MediaStream_nativeAddAudioTrack)(
   2741     JNIEnv* jni, jclass, jlong pointer, jlong j_audio_track_pointer) {
   2742   return reinterpret_cast<MediaStreamInterface*>(pointer)->AddTrack(
   2743       reinterpret_cast<AudioTrackInterface*>(j_audio_track_pointer));
   2744 }
   2745 
   2746 JOW(jboolean, MediaStream_nativeAddVideoTrack)(
   2747     JNIEnv* jni, jclass, jlong pointer, jlong j_video_track_pointer) {
   2748   return reinterpret_cast<MediaStreamInterface*>(pointer)
   2749       ->AddTrack(reinterpret_cast<VideoTrackInterface*>(j_video_track_pointer));
   2750 }
   2751 
   2752 JOW(jboolean, MediaStream_nativeRemoveAudioTrack)(
   2753     JNIEnv* jni, jclass, jlong pointer, jlong j_audio_track_pointer) {
   2754   return reinterpret_cast<MediaStreamInterface*>(pointer)->RemoveTrack(
   2755       reinterpret_cast<AudioTrackInterface*>(j_audio_track_pointer));
   2756 }
   2757 
   2758 JOW(jboolean, MediaStream_nativeRemoveVideoTrack)(
   2759     JNIEnv* jni, jclass, jlong pointer, jlong j_video_track_pointer) {
   2760   return reinterpret_cast<MediaStreamInterface*>(pointer)->RemoveTrack(
   2761       reinterpret_cast<VideoTrackInterface*>(j_video_track_pointer));
   2762 }
   2763 
   2764 JOW(jstring, MediaStream_nativeLabel)(JNIEnv* jni, jclass, jlong j_p) {
   2765   return JavaStringFromStdString(
   2766       jni, reinterpret_cast<MediaStreamInterface*>(j_p)->label());
   2767 }
   2768 
   2769 JOW(void, MediaStream_free)(JNIEnv*, jclass, jlong j_p) {
   2770   CHECK_RELEASE(reinterpret_cast<MediaStreamInterface*>(j_p));
   2771 }
   2772 
   2773 JOW(jlong, PeerConnectionFactory_nativeCreateObserver)(
   2774     JNIEnv * jni, jclass, jobject j_observer) {
   2775   return (jlong)new PCOJava(jni, j_observer);
   2776 }
   2777 
   2778 #if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
   2779 JOW(jboolean, PeerConnectionFactory_initializeAndroidGlobals)(
   2780     JNIEnv* jni, jclass, jobject context,
   2781     jboolean initialize_audio, jboolean initialize_video,
   2782     jobject render_egl_context) {
   2783   CHECK(g_jvm) << "JNI_OnLoad failed to run?";
   2784   bool failure = false;
   2785   if (!factory_static_initialized) {
   2786     if (initialize_video) {
   2787       failure |= webrtc::SetCaptureAndroidVM(g_jvm, context);
   2788       failure |= webrtc::SetRenderAndroidVM(g_jvm);
   2789     }
   2790     if (initialize_audio)
   2791       failure |= webrtc::VoiceEngine::SetAndroidObjects(g_jvm, jni, context);
   2792     factory_static_initialized = true;
   2793   }
   2794   if (initialize_video)
   2795     failure |= MediaCodecVideoDecoder::SetAndroidObjects(jni,
   2796         render_egl_context);
   2797   return !failure;
   2798 }
   2799 #endif  // defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
   2800 
   2801 // Helper struct for working around the fact that CreatePeerConnectionFactory()
   2802 // comes in two flavors: either entirely automagical (constructing its own
   2803 // threads and deleting them on teardown, but no external codec factory support)
   2804 // or entirely manual (requires caller to delete threads after factory
   2805 // teardown).  This struct takes ownership of its ctor's arguments to present a
   2806 // single thing for Java to hold and eventually free.
   2807 class OwnedFactoryAndThreads {
   2808  public:
   2809   OwnedFactoryAndThreads(Thread* worker_thread,
   2810                          Thread* signaling_thread,
   2811                          PeerConnectionFactoryInterface* factory)
   2812       : worker_thread_(worker_thread),
   2813         signaling_thread_(signaling_thread),
   2814         factory_(factory) {}
   2815 
   2816   ~OwnedFactoryAndThreads() { CHECK_RELEASE(factory_); }
   2817 
   2818   PeerConnectionFactoryInterface* factory() { return factory_; }
   2819 
   2820  private:
   2821   const scoped_ptr<Thread> worker_thread_;
   2822   const scoped_ptr<Thread> signaling_thread_;
   2823   PeerConnectionFactoryInterface* factory_;  // Const after ctor except dtor.
   2824 };
   2825 
   2826 JOW(jlong, PeerConnectionFactory_nativeCreatePeerConnectionFactory)(
   2827     JNIEnv* jni, jclass) {
   2828   // talk/ assumes pretty widely that the current Thread is ThreadManager'd, but
   2829   // ThreadManager only WrapCurrentThread()s the thread where it is first
   2830   // created.  Since the semantics around when auto-wrapping happens in
   2831   // webrtc/base/ are convoluted, we simply wrap here to avoid having to think
   2832   // about ramifications of auto-wrapping there.
   2833   rtc::ThreadManager::Instance()->WrapCurrentThread();
   2834   webrtc::Trace::CreateTrace();
   2835   Thread* worker_thread = new Thread();
   2836   worker_thread->SetName("worker_thread", NULL);
   2837   Thread* signaling_thread = new Thread();
   2838   signaling_thread->SetName("signaling_thread", NULL);
   2839   CHECK(worker_thread->Start() && signaling_thread->Start())
   2840       << "Failed to start threads";
   2841   scoped_ptr<cricket::WebRtcVideoEncoderFactory> encoder_factory;
   2842   scoped_ptr<cricket::WebRtcVideoDecoderFactory> decoder_factory;
   2843 #if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
   2844   encoder_factory.reset(new MediaCodecVideoEncoderFactory());
   2845   decoder_factory.reset(new MediaCodecVideoDecoderFactory());
   2846 #endif
   2847   rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
   2848       webrtc::CreatePeerConnectionFactory(worker_thread,
   2849                                           signaling_thread,
   2850                                           NULL,
   2851                                           encoder_factory.release(),
   2852                                           decoder_factory.release()));
   2853   OwnedFactoryAndThreads* owned_factory = new OwnedFactoryAndThreads(
   2854       worker_thread, signaling_thread, factory.release());
   2855   return jlongFromPointer(owned_factory);
   2856 }
   2857 
   2858 JOW(void, PeerConnectionFactory_freeFactory)(JNIEnv*, jclass, jlong j_p) {
   2859   delete reinterpret_cast<OwnedFactoryAndThreads*>(j_p);
   2860   webrtc::Trace::ReturnTrace();
   2861 }
   2862 
   2863 static PeerConnectionFactoryInterface* factoryFromJava(jlong j_p) {
   2864   return reinterpret_cast<OwnedFactoryAndThreads*>(j_p)->factory();
   2865 }
   2866 
   2867 JOW(jlong, PeerConnectionFactory_nativeCreateLocalMediaStream)(
   2868     JNIEnv* jni, jclass, jlong native_factory, jstring label) {
   2869   rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
   2870       factoryFromJava(native_factory));
   2871   rtc::scoped_refptr<MediaStreamInterface> stream(
   2872       factory->CreateLocalMediaStream(JavaToStdString(jni, label)));
   2873   return (jlong)stream.release();
   2874 }
   2875 
   2876 JOW(jlong, PeerConnectionFactory_nativeCreateVideoSource)(
   2877     JNIEnv* jni, jclass, jlong native_factory, jlong native_capturer,
   2878     jobject j_constraints) {
   2879   scoped_ptr<ConstraintsWrapper> constraints(
   2880       new ConstraintsWrapper(jni, j_constraints));
   2881   rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
   2882       factoryFromJava(native_factory));
   2883   rtc::scoped_refptr<VideoSourceInterface> source(
   2884       factory->CreateVideoSource(
   2885           reinterpret_cast<cricket::VideoCapturer*>(native_capturer),
   2886           constraints.get()));
   2887   return (jlong)source.release();
   2888 }
   2889 
   2890 JOW(jlong, PeerConnectionFactory_nativeCreateVideoTrack)(
   2891     JNIEnv* jni, jclass, jlong native_factory, jstring id,
   2892     jlong native_source) {
   2893   rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
   2894       factoryFromJava(native_factory));
   2895   rtc::scoped_refptr<VideoTrackInterface> track(
   2896       factory->CreateVideoTrack(
   2897           JavaToStdString(jni, id),
   2898           reinterpret_cast<VideoSourceInterface*>(native_source)));
   2899   return (jlong)track.release();
   2900 }
   2901 
   2902 JOW(jlong, PeerConnectionFactory_nativeCreateAudioSource)(
   2903     JNIEnv* jni, jclass, jlong native_factory, jobject j_constraints) {
   2904   scoped_ptr<ConstraintsWrapper> constraints(
   2905       new ConstraintsWrapper(jni, j_constraints));
   2906   rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
   2907       factoryFromJava(native_factory));
   2908   rtc::scoped_refptr<AudioSourceInterface> source(
   2909       factory->CreateAudioSource(constraints.get()));
   2910   return (jlong)source.release();
   2911 }
   2912 
   2913 JOW(jlong, PeerConnectionFactory_nativeCreateAudioTrack)(
   2914     JNIEnv* jni, jclass, jlong native_factory, jstring id,
   2915     jlong native_source) {
   2916   rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
   2917       factoryFromJava(native_factory));
   2918   rtc::scoped_refptr<AudioTrackInterface> track(factory->CreateAudioTrack(
   2919       JavaToStdString(jni, id),
   2920       reinterpret_cast<AudioSourceInterface*>(native_source)));
   2921   return (jlong)track.release();
   2922 }
   2923 
   2924 static void JavaIceServersToJsepIceServers(
   2925     JNIEnv* jni, jobject j_ice_servers,
   2926     PeerConnectionInterface::IceServers* ice_servers) {
   2927   jclass list_class = GetObjectClass(jni, j_ice_servers);
   2928   jmethodID iterator_id = GetMethodID(
   2929       jni, list_class, "iterator", "()Ljava/util/Iterator;");
   2930   jobject iterator = jni->CallObjectMethod(j_ice_servers, iterator_id);
   2931   CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
   2932   jmethodID iterator_has_next = GetMethodID(
   2933       jni, GetObjectClass(jni, iterator), "hasNext", "()Z");
   2934   jmethodID iterator_next = GetMethodID(
   2935       jni, GetObjectClass(jni, iterator), "next", "()Ljava/lang/Object;");
   2936   while (jni->CallBooleanMethod(iterator, iterator_has_next)) {
   2937     CHECK_EXCEPTION(jni) << "error during CallBooleanMethod";
   2938     jobject j_ice_server = jni->CallObjectMethod(iterator, iterator_next);
   2939     CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
   2940     jclass j_ice_server_class = GetObjectClass(jni, j_ice_server);
   2941     jfieldID j_ice_server_uri_id =
   2942         GetFieldID(jni, j_ice_server_class, "uri", "Ljava/lang/String;");
   2943     jfieldID j_ice_server_username_id =
   2944         GetFieldID(jni, j_ice_server_class, "username", "Ljava/lang/String;");
   2945     jfieldID j_ice_server_password_id =
   2946         GetFieldID(jni, j_ice_server_class, "password", "Ljava/lang/String;");
   2947     jstring uri = reinterpret_cast<jstring>(
   2948         GetObjectField(jni, j_ice_server, j_ice_server_uri_id));
   2949     jstring username = reinterpret_cast<jstring>(
   2950         GetObjectField(jni, j_ice_server, j_ice_server_username_id));
   2951     jstring password = reinterpret_cast<jstring>(
   2952         GetObjectField(jni, j_ice_server, j_ice_server_password_id));
   2953     PeerConnectionInterface::IceServer server;
   2954     server.uri = JavaToStdString(jni, uri);
   2955     server.username = JavaToStdString(jni, username);
   2956     server.password = JavaToStdString(jni, password);
   2957     ice_servers->push_back(server);
   2958   }
   2959   CHECK_EXCEPTION(jni) << "error during CallBooleanMethod";
   2960 }
   2961 
   2962 JOW(jlong, PeerConnectionFactory_nativeCreatePeerConnection)(
   2963     JNIEnv *jni, jclass, jlong factory, jobject j_ice_servers,
   2964     jobject j_constraints, jlong observer_p) {
   2965   rtc::scoped_refptr<PeerConnectionFactoryInterface> f(
   2966       reinterpret_cast<PeerConnectionFactoryInterface*>(
   2967           factoryFromJava(factory)));
   2968   PeerConnectionInterface::IceServers servers;
   2969   JavaIceServersToJsepIceServers(jni, j_ice_servers, &servers);
   2970   PCOJava* observer = reinterpret_cast<PCOJava*>(observer_p);
   2971   observer->SetConstraints(new ConstraintsWrapper(jni, j_constraints));
   2972   rtc::scoped_refptr<PeerConnectionInterface> pc(f->CreatePeerConnection(
   2973       servers, observer->constraints(), NULL, NULL, observer));
   2974   return (jlong)pc.release();
   2975 }
   2976 
   2977 static rtc::scoped_refptr<PeerConnectionInterface> ExtractNativePC(
   2978     JNIEnv* jni, jobject j_pc) {
   2979   jfieldID native_pc_id = GetFieldID(jni,
   2980       GetObjectClass(jni, j_pc), "nativePeerConnection", "J");
   2981   jlong j_p = GetLongField(jni, j_pc, native_pc_id);
   2982   return rtc::scoped_refptr<PeerConnectionInterface>(
   2983       reinterpret_cast<PeerConnectionInterface*>(j_p));
   2984 }
   2985 
   2986 JOW(jobject, PeerConnection_getLocalDescription)(JNIEnv* jni, jobject j_pc) {
   2987   const SessionDescriptionInterface* sdp =
   2988       ExtractNativePC(jni, j_pc)->local_description();
   2989   return sdp ? JavaSdpFromNativeSdp(jni, sdp) : NULL;
   2990 }
   2991 
   2992 JOW(jobject, PeerConnection_getRemoteDescription)(JNIEnv* jni, jobject j_pc) {
   2993   const SessionDescriptionInterface* sdp =
   2994       ExtractNativePC(jni, j_pc)->remote_description();
   2995   return sdp ? JavaSdpFromNativeSdp(jni, sdp) : NULL;
   2996 }
   2997 
   2998 JOW(jobject, PeerConnection_createDataChannel)(
   2999     JNIEnv* jni, jobject j_pc, jstring j_label, jobject j_init) {
   3000   DataChannelInit init = JavaDataChannelInitToNative(jni, j_init);
   3001   rtc::scoped_refptr<DataChannelInterface> channel(
   3002       ExtractNativePC(jni, j_pc)->CreateDataChannel(
   3003           JavaToStdString(jni, j_label), &init));
   3004   // Mustn't pass channel.get() directly through NewObject to avoid reading its
   3005   // vararg parameter as 64-bit and reading memory that doesn't belong to the
   3006   // 32-bit parameter.
   3007   jlong nativeChannelPtr = jlongFromPointer(channel.get());
   3008   CHECK(nativeChannelPtr) << "Failed to create DataChannel";
   3009   jclass j_data_channel_class = FindClass(jni, "org/webrtc/DataChannel");
   3010   jmethodID j_data_channel_ctor = GetMethodID(
   3011       jni, j_data_channel_class, "<init>", "(J)V");
   3012   jobject j_channel = jni->NewObject(
   3013       j_data_channel_class, j_data_channel_ctor, nativeChannelPtr);
   3014   CHECK_EXCEPTION(jni) << "error during NewObject";
   3015   // Channel is now owned by Java object, and will be freed from there.
   3016   int bumped_count = channel->AddRef();
   3017   CHECK(bumped_count == 2) << "Unexpected refcount";
   3018   return j_channel;
   3019 }
   3020 
   3021 JOW(void, PeerConnection_createOffer)(
   3022     JNIEnv* jni, jobject j_pc, jobject j_observer, jobject j_constraints) {
   3023   ConstraintsWrapper* constraints =
   3024       new ConstraintsWrapper(jni, j_constraints);
   3025   rtc::scoped_refptr<CreateSdpObserverWrapper> observer(
   3026       new rtc::RefCountedObject<CreateSdpObserverWrapper>(
   3027           jni, j_observer, constraints));
   3028   ExtractNativePC(jni, j_pc)->CreateOffer(observer, constraints);
   3029 }
   3030 
   3031 JOW(void, PeerConnection_createAnswer)(
   3032     JNIEnv* jni, jobject j_pc, jobject j_observer, jobject j_constraints) {
   3033   ConstraintsWrapper* constraints =
   3034       new ConstraintsWrapper(jni, j_constraints);
   3035   rtc::scoped_refptr<CreateSdpObserverWrapper> observer(
   3036       new rtc::RefCountedObject<CreateSdpObserverWrapper>(
   3037           jni, j_observer, constraints));
   3038   ExtractNativePC(jni, j_pc)->CreateAnswer(observer, constraints);
   3039 }
   3040 
   3041 // Helper to create a SessionDescriptionInterface from a SessionDescription.
   3042 static SessionDescriptionInterface* JavaSdpToNativeSdp(
   3043     JNIEnv* jni, jobject j_sdp) {
   3044   jfieldID j_type_id = GetFieldID(
   3045       jni, GetObjectClass(jni, j_sdp), "type",
   3046       "Lorg/webrtc/SessionDescription$Type;");
   3047   jobject j_type = GetObjectField(jni, j_sdp, j_type_id);
   3048   jmethodID j_canonical_form_id = GetMethodID(
   3049       jni, GetObjectClass(jni, j_type), "canonicalForm",
   3050       "()Ljava/lang/String;");
   3051   jstring j_type_string = (jstring)jni->CallObjectMethod(
   3052       j_type, j_canonical_form_id);
   3053   CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
   3054   std::string std_type = JavaToStdString(jni, j_type_string);
   3055 
   3056   jfieldID j_description_id = GetFieldID(
   3057       jni, GetObjectClass(jni, j_sdp), "description", "Ljava/lang/String;");
   3058   jstring j_description = (jstring)GetObjectField(jni, j_sdp, j_description_id);
   3059   std::string std_description = JavaToStdString(jni, j_description);
   3060 
   3061   return webrtc::CreateSessionDescription(
   3062       std_type, std_description, NULL);
   3063 }
   3064 
   3065 JOW(void, PeerConnection_setLocalDescription)(
   3066     JNIEnv* jni, jobject j_pc,
   3067     jobject j_observer, jobject j_sdp) {
   3068   rtc::scoped_refptr<SetSdpObserverWrapper> observer(
   3069       new rtc::RefCountedObject<SetSdpObserverWrapper>(
   3070           jni, j_observer, reinterpret_cast<ConstraintsWrapper*>(NULL)));
   3071   ExtractNativePC(jni, j_pc)->SetLocalDescription(
   3072       observer, JavaSdpToNativeSdp(jni, j_sdp));
   3073 }
   3074 
   3075 JOW(void, PeerConnection_setRemoteDescription)(
   3076     JNIEnv* jni, jobject j_pc,
   3077     jobject j_observer, jobject j_sdp) {
   3078   rtc::scoped_refptr<SetSdpObserverWrapper> observer(
   3079       new rtc::RefCountedObject<SetSdpObserverWrapper>(
   3080           jni, j_observer, reinterpret_cast<ConstraintsWrapper*>(NULL)));
   3081   ExtractNativePC(jni, j_pc)->SetRemoteDescription(
   3082       observer, JavaSdpToNativeSdp(jni, j_sdp));
   3083 }
   3084 
   3085 JOW(jboolean, PeerConnection_updateIce)(
   3086     JNIEnv* jni, jobject j_pc, jobject j_ice_servers, jobject j_constraints) {
   3087   PeerConnectionInterface::IceServers ice_servers;
   3088   JavaIceServersToJsepIceServers(jni, j_ice_servers, &ice_servers);
   3089   scoped_ptr<ConstraintsWrapper> constraints(
   3090       new ConstraintsWrapper(jni, j_constraints));
   3091   return ExtractNativePC(jni, j_pc)->UpdateIce(ice_servers, constraints.get());
   3092 }
   3093 
   3094 JOW(jboolean, PeerConnection_nativeAddIceCandidate)(
   3095     JNIEnv* jni, jobject j_pc, jstring j_sdp_mid,
   3096     jint j_sdp_mline_index, jstring j_candidate_sdp) {
   3097   std::string sdp_mid = JavaToStdString(jni, j_sdp_mid);
   3098   std::string sdp = JavaToStdString(jni, j_candidate_sdp);
   3099   scoped_ptr<IceCandidateInterface> candidate(
   3100       webrtc::CreateIceCandidate(sdp_mid, j_sdp_mline_index, sdp, NULL));
   3101   return ExtractNativePC(jni, j_pc)->AddIceCandidate(candidate.get());
   3102 }
   3103 
   3104 JOW(jboolean, PeerConnection_nativeAddLocalStream)(
   3105     JNIEnv* jni, jobject j_pc, jlong native_stream, jobject j_constraints) {
   3106   scoped_ptr<ConstraintsWrapper> constraints(
   3107       new ConstraintsWrapper(jni, j_constraints));
   3108   return ExtractNativePC(jni, j_pc)->AddStream(
   3109       reinterpret_cast<MediaStreamInterface*>(native_stream),
   3110       constraints.get());
   3111 }
   3112 
   3113 JOW(void, PeerConnection_nativeRemoveLocalStream)(
   3114     JNIEnv* jni, jobject j_pc, jlong native_stream) {
   3115   ExtractNativePC(jni, j_pc)->RemoveStream(
   3116       reinterpret_cast<MediaStreamInterface*>(native_stream));
   3117 }
   3118 
   3119 JOW(bool, PeerConnection_nativeGetStats)(
   3120     JNIEnv* jni, jobject j_pc, jobject j_observer, jlong native_track) {
   3121   rtc::scoped_refptr<StatsObserverWrapper> observer(
   3122       new rtc::RefCountedObject<StatsObserverWrapper>(jni, j_observer));
   3123   return ExtractNativePC(jni, j_pc)->GetStats(
   3124       observer,
   3125       reinterpret_cast<MediaStreamTrackInterface*>(native_track),
   3126       PeerConnectionInterface::kStatsOutputLevelStandard);
   3127 }
   3128 
   3129 JOW(jobject, PeerConnection_signalingState)(JNIEnv* jni, jobject j_pc) {
   3130   PeerConnectionInterface::SignalingState state =
   3131       ExtractNativePC(jni, j_pc)->signaling_state();
   3132   return JavaEnumFromIndex(jni, "PeerConnection$SignalingState", state);
   3133 }
   3134 
   3135 JOW(jobject, PeerConnection_iceConnectionState)(JNIEnv* jni, jobject j_pc) {
   3136   PeerConnectionInterface::IceConnectionState state =
   3137       ExtractNativePC(jni, j_pc)->ice_connection_state();
   3138   return JavaEnumFromIndex(jni, "PeerConnection$IceConnectionState", state);
   3139 }
   3140 
   3141 JOW(jobject, PeerGathering_iceGatheringState)(JNIEnv* jni, jobject j_pc) {
   3142   PeerConnectionInterface::IceGatheringState state =
   3143       ExtractNativePC(jni, j_pc)->ice_gathering_state();
   3144   return JavaEnumFromIndex(jni, "PeerGathering$IceGatheringState", state);
   3145 }
   3146 
   3147 JOW(void, PeerConnection_close)(JNIEnv* jni, jobject j_pc) {
   3148   ExtractNativePC(jni, j_pc)->Close();
   3149   return;
   3150 }
   3151 
   3152 JOW(jobject, MediaSource_nativeState)(JNIEnv* jni, jclass, jlong j_p) {
   3153   rtc::scoped_refptr<MediaSourceInterface> p(
   3154       reinterpret_cast<MediaSourceInterface*>(j_p));
   3155   return JavaEnumFromIndex(jni, "MediaSource$State", p->state());
   3156 }
   3157 
   3158 JOW(jlong, VideoCapturer_nativeCreateVideoCapturer)(
   3159     JNIEnv* jni, jclass, jstring j_device_name) {
   3160   std::string device_name = JavaToStdString(jni, j_device_name);
   3161   scoped_ptr<cricket::DeviceManagerInterface> device_manager(
   3162       cricket::DeviceManagerFactory::Create());
   3163   CHECK(device_manager->Init()) << "DeviceManager::Init() failed";
   3164   cricket::Device device;
   3165   if (!device_manager->GetVideoCaptureDevice(device_name, &device)) {
   3166     LOG(LS_ERROR) << "GetVideoCaptureDevice failed for " << device_name;
   3167     return 0;
   3168   }
   3169   scoped_ptr<cricket::VideoCapturer> capturer(
   3170       device_manager->CreateVideoCapturer(device));
   3171   return (jlong)capturer.release();
   3172 }
   3173 
   3174 JOW(jlong, VideoRenderer_nativeCreateGuiVideoRenderer)(
   3175     JNIEnv* jni, jclass, int x, int y) {
   3176   scoped_ptr<VideoRendererWrapper> renderer(VideoRendererWrapper::Create(
   3177       cricket::VideoRendererFactory::CreateGuiVideoRenderer(x, y)));
   3178   return (jlong)renderer.release();
   3179 }
   3180 
   3181 JOW(jlong, VideoRenderer_nativeWrapVideoRenderer)(
   3182     JNIEnv* jni, jclass, jobject j_callbacks) {
   3183   scoped_ptr<JavaVideoRendererWrapper> renderer(
   3184       new JavaVideoRendererWrapper(jni, j_callbacks));
   3185   return (jlong)renderer.release();
   3186 }
   3187 
   3188 JOW(jlong, VideoSource_stop)(JNIEnv* jni, jclass, jlong j_p) {
   3189   cricket::VideoCapturer* capturer =
   3190       reinterpret_cast<VideoSourceInterface*>(j_p)->GetVideoCapturer();
   3191   scoped_ptr<cricket::VideoFormatPod> format(
   3192       new cricket::VideoFormatPod(*capturer->GetCaptureFormat()));
   3193   capturer->Stop();
   3194   return jlongFromPointer(format.release());
   3195 }
   3196 
   3197 JOW(void, VideoSource_restart)(
   3198     JNIEnv* jni, jclass, jlong j_p_source, jlong j_p_format) {
   3199   CHECK(j_p_source);
   3200   CHECK(j_p_format);
   3201   scoped_ptr<cricket::VideoFormatPod> format(
   3202       reinterpret_cast<cricket::VideoFormatPod*>(j_p_format));
   3203   reinterpret_cast<VideoSourceInterface*>(j_p_source)->GetVideoCapturer()->
   3204       StartCapturing(cricket::VideoFormat(*format));
   3205 }
   3206 
   3207 JOW(void, VideoSource_freeNativeVideoFormat)(
   3208     JNIEnv* jni, jclass, jlong j_p) {
   3209   delete reinterpret_cast<cricket::VideoFormatPod*>(j_p);
   3210 }
   3211 
   3212 JOW(jstring, MediaStreamTrack_nativeId)(JNIEnv* jni, jclass, jlong j_p) {
   3213   return JavaStringFromStdString(
   3214       jni, reinterpret_cast<MediaStreamTrackInterface*>(j_p)->id());
   3215 }
   3216 
   3217 JOW(jstring, MediaStreamTrack_nativeKind)(JNIEnv* jni, jclass, jlong j_p) {
   3218   return JavaStringFromStdString(
   3219       jni, reinterpret_cast<MediaStreamTrackInterface*>(j_p)->kind());
   3220 }
   3221 
   3222 JOW(jboolean, MediaStreamTrack_nativeEnabled)(JNIEnv* jni, jclass, jlong j_p) {
   3223   return reinterpret_cast<MediaStreamTrackInterface*>(j_p)->enabled();
   3224 }
   3225 
   3226 JOW(jobject, MediaStreamTrack_nativeState)(JNIEnv* jni, jclass, jlong j_p) {
   3227   return JavaEnumFromIndex(
   3228       jni,
   3229       "MediaStreamTrack$State",
   3230       reinterpret_cast<MediaStreamTrackInterface*>(j_p)->state());
   3231 }
   3232 
   3233 JOW(jboolean, MediaStreamTrack_nativeSetState)(
   3234     JNIEnv* jni, jclass, jlong j_p, jint j_new_state) {
   3235   MediaStreamTrackInterface::TrackState new_state =
   3236       (MediaStreamTrackInterface::TrackState)j_new_state;
   3237   return reinterpret_cast<MediaStreamTrackInterface*>(j_p)
   3238       ->set_state(new_state);
   3239 }
   3240 
   3241 JOW(jboolean, MediaStreamTrack_nativeSetEnabled)(
   3242     JNIEnv* jni, jclass, jlong j_p, jboolean enabled) {
   3243   return reinterpret_cast<MediaStreamTrackInterface*>(j_p)
   3244       ->set_enabled(enabled);
   3245 }
   3246 
   3247 JOW(void, VideoTrack_nativeAddRenderer)(
   3248     JNIEnv* jni, jclass,
   3249     jlong j_video_track_pointer, jlong j_renderer_pointer) {
   3250   reinterpret_cast<VideoTrackInterface*>(j_video_track_pointer)->AddRenderer(
   3251       reinterpret_cast<VideoRendererInterface*>(j_renderer_pointer));
   3252 }
   3253 
   3254 JOW(void, VideoTrack_nativeRemoveRenderer)(
   3255     JNIEnv* jni, jclass,
   3256     jlong j_video_track_pointer, jlong j_renderer_pointer) {
   3257   reinterpret_cast<VideoTrackInterface*>(j_video_track_pointer)->RemoveRenderer(
   3258       reinterpret_cast<VideoRendererInterface*>(j_renderer_pointer));
   3259 }
   3260