18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * Copyright (C) 2007, 2009 Apple Inc.  All rights reserved.
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2007 Collabora Ltd.  All rights reserved.
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2007 Alp Toker <alp@atoker.com>
5231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * Copyright (C) 2009 Gustavo Noronha Silva <gns@gnome.org>
6692e5dbf12901edacf14812a6fae25462920af42Steve Block * Copyright (C) 2009, 2010 Igalia S.L
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is free software; you can redistribute it and/or
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modify it under the terms of the GNU Library General Public
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * License as published by the Free Software Foundation; either
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * version 2 of the License, or (at your option) any later version.
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is distributed in the hope that it will be useful,
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * but WITHOUT ANY WARRANTY; without even the implied warranty of
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Library General Public License for more details.
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * You should have received a copy of the GNU Library General Public License
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * aint with this library; see the file COPYING.LIB.  If not, write to
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Boston, MA 02110-1301, USA.
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "MediaPlayerPrivateGStreamer.h"
2668513a70bcd92384395513322f1b801e7bf9c729Steve Block
27bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#if USE(GSTREAMER)
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
29dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "ColorSpace.h"
30d0825bca7fe65beaee391d30da42e937db621564Steve Block#include "Document.h"
31d0825bca7fe65beaee391d30da42e937db621564Steve Block#include "Frame.h"
32d0825bca7fe65beaee391d30da42e937db621564Steve Block#include "FrameView.h"
33dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "GOwnPtrGStreamer.h"
34e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#include "GStreamerGWorld.h"
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "GraphicsContext.h"
36dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "GraphicsTypes.h"
37dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "ImageGStreamer.h"
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "IntRect.h"
398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "KURL.h"
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "MIMETypeRegistry.h"
418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "MediaPlayer.h"
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "NotImplemented.h"
43d0825bca7fe65beaee391d30da42e937db621564Steve Block#include "SecurityOrigin.h"
44cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block#include "TimeRanges.h"
450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "VideoSinkGStreamer.h"
468a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#include "WebKitWebSourceGStreamer.h"
47dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include <GOwnPtr.h>
488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <gst/gst.h>
4981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#include <gst/interfaces/streamvolume.h>
508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <gst/video/video.h>
518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <limits>
528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <math.h>
538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
54692e5dbf12901edacf14812a6fae25462920af42Steve Block// GstPlayFlags flags from playbin2. It is the policy of GStreamer to
55692e5dbf12901edacf14812a6fae25462920af42Steve Block// not publicly expose element-specific enums. That's why this
56692e5dbf12901edacf14812a6fae25462920af42Steve Block// GstPlayFlags enum has been copied here.
57692e5dbf12901edacf14812a6fae25462920af42Steve Blocktypedef enum {
58692e5dbf12901edacf14812a6fae25462920af42Steve Block    GST_PLAY_FLAG_VIDEO         = 0x00000001,
59692e5dbf12901edacf14812a6fae25462920af42Steve Block    GST_PLAY_FLAG_AUDIO         = 0x00000002,
60692e5dbf12901edacf14812a6fae25462920af42Steve Block    GST_PLAY_FLAG_TEXT          = 0x00000004,
61692e5dbf12901edacf14812a6fae25462920af42Steve Block    GST_PLAY_FLAG_VIS           = 0x00000008,
62692e5dbf12901edacf14812a6fae25462920af42Steve Block    GST_PLAY_FLAG_SOFT_VOLUME   = 0x00000010,
63692e5dbf12901edacf14812a6fae25462920af42Steve Block    GST_PLAY_FLAG_NATIVE_AUDIO  = 0x00000020,
64692e5dbf12901edacf14812a6fae25462920af42Steve Block    GST_PLAY_FLAG_NATIVE_VIDEO  = 0x00000040,
65692e5dbf12901edacf14812a6fae25462920af42Steve Block    GST_PLAY_FLAG_DOWNLOAD      = 0x00000080,
66692e5dbf12901edacf14812a6fae25462920af42Steve Block    GST_PLAY_FLAG_BUFFERING     = 0x000000100
67692e5dbf12901edacf14812a6fae25462920af42Steve Block} GstPlayFlags;
68692e5dbf12901edacf14812a6fae25462920af42Steve Block
698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace std;
708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
73692e5dbf12901edacf14812a6fae25462920af42Steve Blockstatic int greatestCommonDivisor(int a, int b)
74692e5dbf12901edacf14812a6fae25462920af42Steve Block{
75692e5dbf12901edacf14812a6fae25462920af42Steve Block    while (b) {
76692e5dbf12901edacf14812a6fae25462920af42Steve Block        int temp = a;
77692e5dbf12901edacf14812a6fae25462920af42Steve Block        a = b;
78692e5dbf12901edacf14812a6fae25462920af42Steve Block        b = temp % b;
79692e5dbf12901edacf14812a6fae25462920af42Steve Block    }
80692e5dbf12901edacf14812a6fae25462920af42Steve Block
81692e5dbf12901edacf14812a6fae25462920af42Steve Block    return ABS(a);
82692e5dbf12901edacf14812a6fae25462920af42Steve Block}
83692e5dbf12901edacf14812a6fae25462920af42Steve Block
842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic gboolean mediaPlayerPrivateMessageCallback(GstBus*, GstMessage* message, MediaPlayerPrivateGStreamer* player)
858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return player->handleMessage(message);
878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic void mediaPlayerPrivateSourceChangedCallback(GObject*, GParamSpec*, MediaPlayerPrivateGStreamer* player)
90d0825bca7fe65beaee391d30da42e937db621564Steve Block{
912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    player->sourceChanged();
92d0825bca7fe65beaee391d30da42e937db621564Steve Block}
93d0825bca7fe65beaee391d30da42e937db621564Steve Block
942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic void mediaPlayerPrivateVolumeChangedCallback(GObject*, GParamSpec*, MediaPlayerPrivateGStreamer* player)
95d0825bca7fe65beaee391d30da42e937db621564Steve Block{
965e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    // This is called when playbin receives the notify::volume signal.
972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    player->volumeChanged();
98d0825bca7fe65beaee391d30da42e937db621564Steve Block}
99d0825bca7fe65beaee391d30da42e937db621564Steve Block
1002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic gboolean mediaPlayerPrivateVolumeChangeTimeoutCallback(MediaPlayerPrivateGStreamer* player)
101f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
102f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    // This is the callback of the timeout source created in ::volumeChanged.
103f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    player->notifyPlayerOfVolumeChange();
104f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    return FALSE;
105f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
106f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
1072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic void mediaPlayerPrivateMuteChangedCallback(GObject*, GParamSpec*, MediaPlayerPrivateGStreamer* player)
1085e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block{
1095e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    // This is called when playbin receives the notify::mute signal.
1102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    player->muteChanged();
1115e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block}
1125e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block
1132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic gboolean mediaPlayerPrivateMuteChangeTimeoutCallback(MediaPlayerPrivateGStreamer* player)
114f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
115f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    // This is the callback of the timeout source created in ::muteChanged.
116f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    player->notifyPlayerOfMute();
117f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    return FALSE;
118f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
119f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
1202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic void mediaPlayerPrivateVideoSinkCapsChangedCallback(GObject*, GParamSpec*, MediaPlayerPrivateGStreamer* player)
121f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
1222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    player->videoChanged();
123f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
124f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
1252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic void mediaPlayerPrivateVideoChangedCallback(GObject*, MediaPlayerPrivateGStreamer* player)
126f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
1272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    player->videoChanged();
128f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
129f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
1302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic void mediaPlayerPrivateAudioChangedCallback(GObject*, MediaPlayerPrivateGStreamer* player)
131f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
1322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    player->audioChanged();
133f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
134f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
1352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic gboolean mediaPlayerPrivateAudioChangeTimeoutCallback(MediaPlayerPrivateGStreamer* player)
136f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
1372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // This is the callback of the timeout source created in ::audioChanged.
1382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    player->notifyPlayerOfAudio();
139f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    return FALSE;
140f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
141f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
1422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic gboolean mediaPlayerPrivateVideoChangeTimeoutCallback(MediaPlayerPrivateGStreamer* player)
143643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
1442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // This is the callback of the timeout source created in ::videoChanged.
1452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    player->notifyPlayerOfVideo();
1462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return FALSE;
147643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
148643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
1492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic void mediaPlayerPrivateRepaintCallback(WebKitVideoSink*, GstBuffer *buffer, MediaPlayerPrivateGStreamer* playerPrivate)
1508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
1512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    playerPrivate->triggerRepaint(buffer);
1528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
1538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
154dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockMediaPlayerPrivateInterface* MediaPlayerPrivateGStreamer::create(MediaPlayer* player)
1550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
156dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return new MediaPlayerPrivateGStreamer(player);
1578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
1588f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
159dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid MediaPlayerPrivateGStreamer::registerMediaEngine(MediaEngineRegistrar registrar)
1608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
1618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (isAvailable())
16281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        registrar(create, getSupportedTypes, supportsType, 0, 0, 0);
1638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
1648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
165231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockstatic bool gstInitialized = false;
166231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
167d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic bool doGstInit()
168cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block{
169231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // FIXME: We should pass the arguments from the command line
170231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (!gstInitialized) {
171643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        GOwnPtr<GError> error;
172643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        gstInitialized = gst_init_check(0, 0, &error.outPtr());
173f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        if (!gstInitialized)
174643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            LOG_VERBOSE(Media, "Could not initialize GStreamer: %s",
175643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                        error ? error->message : "unknown error occurred");
176f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        else
1778a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block            gst_element_register(0, "webkitwebsrc", GST_RANK_PRIMARY + 100,
1788a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block                                 WEBKIT_TYPE_WEB_SRC);
179231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
180643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    return gstInitialized;
181643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
182643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
183dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockbool MediaPlayerPrivateGStreamer::isAvailable()
184643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
185d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (!doGstInit())
186643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return false;
187643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
188643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    GstElementFactory* factory = gst_element_factory_find("playbin2");
189643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (factory) {
190643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        gst_object_unref(GST_OBJECT(factory));
191643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return true;
192643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
193643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    return false;
194231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
195231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
196dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockMediaPlayerPrivateGStreamer::MediaPlayerPrivateGStreamer(MediaPlayer* player)
1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    : m_player(player)
1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_playBin(0)
19906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    , m_webkitVideoSink(0)
200d0825bca7fe65beaee391d30da42e937db621564Steve Block    , m_fpsSink(0)
2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_source(0)
202643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    , m_seekTime(0)
203643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    , m_changingRate(false)
2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_endTime(numeric_limits<float>::infinity())
2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_networkState(MediaPlayer::Empty)
2068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    , m_readyState(MediaPlayer::HaveNothing)
2078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_isStreaming(false)
2088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    , m_size(IntSize())
209cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    , m_buffer(0)
210d0825bca7fe65beaee391d30da42e937db621564Steve Block    , m_mediaLocations(0)
211d0825bca7fe65beaee391d30da42e937db621564Steve Block    , m_mediaLocationCurrentIndex(0)
212d0825bca7fe65beaee391d30da42e937db621564Steve Block    , m_resetPipeline(false)
213231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    , m_paused(true)
214231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    , m_seeking(false)
215dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    , m_buffering(false)
216d0825bca7fe65beaee391d30da42e937db621564Steve Block    , m_playbackRate(1)
217231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    , m_errorOccured(false)
218692e5dbf12901edacf14812a6fae25462920af42Steve Block    , m_mediaDuration(0)
219692e5dbf12901edacf14812a6fae25462920af42Steve Block    , m_startedBuffering(false)
220dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    , m_fillTimer(this, &MediaPlayerPrivateGStreamer::fillTimerFired)
221692e5dbf12901edacf14812a6fae25462920af42Steve Block    , m_maxTimeLoaded(0)
222dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    , m_bufferingPercentage(0)
223dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    , m_preload(MediaPlayer::Auto)
224dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    , m_delayingLoad(false)
225dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    , m_mediaDurationKnown(true)
226f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    , m_volumeTimerHandler(0)
227f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    , m_muteTimerHandler(0)
228f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    , m_hasVideo(false)
229f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    , m_hasAudio(false)
2302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    , m_audioTimerHandler(0)
2312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    , m_videoTimerHandler(0)
2322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    , m_webkitAudioSink(0)
2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
234692e5dbf12901edacf14812a6fae25462920af42Steve Block    if (doGstInit())
235692e5dbf12901edacf14812a6fae25462920af42Steve Block        createGSTPlayBin();
236231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
237231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
238dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockMediaPlayerPrivateGStreamer::~MediaPlayerPrivateGStreamer()
2398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
240dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (m_fillTimer.isActive())
241dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        m_fillTimer.stop();
242d0825bca7fe65beaee391d30da42e937db621564Steve Block
243cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    if (m_buffer)
244cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        gst_buffer_unref(m_buffer);
245cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    m_buffer = 0;
2468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
247d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (m_mediaLocations) {
248d0825bca7fe65beaee391d30da42e937db621564Steve Block        gst_structure_free(m_mediaLocations);
249d0825bca7fe65beaee391d30da42e937db621564Steve Block        m_mediaLocations = 0;
250d0825bca7fe65beaee391d30da42e937db621564Steve Block    }
251d0825bca7fe65beaee391d30da42e937db621564Steve Block
252d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (m_source) {
253d0825bca7fe65beaee391d30da42e937db621564Steve Block        gst_object_unref(m_source);
254d0825bca7fe65beaee391d30da42e937db621564Steve Block        m_source = 0;
255d0825bca7fe65beaee391d30da42e937db621564Steve Block    }
256d0825bca7fe65beaee391d30da42e937db621564Steve Block
25706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    if (m_videoSinkBin) {
25806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        gst_object_unref(m_videoSinkBin);
25906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        m_videoSinkBin = 0;
26006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    }
26106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
2628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_playBin) {
2638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gst_element_set_state(m_playBin, GST_STATE_NULL);
2648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gst_object_unref(GST_OBJECT(m_playBin));
265f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        m_playBin = 0;
2668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
267231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
268f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    m_player = 0;
269f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
270f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (m_muteTimerHandler)
271f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        g_source_remove(m_muteTimerHandler);
272f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
273f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (m_volumeTimerHandler)
274f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        g_source_remove(m_volumeTimerHandler);
275f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
2762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (m_videoTimerHandler)
2772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        g_source_remove(m_videoTimerHandler);
278f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
2792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (m_audioTimerHandler)
2802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        g_source_remove(m_audioTimerHandler);
2818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
283dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid MediaPlayerPrivateGStreamer::load(const String& url)
2848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
285dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    g_object_set(m_playBin, "uri", url.utf8().data(), NULL);
286dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG_VERBOSE(Media, "Load %s", url.utf8().data());
288dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
289dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (m_preload == MediaPlayer::None) {
290dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        LOG_VERBOSE(Media, "Delaying load.");
291dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        m_delayingLoad = true;
292dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
293dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
294dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // GStreamer needs to have the pipeline set to a paused state to
295dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // start providing anything useful.
296dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    gst_element_set_state(m_playBin, GST_STATE_PAUSED);
297dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
298f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!m_delayingLoad)
299f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        commitLoad();
300f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
301f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
302f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid MediaPlayerPrivateGStreamer::commitLoad()
303f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
304f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    ASSERT(!m_delayingLoad);
305dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    LOG_VERBOSE(Media, "Committing load.");
306f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    updateStates();
3078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochfloat MediaPlayerPrivateGStreamer::playbackPosition() const
3102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
3112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    float ret = 0.0f;
3122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    GstQuery* query = gst_query_new_position(GST_FORMAT_TIME);
3142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!gst_element_query(m_playBin, query)) {
3152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        LOG_VERBOSE(Media, "Position query failed...");
3162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        gst_query_unref(query);
3172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return ret;
3182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
3192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    gint64 position;
3212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    gst_query_parse_position(query, 0, &position);
3222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // Position is available only if the pipeline is not in GST_STATE_NULL or
3242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // GST_STATE_READY state.
3252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (position != static_cast<gint64>(GST_CLOCK_TIME_NONE))
3262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret = static_cast<float>(position) / static_cast<float>(GST_SECOND);
3272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    LOG_VERBOSE(Media, "Position %" GST_TIME_FORMAT, GST_TIME_ARGS(position));
3292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    gst_query_unref(query);
3312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return ret;
3332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
3342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
335dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockbool MediaPlayerPrivateGStreamer::changePipelineState(GstState newState)
3368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
337d0825bca7fe65beaee391d30da42e937db621564Steve Block    ASSERT(newState == GST_STATE_PLAYING || newState == GST_STATE_PAUSED);
338d0825bca7fe65beaee391d30da42e937db621564Steve Block
339d0825bca7fe65beaee391d30da42e937db621564Steve Block    GstState currentState;
340643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    GstState pending;
341643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
342d0825bca7fe65beaee391d30da42e937db621564Steve Block    gst_element_get_state(m_playBin, &currentState, &pending, 0);
343d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (currentState != newState && pending != newState) {
344d0825bca7fe65beaee391d30da42e937db621564Steve Block        GstStateChangeReturn ret = gst_element_set_state(m_playBin, newState);
345d0825bca7fe65beaee391d30da42e937db621564Steve Block        GstState pausedOrPlaying = newState == GST_STATE_PLAYING ? GST_STATE_PAUSED : GST_STATE_PLAYING;
346d0825bca7fe65beaee391d30da42e937db621564Steve Block        if (currentState != pausedOrPlaying && ret == GST_STATE_CHANGE_FAILURE) {
347d0825bca7fe65beaee391d30da42e937db621564Steve Block            loadingFailed(MediaPlayer::Empty);
348d0825bca7fe65beaee391d30da42e937db621564Steve Block            return false;
349d0825bca7fe65beaee391d30da42e937db621564Steve Block        }
350643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
351d0825bca7fe65beaee391d30da42e937db621564Steve Block    return true;
3528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
354dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid MediaPlayerPrivateGStreamer::prepareToPlay()
355dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
356dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (m_delayingLoad) {
357dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        m_delayingLoad = false;
358dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        commitLoad();
359dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
360dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
361dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
362dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid MediaPlayerPrivateGStreamer::play()
3638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
364d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (changePipelineState(GST_STATE_PLAYING))
365d0825bca7fe65beaee391d30da42e937db621564Steve Block        LOG_VERBOSE(Media, "Play");
366d0825bca7fe65beaee391d30da42e937db621564Steve Block}
367643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
368dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid MediaPlayerPrivateGStreamer::pause()
369d0825bca7fe65beaee391d30da42e937db621564Steve Block{
370d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (changePipelineState(GST_STATE_PAUSED))
371643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        LOG_VERBOSE(Media, "Pause");
3728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
374dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockfloat MediaPlayerPrivateGStreamer::duration() const
3758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!m_playBin)
3775af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        return 0.0f;
3788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
379231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (m_errorOccured)
3805af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        return 0.0f;
381231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
382dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // Media duration query failed already, don't attempt new useless queries.
383dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (!m_mediaDurationKnown)
384dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return numeric_limits<float>::infinity();
385dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
386d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (m_mediaDuration)
387d0825bca7fe65beaee391d30da42e937db621564Steve Block        return m_mediaDuration;
388d0825bca7fe65beaee391d30da42e937db621564Steve Block
3898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    GstFormat timeFormat = GST_FORMAT_TIME;
3908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    gint64 timeLength = 0;
3918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
392643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (!gst_element_query_duration(m_playBin, &timeFormat, &timeLength) || timeFormat != GST_FORMAT_TIME || static_cast<guint64>(timeLength) == GST_CLOCK_TIME_NONE) {
3938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        LOG_VERBOSE(Media, "Time duration query failed.");
3948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return numeric_limits<float>::infinity();
3958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    LOG_VERBOSE(Media, "Duration: %" GST_TIME_FORMAT, GST_TIME_ARGS(timeLength));
3988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
399cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    return (float) ((guint64) timeLength / 1000000000.0);
4008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FIXME: handle 3.14.9.5 properly
4018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
403dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockfloat MediaPlayerPrivateGStreamer::currentTime() const
4048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!m_playBin)
4065af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        return 0.0f;
4078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
408231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (m_errorOccured)
4095af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        return 0.0f;
410231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
411643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (m_seeking)
4122bde8e466a4451c7319e3a072d118917957d6554Steve Block        return m_seekTime;
4138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return playbackPosition();
415231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
4168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
418dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid MediaPlayerPrivateGStreamer::seek(float time)
4198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
420d0825bca7fe65beaee391d30da42e937db621564Steve Block    // Avoid useless seeking.
4212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (time == playbackPosition())
422d0825bca7fe65beaee391d30da42e937db621564Steve Block        return;
4238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!m_playBin)
4258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
4268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
427231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (m_errorOccured)
428231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return;
429231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
4302bde8e466a4451c7319e3a072d118917957d6554Steve Block    // Extract the integer part of the time (seconds) and the
4312bde8e466a4451c7319e3a072d118917957d6554Steve Block    // fractional part (microseconds). Attempt to round the
4322bde8e466a4451c7319e3a072d118917957d6554Steve Block    // microseconds so no floating point precision is lost and we can
4332bde8e466a4451c7319e3a072d118917957d6554Steve Block    // perform an accurate seek.
4342bde8e466a4451c7319e3a072d118917957d6554Steve Block    float seconds;
4352bde8e466a4451c7319e3a072d118917957d6554Steve Block    float microSeconds = modf(time, &seconds) * 1000000;
4362bde8e466a4451c7319e3a072d118917957d6554Steve Block    GTimeVal timeValue;
4372bde8e466a4451c7319e3a072d118917957d6554Steve Block    timeValue.tv_sec = static_cast<glong>(seconds);
4382bde8e466a4451c7319e3a072d118917957d6554Steve Block    timeValue.tv_usec = static_cast<glong>(roundf(microSeconds / 10000) * 10000);
4392bde8e466a4451c7319e3a072d118917957d6554Steve Block
4402bde8e466a4451c7319e3a072d118917957d6554Steve Block    GstClockTime clockTime = GST_TIMEVAL_TO_TIME(timeValue);
4412bde8e466a4451c7319e3a072d118917957d6554Steve Block    LOG_VERBOSE(Media, "Seek: %" GST_TIME_FORMAT, GST_TIME_ARGS(clockTime));
4422bde8e466a4451c7319e3a072d118917957d6554Steve Block
443cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    if (!gst_element_seek(m_playBin, m_player->rate(),
4448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            GST_FORMAT_TIME,
4452bde8e466a4451c7319e3a072d118917957d6554Steve Block            (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE),
4462bde8e466a4451c7319e3a072d118917957d6554Steve Block            GST_SEEK_TYPE_SET, clockTime,
4478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE))
4488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        LOG_VERBOSE(Media, "Seek to %f failed", time);
449643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    else {
450231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        m_seeking = true;
4512bde8e466a4451c7319e3a072d118917957d6554Steve Block        m_seekTime = time;
452643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
4538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
455dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockbool MediaPlayerPrivateGStreamer::paused() const
4568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
457231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return m_paused;
4588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
460dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockbool MediaPlayerPrivateGStreamer::seeking() const
4618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
462231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return m_seeking;
4638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Returns the size of the video
466dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockIntSize MediaPlayerPrivateGStreamer::naturalSize() const
4678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!hasVideo())
4698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return IntSize();
4708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
47106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    GstPad* pad = gst_element_get_static_pad(m_webkitVideoSink, "sink");
472692e5dbf12901edacf14812a6fae25462920af42Steve Block    if (!pad)
473692e5dbf12901edacf14812a6fae25462920af42Steve Block        return IntSize();
474692e5dbf12901edacf14812a6fae25462920af42Steve Block
4755af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    guint64 width = 0, height = 0;
476692e5dbf12901edacf14812a6fae25462920af42Steve Block    GstCaps* caps = GST_PAD_CAPS(pad);
477692e5dbf12901edacf14812a6fae25462920af42Steve Block    int pixelAspectRatioNumerator, pixelAspectRatioDenominator;
478692e5dbf12901edacf14812a6fae25462920af42Steve Block    int displayWidth, displayHeight, displayAspectRatioGCD;
479692e5dbf12901edacf14812a6fae25462920af42Steve Block    int originalWidth = 0, originalHeight = 0;
480692e5dbf12901edacf14812a6fae25462920af42Steve Block
481231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // TODO: handle possible clean aperture data. See
482231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // https://bugzilla.gnome.org/show_bug.cgi?id=596571
483231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // TODO: handle possible transformation matrix. See
484231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // https://bugzilla.gnome.org/show_bug.cgi?id=596326
485231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
486692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Get the video PAR and original size.
487692e5dbf12901edacf14812a6fae25462920af42Steve Block    if (!GST_IS_CAPS(caps) || !gst_caps_is_fixed(caps)
488692e5dbf12901edacf14812a6fae25462920af42Steve Block        || !gst_video_format_parse_caps(caps, 0, &originalWidth, &originalHeight)
489692e5dbf12901edacf14812a6fae25462920af42Steve Block        || !gst_video_parse_caps_pixel_aspect_ratio(caps, &pixelAspectRatioNumerator,
490692e5dbf12901edacf14812a6fae25462920af42Steve Block                                                    &pixelAspectRatioDenominator)) {
4918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gst_object_unref(GST_OBJECT(pad));
4922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // The video-sink has likely not yet negotiated its caps.
493692e5dbf12901edacf14812a6fae25462920af42Steve Block        return IntSize();
4948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
496692e5dbf12901edacf14812a6fae25462920af42Steve Block    gst_object_unref(GST_OBJECT(pad));
497692e5dbf12901edacf14812a6fae25462920af42Steve Block
498692e5dbf12901edacf14812a6fae25462920af42Steve Block    LOG_VERBOSE(Media, "Original video size: %dx%d", originalWidth, originalHeight);
499692e5dbf12901edacf14812a6fae25462920af42Steve Block    LOG_VERBOSE(Media, "Pixel aspect ratio: %d/%d", pixelAspectRatioNumerator, pixelAspectRatioDenominator);
500692e5dbf12901edacf14812a6fae25462920af42Steve Block
501692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Calculate DAR based on PAR and video size.
502692e5dbf12901edacf14812a6fae25462920af42Steve Block    displayWidth = originalWidth * pixelAspectRatioNumerator;
503692e5dbf12901edacf14812a6fae25462920af42Steve Block    displayHeight = originalHeight * pixelAspectRatioDenominator;
504692e5dbf12901edacf14812a6fae25462920af42Steve Block
505692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Divide display width and height by their GCD to avoid possible overflows.
506692e5dbf12901edacf14812a6fae25462920af42Steve Block    displayAspectRatioGCD = greatestCommonDivisor(displayWidth, displayHeight);
507692e5dbf12901edacf14812a6fae25462920af42Steve Block    displayWidth /= displayAspectRatioGCD;
508692e5dbf12901edacf14812a6fae25462920af42Steve Block    displayHeight /= displayAspectRatioGCD;
509692e5dbf12901edacf14812a6fae25462920af42Steve Block
510692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Apply DAR to original video size. This is the same behavior as in xvimagesink's setcaps function.
511692e5dbf12901edacf14812a6fae25462920af42Steve Block    if (!(originalHeight % displayHeight)) {
512692e5dbf12901edacf14812a6fae25462920af42Steve Block        LOG_VERBOSE(Media, "Keeping video original height");
513692e5dbf12901edacf14812a6fae25462920af42Steve Block        width = gst_util_uint64_scale_int(originalHeight, displayWidth, displayHeight);
5145af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        height = static_cast<guint64>(originalHeight);
515692e5dbf12901edacf14812a6fae25462920af42Steve Block    } else if (!(originalWidth % displayWidth)) {
516692e5dbf12901edacf14812a6fae25462920af42Steve Block        LOG_VERBOSE(Media, "Keeping video original width");
517692e5dbf12901edacf14812a6fae25462920af42Steve Block        height = gst_util_uint64_scale_int(originalWidth, displayHeight, displayWidth);
5185af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        width = static_cast<guint64>(originalWidth);
519692e5dbf12901edacf14812a6fae25462920af42Steve Block    } else {
520692e5dbf12901edacf14812a6fae25462920af42Steve Block        LOG_VERBOSE(Media, "Approximating while keeping original video height");
521692e5dbf12901edacf14812a6fae25462920af42Steve Block        width = gst_util_uint64_scale_int(originalHeight, displayWidth, displayHeight);
5225af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        height = static_cast<guint64>(originalHeight);
523692e5dbf12901edacf14812a6fae25462920af42Steve Block    }
524692e5dbf12901edacf14812a6fae25462920af42Steve Block
5255af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    LOG_VERBOSE(Media, "Natural size: %" G_GUINT64_FORMAT "x%" G_GUINT64_FORMAT, width, height);
5265af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    return IntSize(static_cast<int>(width), static_cast<int>(height));
5278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid MediaPlayerPrivateGStreamer::videoChanged()
5308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (m_videoTimerHandler)
5322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        g_source_remove(m_videoTimerHandler);
5332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_videoTimerHandler = g_timeout_add(0, reinterpret_cast<GSourceFunc>(mediaPlayerPrivateVideoChangeTimeoutCallback), this);
534f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
535f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
5362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid MediaPlayerPrivateGStreamer::notifyPlayerOfVideo()
537f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
5382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_videoTimerHandler = 0;
539f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
5402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    gint videoTracks = 0;
5418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_playBin)
5422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        g_object_get(m_playBin, "n-video", &videoTracks, NULL);
5432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
5442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_hasVideo = videoTracks > 0;
545f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    m_player->mediaPlayerClient()->mediaPlayerEngineUpdated(m_player);
546f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
547f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
5482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid MediaPlayerPrivateGStreamer::audioChanged()
549f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
5502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (m_audioTimerHandler)
5512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        g_source_remove(m_audioTimerHandler);
5522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_audioTimerHandler = g_timeout_add(0, reinterpret_cast<GSourceFunc>(mediaPlayerPrivateAudioChangeTimeoutCallback), this);
5538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid MediaPlayerPrivateGStreamer::notifyPlayerOfAudio()
556231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
5572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_audioTimerHandler = 0;
558f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
5592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    gint audioTracks = 0;
560231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (m_playBin)
5612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        g_object_get(m_playBin, "n-audio", &audioTracks, NULL);
5622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_hasAudio = audioTracks > 0;
563f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    m_player->mediaPlayerClient()->mediaPlayerEngineUpdated(m_player);
564231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
565231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
566dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid MediaPlayerPrivateGStreamer::setVolume(float volume)
5678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
568231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (!m_playBin)
569231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return;
570231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
57181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    gst_stream_volume_set_volume(GST_STREAM_VOLUME(m_playBin), GST_STREAM_VOLUME_FORMAT_CUBIC,
57281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                                 static_cast<double>(volume));
5738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
575f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid MediaPlayerPrivateGStreamer::notifyPlayerOfVolumeChange()
5765e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block{
577f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    m_volumeTimerHandler = 0;
578f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
579f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!m_player || !m_playBin)
580f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        return;
5815e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    double volume;
58281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    volume = gst_stream_volume_get_volume(GST_STREAM_VOLUME(m_playBin), GST_STREAM_VOLUME_FORMAT_CUBIC);
58381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    // get_volume() can return values superior to 1.0 if the user
58481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    // applies software user gain via third party application (GNOME
58581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    // volume control for instance).
58681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    volume = CLAMP(volume, 0.0, 1.0);
5875e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    m_player->volumeChanged(static_cast<float>(volume));
5885e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block}
5895e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block
590dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid MediaPlayerPrivateGStreamer::volumeChanged()
591d0825bca7fe65beaee391d30da42e937db621564Steve Block{
592f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (m_volumeTimerHandler)
593f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        g_source_remove(m_volumeTimerHandler);
594f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    m_volumeTimerHandler = g_timeout_add(0, reinterpret_cast<GSourceFunc>(mediaPlayerPrivateVolumeChangeTimeoutCallback), this);
595d0825bca7fe65beaee391d30da42e937db621564Steve Block}
596d0825bca7fe65beaee391d30da42e937db621564Steve Block
597dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid MediaPlayerPrivateGStreamer::setRate(float rate)
5988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
599d0825bca7fe65beaee391d30da42e937db621564Steve Block    // Avoid useless playback rate update.
600d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (m_playbackRate == rate)
601d0825bca7fe65beaee391d30da42e937db621564Steve Block        return;
602d0825bca7fe65beaee391d30da42e937db621564Steve Block
603643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    GstState state;
604643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    GstState pending;
605643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
606643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    gst_element_get_state(m_playBin, &state, &pending, 0);
607643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if ((state != GST_STATE_PLAYING && state != GST_STATE_PAUSED)
608643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        || (pending == GST_STATE_PAUSED))
6098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
610231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
6118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_isStreaming)
6128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
6138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
614d0825bca7fe65beaee391d30da42e937db621564Steve Block    m_playbackRate = rate;
615643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    m_changingRate = true;
6162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
6172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!rate) {
6182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        gst_element_set_state(m_playBin, GST_STATE_PAUSED);
6192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return;
6202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
6212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
6222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    float currentPosition = static_cast<float>(playbackPosition() * GST_SECOND);
623643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    GstSeekFlags flags = (GstSeekFlags)(GST_SEEK_FLAG_FLUSH);
624643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    gint64 start, end;
625643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    bool mute = false;
626643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
6278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG_VERBOSE(Media, "Set Rate to %f", rate);
6282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (rate > 0) {
629643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        // Mute the sound if the playback rate is too extreme.
630643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        // TODO: in other cases we should perform pitch adjustments.
631643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        mute = (bool) (rate < 0.8 || rate > 2);
632643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        start = currentPosition;
633643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        end = GST_CLOCK_TIME_NONE;
634643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    } else {
635643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        start = 0;
636643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        mute = true;
637643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
638643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        // If we are at beginning of media, start from the end to
639643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        // avoid immediate EOS.
640643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        if (currentPosition <= 0)
6415af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke            end = static_cast<gint64>(duration() * GST_SECOND);
642643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        else
643643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            end = currentPosition;
644643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
645643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
646643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    LOG_VERBOSE(Media, "Need to mute audio: %d", (int) mute);
647643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
648643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (!gst_element_seek(m_playBin, rate, GST_FORMAT_TIME, flags,
649643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                          GST_SEEK_TYPE_SET, start,
650643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                          GST_SEEK_TYPE_SET, end))
651643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        LOG_VERBOSE(Media, "Set rate to %f failed", rate);
652643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    else
653643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        g_object_set(m_playBin, "mute", mute, NULL);
6548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
656dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockMediaPlayer::NetworkState MediaPlayerPrivateGStreamer::networkState() const
6578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return m_networkState;
6598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
661dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockMediaPlayer::ReadyState MediaPlayerPrivateGStreamer::readyState() const
6628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return m_readyState;
6648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
666dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockPassRefPtr<TimeRanges> MediaPlayerPrivateGStreamer::buffered() const
6678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
668231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    RefPtr<TimeRanges> timeRanges = TimeRanges::create();
669f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (m_errorOccured || m_isStreaming)
670f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        return timeRanges.release();
671f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
672f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#if GST_CHECK_VERSION(0, 10, 31)
673f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    float mediaDuration(duration());
674f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!mediaDuration || isinf(mediaDuration))
675f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        return timeRanges.release();
676f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
677f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    GstQuery* query = gst_query_new_buffering(GST_FORMAT_PERCENT);
678f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
679f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!gst_element_query(m_playBin, query)) {
680f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        gst_query_unref(query);
681f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        return timeRanges.release();
682f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    }
683f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
684f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    gint64 rangeStart = 0, rangeStop = 0;
685f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    for (guint index = 0; index < gst_query_get_n_buffering_ranges(query); index++) {
686f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        if (gst_query_parse_nth_buffering_range(query, index, &rangeStart, &rangeStop))
687f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            timeRanges->add(static_cast<float>((rangeStart * mediaDuration) / 100),
688f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch                            static_cast<float>((rangeStop * mediaDuration) / 100));
689f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    }
690f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
691f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    // Fallback to the more general maxTimeLoaded() if no range has
692f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    // been found.
693f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!timeRanges->length())
694f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        if (float loaded = maxTimeLoaded())
695f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            timeRanges->add(0, loaded);
696f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
697f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    gst_query_unref(query);
698f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#else
699231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    float loaded = maxTimeLoaded();
700231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (!m_errorOccured && !m_isStreaming && loaded > 0)
701231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        timeRanges->add(0, loaded);
702f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#endif
703231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return timeRanges.release();
7048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochgboolean MediaPlayerPrivateGStreamer::handleMessage(GstMessage* message)
7072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
7082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    GOwnPtr<GError> err;
7092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    GOwnPtr<gchar> debug;
7102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    MediaPlayer::NetworkState error;
7112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool issueError = true;
7122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool attemptNextLocation = false;
7132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
7142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (message->structure) {
7152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        const gchar* messageTypeName = gst_structure_get_name(message->structure);
7162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
7172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // Redirect messages are sent from elements, like qtdemux, to
7182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // notify of the new location(s) of the media.
7192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!g_strcmp0(messageTypeName, "redirect")) {
7202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            mediaLocationChanged(message);
7212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return TRUE;
7222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
7232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
7242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
7252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    switch (GST_MESSAGE_TYPE(message)) {
7262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    case GST_MESSAGE_ERROR:
7272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (m_resetPipeline)
7282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            break;
7292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        gst_message_parse_error(message, &err.outPtr(), &debug.outPtr());
7302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        LOG_VERBOSE(Media, "Error: %d, %s", err->code,  err->message);
7312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
7322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        error = MediaPlayer::Empty;
7332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (err->code == GST_STREAM_ERROR_CODEC_NOT_FOUND
7342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            || err->code == GST_STREAM_ERROR_WRONG_TYPE
7352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            || err->code == GST_STREAM_ERROR_FAILED
7362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            || err->code == GST_CORE_ERROR_MISSING_PLUGIN
7372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            || err->code == GST_RESOURCE_ERROR_NOT_FOUND)
7382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            error = MediaPlayer::FormatError;
7392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        else if (err->domain == GST_STREAM_ERROR) {
7402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            // Let the mediaPlayerClient handle the stream error, in
7412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            // this case the HTMLMediaElement will emit a stalled
7422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            // event.
7432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            if (err->code == GST_STREAM_ERROR_TYPE_NOT_FOUND) {
7442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                LOG_VERBOSE(Media, "Decode error, let the Media element emit a stalled event.");
7452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                break;
7462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            }
7472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            error = MediaPlayer::DecodeError;
7482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            attemptNextLocation = true;
7492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        } else if (err->domain == GST_RESOURCE_ERROR)
7502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            error = MediaPlayer::NetworkError;
7512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
7522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (attemptNextLocation)
7532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            issueError = !loadNextLocation();
7542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (issueError)
7552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            loadingFailed(error);
7562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        break;
7572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    case GST_MESSAGE_EOS:
7582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        LOG_VERBOSE(Media, "End of Stream");
7592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        didEnd();
7602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        break;
7612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    case GST_MESSAGE_STATE_CHANGED:
7622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // Ignore state changes if load is delayed (preload=none). The
7632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // player state will be updated once commitLoad() is called.
7642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (m_delayingLoad) {
7652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            LOG_VERBOSE(Media, "Media load has been delayed. Ignoring state changes for now");
7662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            break;
7672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
7682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
7692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // Ignore state changes from internal elements. They are
7702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // forwarded to playbin2 anyway.
7712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (GST_MESSAGE_SRC(message) == reinterpret_cast<GstObject*>(m_playBin))
7722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            updateStates();
7732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        break;
7742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    case GST_MESSAGE_BUFFERING:
7752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        processBufferingStats(message);
7762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        break;
7772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    case GST_MESSAGE_DURATION:
7782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        LOG_VERBOSE(Media, "Duration changed");
7792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        durationChanged();
7802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        break;
7812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    default:
7822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        LOG_VERBOSE(Media, "Unhandled GStreamer message type: %s",
7832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    GST_MESSAGE_TYPE_NAME(message));
7842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        break;
7852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
7862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return TRUE;
7872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
7882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
789dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid MediaPlayerPrivateGStreamer::processBufferingStats(GstMessage* message)
790692e5dbf12901edacf14812a6fae25462920af42Steve Block{
791dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // This is the immediate buffering that needs to happen so we have
792dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // enough to play right now.
793dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    m_buffering = true;
794dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    const GstStructure *structure = gst_message_get_structure(message);
795dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    gst_structure_get_int(structure, "buffer-percent", &m_bufferingPercentage);
796dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
797dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    LOG_VERBOSE(Media, "[Buffering] Buffering: %d%%.", m_bufferingPercentage);
798692e5dbf12901edacf14812a6fae25462920af42Steve Block
799dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    GstBufferingMode mode;
800692e5dbf12901edacf14812a6fae25462920af42Steve Block    gst_message_parse_buffering_stats(message, &mode, 0, 0, 0);
801dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (mode != GST_BUFFERING_DOWNLOAD) {
802dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        updateStates();
803692e5dbf12901edacf14812a6fae25462920af42Steve Block        return;
804dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
805692e5dbf12901edacf14812a6fae25462920af42Steve Block
806dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // This is on-disk buffering, that allows us to download much more
807dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // than needed for right now.
808692e5dbf12901edacf14812a6fae25462920af42Steve Block    if (!m_startedBuffering) {
809dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        LOG_VERBOSE(Media, "[Buffering] Starting on-disk buffering.");
810dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
811692e5dbf12901edacf14812a6fae25462920af42Steve Block        m_startedBuffering = true;
812692e5dbf12901edacf14812a6fae25462920af42Steve Block
813dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (m_fillTimer.isActive())
814dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            m_fillTimer.stop();
815692e5dbf12901edacf14812a6fae25462920af42Steve Block
816dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        m_fillTimer.startRepeating(0.2);
817692e5dbf12901edacf14812a6fae25462920af42Steve Block    }
818692e5dbf12901edacf14812a6fae25462920af42Steve Block}
819692e5dbf12901edacf14812a6fae25462920af42Steve Block
820dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid MediaPlayerPrivateGStreamer::fillTimerFired(Timer<MediaPlayerPrivateGStreamer>*)
821692e5dbf12901edacf14812a6fae25462920af42Steve Block{
822692e5dbf12901edacf14812a6fae25462920af42Steve Block    GstQuery* query = gst_query_new_buffering(GST_FORMAT_PERCENT);
823692e5dbf12901edacf14812a6fae25462920af42Steve Block
824692e5dbf12901edacf14812a6fae25462920af42Steve Block    if (!gst_element_query(m_playBin, query)) {
825692e5dbf12901edacf14812a6fae25462920af42Steve Block        gst_query_unref(query);
826dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return;
827692e5dbf12901edacf14812a6fae25462920af42Steve Block    }
828692e5dbf12901edacf14812a6fae25462920af42Steve Block
829692e5dbf12901edacf14812a6fae25462920af42Steve Block    gint64 start, stop;
830dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    gdouble fillStatus = 100.0;
831692e5dbf12901edacf14812a6fae25462920af42Steve Block
832692e5dbf12901edacf14812a6fae25462920af42Steve Block    gst_query_parse_buffering_range(query, 0, &start, &stop, 0);
833692e5dbf12901edacf14812a6fae25462920af42Steve Block    gst_query_unref(query);
834692e5dbf12901edacf14812a6fae25462920af42Steve Block
835692e5dbf12901edacf14812a6fae25462920af42Steve Block    if (stop != -1)
836dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        fillStatus = 100.0 * stop / GST_FORMAT_PERCENT_MAX;
837692e5dbf12901edacf14812a6fae25462920af42Steve Block
838dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    LOG_VERBOSE(Media, "[Buffering] Download buffer filled up to %f%%", fillStatus);
839692e5dbf12901edacf14812a6fae25462920af42Steve Block
840692e5dbf12901edacf14812a6fae25462920af42Steve Block    if (!m_mediaDuration)
841692e5dbf12901edacf14812a6fae25462920af42Steve Block        durationChanged();
842692e5dbf12901edacf14812a6fae25462920af42Steve Block
843692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Update maxTimeLoaded only if the media duration is
844692e5dbf12901edacf14812a6fae25462920af42Steve Block    // available. Otherwise we can't compute it.
845692e5dbf12901edacf14812a6fae25462920af42Steve Block    if (m_mediaDuration) {
846dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (fillStatus == 100.0)
847dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            m_maxTimeLoaded = m_mediaDuration;
848dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        else
849dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            m_maxTimeLoaded = static_cast<float>((fillStatus * m_mediaDuration) / 100.0);
850dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        LOG_VERBOSE(Media, "[Buffering] Updated maxTimeLoaded: %f", m_maxTimeLoaded);
851692e5dbf12901edacf14812a6fae25462920af42Steve Block    }
852692e5dbf12901edacf14812a6fae25462920af42Steve Block
853dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (fillStatus != 100.0) {
854692e5dbf12901edacf14812a6fae25462920af42Steve Block        updateStates();
855dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return;
856692e5dbf12901edacf14812a6fae25462920af42Steve Block    }
857692e5dbf12901edacf14812a6fae25462920af42Steve Block
858692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Media is now fully loaded. It will play even if network
859692e5dbf12901edacf14812a6fae25462920af42Steve Block    // connection is cut. Buffering is done, remove the fill source
860692e5dbf12901edacf14812a6fae25462920af42Steve Block    // from the main loop.
861dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    m_fillTimer.stop();
862692e5dbf12901edacf14812a6fae25462920af42Steve Block    m_startedBuffering = false;
863692e5dbf12901edacf14812a6fae25462920af42Steve Block    updateStates();
864692e5dbf12901edacf14812a6fae25462920af42Steve Block}
865692e5dbf12901edacf14812a6fae25462920af42Steve Block
866dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockfloat MediaPlayerPrivateGStreamer::maxTimeSeekable() const
8678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
868231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (m_errorOccured)
8695af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        return 0.0f;
870231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
8718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG_VERBOSE(Media, "maxTimeSeekable");
8728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // infinite duration means live stream
873692e5dbf12901edacf14812a6fae25462920af42Steve Block    if (isinf(duration()))
8745af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        return 0.0f;
875692e5dbf12901edacf14812a6fae25462920af42Steve Block
876e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    return duration();
8778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
879dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockfloat MediaPlayerPrivateGStreamer::maxTimeLoaded() const
8808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
881231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (m_errorOccured)
8825af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        return 0.0f;
883231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
884692e5dbf12901edacf14812a6fae25462920af42Steve Block    float loaded = m_maxTimeLoaded;
885dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (!loaded && !m_fillTimer.isActive())
886692e5dbf12901edacf14812a6fae25462920af42Steve Block        loaded = duration();
887692e5dbf12901edacf14812a6fae25462920af42Steve Block    LOG_VERBOSE(Media, "maxTimeLoaded: %f", loaded);
888692e5dbf12901edacf14812a6fae25462920af42Steve Block    return loaded;
8898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
891dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockunsigned MediaPlayerPrivateGStreamer::bytesLoaded() const
8928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
893692e5dbf12901edacf14812a6fae25462920af42Steve Block    if (!m_playBin)
8948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
895231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
896692e5dbf12901edacf14812a6fae25462920af42Steve Block    if (!m_mediaDuration)
897692e5dbf12901edacf14812a6fae25462920af42Steve Block        return 0;
898692e5dbf12901edacf14812a6fae25462920af42Steve Block
899692e5dbf12901edacf14812a6fae25462920af42Steve Block    unsigned loaded = totalBytes() * maxTimeLoaded() / m_mediaDuration;
900692e5dbf12901edacf14812a6fae25462920af42Steve Block    LOG_VERBOSE(Media, "bytesLoaded: %d", loaded);
901692e5dbf12901edacf14812a6fae25462920af42Steve Block    return loaded;
9028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
904dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockunsigned MediaPlayerPrivateGStreamer::totalBytes() const
9058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
906231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (!m_source)
9078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
9088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
909231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (m_errorOccured)
9108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
9118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
912231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    GstFormat fmt = GST_FORMAT_BYTES;
913231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    gint64 length = 0;
914cad810f21b803229eb11403f9209855525a25d57Steve Block    if (gst_element_query_duration(m_source, &fmt, &length)) {
915cad810f21b803229eb11403f9209855525a25d57Steve Block        LOG_VERBOSE(Media, "totalBytes %" G_GINT64_FORMAT, length);
916cad810f21b803229eb11403f9209855525a25d57Steve Block        return static_cast<unsigned>(length);
917cad810f21b803229eb11403f9209855525a25d57Steve Block    }
918cad810f21b803229eb11403f9209855525a25d57Steve Block
919cad810f21b803229eb11403f9209855525a25d57Steve Block    // Fall back to querying the source pads manually.
920cad810f21b803229eb11403f9209855525a25d57Steve Block    // See also https://bugzilla.gnome.org/show_bug.cgi?id=638749
921cad810f21b803229eb11403f9209855525a25d57Steve Block    GstIterator* iter = gst_element_iterate_src_pads(m_source);
922cad810f21b803229eb11403f9209855525a25d57Steve Block    bool done = false;
923cad810f21b803229eb11403f9209855525a25d57Steve Block    while (!done) {
924cad810f21b803229eb11403f9209855525a25d57Steve Block        gpointer data;
925cad810f21b803229eb11403f9209855525a25d57Steve Block
926cad810f21b803229eb11403f9209855525a25d57Steve Block        switch (gst_iterator_next(iter, &data)) {
927cad810f21b803229eb11403f9209855525a25d57Steve Block        case GST_ITERATOR_OK: {
928cad810f21b803229eb11403f9209855525a25d57Steve Block            GstPad* pad = GST_PAD_CAST(data);
929cad810f21b803229eb11403f9209855525a25d57Steve Block            gint64 padLength = 0;
930cad810f21b803229eb11403f9209855525a25d57Steve Block            if (gst_pad_query_duration(pad, &fmt, &padLength)
931cad810f21b803229eb11403f9209855525a25d57Steve Block                && padLength > length)
932cad810f21b803229eb11403f9209855525a25d57Steve Block                length = padLength;
933cad810f21b803229eb11403f9209855525a25d57Steve Block            gst_object_unref(pad);
934cad810f21b803229eb11403f9209855525a25d57Steve Block            break;
935cad810f21b803229eb11403f9209855525a25d57Steve Block        }
936cad810f21b803229eb11403f9209855525a25d57Steve Block        case GST_ITERATOR_RESYNC:
937cad810f21b803229eb11403f9209855525a25d57Steve Block            gst_iterator_resync(iter);
938cad810f21b803229eb11403f9209855525a25d57Steve Block            break;
939cad810f21b803229eb11403f9209855525a25d57Steve Block        case GST_ITERATOR_ERROR:
940cad810f21b803229eb11403f9209855525a25d57Steve Block            // Fall through.
941cad810f21b803229eb11403f9209855525a25d57Steve Block        case GST_ITERATOR_DONE:
942cad810f21b803229eb11403f9209855525a25d57Steve Block            done = true;
943cad810f21b803229eb11403f9209855525a25d57Steve Block            break;
944cad810f21b803229eb11403f9209855525a25d57Steve Block        }
945cad810f21b803229eb11403f9209855525a25d57Steve Block    }
946cad810f21b803229eb11403f9209855525a25d57Steve Block    gst_iterator_free(iter);
947cad810f21b803229eb11403f9209855525a25d57Steve Block
948692e5dbf12901edacf14812a6fae25462920af42Steve Block    LOG_VERBOSE(Media, "totalBytes %" G_GINT64_FORMAT, length);
9498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9505af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    return static_cast<unsigned>(length);
9518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochunsigned MediaPlayerPrivateGStreamer::decodedFrameCount() const
9542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
9552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    guint64 decodedFrames = 0;
9562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (m_fpsSink)
9572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        g_object_get(m_fpsSink, "frames-rendered", &decodedFrames, NULL);
9582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return static_cast<unsigned>(decodedFrames);
9592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
9602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochunsigned MediaPlayerPrivateGStreamer::droppedFrameCount() const
9622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
9632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    guint64 framesDropped = 0;
9642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (m_fpsSink)
9652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        g_object_get(m_fpsSink, "frames-dropped", &framesDropped, NULL);
9662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return static_cast<unsigned>(framesDropped);
9672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
9682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochunsigned MediaPlayerPrivateGStreamer::audioDecodedByteCount() const
9702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
9712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    GstQuery* query = gst_query_new_position(GST_FORMAT_BYTES);
9722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    gint64 position = 0;
9732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (m_webkitAudioSink && gst_element_query(m_webkitAudioSink, query))
9752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        gst_query_parse_position(query, 0, &position);
9762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    gst_query_unref(query);
9782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return static_cast<unsigned>(position);
9792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
9802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochunsigned MediaPlayerPrivateGStreamer::videoDecodedByteCount() const
9822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
9832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    GstQuery* query = gst_query_new_position(GST_FORMAT_BYTES);
9842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    gint64 position = 0;
9852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (gst_element_query(m_webkitVideoSink, query))
9872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        gst_query_parse_position(query, 0, &position);
9882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    gst_query_unref(query);
9902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return static_cast<unsigned>(position);
9912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
9922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid MediaPlayerPrivateGStreamer::updateAudioSink()
9942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
9952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!m_playBin)
9962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return;
9972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    GOwnPtr<GstElement> element;
9992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
10002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    g_object_get(m_playBin, "audio-sink", &element.outPtr(), NULL);
10012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    gst_object_replace(reinterpret_cast<GstObject**>(&m_webkitAudioSink),
10022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                       reinterpret_cast<GstObject*>(element.get()));
10032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
10042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
10052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
10062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid MediaPlayerPrivateGStreamer::sourceChanged()
10072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
10082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    GOwnPtr<GstElement> element;
10092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
10102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    g_object_get(m_playBin, "source", &element.outPtr(), NULL);
10112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    gst_object_replace(reinterpret_cast<GstObject**>(&m_source),
10122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                       reinterpret_cast<GstObject*>(element.get()));
10132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
10142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (WEBKIT_IS_WEB_SRC(element.get())) {
10152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        Frame* frame = m_player->frameView() ? m_player->frameView()->frame() : 0;
10162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
10172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (frame)
10182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            webKitWebSrcSetFrame(WEBKIT_WEB_SRC(element.get()), frame);
10192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
10202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
10212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1022dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid MediaPlayerPrivateGStreamer::cancelLoad()
10238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1024cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    if (m_networkState < MediaPlayer::Loading || m_networkState == MediaPlayer::Loaded)
1025cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        return;
1026cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
1027cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    if (m_playBin)
1028cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        gst_element_set_state(m_playBin, GST_STATE_NULL);
10298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
10308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1031dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid MediaPlayerPrivateGStreamer::updateStates()
10328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1033231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (!m_playBin)
1034231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return;
1035231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
1036231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (m_errorOccured)
1037231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return;
1038231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
10398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    MediaPlayer::NetworkState oldNetworkState = m_networkState;
10408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    MediaPlayer::ReadyState oldReadyState = m_readyState;
10418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    GstState state;
10428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    GstState pending;
10438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    GstStateChangeReturn ret = gst_element_get_state(m_playBin,
10458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        &state, &pending, 250 * GST_NSECOND);
10468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1047231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    bool shouldUpdateAfterSeek = false;
10480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    switch (ret) {
10498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    case GST_STATE_CHANGE_SUCCESS:
10508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        LOG_VERBOSE(Media, "State: %s, pending: %s",
10518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            gst_element_state_get_name(state),
10528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            gst_element_state_get_name(pending));
10538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1054d0825bca7fe65beaee391d30da42e937db621564Steve Block        m_resetPipeline = state <= GST_STATE_READY;
1055d0825bca7fe65beaee391d30da42e937db621564Steve Block
1056dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        // Try to figure out ready and network states.
1057dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (state == GST_STATE_READY) {
10585abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick            m_readyState = MediaPlayer::HaveMetadata;
1059dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            m_networkState = MediaPlayer::Empty;
10605abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick            // Cache the duration without emiting the durationchange
10615abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick            // event because it's taken care of by the media element
10625abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick            // in this precise case.
10635abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick            cacheDuration();
1064dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        } else if (maxTimeLoaded() == duration()) {
1065dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            m_networkState = MediaPlayer::Loaded;
10668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            m_readyState = MediaPlayer::HaveEnoughData;
1067dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        } else {
1068dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            m_readyState = currentTime() < maxTimeLoaded() ? MediaPlayer::HaveFutureData : MediaPlayer::HaveCurrentData;
1069dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            m_networkState = MediaPlayer::Loading;
1070dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
10710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1072dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (m_buffering && state != GST_STATE_READY) {
1073dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            m_readyState = MediaPlayer::HaveCurrentData;
1074dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            m_networkState = MediaPlayer::Loading;
1075dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
1076dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1077dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        // Now let's try to get the states in more detail using
1078dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        // information from GStreamer, while we sync states where
1079dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        // needed.
1080dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (state == GST_STATE_PAUSED) {
10812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            if (!m_webkitAudioSink)
10822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                updateAudioSink();
1083dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if (m_buffering && m_bufferingPercentage == 100) {
1084dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                m_buffering = false;
1085dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                m_bufferingPercentage = 0;
1086dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                m_readyState = MediaPlayer::HaveEnoughData;
1087dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1088dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                LOG_VERBOSE(Media, "[Buffering] Complete.");
1089dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1090dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                if (!m_paused) {
1091dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    LOG_VERBOSE(Media, "[Buffering] Restarting playback.");
1092dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    gst_element_set_state(m_playBin, GST_STATE_PLAYING);
1093dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                }
1094dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            } else if (!m_buffering && (currentTime() < duration())) {
1095dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                m_paused = true;
1096dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            }
1097dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        } else if (state == GST_STATE_PLAYING) {
1098cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            m_readyState = MediaPlayer::HaveEnoughData;
1099231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            m_paused = false;
1100dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1101dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if (m_buffering) {
1102dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                m_readyState = MediaPlayer::HaveCurrentData;
1103dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                m_networkState = MediaPlayer::Loading;
1104dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1105dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                LOG_VERBOSE(Media, "[Buffering] Pausing stream for buffering.");
1106dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1107dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                gst_element_set_state(m_playBin, GST_STATE_PAUSED);
1108dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            }
1109cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        } else
1110231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            m_paused = true;
1111231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
1112692e5dbf12901edacf14812a6fae25462920af42Steve Block        // Is on-disk buffering in progress?
1113dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (m_fillTimer.isActive())
1114692e5dbf12901edacf14812a6fae25462920af42Steve Block            m_networkState = MediaPlayer::Loading;
1115692e5dbf12901edacf14812a6fae25462920af42Steve Block
1116643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        if (m_changingRate) {
1117643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            m_player->rateChanged();
1118643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            m_changingRate = false;
1119643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        }
1120643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
1121231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (m_seeking) {
1122231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            shouldUpdateAfterSeek = true;
1123231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            m_seeking = false;
1124231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        }
1125231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
11268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        break;
11278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    case GST_STATE_CHANGE_ASYNC:
11288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        LOG_VERBOSE(Media, "Async: State: %s, pending: %s",
11298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            gst_element_state_get_name(state),
11308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            gst_element_state_get_name(pending));
11318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Change in progress
1132692e5dbf12901edacf14812a6fae25462920af42Steve Block
1133e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        if (!m_isStreaming && !m_buffering)
1134692e5dbf12901edacf14812a6fae25462920af42Steve Block            return;
1135692e5dbf12901edacf14812a6fae25462920af42Steve Block
1136692e5dbf12901edacf14812a6fae25462920af42Steve Block        if (m_seeking) {
1137692e5dbf12901edacf14812a6fae25462920af42Steve Block            shouldUpdateAfterSeek = true;
1138692e5dbf12901edacf14812a6fae25462920af42Steve Block            m_seeking = false;
1139692e5dbf12901edacf14812a6fae25462920af42Steve Block        }
1140692e5dbf12901edacf14812a6fae25462920af42Steve Block        break;
1141231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    case GST_STATE_CHANGE_FAILURE:
1142231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        LOG_VERBOSE(Media, "Failure: State: %s, pending: %s",
1143231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            gst_element_state_get_name(state),
1144231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            gst_element_state_get_name(pending));
1145231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        // Change failed
1146231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return;
11478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    case GST_STATE_CHANGE_NO_PREROLL:
11488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        LOG_VERBOSE(Media, "No preroll: State: %s, pending: %s",
11498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            gst_element_state_get_name(state),
11508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            gst_element_state_get_name(pending));
1151231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
1152cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        if (state == GST_STATE_READY)
1153cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            m_readyState = MediaPlayer::HaveNothing;
1154692e5dbf12901edacf14812a6fae25462920af42Steve Block        else if (state == GST_STATE_PAUSED) {
1155692e5dbf12901edacf14812a6fae25462920af42Steve Block            m_readyState = MediaPlayer::HaveEnoughData;
1156692e5dbf12901edacf14812a6fae25462920af42Steve Block            m_paused = true;
1157692e5dbf12901edacf14812a6fae25462920af42Steve Block            // Live pipelines go in PAUSED without prerolling.
1158692e5dbf12901edacf14812a6fae25462920af42Steve Block            m_isStreaming = true;
1159dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        } else if (state == GST_STATE_PLAYING)
1160692e5dbf12901edacf14812a6fae25462920af42Steve Block            m_paused = false;
1161692e5dbf12901edacf14812a6fae25462920af42Steve Block
1162692e5dbf12901edacf14812a6fae25462920af42Steve Block        if (m_seeking) {
1163692e5dbf12901edacf14812a6fae25462920af42Steve Block            shouldUpdateAfterSeek = true;
1164692e5dbf12901edacf14812a6fae25462920af42Steve Block            m_seeking = false;
1165dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if (!m_paused)
1166692e5dbf12901edacf14812a6fae25462920af42Steve Block                gst_element_set_state(m_playBin, GST_STATE_PLAYING);
1167dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        } else if (!m_paused)
1168dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            gst_element_set_state(m_playBin, GST_STATE_PLAYING);
11690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
11708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_networkState = MediaPlayer::Loading;
11718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        break;
11728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    default:
11738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        LOG_VERBOSE(Media, "Else : %d", ret);
11748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        break;
11758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
11768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (seeking())
11788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_readyState = MediaPlayer::HaveNothing;
11798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1180231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (shouldUpdateAfterSeek)
1181231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        timeChanged();
1182231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
11838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_networkState != oldNetworkState) {
11848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        LOG_VERBOSE(Media, "Network State Changed from %u to %u",
11858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            oldNetworkState, m_networkState);
11868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_player->networkStateChanged();
11878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
11888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_readyState != oldReadyState) {
11898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        LOG_VERBOSE(Media, "Ready State Changed from %u to %u",
11908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            oldReadyState, m_readyState);
11918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_player->readyStateChanged();
11928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
11938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
11948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1195dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid MediaPlayerPrivateGStreamer::mediaLocationChanged(GstMessage* message)
1196d0825bca7fe65beaee391d30da42e937db621564Steve Block{
1197d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (m_mediaLocations)
1198d0825bca7fe65beaee391d30da42e937db621564Steve Block        gst_structure_free(m_mediaLocations);
1199d0825bca7fe65beaee391d30da42e937db621564Steve Block
1200d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (message->structure) {
1201d0825bca7fe65beaee391d30da42e937db621564Steve Block        // This structure can contain:
1202d0825bca7fe65beaee391d30da42e937db621564Steve Block        // - both a new-location string and embedded locations structure
1203d0825bca7fe65beaee391d30da42e937db621564Steve Block        // - or only a new-location string.
1204d0825bca7fe65beaee391d30da42e937db621564Steve Block        m_mediaLocations = gst_structure_copy(message->structure);
1205d0825bca7fe65beaee391d30da42e937db621564Steve Block        const GValue* locations = gst_structure_get_value(m_mediaLocations, "locations");
1206d0825bca7fe65beaee391d30da42e937db621564Steve Block
1207d0825bca7fe65beaee391d30da42e937db621564Steve Block        if (locations)
1208dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            m_mediaLocationCurrentIndex = static_cast<int>(gst_value_list_get_size(locations)) -1;
1209d0825bca7fe65beaee391d30da42e937db621564Steve Block
1210d0825bca7fe65beaee391d30da42e937db621564Steve Block        loadNextLocation();
1211d0825bca7fe65beaee391d30da42e937db621564Steve Block    }
1212d0825bca7fe65beaee391d30da42e937db621564Steve Block}
1213d0825bca7fe65beaee391d30da42e937db621564Steve Block
1214dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockbool MediaPlayerPrivateGStreamer::loadNextLocation()
1215d0825bca7fe65beaee391d30da42e937db621564Steve Block{
1216d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (!m_mediaLocations)
1217d0825bca7fe65beaee391d30da42e937db621564Steve Block        return false;
1218d0825bca7fe65beaee391d30da42e937db621564Steve Block
1219d0825bca7fe65beaee391d30da42e937db621564Steve Block    const GValue* locations = gst_structure_get_value(m_mediaLocations, "locations");
1220d0825bca7fe65beaee391d30da42e937db621564Steve Block    const gchar* newLocation = 0;
1221d0825bca7fe65beaee391d30da42e937db621564Steve Block
1222d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (!locations) {
1223d0825bca7fe65beaee391d30da42e937db621564Steve Block        // Fallback on new-location string.
1224d0825bca7fe65beaee391d30da42e937db621564Steve Block        newLocation = gst_structure_get_string(m_mediaLocations, "new-location");
1225d0825bca7fe65beaee391d30da42e937db621564Steve Block        if (!newLocation)
1226d0825bca7fe65beaee391d30da42e937db621564Steve Block            return false;
1227d0825bca7fe65beaee391d30da42e937db621564Steve Block    }
1228d0825bca7fe65beaee391d30da42e937db621564Steve Block
1229d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (!newLocation) {
1230d0825bca7fe65beaee391d30da42e937db621564Steve Block        if (m_mediaLocationCurrentIndex < 0) {
1231d0825bca7fe65beaee391d30da42e937db621564Steve Block            m_mediaLocations = 0;
1232d0825bca7fe65beaee391d30da42e937db621564Steve Block            return false;
1233d0825bca7fe65beaee391d30da42e937db621564Steve Block        }
1234d0825bca7fe65beaee391d30da42e937db621564Steve Block
1235d0825bca7fe65beaee391d30da42e937db621564Steve Block        const GValue* location = gst_value_list_get_value(locations,
1236d0825bca7fe65beaee391d30da42e937db621564Steve Block                                                          m_mediaLocationCurrentIndex);
1237d0825bca7fe65beaee391d30da42e937db621564Steve Block        const GstStructure* structure = gst_value_get_structure(location);
1238d0825bca7fe65beaee391d30da42e937db621564Steve Block
1239d0825bca7fe65beaee391d30da42e937db621564Steve Block        if (!structure) {
1240d0825bca7fe65beaee391d30da42e937db621564Steve Block            m_mediaLocationCurrentIndex--;
1241d0825bca7fe65beaee391d30da42e937db621564Steve Block            return false;
1242d0825bca7fe65beaee391d30da42e937db621564Steve Block        }
1243d0825bca7fe65beaee391d30da42e937db621564Steve Block
1244d0825bca7fe65beaee391d30da42e937db621564Steve Block        newLocation = gst_structure_get_string(structure, "new-location");
1245d0825bca7fe65beaee391d30da42e937db621564Steve Block    }
1246d0825bca7fe65beaee391d30da42e937db621564Steve Block
1247d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (newLocation) {
1248d0825bca7fe65beaee391d30da42e937db621564Steve Block        // Found a candidate. new-location is not always an absolute url
1249d0825bca7fe65beaee391d30da42e937db621564Steve Block        // though. We need to take the base of the current url and
1250d0825bca7fe65beaee391d30da42e937db621564Steve Block        // append the value of new-location to it.
1251d0825bca7fe65beaee391d30da42e937db621564Steve Block
1252d0825bca7fe65beaee391d30da42e937db621564Steve Block        gchar* currentLocation = 0;
1253d0825bca7fe65beaee391d30da42e937db621564Steve Block        g_object_get(m_playBin, "uri", &currentLocation, NULL);
1254d0825bca7fe65beaee391d30da42e937db621564Steve Block
1255d0825bca7fe65beaee391d30da42e937db621564Steve Block        KURL currentUrl(KURL(), currentLocation);
1256d0825bca7fe65beaee391d30da42e937db621564Steve Block        g_free(currentLocation);
1257d0825bca7fe65beaee391d30da42e937db621564Steve Block
1258d0825bca7fe65beaee391d30da42e937db621564Steve Block        KURL newUrl;
1259d0825bca7fe65beaee391d30da42e937db621564Steve Block
1260d0825bca7fe65beaee391d30da42e937db621564Steve Block        if (gst_uri_is_valid(newLocation))
1261d0825bca7fe65beaee391d30da42e937db621564Steve Block            newUrl = KURL(KURL(), newLocation);
1262d0825bca7fe65beaee391d30da42e937db621564Steve Block        else
1263d0825bca7fe65beaee391d30da42e937db621564Steve Block            newUrl = KURL(KURL(), currentUrl.baseAsString() + newLocation);
1264d0825bca7fe65beaee391d30da42e937db621564Steve Block
1265d0825bca7fe65beaee391d30da42e937db621564Steve Block        RefPtr<SecurityOrigin> securityOrigin = SecurityOrigin::create(currentUrl);
1266d0825bca7fe65beaee391d30da42e937db621564Steve Block        if (securityOrigin->canRequest(newUrl)) {
1267d0825bca7fe65beaee391d30da42e937db621564Steve Block            LOG_VERBOSE(Media, "New media url: %s", newUrl.string().utf8().data());
1268d0825bca7fe65beaee391d30da42e937db621564Steve Block
1269d0825bca7fe65beaee391d30da42e937db621564Steve Block            // Reset player states.
1270d0825bca7fe65beaee391d30da42e937db621564Steve Block            m_networkState = MediaPlayer::Loading;
1271d0825bca7fe65beaee391d30da42e937db621564Steve Block            m_player->networkStateChanged();
1272d0825bca7fe65beaee391d30da42e937db621564Steve Block            m_readyState = MediaPlayer::HaveNothing;
1273d0825bca7fe65beaee391d30da42e937db621564Steve Block            m_player->readyStateChanged();
1274d0825bca7fe65beaee391d30da42e937db621564Steve Block
1275d0825bca7fe65beaee391d30da42e937db621564Steve Block            // Reset pipeline state.
1276d0825bca7fe65beaee391d30da42e937db621564Steve Block            m_resetPipeline = true;
1277d0825bca7fe65beaee391d30da42e937db621564Steve Block            gst_element_set_state(m_playBin, GST_STATE_READY);
1278d0825bca7fe65beaee391d30da42e937db621564Steve Block
1279d0825bca7fe65beaee391d30da42e937db621564Steve Block            GstState state;
1280d0825bca7fe65beaee391d30da42e937db621564Steve Block            gst_element_get_state(m_playBin, &state, 0, 0);
1281d0825bca7fe65beaee391d30da42e937db621564Steve Block            if (state <= GST_STATE_READY) {
1282d0825bca7fe65beaee391d30da42e937db621564Steve Block                // Set the new uri and start playing.
1283d0825bca7fe65beaee391d30da42e937db621564Steve Block                g_object_set(m_playBin, "uri", newUrl.string().utf8().data(), NULL);
1284d0825bca7fe65beaee391d30da42e937db621564Steve Block                gst_element_set_state(m_playBin, GST_STATE_PLAYING);
1285d0825bca7fe65beaee391d30da42e937db621564Steve Block                return true;
1286d0825bca7fe65beaee391d30da42e937db621564Steve Block            }
1287d0825bca7fe65beaee391d30da42e937db621564Steve Block        }
1288d0825bca7fe65beaee391d30da42e937db621564Steve Block    }
1289d0825bca7fe65beaee391d30da42e937db621564Steve Block    m_mediaLocationCurrentIndex--;
1290d0825bca7fe65beaee391d30da42e937db621564Steve Block    return false;
1291d0825bca7fe65beaee391d30da42e937db621564Steve Block
1292d0825bca7fe65beaee391d30da42e937db621564Steve Block}
1293d0825bca7fe65beaee391d30da42e937db621564Steve Block
1294dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid MediaPlayerPrivateGStreamer::loadStateChanged()
12958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
12968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    updateStates();
12978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
12988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1299dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid MediaPlayerPrivateGStreamer::sizeChanged()
13008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
13018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    notImplemented();
13028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
13038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1304dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid MediaPlayerPrivateGStreamer::timeChanged()
13058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
13068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    updateStates();
13078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_player->timeChanged();
13088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
13098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1310dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid MediaPlayerPrivateGStreamer::didEnd()
13118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1312d0825bca7fe65beaee391d30da42e937db621564Steve Block    // EOS was reached but in case of reverse playback the position is
1313d0825bca7fe65beaee391d30da42e937db621564Steve Block    // not always 0. So to not confuse the HTMLMediaElement we
1314d0825bca7fe65beaee391d30da42e937db621564Steve Block    // synchronize position and duration values.
1315d0825bca7fe65beaee391d30da42e937db621564Steve Block    float now = currentTime();
1316692e5dbf12901edacf14812a6fae25462920af42Steve Block    if (now > 0) {
1317d0825bca7fe65beaee391d30da42e937db621564Steve Block        m_mediaDuration = now;
131821939df44de1705786c545cd1bf519d47250322dBen Murdoch        m_mediaDurationKnown = true;
1319692e5dbf12901edacf14812a6fae25462920af42Steve Block        m_player->durationChanged();
1320692e5dbf12901edacf14812a6fae25462920af42Steve Block    }
1321692e5dbf12901edacf14812a6fae25462920af42Steve Block
1322d0825bca7fe65beaee391d30da42e937db621564Steve Block    gst_element_set_state(m_playBin, GST_STATE_PAUSED);
1323d0825bca7fe65beaee391d30da42e937db621564Steve Block
1324d0825bca7fe65beaee391d30da42e937db621564Steve Block    timeChanged();
13258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
13268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
13275abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrickvoid MediaPlayerPrivateGStreamer::cacheDuration()
13288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1329d0825bca7fe65beaee391d30da42e937db621564Steve Block    // Reset cached media duration
1330d0825bca7fe65beaee391d30da42e937db621564Steve Block    m_mediaDuration = 0;
1331d0825bca7fe65beaee391d30da42e937db621564Steve Block
1332d0825bca7fe65beaee391d30da42e937db621564Steve Block    // And re-cache it if possible.
1333dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    GstState state;
1334dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    gst_element_get_state(m_playBin, &state, 0, 0);
1335d0825bca7fe65beaee391d30da42e937db621564Steve Block    float newDuration = duration();
1336dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1337dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (state <= GST_STATE_READY) {
1338dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        // Don't set m_mediaDurationKnown yet if the pipeline is not
1339dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        // paused. This allows duration() query to fail at least once
1340dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        // before playback starts and duration becomes known.
1341dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (!isinf(newDuration))
1342dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            m_mediaDuration = newDuration;
1343dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    } else {
1344dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        m_mediaDurationKnown = !isinf(newDuration);
1345dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (m_mediaDurationKnown)
1346dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            m_mediaDuration = newDuration;
1347dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
1348dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1349d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (!isinf(newDuration))
1350d0825bca7fe65beaee391d30da42e937db621564Steve Block        m_mediaDuration = newDuration;
13515abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick}
1352d0825bca7fe65beaee391d30da42e937db621564Steve Block
13535abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrickvoid MediaPlayerPrivateGStreamer::durationChanged()
13545abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick{
13555abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    float previousDuration = m_mediaDuration;
13565abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick
13575abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    cacheDuration();
1358f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    // Avoid emiting durationchanged in the case where the previous
1359f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    // duration was 0 because that case is already handled by the
1360f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    // HTMLMediaElement.
1361f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (previousDuration && m_mediaDuration != previousDuration)
13625abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick        m_player->durationChanged();
13638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
13648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1365dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockbool MediaPlayerPrivateGStreamer::supportsMuting() const
13665e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block{
13675e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    return true;
13685e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block}
13695e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block
1370dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid MediaPlayerPrivateGStreamer::setMuted(bool muted)
13715e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block{
13725e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    if (!m_playBin)
13735e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        return;
13745e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block
13755e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    g_object_set(m_playBin, "mute", muted, NULL);
13765e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block}
13775e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block
1378f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid MediaPlayerPrivateGStreamer::notifyPlayerOfMute()
13795e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block{
1380f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    m_muteTimerHandler = 0;
1381f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
1382f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!m_player || !m_playBin)
1383f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        return;
1384f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
13855e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    gboolean muted;
13865e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    g_object_get(m_playBin, "mute", &muted, NULL);
13875e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    m_player->muteChanged(static_cast<bool>(muted));
13885e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block}
13895e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block
1390dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid MediaPlayerPrivateGStreamer::muteChanged()
13915e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block{
1392f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (m_muteTimerHandler)
1393f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        g_source_remove(m_muteTimerHandler);
1394f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    m_muteTimerHandler = g_timeout_add(0, reinterpret_cast<GSourceFunc>(mediaPlayerPrivateMuteChangeTimeoutCallback), this);
13955e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block}
13965e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block
1397dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid MediaPlayerPrivateGStreamer::loadingFailed(MediaPlayer::NetworkState error)
13988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1399231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    m_errorOccured = true;
1400231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (m_networkState != error) {
1401231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        m_networkState = error;
14028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_player->networkStateChanged();
14038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
14048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (m_readyState != MediaPlayer::HaveNothing) {
14058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_readyState = MediaPlayer::HaveNothing;
14068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_player->readyStateChanged();
14078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
14088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
14098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1410dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid MediaPlayerPrivateGStreamer::setSize(const IntSize& size)
14118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
14128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    m_size = size;
14138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
14148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1415dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid MediaPlayerPrivateGStreamer::setVisible(bool visible)
14168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
14178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
14188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
14192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
14202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid MediaPlayerPrivateGStreamer::triggerRepaint(GstBuffer* buffer)
14218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
14222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    g_return_if_fail(GST_IS_BUFFER(buffer));
14232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    gst_buffer_replace(&m_buffer, buffer);
14248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_player->repaint();
14258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
14268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1427dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid MediaPlayerPrivateGStreamer::paint(GraphicsContext* context, const IntRect& rect)
14288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
14298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (context->paintingDisabled())
14308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
14318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1432cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    if (!m_player->visible())
14338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
14342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1435cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    if (!m_buffer)
1436cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        return;
1437cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
1438dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    RefPtr<ImageGStreamer> gstImage = ImageGStreamer::createImage(m_buffer);
1439dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (!gstImage)
1440dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return;
1441cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
1442a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    context->drawImage(reinterpret_cast<Image*>(gstImage->image().get()), ColorSpaceSRGB,
1443dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                       rect, CompositeCopy, false);
14448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
14458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1446231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockstatic HashSet<String> mimeTypeCache()
1447231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
1448231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
1449d0825bca7fe65beaee391d30da42e937db621564Steve Block    doGstInit();
1450231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
1451dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    DEFINE_STATIC_LOCAL(HashSet<String>, cache, ());
1452231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    static bool typeListInitialized = false;
1453231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
1454231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (!typeListInitialized) {
1455643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        // Build a whitelist of mime-types known to be supported by
1456643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        // GStreamer.
1457643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        HashSet<String> handledApplicationSubtypes;
1458643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        handledApplicationSubtypes.add(String("ogg"));
1459643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        handledApplicationSubtypes.add(String("vnd.rn-realmedia"));
1460643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        handledApplicationSubtypes.add(String("x-pn-realaudio"));
1461231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
1462231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        GList* factories = gst_type_find_factory_get_list();
1463231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        for (GList* iterator = factories; iterator; iterator = iterator->next) {
1464231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            GstTypeFindFactory* factory = GST_TYPE_FIND_FACTORY(iterator->data);
1465231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            GstCaps* caps = gst_type_find_factory_get_caps(factory);
14665ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            gchar** extensions;
1467231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
1468643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            if (!caps)
1469643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                continue;
1470643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
1471643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            for (guint structureIndex = 0; structureIndex < gst_caps_get_size(caps); structureIndex++) {
1472643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                GstStructure* structure = gst_caps_get_structure(caps, structureIndex);
1473643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                const gchar* name = gst_structure_get_name(structure);
1474643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                bool cached = false;
1475643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
1476643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                // These formats are supported by GStreamer, but not
1477643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                // correctly advertised.
14782fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                if (g_str_equal(name, "video/x-h264")) {
1479231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                    cache.add(String("video/mp4"));
14802fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                    cached = true;
14812fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                }
14822fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
14832fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                if (g_str_equal(name, "audio/x-m4a")) {
1484231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                    cache.add(String("audio/aac"));
14850617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                    cache.add(String("audio/mp4"));
14862fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                    cache.add(String("audio/x-m4a"));
1487643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                    cached = true;
1488231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                }
1489231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
1490cad810f21b803229eb11403f9209855525a25d57Steve Block                if (g_str_equal(name, "application/x-3gp")) {
1491cad810f21b803229eb11403f9209855525a25d57Steve Block                    cache.add(String("audio/3gpp"));
1492cad810f21b803229eb11403f9209855525a25d57Steve Block                    cache.add(String("video/3gpp"));
1493cad810f21b803229eb11403f9209855525a25d57Steve Block                    cache.add(String("application/x-3gp"));
1494cad810f21b803229eb11403f9209855525a25d57Steve Block                    cached = true;
1495cad810f21b803229eb11403f9209855525a25d57Steve Block                }
1496cad810f21b803229eb11403f9209855525a25d57Steve Block
1497643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                if (g_str_equal(name, "video/x-theora")) {
1498231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                    cache.add(String("video/ogg"));
1499643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                    cached = true;
1500643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                }
1501231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
1502643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                if (g_str_equal(name, "audio/x-vorbis")) {
1503643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                    cache.add(String("audio/ogg"));
15045abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick                    cache.add(String("audio/x-vorbis+ogg"));
1505643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                    cached = true;
1506643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                }
1507231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
1508643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                if (g_str_equal(name, "audio/x-wav")) {
1509643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                    cache.add(String("audio/wav"));
15100617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                    cache.add(String("audio/x-wav"));
1511643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                    cached = true;
1512643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                }
1513231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
1514643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                if (g_str_equal(name, "audio/mpeg")) {
1515643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                    cache.add(String(name));
15160617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                    cache.add(String("audio/x-mpeg"));
1517643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                    cached = true;
1518643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
1519643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                    // This is what we are handling:
1520643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                    // mpegversion=(int)1, layer=(int)[ 1, 3 ]
1521643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                    gint mpegVersion = 0;
1522643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                    if (gst_structure_get_int(structure, "mpegversion", &mpegVersion) && (mpegVersion == 1)) {
1523643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                        const GValue* layer = gst_structure_get_value(structure, "layer");
1524643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                        if (G_VALUE_TYPE(layer) == GST_TYPE_INT_RANGE) {
1525643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                            gint minLayer = gst_value_get_int_range_min(layer);
1526643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                            gint maxLayer = gst_value_get_int_range_max(layer);
1527d0825bca7fe65beaee391d30da42e937db621564Steve Block                            if (minLayer <= 1 && 1 <= maxLayer)
1528231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                                cache.add(String("audio/mp1"));
1529d0825bca7fe65beaee391d30da42e937db621564Steve Block                            if (minLayer <= 2 && 2 <= maxLayer)
1530231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                                cache.add(String("audio/mp2"));
15310617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                            if (minLayer <= 3 && 3 <= maxLayer) {
15320617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                                cache.add(String("audio/x-mp3"));
1533231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                                cache.add(String("audio/mp3"));
15340617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                            }
1535231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                        }
1536231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                    }
1537643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                }
1538231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
1539643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                if (!cached) {
1540643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                    // GStreamer plugins can be capable of supporting
1541643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                    // types which WebKit supports by default. In that
1542643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                    // case, we should not consider these types
1543643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                    // supportable by GStreamer.  Examples of what
1544643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                    // GStreamer can support but should not be added:
1545643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                    // text/plain, text/html, image/jpeg,
1546643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                    // application/xml
1547643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                    gchar** mimetype = g_strsplit(name, "/", 2);
1548643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                    if (g_str_equal(mimetype[0], "audio")
1549643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                        || g_str_equal(mimetype[0], "video")
1550643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                        || (g_str_equal(mimetype[0], "application")
1551643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                            && handledApplicationSubtypes.contains(String(mimetype[1]))))
1552643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                        cache.add(String(name));
15532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    else if (g_str_equal(name, "application/x-hls"))
15542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                        cache.add(String("application/vnd.apple.mpegurl"));
15552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1556643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
1557643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                    g_strfreev(mimetype);
1558231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                }
15595ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
15605ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                // As a last resort try some special cases depending
15615ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                // on the file extensions registered with the typefind
15625ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                // factory.
15635ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                if (!cached && (extensions = gst_type_find_factory_get_extensions(factory))) {
15645ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                    for (int index = 0; extensions[index]; index++) {
15655ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                        if (g_str_equal(extensions[index], "m4v"))
15665ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                            cache.add(String("video/x-m4v"));
15672fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
15682fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                        // Workaround for
15692fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                        // https://bugzilla.gnome.org/show_bug.cgi?id=640709.
15702fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                        // typefindfunctions <= 0.10.32 doesn't
15712fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                        // register the H264 typefinder correctly so
15722fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                        // as a workaround we check the registered
15732fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                        // file extensions for it.
15742fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                        if (g_str_equal(extensions[index], "h264"))
15752fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                            cache.add(String("video/mp4"));
15765ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                    }
15775ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                }
1578231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            }
1579231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        }
1580231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
1581231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        gst_plugin_feature_list_free(factories);
1582231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        typeListInitialized = true;
1583231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
1584231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
1585231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return cache;
1586231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
1587231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
1588dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid MediaPlayerPrivateGStreamer::getSupportedTypes(HashSet<String>& types)
15898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1590231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    types = mimeTypeCache();
15918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
15928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1593dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockMediaPlayer::SupportsType MediaPlayerPrivateGStreamer::supportsType(const String& type, const String& codecs)
15948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
1595231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (type.isNull() || type.isEmpty())
1596231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return MediaPlayer::IsNotSupported;
1597231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
1598231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // spec says we should not return "probably" if the codecs string is empty
1599231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (mimeTypeCache().contains(type))
1600231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return codecs.isEmpty() ? MediaPlayer::MayBeSupported : MediaPlayer::IsSupported;
1601231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return MediaPlayer::IsNotSupported;
1602231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
1603231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
1604dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockbool MediaPlayerPrivateGStreamer::hasSingleSecurityOrigin() const
1605231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
1606231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return true;
1607231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
1608231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
1609dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockbool MediaPlayerPrivateGStreamer::supportsFullscreen() const
1610231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
1611f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
1612f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    // See <rdar://problem/7389945>
1613f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    return false;
1614f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#else
1615231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return true;
1616f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#endif
16178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
16188f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1619e78cbe89e6f337f2f1fe40315be88f742b547151Steve BlockPlatformMedia MediaPlayerPrivateGStreamer::platformMedia() const
1620e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block{
1621e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block    PlatformMedia p;
1622e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block    p.type = PlatformMedia::GStreamerGWorldType;
1623e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block    p.media.gstreamerGWorld = m_gstGWorld.get();
1624e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block    return p;
1625e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block}
1626e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block
1627dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid MediaPlayerPrivateGStreamer::setPreload(MediaPlayer::Preload preload)
1628692e5dbf12901edacf14812a6fae25462920af42Steve Block{
1629692e5dbf12901edacf14812a6fae25462920af42Steve Block    ASSERT(m_playBin);
1630692e5dbf12901edacf14812a6fae25462920af42Steve Block
1631dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    m_preload = preload;
1632dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1633692e5dbf12901edacf14812a6fae25462920af42Steve Block    GstPlayFlags flags;
1634692e5dbf12901edacf14812a6fae25462920af42Steve Block    g_object_get(m_playBin, "flags", &flags, NULL);
1635dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (preload == MediaPlayer::None)
1636692e5dbf12901edacf14812a6fae25462920af42Steve Block        g_object_set(m_playBin, "flags", flags & ~GST_PLAY_FLAG_DOWNLOAD, NULL);
1637dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    else
1638dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        g_object_set(m_playBin, "flags", flags | GST_PLAY_FLAG_DOWNLOAD, NULL);
1639dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1640dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (m_delayingLoad && m_preload != MediaPlayer::None) {
1641dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        m_delayingLoad = false;
1642dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        commitLoad();
1643dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
1644692e5dbf12901edacf14812a6fae25462920af42Steve Block}
1645692e5dbf12901edacf14812a6fae25462920af42Steve Block
1646dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid MediaPlayerPrivateGStreamer::createGSTPlayBin()
16478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
16488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(!m_playBin);
1649231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    m_playBin = gst_element_factory_make("playbin2", "play");
16508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1651e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    m_gstGWorld = GStreamerGWorld::createGWorld(m_playBin);
1652e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block
16538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(m_playBin));
16548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    gst_bus_add_signal_watch(bus);
1655cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    g_signal_connect(bus, "message", G_CALLBACK(mediaPlayerPrivateMessageCallback), this);
16568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    gst_object_unref(bus);
16578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
165881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    g_object_set(m_playBin, "mute", m_player->muted(), NULL);
1659f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
1660d0825bca7fe65beaee391d30da42e937db621564Steve Block    g_signal_connect(m_playBin, "notify::volume", G_CALLBACK(mediaPlayerPrivateVolumeChangedCallback), this);
1661d0825bca7fe65beaee391d30da42e937db621564Steve Block    g_signal_connect(m_playBin, "notify::source", G_CALLBACK(mediaPlayerPrivateSourceChangedCallback), this);
16625e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    g_signal_connect(m_playBin, "notify::mute", G_CALLBACK(mediaPlayerPrivateMuteChangedCallback), this);
16632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    g_signal_connect(m_playBin, "video-changed", G_CALLBACK(mediaPlayerPrivateVideoChangedCallback), this);
16642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    g_signal_connect(m_playBin, "audio-changed", G_CALLBACK(mediaPlayerPrivateAudioChangedCallback), this);
16658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
166606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    m_webkitVideoSink = webkit_video_sink_new();
166706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
166806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    g_signal_connect(m_webkitVideoSink, "repaint-requested", G_CALLBACK(mediaPlayerPrivateRepaintCallback), this);
166906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
167006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    m_videoSinkBin = gst_bin_new("sink");
167106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    GstElement* videoTee = gst_element_factory_make("tee", "videoTee");
167206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    GstElement* queue = gst_element_factory_make("queue", 0);
16734576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    GstElement* identity = gst_element_factory_make("identity", "videoValve");
1674231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
167506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    // Take ownership.
16764576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    gst_object_ref_sink(m_videoSinkBin);
167706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
167806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    // Build a new video sink consisting of a bin containing a tee
167906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    // (meant to distribute data to multiple video sinks) and our
168006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    // internal video sink. For fullscreen we create an autovideosink
168106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    // and initially block the data flow towards it and configure it
168206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
16834576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    gst_bin_add_many(GST_BIN(m_videoSinkBin), videoTee, queue, identity, NULL);
168406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
168506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    // Link a new src pad from tee to queue1.
168606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    GstPad* srcPad = gst_element_get_request_pad(videoTee, "src%d");
168706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    GstPad* sinkPad = gst_element_get_static_pad(queue, "sink");
168806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    gst_pad_link(srcPad, sinkPad);
168906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    gst_object_unref(GST_OBJECT(srcPad));
169006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    gst_object_unref(GST_OBJECT(sinkPad));
1691d0825bca7fe65beaee391d30da42e937db621564Steve Block
16922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    GstElement* actualVideoSink = 0;
16932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_fpsSink = gst_element_factory_make("fpsdisplaysink", "sink");
16942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (m_fpsSink) {
16952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // The verbose property has been added in -bad 0.10.22. Making
16962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // this whole code depend on it because we don't want
16972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // fpsdiplaysink to spit data on stdout.
16982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        GstElementFactory* factory = GST_ELEMENT_FACTORY(GST_ELEMENT_GET_CLASS(m_fpsSink)->elementfactory);
16992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (gst_plugin_feature_check_version(GST_PLUGIN_FEATURE(factory), 0, 10, 22)) {
17002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            g_object_set(m_fpsSink, "silent", TRUE , NULL);
17012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            // Turn off text overlay unless logging is enabled.
17032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            WTFLogChannel* channel = getChannelFromName("Media");
17042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            if (channel->state != WTFLogChannelOn)
17052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                g_object_set(m_fpsSink, "text-overlay", FALSE , NULL);
17062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            if (g_object_class_find_property(G_OBJECT_GET_CLASS(m_fpsSink), "video-sink")) {
17082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                g_object_set(m_fpsSink, "video-sink", m_webkitVideoSink, NULL);
17092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                gst_bin_add(GST_BIN(m_videoSinkBin), m_fpsSink);
17102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                actualVideoSink = m_fpsSink;
17112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            } else
17122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                m_fpsSink = 0;
17132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        } else
1714d0825bca7fe65beaee391d30da42e937db621564Steve Block            m_fpsSink = 0;
17152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
17162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!m_fpsSink) {
171806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        gst_bin_add(GST_BIN(m_videoSinkBin), m_webkitVideoSink);
17192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        actualVideoSink = m_webkitVideoSink;
17202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
17212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(actualVideoSink);
1723f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#if GST_CHECK_VERSION(0, 10, 30)
1724f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        // Faster elements linking, if possible.
1725f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        gst_element_link_pads_full(queue, "src", identity, "sink", GST_PAD_LINK_CHECK_NOTHING);
17262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        gst_element_link_pads_full(identity, "src", actualVideoSink, "sink", GST_PAD_LINK_CHECK_NOTHING);
1727f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#else
17282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        gst_element_link_many(queue, identity, actualVideoSink, NULL);
1729f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#endif
173006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
173106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    // Add a ghostpad to the bin so it can proxy to tee.
173206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    GstPad* pad = gst_element_get_static_pad(videoTee, "sink");
173306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    gst_element_add_pad(m_videoSinkBin, gst_ghost_pad_new("sink", pad));
173406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    gst_object_unref(GST_OBJECT(pad));
17358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
173606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    // Set the bin as video sink of playbin.
173706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    g_object_set(m_playBin, "video-sink", m_videoSinkBin, NULL);
17382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    pad = gst_element_get_static_pad(m_webkitVideoSink, "sink");
17412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (pad) {
17422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        g_signal_connect(pad, "notify::caps", G_CALLBACK(mediaPlayerPrivateVideoSinkCapsChangedCallback), this);
17432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        gst_object_unref(GST_OBJECT(pad));
17442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
17452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
17478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
17488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
17498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1750bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#endif // USE(GSTREAMER)
1751