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