Support "forced" subtitles

https://bugs.webkit.org/show_bug.cgi?id=114460

Reviewed by Jer Noble.

Source/WebCore: 

Test: media/track/track-forced-subtitles.html

* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::configureTextTrackGroup): Enable a forced track if nothing else is enabled.
(WebCore::HTMLMediaElement::configureTextTracks): Include forced tracks with captions+subtitles.

* html/track/InbandTextTrack.cpp:
(WebCore::InbandTextTrack::InbandTextTrack): Deal with kind=forced.

* html/track/TextTrack.cpp:
(WebCore::TextTrack::forcedKeyword): New keyword.
(WebCore::TextTrack::isValidKindKeyword): Include forced.
(WebCore::TextTrack::platformTextTrack): Ditto.
* html/track/TextTrack.h:

* page/CaptionUserPreferences.cpp:
(WebCore::CaptionUserPreferences::primaryAudioTrackLanguageOverride): New override to support testing.
* page/CaptionUserPreferences.h:

* page/CaptionUserPreferencesMac.mm:
(WebCore::CaptionUserPreferencesMac::textTrackSelectionScore): Support forced tracks.
* platform/graphics/InbandTextTrackPrivate.h:

* platform/graphics/PlatformTextTrack.h: Add Forced, minor cleanup.

* platform/graphics/avfoundation/InbandTextTrackPrivateAVF.cpp:
(WebCore::InbandTextTrackPrivateAVF::processCue): Drive-by enhancement: log cue position.

* platform/graphics/avfoundation/objc/InbandTextTrackPrivateAVFObjC.mm:
(WebCore::InbandTextTrackPrivateAVFObjC::kind): Support forced.
(WebCore::InbandTextTrackPrivateAVFObjC::label): Drive-by cleanup.

* platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:
(WebCore::MediaPlayerPrivateAVFoundationObjC::processTextTracks): Don't filter out forced tracks.
(WebCore::MediaPlayerPrivateAVFoundationObjC::languageOfPrimaryAudioTrack): Log the language returned.

* testing/Internals.cpp:
(WebCore::Internals::setPrimaryAudioTrackLanguageOverride): New.
(WebCore::Internals::setCaptionDisplayMode): New.
* testing/Internals.h:
* testing/Internals.idl:

LayoutTests: 

* media/content/CC+Subtitles.m4v: Added.
* media/track/track-forced-subtitles-in-band-expected.txt: Added.
* media/track/track-forced-subtitles-in-band.html: Added.
* media/trackmenu-test.js:

* platform/efl/TestExpectations: Skip new test.
* platform/gtk/TestExpectations: Ditto.
* platform/mac/TestExpectations: Ditto.
* platform/qt/TestExpectations: Ditto.
* platform/win/TestExpectations: Ditto.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@148285 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 58481e6f
2013-04-12 Eric Carlson <eric.carlson@apple.com>
Support "forced" subtitles
https://bugs.webkit.org/show_bug.cgi?id=114460
Reviewed by Jer Noble.
* media/content/CC+Subtitles.m4v: Added.
* media/track/track-forced-subtitles-in-band-expected.txt: Added.
* media/track/track-forced-subtitles-in-band.html: Added.
* media/trackmenu-test.js:
* platform/efl/TestExpectations: Skip new test.
* platform/gtk/TestExpectations: Ditto.
* platform/mac/TestExpectations: Ditto.
* platform/qt/TestExpectations: Ditto.
* platform/win/TestExpectations: Ditto.
2013-04-12 Ryosuke Niwa <rniwa@webkit.org>
[Mac] Enable spellchecking tests added in r141471
Tests that forced subtitles are enable automatically.
RUN(internals.settings.setShouldDisplayTrackKind('Captions', false))
RUN(internals.settings.setShouldDisplayTrackKind('Subtitles', true))
RUN(internals.setUserPreferredLanguages(['en']))
RUN(internals.setPrimaryAudioTrackLanguageOverride('fr'))
RUN(internals.setCaptionDisplayMode('ForcedOnly'))
EVENT(canplaythrough)
** Forced tracks should be in .textTracks, but not in the menu
EXPECTED (video.textTracks.length == '9') OK
EXPECTED (trackMenuItems.length == '6') OK
** Only the 'fr' forced track should be showing
EXPECTED (video.textTracks[0].language == 'en') OK
EXPECTED (video.textTracks[0].kind == 'subtitles') OK
EXPECTED (video.textTracks[0].mode == 'disabled') OK
EXPECTED (video.textTracks[1].language == 'en') OK
EXPECTED (video.textTracks[1].kind == 'forced') OK
EXPECTED (video.textTracks[1].mode == 'disabled') OK
EXPECTED (video.textTracks[2].language == 'fr') OK
EXPECTED (video.textTracks[2].kind == 'subtitles') OK
EXPECTED (video.textTracks[2].mode == 'disabled') OK
EXPECTED (video.textTracks[3].language == 'fr') OK
EXPECTED (video.textTracks[3].kind == 'forced') OK
EXPECTED (video.textTracks[3].mode == 'showing') OK
EXPECTED (video.textTracks[4].language == 'es') OK
EXPECTED (video.textTracks[4].kind == 'subtitles') OK
EXPECTED (video.textTracks[4].mode == 'disabled') OK
EXPECTED (video.textTracks[5].language == 'es') OK
EXPECTED (video.textTracks[5].kind == 'forced') OK
EXPECTED (video.textTracks[5].mode == 'disabled') OK
EXPECTED (video.textTracks[6].language == 'de') OK
EXPECTED (video.textTracks[6].kind == 'subtitles') OK
EXPECTED (video.textTracks[6].mode == 'disabled') OK
EXPECTED (video.textTracks[7].language == 'de') OK
EXPECTED (video.textTracks[7].kind == 'forced') OK
EXPECTED (video.textTracks[7].mode == 'disabled') OK
EXPECTED (video.textTracks[8].language == 'en') OK
EXPECTED (video.textTracks[8].kind == 'captions') OK
EXPECTED (video.textTracks[8].mode == 'disabled') OK
END OF TEST
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script src=../media-controls.js></script>
<script src=../trackmenu-test.js></script>
<script src=../video-test.js></script>
<script>
var test = 0;
function testForced()
{
consoleWrite("<br><i>** Forced tracks should be in .textTracks, but not in the menu<" + "/i>");
testExpected("video.textTracks.length", 9);
// Click the CC button to show the menu because it isn't created until it becomes visible.
clickCCButton();
trackMenuItems = trackMenuList();
if (!trackMenuItems)
return;
testExpected("trackMenuItems.length", 6);
consoleWrite("<br><i>** Only the 'fr' forced track should be showing<" + "/i>");
testExpected("video.textTracks[0].language", "en");
testExpected("video.textTracks[0].kind", "subtitles");
testExpected("video.textTracks[0].mode", "disabled");
consoleWrite("");
testExpected("video.textTracks[1].language", "en");
testExpected("video.textTracks[1].kind", "forced");
testExpected("video.textTracks[1].mode", "disabled");
consoleWrite("");
testExpected("video.textTracks[2].language", "fr");
testExpected("video.textTracks[2].kind", "subtitles");
testExpected("video.textTracks[2].mode", "disabled");
consoleWrite("");
testExpected("video.textTracks[3].language", "fr");
testExpected("video.textTracks[3].kind", "forced");
testExpected("video.textTracks[3].mode", "showing");
consoleWrite("");
testExpected("video.textTracks[4].language", "es");
testExpected("video.textTracks[4].kind", "subtitles");
testExpected("video.textTracks[4].mode", "disabled");
consoleWrite("");
testExpected("video.textTracks[5].language", "es");
testExpected("video.textTracks[5].kind", "forced");
testExpected("video.textTracks[5].mode", "disabled");
consoleWrite("");
testExpected("video.textTracks[6].language", "de");
testExpected("video.textTracks[6].kind", "subtitles");
testExpected("video.textTracks[6].mode", "disabled");
consoleWrite("");
testExpected("video.textTracks[7].language", "de");
testExpected("video.textTracks[7].kind", "forced");
testExpected("video.textTracks[7].mode", "disabled");
consoleWrite("");
testExpected("video.textTracks[8].language", "en");
testExpected("video.textTracks[8].kind", "captions");
testExpected("video.textTracks[8].mode", "disabled");
consoleWrite("");
endTest();
}
function setup()
{
findMediaElement();
run("internals.settings.setShouldDisplayTrackKind('Captions', false)");
run("internals.settings.setShouldDisplayTrackKind('Subtitles', true)");
run("internals.setUserPreferredLanguages(['en'])");
run("internals.setPrimaryAudioTrackLanguageOverride('fr')");
run("internals.setCaptionDisplayMode('ForcedOnly')");
video.src = '../content/CC+Subtitles.m4v';
video.volume = 0;
waitForEvent('canplaythrough', testForced);
}
</script>
</head>
<body onload="setup()">
<p>Tests that forced subtitles are enable automatically.</p>
<video width="640" height="360" controls>
</video>
</body>
</html>
var captionsButtonCoordinates;
var captionsButtonCoordinates = null;
function clickCCButton()
{
if (!captionsButtonCoordinates) {
try {
captionsButtonCoordinates = mediaControlsButtonCoordinates(video, "toggle-closed-captions-button");
} catch (exception) {
failTest(exception.description);
return;
}
}
eventSender.mouseMoveTo(captionsButtonCoordinates[0], captionsButtonCoordinates[1]);
eventSender.mouseDown();
eventSender.mouseUp();
......@@ -13,12 +22,6 @@ function startTrackMenuTest(testFunction)
consoleWrite("<br>*** Set the user language preference.");
run("internals.setUserPreferredLanguages(['en'])");
try {
captionsButtonCoordinates = mediaControlsButtonCoordinates(video, "toggle-closed-captions-button");
} catch (exception) {
failTest(exception.description);
return;
}
clickCCButton();
window.setTimeout(testFunction, 100);
}
......
......@@ -1637,6 +1637,7 @@ Bug(EFL) media/track/track-in-band.html [ Skip ]
Bug(EFL) media/track/track-in-band-cues-added-once.html [ Skip ]
Bug(EFL) media/track/track-in-band-style.html [ Skip ]
Bug(EFL) media/track/track-in-band-legacy-api.html [ Skip ]
Bug(EFL) media/track/track-forced-subtitles-in-band.html [ Skip ]
# All debug bots timeout (crash) on this one
webkit.org/b/56496 [ Debug ] fast/js/array-sort-modifying-tostring.html [ Crash Pass ]
......
......@@ -403,6 +403,7 @@ webkit.org/b/103771 media/track/track-in-band.html [ Failure ]
webkit.org/b/103771 media/track/track-in-band-cues-added-once.html [ Timeout ]
webkit.org/b/103771 media/track/track-in-band-style.html [ Timeout ]
webkit.org/b/103771 media/track/track-in-band-legacy-api.html [ Failure ]
webkit.org/b/103771 media/track/track-forced-subtitles-in-band.html [ Failure ]
#Incorrect rebaseline
webkit.org/b/107818 media/controls-styling.html [ Failure ]
......
......@@ -1366,6 +1366,7 @@ webkit.org/b/103663 [ MountainLion Lion SnowLeopard ] media/track/track-in-band.
webkit.org/b/103663 [ MountainLion Lion SnowLeopard ] media/track/track-in-band-cues-added-once.html
webkit.org/b/103663 [ MountainLion Lion SnowLeopard ] media/track/track-in-band-style.html
webkit.org/b/103663 [ MountainLion Lion SnowLeopard ] media/track/track-in-band-legacy-api.html
webkit.org/b/103663 [ MountainLion Lion SnowLeopard ] media/track/track-forced-subtitles-in-band.html
# These two tests sometimes timeout
webkit.org/b/112492 media/track/track-language-preference.html [ Failure Pass ]
......
......@@ -2623,6 +2623,7 @@ webkit.org/b/103769 media/track/track-in-band.html [ Skip ]
webkit.org/b/103769 media/track/track-in-band-cues-added-once.html [ Skip ]
webkit.org/b/103769 media/track/track-in-band-style.html [ Skip ]
webkit.org/b/103769 media/track/track-in-band-legacy-api.html [ Skip ]
webkit.org/b/103769 media/track/track-forced-subtitles-in-band.html [ Skip ]
webkit.org/b/104150 fast/media/implicit-media-all.html [ ImageOnlyFailure ]
......
......@@ -2539,6 +2539,7 @@ webkit.org/b/103770 media/track/track-in-band.html [ Skip ]
webkit.org/b/103770 media/track/track-in-band-cues-added-once.html [ Skip ]
webkit.org/b/103770 media/track/track-in-band-style.html [ Skip ]
webkit.org/b/103770 media/track/track-in-band-legacy-api.html [ Skip ]
webkit.org/b/103770 media/track/track-forced-subtitles-in-band.html [ Skip ]
# https://bugs.webkit.org/show_bug.cgi?id=97026
fast/events/keydown-leftright-keys.html
......
2013-04-12 Eric Carlson <eric.carlson@apple.com>
Support "forced" subtitles
https://bugs.webkit.org/show_bug.cgi?id=114460
Reviewed by Jer Noble.
Test: media/track/track-forced-subtitles.html
* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::configureTextTrackGroup): Enable a forced track if nothing else is enabled.
(WebCore::HTMLMediaElement::configureTextTracks): Include forced tracks with captions+subtitles.
* html/track/InbandTextTrack.cpp:
(WebCore::InbandTextTrack::InbandTextTrack): Deal with kind=forced.
* html/track/TextTrack.cpp:
(WebCore::TextTrack::forcedKeyword): New keyword.
(WebCore::TextTrack::isValidKindKeyword): Include forced.
(WebCore::TextTrack::platformTextTrack): Ditto.
* html/track/TextTrack.h:
* page/CaptionUserPreferences.cpp:
(WebCore::CaptionUserPreferences::primaryAudioTrackLanguageOverride): New override to support testing.
* page/CaptionUserPreferences.h:
* page/CaptionUserPreferencesMac.mm:
(WebCore::CaptionUserPreferencesMac::textTrackSelectionScore): Support forced tracks.
* platform/graphics/InbandTextTrackPrivate.h:
* platform/graphics/PlatformTextTrack.h: Add Forced, minor cleanup.
* platform/graphics/avfoundation/InbandTextTrackPrivateAVF.cpp:
(WebCore::InbandTextTrackPrivateAVF::processCue): Drive-by enhancement: log cue position.
* platform/graphics/avfoundation/objc/InbandTextTrackPrivateAVFObjC.mm:
(WebCore::InbandTextTrackPrivateAVFObjC::kind): Support forced.
(WebCore::InbandTextTrackPrivateAVFObjC::label): Drive-by cleanup.
* platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:
(WebCore::MediaPlayerPrivateAVFoundationObjC::processTextTracks): Don't filter out forced tracks.
(WebCore::MediaPlayerPrivateAVFoundationObjC::languageOfPrimaryAudioTrack): Log the language returned.
* testing/Internals.cpp:
(WebCore::Internals::setPrimaryAudioTrackLanguageOverride): New.
(WebCore::Internals::setCaptionDisplayMode): New.
* testing/Internals.h:
* testing/Internals.idl:
2013-04-12 Ryosuke Niwa <rniwa@webkit.org>
[Mac] Some ligatures are applied across different fronts
......@@ -3074,7 +3074,9 @@ void HTMLMediaElement::configureTextTrackGroup(const TrackGroup& group)
RefPtr<TextTrack> trackToEnable;
RefPtr<TextTrack> defaultTrack;
RefPtr<TextTrack> fallbackTrack;
RefPtr<TextTrack> forcedSubitleTrack;
int highestTrackScore = 0;
int highestForcedScore = 0;
for (size_t i = 0; i < group.tracks.size(); ++i) {
RefPtr<TextTrack> textTrack = group.tracks[i];
......@@ -3101,6 +3103,10 @@ void HTMLMediaElement::configureTextTrackGroup(const TrackGroup& group)
defaultTrack = textTrack;
if (!defaultTrack && !fallbackTrack)
fallbackTrack = textTrack;
if (textTrack->containsOnlyForcedSubtitles() && trackScore > highestForcedScore) {
forcedSubitleTrack = textTrack;
highestForcedScore = trackScore;
}
} else if (!group.visibleTrack && !defaultTrack && textTrack->isDefault()) {
// * If the track element has a default attribute specified, and there is no other text track in the media
// element's list of text tracks whose text track mode is showing or showing by default
......@@ -3112,6 +3118,11 @@ void HTMLMediaElement::configureTextTrackGroup(const TrackGroup& group)
if (!trackToEnable && defaultTrack)
trackToEnable = defaultTrack;
// If no track matches the user's preferred language, none was marked as 'default', and there is a forced subtitle track
// in the same language as the language of the primary audio track, enable it.
if (!trackToEnable && forcedSubitleTrack)
trackToEnable = forcedSubitleTrack;
// If no track matches the user's preferred language and non was marked 'default', enable the first track
// because the user has explicitly stated a preference for this kind of track.
if (!trackToEnable && fallbackTrack)
......@@ -3189,7 +3200,7 @@ void HTMLMediaElement::configureTextTracks()
String kind = textTrack->kind();
TrackGroup* currentGroup;
if (kind == TextTrack::subtitlesKeyword() || kind == TextTrack::captionsKeyword())
if (kind == TextTrack::subtitlesKeyword() || kind == TextTrack::captionsKeyword() || kind == TextTrack::forcedKeyword())
currentGroup = &captionAndSubtitleTracks;
else if (kind == TextTrack::descriptionsKeyword())
currentGroup = &descriptionTracks;
......
......@@ -69,6 +69,9 @@ InbandTextTrack::InbandTextTrack(ScriptExecutionContext* context, TextTrackClien
case InbandTextTrackPrivate::Metadata:
setKind(TextTrack::metadataKeyword());
break;
case InbandTextTrackPrivate::Forced:
setKind(TextTrack::forcedKeyword());
break;
case InbandTextTrackPrivate::None:
default:
ASSERT_NOT_REACHED();
......
......@@ -76,6 +76,12 @@ const AtomicString& TextTrack::metadataKeyword()
DEFINE_STATIC_LOCAL(const AtomicString, metadata, ("metadata", AtomicString::ConstructFromLiteral));
return metadata;
}
const AtomicString& TextTrack::forcedKeyword()
{
DEFINE_STATIC_LOCAL(const AtomicString, forced, ("forced", AtomicString::ConstructFromLiteral));
return forced;
}
const AtomicString& TextTrack::disabledKeyword()
{
......@@ -155,6 +161,8 @@ bool TextTrack::isValidKindKeyword(const AtomicString& value)
return true;
if (value == metadataKeyword())
return true;
if (value == forcedKeyword())
return true;
return false;
}
......@@ -513,6 +521,8 @@ PassRefPtr<PlatformTextTrack> TextTrack::platformTextTrack()
kind = PlatformTextTrack::Chapter;
else if (m_kind == metadataKeyword())
kind = PlatformTextTrack::MetaData;
else if (m_kind == forcedKeyword())
kind = PlatformTextTrack::Forced;
PlatformTextTrack::TrackType type = PlatformTextTrack::OutOfBand;
if (m_trackType == TrackElement)
......
......@@ -87,6 +87,7 @@ public:
static const AtomicString& descriptionsKeyword();
static const AtomicString& chaptersKeyword();
static const AtomicString& metadataKeyword();
static const AtomicString& forcedKeyword();
static bool isValidKindKeyword(const AtomicString&);
AtomicString label() const { return m_label; }
......
......@@ -244,6 +244,12 @@ void CaptionUserPreferences::updateCaptionStyleSheetOveride()
Vector<String>(), InjectInAllFrames, UserStyleAuthorLevel, InjectInExistingDocuments);
}
String CaptionUserPreferences::primaryAudioTrackLanguageOverride() const
{
if (!m_primaryAudioTrackLanguageOverride.isEmpty())
return m_primaryAudioTrackLanguageOverride;
return defaultLanguage();
}
}
......
......@@ -81,6 +81,9 @@ public:
virtual String displayNameForTrack(TextTrack*) const;
virtual Vector<RefPtr<TextTrack> > sortedTrackListForMenu(TextTrackList*);
void setPrimaryAudioTrackLanguageOverride(const String& language) { m_primaryAudioTrackLanguageOverride = language; }
String primaryAudioTrackLanguageOverride() const;
virtual bool testingMode() const { return m_testingMode; }
virtual void setTestingMode(bool override) { m_testingMode = override; }
......@@ -99,6 +102,7 @@ private:
Timer<CaptionUserPreferences> m_timer;
String m_userPreferredLanguage;
String m_captionsStyleSheetOverride;
String m_primaryAudioTrackLanguageOverride;
bool m_testingMode;
bool m_havePreferences;
};
......
......@@ -619,37 +619,54 @@ String CaptionUserPreferencesMac::displayNameForTrack(TextTrack* track) const
int CaptionUserPreferencesMac::textTrackSelectionScore(TextTrack* track, HTMLMediaElement* mediaElement) const
{
CaptionDisplayMode displayMode = captionDisplayMode();
if (displayMode == ForcedOnly)
return 0;
if (displayMode == AlwaysOn && (!userPrefersSubtitles() && !userPrefersCaptions()))
return 0;
if (track->kind() != TextTrack::captionsKeyword() && track->kind() != TextTrack::subtitlesKeyword())
return 0;
if (track->containsOnlyForcedSubtitles())
if (track->kind() != TextTrack::captionsKeyword() && track->kind() != TextTrack::subtitlesKeyword() && track->kind() != TextTrack::forcedKeyword())
return 0;
if (!track->isMainProgramContent())
return 0;
if (displayMode == ForcedOnly && !track->containsOnlyForcedSubtitles())
return 0;
Vector<String> userPreferredCaptionLanguages = preferredLanguages();
if (displayMode == Automatic) {
if (displayMode == Automatic || track->containsOnlyForcedSubtitles()) {
// Only enable a text track if the current audio track is not in the user's preferred language.
if (!mediaElement || !mediaElement->player())
return 0;
String audioTrackLanguage = mediaElement->player()->languageOfPrimaryAudioTrack();
String audioTrackLanguage;
Vector<String> languageList;
languageList.reserveCapacity(1);
if (testingMode())
audioTrackLanguage = primaryAudioTrackLanguageOverride();
else
audioTrackLanguage = mediaElement->player()->languageOfPrimaryAudioTrack();
if (audioTrackLanguage.isEmpty())
return 0;
Vector<String> languages;
languages.append(defaultLanguage());
size_t offset = indexOfBestMatchingLanguageInList(audioTrackLanguage, languages);
if (!offset)
return 0;
if (displayMode == Automatic) {
// Only enable a text track if the current audio track is not in the user's preferred language.
languageList.append(defaultLanguage());
size_t offset = indexOfBestMatchingLanguageInList(audioTrackLanguage, languageList);
if (offset)
return 0;
} else {
// Only consider a forced-only track if it is in the same language as the primary audio track.
String trackLanguage = track->language();
if (trackLanguage.isEmpty())
return 0;
languageList.append(audioTrackLanguage);
size_t offset = indexOfBestMatchingLanguageInList(trackLanguage, languageList);
if (offset)
return 0;
}
userPreferredCaptionLanguages = languages;
userPreferredCaptionLanguages = languageList;
}
int trackScore = 0;
......
......@@ -49,11 +49,23 @@ public:
void setClient(InbandTextTrackPrivateClient* client) { m_client = client; }
InbandTextTrackPrivateClient* client() { return m_client; }
enum Mode { Disabled, Hidden, Showing };
enum Mode {
Disabled,
Hidden,
Showing
};
virtual void setMode(Mode mode) { m_mode = mode; };
virtual InbandTextTrackPrivate::Mode mode() const { return m_mode; }
enum Kind { Subtitles, Captions, Descriptions, Chapters, Metadata, None };
enum Kind {
Subtitles,
Captions,
Descriptions,
Chapters,
Metadata,
Forced,
None
};
virtual Kind kind() const { return Subtitles; }
virtual bool isClosedCaptions() const { return false; }
virtual bool containsOnlyForcedSubtitles() const { return false; }
......
......@@ -46,8 +46,19 @@ public:
class PlatformTextTrack : public RefCounted<PlatformTextTrack> {
public:
enum TrackKind { Subtitle = 0, Caption = 1, Description = 2, Chapter = 3, MetaData = 4 };
enum TrackType { InBand = 0, OutOfBand = 1, Script = 2 };
enum TrackKind {
Subtitle = 0,
Caption = 1,
Description = 2,
Chapter = 3,
MetaData = 4,
Forced = 5,
};
enum TrackType {
InBand = 0,
OutOfBand = 1,
Script = 2
};
static PassRefPtr<PlatformTextTrack> create(PlatformTextTrackClient* client, const String& label, const String& language, TrackKind kind, TrackType type)
{
......
......@@ -356,7 +356,7 @@ void InbandTextTrackPrivateAVF::processCue(CFArrayRef attributedStrings, double
if (cueData->position() >= 0 && cueData->size() > 0)
cueData->setPosition(cueData->position() - cueData->size() / 2);
LOG(Media, "InbandTextTrackPrivateAVF::processCue(%p) - adding cue for time %.2f", this, cueData->startTime());
LOG(Media, "InbandTextTrackPrivateAVF::processCue(%p) - adding cue for time = %.2f, position = %.2f, line = %.2f", this, cueData->startTime(), cueData->position(), cueData->line());
client()->addGenericCue(this, cueData);
}
} else
......
......@@ -99,10 +99,14 @@ InbandTextTrackPrivate::Kind InbandTextTrackPrivateAVFObjC::kind() const
return None;
NSString *mediaType = [m_mediaSelectionOption mediaType];
if ([mediaType isEqualToString:AVMediaTypeClosedCaption])
return Captions;
if ([mediaType isEqualToString:AVMediaTypeSubtitle]) {
if ([m_mediaSelectionOption hasMediaCharacteristic:AVMediaCharacteristicContainsOnlyForcedSubtitles])
return Forced;
// An "SDH" track is a subtitle track created for the deaf or hard-of-hearing. "captions" in WebVTT are
// "labeled as appropriate for the hard-of-hearing", so tag SDH sutitles as "captions".
if ([m_mediaSelectionOption hasMediaCharacteristic:AVMediaCharacteristicTranscribesSpokenDialogForAccessibility])
......@@ -153,17 +157,20 @@ AtomicString InbandTextTrackPrivateAVFObjC::label() const
if (!m_mediaSelectionOption)
return emptyAtom;
NSString *title = 0;
NSArray *titles = [AVMetadataItem metadataItemsFromArray:[m_mediaSelectionOption.get() commonMetadata] withKey:AVMetadataCommonKeyTitle keySpace:AVMetadataKeySpaceCommon];
if ([titles count]) {
// If possible, return a title in one of the user's preferred languages.
NSArray *titlesForPreferredLanguages = [AVMetadataItem metadataItemsFromArray:titles filteredAndSortedAccordingToPreferredLanguages:[NSLocale preferredLanguages]];
if ([titlesForPreferredLanguages count])
return [[titlesForPreferredLanguages objectAtIndex:0] stringValue];
title = [[titlesForPreferredLanguages objectAtIndex:0] stringValue];
return [[titles objectAtIndex:0] stringValue];
if (!title)
title = [[titles objectAtIndex:0] stringValue];
}
return emptyAtom;
return title ? AtomicString(title) : emptyAtom;
}
AtomicString InbandTextTrackPrivateAVFObjC::language() const
......
......@@ -1331,9 +1331,6 @@ void MediaPlayerPrivateAVFoundationObjC::processTextTracks()
if (!newTrack)
continue;
if ([[option mediaType] isEqualToString:AVMediaTypeSubtitle] && [option hasMediaCharacteristic:AVMediaCharacteristicContainsOnlyForcedSubtitles])
continue;
m_textTracks.append(InbandTextTrackPrivateAVFObjC::create(this, option));
}
......@@ -1404,6 +1401,8 @@ String MediaPlayerPrivateAVFoundationObjC::languageOfPrimaryAudioTrack() const
AVMediaSelectionOptionType *currentlySelectedAudibleOption = [m_avPlayerItem.get() selectedMediaOptionInMediaSelectionGroup:audibleGroup];
if (currentlySelectedAudibleOption) {
m_languageOfPrimaryAudioTrack = [[currentlySelectedAudibleOption locale] localeIdentifier];
LOG(Media, "MediaPlayerPrivateAVFoundationObjC::languageOfPrimaryAudioTrack(%p) - returning language of selected audible option: %s", this, m_languageOfPrimaryAudioTrack.utf8().data());
return m_languageOfPrimaryAudioTrack;
}
#endif // HAVE(AVFOUNDATION_TEXT_TRACK_SUPPORT)
......@@ -1413,6 +1412,7 @@ String MediaPlayerPrivateAVFoundationObjC::languageOfPrimaryAudioTrack() const
NSArray *tracks = [m_avAsset.get() tracksWithMediaType:AVMediaTypeAudio];
if (!tracks || [tracks count] != 1) {
m_languageOfPrimaryAudioTrack = emptyString();
LOG(Media, "MediaPlayerPrivateAVFoundationObjC::languageOfPrimaryAudioTrack(%p) - %i audio tracks, returning emptyString()", this, (tracks ? [tracks count] : 0));
return m_languageOfPrimaryAudioTrack;
}
......@@ -1422,9 +1422,11 @@ String MediaPlayerPrivateAVFoundationObjC::languageOfPrimaryAudioTrack() const
// Some legacy tracks have "und" as a language, treat that the same as no language at all.
if (language && ![language isEqualToString:@"und"]) {
m_languageOfPrimaryAudioTrack = language;
LOG(Media, "MediaPlayerPrivateAVFoundationObjC::languageOfPrimaryAudioTrack(%p) - returning language of single audio track: %s", this, m_languageOfPrimaryAudioTrack.utf8().data());
return m_languageOfPrimaryAudioTrack;
}
LOG(Media, "MediaPlayerPrivateAVFoundationObjC::languageOfPrimaryAudioTrack(%p) - single audio track has no language, returning emptyString()", this);
m_languageOfPrimaryAudioTrack = emptyString();
return m_languageOfPrimaryAudioTrack;
}
......
......@@ -2202,4 +2202,43 @@ void Internals::setCaptionsStyleSheetOverride(const String& override, ExceptionC
#endif
}
void Internals::setPrimaryAudioTrackLanguageOverride(const String& language, ExceptionCode& ec)
{
Document* document = contextDocument();
if (!document || !document->page()) {
ec = INVALID_ACCESS_ERR;
return;
}
#if ENABLE(VIDEO_TRACK) && !PLATFORM(WIN)
document->page()->group().captionPreferences()->setPrimaryAudioTrackLanguageOverride(language);
#else
UNUSED_PARAM(language);
#endif
}
void Internals::setCaptionDisplayMode(const String& mode, ExceptionCode& ec)
{
Document* document = contextDocument();
if (!document || !document->page()) {