/*
 * Copyright 2009, The Android Open Source Project
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "MediaPlayerPrivateAndroid.h"

#if ENABLE(VIDEO)

#include "BaseLayerAndroid.h"
#include "GraphicsContext.h"
#include "HTMLMediaElement.h"
#include "SkiaUtils.h"
#include "TilesManager.h"
#include "VideoLayerAndroid.h"
#include "WebCoreJni.h"
#include "WebViewCore.h"
#include <GraphicsJNI.h>
#include <JNIHelp.h>
#include <JNIUtility.h>
#include <SkBitmap.h>
#include <gui/GLConsumer.h>

using namespace android;
// Forward decl
namespace android {
sp<GLConsumer> SurfaceTexture_getSurfaceTexture(JNIEnv* env, jobject thiz);
};

namespace WebCore {

static const char* g_ProxyJavaClass = "android/webkit/HTML5VideoViewProxy";
static const char* g_ProxyJavaClassAudio = "android/webkit/HTML5Audio";

struct MediaPlayerPrivate::JavaGlue {
    jobject   m_javaProxy;
    jmethodID m_play;
    jmethodID m_enterFullscreenForVideoLayer;
    jmethodID m_teardown;
    jmethodID m_seek;
    jmethodID m_pause;
    // Audio
    jmethodID m_newInstance;
    jmethodID m_setDataSource;
    jmethodID m_getMaxTimeSeekable;
    // Video
    jmethodID m_getInstance;
    jmethodID m_loadPoster;
};

MediaPlayerPrivate::~MediaPlayerPrivate()
{
    TilesManager::instance()->videoLayerManager()->removeLayer(m_videoLayer->uniqueId());
    // m_videoLayer is reference counted, unref is enough here.
    m_videoLayer->unref();
    if (m_glue->m_javaProxy) {
        JNIEnv* env = JSC::Bindings::getJNIEnv();
        if (env) {
            env->CallVoidMethod(m_glue->m_javaProxy, m_glue->m_teardown);
            env->DeleteGlobalRef(m_glue->m_javaProxy);
        }
    }
    delete m_glue;
}

void MediaPlayerPrivate::registerMediaEngine(MediaEngineRegistrar registrar)
{
    registrar(create, getSupportedTypes, supportsType, 0, 0, 0);
}

MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const String& type, const String& codecs)
{
    if (WebViewCore::isSupportedMediaMimeType(type))
        return MediaPlayer::MayBeSupported;
    return MediaPlayer::IsNotSupported;
}

void MediaPlayerPrivate::pause()
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    if (!env || !m_glue->m_javaProxy || !m_url.length())
        return;

    m_paused = true;
    m_player->playbackStateChanged();
    env->CallVoidMethod(m_glue->m_javaProxy, m_glue->m_pause);
    checkException(env);
}

void MediaPlayerPrivate::setVisible(bool visible)
{
    m_isVisible = visible;
    if (m_isVisible)
        createJavaPlayerIfNeeded();
}

void MediaPlayerPrivate::seek(float time)
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    if (!env || !m_url.length())
        return;

    if (m_glue->m_javaProxy) {
        env->CallVoidMethod(m_glue->m_javaProxy, m_glue->m_seek, static_cast<jint>(time * 1000.0f));
        m_currentTime = time;
    }
    checkException(env);
}

void MediaPlayerPrivate::prepareToPlay()
{
    // We are about to start playing. Since our Java VideoView cannot
    // buffer any data, we just simply transition to the HaveEnoughData
    // state in here. This will allow the MediaPlayer to transition to
    // the "play" state, at which point our VideoView will start downloading
    // the content and start the playback.
    m_networkState = MediaPlayer::Loaded;
    m_player->networkStateChanged();
    m_readyState = MediaPlayer::HaveEnoughData;
    m_player->readyStateChanged();
}

MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player)
    : m_player(player),
    m_glue(0),
    m_duration(1), // keep this minimal to avoid initial seek problem
    m_currentTime(0),
    m_paused(true),
    m_readyState(MediaPlayer::HaveNothing),
    m_networkState(MediaPlayer::Empty),
    m_poster(0),
    m_naturalSize(100, 100),
    m_naturalSizeUnknown(true),
    m_isVisible(false),
    m_videoLayer(new VideoLayerAndroid())
{
}

void MediaPlayerPrivate::onEnded()
{
    m_currentTime = duration();
    m_player->timeChanged();
    m_paused = true;
    m_player->playbackStateChanged();
    m_networkState = MediaPlayer::Idle;
}

void MediaPlayerPrivate::onRequestPlay()
{
    play();
}

void MediaPlayerPrivate::onRestoreState()
{
    if (!m_paused) {
        //Kick off a JNI call to start the video.
        play();
    }
}

void MediaPlayerPrivate::onPaused()
{
    m_paused = true;
    m_player->playbackStateChanged();
    m_networkState = MediaPlayer::Idle;
    m_player->playbackStateChanged();
}

void MediaPlayerPrivate::onTimeupdate(int position)
{
    m_currentTime = position / 1000.0f;
    m_player->timeChanged();
}

void MediaPlayerPrivate::onStopFullscreen(bool stillPlaying)
{
    if (m_player && m_player->mediaPlayerClient()) {
        Document* doc = m_player->mediaPlayerClient()->mediaPlayerOwningDocument();
        if (doc) {
            HTMLMediaElement* element =
                static_cast<HTMLMediaElement*>(doc->webkitCurrentFullScreenElement());
            element->exitFullscreen();
            doc->webkitDidExitFullScreenForElement(element);

            if (stillPlaying)
                element->play(true);
        }
    }
}

class MediaPlayerVideoPrivate : public MediaPlayerPrivate {
public:
    void load(const String& url)
    {
        m_url = url;
        // Cheat a bit here to make sure Window.onLoad event can be triggered
        // at the right time instead of real video play time, since only full
        // screen video play is supported in Java's VideoView.
        // See also comments in prepareToPlay function.
        m_networkState = MediaPlayer::Loading;
        m_player->networkStateChanged();
        m_readyState = MediaPlayer::HaveCurrentData;
        m_player->readyStateChanged();
    }

    void play()
    {
        JNIEnv* env = JSC::Bindings::getJNIEnv();
        if (!env || !m_url.length() || !m_glue->m_javaProxy)
            return;

        m_paused = false;
        m_player->playbackStateChanged();

        if (m_currentTime == duration())
            m_currentTime = 0;

        jstring jUrl = wtfStringToJstring(env, m_url);
        env->CallVoidMethod(m_glue->m_javaProxy, m_glue->m_play, jUrl,
                            static_cast<jint>(m_currentTime * 1000.0f),
                            m_videoLayer->uniqueId());
        env->DeleteLocalRef(jUrl);

        checkException(env);
    }

    void enterFullscreenMode()
    {
        JNIEnv* env = JSC::Bindings::getJNIEnv();
        if (!env || !m_url.length() || !m_glue->m_javaProxy)
            return;

        jstring jUrl = wtfStringToJstring(env, m_url);
        env->CallVoidMethod(m_glue->m_javaProxy,
                            m_glue->m_enterFullscreenForVideoLayer, jUrl,
                            m_videoLayer->uniqueId());
        env->DeleteLocalRef(jUrl);

        checkException(env);
    }

    bool canLoadPoster() const { return true; }
    void setPoster(const String& url)
    {
        if (m_posterUrl == url)
            return;

        m_posterUrl = url;
        JNIEnv* env = JSC::Bindings::getJNIEnv();
        if (!env || !m_glue->m_javaProxy || !m_posterUrl.length())
            return;
        // Send the poster
        jstring jUrl = wtfStringToJstring(env, m_posterUrl);
        env->CallVoidMethod(m_glue->m_javaProxy, m_glue->m_loadPoster, jUrl);
        env->DeleteLocalRef(jUrl);
    }
    void paint(GraphicsContext* ctxt, const IntRect& r)
    {
        if (ctxt->paintingDisabled())
            return;

        if (!m_isVisible)
            return;

        if (!m_poster || (!m_poster->getPixels() && !m_poster->pixelRef()))
            return;

        // We paint with the following rules in mind:
        // - only downscale the poster, never upscale
        // - maintain the natural aspect ratio of the poster
        // - the poster should be centered in the target rect
        float originalRatio = static_cast<float>(m_poster->width()) / static_cast<float>(m_poster->height());
        int posterWidth = r.width() > m_poster->width() ? m_poster->width() : r.width();
        int posterHeight = posterWidth / originalRatio;
        int posterX = ((r.width() - posterWidth) / 2) + r.x();
        int posterY = ((r.height() - posterHeight) / 2) + r.y();
        IntRect targetRect(posterX, posterY, posterWidth, posterHeight);
        ctxt->platformContext()->drawBitmapRect(*m_poster, 0, targetRect);
    }

    void onPosterFetched(SkBitmap* poster)
    {
        m_poster = poster;
        if (m_naturalSizeUnknown) {
            // We had to fake the size at startup, or else our paint
            // method would not be called. If we haven't yet received
            // the onPrepared event, update the intrinsic size to the size
            // of the poster. That will be overriden when onPrepare comes.
            // In case of an error, we should report the poster size, rather
            // than our initial fake value.
            m_naturalSize = IntSize(poster->width(), poster->height());
            m_player->sizeChanged();
        }
        // At this time, we know that the proxy has been setup. And it is the
        // right time to trigger autoplay through the HTMLMediaElement state
        // change. Since we are using the java MediaPlayer, so we have to
        // pretend that the MediaPlayer has enough data.
        m_readyState = MediaPlayer::HaveEnoughData;
        m_player->readyStateChanged();

    }

    void onPrepared(int duration, int width, int height)
    {
        m_duration = duration / 1000.0f;
        m_naturalSize = IntSize(width, height);
        m_naturalSizeUnknown = false;
        m_player->durationChanged();
        m_player->sizeChanged();
        TilesManager::instance()->videoLayerManager()->updateVideoLayerSize(
            m_player->platformLayer()->uniqueId(), width * height,
            width / (float)height);
    }

    virtual bool hasAudio() const { return false; } // do not display the audio UI
    virtual bool hasVideo() const { return true; }
    virtual bool supportsFullscreen() const { return true; }

    MediaPlayerVideoPrivate(MediaPlayer* player) : MediaPlayerPrivate(player)
    {
        JNIEnv* env = JSC::Bindings::getJNIEnv();
        if (!env)
            return;

        jclass clazz = env->FindClass(g_ProxyJavaClass);

        if (!clazz)
            return;

        m_glue = new JavaGlue;
        m_glue->m_getInstance =
            env->GetStaticMethodID(clazz, "getInstance",
                                   "(Landroid/webkit/WebViewCore;I)Landroid/webkit/HTML5VideoViewProxy;");
        m_glue->m_loadPoster = env->GetMethodID(clazz, "loadPoster", "(Ljava/lang/String;)V");
        m_glue->m_play = env->GetMethodID(clazz, "play", "(Ljava/lang/String;II)V");
        m_glue->m_enterFullscreenForVideoLayer =
            env->GetMethodID(clazz, "enterFullscreenForVideoLayer", "(Ljava/lang/String;I)V");

        m_glue->m_teardown = env->GetMethodID(clazz, "teardown", "()V");
        m_glue->m_seek = env->GetMethodID(clazz, "seek", "(I)V");
        m_glue->m_pause = env->GetMethodID(clazz, "pause", "()V");
        m_glue->m_javaProxy = 0;
        env->DeleteLocalRef(clazz);
        // An exception is raised if any of the above fails.
        checkException(env);
    }

    void createJavaPlayerIfNeeded()
    {
        // Check if we have been already created.
        if (m_glue->m_javaProxy)
            return;

        JNIEnv* env = JSC::Bindings::getJNIEnv();
        if (!env)
            return;

        jclass clazz = env->FindClass(g_ProxyJavaClass);

        if (!clazz)
            return;

        jobject obj = 0;

        FrameView* frameView = m_player->frameView();
        if (!frameView)
            return;
        AutoJObject javaObject = WebViewCore::getWebViewCore(frameView)->getJavaObject();
        if (!javaObject.get())
            return;

        // Get the HTML5VideoViewProxy instance
        obj = env->CallStaticObjectMethod(clazz, m_glue->m_getInstance, javaObject.get(), this);
        m_glue->m_javaProxy = env->NewGlobalRef(obj);
        // Send the poster
        jstring jUrl = 0;
        if (m_posterUrl.length())
            jUrl = wtfStringToJstring(env, m_posterUrl);
        // Sending a NULL jUrl allows the Java side to try to load the default poster.
        env->CallVoidMethod(m_glue->m_javaProxy, m_glue->m_loadPoster, jUrl);
        if (jUrl)
            env->DeleteLocalRef(jUrl);

        // Clean up.
        env->DeleteLocalRef(obj);
        env->DeleteLocalRef(clazz);
        checkException(env);
    }

    float maxTimeSeekable() const
    {
        return m_duration;
    }
};

class MediaPlayerAudioPrivate : public MediaPlayerPrivate {
public:
    void load(const String& url)
    {
        m_url = url;
        JNIEnv* env = JSC::Bindings::getJNIEnv();
        if (!env || !m_url.length())
            return;

        createJavaPlayerIfNeeded();

        if (!m_glue->m_javaProxy)
            return;

        jstring jUrl = wtfStringToJstring(env, m_url);
        // start loading the data asynchronously
        env->CallVoidMethod(m_glue->m_javaProxy, m_glue->m_setDataSource, jUrl);
        env->DeleteLocalRef(jUrl);
        checkException(env);
    }

    void play()
    {
        JNIEnv* env = JSC::Bindings::getJNIEnv();
        if (!env || !m_url.length())
            return;

        createJavaPlayerIfNeeded();

        if (!m_glue->m_javaProxy)
            return;

        m_paused = false;
        m_player->playbackStateChanged();
        env->CallVoidMethod(m_glue->m_javaProxy, m_glue->m_play);
        checkException(env);
    }

    virtual bool hasAudio() const { return true; }
    virtual bool hasVideo() const { return false; }
    virtual bool supportsFullscreen() const { return false; }

    float maxTimeSeekable() const
    {
        if (m_glue->m_javaProxy) {
            JNIEnv* env = JSC::Bindings::getJNIEnv();
            if (env) {
                float maxTime = env->CallFloatMethod(m_glue->m_javaProxy,
                                                     m_glue->m_getMaxTimeSeekable);
                checkException(env);
                return maxTime;
            }
        }
        return 0;
    }

    MediaPlayerAudioPrivate(MediaPlayer* player) : MediaPlayerPrivate(player)
    {
        JNIEnv* env = JSC::Bindings::getJNIEnv();
        if (!env)
            return;

        jclass clazz = env->FindClass(g_ProxyJavaClassAudio);

        if (!clazz)
            return;

        m_glue = new JavaGlue;
        m_glue->m_newInstance = env->GetMethodID(clazz, "<init>", "(Landroid/webkit/WebViewCore;I)V");
        m_glue->m_setDataSource = env->GetMethodID(clazz, "setDataSource", "(Ljava/lang/String;)V");
        m_glue->m_play = env->GetMethodID(clazz, "play", "()V");
        m_glue->m_getMaxTimeSeekable = env->GetMethodID(clazz, "getMaxTimeSeekable", "()F");
        m_glue->m_teardown = env->GetMethodID(clazz, "teardown", "()V");
        m_glue->m_seek = env->GetMethodID(clazz, "seek", "(I)V");
        m_glue->m_pause = env->GetMethodID(clazz, "pause", "()V");
        m_glue->m_javaProxy = 0;
        env->DeleteLocalRef(clazz);
        // An exception is raised if any of the above fails.
        checkException(env);
    }

    void createJavaPlayerIfNeeded()
    {
        // Check if we have been already created.
        if (m_glue->m_javaProxy)
            return;

        JNIEnv* env = JSC::Bindings::getJNIEnv();
        if (!env)
            return;

        jclass clazz = env->FindClass(g_ProxyJavaClassAudio);

        if (!clazz)
            return;

        FrameView* frameView = m_player->mediaPlayerClient()->mediaPlayerOwningDocument()->view();
        if (!frameView)
            return;
        AutoJObject javaObject = WebViewCore::getWebViewCore(frameView)->getJavaObject();
        if (!javaObject.get())
            return;

        jobject obj = 0;

        // Get the HTML5Audio instance
        obj = env->NewObject(clazz, m_glue->m_newInstance, javaObject.get(), this);
        m_glue->m_javaProxy = env->NewGlobalRef(obj);

        // Clean up.
        if (obj)
            env->DeleteLocalRef(obj);
        env->DeleteLocalRef(clazz);
        checkException(env);
    }

    void onPrepared(int duration, int width, int height)
    {
        // Android media player gives us a duration of 0 for a live
        // stream, so in that case set the real duration to infinity.
        // We'll still be able to handle the case that we genuinely
        // get an audio clip with a duration of 0s as we'll get the
        // ended event when it stops playing.
        if (duration > 0) {
            m_duration = duration / 1000.0f;
        } else {
            m_duration = std::numeric_limits<float>::infinity();
        }
        m_player->durationChanged();
        m_player->sizeChanged();
        m_player->prepareToPlay();
    }
};

MediaPlayerPrivateInterface* MediaPlayerPrivate::create(MediaPlayer* player)
{
    if (player->mediaElementType() == MediaPlayer::Video)
       return new MediaPlayerVideoPrivate(player);
    return new MediaPlayerAudioPrivate(player);
}

}

namespace android {

static void OnPrepared(JNIEnv* env, jobject obj, int duration, int width, int height, int pointer)
{
    if (pointer) {
        WebCore::MediaPlayerPrivate* player = reinterpret_cast<WebCore::MediaPlayerPrivate*>(pointer);
        player->onPrepared(duration, width, height);
    }
}

static void OnEnded(JNIEnv* env, jobject obj, int pointer)
{
    if (pointer) {
        WebCore::MediaPlayerPrivate* player = reinterpret_cast<WebCore::MediaPlayerPrivate*>(pointer);
        player->onEnded();
    }
}

static void OnRequestPlay(JNIEnv* env, jobject obj, int pointer)
{
    if (pointer) {
        WebCore::MediaPlayerPrivate* player = reinterpret_cast<WebCore::MediaPlayerPrivate*>(pointer);
        player->onRequestPlay();
    }
}

static void OnPaused(JNIEnv* env, jobject obj, int pointer)
{
    if (pointer) {
        WebCore::MediaPlayerPrivate* player = reinterpret_cast<WebCore::MediaPlayerPrivate*>(pointer);
        player->onPaused();
    }
}

static void OnPosterFetched(JNIEnv* env, jobject obj, jobject poster, int pointer)
{
    if (!pointer || !poster)
        return;

    WebCore::MediaPlayerPrivate* player = reinterpret_cast<WebCore::MediaPlayerPrivate*>(pointer);
    SkBitmap* posterNative = GraphicsJNI::getNativeBitmap(env, poster);
    if (!posterNative)
        return;
    player->onPosterFetched(posterNative);
}

static void OnBuffering(JNIEnv* env, jobject obj, int percent, int pointer)
{
    if (pointer) {
        WebCore::MediaPlayerPrivate* player = reinterpret_cast<WebCore::MediaPlayerPrivate*>(pointer);
        // TODO: player->onBuffering(percent);
    }
}

static void OnTimeupdate(JNIEnv* env, jobject obj, int position, int pointer)
{
    if (pointer) {
        WebCore::MediaPlayerPrivate* player = reinterpret_cast<WebCore::MediaPlayerPrivate*>(pointer);
        player->onTimeupdate(position);
    }
}

static void OnRestoreState(JNIEnv* env, jobject obj, int pointer)
{
    if (pointer) {
        WebCore::MediaPlayerPrivate* player = reinterpret_cast<WebCore::MediaPlayerPrivate*>(pointer);
        player->onRestoreState();
    }
}


// This is called on the UI thread only.
// The video layers are composited on the webkit thread and then copied over
// to the UI thread with the same ID. For rendering, we are only using the
// video layers on the UI thread. Therefore, on the UI thread, we have to use
// the videoLayerId from Java side to find the exact video layer in the tree
// to set the surface texture.
// Every time a play call into Java side, the videoLayerId will be sent and
// saved in Java side. Then every time setBaseLayer call, the saved
// videoLayerId will be passed to this function to find the Video Layer.
// Return value: true when the video layer is found.
static bool SendSurfaceTexture(JNIEnv* env, jobject obj, jobject surfTex,
                               int baseLayer, int videoLayerId,
                               int textureName, int playerState) {
    if (!surfTex)
        return false;

    sp<GLConsumer> texture = android::SurfaceTexture_getSurfaceTexture(env, surfTex);
    if (!texture.get())
        return false;

    BaseLayerAndroid* layerImpl = reinterpret_cast<BaseLayerAndroid*>(baseLayer);
    if (!layerImpl)
        return false;

    VideoLayerAndroid* videoLayer =
        static_cast<VideoLayerAndroid*>(layerImpl->findById(videoLayerId));
    if (!videoLayer)
        return false;

    // Set the GLConsumer to the layer we found
    videoLayer->setSurfaceTexture(texture, textureName, static_cast<PlayerState>(playerState));
    return true;
}

static void OnStopFullscreen(JNIEnv* env, jobject obj, int stillPlaying, int pointer)
{
    if (pointer) {
        WebCore::MediaPlayerPrivate* player =
            reinterpret_cast<WebCore::MediaPlayerPrivate*>(pointer);
        player->onStopFullscreen(stillPlaying);
    }
}

/*
 * JNI registration
 */
static JNINativeMethod g_MediaPlayerMethods[] = {
    { "nativeOnPrepared", "(IIII)V",
        (void*) OnPrepared },
    { "nativeOnEnded", "(I)V",
        (void*) OnEnded },
    { "nativeOnStopFullscreen", "(II)V",
        (void*) OnStopFullscreen },
    { "nativeOnPaused", "(I)V",
        (void*) OnPaused },
    { "nativeOnPosterFetched", "(Landroid/graphics/Bitmap;I)V",
        (void*) OnPosterFetched },
    { "nativeOnRestoreState", "(I)V",
        (void*) OnRestoreState },
    { "nativeSendSurfaceTexture", "(Landroid/graphics/SurfaceTexture;IIII)Z",
        (void*) SendSurfaceTexture },
    { "nativeOnTimeupdate", "(II)V",
        (void*) OnTimeupdate },
};

static JNINativeMethod g_MediaAudioPlayerMethods[] = {
    { "nativeOnBuffering", "(II)V",
        (void*) OnBuffering },
    { "nativeOnEnded", "(I)V",
        (void*) OnEnded },
    { "nativeOnPrepared", "(IIII)V",
        (void*) OnPrepared },
    { "nativeOnRequestPlay", "(I)V",
        (void*) OnRequestPlay },
    { "nativeOnTimeupdate", "(II)V",
        (void*) OnTimeupdate },
};

int registerMediaPlayerVideo(JNIEnv* env)
{
    return jniRegisterNativeMethods(env, g_ProxyJavaClass,
            g_MediaPlayerMethods, NELEM(g_MediaPlayerMethods));
}

int registerMediaPlayerAudio(JNIEnv* env)
{
    return jniRegisterNativeMethods(env, g_ProxyJavaClassAudio,
            g_MediaAudioPlayerMethods, NELEM(g_MediaAudioPlayerMethods));
}

}
#endif // VIDEO
