VideoPlugin.cpp revision b8947eee3405616e00b1e4b70ae8bb97ac0e1d17
11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/*
21cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2009, The Android Open Source Project
31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *
41cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Redistribution and use in source and binary forms, with or without
51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * modification, are permitted provided that the following conditions
61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * are met:
71cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *  * Redistributions of source code must retain the above copyright
80b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger *    notice, this list of conditions and the following disclaimer.
90b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger *  * Redistributions in binary form must reproduce the above copyright
100b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger *    notice, this list of conditions and the following disclaimer in the
110b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger *    documentation and/or other materials provided with the distribution.
120b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger *
130b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
140b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
150b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
160b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
170b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
180b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
190b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
200b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
210b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
220b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
230b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
240b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger */
250b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
260b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "VideoPlugin.h"
270b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "android_npapi.h"
280b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
290b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include <stdio.h>
300b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include <sys/time.h>
310b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include <time.h>
320b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include <math.h>
330b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include <string.h>
340b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
350b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerextern NPNetscapeFuncs*        browser;
360b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerextern ANPBitmapInterfaceV0    gBitmapI;
370b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerextern ANPCanvasInterfaceV0    gCanvasI;
380b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerextern ANPLogInterfaceV0       gLogI;
390b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerextern ANPPaintInterfaceV0     gPaintI;
400b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerextern ANPSurfaceInterfaceV0   gSurfaceI;
410b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerextern ANPTypefaceInterfaceV0  gTypefaceI;
420b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerextern ANPWindowInterfaceV0  gWindowI;
430b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
440b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger///////////////////////////////////////////////////////////////////////////////
450b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
460b15698a8c76bb8abc1b555c1d91892669b4118fDerek SollenbergerVideoPlugin::VideoPlugin(NPP inst) : SurfaceSubPlugin(inst) {
470b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
480b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    // initialize the drawing surface
490b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    m_surface = NULL;
500b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
510b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    //register for touch events
520b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    ANPEventFlags flags = kTouch_ANPEventFlag;
530b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    NPError err = browser->setvalue(inst, kAcceptEvents_ANPSetValue, &flags);
540b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    if (err != NPERR_NO_ERROR) {
550b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        gLogI.log(inst, kError_ANPLogType, "Error selecting input events.");
560b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    }
570b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger}
580b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
590b15698a8c76bb8abc1b555c1d91892669b4118fDerek SollenbergerVideoPlugin::~VideoPlugin() {
600b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    surfaceDestroyed();
610b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger}
620b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
630b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerbool VideoPlugin::supportsDrawingModel(ANPDrawingModel model) {
640b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    return (model == kSurface_ANPDrawingModel);
650b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger}
660b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
670b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerbool VideoPlugin::isFixedSurface() {
680b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    return true;
690b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger}
700b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
710b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid VideoPlugin::surfaceCreated(jobject surface) {
720b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    m_surface = surface;
730b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    drawPlugin();
740b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger}
750b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
760b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid VideoPlugin::surfaceChanged(int format, int width, int height) {
770b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    gLogI.log(inst(), kDebug_ANPLogType, "----%p SurfaceChanged Event: %d",
780b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger              inst(), format);
790b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    drawPlugin();
800b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger}
810b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
820b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid VideoPlugin::surfaceDestroyed() {
830b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    JNIEnv* env = NULL;
840b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    if (m_surface && gVM->GetEnv((void**) &env, JNI_VERSION_1_4) == JNI_OK) {
850b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        env->DeleteGlobalRef(m_surface);
860b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        m_surface = NULL;
870b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    }
880b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger}
890b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
900b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid VideoPlugin::drawPlugin() {
910b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
920b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    ANPBitmap bitmap;
930b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    JNIEnv* env = NULL;
940b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    if (!m_surface || gVM->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK ||
950b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        !gSurfaceI.lock(env, m_surface, &bitmap, NULL)) {
960b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger            gLogI.log(inst(), kError_ANPLogType, "----%p Unable to Lock Surface", inst());
970b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger            return;
980b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    }
990b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
1000b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    ANPCanvas* canvas = gCanvasI.newCanvas(&bitmap);
1010b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
1020b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    // get the plugin's dimensions according to the DOM
1030b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    PluginObject *obj = (PluginObject*) inst()->pdata;
1040b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    const int pW = obj->window->width;
1050b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    const int pH = obj->window->height;
1060b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
1070b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    // compare DOM dimensions to the plugin's surface dimensions
1080b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    if (pW != bitmap.width || pH != bitmap.height)
1090b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        gLogI.log(inst(), kError_ANPLogType,
1100b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger                  "----%p Invalid Surface Dimensions (%d,%d):(%d,%d)",
1110b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger                  inst(), pW, pH, bitmap.width, bitmap.height);
1120b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
1130b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    // set constants
1140b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    const int fontSize = 16;
1150b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    const int leftMargin = 10;
1160b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
1170b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    gCanvasI.drawColor(canvas, 0xFFCDCDCD);
1180b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
1190b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    ANPPaint* paint = gPaintI.newPaint();
1200b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    gPaintI.setFlags(paint, gPaintI.getFlags(paint) | kAntiAlias_ANPPaintFlag);
1210b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    gPaintI.setColor(paint, 0xFFFF0000);
1220b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    gPaintI.setTextSize(paint, fontSize);
1230b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
1240b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    ANPTypeface* tf = gTypefaceI.createFromName("serif", kItalic_ANPTypefaceStyle);
1250b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    gPaintI.setTypeface(paint, tf);
1260b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    gTypefaceI.unref(tf);
1270b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
1280b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    ANPFontMetrics fm;
1290b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    gPaintI.getFontMetrics(paint, &fm);
1300b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
1310b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    gPaintI.setColor(paint, 0xFF0000FF);
1320b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    const char c[] = "Touch anywhere on the plugin to begin video playback!";
1330b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    gCanvasI.drawText(canvas, c, sizeof(c)-1, leftMargin, -fm.fTop, paint);
1340b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
1350b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    // clean up variables and unlock the surface
1360b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    gPaintI.deletePaint(paint);
1370b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    gCanvasI.deleteCanvas(canvas);
1380b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    gSurfaceI.unlock(env, m_surface);
1390b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger}
1400b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
1410b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerint16 VideoPlugin::handleEvent(const ANPEvent* evt) {
1420b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    switch (evt->eventType) {
1430b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        case kDraw_ANPEventType:
1440b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger            gLogI.log(inst(), kError_ANPLogType, " ------ %p the plugin did not request draw events", inst());
1450b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger            break;
1460b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        case kTouch_ANPEventType:
1470b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger            if (kDown_ANPTouchAction == evt->data.touch.action) {
1480b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger                gLogI.log(inst(), kDebug_ANPLogType, " ------ %p requesting fullscreen mode", inst());
1490b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger                gWindowI.requestFullScreen(inst());
1500b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger            }
1510b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger            return 1;
1520b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        case kKey_ANPEventType:
1530b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger            gLogI.log(inst(), kError_ANPLogType, " ------ %p the plugin did not request key events", inst());
1540b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger            break;
155        default:
156            break;
157    }
158    return 0;   // unknown or unhandled event
159}
160