[Mac] process raw VTT in-band captions
authoreric.carlson@apple.com <eric.carlson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 24 Jun 2014 19:35:47 +0000 (19:35 +0000)
committereric.carlson@apple.com <eric.carlson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 24 Jun 2014 19:35:47 +0000 (19:35 +0000)
https://bugs.webkit.org/show_bug.cgi?id=134178

Reviewed by Jer Noble.

* CMakeLists.txt: Add ISOVTTCue.cpp|h.
* WebCore.vcxproj/WebCore.vcxproj: Ditto.
* WebCore.xcodeproj/project.pbxproj: Ditto.

* html/track/BufferedLineReader.h:
(WebCore::BufferedLineReader::reset): New, empty the input buffer.

Make it possible to process WebVTT captions.
* html/track/InbandGenericTextTrack.cpp:
(WebCore::InbandGenericTextTrack::parser): Allocate, if necessary, and return a WebVTT parser.
(WebCore::InbandGenericTextTrack::parseWebVTTCueData): Pass a cue to the parser.
(WebCore::InbandGenericTextTrack::parseWebVTTFileHeader): Pass a VTT file header to the parser.
(WebCore::InbandGenericTextTrack::newCuesParsed): Parser callback.
(WebCore::InbandGenericTextTrack::newRegionsParsed): Ditto.
(WebCore::InbandGenericTextTrack::fileFailedToParse): Ditto.
* html/track/InbandGenericTextTrack.h:

* html/track/InbandTextTrack.h:

* html/track/InbandWebVTTTextTrack.cpp:
(WebCore::InbandWebVTTTextTrack::parser): New, parser accessor.
(WebCore::InbandWebVTTTextTrack::parseWebVTTCueData): New, parse VTT data in an ISOWebVTTCue
    object.
(WebCore::InbandWebVTTTextTrack::newCuesParsed): Cleanup.
(WebCore::InbandWebVTTTextTrack::newRegionsParsed): Implement.
(WebCore::InbandWebVTTTextTrack::fileFailedToParse): Change the error message.
* html/track/InbandWebVTTTextTrack.h:

* html/track/TextTrackCueGeneric.cpp:
(WebCore::TextTrackCueGenericBoxElement::TextTrackCueGenericBoxElement): Change cue parameter
    from a pointer to a reference.
(WebCore::TextTrackCueGeneric::createDisplayTree): Ditto.

* html/track/VTTCue.cpp:
(WebCore::VTTCueBox::create): Change cue parameter from a pointer to a reference.
(WebCore::VTTCueBox::VTTCueBox): Ditto.
(WebCore::VTTCueBox::getCue): Return a reference.
(WebCore::VTTCueBox::applyCSSProperties): m_cue is a reference, not a pointer.
(WebCore::VTTCue::create): New, create a VTTCue from WebVTTCueData.
(WebCore::VTTCue::VTTCue): New, internal constructor that takes a WebVTTCueData.
(WebCore::VTTCue::initialize): New, shared constructor initialization.
(WebCore::VTTCue::createDisplayTree): m_cue is a reference, not a pointer.
(WebCore::VTTCue::markFutureAndPastNodes): Ditto.
(WebCore::VTTCue::setCueSettings): Ditto.
* html/track/VTTCue.h:
(WebCore::VTTCueBox::create): Deleted.
(WebCore::VTTCue::create): Deleted.

* html/track/WebVTTParser.cpp:
(WebCore::WebVTTParser::parseFileHeader): New. Reset the line reader buffer and parser state,
    call the parser.
(WebCore::WebVTTParser::parseCueData): Create a cue from ISOWebVTTCue.
(WebCore::WebVTTParser::collectTimingsAndSettings): Return immediately if the string is empty.
(WebCore::WebVTTParser::collectTimeStamp): Ditto.
* html/track/WebVTTParser.h:
(WebCore::WebVTTCueData::originalStartTime): New.
(WebCore::WebVTTCueData::setOriginalStartTime): New.
(WebCore::WebVTTCueData::WebVTTCueData):

* loader/TextTrackLoader.cpp:
(WebCore::TextTrackLoader::getNewCues): Cleanup, use the new VTTCue::create.

Parse ISO WebVTT cue boxes.
* platform/graphics/ISOVTTCue.cpp: Added.
(WebCore::ISOBox::ISOBox):
(WebCore::ISOBox::peekType):
(WebCore::ISOBox::peekLength):
(WebCore::ISOBox::peekString):
(WebCore::vttCueBoxType):
(WebCore::vttIdBoxType):
(WebCore::vttSettingsBoxType):
(WebCore::vttPayloadBoxType):
(WebCore::vttCurrentTimeBoxType):
(WebCore::vttCueSourceIDBoxType):
(WebCore::ISOWebVTTCue::boxType):
(WebCore::ISOWebVTTCue::ISOWebVTTCue):
* platform/graphics/ISOVTTCue.h: Added.
(WebCore::ISOBox::boxHeaderSize):
(WebCore::ISOBox::length):
(WebCore::ISOBox::type):
(WebCore::ISOWebVTTCue::presentationTime):
(WebCore::ISOWebVTTCue::duration):
(WebCore::ISOWebVTTCue::sourceID):
(WebCore::ISOWebVTTCue::id):
(WebCore::ISOWebVTTCue::originalStartTime):
(WebCore::ISOWebVTTCue::settings):
(WebCore::ISOWebVTTCue::cueText):

* platform/graphics/InbandTextTrackPrivateClient.h:
(WebCore::InbandTextTrackPrivateClient::parseWebVTTFileHeader): New.

* platform/graphics/avfoundation/InbandTextTrackPrivateAVF.cpp:
(WebCore::InbandTextTrackPrivateAVF::InbandTextTrackPrivateAVF): Add a cue format parameter.
(WebCore::InbandTextTrackPrivateAVF::processCue): Call processNativeSamples.
(WebCore::InbandTextTrackPrivateAVF::processAttributedStrings): Add logging. Minor cleanup.
(WebCore::InbandTextTrackPrivateAVF::processNativeSamples): New, process an array of
    CMSampleBuffers, create ISOWebVTTCue from the sample data.
* platform/graphics/avfoundation/InbandTextTrackPrivateAVF.h:

* platform/graphics/avfoundation/cf/InbandTextTrackPrivateAVCF.cpp:
(WebCore::InbandTextTrackPrivateAVCF::InbandTextTrackPrivateAVCF):
* platform/graphics/avfoundation/cf/InbandTextTrackPrivateAVCF.h:
(WebCore::InbandTextTrackPrivateAVCF::create):
* platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp:
(WebCore::MediaPlayerPrivateAVFoundationCF::processMediaSelectionOptions):
(WebCore::LegibleOutputData::LegibleOutputData):
(WebCore::AVFWrapper::processCue):
(WebCore::AVFWrapper::legibleOutputCallback):

* platform/graphics/avfoundation/objc/InbandTextTrackPrivateAVFObjC.h:
(WebCore::InbandTextTrackPrivateAVFObjC::create): Add a cue format parameter.
* platform/graphics/avfoundation/objc/InbandTextTrackPrivateAVFObjC.mm:
(WebCore::InbandTextTrackPrivateAVFObjC::InbandTextTrackPrivateAVFObjC): Ditto.

* platform/graphics/avfoundation/InbandTextTrackPrivateLegacyAVFObjC.cpp:
(WebCore::InbandTextTrackPrivateLegacyAVFObjC::InbandTextTrackPrivateLegacyAVFObjC): Pass cue
    format to base class.

* platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h:
* platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:
(WebCore::MediaPlayerPrivateAVFoundationObjC::createAVAssetForURL): Improve logging.
(WebCore::MediaPlayerPrivateAVFoundationObjC::createAVPlayerItem): Don't leak an NSDictionary.
(WebCore::MediaPlayerPrivateAVFoundationObjC::tracksChanged): Don't process media selection
    options until we have tracks.
(WebCore::MediaPlayerPrivateAVFoundationObjC::processMediaSelectionOptions):
(WebCore::MediaPlayerPrivateAVFoundationObjC::processCue): Pass native samples as well as
    attributed strings to track.
(-[WebCoreAVFMovieObserver legibleOutput:didOutputAttributedStrings:nativeSampleBuffers:forItemTime:]):
* platform/graphics/avfoundation/objc/OutOfBandTextTrackPrivateAVF.h:
(WebCore::OutOfBandTextTrackPrivateAVF::OutOfBandTextTrackPrivateAVF):

* platform/graphics/avfoundation/objc/OutOfBandTextTrackPrivateAVF.h:
(WebCore::OutOfBandTextTrackPrivateAVF::OutOfBandTextTrackPrivateAVF):

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

30 files changed:
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/WebCore.vcxproj/WebCore.vcxproj
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/html/track/BufferedLineReader.h
Source/WebCore/html/track/InbandGenericTextTrack.cpp
Source/WebCore/html/track/InbandGenericTextTrack.h
Source/WebCore/html/track/InbandTextTrack.h
Source/WebCore/html/track/InbandWebVTTTextTrack.cpp
Source/WebCore/html/track/InbandWebVTTTextTrack.h
Source/WebCore/html/track/TextTrackCueGeneric.cpp
Source/WebCore/html/track/VTTCue.cpp
Source/WebCore/html/track/VTTCue.h
Source/WebCore/html/track/WebVTTParser.cpp
Source/WebCore/html/track/WebVTTParser.h
Source/WebCore/loader/TextTrackLoader.cpp
Source/WebCore/platform/graphics/ISOVTTCue.cpp [new file with mode: 0644]
Source/WebCore/platform/graphics/ISOVTTCue.h [new file with mode: 0644]
Source/WebCore/platform/graphics/InbandTextTrackPrivateClient.h
Source/WebCore/platform/graphics/avfoundation/InbandTextTrackPrivateAVF.cpp
Source/WebCore/platform/graphics/avfoundation/InbandTextTrackPrivateAVF.h
Source/WebCore/platform/graphics/avfoundation/cf/InbandTextTrackPrivateAVCF.cpp
Source/WebCore/platform/graphics/avfoundation/cf/InbandTextTrackPrivateAVCF.h
Source/WebCore/platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp
Source/WebCore/platform/graphics/avfoundation/objc/InbandTextTrackPrivateAVFObjC.h
Source/WebCore/platform/graphics/avfoundation/objc/InbandTextTrackPrivateAVFObjC.mm
Source/WebCore/platform/graphics/avfoundation/objc/InbandTextTrackPrivateLegacyAVFObjC.mm
Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h
Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm
Source/WebCore/platform/graphics/avfoundation/objc/OutOfBandTextTrackPrivateAVF.h

index 1c7ca6d..726c190 100644 (file)
@@ -2090,6 +2090,7 @@ set(WebCore_SOURCES
     platform/graphics/IntPoint.cpp
     platform/graphics/IntRect.cpp
     platform/graphics/IntSize.cpp
+    platform/graphics/ISOVTTCue.cpp
     platform/graphics/LayoutBoxExtent.cpp
     platform/graphics/LayoutRect.cpp
     platform/graphics/MediaPlayer.cpp
index b9657ed..f71106b 100644 (file)
@@ -1,3 +1,144 @@
+2014-06-24  Eric Carlson  <eric.carlson@apple.com>
+
+        [Mac] process raw VTT in-band captions
+        https://bugs.webkit.org/show_bug.cgi?id=134178
+
+        Reviewed by Jer Noble.
+
+        * CMakeLists.txt: Add ISOVTTCue.cpp|h.
+        * WebCore.vcxproj/WebCore.vcxproj: Ditto.
+        * WebCore.xcodeproj/project.pbxproj: Ditto.
+
+        * html/track/BufferedLineReader.h:
+        (WebCore::BufferedLineReader::reset): New, empty the input buffer.
+
+        Make it possible to process WebVTT captions. 
+        * html/track/InbandGenericTextTrack.cpp:
+        (WebCore::InbandGenericTextTrack::parser): Allocate, if necessary, and return a WebVTT parser.
+        (WebCore::InbandGenericTextTrack::parseWebVTTCueData): Pass a cue to the parser.
+        (WebCore::InbandGenericTextTrack::parseWebVTTFileHeader): Pass a VTT file header to the parser.
+        (WebCore::InbandGenericTextTrack::newCuesParsed): Parser callback.
+        (WebCore::InbandGenericTextTrack::newRegionsParsed): Ditto.
+        (WebCore::InbandGenericTextTrack::fileFailedToParse): Ditto.
+        * html/track/InbandGenericTextTrack.h:
+
+        * html/track/InbandTextTrack.h:
+
+        * html/track/InbandWebVTTTextTrack.cpp:
+        (WebCore::InbandWebVTTTextTrack::parser): New, parser accessor.
+        (WebCore::InbandWebVTTTextTrack::parseWebVTTCueData): New, parse VTT data in an ISOWebVTTCue
+            object.
+        (WebCore::InbandWebVTTTextTrack::newCuesParsed): Cleanup.
+        (WebCore::InbandWebVTTTextTrack::newRegionsParsed): Implement.
+        (WebCore::InbandWebVTTTextTrack::fileFailedToParse): Change the error message.
+        * html/track/InbandWebVTTTextTrack.h:
+
+        * html/track/TextTrackCueGeneric.cpp:
+        (WebCore::TextTrackCueGenericBoxElement::TextTrackCueGenericBoxElement): Change cue parameter
+            from a pointer to a reference.
+        (WebCore::TextTrackCueGeneric::createDisplayTree): Ditto.
+
+        * html/track/VTTCue.cpp:
+        (WebCore::VTTCueBox::create): Change cue parameter from a pointer to a reference.
+        (WebCore::VTTCueBox::VTTCueBox): Ditto.
+        (WebCore::VTTCueBox::getCue): Return a reference.
+        (WebCore::VTTCueBox::applyCSSProperties): m_cue is a reference, not a pointer.
+        (WebCore::VTTCue::create): New, create a VTTCue from WebVTTCueData.
+        (WebCore::VTTCue::VTTCue): New, internal constructor that takes a WebVTTCueData.
+        (WebCore::VTTCue::initialize): New, shared constructor initialization.
+        (WebCore::VTTCue::createDisplayTree): m_cue is a reference, not a pointer.
+        (WebCore::VTTCue::markFutureAndPastNodes): Ditto.
+        (WebCore::VTTCue::setCueSettings): Ditto.
+        * html/track/VTTCue.h:
+        (WebCore::VTTCueBox::create): Deleted.
+        (WebCore::VTTCue::create): Deleted.
+
+        * html/track/WebVTTParser.cpp:
+        (WebCore::WebVTTParser::parseFileHeader): New. Reset the line reader buffer and parser state, 
+            call the parser.
+        (WebCore::WebVTTParser::parseCueData): Create a cue from ISOWebVTTCue.
+        (WebCore::WebVTTParser::collectTimingsAndSettings): Return immediately if the string is empty.
+        (WebCore::WebVTTParser::collectTimeStamp): Ditto.
+        * html/track/WebVTTParser.h:
+        (WebCore::WebVTTCueData::originalStartTime): New.
+        (WebCore::WebVTTCueData::setOriginalStartTime): New.
+        (WebCore::WebVTTCueData::WebVTTCueData):
+
+        * loader/TextTrackLoader.cpp:
+        (WebCore::TextTrackLoader::getNewCues): Cleanup, use the new VTTCue::create.
+
+        Parse ISO WebVTT cue boxes.
+        * platform/graphics/ISOVTTCue.cpp: Added.
+        (WebCore::ISOBox::ISOBox):
+        (WebCore::ISOBox::peekType):
+        (WebCore::ISOBox::peekLength):
+        (WebCore::ISOBox::peekString):
+        (WebCore::vttCueBoxType):
+        (WebCore::vttIdBoxType):
+        (WebCore::vttSettingsBoxType):
+        (WebCore::vttPayloadBoxType):
+        (WebCore::vttCurrentTimeBoxType):
+        (WebCore::vttCueSourceIDBoxType):
+        (WebCore::ISOWebVTTCue::boxType):
+        (WebCore::ISOWebVTTCue::ISOWebVTTCue):
+        * platform/graphics/ISOVTTCue.h: Added.
+        (WebCore::ISOBox::boxHeaderSize):
+        (WebCore::ISOBox::length):
+        (WebCore::ISOBox::type):
+        (WebCore::ISOWebVTTCue::presentationTime):
+        (WebCore::ISOWebVTTCue::duration):
+        (WebCore::ISOWebVTTCue::sourceID):
+        (WebCore::ISOWebVTTCue::id):
+        (WebCore::ISOWebVTTCue::originalStartTime):
+        (WebCore::ISOWebVTTCue::settings):
+        (WebCore::ISOWebVTTCue::cueText):
+
+        * platform/graphics/InbandTextTrackPrivateClient.h:
+        (WebCore::InbandTextTrackPrivateClient::parseWebVTTFileHeader): New.
+
+        * platform/graphics/avfoundation/InbandTextTrackPrivateAVF.cpp:
+        (WebCore::InbandTextTrackPrivateAVF::InbandTextTrackPrivateAVF): Add a cue format parameter.
+        (WebCore::InbandTextTrackPrivateAVF::processCue): Call processNativeSamples.
+        (WebCore::InbandTextTrackPrivateAVF::processAttributedStrings): Add logging. Minor cleanup.
+        (WebCore::InbandTextTrackPrivateAVF::processNativeSamples): New, process an array of 
+            CMSampleBuffers, create ISOWebVTTCue from the sample data.
+        * platform/graphics/avfoundation/InbandTextTrackPrivateAVF.h:
+
+        * platform/graphics/avfoundation/cf/InbandTextTrackPrivateAVCF.cpp:
+        (WebCore::InbandTextTrackPrivateAVCF::InbandTextTrackPrivateAVCF):
+        * platform/graphics/avfoundation/cf/InbandTextTrackPrivateAVCF.h:
+        (WebCore::InbandTextTrackPrivateAVCF::create):
+        * platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp:
+        (WebCore::MediaPlayerPrivateAVFoundationCF::processMediaSelectionOptions):
+        (WebCore::LegibleOutputData::LegibleOutputData):
+        (WebCore::AVFWrapper::processCue):
+        (WebCore::AVFWrapper::legibleOutputCallback):
+
+        * platform/graphics/avfoundation/objc/InbandTextTrackPrivateAVFObjC.h:
+        (WebCore::InbandTextTrackPrivateAVFObjC::create): Add a cue format parameter.
+        * platform/graphics/avfoundation/objc/InbandTextTrackPrivateAVFObjC.mm:
+        (WebCore::InbandTextTrackPrivateAVFObjC::InbandTextTrackPrivateAVFObjC): Ditto.
+
+        * platform/graphics/avfoundation/InbandTextTrackPrivateLegacyAVFObjC.cpp:
+        (WebCore::InbandTextTrackPrivateLegacyAVFObjC::InbandTextTrackPrivateLegacyAVFObjC): Pass cue
+            format to base class.
+
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h:
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::createAVAssetForURL): Improve logging.
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::createAVPlayerItem): Don't leak an NSDictionary.
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::tracksChanged): Don't process media selection
+            options until we have tracks.
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::processMediaSelectionOptions): 
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::processCue): Pass native samples as well as 
+            attributed strings to track.
+        (-[WebCoreAVFMovieObserver legibleOutput:didOutputAttributedStrings:nativeSampleBuffers:forItemTime:]):
+        * platform/graphics/avfoundation/objc/OutOfBandTextTrackPrivateAVF.h:
+        (WebCore::OutOfBandTextTrackPrivateAVF::OutOfBandTextTrackPrivateAVF):
+
+        * platform/graphics/avfoundation/objc/OutOfBandTextTrackPrivateAVF.h:
+        (WebCore::OutOfBandTextTrackPrivateAVF::OutOfBandTextTrackPrivateAVF):
+
 2014-06-24  Antti Koivisto  <antti@apple.com>
 
         Only flush layers when the exposed rect actually changes
index de95eca..f883ffd 100644 (file)
     <ClCompile Include="..\platform\FileChooser.cpp" />
     <ClCompile Include="..\platform\FileStream.cpp" />
     <ClCompile Include="..\platform\FileSystem.cpp" />
+    <ClCompile Include="..\platform\graphics\ISOVTTCue.cpp" />
     <ClCompile Include="..\platform\audio\AudioSession.cpp" />
     <ClCompile Include="..\platform\audio\MediaSession.cpp" />
     <ClCompile Include="..\platform\audio\MediaSessionManager.cpp" />
     <ClInclude Include="..\platform\graphics\IntRect.h" />
     <ClInclude Include="..\platform\graphics\IntSize.h" />
     <ClInclude Include="..\platform\graphics\IntSizeHash.h" />
+    <ClInclude Include="..\platform\graphics\ISOVTTCue.h" />
     <ClInclude Include="..\platform\graphics\LayoutBoxExtent.h" />
     <ClInclude Include="..\platform\graphics\LayoutPoint.h" />
     <ClInclude Include="..\platform\graphics\LayoutRect.h" />
index 60dbe86..4c3b31c 100644 (file)
                07AB996B18DA3C010018771E /* RTCIceServer.h in Headers */ = {isa = PBXBuildFile; fileRef = 07AB996718DA3C010018771E /* RTCIceServer.h */; };
                07AB996F18DA3C740018771E /* RTCConfigurationPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 07AB996D18DA3C740018771E /* RTCConfigurationPrivate.h */; };
                07AB997018DA3C740018771E /* RTCIceServerPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 07AB996E18DA3C740018771E /* RTCIceServerPrivate.h */; };
+               07AC47011952102100EE9723 /* ISOVTTCue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07AC46FF1952102100EE9723 /* ISOVTTCue.cpp */; };
+               07AC47021952102100EE9723 /* ISOVTTCue.h in Headers */ = {isa = PBXBuildFile; fileRef = 07AC47001952102100EE9723 /* ISOVTTCue.h */; };
                07B0113F1032242200FBDC33 /* AccessibilityMediaControls.h in Headers */ = {isa = PBXBuildFile; fileRef = 07B0113E1032242200FBDC33 /* AccessibilityMediaControls.h */; };
                07B442D6166C70B000556CAD /* InbandTextTrackPrivateAVF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07B442D4166C70B000556CAD /* InbandTextTrackPrivateAVF.cpp */; };
                07B442D7166C70B000556CAD /* InbandTextTrackPrivateAVF.h in Headers */ = {isa = PBXBuildFile; fileRef = 07B442D5166C70B000556CAD /* InbandTextTrackPrivateAVF.h */; settings = {ATTRIBUTES = (Private, ); }; };
                07AB996818DA3C010018771E /* RTCIceServer.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = RTCIceServer.idl; sourceTree = "<group>"; };
                07AB996D18DA3C740018771E /* RTCConfigurationPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RTCConfigurationPrivate.h; sourceTree = "<group>"; };
                07AB996E18DA3C740018771E /* RTCIceServerPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RTCIceServerPrivate.h; sourceTree = "<group>"; };
+               07AC46FF1952102100EE9723 /* ISOVTTCue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ISOVTTCue.cpp; path = ISOVTTCue.cpp; sourceTree = "<group>"; };
+               07AC47001952102100EE9723 /* ISOVTTCue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ISOVTTCue.h; path = ISOVTTCue.h; sourceTree = "<group>"; };
                07B0113E1032242200FBDC33 /* AccessibilityMediaControls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AccessibilityMediaControls.h; sourceTree = "<group>"; };
                07B442D4166C70B000556CAD /* InbandTextTrackPrivateAVF.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InbandTextTrackPrivateAVF.cpp; sourceTree = "<group>"; };
                07B442D5166C70B000556CAD /* InbandTextTrackPrivateAVF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InbandTextTrackPrivateAVF.h; sourceTree = "<group>"; };
                                2D46F04F17B96FD2005647F0 /* IntSize.cpp */,
                                B27535470B053814002CE64F /* IntSize.h */,
                                B27535480B053814002CE64F /* IntSizeHash.h */,
+                               07AC46FF1952102100EE9723 /* ISOVTTCue.cpp */,
+                               07AC47001952102100EE9723 /* ISOVTTCue.h */,
                                65CC6BED16014EC0000ED27D /* Latin1TextIterator.h */,
                                141DC049164834B900371E5A /* LayoutBoxExtent.cpp */,
                                141DC04A164834B900371E5A /* LayoutBoxExtent.h */,
                                E1FF8F65180745D800132674 /* JSSubtleCrypto.h in Headers */,
                                B20111080AB7740500DB0E68 /* JSSVGAElement.h in Headers */,
                                24D9129213CA951E00D21915 /* JSSVGAltGlyphDefElement.h in Headers */,
+                               07AC47021952102100EE9723 /* ISOVTTCue.h in Headers */,
                                6515EC920D9723FF0063D49A /* JSSVGAltGlyphElement.h in Headers */,
                                24D9129613CA956100D21915 /* JSSVGAltGlyphItemElement.h in Headers */,
                                B222F6990AB771950022EFAD /* JSSVGAngle.h in Headers */,
                                B2227A530D00BF220071B782 /* SVGPaint.cpp in Sources */,
                                B2227A560D00BF220071B782 /* SVGParserUtilities.cpp in Sources */,
                                84C6784C1214814700A92902 /* SVGPathBlender.cpp in Sources */,
+                               07AC47011952102100EE9723 /* ISOVTTCue.cpp in Sources */,
                                8476C9EA11DF6A2900555B02 /* SVGPathBuilder.cpp in Sources */,
                                8419D2A8120D92D000141F8F /* SVGPathByteStreamBuilder.cpp in Sources */,
                                8419D2AC120D92FC00141F8F /* SVGPathByteStreamSource.cpp in Sources */,
index df3a749..8aacd81 100644 (file)
@@ -68,6 +68,8 @@ public:
     // Returns true if EOS has been reached proper.
     bool isAtEndOfStream() const { return m_endOfStream && m_buffer.isEmpty(); }
 
+    void reset() { m_buffer.clear(); }
+
 private:
     // Consume the next character the buffer if it is the character |c|.
     void scanCharacter(UChar c)
index ca39dab..02b7e96 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 Apple Inc.  All rights reserved.
+ * Copyright (C) 2012-2014 Apple Inc.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #include <math.h>
 #include <wtf/text/CString.h>
 
+#if ENABLE(WEBVTT_REGIONS)
+#include "VTTRegionList.h"
+#endif
+
 namespace WebCore {
 
 GenericTextTrackCueMap::GenericTextTrackCueMap()
@@ -190,6 +194,59 @@ void InbandGenericTextTrack::removeCue(TextTrackCue* cue, ExceptionCode& ec)
     TextTrack::removeCue(cue, ec);
 }
 
+WebVTTParser& InbandGenericTextTrack::parser()
+{
+    if (!m_webVTTParser)
+        m_webVTTParser = std::make_unique<WebVTTParser>(static_cast<WebVTTParserClient*>(this), scriptExecutionContext());
+    return *m_webVTTParser;
+}
+
+void InbandGenericTextTrack::parseWebVTTCueData(InbandTextTrackPrivate* trackPrivate, const ISOWebVTTCue& cueData)
+{
+    ASSERT_UNUSED(trackPrivate, trackPrivate == m_private);
+    parser().parseCueData(cueData);
+}
+
+void InbandGenericTextTrack::parseWebVTTFileHeader(InbandTextTrackPrivate* trackPrivate, String header)
+{
+    ASSERT_UNUSED(trackPrivate, trackPrivate == m_private);
+    parser().parseFileHeader(header);
+}
+
+void InbandGenericTextTrack::newCuesParsed()
+{
+    Vector<RefPtr<WebVTTCueData>> cues;
+    parser().getNewCues(cues);
+
+    for (auto& cueData : cues) {
+        RefPtr<VTTCue> vttCue = VTTCue::create(*scriptExecutionContext(), *cueData);
+
+        if (hasCue(vttCue.get(), TextTrackCue::IgnoreDuration)) {
+            LOG(Media, "InbandGenericTextTrack::newCuesParsed ignoring already added cue: start=%.2f, end=%.2f, content=\"%s\"\n", vttCue->startTime(), vttCue->endTime(), vttCue->text().utf8().data());
+            return;
+        }
+        addCue(vttCue.release(), ASSERT_NO_EXCEPTION);
+    }
+}
+
+#if ENABLE(WEBVTT_REGIONS)
+void InbandGenericTextTrack::newRegionsParsed()
+{
+    Vector<RefPtr<VTTRegion>> newRegions;
+    parser().getNewRegions(newRegions);
+
+    for (auto& region : newRegions) {
+        region->setTrack(this);
+        regions()->add(region);
+    }
+}
+#endif
+
+void InbandGenericTextTrack::fileFailedToParse()
+{
+    LOG(Media, "Error parsing WebVTT stream.");
+}
+
 } // namespace WebCore
 
 #endif
index b02bd87..d01fa83 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -30,6 +30,7 @@
 
 #include "InbandTextTrack.h"
 #include "TextTrackCueGeneric.h"
+#include "WebVTTParser.h"
 #include <wtf/RefPtr.h>
 
 namespace WebCore {
@@ -59,7 +60,7 @@ private:
     CueDataToCueMap m_dataToCueMap;
 };
 
-class InbandGenericTextTrack : public InbandTextTrack {
+class InbandGenericTextTrack : public InbandTextTrack, private WebVTTParserClient {
 public:
     static PassRefPtr<InbandGenericTextTrack> create(ScriptExecutionContext*, TextTrackClient*, PassRefPtr<InbandTextTrackPrivate>);
     virtual ~InbandGenericTextTrack();
@@ -75,7 +76,18 @@ private:
     PassRefPtr<TextTrackCueGeneric> createCue(PassRefPtr<GenericCueData>);
     void updateCueFromCueData(TextTrackCueGeneric*, GenericCueData*);
 
+    WebVTTParser& parser();
+    virtual void parseWebVTTCueData(InbandTextTrackPrivate*, const ISOWebVTTCue&) override;
+    virtual void parseWebVTTFileHeader(InbandTextTrackPrivate*, String) override;
+
+    virtual void newCuesParsed() override;
+#if ENABLE(WEBVTT_REGIONS)
+    virtual void newRegionsParsed() override;
+#endif
+    virtual void fileFailedToParse() override;
+
     GenericTextTrackCueMap m_cueMap;
+    std::unique_ptr<WebVTTParser> m_webVTTParser;
 };
 
 } // namespace WebCore
index 2b3ff1a..bb2404d 100644 (file)
@@ -81,7 +81,10 @@ private:
     virtual void updateGenericCue(InbandTextTrackPrivate*, GenericCueData*) override { ASSERT_NOT_REACHED(); }
     virtual void removeGenericCue(InbandTextTrackPrivate*, GenericCueData*) override { ASSERT_NOT_REACHED(); }
 
+    virtual void parseWebVTTFileHeader(InbandTextTrackPrivate*, String) override { ASSERT_NOT_REACHED(); }
     virtual void parseWebVTTCueData(InbandTextTrackPrivate*, const char*, unsigned) override { ASSERT_NOT_REACHED(); }
+    virtual void parseWebVTTCueData(InbandTextTrackPrivate*, const ISOWebVTTCue&) override { ASSERT_NOT_REACHED(); }
+
     virtual double startTimeVariance() const;
 
 #if USE(PLATFORM_TEXT_TRACK_MENU)
index 1268d95..caf7787 100644 (file)
 #include "NotImplemented.h"
 #include <wtf/text/CString.h>
 
+#if ENABLE(WEBVTT_REGIONS)
+#include "VTTRegionList.h"
+#endif
+
 namespace WebCore {
 
 PassRefPtr<InbandTextTrack> InbandWebVTTTextTrack::create(ScriptExecutionContext* context, TextTrackClient* client, PassRefPtr<InbandTextTrackPrivate> playerPrivate)
@@ -50,42 +54,57 @@ InbandWebVTTTextTrack::~InbandWebVTTTextTrack()
 {
 }
 
-void InbandWebVTTTextTrack::parseWebVTTCueData(InbandTextTrackPrivate* trackPrivate, const char* data, unsigned length)
+WebVTTParser& InbandWebVTTTextTrack::parser()
 {
-    ASSERT_UNUSED(trackPrivate, trackPrivate == m_private);
     if (!m_webVTTParser)
         m_webVTTParser = std::make_unique<WebVTTParser>(static_cast<WebVTTParserClient*>(this), scriptExecutionContext());
-    m_webVTTParser->parseBytes(data, length);
+    return *m_webVTTParser;
+}
+
+void InbandWebVTTTextTrack::parseWebVTTCueData(InbandTextTrackPrivate* trackPrivate, const char* data, unsigned length)
+{
+    ASSERT_UNUSED(trackPrivate, trackPrivate == m_private);
+    parser().parseBytes(data, length);
+}
+
+void InbandWebVTTTextTrack::parseWebVTTCueData(InbandTextTrackPrivate* trackPrivate, const ISOWebVTTCue& cueData)
+{
+    ASSERT_UNUSED(trackPrivate, trackPrivate == m_private);
+    parser().parseCueData(cueData);
 }
 
 void InbandWebVTTTextTrack::newCuesParsed()
 {
     Vector<RefPtr<WebVTTCueData>> cues;
-    m_webVTTParser->getNewCues(cues);
-    for (size_t i = 0; i < cues.size(); ++i) {
-        RefPtr<WebVTTCueData> cueData = cues[i];
-        RefPtr<VTTCue> cue = VTTCue::create(*scriptExecutionContext(), cueData->startTime(), cueData->endTime(), cueData->content());
-        cue->setId(cueData->id());
-        cue->setCueSettings(cueData->settings());
-
-        if (hasCue(cue.get(), TextTrackCue::IgnoreDuration)) {
-            LOG(Media, "InbandWebVTTTextTrack::newCuesParsed ignoring already added cue: start=%.2f, end=%.2f, content=\"%s\"\n", cueData->startTime(), cueData->endTime(), cueData->content().utf8().data());
+    parser().getNewCues(cues);
+
+    for (auto& cueData : cues) {
+        RefPtr<VTTCue> vttCue = VTTCue::create(*scriptExecutionContext(), *cueData);
+
+        if (hasCue(vttCue.get(), TextTrackCue::IgnoreDuration)) {
+            LOG(Media, "InbandWebVTTTextTrack::newCuesParsed ignoring already added cue: start=%.2f, end=%.2f, content=\"%s\"\n", vttCue->startTime(), vttCue->endTime(), vttCue->text().utf8().data());
             return;
         }
-        addCue(cue.release(), ASSERT_NO_EXCEPTION);
+        addCue(vttCue.release(), ASSERT_NO_EXCEPTION);
     }
 }
     
 #if ENABLE(WEBVTT_REGIONS)
 void InbandWebVTTTextTrack::newRegionsParsed()
 {
-    notImplemented();
+    Vector<RefPtr<VTTRegion>> newRegions;
+    parser().getNewRegions(newRegions);
+
+    for (auto& region : newRegions) {
+        region->setTrack(this);
+        regions()->add(region);
+    }
 }
 #endif
     
 void InbandWebVTTTextTrack::fileFailedToParse()
 {
-    LOG(Media, "Unable to parse WebVTT stream.");
+    LOG(Media, "Error parsing WebVTT stream.");
 }
 
 } // namespace WebCore
index 5966c4b..abbbdd8 100644 (file)
@@ -43,7 +43,9 @@ public:
 private:
     InbandWebVTTTextTrack(ScriptExecutionContext*, TextTrackClient*, PassRefPtr<InbandTextTrackPrivate>);
 
+    WebVTTParser& parser();
     virtual void parseWebVTTCueData(InbandTextTrackPrivate*, const char* data, unsigned length) override;
+    virtual void parseWebVTTCueData(InbandTextTrackPrivate*, const ISOWebVTTCue&) override;
 
     virtual void newCuesParsed() override;
 #if ENABLE(WEBVTT_REGIONS)
index e5224d4..4b1b207 100644 (file)
@@ -43,7 +43,7 @@ namespace WebCore {
 
 class TextTrackCueGenericBoxElement final : public VTTCueBox {
 public:
-    static PassRefPtr<TextTrackCueGenericBoxElement> create(Document& document, TextTrackCueGeneric* cue)
+    static PassRefPtr<TextTrackCueGenericBoxElement> create(Document& document, TextTrackCueGeneric& cue)
     {
         return adoptRef(new TextTrackCueGenericBoxElement(document, cue));
     }
@@ -51,10 +51,10 @@ public:
     virtual void applyCSSProperties(const IntSize&) override;
     
 private:
-    TextTrackCueGenericBoxElement(Document&, VTTCue*);
+    TextTrackCueGenericBoxElement(Document&, VTTCue&);
 };
 
-TextTrackCueGenericBoxElement::TextTrackCueGenericBoxElement(Document& document, VTTCue* cue)
+TextTrackCueGenericBoxElement::TextTrackCueGenericBoxElement(Document& document, VTTCue& cue)
     : VTTCueBox(document, cue)
 {
 }
@@ -118,7 +118,7 @@ TextTrackCueGeneric::TextTrackCueGeneric(ScriptExecutionContext& context, double
 
 PassRefPtr<VTTCueBox> TextTrackCueGeneric::createDisplayTree()
 {
-    return TextTrackCueGenericBoxElement::create(ownerDocument(), this);
+    return TextTrackCueGenericBoxElement::create(ownerDocument(), *this);
 }
 
 void TextTrackCueGeneric::setLine(int line, ExceptionCode& ec)
index 502804b..95892d4 100644 (file)
@@ -119,7 +119,14 @@ static const String& verticalGrowingRightKeyword()
 
 // ----------------------------
 
-VTTCueBox::VTTCueBox(Document& document, VTTCue* cue)
+PassRefPtr<VTTCueBox> VTTCueBox::create(Document& document, VTTCue& cue)
+{
+    VTTCueBox* cueBox = new VTTCueBox(document, cue);
+    cueBox->setPseudo(VTTCueBox::vttCueBoxShadowPseudoId());
+    return adoptRef(cueBox);
+}
+
+VTTCueBox::VTTCueBox(Document& document, VTTCue& cue)
     : HTMLElement(divTag, document)
     , m_cue(cue)
 {
@@ -128,14 +135,14 @@ VTTCueBox::VTTCueBox(Document& document, VTTCue* cue)
 
 VTTCue* VTTCueBox::getCue() const
 {
-    return m_cue;
+    return &m_cue;
 }
 
 void VTTCueBox::applyCSSProperties(const IntSize&)
 {
     // FIXME: Apply all the initial CSS positioning properties. http://wkb.ug/79916
 #if ENABLE(WEBVTT_REGIONS)
-    if (!m_cue->regionId().isEmpty()) {
+    if (!m_cue.regionId().isEmpty()) {
         setInlineStyleProperty(CSSPropertyPosition, CSSValueRelative);
         return;
     }
@@ -150,12 +157,12 @@ void VTTCueBox::applyCSSProperties(const IntSize&)
     setInlineStyleProperty(CSSPropertyUnicodeBidi, CSSValueWebkitPlaintext);
 
     // the 'direction' property must be set to direction
-    setInlineStyleProperty(CSSPropertyDirection, m_cue->getCSSWritingDirection());
+    setInlineStyleProperty(CSSPropertyDirection, m_cue.getCSSWritingDirection());
 
     // the 'writing-mode' property must be set to writing-mode
-    setInlineStyleProperty(CSSPropertyWebkitWritingMode, m_cue->getCSSWritingMode(), false);
+    setInlineStyleProperty(CSSPropertyWebkitWritingMode, m_cue.getCSSWritingMode(), false);
 
-    std::pair<float, float> position = m_cue->getCSSPosition();
+    std::pair<float, float> position = m_cue.getCSSPosition();
 
     // the 'top' property must be set to top,
     setInlineStyleProperty(CSSPropertyTop, static_cast<double>(position.second), CSSPrimitiveValue::CSS_PERCENTAGE);
@@ -164,21 +171,21 @@ void VTTCueBox::applyCSSProperties(const IntSize&)
     setInlineStyleProperty(CSSPropertyLeft, static_cast<double>(position.first), CSSPrimitiveValue::CSS_PERCENTAGE);
 
     // the 'width' property must be set to width, and the 'height' property  must be set to height
-    if (m_cue->vertical() == horizontalKeyword()) {
-        setInlineStyleProperty(CSSPropertyWidth, static_cast<double>(m_cue->getCSSSize()), CSSPrimitiveValue::CSS_PERCENTAGE);
+    if (m_cue.vertical() == horizontalKeyword()) {
+        setInlineStyleProperty(CSSPropertyWidth, static_cast<double>(m_cue.getCSSSize()), CSSPrimitiveValue::CSS_PERCENTAGE);
         setInlineStyleProperty(CSSPropertyHeight, CSSValueAuto);
     } else {
         setInlineStyleProperty(CSSPropertyWidth, CSSValueAuto);
-        setInlineStyleProperty(CSSPropertyHeight, static_cast<double>(m_cue->getCSSSize()),  CSSPrimitiveValue::CSS_PERCENTAGE);
+        setInlineStyleProperty(CSSPropertyHeight, static_cast<double>(m_cue.getCSSSize()),  CSSPrimitiveValue::CSS_PERCENTAGE);
     }
 
     // The 'text-align' property on the (root) List of WebVTT Node Objects must
     // be set to the value in the second cell of the row of the table below
     // whose first cell is the value of the corresponding cue's text track cue
     // alignment:
-    setInlineStyleProperty(CSSPropertyTextAlign, m_cue->getCSSAlignment());
+    setInlineStyleProperty(CSSPropertyTextAlign, m_cue.getCSSAlignment());
 
-    if (!m_cue->snapToLines()) {
+    if (!m_cue.snapToLines()) {
         // 10.13.1 Set up x and y:
         // Note: x and y are set through the CSS left and top above.
 
@@ -209,23 +216,33 @@ RenderPtr<RenderElement> VTTCueBox::createElementRenderer(PassRef<RenderStyle> s
 
 // ----------------------------
 
+PassRefPtr<VTTCue> VTTCue::create(ScriptExecutionContext& context, double start, double end, const String& content)
+{
+    return adoptRef(new VTTCue(context, start, end, content));
+}
+
+PassRefPtr<VTTCue> VTTCue::create(ScriptExecutionContext& context, const WebVTTCueData& data)
+{
+    return adoptRef(new VTTCue(context, data));
+}
+
 VTTCue::VTTCue(ScriptExecutionContext& context, double start, double end, const String& content)
     : TextTrackCue(context, start, end)
     , m_content(content)
-    , m_linePosition(undefinedPosition)
-    , m_computedLinePosition(undefinedPosition)
-    , m_textPosition(50)
-    , m_cueSize(100)
-    , m_writingDirection(Horizontal)
-    , m_cueAlignment(Middle)
-    , m_webVTTNodeTree(nullptr)
-    , m_cueBackgroundBox(HTMLSpanElement::create(spanTag, toDocument(context)))
-    , m_displayDirection(CSSValueLtr)
-    , m_displaySize(0)
-    , m_snapToLines(true)
-    , m_displayTreeShouldChange(true)
-    , m_notifyRegion(true)
 {
+    initialize(context);
+}
+
+VTTCue::VTTCue(ScriptExecutionContext& context, const WebVTTCueData& cueData)
+    : TextTrackCue(context, 0, 0)
+{
+    initialize(context);
+    setText(cueData.content());
+    setStartTime(cueData.startTime(), IGNORE_EXCEPTION);
+    setEndTime(cueData.endTime(), IGNORE_EXCEPTION);
+    setId(cueData.id());
+    setCueSettings(cueData.settings());
+    m_originalStartTime = cueData.originalStartTime();
 }
 
 VTTCue::~VTTCue()
@@ -236,9 +253,27 @@ VTTCue::~VTTCue()
     displayTreeInternal()->remove(ASSERT_NO_EXCEPTION);
 }
 
+void VTTCue::initialize(ScriptExecutionContext& context)
+{
+    m_linePosition = undefinedPosition;
+    m_computedLinePosition = undefinedPosition;
+    m_textPosition = 50;
+    m_cueSize = 100;
+    m_writingDirection = Horizontal;
+    m_cueAlignment = Middle;
+    m_webVTTNodeTree = nullptr;
+    m_cueBackgroundBox = HTMLSpanElement::create(spanTag, toDocument(context));
+    m_displayDirection = CSSValueLtr;
+    m_displaySize = 0;
+    m_snapToLines = true;
+    m_displayTreeShouldChange = true;
+    m_notifyRegion = true;
+    m_originalStartTime = 0;
+}
+
 PassRefPtr<VTTCueBox> VTTCue::createDisplayTree()
 {
-    return VTTCueBox::create(ownerDocument(), this);
+    return VTTCueBox::create(ownerDocument(), *this);
 }
 
 VTTCueBox* VTTCue::displayTreeInternal()
@@ -699,6 +734,7 @@ void VTTCue::markFutureAndPastNodes(ContainerNode* root, double previousTimestam
             bool check = WebVTTParser::collectTimeStamp(child->nodeValue(), currentTimestamp);
             ASSERT_UNUSED(check, check);
             
+            currentTimestamp += m_originalStartTime;
             if (currentTimestamp > movieTime)
                 isPastNode = false;
         }
@@ -884,6 +920,9 @@ static bool scanPercentage(VTTScanner& input, const VTTScanner::Run& valueRun, i
 
 void VTTCue::setCueSettings(const String& inputString)
 {
+    if (inputString.isEmpty())
+        return;
+
     VTTScanner input(inputString);
 
     while (!input.isAtEnd()) {
index 947ace6..e156746 100644 (file)
@@ -46,15 +46,13 @@ class HTMLSpanElement;
 class ScriptExecutionContext;
 class VTTCue;
 class VTTScanner;
+class WebVTTCueData;
 
 // ----------------------------
 
 class VTTCueBox : public HTMLElement {
 public:
-    static PassRefPtr<VTTCueBox> create(Document& document, VTTCue* cue)
-    {
-        return adoptRef(new VTTCueBox(document, cue));
-    }
+    static PassRefPtr<VTTCueBox> create(Document&, VTTCue&);
 
     VTTCue* getCue() const;
     virtual void applyCSSProperties(const IntSize& videoSize);
@@ -62,21 +60,19 @@ public:
     static const AtomicString& vttCueBoxShadowPseudoId();
 
 protected:
-    VTTCueBox(Document&, VTTCue*);
+    VTTCueBox(Document&, VTTCue&);
 
     virtual RenderPtr<RenderElement> createElementRenderer(PassRef<RenderStyle>) override;
 
-    VTTCue* m_cue;
+    VTTCue& m_cue;
 };
 
 // ----------------------------
 
 class VTTCue : public TextTrackCue {
 public:
-    static PassRefPtr<VTTCue> create(ScriptExecutionContext& context, double start, double end, const String& content)
-    {
-        return adoptRef(new VTTCue(context, start, end, content));
-    }
+    static PassRefPtr<VTTCue> create(ScriptExecutionContext&, double start, double end, const String&);
+    static PassRefPtr<VTTCue> create(ScriptExecutionContext&, const WebVTTCueData&);
 
     virtual ~VTTCue();
 
@@ -164,11 +160,13 @@ public:
 
 protected:
     VTTCue(ScriptExecutionContext&, double start, double end, const String& content);
+    VTTCue(ScriptExecutionContext&, const WebVTTCueData&);
 
     virtual PassRefPtr<VTTCueBox> createDisplayTree();
     VTTCueBox* displayTreeInternal();
 
 private:
+    void initialize(ScriptExecutionContext&);
     void createWebVTTNodeTree();
     void copyWebVTTNodeToDOMTree(ContainerNode* WebVTTNode, ContainerNode* root);
 
@@ -211,6 +209,8 @@ private:
     int m_displaySize;
     std::pair<float, float> m_displayPosition;
 
+    double m_originalStartTime;
+
     bool m_snapToLines : 1;
     bool m_displayTreeShouldChange : 1;
     bool m_notifyRegion : 1;
index bf7d603..5113f92 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2011, 2013 Google Inc.  All rights reserved.
  * Copyright (C) 2013 Cable Television Labs, Inc.
- * Copyright (C) 2014 Apple Inc.  All rights reserved.
+ * Copyright (C) 2011-2014 Apple Inc.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -36,6 +36,7 @@
 
 #include "WebVTTParser.h"
 
+#include "ISOVTTCue.h"
 #include "ProcessingInstruction.h"
 #include "Text.h"
 #include "VTTScanner.h"
@@ -108,6 +109,14 @@ void WebVTTParser::getNewRegions(Vector<RefPtr<VTTRegion>>& outputRegions)
 }
 #endif
 
+void WebVTTParser::parseFileHeader(const String& data)
+{
+    m_state = Initial;
+    m_lineReader.reset();
+    m_lineReader.append(data);
+    parse();
+}
+
 void WebVTTParser::parseBytes(const char* data, unsigned length)
 {
     String textData = m_decoder->decode(data, length);
@@ -115,6 +124,27 @@ void WebVTTParser::parseBytes(const char* data, unsigned length)
     parse();
 }
 
+void WebVTTParser::parseCueData(const ISOWebVTTCue& data)
+{
+    RefPtr<WebVTTCueData> cue = WebVTTCueData::create();
+
+    double startTime = data.presentationTime().toDouble();
+    cue->setStartTime(startTime);
+    cue->setEndTime(startTime + data.duration().toDouble());
+
+    cue->setContent(data.cueText());
+    cue->setId(data.id());
+    cue->setSettings(data.settings());
+
+    double originalStartTime;
+    if (WebVTTParser::collectTimeStamp(data.originalStartTime(), originalStartTime))
+        cue->setOriginalStartTime(originalStartTime);
+
+    m_cuelist.append(cue);
+    if (m_client)
+        m_client->newCuesParsed();
+}
+
 void WebVTTParser::flush()
 {
     String textData = m_decoder->flush();
@@ -271,6 +301,9 @@ WebVTTParser::ParseState WebVTTParser::collectCueId(const String& line)
 
 WebVTTParser::ParseState WebVTTParser::collectTimingsAndSettings(const String& line)
 {
+    if (line.isEmpty())
+        return BadCue;
+
     VTTScanner input(line);
 
     // Collect WebVTT cue timings and settings. (5.3 WebVTT cue timings and settings parsing.)
@@ -434,6 +467,9 @@ void WebVTTParser::createNewRegion(const String& headerValue)
 
 bool WebVTTParser::collectTimeStamp(const String& line, double& timeStamp)
 {
+    if (line.isEmpty())
+        return false;
+
     VTTScanner input(line);
     return collectTimeStamp(input, timeStamp);
 }
index fc3fd2d..0f7d812 100644 (file)
@@ -49,6 +49,7 @@ namespace WebCore {
 using namespace HTMLNames;
 
 class Document;
+class ISOWebVTTCue;
 class VTTScanner;
 
 class WebVTTParserClient {
@@ -83,15 +84,20 @@ public:
     String settings() const { return m_settings; }
     void setSettings(String settings) { m_settings = settings; }
 
+    double originalStartTime() const { return m_originalStartTime; }
+    void setOriginalStartTime(double time) { m_originalStartTime = time; }
+
 private:
     WebVTTCueData()
         : m_startTime(0)
         , m_endTime(0)
+        , m_originalStartTime(0)
     {
     }
 
     double m_startTime;
     double m_endTime;
+    double m_originalStartTime;
     String m_id;
     String m_content;
     String m_settings;
@@ -140,7 +146,9 @@ public:
 #endif
 
     // Input data to the parser to parse.
-    void parseBytes(const char* data, unsigned length);
+    void parseBytes(const char*, unsigned);
+    void parseFileHeader(const String&);
+    void parseCueData(const ISOWebVTTCue&);
     void flush();
     void fileFinished();
 
@@ -184,7 +192,7 @@ private:
     double m_currentEndTime;
     StringBuilder m_currentContent;
     String m_currentSettings;
-    
+
     WebVTTParserClient* m_client;
 
     Vector<RefPtr<WebVTTCueData>> m_cuelist;
index ec3c3bb..4b0f651 100644 (file)
@@ -215,13 +215,9 @@ void TextTrackLoader::getNewCues(Vector<RefPtr<TextTrackCue>>& outputCues)
     if (m_cueParser) {
         Vector<RefPtr<WebVTTCueData>> newCues;
         m_cueParser->getNewCues(newCues);
-        for (size_t i = 0; i < newCues.size(); ++i) {
-            RefPtr<WebVTTCueData> data = newCues[i];
-            RefPtr<VTTCue> cue = VTTCue::create(*m_scriptExecutionContext, data->startTime(), data->endTime(), data->content());
-            cue->setId(data->id());
-            cue->setCueSettings(data->settings());
-            outputCues.append(cue);
-        }
+
+        for (auto& cueData : newCues)
+            outputCues.append(VTTCue::create(*m_scriptExecutionContext, *cueData));
     }
 }
 
diff --git a/Source/WebCore/platform/graphics/ISOVTTCue.cpp b/Source/WebCore/platform/graphics/ISOVTTCue.cpp
new file mode 100644 (file)
index 0000000..944fbd8
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * 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 APPLE INC. ``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
+ * 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"
+#include "ISOVTTCue.h"
+
+#include "Logging.h"
+#include <runtime/ArrayBuffer.h>
+#include <runtime/DataView.h>
+#include <runtime/Int8Array.h>
+#include <wtf/NeverDestroyed.h>
+#include <wtf/text/CString.h>
+#include <wtf/text/StringBuilder.h>
+
+namespace JSC {
+class ArrayBuffer;
+}
+
+namespace WebCore {
+
+ISOBox::ISOBox(ArrayBuffer* data)
+{
+    m_type = peekType(data);
+    m_length = peekLength(data);
+    ASSERT(m_length >= 8);
+}
+
+String ISOBox::peekType(ArrayBuffer* data)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(data->byteLength() >= 2 * sizeof(uint32_t));
+    if (data->byteLength() < 2 * sizeof(uint32_t))
+        return emptyString();
+
+    StringBuilder builder;
+    RefPtr<Int8Array> array = JSC::Int8Array::create(data, 4, sizeof(uint32_t));
+    for (int i = 0; i < 4; ++i)
+        builder.append(array->item(i));
+    return builder.toString();
+}
+
+size_t ISOBox::peekLength(ArrayBuffer* data)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(data->byteLength() >= sizeof(uint32_t));
+    if (data->byteLength() < sizeof(uint32_t))
+        return 0;
+
+    return JSC::DataView::create(data, 0, sizeof(uint32_t))->get<uint32_t>(0, false);
+}
+
+String ISOBox::peekString(ArrayBuffer* data, unsigned offset, unsigned length)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(offset + length <= data->byteLength());
+    if (data->byteLength() < offset + length)
+        return emptyString();
+
+    return String(JSC::Uint8Array::create(data, offset, length)->data(), length);
+}
+
+static const AtomicString& vttCueBoxType()
+{
+    static NeverDestroyed<AtomicString> vttc("vttc", AtomicString::ConstructFromLiteral);
+    return vttc;
+}
+
+static const AtomicString& vttIdBoxType()
+{
+    static NeverDestroyed<AtomicString> iden("iden", AtomicString::ConstructFromLiteral);
+    return iden;
+}
+
+static const AtomicString& vttSettingsBoxType()
+{
+    static NeverDestroyed<AtomicString> sttg("sttg", AtomicString::ConstructFromLiteral);
+    return sttg;
+}
+
+static const AtomicString& vttPayloadBoxType()
+{
+    static NeverDestroyed<AtomicString> payl("payl", AtomicString::ConstructFromLiteral);
+    return payl;
+}
+
+static const AtomicString& vttCurrentTimeBoxType()
+{
+    static NeverDestroyed<AtomicString> ctim("ctim", AtomicString::ConstructFromLiteral);
+    return ctim;
+}
+
+static const AtomicString& vttCueSourceIDBoxType()
+{
+    static NeverDestroyed<AtomicString> vsid("vsid", AtomicString::ConstructFromLiteral);
+    return vsid;
+}
+
+const AtomicString& ISOWebVTTCue::boxType()
+{
+    return vttCueBoxType();
+}
+
+ISOWebVTTCue::ISOWebVTTCue(const MediaTime& presentationTime, const MediaTime& duration, JSC::ArrayBuffer* buffer)
+    : ISOBox(buffer)
+    , m_presentationTime(presentationTime)
+    , m_duration(duration)
+{
+    size_t offset = ISOBox::boxHeaderSize();
+    while (offset < length() && length() - offset > ISOBox::boxHeaderSize()) {
+        RefPtr<ArrayBuffer> subBuffer = buffer->slice(offset);
+        String boxType = ISOBox::peekType(subBuffer.get());
+        size_t boxSize = ISOBox::peekLength(subBuffer.get());
+        size_t boxDataSize = boxSize - ISOBox::boxHeaderSize();
+
+        if (boxType == vttCueSourceIDBoxType())
+            m_sourceID = peekString(subBuffer.get(), ISOBox::boxHeaderSize(), boxDataSize);
+        else if (boxType == vttIdBoxType())
+            m_identifer = peekString(subBuffer.get(), ISOBox::boxHeaderSize(), boxDataSize);
+        else if (boxType == vttCurrentTimeBoxType())
+            m_originalStartTime = peekString(subBuffer.get(), ISOBox::boxHeaderSize(), boxDataSize);
+        else if (boxType == vttSettingsBoxType())
+            m_settings = peekString(subBuffer.get(), ISOBox::boxHeaderSize(), boxDataSize);
+        else if (boxType == vttPayloadBoxType())
+            m_cueText = peekString(subBuffer.get(), ISOBox::boxHeaderSize(), boxDataSize);
+        else
+            LOG(Media, "ISOWebVTTCue::ISOWebVTTCue - skipping box id = \"%s\", size = %zu", boxType.utf8().data(), boxSize);
+
+        offset += boxSize;
+    }
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/ISOVTTCue.h b/Source/WebCore/platform/graphics/ISOVTTCue.h
new file mode 100644 (file)
index 0000000..c96b4d6
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * 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 APPLE INC. ``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
+ * 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 ISOVTTCue_h
+#define ISOVTTCue_h
+
+#include <wtf/MediaTime.h>
+#include <wtf/text/WTFString.h>
+
+namespace JSC {
+class ArrayBuffer;
+}
+
+namespace WebCore {
+
+// An ISOBox represents a ISO-BMFF box. Data in the structure is big-endian. The layout of the data structure as follows:
+// 4 bytes : 4CC : identifier
+// 4 bytes : unsigned : length
+class ISOBox {
+public:
+    static String peekType(JSC::ArrayBuffer*);
+    static size_t peekLength(JSC::ArrayBuffer*);
+    static String peekString(JSC::ArrayBuffer*, unsigned offset, unsigned length);
+    static unsigned boxHeaderSize() { return 2 * sizeof(uint32_t); }
+
+    size_t length() const { return m_length; }
+    const AtomicString& type() const { return m_type; }
+
+protected:
+    ISOBox(JSC::ArrayBuffer*);
+    
+private:
+    size_t m_length;
+    AtomicString m_type;
+};
+
+// 4 bytes : 4CC : identifier = 'vttc'
+// 4 bytes : unsigned : length
+// N bytes : CueSourceIDBox : box : optional
+// N bytes : CueIDBox : box : optional
+// N bytes : CueTimeBox : box : optional
+// N bytes : CueSettingsBox : box : optional
+// N bytes : CuePayloadBox : box : required
+class ISOWebVTTCue : public ISOBox {
+public:
+    ISOWebVTTCue(const MediaTime& presentationTime, const MediaTime& duration, JSC::ArrayBuffer*);
+
+    static const AtomicString& boxType();
+
+    const MediaTime& presentationTime() const { return m_presentationTime; }
+    const MediaTime& duration() const { return m_duration; }
+
+    const String& sourceID() const { return m_sourceID; }
+    const String& id() const { return m_identifer; }
+    const String& originalStartTime() const { return m_originalStartTime; }
+    const String& settings() const { return m_settings; }
+    const String& cueText() const { return m_cueText; }
+
+private:
+    MediaTime m_presentationTime;
+    MediaTime m_duration;
+
+    String m_sourceID;
+    String m_identifer;
+    String m_originalStartTime;
+    String m_settings;
+    String m_cueText;
+};
+
+}
+
+#endif // ISOVTTCue_h
index d626e7b..ce535d1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -38,6 +38,7 @@
 namespace WebCore {
 
 class InbandTextTrackPrivate;
+class ISOWebVTTCue;
 
 class GenericCueData : public RefCounted<GenericCueData> {
 public:
@@ -180,7 +181,9 @@ public:
     virtual void updateGenericCue(InbandTextTrackPrivate*, GenericCueData*) = 0;
     virtual void removeGenericCue(InbandTextTrackPrivate*, GenericCueData*) = 0;
 
+    virtual void parseWebVTTFileHeader(InbandTextTrackPrivate*, String) { ASSERT_NOT_REACHED(); }
     virtual void parseWebVTTCueData(InbandTextTrackPrivate*, const char* data, unsigned length) = 0;
+    virtual void parseWebVTTCueData(InbandTextTrackPrivate*, const ISOWebVTTCue&) = 0;
 };
 
 } // namespace WebCore
index a5437cf..d4393d0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 
 #include "InbandTextTrackPrivateAVF.h"
 
+#include "ISOVTTCue.h"
 #include "InbandTextTrackPrivateClient.h"
 #include "Logging.h"
 #include "SoftLinking.h"
 #include <CoreMedia/CoreMedia.h>
+#include <runtime/ArrayBuffer.h>
+#include <runtime/DataView.h>
+#include <runtime/Int8Array.h>
+#include <wtf/MediaTime.h>
+#include <wtf/NeverDestroyed.h>
 #include <wtf/PassOwnPtr.h>
 #include <wtf/text/CString.h>
+#include <wtf/text/StringBuilder.h>
 #include <wtf/text/WTFString.h>
 #include <wtf/unicode/CharacterNames.h>
 
 #if !PLATFORM(WIN)
+#include "MediaTimeMac.h"
+#endif
+
+#if !PLATFORM(WIN)
 #define SOFT_LINK_AVF_FRAMEWORK(Lib) SOFT_LINK_FRAMEWORK_OPTIONAL(Lib)
 #define SOFT_LINK_AVF_POINTER(Lib, Name, Type) SOFT_LINK_POINTER_OPTIONAL(Lib, Name, Type)
 #else
 
 SOFT_LINK_AVF_FRAMEWORK(CoreMedia)
 
+#if !PLATFORM(WIN)
+SOFT_LINK(CoreMedia, CMSampleBufferGetDataBuffer, CMBlockBufferRef, (CMSampleBufferRef sbuf), (sbuf))
+SOFT_LINK(CoreMedia, CMBlockBufferCopyDataBytes, OSStatus, (CMBlockBufferRef theSourceBuffer, size_t offsetToData, size_t dataLength, void* destination), (theSourceBuffer, offsetToData, dataLength, destination))
+SOFT_LINK(CoreMedia, CMBlockBufferGetDataLength, size_t, (CMBlockBufferRef theBuffer), (theBuffer))
+SOFT_LINK(CoreMedia, CMSampleBufferGetSampleTimingInfo, OSStatus, (CMSampleBufferRef sbuf, CMItemIndex sampleIndex, CMSampleTimingInfo* timingInfoOut), (sbuf, sampleIndex, timingInfoOut))
+SOFT_LINK(CoreMedia, CMFormatDescriptionGetExtensions, CFDictionaryRef, (CMFormatDescriptionRef desc), (desc))
+SOFT_LINK(CoreMedia, CMSampleBufferGetFormatDescription, CMFormatDescriptionRef, (CMSampleBufferRef sbuf), (sbuf))
+#endif
+
 SOFT_LINK_AVF_POINTER(CoreMedia, kCMTextMarkupAttribute_Alignment, CFStringRef)
 SOFT_LINK_AVF_POINTER(CoreMedia, kCMTextMarkupAlignmentType_Start, CFStringRef)
 SOFT_LINK_AVF_POINTER(CoreMedia, kCMTextMarkupAlignmentType_Middle, CFStringRef)
@@ -72,6 +92,7 @@ SOFT_LINK_AVF_POINTER(CoreMedia, kCMTextMarkupAttribute_FontFamilyName, CFString
 SOFT_LINK_AVF_POINTER(CoreMedia, kCMTextMarkupAttribute_ForegroundColorARGB, CFStringRef)
 SOFT_LINK_AVF_POINTER(CoreMedia, kCMTextMarkupAttribute_BackgroundColorARGB, CFStringRef)
 SOFT_LINK_AVF_POINTER(CoreMedia, kCMTextMarkupAttribute_CharacterBackgroundColorARGB, CFStringRef)
+SOFT_LINK_AVF_POINTER(CoreMedia, kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms, CFStringRef)
 
 #define kCMTextMarkupAttribute_Alignment getkCMTextMarkupAttribute_Alignment()
 #define kCMTextMarkupAlignmentType_Start getkCMTextMarkupAlignmentType_Start()
@@ -92,6 +113,11 @@ SOFT_LINK_AVF_POINTER(CoreMedia, kCMTextMarkupAttribute_CharacterBackgroundColor
 #define kCMTextMarkupAttribute_ForegroundColorARGB getkCMTextMarkupAttribute_ForegroundColorARGB()
 #define kCMTextMarkupAttribute_BackgroundColorARGB getkCMTextMarkupAttribute_BackgroundColorARGB()
 #define kCMTextMarkupAttribute_CharacterBackgroundColorARGB getkCMTextMarkupAttribute_CharacterBackgroundColorARGB()
+#define kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms getkCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms()
+
+namespace JSC {
+class ArrayBuffer;
+}
 
 namespace WebCore {
 
@@ -99,13 +125,14 @@ AVFInbandTrackParent::~AVFInbandTrackParent()
 {
 }
 
-InbandTextTrackPrivateAVF::InbandTextTrackPrivateAVF(AVFInbandTrackParent* owner)
-    : InbandTextTrackPrivate(Generic)
+InbandTextTrackPrivateAVF::InbandTextTrackPrivateAVF(AVFInbandTrackParent* owner, CueFormat format)
+    : InbandTextTrackPrivate(format)
     , m_owner(owner)
     , m_pendingCueStatus(None)
     , m_index(0)
     , m_hasBeenReported(false)
     , m_seeking(false)
+    , m_haveReportedVTTHeader(false)
 {
 }
 
@@ -353,12 +380,18 @@ void InbandTextTrackPrivateAVF::processCueAttributes(CFAttributedStringRef attri
         cueData->setContent(content.toString());
 }
 
-void InbandTextTrackPrivateAVF::processCue(CFArrayRef attributedStrings, double time)
+void InbandTextTrackPrivateAVF::processCue(CFArrayRef attributedStrings, CFArrayRef nativeSamples, double time)
 {
     if (!client())
         return;
 
-    LOG(Media, "InbandTextTrackPrivateAVF::processCue - %li cues at time %.2f\n", attributedStrings ? CFArrayGetCount(attributedStrings) : 0, time);
+    processAttributedStrings(attributedStrings, time);
+    processNativeSamples(nativeSamples, time);
+}
+
+void InbandTextTrackPrivateAVF::processAttributedStrings(CFArrayRef attributedStrings, double time)
+{
+    LOG(Media, "InbandTextTrackPrivateAVF::processAttributedStrings - %li attributed strings at time %.2f\n", attributedStrings ? CFArrayGetCount(attributedStrings) : 0, time);
 
     Vector<RefPtr<GenericCueData>> arrivingCues;
     if (attributedStrings) {
@@ -442,9 +475,9 @@ void InbandTextTrackPrivateAVF::processCue(CFArrayRef attributedStrings, double
         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.release());
-
-        m_pendingCueStatus = seeking() ? DeliveredDuringSeek : Valid;
     }
+
+    m_pendingCueStatus = seeking() ? DeliveredDuringSeek : Valid;
 }
 
 void InbandTextTrackPrivateAVF::beginSeeking()
@@ -513,6 +546,109 @@ void InbandTextTrackPrivateAVF::setMode(InbandTextTrackPrivate::Mode newMode)
     m_owner->trackModeChanged();
 }
 
+void InbandTextTrackPrivateAVF::processNativeSamples(CFArrayRef nativeSamples, double presentationTime)
+{
+#if PLATFORM(WIN)
+    UNUSED_PARAM(nativeSamples);
+    UNUSED_PARAM(presentationTime);
+    ASSERT_NOT_REACHED();
+#else
+    if (!nativeSamples)
+        return;
+
+    CFIndex count = CFArrayGetCount(nativeSamples);
+    if (!count)
+        return;
+
+    LOG(Media, "InbandTextTrackPrivateAVF::processNativeSamples - %li sample buffers at time %.2f\n", count, presentationTime);
+
+    for (CFIndex i = 0; i < count; i++) {
+
+        CMSampleBufferRef sampleBuffer = (CMSampleBufferRef)CFArrayGetValueAtIndex(nativeSamples, i);
+        if (!sampleBuffer)
+            continue;
+
+        CMSampleTimingInfo timingInfo;
+        OSStatus status = CMSampleBufferGetSampleTimingInfo(sampleBuffer, i, &timingInfo);
+        if (status) {
+            LOG(Media, "InbandTextTrackPrivateAVF::processNativeSamples(%p) - CMSampleBufferGetSampleTimingInfo returned error %x for sample %li", this, static_cast<SInt32>(status), i);
+            continue;
+        }
+
+        CMBlockBufferRef blockBuffer = CMSampleBufferGetDataBuffer(sampleBuffer);
+        size_t bufferLength = CMBlockBufferGetDataLength(blockBuffer);
+        if (bufferLength < ISOBox::boxHeaderSize()) {
+            LOG(Media, "InbandTextTrackPrivateAVF::processNativeSamples(%p) - ERROR: CMSampleBuffer size length unexpectedly small (%zu)!!", this, bufferLength);
+            continue;
+        }
+
+        m_sampleInputBuffer.resize(m_sampleInputBuffer.size() + bufferLength);
+        CMBlockBufferCopyDataBytes(blockBuffer, 0, bufferLength, m_sampleInputBuffer.data() + m_sampleInputBuffer.size() - bufferLength);
+
+        RefPtr<ArrayBuffer> buffer = ArrayBuffer::create(m_sampleInputBuffer.data(), m_sampleInputBuffer.size());
+
+        String type = ISOBox::peekType(buffer.get());
+        size_t boxLength = ISOBox::peekLength(buffer.get());
+        if (boxLength > buffer->byteLength()) {
+            LOG(Media, "InbandTextTrackPrivateAVF::processNativeSamples(%p) - ERROR: chunk '%s' size (%zu) larger than buffer length (%u)!!", this, type.utf8().data(), boxLength, buffer->byteLength());
+            continue;
+        }
+
+        LOG(Media, "InbandTextTrackPrivateAVF::processNativeSamples(%p) - chunk type = '%s', size = %zu", this, type.utf8().data(), boxLength);
+
+        if (type == ISOWebVTTCue::boxType()) {
+#if !PLATFORM(WIN)
+            ISOWebVTTCue cueData = ISOWebVTTCue(MediaTime::createWithDouble(presentationTime), toMediaTime(timingInfo.duration), buffer.get());
+#else
+            ISOWebVTTCue cueData = ISOWebVTTCue(MediaTime::createWithDouble(presentationTime), MediaTime::createWithDouble(CMTimeGetSeconds(timingInfo.duration)), buffer.get());
+#endif
+            LOG(Media, "    sample presentation time = %.2f, duration = %.2f", cueData.presentationTime().toDouble(), cueData.duration().toDouble());
+            LOG(Media, "    id = \"%s\", settings = \"%s\", cue text = \"%s\"", cueData.id().utf8().data(), cueData.settings().utf8().data(), cueData.cueText().utf8().data());
+            LOG(Media, "    sourceID = \"%s\", originalStartTime = \"%s\"", cueData.sourceID().utf8().data(), cueData.originalStartTime().utf8().data());
+
+            client()->parseWebVTTCueData(this, cueData);
+        }
+
+        do {
+            if (m_haveReportedVTTHeader)
+                break;
+
+            CMFormatDescriptionRef formatDescription = CMSampleBufferGetFormatDescription(sampleBuffer);
+            if (!formatDescription)
+                break;
+
+            CFDictionaryRef extensions = CMFormatDescriptionGetExtensions(formatDescription);
+            if (!extensions)
+                break;
+
+            CFDictionaryRef sampleDescriptionExtensions = static_cast<CFDictionaryRef>(CFDictionaryGetValue(extensions, kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms));
+            if (!sampleDescriptionExtensions)
+                break;
+            
+            CFDataRef webvttHeaderData = static_cast<CFDataRef>(CFDictionaryGetValue(sampleDescriptionExtensions, CFSTR("vttC")));
+            if (!webvttHeaderData)
+                break;
+
+            unsigned length = CFDataGetLength(webvttHeaderData);
+            if (!length)
+                break;
+
+            // A WebVTT header is terminated by "One or more WebVTT line terminators" so append two line feeds to make sure the parser
+            // reccognized this string as a full header.
+            StringBuilder header;
+            header.append(reinterpret_cast<const unsigned char*>(CFDataGetBytePtr(webvttHeaderData)), length);
+            header.append("\n\n");
+
+            LOG(Media, "    vtt header = \n%s", header.toString().utf8().data());
+            client()->parseWebVTTFileHeader(this, header.toString());
+            m_haveReportedVTTHeader = true;
+        } while (0);
+
+        m_sampleInputBuffer.remove(0, boxLength);
+    }
+#endif
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(VIDEO) && (USE(AVFOUNDATION) || PLATFORM(IOS))
index 2d51aab..38c59bc 100644 (file)
@@ -55,7 +55,7 @@ public:
     bool hasBeenReported() const { return m_hasBeenReported; }
     void setHasBeenReported(bool reported) { m_hasBeenReported = reported; }
 
-    virtual void processCue(CFArrayRef, double);
+    virtual void processCue(CFArrayRef attributedStrings, CFArrayRef nativeSamples, double);
     virtual void resetCueValues();
 
     void beginSeeking();
@@ -68,13 +68,15 @@ public:
         InBand
     };
     virtual Category textTrackCategory() const = 0;
-    
+
     virtual double startTimeVariance() const override { return 0.25; }
-    
+
 protected:
-    InbandTextTrackPrivateAVF(AVFInbandTrackParent*);
+    InbandTextTrackPrivateAVF(AVFInbandTrackParent*, CueFormat);
 
     void processCueAttributes(CFAttributedStringRef, GenericCueData*);
+    void processAttributedStrings(CFArrayRef, double);
+    void processNativeSamples(CFArrayRef, double);
     void removeCompletedCues();
 
     double m_currentCueStartTime;
@@ -83,6 +85,8 @@ protected:
     Vector<RefPtr<GenericCueData>> m_cues;
     AVFInbandTrackParent* m_owner;
 
+    Vector<char> m_sampleInputBuffer;
+
     enum PendingCueStatus {
         None,
         DeliveredDuringSeek,
@@ -93,6 +97,7 @@ protected:
     int m_index;
     bool m_hasBeenReported;
     bool m_seeking;
+    bool m_haveReportedVTTHeader;
 };
 
 } // namespace WebCore
index 2abb72d..afcb706 100644 (file)
@@ -45,8 +45,8 @@
 
 namespace WebCore {
 
-InbandTextTrackPrivateAVCF::InbandTextTrackPrivateAVCF(AVFInbandTrackParent* player, AVCFMediaSelectionOptionRef selection)
-    : InbandTextTrackPrivateAVF(player)
+InbandTextTrackPrivateAVCF::InbandTextTrackPrivateAVCF(AVFInbandTrackParent* player, AVCFMediaSelectionOptionRef selection, InbandTextTrackPrivate::CueFormat format)
+    : InbandTextTrackPrivateAVF(player, format)
     , m_mediaSelectionOption(selection)
 {
 }
index d39ebcb..88f732a 100644 (file)
@@ -36,9 +36,9 @@ namespace WebCore {
 
 class InbandTextTrackPrivateAVCF : public InbandTextTrackPrivateAVF {
 public:
-    static PassRefPtr<InbandTextTrackPrivateAVCF> create(AVFInbandTrackParent* player,  AVCFMediaSelectionOptionRef selection)
+    static PassRefPtr<InbandTextTrackPrivateAVCF> create(AVFInbandTrackParent* player,  AVCFMediaSelectionOptionRef selection, InbandTextTrackPrivate::CueFormat format)
     {
-        return adoptRef(new InbandTextTrackPrivateAVCF(player, selection));
+        return adoptRef(new InbandTextTrackPrivateAVCF(player, selection, format));
     }
 
     ~InbandTextTrackPrivateAVCF() { }
@@ -60,7 +60,7 @@ public:
     AVCFMediaSelectionOptionRef mediaSelectionOption() const { return m_mediaSelectionOption.get(); }
 
 protected:
-    InbandTextTrackPrivateAVCF(AVFInbandTrackParent*, AVCFMediaSelectionOptionRef);
+    InbandTextTrackPrivateAVCF(AVFInbandTrackParent*, AVCFMediaSelectionOptionRef, InbandTextTrackPrivate::CueFormat);
     
     RetainPtr<AVCFMediaSelectionOptionRef> m_mediaSelectionOption;
 };
index d56f567..0bead9f 100644 (file)
@@ -1093,7 +1093,7 @@ void MediaPlayerPrivateAVFoundationCF::processMediaSelectionOptions()
         if (!newTrack)
             continue;
 
-        m_textTracks.append(InbandTextTrackPrivateAVCF::create(this, option));
+        m_textTracks.append(InbandTextTrackPrivateAVCF::create(this, option, InbandTextTrackPrivate::Generic));
     }
 
     processNewAndRemovedTextTracks(removedTextTracks);
@@ -1594,11 +1594,12 @@ void AVFWrapper::seekToTime(double time, double negativeTolerance, double positi
 #if HAVE(AVFOUNDATION_MEDIA_SELECTION_GROUP) && HAVE(AVFOUNDATION_LEGIBLE_OUTPUT_SUPPORT)
 struct LegibleOutputData {
     RetainPtr<CFArrayRef> m_attributedStrings;
+    RetainPtr<CFArrayRef> m_samples;
     double m_time;
     void* m_context;
 
-    LegibleOutputData(CFArrayRef strings, double time, void* context)
-        : m_attributedStrings(strings), m_time(time), m_context(context)
+    LegibleOutputData(CFArrayRef strings, CFArrayRef samples, double time, void* context)
+        : m_attributedStrings(strings), m_samples(samples), m_time(time), m_context(context)
     {
     }
 };
@@ -1623,10 +1624,10 @@ void AVFWrapper::processCue(void* context)
     if (!self->m_currentTextTrack)
         return;
 
-    self->m_currentTextTrack->processCue(legibleOutputData->m_attributedStrings.get(), legibleOutputData->m_time);
+    self->m_currentTextTrack->processCue(legibleOutputData->m_attributedStrings.get(), legibleOutputData->m_samples.get(), legibleOutputData->m_time);
 }
 
-void AVFWrapper::legibleOutputCallback(void* context, AVCFPlayerItemLegibleOutputRef legibleOutput, CFArrayRef attributedStrings, CFArrayRef /*nativeSampleBuffers*/, CMTime itemTime)
+void AVFWrapper::legibleOutputCallback(void* context, AVCFPlayerItemLegibleOutputRef legibleOutput, CFArrayRef attributedStrings, CFArrayRef nativeSampleBuffers, CMTime itemTime)
 {
     ASSERT(dispatch_get_main_queue() != dispatch_get_current_queue());
     MutexLocker locker(mapLock());
@@ -1640,7 +1641,7 @@ void AVFWrapper::legibleOutputCallback(void* context, AVCFPlayerItemLegibleOutpu
 
     ASSERT(legibleOutput == self->m_legibleOutput);
 
-    OwnPtr<LegibleOutputData> legibleOutputData = adoptPtr(new LegibleOutputData(attributedStrings, CMTimeGetSeconds(itemTime), context));
+    OwnPtr<LegibleOutputData> legibleOutputData = adoptPtr(new LegibleOutputData(attributedStrings, nativeSampleBuffers, CMTimeGetSeconds(itemTime), context));
 
     dispatch_async_f(dispatch_get_main_queue(), legibleOutputData.leakPtr(), processCue);
 }
index 4b780bf..0cadaf2 100644 (file)
 #include "InbandTextTrackPrivateAVF.h"
 #include <wtf/RetainPtr.h>
 
+OBJC_CLASS AVAsset;
 OBJC_CLASS AVMediaSelectionOption;
 
 namespace WebCore {
 
 class InbandTextTrackPrivateAVFObjC : public InbandTextTrackPrivateAVF {
 public:
-    static PassRefPtr<InbandTextTrackPrivateAVFObjC> create(AVFInbandTrackParent* player,  AVMediaSelectionOption *selection)
+    static PassRefPtr<InbandTextTrackPrivateAVFObjC> create(AVFInbandTrackParent* player,  AVMediaSelectionOption *selection, InbandTextTrackPrivate::CueFormat format)
     {
-        return adoptRef(new InbandTextTrackPrivateAVFObjC(player, selection));
+        return adoptRef(new InbandTextTrackPrivateAVFObjC(player, selection, format));
     }
 
     ~InbandTextTrackPrivateAVFObjC() { }
@@ -61,7 +62,7 @@ public:
     AVMediaSelectionOption *mediaSelectionOption() const { return m_mediaSelectionOption.get(); }
 
 protected:
-    InbandTextTrackPrivateAVFObjC(AVFInbandTrackParent*, AVMediaSelectionOption *);
+    InbandTextTrackPrivateAVFObjC(AVFInbandTrackParent*, AVMediaSelectionOption *, InbandTextTrackPrivate::CueFormat);
     
     RetainPtr<AVMediaSelectionOption> m_mediaSelectionOption;
 };
index 2b308dc..0b2b184 100644 (file)
@@ -76,8 +76,8 @@ SOFT_LINK_POINTER(AVFoundation, AVMediaCharacteristicEasyToRead, NSString *)
 
 namespace WebCore {
 
-InbandTextTrackPrivateAVFObjC::InbandTextTrackPrivateAVFObjC(AVFInbandTrackParent* player, AVMediaSelectionOption *selection)
-    : InbandTextTrackPrivateAVF(player)
+InbandTextTrackPrivateAVFObjC::InbandTextTrackPrivateAVFObjC(AVFInbandTrackParent* player, AVMediaSelectionOption *selection, InbandTextTrackPrivate::CueFormat format)
+    : InbandTextTrackPrivateAVF(player, format)
     , m_mediaSelectionOption(selection)
 {
 }
index baf869d..13c05eb 100644 (file)
@@ -56,7 +56,7 @@ SOFT_LINK_POINTER(AVFoundation, AVMetadataKeySpaceCommon, NSString *)
 namespace WebCore {
 
 InbandTextTrackPrivateLegacyAVFObjC::InbandTextTrackPrivateLegacyAVFObjC(MediaPlayerPrivateAVFoundationObjC* player, AVPlayerItemTrack* track)
-    : InbandTextTrackPrivateAVF(player)
+    : InbandTextTrackPrivateAVF(player, InbandTextTrackPrivate::Generic)
     , m_playerItemTrack(track)
 {
 }
index 28d953c..720678e 100644 (file)
@@ -76,7 +76,7 @@ public:
 
 #if HAVE(AVFOUNDATION_MEDIA_SELECTION_GROUP)
     RetainPtr<AVPlayerItem> playerItem() const { return m_avPlayerItem; }
-    void processCue(NSArray *, double);
+    void processCue(NSArray *, NSArray *, double);
     void flushCues();
 #endif
     
index 20c82cd..d296632 100644 (file)
@@ -676,7 +676,7 @@ void MediaPlayerPrivateAVFoundationObjC::createAVAssetForURL(const String& url)
     if (m_avAsset)
         return;
 
-    LOG(Media, "MediaPlayerPrivateAVFoundationObjC::createAVAssetForURL(%p)", this);
+    LOG(Media, "MediaPlayerPrivateAVFoundationObjC::createAVAssetForURL(%p) - url = %s", this, url.utf8().data());
 
     setDelayCallbacks(true);
 
@@ -808,7 +808,8 @@ void MediaPlayerPrivateAVFoundationObjC::createAVPlayerItem()
 #if HAVE(AVFOUNDATION_MEDIA_SELECTION_GROUP) && HAVE(AVFOUNDATION_LEGIBLE_OUTPUT_SUPPORT)
     const NSTimeInterval legibleOutputAdvanceInterval = 2;
 
-    m_legibleOutput = adoptNS([[AVPlayerItemLegibleOutput alloc] initWithMediaSubtypesForNativeRepresentation:[NSArray array]]);
+    RetainPtr<NSArray> subtypes = adoptNS([[NSArray alloc] initWithObjects:[NSNumber numberWithUnsignedInt:kCMSubtitleFormatType_WebVTT], nil]);
+    m_legibleOutput = adoptNS([[AVPlayerItemLegibleOutput alloc] initWithMediaSubtypesForNativeRepresentation:subtypes.get()]);
     [m_legibleOutput.get() setSuppressesPlayerRendering:YES];
 
     [m_legibleOutput.get() setDelegate:m_objcObserver.get() queue:dispatch_get_main_queue()];
@@ -1577,7 +1578,8 @@ void MediaPlayerPrivateAVFoundationObjC::tracksChanged()
     }
 
 #if HAVE(AVFOUNDATION_MEDIA_SELECTION_GROUP)
-    if (AVMediaSelectionGroupType *legibleGroup = safeMediaSelectionGroupForLegibleMedia()) {
+    AVMediaSelectionGroupType *legibleGroup = safeMediaSelectionGroupForLegibleMedia();
+    if (legibleGroup && m_cachedTracks) {
         hasCaptions = [[AVMediaSelectionGroup playableMediaSelectionOptionsFromArray:[legibleGroup options]] count];
         if (hasCaptions)
             processMediaSelectionOptions();
@@ -2164,7 +2166,7 @@ void MediaPlayerPrivateAVFoundationObjC::processMediaSelectionOptions()
         }
 #endif
 
-        m_textTracks.append(InbandTextTrackPrivateAVFObjC::create(this, option));
+        m_textTracks.append(InbandTextTrackPrivateAVFObjC::create(this, option, InbandTextTrackPrivate::Generic));
     }
 
     processNewAndRemovedTextTracks(removedTextTracks);
@@ -2180,12 +2182,12 @@ void MediaPlayerPrivateAVFoundationObjC::processMetadataTrack()
     player()->addTextTrack(m_metadataTrack);
 }
 
-void MediaPlayerPrivateAVFoundationObjC::processCue(NSArray *attributedStrings, double time)
+void MediaPlayerPrivateAVFoundationObjC::processCue(NSArray *attributedStrings, NSArray *nativeSamples, double time)
 {
     if (!m_currentTextTrack)
         return;
 
-    m_currentTextTrack->processCue(reinterpret_cast<CFArrayRef>(attributedStrings), time);
+    m_currentTextTrack->processCue(reinterpret_cast<CFArrayRef>(attributedStrings), reinterpret_cast<CFArrayRef>(nativeSamples), time);
 }
 
 void MediaPlayerPrivateAVFoundationObjC::flushCues()
@@ -2734,11 +2736,12 @@ NSArray* assetTrackMetadataKeyNames()
 
     RetainPtr<WebCoreAVFMovieObserver> strongSelf = self;
     RetainPtr<NSArray> strongStrings = strings;
-    callOnMainThread([strongSelf, strongStrings, itemTime] {
+    RetainPtr<NSArray> strongSamples = nativeSamples;
+    callOnMainThread([strongSelf, strongStrings, strongSamples, itemTime] {
         MediaPlayerPrivateAVFoundationObjC* callback = strongSelf->m_callback;
         if (!callback)
             return;
-        callback->processCue(strongStrings.get(), CMTimeGetSeconds(itemTime));
+        callback->processCue(strongStrings.get(), strongSamples.get(), CMTimeGetSeconds(itemTime));
     });
 }
 
index ff45b21..cba0176 100644 (file)
@@ -41,7 +41,7 @@ public:
         return adoptRef(new OutOfBandTextTrackPrivateAVF(player, selection));
     }
     
-    virtual void processCue(CFArrayRef, double) override { }
+    virtual void processCue(CFArrayRef, CFArrayRef, double) override { }
     virtual void resetCueValues() override { }
     
     virtual Category textTrackCategory() const override { return OutOfBand; }
@@ -50,7 +50,7 @@ public:
     
 protected:
     OutOfBandTextTrackPrivateAVF(AVFInbandTrackParent* player, AVMediaSelectionOption* selection)
-        : InbandTextTrackPrivateAVF(player)
+        : InbandTextTrackPrivateAVF(player, InbandTextTrackPrivate::Generic)
         , m_mediaSelectionOption(selection)
     {
     }