1 /*
   2  * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include "config.h"
  27 
  28 #include "GraphicsContext.h"
  29 #include <wtf/java/JavaEnv.h>
  30 #include "MediaPlayerPrivateJava.h"
  31 #include "NotImplemented.h"
  32 #include "PlatformContextJava.h"
  33 
  34 #include "Document.h"
  35 #include "Settings.h"
  36 
  37 #include <wtf/text/CString.h> // todo tav remove when building w/ pch
  38 
  39 #include "com_sun_webkit_graphics_WCMediaPlayer.h"
  40 #include "com_sun_webkit_graphics_GraphicsDecoder.h"
  41 
  42 
  43 namespace WebCore {
  44 
  45 
  46 ///////////////////////// log support
  47 
  48 #if defined(NDEBUG)
  49 
  50     #define LOG_TRACE0(szFormat)                    ((void)0)
  51     #define LOG_TRACE1(szFormat, p1)                ((void)0)
  52     #define LOG_TRACE2(szFormat, p1, p2)            ((void)0)
  53     #define LOG_TRACE3(szFormat, p1, p2, p3)        ((void)0)
  54     #define LOG_TRACE4(szFormat, p1, p2, p3, p4)    ((void)0)
  55 
  56     #define LOG_ERROR0(szFormat)                    ((void)0)
  57     #define LOG_ERROR1(szFormat, p1)                ((void)0)
  58 
  59     #define PLOG_TRACE0(szFormat)                    ((void)0)
  60     #define PLOG_TRACE1(szFormat, p1)                ((void)0)
  61     #define PLOG_TRACE2(szFormat, p1, p2)            ((void)0)
  62     #define PLOG_TRACE3(szFormat, p1, p2, p3)        ((void)0)
  63     #define PLOG_TRACE4(szFormat, p1, p2, p3, p4)    ((void)0)
  64 
  65     #define PLOG_ERROR0(szFormat)                    ((void)0)
  66     #define PLOG_ERROR1(szFormat, p1)                ((void)0)
  67 
  68 #else
  69 
  70     #include <stdio.h>
  71     #include "wtf/CurrentTime.h"
  72     #include "wtf/Threading.h"
  73 
  74     const char* networkStateStr(MediaPlayer::NetworkState networkState) {
  75         switch (networkState) {
  76         case MediaPlayer::Empty:
  77             return "Empty";
  78         case MediaPlayer::Idle:
  79             return "Idle";
  80         case MediaPlayer::Loading:
  81             return "Loading";
  82         case MediaPlayer::Loaded:
  83             return "Loaded";
  84         case MediaPlayer::FormatError:
  85             return "FormatError";
  86         case MediaPlayer::NetworkError:
  87             return "NetworkError";
  88         case MediaPlayer::DecodeError:
  89             return "DecodeError";
  90         }
  91         return "<unknown network state>";
  92     }
  93 
  94     const char* readyStateStr(MediaPlayer::ReadyState readyState) {
  95         switch (readyState) {
  96         case MediaPlayer::HaveNothing:
  97             return "HaveNothing";
  98         case MediaPlayer::HaveMetadata:
  99             return "HaveMetadata";
 100         case MediaPlayer::HaveCurrentData:
 101             return "HaveCurrentData";
 102         case MediaPlayer::HaveFutureData:
 103             return "HaveFutureData";
 104         case MediaPlayer::HaveEnoughData:
 105             return "HaveEnoughData";
 106         }
 107         return "<unknown ready state>";
 108     }
 109 
 110     namespace Logger {
 111 
 112         FILE* getLogStream() {
 113             FILE *stream = stderr;
 114             //FILE *stream = fopen("webVideo.log", "a");
 115             return stream;
 116         }
 117 
 118         void releaseLogStream(FILE *stream) {
 119             fflush(stream);
 120             //fclose(stream);
 121         }
 122 
 123         void AMLogf(const char* szLevel, const char* szFormat, ...) {
 124             FILE *stream = getLogStream();
 125             fprintf(stream, "[%s (native)] ", szLevel);
 126             va_list args;
 127             va_start(args, szFormat);
 128             vfprintf(stream, szFormat, args);
 129             releaseLogStream(stream);
 130         }
 131 
 132         void AMLogf_p(const MediaPlayerPrivate *p, const char* szLevel, const char* szFormat, ...) {
 133             FILE *stream = getLogStream();
 134             fprintf(stream, "[%s (native),states:(%s,%s), paused:%d, seeking:%d, pos:%f/%f]",
 135                 szLevel, networkStateStr(p->networkState()), readyStateStr(p->readyState()),
 136                 (p->paused() ? 1 : 0), (p->seeking() ? 1 : 0),
 137                 p->currentTime(), p->duration());
 138             va_list args;
 139             va_start(args, szFormat);
 140             vfprintf(stream, szFormat, args);
 141             releaseLogStream(stream);
 142         }
 143     }
 144 
 145     #define LOG_TRACE0(szFormat)                    Logger::AMLogf("INFO", szFormat)
 146     #define LOG_TRACE1(szFormat, p1)                Logger::AMLogf("INFO", szFormat, p1)
 147     #define LOG_TRACE2(szFormat, p1, p2)            Logger::AMLogf("INFO", szFormat, p1, p2)
 148     #define LOG_TRACE3(szFormat, p1, p2, p3)        Logger::AMLogf("INFO", szFormat, p1, p2, p3)
 149     #define LOG_TRACE4(szFormat, p1, p2, p3, p4)    Logger::AMLogf("INFO", szFormat, p1, p2, p3, p4)
 150 
 151     #define LOG_ERROR0(szFormat)                    Logger::AMLogf("SEVERE", szFormat)
 152     #define LOG_ERROR1(szFormat, p1)                Logger::AMLogf("SEVERE", szFormat, p1)
 153 
 154     #define PLOG_TRACE0(szFormat)                   Logger::AMLogf_p(this, "INFO", szFormat)
 155     #define PLOG_TRACE1(szFormat, p1)               Logger::AMLogf_p(this, "INFO", szFormat, p1)
 156     #define PLOG_TRACE2(szFormat, p1, p2)           Logger::AMLogf_p(this, "INFO", szFormat, p1, p2)
 157     #define PLOG_TRACE3(szFormat, p1, p2, p3)       Logger::AMLogf_p(this, "INFO", szFormat, p1, p2, p3)
 158     #define PLOG_TRACE4(szFormat, p1, p2, p3, p4)   Logger::AMLogf_p(this, "INFO", szFormat, p1, p2, p3, p4)
 159 
 160     #define PLOG_ERROR0(szFormat)                   Logger::AMLogf_p(this, "SEVERE", szFormat)
 161     #define PLOG_ERROR1(szFormat, p1)               Logger::AMLogf_p(this, "SEVERE", szFormat, p1)
 162 
 163 #endif
 164 
 165 ////////////////////////
 166 
 167 
 168 
 169 
 170 void MediaPlayerPrivate::registerMediaEngine(MediaEngineRegistrar registrar)
 171 {
 172     LOG_TRACE0(">>registerMediaEngine\n");
 173     JNIEnv* env = WebCore_GetJavaEnv();
 174     jclass playerCls = PG_GetMediaPlayerClass(env);
 175     if (!playerCls) {
 176         LOG_ERROR0("<<registerMediaEngine ERROR: MediaPlayer class is unavailable\n");
 177         return;
 178     }
 179     //CreateMediaEnginePlayer, MediaEngineSupportedTypes, MediaEngineSupportsType,
 180     //MediaEngineGetSitesInMediaCache, MediaEngineClearMediaCache, MediaEngineClearMediaCacheForSite
 181     registrar([] (MediaPlayer* player) { return std::unique_ptr<MediaPlayerPrivate>(new MediaPlayerPrivate(player)); },
 182         MediaEngineSupportedTypes, MediaEngineSupportsType, 0, 0, 0, 0);
 183 }
 184 
 185 void MediaPlayerPrivate::MediaEngineSupportedTypes(HashSet<String, ASCIICaseInsensitiveHash>& types)
 186 {
 187     LOG_TRACE0(">>MediaEngineSupportedTypes\n");
 188     HashSet<String, ASCIICaseInsensitiveHash>& supportedTypes = GetSupportedTypes();
 189     for (const auto& type : supportedTypes) {
 190         types.add(type);
 191     }
 192     LOG_TRACE0("<<MediaEngineSupportedTypes\n");
 193 }
 194 
 195 MediaPlayer::SupportsType MediaPlayerPrivate::MediaEngineSupportsType(const MediaEngineSupportParameters& parameters)
 196 {
 197     for (const auto& codecValue: parameters.type.codecs()) {
 198         UNUSED_PARAM(codecValue);
 199         LOG_TRACE2(">>MediaEngineSupportsType, type=%s, codecs=%s\n", parameters.type.raw().utf8().data(), codecValue.utf8().data());
 200     }
 201 
 202     if (parameters.type.isEmpty()) {
 203         LOG_TRACE0("<<MediaEngineSupportsType: NOT supported (type is empty)\n");
 204         return MediaPlayer::IsNotSupported;
 205     }
 206 
 207     if (GetSupportedTypes().contains(parameters.type.containerType())) {
 208         LOG_TRACE0("<<MediaEngineSupportsType: MayBeSupported/IsSupported\n");
 209         auto codecs = parameters.type.parameter(ContentType::codecsParameter());
 210         return codecs.isEmpty() ? MediaPlayer::MayBeSupported : MediaPlayer::IsSupported;
 211     }
 212     LOG_TRACE0("<<MediaEngineSupportsType: NOT supported\n");
 213     return MediaPlayer::IsNotSupported;
 214 }
 215 
 216 HashSet<String, ASCIICaseInsensitiveHash>& MediaPlayerPrivate::GetSupportedTypes()
 217 {
 218     static HashSet<String, ASCIICaseInsensitiveHash> supportedTypes;
 219     // TODO: refresh after change
 220 
 221     if (!supportedTypes.isEmpty()) {
 222         return supportedTypes;
 223     }
 224 
 225     JNIEnv* env = WebCore_GetJavaEnv();
 226     static jmethodID s_mID = env->GetMethodID(PG_GetGraphicsManagerClass(env),
 227         "getSupportedMediaTypes", "()[Ljava/lang/String;");
 228     ASSERT(s_mID);
 229 
 230     JLocalRef<jobjectArray> jArray(
 231         (jobjectArray)env->CallObjectMethod(PL_GetGraphicsManager(env), s_mID));
 232     ASSERT(jArray);
 233     CheckAndClearException(env);
 234 
 235     jsize len = env->GetArrayLength(jArray);
 236     for (jsize  i=0; i<len; i++) {
 237         JLString jStr((jstring)env->GetObjectArrayElement(jArray, i));
 238         String s(env, jStr);
 239         supportedTypes.add(s);
 240     }
 241 
 242     return supportedTypes;
 243 }
 244 
 245 
 246 // *********************************************************
 247 // MediaPlayerPrivate
 248 // *********************************************************
 249 MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer *player)
 250     : m_player(player)
 251     , m_networkState(MediaPlayer::Empty)
 252     , m_readyState(MediaPlayer::HaveNothing)
 253     , m_isVisible(false)
 254     , m_hasVideo(false)
 255     , m_hasAudio(false)
 256     , m_paused(true)
 257     , m_seeking(false)
 258     , m_seekTime(0)
 259     , m_duration(0)
 260     , m_bytesLoaded(0)
 261     , m_didLoadingProgress(false)
 262 {
 263     JNIEnv* env = WebCore_GetJavaEnv();
 264     static jmethodID mid = env->GetMethodID(PG_GetGraphicsManagerClass(env),
 265         "fwkCreateMediaPlayer", "(J)Lcom/sun/webkit/graphics/WCMediaPlayer;");
 266     ASSERT(mid);
 267 
 268     JLocalRef<jobject> obj(env->CallObjectMethod(PL_GetGraphicsManager(env),
 269         mid, ptr_to_jlong(this)));
 270     ASSERT(obj);
 271     CheckAndClearException(env);
 272 
 273     m_buffered = std::make_unique<PlatformTimeRanges>();
 274     m_jPlayer = RQRef::create(obj);
 275 }
 276 
 277 MediaPlayerPrivate::~MediaPlayerPrivate()
 278 {
 279     WC_GETJAVAENV_CHKRET(env);
 280     static jmethodID s_mID
 281         = env->GetMethodID(PG_GetMediaPlayerClass(env), "fwkDispose", "()V");
 282     ASSERT(s_mID);
 283 
 284     env->CallVoidMethod(*m_jPlayer, s_mID);
 285     CheckAndClearException(env);
 286 }
 287 
 288 void MediaPlayerPrivate::load(const String& url)
 289 {
 290     if (m_networkState == MediaPlayer::Loading) {
 291         cancelLoad();
 292     }
 293 
 294     String userAgent;
 295     // MediaPlayerClient mpClient = m_player->client();
 296     // Document* doc = mpClient.mediaPlayerOwningDocument(); //XXX: mediaPlayerOwningDocument removed
 297     // if (doc != NULL && doc->settings() != NULL) {
 298     //     userAgent = doc->settings()->userAgent();
 299     // }
 300 
 301     JNIEnv* env = WebCore_GetJavaEnv();
 302     static jmethodID s_mID
 303         = env->GetMethodID(PG_GetMediaPlayerClass(env), "fwkLoad", "(Ljava/lang/String;Ljava/lang/String;)V");
 304     ASSERT(s_mID);
 305 
 306     env->CallVoidMethod(*m_jPlayer, s_mID,
 307         (jstring)url.toJavaString(env),
 308         userAgent.isEmpty() ? NULL : (jstring)userAgent.toJavaString(env));
 309     CheckAndClearException(env);
 310 }
 311 
 312 void MediaPlayerPrivate::cancelLoad()
 313 {
 314     m_paused = true;
 315     m_seeking = false;
 316 
 317     JNIEnv* env = WebCore_GetJavaEnv();
 318     static jmethodID s_mID
 319         = env->GetMethodID(PG_GetMediaPlayerClass(env), "fwkCancelLoad", "()V");
 320     ASSERT(s_mID);
 321 
 322     env->CallVoidMethod(*m_jPlayer, s_mID);
 323     CheckAndClearException(env);
 324 }
 325 
 326 void MediaPlayerPrivate::prepareToPlay()
 327 {
 328     JNIEnv* env = WebCore_GetJavaEnv();
 329     static jmethodID s_mID
 330         = env->GetMethodID(PG_GetMediaPlayerClass(env), "fwkPrepareToPlay", "()V");
 331     ASSERT(s_mID);
 332 
 333     env->CallVoidMethod(*m_jPlayer, s_mID);
 334     CheckAndClearException(env);
 335 }
 336 
 337 //PlatformMedia MediaPlayerPrivate::platformMedia() const { return NoPlatformMedia; }
 338 
 339 //#if USE(ACCELERATED_COMPOSITING)
 340 //        PlatformLayer* MediaPlayerPrivate::platformLayer() const { return 0; }
 341 //#endif
 342 
 343 void MediaPlayerPrivate::play()
 344 {
 345     PLOG_TRACE0(">>MediaPlayerPrivate::play\n");
 346 
 347     if (!paused()) {
 348         PLOG_TRACE0("<<MediaPlayerPrivate::play - already playing\n");
 349         return;
 350     }
 351 
 352     JNIEnv* env = WebCore_GetJavaEnv();
 353     static jmethodID s_mID
 354         = env->GetMethodID(PG_GetMediaPlayerClass(env), "fwkPlay", "()V");
 355     ASSERT(s_mID);
 356 
 357     env->CallVoidMethod(*m_jPlayer, s_mID);
 358     CheckAndClearException(env);
 359 
 360     PLOG_TRACE0("<<MediaPlayerPrivate::play\n");
 361 }
 362 
 363 void MediaPlayerPrivate::pause()
 364 {
 365     if (paused()) {
 366         return;
 367     }
 368 
 369     JNIEnv* env = WebCore_GetJavaEnv();
 370     static jmethodID s_mID
 371         = env->GetMethodID(PG_GetMediaPlayerClass(env), "fwkPause", "()V");
 372     ASSERT(s_mID);
 373 
 374     env->CallVoidMethod(*m_jPlayer, s_mID);
 375     CheckAndClearException(env);
 376 }
 377 
 378 //bool MediaPlayerPrivate::supportsFullscreen() const { return false; }
 379 //bool MediaPlayerPrivate::supportsSave() const { return false; }
 380 
 381 FloatSize MediaPlayerPrivate::naturalSize() const
 382 {
 383 //    PLOG_TRACE2("MediaPlayerPrivate naturalSize - return %d x %d\n", m_naturalSize.width(), m_naturalSize.height());
 384     return m_naturalSize;
 385 }
 386 
 387 bool MediaPlayerPrivate::hasVideo() const
 388 {
 389 //    PLOG_TRACE1("MediaPlayerPrivate hasVideo - return %d\n", m_hasVideo ? 1 : 0);
 390     return m_hasVideo;
 391 }
 392 
 393 bool MediaPlayerPrivate::hasAudio() const
 394 {
 395 //    PLOG_TRACE1("MediaPlayerPrivate hasAudio - return %d\n", m_hasAudio ? 1 : 0);
 396     return m_hasAudio;
 397 }
 398 
 399 void MediaPlayerPrivate::setVisible(bool visible)
 400 {
 401     if (m_isVisible != visible) {
 402         PLOG_TRACE2("MediaPlayerPrivate setVisible: %d => %d\n", m_isVisible ? 1 : 0, visible ? 1 : 0);
 403         m_isVisible = visible;
 404     }
 405 }
 406 
 407 float MediaPlayerPrivate::duration() const
 408 {
 409     // return numeric_limits<float>::infinity(); // "live" stream
 410     return m_duration;
 411 }
 412 
 413 float MediaPlayerPrivate::currentTime() const
 414 {
 415     if (m_seeking) {
 416         LOG_TRACE1("MediaPlayerPrivate currentTime returns (seekTime): %f\n", m_seekTime);
 417         return m_seekTime;
 418     }
 419     JNIEnv* env = WebCore_GetJavaEnv();
 420     static jmethodID s_mID
 421         = env->GetMethodID(PG_GetMediaPlayerClass(env), "fwkGetCurrentTime", "()F");
 422     ASSERT(s_mID);
 423 
 424     double result = env->CallFloatMethod(*m_jPlayer, s_mID);
 425     CheckAndClearException(env);
 426 
 427 //    LOG_TRACE1("MediaPlayerPrivate currentTime returns: %f\n", (float)result);
 428 
 429     return (float)result;
 430 }
 431 
 432 void MediaPlayerPrivate::seek(float time)
 433 {
 434     PLOG_TRACE1(">>MediaPlayerPrivate::seek(%f)\n", time);
 435 
 436     m_seekTime = time;
 437 
 438     JNIEnv* env = WebCore_GetJavaEnv();
 439     static jmethodID s_mID
 440         = env->GetMethodID(PG_GetMediaPlayerClass(env), "fwkSeek", "(F)V");
 441     ASSERT(s_mID);
 442 
 443     env->CallVoidMethod(*m_jPlayer, s_mID, time);
 444     CheckAndClearException(env);
 445 
 446     PLOG_TRACE1("<<MediaPlayerPrivate::seek(%f)\n", time);
 447 }
 448 
 449 bool MediaPlayerPrivate::seeking() const
 450 {
 451     return m_seeking;
 452 }
 453 
 454 MediaTime MediaPlayerPrivate::startTime() const
 455 {
 456     // always 0
 457     return MediaTime::zeroTime();
 458 }
 459 
 460 void MediaPlayerPrivate::setRate(float rate)
 461 {
 462     JNIEnv* env = WebCore_GetJavaEnv();
 463     static jmethodID s_mID
 464         = env->GetMethodID(PG_GetMediaPlayerClass(env), "fwkSetRate", "(F)V");
 465     ASSERT(s_mID);
 466 
 467     env->CallVoidMethod(*m_jPlayer, s_mID, rate);
 468     CheckAndClearException(env);
 469 }
 470 
 471 void MediaPlayerPrivate::setPreservesPitch(bool preserve)
 472 {
 473     JNIEnv* env = WebCore_GetJavaEnv();
 474     static jmethodID s_mID
 475         = env->GetMethodID(PG_GetMediaPlayerClass(env), "fwkSetPreservesPitch", "(Z)V");
 476     ASSERT(s_mID);
 477 
 478     env->CallVoidMethod(*m_jPlayer, s_mID, bool_to_jbool(preserve));
 479     CheckAndClearException(env);
 480 }
 481 
 482 bool MediaPlayerPrivate::paused() const
 483 {
 484     return m_paused;
 485 }
 486 
 487 void MediaPlayerPrivate::setVolume(float volume)
 488 {
 489     JNIEnv* env = WebCore_GetJavaEnv();
 490     static jmethodID s_mID
 491         = env->GetMethodID(PG_GetMediaPlayerClass(env), "fwkSetVolume", "(F)V");
 492     ASSERT(s_mID);
 493 
 494     env->CallVoidMethod(*m_jPlayer, s_mID, volume);
 495     CheckAndClearException(env);
 496 }
 497 
 498 bool MediaPlayerPrivate::supportsMuting() const
 499 {
 500     return true;
 501 }
 502 
 503 void MediaPlayerPrivate::setMuted(bool mute)
 504 {
 505     JNIEnv* env = WebCore_GetJavaEnv();
 506     static jmethodID
 507         s_mID = env->GetMethodID(PG_GetMediaPlayerClass(env), "fwkSetMute", "(Z)V");
 508     ASSERT(s_mID);
 509 
 510     env->CallVoidMethod(*m_jPlayer, s_mID, bool_to_jbool(mute));
 511     CheckAndClearException(env);
 512 }
 513 
 514 //bool MediaPlayerPrivate::hasClosedCaptions() const { return false; }
 515 //void MediaPlayerPrivate::setClosedCaptionsVisible(bool) { }
 516 
 517 MediaPlayer::NetworkState MediaPlayerPrivate::networkState() const
 518 {
 519 //    LOG_TRACE1("MediaPlayerPrivate networkState - return %d\n", (int)m_networkState);
 520     return m_networkState;
 521 }
 522 
 523 MediaPlayer::ReadyState MediaPlayerPrivate::readyState() const
 524 {
 525 //    LOG_TRACE1("MediaPlayerPrivate readyState - return %d\n", (int)m_readyState);
 526     return m_readyState;
 527 }
 528 
 529 float MediaPlayerPrivate::maxTimeSeekable() const
 530 {
 531     return m_duration;
 532 }
 533 
 534 bool MediaPlayerPrivate::didLoadingProgress() const
 535 {
 536     bool didLoadingProgress = m_didLoadingProgress;
 537     m_didLoadingProgress = false;
 538     PLOG_TRACE1("MediaPlayerPrivate didLoadingProgress - returning %d", didLoadingProgress ? 1 : 0);
 539     return didLoadingProgress;
 540 }
 541 
 542 std::unique_ptr<PlatformTimeRanges> MediaPlayerPrivate::buffered() const
 543 {
 544     return std::make_unique<PlatformTimeRanges>(); //XXX recheck; USE m_buffered
 545 }
 546 
 547 unsigned MediaPlayerPrivate::bytesLoaded() const
 548 {
 549     return m_bytesLoaded;
 550 }
 551 
 552 void MediaPlayerPrivate::setSize(const IntSize& size)
 553 {
 554     JNIEnv* env = WebCore_GetJavaEnv();
 555     static jmethodID s_mID
 556         = env->GetMethodID(PG_GetMediaPlayerClass(env), "fwkSetSize", "(II)V");
 557     ASSERT(s_mID);
 558 
 559     env->CallVoidMethod(*m_jPlayer, s_mID, (jint)size.width(), (jint)size.height());
 560     CheckAndClearException(env);
 561 }
 562 
 563 void MediaPlayerPrivate::paint(GraphicsContext& gc, const FloatRect& r)
 564 {
 565 //    PLOG_TRACE4(">>MediaPlayerPrivate paint (%d, %d), [%d x %d]\n", r.x(), r.y(), r.width(), r.height());
 566     if (gc.paintingDisabled()) {
 567         PLOG_TRACE0("<<MediaPlayerPrivate paint (!gc or paintingDisabled)\n");
 568         return;
 569     }
 570     if (!m_isVisible) {
 571         PLOG_TRACE0("<<MediaPlayerPrivate paint (!visible)\n");
 572         return;
 573     }
 574 
 575     gc.platformContext()->rq().freeSpace(24)
 576     << (jint)com_sun_webkit_graphics_GraphicsDecoder_RENDERMEDIAPLAYER
 577     << m_jPlayer << (jint)r.x() <<  (jint)r.y()
 578     << (jint)r.width() << (jint)r.height();
 579 
 580 //    PLOG_TRACE0("<<MediaPlayerPrivate paint (OK)\n");
 581 }
 582 
 583 //void MediaPlayerPrivate::paintCurrentFrameInContext(GraphicsContext* c, const IntRect& r) { paint(c, r); }
 584 
 585 void MediaPlayerPrivate::setPreload(MediaPlayer::Preload preload)
 586 {
 587     // enum Preload { None, MetaData, Auto };
 588     PLOG_TRACE1("MediaPlayerPrivate setPreload, preload=%u\n", (int)preload);
 589     jint jPreload =
 590         (preload == MediaPlayer::None) ? com_sun_webkit_graphics_WCMediaPlayer_PRELOAD_NONE
 591         : (preload == MediaPlayer::MetaData) ? com_sun_webkit_graphics_WCMediaPlayer_PRELOAD_METADATA
 592         : (preload == MediaPlayer::Auto) ? com_sun_webkit_graphics_WCMediaPlayer_PRELOAD_AUTO
 593         : -1;
 594     if (jPreload < 0) {
 595         // unexpected preload value
 596         return;
 597     }
 598     JNIEnv* env = WebCore_GetJavaEnv();
 599     static jmethodID s_mID
 600         = env->GetMethodID(PG_GetMediaPlayerClass(env), "fwkSetPreload", "(I)V");
 601     ASSERT(s_mID);
 602 
 603     env->CallVoidMethod(*m_jPlayer, s_mID, jPreload);
 604     CheckAndClearException(env);
 605 }
 606 
 607 //bool MediaPlayerPrivate::hasAvailableVideoFrame() const { return readyState() >= MediaPlayer::HaveCurrentData; }
 608 
 609 //bool MediaPlayerPrivate::canLoadPoster() const { return false; }
 610 //void MediaPlayerPrivate::setPoster(const String&) { }
 611 
 612 //#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
 613 //        virtual void deliverNotification(MediaPlayerProxyNotificationType) = 0;
 614 //        virtual void setMediaPlayerProxy(WebMediaPlayerProxy*) = 0;
 615 //#endif
 616 
 617 //#if USE(ACCELERATED_COMPOSITING)
 618 //        // whether accelerated rendering is supported by the media engine for the current media.
 619 //        virtual bool supportsAcceleratedRendering() const { return false; }
 620 //        // called when the rendering system flips the into or out of accelerated rendering mode.
 621 //        virtual void acceleratedRenderingStateChanged() { }
 622 //#endif
 623 
 624 //bool MediaPlayerPrivate::hasSingleSecurityOrigin() const { return false; }
 625 
 626 //MediaPlayer::MovieLoadType MediaPlayerPrivate::movieLoadType() const { return MediaPlayer::Unknown; }
 627 
 628 void MediaPlayerPrivate::setNetworkState(MediaPlayer::NetworkState networkState)
 629 {
 630     if (m_networkState != networkState) {
 631         PLOG_TRACE4("MediaPlayerPrivate NetworkState: %s (%d) => %s (%d)\n",
 632             networkStateStr(m_networkState), (int)m_networkState, networkStateStr(networkState), (int)networkState);
 633         m_networkState = networkState;
 634         m_player->networkStateChanged();
 635     }
 636 }
 637 
 638 void MediaPlayerPrivate::setReadyState(MediaPlayer::ReadyState readyState)
 639 {
 640     if (m_readyState != readyState) {
 641         PLOG_TRACE4("MediaPlayerPrivate ReadyState: %s (%d) => %s (%d)\n",
 642             readyStateStr(m_readyState), (int)m_readyState, readyStateStr(readyState), (int)readyState);
 643         m_readyState = readyState;
 644         m_player->readyStateChanged();
 645     }
 646 }
 647 
 648 
 649 MediaPlayerPrivate* MediaPlayerPrivate::getPlayer(jlong ptr)
 650 {
 651     return reinterpret_cast<MediaPlayerPrivate *>(jlong_to_ptr(ptr));
 652 }
 653 
 654 void MediaPlayerPrivate::notifyNetworkStateChanged(int networkState)
 655 {
 656     switch (networkState) {
 657     case com_sun_webkit_graphics_WCMediaPlayer_NETWORK_STATE_EMPTY:
 658         setNetworkState(MediaPlayer::Empty);
 659         break;
 660     case com_sun_webkit_graphics_WCMediaPlayer_NETWORK_STATE_IDLE:
 661         setNetworkState(MediaPlayer::Idle);
 662         break;
 663     case com_sun_webkit_graphics_WCMediaPlayer_NETWORK_STATE_LOADING:
 664         setNetworkState(MediaPlayer::Loading);
 665         break;
 666     case com_sun_webkit_graphics_WCMediaPlayer_NETWORK_STATE_LOADED:
 667         setNetworkState(MediaPlayer::Loaded);
 668         break;
 669     case com_sun_webkit_graphics_WCMediaPlayer_NETWORK_STATE_FORMAT_ERROR:
 670         setNetworkState(MediaPlayer::FormatError);
 671         break;
 672     case com_sun_webkit_graphics_WCMediaPlayer_NETWORK_STATE_NETWORK_ERROR:
 673         setNetworkState(MediaPlayer::NetworkError);
 674         break;
 675     case com_sun_webkit_graphics_WCMediaPlayer_NETWORK_STATE_DECODE_ERROR:
 676         setNetworkState(MediaPlayer::DecodeError);
 677         break;
 678     }
 679 }
 680 
 681 void MediaPlayerPrivate::notifyReadyStateChanged(int readyState)
 682 {
 683     switch (readyState) {
 684     case com_sun_webkit_graphics_WCMediaPlayer_READY_STATE_HAVE_NOTHING:
 685         setReadyState(MediaPlayer::HaveNothing);
 686         break;
 687     case com_sun_webkit_graphics_WCMediaPlayer_READY_STATE_HAVE_METADATA:
 688         setReadyState(MediaPlayer::HaveMetadata);
 689         break;
 690     case com_sun_webkit_graphics_WCMediaPlayer_READY_STATE_HAVE_CURRENT_DATA:
 691         setReadyState(MediaPlayer::HaveCurrentData);
 692         break;
 693     case com_sun_webkit_graphics_WCMediaPlayer_READY_STATE_HAVE_FUTURE_DATA:
 694         setReadyState(MediaPlayer::HaveFutureData);
 695         break;
 696     case com_sun_webkit_graphics_WCMediaPlayer_READY_STATE_HAVE_ENOUGH_DATA:
 697         setReadyState(MediaPlayer::HaveEnoughData);
 698         break;
 699     }
 700 }
 701 
 702 void MediaPlayerPrivate::notifyPaused(bool paused)
 703 {
 704     PLOG_TRACE2(">>MediaPlayerPrivate notifyPaused: %d => %d\n", m_paused ? 1 : 0, paused ? 1 : 0);
 705 
 706     if (m_paused != paused) {
 707         m_paused = paused;
 708         m_player->playbackStateChanged();
 709     }
 710 }
 711 
 712 void MediaPlayerPrivate::notifySeeking(bool seeking)
 713 {
 714     PLOG_TRACE2(">>MediaPlayerPrivate notifySeeking: %d => %d\n", m_seeking ? 1 : 0, seeking ? 1 : 0);
 715     if (m_seeking != seeking) {
 716         m_seeking = seeking;
 717         if (!seeking) {
 718             // notify time change after seek completed
 719             //LOG_TRACE0("==MediaPlayerPrivate notifySeeking: NOTIFYING time changed\n");
 720             m_player->timeChanged();
 721         }
 722     }
 723 }
 724 
 725 void MediaPlayerPrivate::notifyFinished() {
 726     PLOG_TRACE0(">>MediaPlayerPrivate notifyFinished\n");
 727     m_player->timeChanged();
 728 }
 729 
 730 void MediaPlayerPrivate::notifyReady(bool hasVideo, bool hasAudio)
 731 {
 732     PLOG_TRACE2(">>MediaPlayerPrivate notifyReady: hasVideo=%d, hasAudio=%d\n", hasVideo ? 1 : 0, hasAudio ? 1 : 0);
 733     m_hasVideo = hasVideo;
 734     m_hasAudio = hasAudio;
 735     PLOG_TRACE0("<<MediaPlayerPrivate notifyReady\n");
 736 }
 737 
 738 void MediaPlayerPrivate::notifyDurationChanged(float duration)
 739 {
 740     PLOG_TRACE2(">>MediaPlayerPrivate notifyDurationChanged, %f => %f\n",
 741         m_duration, duration);
 742     m_duration = duration;
 743     m_player->durationChanged();
 744 }
 745 
 746 void MediaPlayerPrivate::notifySizeChanged(int width, int height)
 747 {
 748     PLOG_TRACE2("MediaPlayerPrivate notifySizeChanged: %d x %d\n", width, height);
 749     m_naturalSize = FloatSize(width, height); //XXX leave it as IntSize?
 750 }
 751 
 752 void MediaPlayerPrivate::notifyNewFrame()
 753 {
 754     PLOG_TRACE0(">>MediaPlayerPrivate notifyNewFrame\n");
 755     m_player->repaint();
 756     //PLOG_TRACE0("<<MediaPlayerPrivate notifyNewFrame\n");
 757 }
 758 
 759 void MediaPlayerPrivate::notifyBufferChanged(std::unique_ptr<PlatformTimeRanges> timeRanges, int bytesLoaded)
 760 {
 761     PLOG_TRACE0("MediaPlayerPrivate notifyBufferChanged\n");
 762     m_buffered = std::move(timeRanges);
 763     m_bytesLoaded = bytesLoaded;
 764     m_didLoadingProgress = true;
 765 }
 766 
 767 
 768 // *********************************************************
 769 // JNI functions
 770 // *********************************************************
 771 extern "C" {
 772 JNIEXPORT void JNICALL Java_com_sun_webkit_graphics_WCMediaPlayer_notifyNetworkStateChanged
 773     (JNIEnv*, jobject, jlong ptr, jint networkState)
 774 {
 775     MediaPlayerPrivate* player = MediaPlayerPrivate::getPlayer(ptr);
 776     player->notifyNetworkStateChanged(networkState);
 777 }
 778 
 779 JNIEXPORT void JNICALL Java_com_sun_webkit_graphics_WCMediaPlayer_notifyReadyStateChanged
 780     (JNIEnv*, jobject, jlong ptr, jint readyState)
 781 {
 782     MediaPlayerPrivate* player = MediaPlayerPrivate::getPlayer(ptr);
 783     player->notifyReadyStateChanged(readyState);
 784 }
 785 
 786 JNIEXPORT void JNICALL Java_com_sun_webkit_graphics_WCMediaPlayer_notifyPaused
 787     (JNIEnv*, jobject, jlong ptr, jboolean paused)
 788 {
 789     MediaPlayerPrivate* player = MediaPlayerPrivate::getPlayer(ptr);
 790     player->notifyPaused(jbool_to_bool(paused));
 791 }
 792 
 793 JNIEXPORT void JNICALL Java_com_sun_webkit_graphics_WCMediaPlayer_notifySeeking
 794     (JNIEnv*, jobject, jlong ptr, jboolean seeking, jint /*readyState*/)
 795 {
 796     MediaPlayerPrivate* player = MediaPlayerPrivate::getPlayer(ptr);
 797     player->notifySeeking(jbool_to_bool(seeking));
 798 }
 799 
 800 JNIEXPORT void JNICALL Java_com_sun_webkit_graphics_WCMediaPlayer_notifyFinished
 801     (JNIEnv*, jobject, jlong ptr)
 802 {
 803     MediaPlayerPrivate* player = MediaPlayerPrivate::getPlayer(ptr);
 804     player->notifyFinished();
 805 }
 806 
 807 JNIEXPORT void JNICALL Java_com_sun_webkit_graphics_WCMediaPlayer_notifyReady
 808     (JNIEnv*, jobject, jlong ptr, jboolean hasVideo, jboolean hasAudio, jfloat duration)
 809 {
 810     MediaPlayerPrivate* player = MediaPlayerPrivate::getPlayer(ptr);
 811     player->notifyReady(jbool_to_bool(hasVideo), jbool_to_bool(hasAudio));
 812     if (duration >= 0) {
 813         player->notifyDurationChanged(duration);
 814     }
 815 }
 816 
 817 JNIEXPORT void JNICALL Java_com_sun_webkit_graphics_WCMediaPlayer_notifyDurationChanged
 818   (JNIEnv*, jobject, jlong ptr, jfloat duration)
 819 {
 820     MediaPlayerPrivate* player = MediaPlayerPrivate::getPlayer(ptr);
 821     if (duration != player->duration()) {
 822         player->notifyDurationChanged(duration);
 823     }
 824 }
 825 
 826 JNIEXPORT void JNICALL Java_com_sun_webkit_graphics_WCMediaPlayer_notifySizeChanged
 827     (JNIEnv*, jobject, jlong ptr, jint width, jint height)
 828 {
 829     MediaPlayerPrivate* player = MediaPlayerPrivate::getPlayer(ptr);
 830     player->notifySizeChanged(width, height);
 831 }
 832 
 833 JNIEXPORT void JNICALL Java_com_sun_webkit_graphics_WCMediaPlayer_notifyNewFrame
 834     (JNIEnv*, jobject, jlong ptr)
 835 {
 836     MediaPlayerPrivate* player = MediaPlayerPrivate::getPlayer(ptr);
 837     player->notifyNewFrame();
 838 }
 839 
 840 JNIEXPORT void JNICALL Java_com_sun_webkit_graphics_WCMediaPlayer_notifyBufferChanged
 841   (JNIEnv *env, jobject, jlong ptr, jfloatArray ranges, jint bytesLoaded)
 842 {
 843     MediaPlayerPrivate* player = MediaPlayerPrivate::getPlayer(ptr);
 844 
 845     jboolean isCopy;
 846     jint len = env->GetArrayLength(ranges);
 847     jfloat* rangesElems = env->GetFloatArrayElements(ranges, &isCopy);
 848 
 849     PlatformTimeRanges* timeRanges = new PlatformTimeRanges();
 850     for (int i = 0; i < len; i+=2) {
 851         timeRanges->add(MediaTime::createWithDouble(rangesElems[i]),
 852                         MediaTime::createWithDouble(rangesElems[i+1]));
 853     }
 854     if (isCopy == JNI_TRUE) {
 855        env->ReleaseFloatArrayElements(ranges, rangesElems, JNI_ABORT);
 856     }
 857 
 858     player->notifyBufferChanged(std::unique_ptr<PlatformTimeRanges>(timeRanges), bytesLoaded);
 859 }
 860 
 861 } // extern "C"
 862 
 863 } // namespace WebCore
 864