[GStreamer] Support audio and video tracks
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 1 Nov 2013 16:30:03 +0000 (16:30 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 1 Nov 2013 16:30:03 +0000 (16:30 +0000)
https://bugs.webkit.org/show_bug.cgi?id=117039

Patch by Brendan Long <b.long@cablelabs.com> on 2013-11-01
Reviewed by Philippe Normand.

Source/WebCore:

Tests: media/track/audio/audio-track-mkv-vorbis-addtrack.html
       media/track/audio/audio-track-mkv-vorbis-enabled.html
       media/track/audio/audio-track-mkv-vorbis-language.html
       media/track/in-band/track-in-band-kate-ogg-addtrack.html
       media/track/in-band/track-in-band-srt-mkv-addtrack.html
       media/track/video/video-track-mkv-theora-addtrack.html
       media/track/video/video-track-mkv-theora-language.html
       media/track/video/video-track-mkv-theora-selected.html

* GNUmakefile.list.am: Add audio and video track files.
* PlatformEfl.cmake: Same.
* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::audioTrackEnabledChanged): Schedule "change" event.
(WebCore::HTMLMediaElement::videoTrackSelectedChanged): Same.
* html/track/AudioTrack.cpp:
(WebCore::AudioTrack::setEnabled): Call m_private->setEnabled
(WebCore::AudioTrack::enabledChanged): Added callback.
(WebCore::AudioTrack::labelChanged): Same.
(WebCore::AudioTrack::languageChanged): Same.
(WebCore::AudioTrack::willRemoveAudioTrackPrivate): Use ASSERT_UNUSED for consistence.
* html/track/AudioTrack.h: Add new enabled, label and language callbacks.
* html/track/VideoTrack.cpp:
(WebCore::VideoTrack::setSelected): Call m_private->setEnabled
(WebCore::VideoTrack::selectedChanged): Added callback.
(WebCore::VideoTrack::labelChanged): Same.
(WebCore::VideoTrack::languageChanged): Same.
(WebCore::VideoTrack::willRemoveVideoTrackPrivate): Use ASSERT_UNUSED for consistence.
* html/track/VideoTrack.h: Add new selected, label and language callbacks.
* platform/graphics/AudioTrackPrivate.h:
(WebCore::AudioTrackPrivate::setEnabled): Call m_client->enabledChanged
* platform/graphics/VideoTrackPrivate.h:
(WebCore::VideoTrackPrivate::setSelected): Call m_client->selectedChanged
* platform/graphics/gstreamer/InbandTextTrackPrivateGStreamer.cpp:
(WebCore::InbandTextTrackPrivateGStreamer::InbandTextTrackPrivateGStreamer): Add ASSERT(m_pad)
(WebCore::InbandTextTrackPrivateGStreamer::notifyTrackOfTagsChanged): Look at all tag events instead of just the first one.
* platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp:
(WebCore::mediaPlayerPrivateVideoSinkCapsChangedCallback): Separated callback when caps change from callback when number of videos change.
(WebCore::mediaPlayerPrivateVideoCapsChangeTimeoutCallback): Same.
(WebCore::MediaPlayerPrivateGStreamer::MediaPlayerPrivateGStreamer): Initialize m_videoCapsTimerHandler.
(WebCore::MediaPlayerPrivateGStreamer::~MediaPlayerPrivateGStreamer): Disconnect audio and video tracks and remove callbacks.
(WebCore::MediaPlayerPrivateGStreamer::videoCapsChanged): Separated callback when caps change from callback when number of videos change.
(WebCore::MediaPlayerPrivateGStreamer::notifyPlayerOfVideo): Create video tracks for each stream.
(WebCore::MediaPlayerPrivateGStreamer::notifyPlayerOfVideoCaps): Separated callback when caps change from callback when number of videos change.
(WebCore::MediaPlayerPrivateGStreamer::notifyPlayerOfAudio): Create audio tracks for each stream.
* platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h: Add audio and video tracks, and a pointer to keep track of the default audio stream.
* platform/graphics/gstreamer/AudioTrackPrivateGStreamer.cpp: Added.
* platform/graphics/gstreamer/AudioTrackPrivateGStreamer.h: Added.
* platform/graphics/gstreamer/GRefPtrGStreamer.cpp: Add GRefPtr<GstTagList>
* platform/graphics/gstreamer/TrackPrivateBaseGStreamer.cpp: Added, handles tags and "active" property of audio and video tracks.
* platform/graphics/gstreamer/TrackPrivateBaseGStreamer.h: Added.
* platform/graphics/gstreamer/VideoTrackPrivateGStreamer.cpp: Added.
* platform/graphics/gstreamer/VideoTrackPrivateGStreamer.h: Added.

LayoutTests:

* media/content/two-audio-and-video-tracks.mkv: Added.
* media/in-band-tracks.js: Renamed from LayoutTests/media/in-band-cues.js.
(testAddTrack): Tests addtrack events.
(testAttribute): Added "type" parameter so we can use this for audio and video tracks.
(testTextTrackMode): Renamed to make it clear that this only applies to text tracks.
(testCueStyle): Same.
(testTextTrackOrder): Same.
* media/track/audio/audio-track-mkv-vorbis-addtrack-expected.txt: Added.
* media/track/audio/audio-track-mkv-vorbis-addtrack.html: Copied from LayoutTests/media/track/in-band/track-in-band-srt-mkv-track-order.html.
* media/track/audio/audio-track-mkv-vorbis-enabled-expected.txt: Added.
* media/track/audio/audio-track-mkv-vorbis-enabled.html: Added.
* media/track/audio/audio-track-mkv-vorbis-language-expected.txt: Added.
* media/track/audio/audio-track-mkv-vorbis-language.html: Copied from LayoutTests/media/track/in-band/track-in-band-kate-ogg-track-order.html.
* media/track/in-band/track-in-band-kate-ogg-addtrack-expected.txt: Added.
* media/track/in-band/track-in-band-kate-ogg-addtrack.html: Copied from LayoutTests/media/track/in-band/track-in-band-srt-mkv-track-order.html.
* media/track/in-band/track-in-band-kate-ogg-cues-added-once.html: Added.
* media/track/in-band/track-in-band-kate-ogg-kind.html: Added.
* media/track/in-band/track-in-band-kate-ogg-language.html: Added.
* media/track/in-band/track-in-band-kate-ogg-mode.html: Added.
* media/track/in-band/track-in-band-kate-ogg-style.html: Added.
* media/track/in-band/track-in-band-kate-ogg-track-order.html: Added.
* media/track/in-band/track-in-band-srt-mkv-addtrack-expected.txt: Added.
* media/track/in-band/track-in-band-srt-mkv-addtrack.html: Copied from LayoutTests/media/track/in-band/track-in-band-srt-mkv-track-order.html.
* media/track/in-band/track-in-band-srt-mkv-cues-added-once.html: Added.
* media/track/in-band/track-in-band-srt-mkv-kind.html: Added.
* media/track/in-band/track-in-band-srt-mkv-language.html: Added.
* media/track/in-band/track-in-band-srt-mkv-mode.html: Added.
* media/track/in-band/track-in-band-srt-mkv-style.html: Added.
* media/track/in-band/track-in-band-srt-mkv-track-order.html: Added.
* media/track/video/video-track-mkv-theora-addtrack-expected.txt: Added.
* media/track/video/video-track-mkv-theora-addtrack.html: Copied from LayoutTests/media/track/in-band/track-in-band-srt-mkv-track-order.html.
* media/track/video/video-track-mkv-theora-language-expected.txt: Added.
* media/track/video/video-track-mkv-theora-language.html: Copied from LayoutTests/media/track/in-band/track-in-band-kate-ogg-track-order.html.
* media/track/video/video-track-mkv-theora-selected-expected.txt: Added.
* media/track/video/video-track-mkv-theora-selected.html: Added.
* platform/mac/TestExpectations: Ignore audio and video track tests on mac.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@158436 268f45cc-cd09-0410-ab3c-d52691b4dbfc

54 files changed:
LayoutTests/ChangeLog
LayoutTests/media/content/two-audio-and-video-tracks.mkv [new file with mode: 0644]
LayoutTests/media/in-band-tracks.js [moved from LayoutTests/media/in-band-cues.js with 80% similarity]
LayoutTests/media/track/audio/audio-track-mkv-vorbis-addtrack-expected.txt [new file with mode: 0644]
LayoutTests/media/track/audio/audio-track-mkv-vorbis-addtrack.html [new file with mode: 0644]
LayoutTests/media/track/audio/audio-track-mkv-vorbis-enabled-expected.txt [new file with mode: 0644]
LayoutTests/media/track/audio/audio-track-mkv-vorbis-enabled.html [new file with mode: 0644]
LayoutTests/media/track/audio/audio-track-mkv-vorbis-language-expected.txt [new file with mode: 0644]
LayoutTests/media/track/audio/audio-track-mkv-vorbis-language.html [new file with mode: 0644]
LayoutTests/media/track/in-band/track-in-band-kate-ogg-addtrack-expected.txt [new file with mode: 0644]
LayoutTests/media/track/in-band/track-in-band-kate-ogg-addtrack.html [new file with mode: 0644]
LayoutTests/media/track/in-band/track-in-band-kate-ogg-cues-added-once.html
LayoutTests/media/track/in-band/track-in-band-kate-ogg-kind.html
LayoutTests/media/track/in-band/track-in-band-kate-ogg-language.html
LayoutTests/media/track/in-band/track-in-band-kate-ogg-mode.html
LayoutTests/media/track/in-band/track-in-band-kate-ogg-style.html
LayoutTests/media/track/in-band/track-in-band-kate-ogg-track-order.html
LayoutTests/media/track/in-band/track-in-band-mkv-chapters.html
LayoutTests/media/track/in-band/track-in-band-srt-mkv-addtrack-expected.txt [new file with mode: 0644]
LayoutTests/media/track/in-band/track-in-band-srt-mkv-addtrack.html [new file with mode: 0644]
LayoutTests/media/track/in-band/track-in-band-srt-mkv-cues-added-once.html
LayoutTests/media/track/in-band/track-in-band-srt-mkv-kind.html
LayoutTests/media/track/in-band/track-in-band-srt-mkv-language.html
LayoutTests/media/track/in-band/track-in-band-srt-mkv-mode.html
LayoutTests/media/track/in-band/track-in-band-srt-mkv-style.html
LayoutTests/media/track/in-band/track-in-band-srt-mkv-track-order.html
LayoutTests/media/track/video/video-track-mkv-theora-addtrack-expected.txt [new file with mode: 0644]
LayoutTests/media/track/video/video-track-mkv-theora-addtrack.html [new file with mode: 0644]
LayoutTests/media/track/video/video-track-mkv-theora-language-expected.txt [new file with mode: 0644]
LayoutTests/media/track/video/video-track-mkv-theora-language.html [new file with mode: 0644]
LayoutTests/media/track/video/video-track-mkv-theora-selected-expected.txt [new file with mode: 0644]
LayoutTests/media/track/video/video-track-mkv-theora-selected.html [new file with mode: 0644]
LayoutTests/platform/mac/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/GNUmakefile.list.am
Source/WebCore/PlatformEfl.cmake
Source/WebCore/html/HTMLMediaElement.cpp
Source/WebCore/html/track/AudioTrack.cpp
Source/WebCore/html/track/AudioTrack.h
Source/WebCore/html/track/VideoTrack.cpp
Source/WebCore/html/track/VideoTrack.h
Source/WebCore/platform/graphics/AudioTrackPrivate.h
Source/WebCore/platform/graphics/VideoTrackPrivate.h
Source/WebCore/platform/graphics/gstreamer/AudioTrackPrivateGStreamer.cpp [new file with mode: 0644]
Source/WebCore/platform/graphics/gstreamer/AudioTrackPrivateGStreamer.h [new file with mode: 0644]
Source/WebCore/platform/graphics/gstreamer/GRefPtrGStreamer.cpp
Source/WebCore/platform/graphics/gstreamer/GRefPtrGStreamer.h
Source/WebCore/platform/graphics/gstreamer/InbandTextTrackPrivateGStreamer.cpp
Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h
Source/WebCore/platform/graphics/gstreamer/TrackPrivateBaseGStreamer.cpp [new file with mode: 0644]
Source/WebCore/platform/graphics/gstreamer/TrackPrivateBaseGStreamer.h [new file with mode: 0644]
Source/WebCore/platform/graphics/gstreamer/VideoTrackPrivateGStreamer.cpp [new file with mode: 0644]
Source/WebCore/platform/graphics/gstreamer/VideoTrackPrivateGStreamer.h [new file with mode: 0644]

index 28cb15a..c53c863 100644 (file)
@@ -1,3 +1,47 @@
+2013-11-01  Brendan Long  <b.long@cablelabs.com>
+
+        [GStreamer] Support audio and video tracks
+        https://bugs.webkit.org/show_bug.cgi?id=117039
+
+        Reviewed by Philippe Normand.
+
+        * media/content/two-audio-and-video-tracks.mkv: Added.
+        * media/in-band-tracks.js: Renamed from LayoutTests/media/in-band-cues.js.
+        (testAddTrack): Tests addtrack events.
+        (testAttribute): Added "type" parameter so we can use this for audio and video tracks.
+        (testTextTrackMode): Renamed to make it clear that this only applies to text tracks.
+        (testCueStyle): Same.
+        (testTextTrackOrder): Same.
+        * media/track/audio/audio-track-mkv-vorbis-addtrack-expected.txt: Added.
+        * media/track/audio/audio-track-mkv-vorbis-addtrack.html: Copied from LayoutTests/media/track/in-band/track-in-band-srt-mkv-track-order.html.
+        * media/track/audio/audio-track-mkv-vorbis-enabled-expected.txt: Added.
+        * media/track/audio/audio-track-mkv-vorbis-enabled.html: Added.
+        * media/track/audio/audio-track-mkv-vorbis-language-expected.txt: Added.
+        * media/track/audio/audio-track-mkv-vorbis-language.html: Copied from LayoutTests/media/track/in-band/track-in-band-kate-ogg-track-order.html.
+        * media/track/in-band/track-in-band-kate-ogg-addtrack-expected.txt: Added.
+        * media/track/in-band/track-in-band-kate-ogg-addtrack.html: Copied from LayoutTests/media/track/in-band/track-in-band-srt-mkv-track-order.html.
+        * media/track/in-band/track-in-band-kate-ogg-cues-added-once.html: Added.
+        * media/track/in-band/track-in-band-kate-ogg-kind.html: Added.
+        * media/track/in-band/track-in-band-kate-ogg-language.html: Added.
+        * media/track/in-band/track-in-band-kate-ogg-mode.html: Added.
+        * media/track/in-band/track-in-band-kate-ogg-style.html: Added.
+        * media/track/in-band/track-in-band-kate-ogg-track-order.html: Added.
+        * media/track/in-band/track-in-band-srt-mkv-addtrack-expected.txt: Added.
+        * media/track/in-band/track-in-band-srt-mkv-addtrack.html: Copied from LayoutTests/media/track/in-band/track-in-band-srt-mkv-track-order.html.
+        * media/track/in-band/track-in-band-srt-mkv-cues-added-once.html: Added.
+        * media/track/in-band/track-in-band-srt-mkv-kind.html: Added.
+        * media/track/in-band/track-in-band-srt-mkv-language.html: Added.
+        * media/track/in-band/track-in-band-srt-mkv-mode.html: Added.
+        * media/track/in-band/track-in-band-srt-mkv-style.html: Added.
+        * media/track/in-band/track-in-band-srt-mkv-track-order.html: Added.
+        * media/track/video/video-track-mkv-theora-addtrack-expected.txt: Added.
+        * media/track/video/video-track-mkv-theora-addtrack.html: Copied from LayoutTests/media/track/in-band/track-in-band-srt-mkv-track-order.html.
+        * media/track/video/video-track-mkv-theora-language-expected.txt: Added.
+        * media/track/video/video-track-mkv-theora-language.html: Copied from LayoutTests/media/track/in-band/track-in-band-kate-ogg-track-order.html.
+        * media/track/video/video-track-mkv-theora-selected-expected.txt: Added.
+        * media/track/video/video-track-mkv-theora-selected.html: Added.
+        * platform/mac/TestExpectations: Ignore audio and video track tests on mac.
+
 2013-11-01  Gyuyoung Kim  <gyuyoung.kim@samsung.com>
 
         Unreviewed, EFL gardening. Skip webgl tests because EFL port doesn't fully support webgl yet. 
diff --git a/LayoutTests/media/content/two-audio-and-video-tracks.mkv b/LayoutTests/media/content/two-audio-and-video-tracks.mkv
new file mode 100644 (file)
index 0000000..eea6792
Binary files /dev/null and b/LayoutTests/media/content/two-audio-and-video-tracks.mkv differ
similarity index 80%
rename from LayoutTests/media/in-band-cues.js
rename to LayoutTests/media/in-band-tracks.js
index c061b55..6a430ab 100644 (file)
@@ -1,11 +1,53 @@
-function testAttribute(uri, attribute, values)
+function testTrackListContainsTrack(listStr, trackStr)
+{
+    var list = eval(listStr);
+    var track = eval(trackStr);
+    var found = false;
+    for (var i = 0; i < list.length; ++i) {
+        if (list[i] == track) {
+            found = true;
+            break;
+        }
+    }
+    reportExpected(found, listStr, " contains ", trackStr, list);
+}
+
+function compareTracks(track1, track2)
+{
+    var equal = (eval(track1) == eval(track2));
+    reportExpected(equal, track1, "==", track2, track1);
+}
+
+function testAddTrack(uri, type)
+{
+    var addtrackEventCount = 0;
+
+    function trackAdded(event)
+    {
+        consoleWrite("EVENT(" + event.type + ")");
+        ++addtrackEventCount;
+
+        /* Don't make assumptions about the order of track events. If you know
+         * the expected order, it should be tested separately. */
+        testTrackListContainsTrack("video." + type + "Tracks", "event.track");
+        consoleWrite("");
+    }
+
+    findMediaElement();
+    var tracks = eval("video." + type + "Tracks");
+    tracks.addEventListener("addtrack", trackAdded);
+    video.src = uri;
+    waitForEventAndEnd('canplaythrough');
+}
+
+function testAttribute(uri, type, attribute, values)
 {
     function canplaythrough()
     {
         consoleWrite("<br><i>** Check in-band kind attributes</i>");
-        testExpected("video.textTracks.length", values.length);
+        testExpected("video." + type +"Tracks.length", values.length);
         for (var i = 0; i < values.length; ++i)
-            testExpected("video.textTracks[" + i + "]." + attribute, values[i]);
+            testExpected("video." + type +"Tracks[" + i + "]." + attribute, values[i]);
 
         consoleWrite("");
         endTest();
@@ -79,7 +121,7 @@ function testCuesAddedOnce(uri, kind)
     waitForEvent('canplaythrough', canplaythrough);
 }
 
-function testMode(uri, kind)
+function testTextTrackMode(uri, kind)
 {
     function seeked()
     {
@@ -118,7 +160,7 @@ function testMode(uri, kind)
     waitForEvent('canplaythrough', canplaythrough);
 }
 
-function testStyle(uri)
+function testCueStyle(uri)
 {
     function seeked()
     {
@@ -155,7 +197,8 @@ function testStyle(uri)
     waitForEvent('canplaythrough', canplaythrough);
 }
 
-function testTrackOrder(uri, numInBandTracks) {
+function testTextTrackOrder(uri, numInBandTracks)
+{
     function compareTracks(track1, track2)
     {
         var equal = (eval(track1) == eval(track2));
diff --git a/LayoutTests/media/track/audio/audio-track-mkv-vorbis-addtrack-expected.txt b/LayoutTests/media/track/audio/audio-track-mkv-vorbis-addtrack-expected.txt
new file mode 100644 (file)
index 0000000..6833f39
--- /dev/null
@@ -0,0 +1,11 @@
+Testing audio track "addtrack" events.
+
+EVENT(addtrack)
+EXPECTED (video.audioTracks contains 'event.track') OK
+
+EVENT(addtrack)
+EXPECTED (video.audioTracks contains 'event.track') OK
+
+EVENT(canplaythrough)
+END OF TEST
+
diff --git a/LayoutTests/media/track/audio/audio-track-mkv-vorbis-addtrack.html b/LayoutTests/media/track/audio/audio-track-mkv-vorbis-addtrack.html
new file mode 100644 (file)
index 0000000..f867737
--- /dev/null
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+        <script src=../../media-file.js></script>
+        <script src=../../video-test.js></script>
+        <script src=../../in-band-tracks.js></script>
+    </head>
+    <body onload="testAddTrack('../../content/two-audio-and-video-tracks.mkv', 'audio')">
+        <video controls></video>
+        <p>Testing audio track "addtrack" events.</p>
+    </body>
+</html>
diff --git a/LayoutTests/media/track/audio/audio-track-mkv-vorbis-enabled-expected.txt b/LayoutTests/media/track/audio/audio-track-mkv-vorbis-enabled-expected.txt
new file mode 100644 (file)
index 0000000..23f9d3c
--- /dev/null
@@ -0,0 +1,23 @@
+Test audio track enabled attributes.
+
+EVENT(canplaythrough)
+EXPECTED (video.audioTracks.length == '2') OK
+RUN(track1 = video.audioTracks[0])
+RUN(track2 = video.audioTracks[1])
+
+** Checking initial state
+EXPECTED (track1.enabled == 'true') OK
+EXPECTED (track2.enabled == 'false') OK
+
+** Ensuring we can have two enabled tracks
+RUN(track2.enabled = true)
+EXPECTED (track1.enabled == 'true') OK
+EXPECTED (track2.enabled == 'true') OK
+
+** Ensuring we can have zero enabled tracks
+RUN(track1.enabled = false)
+RUN(track2.enabled = false)
+EXPECTED (track1.enabled == 'false') OK
+EXPECTED (track2.enabled == 'false') OK
+END OF TEST
+
diff --git a/LayoutTests/media/track/audio/audio-track-mkv-vorbis-enabled.html b/LayoutTests/media/track/audio/audio-track-mkv-vorbis-enabled.html
new file mode 100644 (file)
index 0000000..4bc82f0
--- /dev/null
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+        <script src=../../media-file.js></script>
+        <script src=../../video-test.js></script>
+        <script>
+
+            function canplaythrough()
+            {
+                testExpected("video.audioTracks.length", 2);
+                run("track1 = video.audioTracks[0]");
+                run("track2 = video.audioTracks[1]");
+
+                consoleWrite("<br><i>** Checking initial state</i>");
+                testExpected("track1.enabled", true);
+                testExpected("track2.enabled", false);
+                
+                consoleWrite("<br><i>** Ensuring we can have two enabled tracks</i>");
+                run("track2.enabled = true");
+                testExpected("track1.enabled", true);
+                testExpected("track2.enabled", true);
+                
+                consoleWrite("<br><i>** Ensuring we can have zero enabled tracks</i>");
+                run("track1.enabled = false");
+                run("track2.enabled = false");
+                testExpected("track1.enabled", false);
+                testExpected("track2.enabled", false);
+            }
+
+            function setup()
+            {
+                findMediaElement();
+                video.src = '../../content/two-audio-and-video-tracks.mkv';
+                waitForEventAndEnd('canplaythrough', canplaythrough);
+            }
+
+        </script>
+    </head>
+    <body onload="setup()">
+        <video controls></video>
+        <p>Test audio track enabled attributes.</p>
+    </body>
+</html>
diff --git a/LayoutTests/media/track/audio/audio-track-mkv-vorbis-language-expected.txt b/LayoutTests/media/track/audio/audio-track-mkv-vorbis-language-expected.txt
new file mode 100644 (file)
index 0000000..3c95128
--- /dev/null
@@ -0,0 +1,11 @@
+Check audio tracks' language attributes.
+
+EVENT(canplaythrough)
+
+** Check in-band kind attributes
+EXPECTED (video.audioTracks.length == '2') OK
+EXPECTED (video.audioTracks[0].language == 'la') OK
+EXPECTED (video.audioTracks[1].language == 'en') OK
+
+END OF TEST
+
diff --git a/LayoutTests/media/track/audio/audio-track-mkv-vorbis-language.html b/LayoutTests/media/track/audio/audio-track-mkv-vorbis-language.html
new file mode 100644 (file)
index 0000000..299c763
--- /dev/null
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+        <script src=../../media-file.js></script>
+        <script src=../../video-test.js></script>
+        <script src=../../in-band-tracks.js></script>
+    </head>
+    <body onload="testAttribute('../../content/two-audio-and-video-tracks.mkv', 'audio', 'language', ['la', 'en'])">
+        <video controls></video>
+        <p>Check audio tracks' language attributes.</p>
+    </body>
+</html>
diff --git a/LayoutTests/media/track/in-band/track-in-band-kate-ogg-addtrack-expected.txt b/LayoutTests/media/track/in-band/track-in-band-kate-ogg-addtrack-expected.txt
new file mode 100644 (file)
index 0000000..2144afb
--- /dev/null
@@ -0,0 +1,11 @@
+Testing text track "addtrack" events.
+
+EVENT(addtrack)
+EXPECTED (video.textTracks contains 'event.track') OK
+
+EVENT(addtrack)
+EXPECTED (video.textTracks contains 'event.track') OK
+
+EVENT(canplaythrough)
+END OF TEST
+
diff --git a/LayoutTests/media/track/in-band/track-in-band-kate-ogg-addtrack.html b/LayoutTests/media/track/in-band/track-in-band-kate-ogg-addtrack.html
new file mode 100644 (file)
index 0000000..d69b591
--- /dev/null
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+        <script src=../../media-file.js></script>
+        <script src=../../video-test.js></script>
+        <script src=../../in-band-tracks.js></script>
+    </head>
+    <body onload="testAddTrack('../../content/counting-subtitled-kate.ogv', 'text')">
+        <video controls></video>
+        <p>Testing text track "addtrack" events.</p>
+    </body>
+</html>
index fc1ccb4..3251ed3 100644 (file)
@@ -5,7 +5,7 @@
 
         <script src=../../media-file.js></script>
         <script src=../../video-test.js></script>
-        <script src=../../in-band-cues.js></script>
+        <script src=../../in-band-tracks.js></script>
     </head>
     <body onload="testCuesAddedOnce('../../content/counting-subtitled-kate.ogv', 'subtitles')">
         <video controls></video>
index d26e0df..0a3c9b4 100644 (file)
@@ -5,9 +5,9 @@
 
         <script src=../../media-file.js></script>
         <script src=../../video-test.js></script>
-        <script src=../../in-band-cues.js></script>
+        <script src=../../in-band-tracks.js></script>
     </head>
-    <body onload="testAttribute('../../content/counting-subtitled-kate.ogv', 'kind', ['subtitles', 'subtitles'])">
+    <body onload="testAttribute('../../content/counting-subtitled-kate.ogv', 'text', 'kind', ['subtitles', 'subtitles'])">
         <video controls></video>
         <p>Check in-band text tracks' kind attributes.</p>
     </body>
index 111995f..3567645 100644 (file)
@@ -5,9 +5,9 @@
 
         <script src=../../media-file.js></script>
         <script src=../../video-test.js></script>
-        <script src=../../in-band-cues.js></script>
+        <script src=../../in-band-tracks.js></script>
     </head>
-    <body onload="testAttribute('../../content/counting-subtitled-kate.ogv', 'language', ['en', 'fr'])">
+    <body onload="testAttribute('../../content/counting-subtitled-kate.ogv', 'text', 'language', ['en', 'fr'])">
         <video controls></video>
         <p>Check in-band text tracks' language attributes.</p>
     </body>
index 57f8b01..a51cd95 100644 (file)
@@ -6,9 +6,9 @@
         <script src=../../media-file.js></script>
         <script src=../../video-test.js></script>
         <script src=../../media-controls.js></script>
-        <script src=../../in-band-cues.js></script>
+        <script src=../../in-band-tracks.js></script>
     </head>
-    <body onload="testMode('../../content/counting-subtitled-kate.ogv', 'subtitles')">
+    <body onload="testTextTrackMode('../../content/counting-subtitled-kate.ogv', 'subtitles')">
         <video controls></video>
         <p>Test that cues from in-band tracks are displayed immediately when a track is made visible.</p>
     </body>
index c7c54f8..1dc0d29 100644 (file)
@@ -6,9 +6,9 @@
         <script src=../../media-file.js></script>
         <script src=../../video-test.js></script>
         <script src=../../media-controls.js></script>
-        <script src=../../in-band-cues.js></script>
+        <script src=../../in-band-tracks.js></script>
     </head>
-    <body onload="testStyle('../../content/counting-subtitled-kate.ogv')">
+    <body onload="testCueStyle('../../content/counting-subtitled-kate.ogv')">
         <video controls >
         </video>
     </body>
index e784267..0205c85 100644 (file)
@@ -5,9 +5,9 @@
 
         <script src=../../media-file.js></script>
         <script src=../../video-test.js></script>
-        <script src=../../in-band-cues.js></script>
+        <script src=../../in-band-tracks.js></script>
     </head>
-    <body onload="testTrackOrder('../../content/counting-subtitled-kate.ogv', 2)">
+    <body onload="testTextTrackOrder('../../content/counting-subtitled-kate.ogv', 2)">
         <video controls></video>
         <p>Test track order when using in-band and out-of-band text tracks.</p>
     </body>
index 55f6a8d..4557762 100644 (file)
@@ -5,7 +5,7 @@
 
         <script src=../../media-file.js></script>
         <script src=../../video-test.js></script>
-        <script src=../../in-band-cues.js></script>
+        <script src=../../in-band-tracks.js></script>
     </head>
     <body onload="testCuesAddedOnce('../../content/counting-subtitled-srt.mkv', 'chapters')">
         <video controls></video>
diff --git a/LayoutTests/media/track/in-band/track-in-band-srt-mkv-addtrack-expected.txt b/LayoutTests/media/track/in-band/track-in-band-srt-mkv-addtrack-expected.txt
new file mode 100644 (file)
index 0000000..88806f6
--- /dev/null
@@ -0,0 +1,17 @@
+Testing text track "addtrack" events.
+
+EVENT(addtrack)
+EXPECTED (video.textTracks contains 'event.track') OK
+
+EVENT(addtrack)
+EXPECTED (video.textTracks contains 'event.track') OK
+
+EVENT(addtrack)
+EXPECTED (video.textTracks contains 'event.track') OK
+
+EVENT(addtrack)
+EXPECTED (video.textTracks contains 'event.track') OK
+
+EVENT(canplaythrough)
+END OF TEST
+
diff --git a/LayoutTests/media/track/in-band/track-in-band-srt-mkv-addtrack.html b/LayoutTests/media/track/in-band/track-in-band-srt-mkv-addtrack.html
new file mode 100644 (file)
index 0000000..093ebb6
--- /dev/null
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+        <script src=../../media-file.js></script>
+        <script src=../../video-test.js></script>
+        <script src=../../in-band-tracks.js></script>
+    </head>
+    <body onload="testAddTrack('../../content/counting-subtitled-srt.mkv', 'text')">
+        <video controls></video>
+        <p>Testing text track "addtrack" events.</p>
+    </body>
+</html>
index 5e8b4fe..970facf 100644 (file)
@@ -5,7 +5,7 @@
 
         <script src=../../media-file.js></script>
         <script src=../../video-test.js></script>
-        <script src=../../in-band-cues.js></script>
+        <script src=../../in-band-tracks.js></script>
     </head>
     <body onload="testCuesAddedOnce('../../content/counting-subtitled-srt.mkv', 'subtitles')">
         <video controls></video>
index e391fba..6a587e2 100644 (file)
@@ -5,9 +5,9 @@
 
         <script src=../../media-file.js></script>
         <script src=../../video-test.js></script>
-        <script src=../../in-band-cues.js></script>
+        <script src=../../in-band-tracks.js></script>
     </head>
-    <body onload="testAttribute('../../content/counting-subtitled-srt.mkv', 'kind', ['chapters', 'subtitles', 'subtitles'])">
+    <body onload="testAttribute('../../content/counting-subtitled-srt.mkv', 'text', 'kind', ['chapters', 'subtitles', 'subtitles'])">
         <video controls></video>
         <p>Check in-band text tracks' kind attributes.</p>
     </body>
index 9d6c892..4c21933 100644 (file)
@@ -5,9 +5,9 @@
 
         <script src=../../media-file.js></script>
         <script src=../../video-test.js></script>
-        <script src=../../in-band-cues.js></script>
+        <script src=../../in-band-tracks.js></script>
     </head>
-    <body onload="testAttribute('../../content/counting-subtitled-srt.mkv', 'language', ['', 'en', 'fr'])">
+    <body onload="testAttribute('../../content/counting-subtitled-srt.mkv', 'text', 'language', ['', 'en', 'fr'])">
         <video controls></video>
         <p>Check in-band text tracks' language attributes.</p>
     </body>
index 8eef764..60bd33b 100644 (file)
@@ -6,9 +6,9 @@
         <script src=../../media-file.js></script>
         <script src=../../video-test.js></script>
         <script src=../../media-controls.js></script>
-        <script src=../../in-band-cues.js></script>
+        <script src=../../in-band-tracks.js></script>
     </head>
-    <body onload="testMode('../../content/counting-subtitled-srt.mkv', 'subtitles')">
+    <body onload="testTextTrackMode('../../content/counting-subtitled-srt.mkv', 'subtitles')">
         <video controls></video>
         <p>Test that cues from in-band tracks are displayed immediately when a track is made visible.</p>
     </body>
index 790da12..f371e5c 100644 (file)
@@ -6,9 +6,9 @@
         <script src=../../media-file.js></script>
         <script src=../../video-test.js></script>
         <script src=../../media-controls.js></script>
-        <script src=../../in-band-cues.js></script>
+        <script src=../../in-band-tracks.js></script>
     </head>
-    <body onload="testStyle('../../content/counting-subtitled-srt.mkv')">
+    <body onload="testCueStyle('../../content/counting-subtitled-srt.mkv')">
         <video controls >
         </video>
     </body>
index f459437..6c7b98e 100644 (file)
@@ -5,9 +5,9 @@
 
         <script src=../../media-file.js></script>
         <script src=../../video-test.js></script>
-        <script src=../../in-band-cues.js></script>
+        <script src=../../in-band-tracks.js></script>
     </head>
-    <body onload="testTrackOrder('../../content/counting-subtitled-srt.mkv', 3)">
+    <body onload="testTextTrackOrder('../../content/counting-subtitled-srt.mkv', 3)">
         <video controls></video>
         <p>Test track order when using in-band and out-of-band text tracks.</p>
     </body>
diff --git a/LayoutTests/media/track/video/video-track-mkv-theora-addtrack-expected.txt b/LayoutTests/media/track/video/video-track-mkv-theora-addtrack-expected.txt
new file mode 100644 (file)
index 0000000..bc74ea3
--- /dev/null
@@ -0,0 +1,11 @@
+Testing video track "addtrack" events.
+
+EVENT(addtrack)
+EXPECTED (video.videoTracks contains 'event.track') OK
+
+EVENT(addtrack)
+EXPECTED (video.videoTracks contains 'event.track') OK
+
+EVENT(canplaythrough)
+END OF TEST
+
diff --git a/LayoutTests/media/track/video/video-track-mkv-theora-addtrack.html b/LayoutTests/media/track/video/video-track-mkv-theora-addtrack.html
new file mode 100644 (file)
index 0000000..e6df8dd
--- /dev/null
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+        <script src=../../media-file.js></script>
+        <script src=../../video-test.js></script>
+        <script src=../../in-band-tracks.js></script>
+    </head>
+    <body onload="testAddTrack('../../content/two-audio-and-video-tracks.mkv', 'video')">
+        <video controls></video>
+        <p>Testing video track "addtrack" events.</p>
+    </body>
+</html>
diff --git a/LayoutTests/media/track/video/video-track-mkv-theora-language-expected.txt b/LayoutTests/media/track/video/video-track-mkv-theora-language-expected.txt
new file mode 100644 (file)
index 0000000..9438b24
--- /dev/null
@@ -0,0 +1,11 @@
+Check video tracks' language attributes.
+
+EVENT(canplaythrough)
+
+** Check in-band kind attributes
+EXPECTED (video.videoTracks.length == '2') OK
+EXPECTED (video.videoTracks[0].language == 'ru') OK
+EXPECTED (video.videoTracks[1].language == 'zh') OK
+
+END OF TEST
+
diff --git a/LayoutTests/media/track/video/video-track-mkv-theora-language.html b/LayoutTests/media/track/video/video-track-mkv-theora-language.html
new file mode 100644 (file)
index 0000000..6109d60
--- /dev/null
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+        <script src=../../media-file.js></script>
+        <script src=../../video-test.js></script>
+        <script src=../../in-band-tracks.js></script>
+    </head>
+    <body onload="testAttribute('../../content/two-audio-and-video-tracks.mkv', 'video', 'language', ['ru', 'zh'])">
+        <video controls></video>
+        <p>Check video tracks' language attributes.</p>
+    </body>
+</html>
diff --git a/LayoutTests/media/track/video/video-track-mkv-theora-selected-expected.txt b/LayoutTests/media/track/video/video-track-mkv-theora-selected-expected.txt
new file mode 100644 (file)
index 0000000..163b459
--- /dev/null
@@ -0,0 +1,17 @@
+Test audio track enabled attributes.
+
+EVENT(canplaythrough)
+EXPECTED (video.videoTracks.length == '2') OK
+RUN(track1 = video.videoTracks[0])
+RUN(track2 = video.videoTracks[1])
+
+** Checking initial state
+EXPECTED (track1.selected == 'true') OK
+EXPECTED (track2.selected == 'false') OK
+
+** If we select one track, the other should be deselected
+RUN(track2.selected = true)
+EXPECTED (track1.selected == 'false') OK
+EXPECTED (track2.selected == 'true') OK
+END OF TEST
+
diff --git a/LayoutTests/media/track/video/video-track-mkv-theora-selected.html b/LayoutTests/media/track/video/video-track-mkv-theora-selected.html
new file mode 100644 (file)
index 0000000..7cbb470
--- /dev/null
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+        <script src=../../media-file.js></script>
+        <script src=../../video-test.js></script>
+        <script>
+
+            var changedEventCount = 0;
+            var track1;
+            var track2;
+
+            function trackChanged(event)
+            {
+                ++changedEventCount;
+                if (changedEventCount > 1) {
+                    testExpected("track1.selected", false);
+                    testExpected("track2.selected", true);
+
+                    endTest();
+                }
+            }
+
+            function canplaythrough()
+            {
+                testExpected("video.videoTracks.length", 2);
+                run("track1 = video.videoTracks[0]");
+                run("track2 = video.videoTracks[1]");
+
+                consoleWrite("<br><i>** Checking initial state</i>");
+                testExpected("track1.selected", true);
+                testExpected("track2.selected", false);
+
+                consoleWrite("<br><i>** If we select one track, the other should be deselected</i>");
+                video.videoTracks.addEventListener("change", trackChanged);
+                run("track2.selected = true");
+            }
+
+            function setup()
+            {
+                findMediaElement();
+                video.src = '../../content/two-audio-and-video-tracks.mkv';
+                waitForEvent('canplaythrough', canplaythrough);
+            }
+
+        </script>
+    </head>
+    <body onload="setup()">
+        <video controls></video>
+        <p>Test audio track enabled attributes.</p>
+    </body>
+</html>
index 1ac56c4..3448916 100644 (file)
@@ -1297,3 +1297,7 @@ webkit.org/b/123490 [ Mavericks ] webaudio/oscillator-sawtooth.html [ Failure ]
 webkit.org/b/123498 [ Mavericks ] media/track/track-in-band-cues-added-once.html [ Failure ]
 
 webkit.org/b/123522 [ Mavericks ] media/track/track-in-band-legacy-api.html [ Pass Failure ]
+
+# Audio and video tracks aren't supported on mac
+media/track/audio
+media/track/video
index 9f0df13..2ca2aa8 100644 (file)
@@ -1,3 +1,63 @@
+2013-11-01  Brendan Long  <b.long@cablelabs.com>
+
+        [GStreamer] Support audio and video tracks
+        https://bugs.webkit.org/show_bug.cgi?id=117039
+
+        Reviewed by Philippe Normand.
+
+        Tests: media/track/audio/audio-track-mkv-vorbis-addtrack.html
+               media/track/audio/audio-track-mkv-vorbis-enabled.html
+               media/track/audio/audio-track-mkv-vorbis-language.html
+               media/track/in-band/track-in-band-kate-ogg-addtrack.html
+               media/track/in-band/track-in-band-srt-mkv-addtrack.html
+               media/track/video/video-track-mkv-theora-addtrack.html
+               media/track/video/video-track-mkv-theora-language.html
+               media/track/video/video-track-mkv-theora-selected.html
+
+        * GNUmakefile.list.am: Add audio and video track files.
+        * PlatformEfl.cmake: Same.
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::audioTrackEnabledChanged): Schedule "change" event.
+        (WebCore::HTMLMediaElement::videoTrackSelectedChanged): Same.
+        * html/track/AudioTrack.cpp:
+        (WebCore::AudioTrack::setEnabled): Call m_private->setEnabled
+        (WebCore::AudioTrack::enabledChanged): Added callback.
+        (WebCore::AudioTrack::labelChanged): Same.
+        (WebCore::AudioTrack::languageChanged): Same.
+        (WebCore::AudioTrack::willRemoveAudioTrackPrivate): Use ASSERT_UNUSED for consistence.
+        * html/track/AudioTrack.h: Add new enabled, label and language callbacks.
+        * html/track/VideoTrack.cpp:
+        (WebCore::VideoTrack::setSelected): Call m_private->setEnabled
+        (WebCore::VideoTrack::selectedChanged): Added callback.
+        (WebCore::VideoTrack::labelChanged): Same.
+        (WebCore::VideoTrack::languageChanged): Same.
+        (WebCore::VideoTrack::willRemoveVideoTrackPrivate): Use ASSERT_UNUSED for consistence.
+        * html/track/VideoTrack.h: Add new selected, label and language callbacks.
+        * platform/graphics/AudioTrackPrivate.h:
+        (WebCore::AudioTrackPrivate::setEnabled): Call m_client->enabledChanged
+        * platform/graphics/VideoTrackPrivate.h:
+        (WebCore::VideoTrackPrivate::setSelected): Call m_client->selectedChanged
+        * platform/graphics/gstreamer/InbandTextTrackPrivateGStreamer.cpp:
+        (WebCore::InbandTextTrackPrivateGStreamer::InbandTextTrackPrivateGStreamer): Add ASSERT(m_pad)
+        (WebCore::InbandTextTrackPrivateGStreamer::notifyTrackOfTagsChanged): Look at all tag events instead of just the first one.
+        * platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp:
+        (WebCore::mediaPlayerPrivateVideoSinkCapsChangedCallback): Separated callback when caps change from callback when number of videos change.
+        (WebCore::mediaPlayerPrivateVideoCapsChangeTimeoutCallback): Same.
+        (WebCore::MediaPlayerPrivateGStreamer::MediaPlayerPrivateGStreamer): Initialize m_videoCapsTimerHandler.
+        (WebCore::MediaPlayerPrivateGStreamer::~MediaPlayerPrivateGStreamer): Disconnect audio and video tracks and remove callbacks.
+        (WebCore::MediaPlayerPrivateGStreamer::videoCapsChanged): Separated callback when caps change from callback when number of videos change.
+        (WebCore::MediaPlayerPrivateGStreamer::notifyPlayerOfVideo): Create video tracks for each stream.
+        (WebCore::MediaPlayerPrivateGStreamer::notifyPlayerOfVideoCaps): Separated callback when caps change from callback when number of videos change.
+        (WebCore::MediaPlayerPrivateGStreamer::notifyPlayerOfAudio): Create audio tracks for each stream.
+        * platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h: Add audio and video tracks, and a pointer to keep track of the default audio stream.
+        * platform/graphics/gstreamer/AudioTrackPrivateGStreamer.cpp: Added.
+        * platform/graphics/gstreamer/AudioTrackPrivateGStreamer.h: Added.
+        * platform/graphics/gstreamer/GRefPtrGStreamer.cpp: Add GRefPtr<GstTagList>
+        * platform/graphics/gstreamer/TrackPrivateBaseGStreamer.cpp: Added, handles tags and "active" property of audio and video tracks.
+        * platform/graphics/gstreamer/TrackPrivateBaseGStreamer.h: Added.
+        * platform/graphics/gstreamer/VideoTrackPrivateGStreamer.cpp: Added.
+        * platform/graphics/gstreamer/VideoTrackPrivateGStreamer.h: Added.
+
 2013-11-01  Patrick Gansterer  <paroga@webkit.org>
 
         Buildfix for !ENABLE(INSPECTOR) after 157288.
index 0fe7aed..a3fda1c 100644 (file)
@@ -6282,19 +6282,24 @@ endif # END USE_GLES2
 
 if USE_GSTREAMER
 platform_sources += \
+       Source/WebCore/platform/graphics/gstreamer/AudioTrackPrivateGStreamer.cpp \
+       Source/WebCore/platform/graphics/gstreamer/AudioTrackPrivateGStreamer.h \
        Source/WebCore/platform/graphics/gstreamer/GRefPtrGStreamer.cpp \
        Source/WebCore/platform/graphics/gstreamer/GRefPtrGStreamer.h \
        Source/WebCore/platform/graphics/gstreamer/GStreamerUtilities.cpp \
        Source/WebCore/platform/graphics/gstreamer/GStreamerUtilities.h \
        Source/WebCore/platform/graphics/gstreamer/GStreamerVersioning.cpp \
        Source/WebCore/platform/graphics/gstreamer/GStreamerVersioning.h \
+       Source/WebCore/platform/graphics/gstreamer/InbandTextTrackPrivateGStreamer.cpp \
+       Source/WebCore/platform/graphics/gstreamer/InbandTextTrackPrivateGStreamer.h \
        Source/WebCore/platform/graphics/gstreamer/TextCombinerGStreamer.cpp \
        Source/WebCore/platform/graphics/gstreamer/TextCombinerGStreamer.h \
        Source/WebCore/platform/graphics/gstreamer/TextSinkGStreamer.cpp \
-       Source/WebCore/platform/graphics/gstreamer/TextSinkGStreamer.h
-webcore_platform_sources += \
-       Source/WebCore/platform/graphics/gstreamer/InbandTextTrackPrivateGStreamer.cpp \
-       Source/WebCore/platform/graphics/gstreamer/InbandTextTrackPrivateGStreamer.h
+       Source/WebCore/platform/graphics/gstreamer/TextSinkGStreamer.h \
+       Source/WebCore/platform/graphics/gstreamer/TrackPrivateBaseGStreamer.cpp \
+       Source/WebCore/platform/graphics/gstreamer/TrackPrivateBaseGStreamer.h \
+       Source/WebCore/platform/graphics/gstreamer/VideoTrackPrivateGStreamer.cpp \
+       Source/WebCore/platform/graphics/gstreamer/VideoTrackPrivateGStreamer.h
 endif
 
 # ---
index e4eef4e..815557b 100644 (file)
@@ -123,6 +123,7 @@ list(APPEND WebCore_SOURCES
     platform/graphics/freetype/GlyphPageTreeNodeFreeType.cpp
     platform/graphics/freetype/SimpleFontDataFreeType.cpp
 
+    platform/graphics/gstreamer/AudioTrackPrivateGStreamer.cpp
     platform/graphics/gstreamer/GRefPtrGStreamer.cpp
     platform/graphics/gstreamer/GStreamerGWorld.cpp
     platform/graphics/gstreamer/GStreamerUtilities.cpp
@@ -134,7 +135,9 @@ list(APPEND WebCore_SOURCES
     platform/graphics/gstreamer/PlatformVideoWindowEfl.cpp
     platform/graphics/gstreamer/TextCombinerGStreamer.cpp
     platform/graphics/gstreamer/TextSinkGStreamer.cpp
+    platform/graphics/gstreamer/TrackPrivateBaseGStreamer.cpp
     platform/graphics/gstreamer/VideoSinkGStreamer.cpp
+    platform/graphics/gstreamer/VideoTrackPrivateGStreamer.cpp
     platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp
 
     platform/graphics/harfbuzz/HarfBuzzFace.cpp
index f3b16b5..dcb2f1f 100644 (file)
@@ -1441,9 +1441,12 @@ void HTMLMediaElement::textTrackReadyStateChanged(TextTrack* track)
     }
 }
 
-void HTMLMediaElement::audioTrackEnabledChanged(AudioTrack*)
+void HTMLMediaElement::audioTrackEnabledChanged(AudioTrack* track)
 {
-    // We will want to change the media controls here once they exist
+    if (!RuntimeEnabledFeatures::sharedFeatures().webkitVideoTrackEnabled())
+        return;
+    ASSERT_UNUSED(track, m_audioTracks->contains(track));
+    m_audioTracks->scheduleChangeEvent();
 }
 
 void HTMLMediaElement::textTrackModeChanged(TextTrack* track)
@@ -1479,9 +1482,12 @@ void HTMLMediaElement::textTrackModeChanged(TextTrack* track)
     configureTextTrackDisplay(AssumeTextTrackVisibilityChanged);
 }
 
-void HTMLMediaElement::videoTrackSelectedChanged(VideoTrack*)
+void HTMLMediaElement::videoTrackSelectedChanged(VideoTrack* track)
 {
-    // We will want to change the media controls here once they exist
+    if (!RuntimeEnabledFeatures::sharedFeatures().webkitVideoTrackEnabled())
+        return;
+    ASSERT_UNUSED(track, m_videoTracks->contains(track));
+    m_videoTracks->scheduleChangeEvent();
 }
 
 void HTMLMediaElement::textTrackKindChanged(TextTrack* track)
index 1e144a8..e2e82d6 100644 (file)
@@ -145,7 +145,6 @@ void AudioTrack::setEnabled(const bool enabled)
         return;
 
     m_enabled = enabled;
-
     m_private->setEnabled(enabled);
 
     if (m_client)
@@ -158,10 +157,27 @@ size_t AudioTrack::inbandTrackIndex()
     return m_private->audioTrackIndex();
 }
 
+void AudioTrack::enabledChanged(AudioTrackPrivate* trackPrivate, bool enabled)
+{
+    ASSERT_UNUSED(trackPrivate, trackPrivate == m_private);
+    setEnabled(enabled);
+}
+
+void AudioTrack::labelChanged(AudioTrackPrivate* trackPrivate, const String& label)
+{
+    ASSERT_UNUSED(trackPrivate, trackPrivate == m_private);
+    setLabel(label);
+}
+
+void AudioTrack::languageChanged(AudioTrackPrivate* trackPrivate, const String& language)
+{
+    ASSERT_UNUSED(trackPrivate, trackPrivate == m_private);
+    setLanguage(language);
+}
+
 void AudioTrack::willRemoveAudioTrackPrivate(AudioTrackPrivate* trackPrivate)
 {
-    UNUSED_PARAM(trackPrivate);
-    ASSERT(trackPrivate == m_private);
+    ASSERT_UNUSED(trackPrivate, trackPrivate == m_private);
     mediaElement()->removeAudioTrack(this);
 }
 
index a2e320f..04ca5fc 100644 (file)
@@ -78,6 +78,10 @@ protected:
 
 private:
     virtual bool isValidKind(const AtomicString&) const OVERRIDE;
+
+    virtual void enabledChanged(AudioTrackPrivate*, bool) OVERRIDE;
+    virtual void labelChanged(AudioTrackPrivate*, const String&) OVERRIDE;
+    virtual void languageChanged(AudioTrackPrivate*, const String&) OVERRIDE;
     virtual void willRemoveAudioTrackPrivate(AudioTrackPrivate*) OVERRIDE;
 
     AtomicString m_id;
index cfa0826..d3668a2 100644 (file)
@@ -145,6 +145,7 @@ void VideoTrack::setSelected(const bool selected)
         return;
 
     m_selected = selected;
+    m_private->setSelected(selected);
 
     if (m_client)
         m_client->videoTrackSelectedChanged(this);
@@ -156,10 +157,27 @@ size_t VideoTrack::inbandTrackIndex()
     return m_private->videoTrackIndex();
 }
 
+void VideoTrack::selectedChanged(VideoTrackPrivate* trackPrivate, bool selected)
+{
+    ASSERT_UNUSED(trackPrivate, trackPrivate == m_private);
+    setSelected(selected);
+}
+
+void VideoTrack::labelChanged(VideoTrackPrivate* trackPrivate, const String& label)
+{
+    ASSERT_UNUSED(trackPrivate, trackPrivate == m_private);
+    setLabel(label);
+}
+
+void VideoTrack::languageChanged(VideoTrackPrivate* trackPrivate, const String& language)
+{
+    ASSERT_UNUSED(trackPrivate, trackPrivate == m_private);
+    setLanguage(language);
+}
+
 void VideoTrack::willRemoveVideoTrackPrivate(VideoTrackPrivate* trackPrivate)
 {
-    UNUSED_PARAM(trackPrivate);
-    ASSERT(trackPrivate == m_private);
+    ASSERT_UNUSED(trackPrivate, trackPrivate == m_private);
     mediaElement()->removeVideoTrack(this);
 }
 
index d3a8846..fbd4e17 100644 (file)
@@ -78,6 +78,10 @@ protected:
 
 private:
     virtual bool isValidKind(const AtomicString&) const OVERRIDE;
+
+    virtual void selectedChanged(VideoTrackPrivate*, bool) OVERRIDE;
+    virtual void labelChanged(VideoTrackPrivate*, const String&) OVERRIDE;
+    virtual void languageChanged(VideoTrackPrivate*, const String&) OVERRIDE;
     virtual void willRemoveVideoTrackPrivate(VideoTrackPrivate*) OVERRIDE;
 
     AtomicString m_id;
index 9dec2f9..aab66a0 100644 (file)
@@ -40,6 +40,9 @@ class AudioTrackPrivate;
 class AudioTrackPrivateClient {
 public:
     virtual ~AudioTrackPrivateClient() { }
+    virtual void enabledChanged(AudioTrackPrivate*, bool) = 0;
+    virtual void labelChanged(AudioTrackPrivate*, const String&) = 0;
+    virtual void languageChanged(AudioTrackPrivate*, const String&) = 0;
     virtual void willRemoveAudioTrackPrivate(AudioTrackPrivate*) = 0;
 };
 
@@ -55,7 +58,14 @@ public:
     void setClient(AudioTrackPrivateClient* client) { m_client = client; }
     AudioTrackPrivateClient* client() { return m_client; }
 
-    virtual void setEnabled(bool enabled) { m_enabled = enabled; };
+    virtual void setEnabled(bool enabled)
+    {
+        if (m_enabled == enabled)
+            return;
+        m_enabled = enabled;
+        if (m_client)
+            m_client->enabledChanged(this, enabled);
+    };
     virtual bool enabled() const { return m_enabled; }
 
     enum Kind { Alternative, Description, Main, MainDesc, Translation, Commentary, None };
index d8279f6..e5f5f24 100644 (file)
@@ -40,6 +40,9 @@ class VideoTrackPrivate;
 class VideoTrackPrivateClient {
 public:
     virtual ~VideoTrackPrivateClient() { }
+    virtual void selectedChanged(VideoTrackPrivate*, bool) = 0;
+    virtual void labelChanged(VideoTrackPrivate*, const String&) = 0;
+    virtual void languageChanged(VideoTrackPrivate*, const String&) = 0;
     virtual void willRemoveVideoTrackPrivate(VideoTrackPrivate*) = 0;
 };
 
@@ -55,7 +58,14 @@ public:
     void setClient(VideoTrackPrivateClient* client) { m_client = client; }
     VideoTrackPrivateClient* client() { return m_client; }
 
-    virtual void setSelected(bool selected) { m_selected = selected; };
+    virtual void setSelected(bool selected)
+    {
+        if (m_selected == selected)
+            return;
+        m_selected = selected;
+        if (m_client)
+            m_client->selectedChanged(this, m_selected);
+    };
     virtual bool selected() const { return m_selected; }
 
     enum Kind { Alternative, Captions, Main, Sign, Subtitles, Commentary, None };
diff --git a/Source/WebCore/platform/graphics/gstreamer/AudioTrackPrivateGStreamer.cpp b/Source/WebCore/platform/graphics/gstreamer/AudioTrackPrivateGStreamer.cpp
new file mode 100644 (file)
index 0000000..fa55967
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2013 Cable Television Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(VIDEO) && USE(GSTREAMER) && ENABLE(VIDEO_TRACK) && defined(GST_API_VERSION_1)
+
+#include "AudioTrackPrivateGStreamer.h"
+
+#include <glib-object.h>
+
+namespace WebCore {
+
+AudioTrackPrivateGStreamer::AudioTrackPrivateGStreamer(GRefPtr<GstElement> playbin, gint index, GRefPtr<GstPad> pad)
+    : TrackPrivateBaseGStreamer("notify::current-audio", playbin, index, pad)
+{
+    activeChanged();
+    tagsChanged();
+}
+
+void AudioTrackPrivateGStreamer::setEnabled(bool enabled)
+{
+    if (enabled == this->enabled())
+        return;
+    AudioTrackPrivate::setEnabled(enabled);
+
+    if (enabled && m_playbin)
+        g_object_set(m_playbin.get(), "current-audio", m_index, NULL);
+}
+
+void AudioTrackPrivateGStreamer::labelChanged(const String& label)
+{
+    if (client())
+        client()->labelChanged(this, label);
+}
+
+void AudioTrackPrivateGStreamer::languageChanged(const String& language)
+{
+    if (client())
+        client()->languageChanged(this, language);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(VIDEO) && USE(GSTREAMER) && ENABLE(VIDEO_TRACK) && defined(GST_API_VERSION_1)
diff --git a/Source/WebCore/platform/graphics/gstreamer/AudioTrackPrivateGStreamer.h b/Source/WebCore/platform/graphics/gstreamer/AudioTrackPrivateGStreamer.h
new file mode 100644 (file)
index 0000000..6e4357f
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2013 Cable Television Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef AudioTrackPrivateGStreamer_h
+#define AudioTrackPrivateGStreamer_h
+
+#if ENABLE(VIDEO) && USE(GSTREAMER) && ENABLE(VIDEO_TRACK) && defined(GST_API_VERSION_1)
+
+#include "AudioTrackPrivate.h"
+#include "GRefPtrGStreamer.h"
+#include "TrackPrivateBaseGStreamer.h"
+
+namespace WebCore {
+
+class AudioTrackPrivateGStreamer FINAL : public AudioTrackPrivate, public TrackPrivateBaseGStreamer {
+public:
+    static PassRefPtr<AudioTrackPrivateGStreamer> create(GRefPtr<GstElement> playbin, gint index, GRefPtr<GstPad> pad)
+    {
+        return adoptRef(new AudioTrackPrivateGStreamer(playbin, index, pad));
+    }
+
+    virtual void setEnabled(bool) OVERRIDE;
+    virtual void setActive(bool enabled) OVERRIDE { setEnabled(enabled); }
+
+    virtual int audioTrackIndex() const OVERRIDE { return m_index; }
+    virtual void labelChanged(const String&) OVERRIDE;
+    virtual void languageChanged(const String&) OVERRIDE;
+
+private:
+    AudioTrackPrivateGStreamer(GRefPtr<GstElement> playbin, gint index, GRefPtr<GstPad>);
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(VIDEO) && USE(GSTREAMER) && ENABLE(VIDEO_TRACK) && defined(GST_API_VERSION_1)
+
+#endif // AudioTrackPrivateGStreamer_h
index 0dbdf7c..2addccd 100644 (file)
@@ -203,6 +203,25 @@ template<> void derefGPtr<GstSample>(GstSample* ptr)
     if (ptr)
         gst_sample_unref(ptr);
 }
+
+template<> GRefPtr<GstTagList> adoptGRef(GstTagList* ptr)
+{
+    return GRefPtr<GstTagList>(ptr, GRefPtrAdopt);
+}
+
+template<> GstTagList* refGPtr<GstTagList>(GstTagList* ptr)
+{
+    if (ptr)
+        gst_tag_list_ref(ptr);
+
+    return ptr;
+}
+
+template<> void derefGPtr<GstTagList>(GstTagList* ptr)
+{
+    if (ptr)
+        gst_tag_list_unref(ptr);
+}
 #endif
 
 template<> GRefPtr<GstEvent> adoptGRef(GstEvent* ptr)
index 8d63b2c..5e05657 100644 (file)
@@ -33,6 +33,7 @@ typedef struct _GstElementFactory GstElementFactory;
 typedef struct _GstBuffer GstBuffer;
 #ifdef GST_API_VERSION_1
 typedef struct _GstSample GstSample;
+typedef struct _GstTagList GstTagList;
 #endif
 typedef struct _GstEvent GstEvent;
 typedef struct _GstToc GstToc;
@@ -72,9 +73,15 @@ template<> GstBuffer* refGPtr<GstBuffer>(GstBuffer* ptr);
 template<> void derefGPtr<GstBuffer>(GstBuffer* ptr);
 
 #ifdef GST_API_VERSION_1
+/* GstSample was added in GStreamer 1.0 */
 template<> GRefPtr<GstSample> adoptGRef(GstSample* ptr);
 template<> GstSample* refGPtr<GstSample>(GstSample* ptr);
 template<> void derefGPtr<GstSample>(GstSample* ptr);
+
+/* GstTagList isn't refcounted in GStreamer 0.10 */
+template<> GRefPtr<GstTagList> adoptGRef(GstTagList* ptr);
+template<> GstTagList* refGPtr<GstTagList>(GstTagList* ptr);
+template<> void derefGPtr<GstTagList>(GstTagList* ptr);
 #endif
 
 template<> GRefPtr<GstEvent> adoptGRef(GstEvent* ptr);
index 6641d5a..70d838c 100644 (file)
@@ -81,6 +81,7 @@ InbandTextTrackPrivateGStreamer::InbandTextTrackPrivateGStreamer(gint index, GRe
     , m_streamTimerHandler(0)
     , m_tagTimerHandler(0)
 {
+    ASSERT(m_pad);
     m_eventProbe = gst_pad_add_probe(m_pad.get(), GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
         reinterpret_cast<GstPadProbeCallback>(textTrackPrivateEventCallback), this, 0);
 
@@ -187,24 +188,26 @@ void InbandTextTrackPrivateGStreamer::notifyTrackOfStreamChanged()
 void InbandTextTrackPrivateGStreamer::notifyTrackOfTagsChanged()
 {
     m_tagTimerHandler = 0;
-
-    GRefPtr<GstEvent> event = adoptGRef(gst_pad_get_sticky_event(m_pad.get(), GST_EVENT_TAG, 0));
-    GstTagList* tags = 0;
-    if (event)
-        gst_event_parse_tag(event.get(), &tags);
+    if (!m_pad)
+        return;
 
     String label;
     String language;
-    if (tags) {
+    GRefPtr<GstEvent> event;
+    for (guint i = 0; (event = adoptGRef(gst_pad_get_sticky_event(m_pad.get(), GST_EVENT_TAG, i))); ++i) {
+        GstTagList* tags = 0;
+        gst_event_parse_tag(event.get(), &tags);
+        ASSERT(tags);
+
         gchar* tagValue;
         if (gst_tag_list_get_string(tags, GST_TAG_TITLE, &tagValue)) {
-            INFO_MEDIA_MESSAGE("Track %d got title %s.", m_index, tagValue);
+            INFO_MEDIA_MESSAGE("Text track %d got title %s.", m_index, tagValue);
             label = tagValue;
             g_free(tagValue);
         }
 
         if (gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &tagValue)) {
-            INFO_MEDIA_MESSAGE("Track %d got language %s.", m_index, tagValue);
+            INFO_MEDIA_MESSAGE("Text track %d got language %s.", m_index, tagValue);
             language = tagValue;
             g_free(tagValue);
         }
index e9a5e7d..b33cc26 100644 (file)
 #include <wtf/text/CString.h>
 
 #if ENABLE(VIDEO_TRACK) && defined(GST_API_VERSION_1)
+#include "AudioTrackPrivateGStreamer.h"
 #include "InbandMetadataTextTrackPrivateGStreamer.h"
 #include "InbandTextTrackPrivateGStreamer.h"
 #include "TextCombinerGStreamer.h"
 #include "TextSinkGStreamer.h"
+#include "VideoTrackPrivateGStreamer.h"
 #endif
 
 #ifdef GST_API_VERSION_1
@@ -104,7 +106,7 @@ static void mediaPlayerPrivateSourceChangedCallback(GObject*, GParamSpec*, Media
 
 static void mediaPlayerPrivateVideoSinkCapsChangedCallback(GObject*, GParamSpec*, MediaPlayerPrivateGStreamer* player)
 {
-    player->videoChanged();
+    player->videoCapsChanged();
 }
 
 static void mediaPlayerPrivateVideoChangedCallback(GObject*, MediaPlayerPrivateGStreamer* player)
@@ -141,6 +143,13 @@ static gboolean mediaPlayerPrivateVideoChangeTimeoutCallback(MediaPlayerPrivateG
     return FALSE;
 }
 
+static gboolean mediaPlayerPrivateVideoCapsChangeTimeoutCallback(MediaPlayerPrivateGStreamer* player)
+{
+    // This is the callback of the timeout source created in ::videoCapsChanged.
+    player->notifyPlayerOfVideoCaps();
+    return FALSE;
+}
+
 #if ENABLE(VIDEO_TRACK) && defined(GST_API_VERSION_1)
 static void mediaPlayerPrivateTextChangedCallback(GObject*, MediaPlayerPrivateGStreamer* player)
 {
@@ -268,6 +277,7 @@ MediaPlayerPrivateGStreamer::MediaPlayerPrivateGStreamer(MediaPlayer* player)
     , m_audioTimerHandler(0)
     , m_textTimerHandler(0)
     , m_videoTimerHandler(0)
+    , m_videoCapsTimerHandler(0)
     , m_readyTimerHandler(0)
     , m_webkitAudioSink(0)
     , m_totalBytes(-1)
@@ -280,8 +290,14 @@ MediaPlayerPrivateGStreamer::MediaPlayerPrivateGStreamer(MediaPlayer* player)
 MediaPlayerPrivateGStreamer::~MediaPlayerPrivateGStreamer()
 {
 #if ENABLE(VIDEO_TRACK) && defined(GST_API_VERSION_1)
+    for (size_t i = 0; i < m_audioTracks.size(); ++i)
+        m_audioTracks[i]->disconnect();
+
     for (size_t i = 0; i < m_textTracks.size(); ++i)
         m_textTracks[i]->disconnect();
+
+    for (size_t i = 0; i < m_videoTracks.size(); ++i)
+        m_videoTracks[i]->disconnect();
 #endif
     if (m_fillTimer.isActive())
         m_fillTimer.stop();
@@ -327,6 +343,9 @@ MediaPlayerPrivateGStreamer::~MediaPlayerPrivateGStreamer()
 
     if (m_textTimerHandler)
         g_source_remove(m_textTimerHandler);
+
+    if (m_videoCapsTimerHandler)
+        g_source_remove(m_videoCapsTimerHandler);
 }
 
 void MediaPlayerPrivateGStreamer::load(const String& url)
@@ -631,21 +650,59 @@ void MediaPlayerPrivateGStreamer::videoChanged()
     m_videoTimerHandler = g_idle_add_full(G_PRIORITY_DEFAULT, reinterpret_cast<GSourceFunc>(mediaPlayerPrivateVideoChangeTimeoutCallback), this, 0);
 }
 
+void MediaPlayerPrivateGStreamer::videoCapsChanged()
+{
+    if (m_videoCapsTimerHandler)
+        g_source_remove(m_videoCapsTimerHandler);
+    m_videoCapsTimerHandler = g_timeout_add(0, reinterpret_cast<GSourceFunc>(mediaPlayerPrivateVideoCapsChangeTimeoutCallback), this);
+}
+
 void MediaPlayerPrivateGStreamer::notifyPlayerOfVideo()
 {
     m_videoTimerHandler = 0;
 
-    gint videoTracks = 0;
+    gint numTracks = 0;
     if (m_playBin)
-        g_object_get(m_playBin.get(), "n-video", &videoTracks, NULL);
+        g_object_get(m_playBin.get(), "n-video", &numTracks, NULL);
 
-    m_hasVideo = videoTracks > 0;
+    m_hasVideo = numTracks > 0;
 
-    m_videoSize = IntSize();
+#if ENABLE(VIDEO_TRACK) && defined(GST_API_VERSION_1)
+    for (gint i = 0; i < numTracks; ++i) {
+        GRefPtr<GstPad> pad;
+        g_signal_emit_by_name(m_playBin.get(), "get-video-pad", i, &pad.outPtr(), NULL);
+        ASSERT(pad);
+
+        if (i < static_cast<gint>(m_videoTracks.size())) {
+            RefPtr<VideoTrackPrivateGStreamer> existingTrack = m_videoTracks[i];
+            existingTrack->setIndex(i);
+            if (existingTrack->pad() == pad)
+                continue;
+        }
+
+        RefPtr<VideoTrackPrivateGStreamer> track = VideoTrackPrivateGStreamer::create(m_playBin, i, pad);
+        m_videoTracks.append(track);
+        m_player->addVideoTrack(track.release());
+    }
+
+    while (static_cast<gint>(m_videoTracks.size()) > numTracks) {
+        RefPtr<VideoTrackPrivateGStreamer> track = m_videoTracks.last();
+        track->disconnect();
+        m_videoTracks.removeLast();
+        m_player->removeVideoTrack(track.release());
+    }
+#endif
 
     m_player->mediaPlayerClient()->mediaPlayerEngineUpdated(m_player);
 }
 
+void MediaPlayerPrivateGStreamer::notifyPlayerOfVideoCaps()
+{
+    m_videoCapsTimerHandler = 0;
+    m_videoSize = IntSize();
+    m_player->mediaPlayerClient()->mediaPlayerEngineUpdated(m_player);
+}
+
 void MediaPlayerPrivateGStreamer::audioChanged()
 {
     if (m_audioTimerHandler)
@@ -657,10 +714,38 @@ void MediaPlayerPrivateGStreamer::notifyPlayerOfAudio()
 {
     m_audioTimerHandler = 0;
 
-    gint audioTracks = 0;
+    gint numTracks = 0;
     if (m_playBin)
-        g_object_get(m_playBin.get(), "n-audio", &audioTracks, NULL);
-    m_hasAudio = audioTracks > 0;
+        g_object_get(m_playBin.get(), "n-audio", &numTracks, NULL);
+
+    m_hasAudio = numTracks > 0;
+
+#if ENABLE(VIDEO_TRACK) && defined(GST_API_VERSION_1)
+    for (gint i = 0; i < numTracks; ++i) {
+        GRefPtr<GstPad> pad;
+        g_signal_emit_by_name(m_playBin.get(), "get-audio-pad", i, &pad.outPtr(), NULL);
+        ASSERT(pad);
+
+        if (i < static_cast<gint>(m_audioTracks.size())) {
+            RefPtr<AudioTrackPrivateGStreamer> existingTrack = m_audioTracks[i];
+            existingTrack->setIndex(i);
+            if (existingTrack->pad() == pad)
+                continue;
+        }
+
+        RefPtr<AudioTrackPrivateGStreamer> track = AudioTrackPrivateGStreamer::create(m_playBin, i, pad);
+        m_audioTracks.insert(i, track);
+        m_player->addAudioTrack(track.release());
+    }
+
+    while (static_cast<gint>(m_audioTracks.size()) > numTracks) {
+        RefPtr<AudioTrackPrivateGStreamer> track = m_audioTracks.last();
+        track->disconnect();
+        m_audioTracks.removeLast();
+        m_player->removeAudioTrack(track.release());
+    }
+#endif
+
     m_player->mediaPlayerClient()->mediaPlayerEngineUpdated(m_player);
 }
 
index 1a355cd..d1c983a 100644 (file)
@@ -39,7 +39,9 @@ typedef struct _GstElement GstElement;
 
 namespace WebCore {
 
+class AudioTrackPrivateGStreamer;
 class InbandTextTrackPrivateGStreamer;
+class VideoTrackPrivateGStreamer;
 
 class MediaPlayerPrivateGStreamer : public MediaPlayerPrivateGStreamerBase {
 public:
@@ -88,8 +90,10 @@ public:
     void loadingFailed(MediaPlayer::NetworkState);
 
     void videoChanged();
+    void videoCapsChanged();
     void audioChanged();
     void notifyPlayerOfVideo();
+    void notifyPlayerOfVideoCaps();
     void notifyPlayerOfAudio();
 
 #if ENABLE(VIDEO_TRACK) && defined(GST_API_VERSION_1)
@@ -181,6 +185,7 @@ private:
     guint m_audioTimerHandler;
     guint m_textTimerHandler;
     guint m_videoTimerHandler;
+    guint m_videoCapsTimerHandler;
     guint m_readyTimerHandler;
     GRefPtr<GstElement> m_webkitAudioSink;
     mutable long m_totalBytes;
@@ -190,7 +195,9 @@ private:
     GRefPtr<GstElement> m_autoAudioSink;
     bool m_missingPlugins;
 #if ENABLE(VIDEO_TRACK) && defined(GST_API_VERSION_1)
-    Vector<RefPtr<InbandTextTrackPrivateGStreamer> > m_textTracks;
+    Vector<RefPtr<AudioTrackPrivateGStreamer>> m_audioTracks;
+    Vector<RefPtr<InbandTextTrackPrivateGStreamer>> m_textTracks;
+    Vector<RefPtr<VideoTrackPrivateGStreamer>> m_videoTracks;
     RefPtr<InbandTextTrackPrivate> m_chaptersTrack;
 #endif
 };
diff --git a/Source/WebCore/platform/graphics/gstreamer/TrackPrivateBaseGStreamer.cpp b/Source/WebCore/platform/graphics/gstreamer/TrackPrivateBaseGStreamer.cpp
new file mode 100644 (file)
index 0000000..a3c45ef
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2013 Cable Television Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(VIDEO) && USE(GSTREAMER) && ENABLE(VIDEO_TRACK) && defined(GST_API_VERSION_1)
+
+#include "TrackPrivateBaseGStreamer.h"
+
+#include "GStreamerUtilities.h"
+#include "Logging.h"
+#include <glib-object.h>
+#include <gst/gst.h>
+
+GST_DEBUG_CATEGORY_EXTERN(webkit_media_player_debug);
+#define GST_CAT_DEFAULT webkit_media_player_debug
+
+namespace WebCore {
+
+static void trackPrivateActiveChangedCallback(GObject*, GParamSpec*, TrackPrivateBaseGStreamer* track)
+{
+    track->activeChanged();
+}
+
+static void trackPrivateTagsChangedCallback(GObject*, GParamSpec*, TrackPrivateBaseGStreamer* track)
+{
+    track->tagsChanged();
+}
+
+static gboolean trackPrivateActiveChangeTimeoutCallback(TrackPrivateBaseGStreamer* track)
+{
+    track->notifyTrackOfActiveChanged();
+    return FALSE;
+}
+
+static gboolean trackPrivateTagsChangeTimeoutCallback(TrackPrivateBaseGStreamer* track)
+{
+    track->notifyTrackOfTagsChanged();
+    return FALSE;
+}
+
+TrackPrivateBaseGStreamer::TrackPrivateBaseGStreamer(const char* notifyActiveSignal, GRefPtr<GstElement> playbin, gint index, GRefPtr<GstPad> pad)
+    : m_index(index)
+    , m_playbin(playbin)
+    , m_pad(pad)
+    , m_activeTimerHandler(0)
+    , m_tagTimerHandler(0)
+{
+    ASSERT(m_pad);
+    g_signal_connect(m_playbin.get(), notifyActiveSignal, G_CALLBACK(trackPrivateActiveChangedCallback), this);
+    g_signal_connect(m_pad.get(), "notify::tags", G_CALLBACK(trackPrivateTagsChangedCallback), this);
+}
+
+TrackPrivateBaseGStreamer::~TrackPrivateBaseGStreamer()
+{
+    disconnect();
+}
+
+void TrackPrivateBaseGStreamer::disconnect()
+{
+    if (!m_pad)
+        return;
+
+    g_signal_handlers_disconnect_by_func(m_pad.get(),
+        reinterpret_cast<gpointer>(trackPrivateActiveChangedCallback), this);
+    g_signal_handlers_disconnect_by_func(m_pad.get(),
+        reinterpret_cast<gpointer>(trackPrivateTagsChangedCallback), this);
+
+    if (m_activeTimerHandler)
+        g_source_remove(m_activeTimerHandler);
+
+    if (m_tagTimerHandler)
+        g_source_remove(m_tagTimerHandler);
+
+    m_pad.clear();
+    m_playbin.clear();
+}
+
+void TrackPrivateBaseGStreamer::activeChanged()
+{
+    if (m_activeTimerHandler)
+        g_source_remove(m_activeTimerHandler);
+    m_activeTimerHandler = g_timeout_add(0,
+        reinterpret_cast<GSourceFunc>(trackPrivateActiveChangeTimeoutCallback), this);
+}
+
+void TrackPrivateBaseGStreamer::tagsChanged()
+{
+    if (m_tagTimerHandler)
+        g_source_remove(m_tagTimerHandler);
+    m_tagTimerHandler = g_timeout_add(0,
+        reinterpret_cast<GSourceFunc>(trackPrivateTagsChangeTimeoutCallback), this);
+}
+
+void TrackPrivateBaseGStreamer::notifyTrackOfActiveChanged()
+{
+    if (!m_pad)
+        return;
+
+    gboolean active = false;
+    if (m_pad)
+        g_object_get(m_pad.get(), "active", &active, NULL);
+
+    setActive(active);
+}
+
+void TrackPrivateBaseGStreamer::notifyTrackOfTagsChanged()
+{
+    m_tagTimerHandler = 0;
+    if (!m_pad)
+        return;
+
+    String label;
+    String language;
+    GRefPtr<GstTagList> tags;
+    g_object_get(m_pad.get(), "tags", &tags.outPtr(), NULL);
+    if (tags) {
+        gchar* tagValue;
+        if (gst_tag_list_get_string(tags.get(), GST_TAG_TITLE, &tagValue)) {
+            INFO_MEDIA_MESSAGE("Video track %d got title %s.", m_index, tagValue);
+            label = tagValue;
+            g_free(tagValue);
+        }
+
+        if (gst_tag_list_get_string(tags.get(), GST_TAG_LANGUAGE_CODE, &tagValue)) {
+            INFO_MEDIA_MESSAGE("Video track %d got language %s.", m_index, tagValue);
+            language = tagValue;
+            g_free(tagValue);
+        }
+    }
+
+    if (m_label != label) {
+        m_label = label;
+        labelChanged(m_label);
+    }
+
+    if (m_language != language) {
+        m_language = language;
+        languageChanged(m_language);
+    }
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(VIDEO) && USE(GSTREAMER) && ENABLE(VIDEO_TRACK) && defined(GST_API_VERSION_1)
diff --git a/Source/WebCore/platform/graphics/gstreamer/TrackPrivateBaseGStreamer.h b/Source/WebCore/platform/graphics/gstreamer/TrackPrivateBaseGStreamer.h
new file mode 100644 (file)
index 0000000..2c81173
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2013 Cable Television Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TrackPrivateBaseGStreamer_h
+#define TrackPrivateBaseGStreamer_h
+
+#if ENABLE(VIDEO) && USE(GSTREAMER) && ENABLE(VIDEO_TRACK) && defined(GST_API_VERSION_1)
+
+#include "GRefPtrGStreamer.h"
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class TrackPrivateBaseGStreamer {
+public:
+    virtual ~TrackPrivateBaseGStreamer();
+
+    virtual void labelChanged(const String&) = 0;
+    virtual void languageChanged(const String&) = 0;
+
+    GstPad* pad() const { return m_pad.get(); }
+
+    void disconnect();
+
+    virtual void setActive(bool) = 0;
+
+    void setIndex(int index) { m_index =  index; }
+
+    void activeChanged();
+    void tagsChanged();
+
+    void notifyTrackOfActiveChanged();
+    void notifyTrackOfTagsChanged();
+
+protected:
+    TrackPrivateBaseGStreamer(const char* notifyActiveSignal, GRefPtr<GstElement> playbin, gint index, GRefPtr<GstPad>);
+
+    gint m_index;
+    GRefPtr<GstElement> m_playbin;
+
+private:
+    GRefPtr<GstPad> m_pad;
+    String m_label;
+    String m_language;
+    guint m_activeTimerHandler;
+    guint m_tagTimerHandler;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(VIDEO) && USE(GSTREAMER) && ENABLE(VIDEO_TRACK) && defined(GST_API_VERSION_1)
+
+#endif // TrackPrivateBaseGStreamer_h
diff --git a/Source/WebCore/platform/graphics/gstreamer/VideoTrackPrivateGStreamer.cpp b/Source/WebCore/platform/graphics/gstreamer/VideoTrackPrivateGStreamer.cpp
new file mode 100644 (file)
index 0000000..958c929
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2013 Cable Television Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(VIDEO) && USE(GSTREAMER) && ENABLE(VIDEO_TRACK) && defined(GST_API_VERSION_1)
+
+#include "VideoTrackPrivateGStreamer.h"
+
+#include <glib-object.h>
+
+namespace WebCore {
+
+VideoTrackPrivateGStreamer::VideoTrackPrivateGStreamer(GRefPtr<GstElement> playbin, gint index, GRefPtr<GstPad> pad)
+    : TrackPrivateBaseGStreamer("notify::current-video", playbin, index, pad)
+{
+    activeChanged();
+    tagsChanged();
+}
+
+void VideoTrackPrivateGStreamer::setSelected(bool selected)
+{
+    if (selected == this->selected())
+        return;
+    VideoTrackPrivate::setSelected(selected);
+
+    if (selected && m_playbin)
+        g_object_set(m_playbin.get(), "current-video", m_index, NULL);
+}
+
+void VideoTrackPrivateGStreamer::labelChanged(const String& label)
+{
+    if (client())
+        client()->labelChanged(this, label);
+}
+
+void VideoTrackPrivateGStreamer::languageChanged(const String& language)
+{
+    if (client())
+        client()->languageChanged(this, language);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(VIDEO) && USE(GSTREAMER) && ENABLE(VIDEO_TRACK) && defined(GST_API_VERSION_1)
diff --git a/Source/WebCore/platform/graphics/gstreamer/VideoTrackPrivateGStreamer.h b/Source/WebCore/platform/graphics/gstreamer/VideoTrackPrivateGStreamer.h
new file mode 100644 (file)
index 0000000..6f321bb
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2013 Cable Television Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef VideoTrackPrivateGStreamer_h
+#define VideoTrackPrivateGStreamer_h
+
+#if ENABLE(VIDEO) && USE(GSTREAMER) && ENABLE(VIDEO_TRACK) && defined(GST_API_VERSION_1)
+
+#include "GRefPtrGStreamer.h"
+#include "TrackPrivateBaseGStreamer.h"
+#include "VideoTrackPrivate.h"
+
+namespace WebCore {
+
+class VideoTrackPrivateGStreamer FINAL : public VideoTrackPrivate, public TrackPrivateBaseGStreamer {
+public:
+    static PassRefPtr<VideoTrackPrivateGStreamer> create(GRefPtr<GstElement> playbin, gint index, GRefPtr<GstPad> pad)
+    {
+        return adoptRef(new VideoTrackPrivateGStreamer(playbin, index, pad));
+    }
+
+    virtual void setSelected(bool) OVERRIDE;
+    virtual void setActive(bool enabled) OVERRIDE { setSelected(enabled); }
+
+    virtual int videoTrackIndex() const OVERRIDE { return m_index; }
+    virtual void labelChanged(const String&) OVERRIDE;
+    virtual void languageChanged(const String&) OVERRIDE;
+
+private:
+    VideoTrackPrivateGStreamer(GRefPtr<GstElement> playbin, gint index, GRefPtr<GstPad>);
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(VIDEO) && USE(GSTREAMER) && ENABLE(VIDEO_TRACK) && defined(GST_API_VERSION_1)
+
+#endif // VideoTrackPrivateGStreamer_h