Source/WebCore:
authorjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 19 Oct 2016 07:07:26 +0000 (07:07 +0000)
committerjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 19 Oct 2016 07:07:26 +0000 (07:07 +0000)
[Mac][MSE] Movies with a 'mehd' box have a zero-duration
https://bugs.webkit.org/show_bug.cgi?id=163641

Reviewed by Darin Adler.

Test: media/media-source/media-source-init-segment-duration.html

The canonical (ISO/IEC 14496-12:2012) way to signal the duration of a fragmented media file is to add a
'mehd' box to the 'mvex' container box specifying the duration of the fragment. Support this through the
AVAsset -overallDurationHint property.

* platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm:
(WebCore::SourceBufferPrivateAVFObjC::didParseStreamDataAsAsset):
* platform/spi/mac/AVFoundationSPI.h:

LayoutTests:
[Mac][MSE] Movies with a 'mvex' box have a zero-duration
https://bugs.webkit.org/show_bug.cgi?id=163641

Reviewed by Darin Adler.

* media/media-source/content/test-fragmented-manifest.json:
* media/media-source/content/test-fragmented.mp4:
* platform/mac/TestExpectations:

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

LayoutTests/ChangeLog
LayoutTests/media/media-source/content/test-fragmented-manifest.json
LayoutTests/media/media-source/content/test-fragmented.mp4
LayoutTests/media/media-source/media-source-init-segment-duration-expected.txt [new file with mode: 0644]
LayoutTests/media/media-source/media-source-init-segment-duration.html [new file with mode: 0644]
LayoutTests/platform/mac/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm
Source/WebCore/platform/spi/mac/AVFoundationSPI.h

index 13be7cb..fca34cf 100644 (file)
@@ -1,3 +1,14 @@
+2016-10-19  Jer Noble  <jer.noble@apple.com>
+
+        [Mac][MSE] Movies with a 'mvex' box have a zero-duration
+        https://bugs.webkit.org/show_bug.cgi?id=163641
+
+        Reviewed by Darin Adler.
+
+        * media/media-source/content/test-fragmented-manifest.json:
+        * media/media-source/content/test-fragmented.mp4:
+        * platform/mac/TestExpectations:
+
 2016-10-18  Ryosuke Niwa  <rniwa@webkit.org>
 
         Import the latest custom elements tests from W3C
index 73bfeef..f4b858a 100644 (file)
@@ -1,18 +1,18 @@
 {
     "url": "content/test-fragmented.mp4",
     "type": "video/mp4; codecs=\"mp4a.40.2,avc1.4d281e\"",
-    "init": { "offset": 0, "size": 1215 },
+    "init": { "offset": 0, "size": 1231 },
     "duration": 10.327753,
     "media": [
-        { "offset": 1215,   "size": 67526, "timecode": 0.000000, "duration": 1.041668 },
-        { "offset": 68741,  "size": 72683, "timecode": 1.016916, "duration": 1.024752 },
-        { "offset": 141424, "size": 78499, "timecode": 2.015374, "duration": 1.026294 },
-        { "offset": 219923, "size": 77358, "timecode": 3.013832, "duration": 1.027835 },
-        { "offset": 297281, "size": 80748, "timecode": 4.012290, "duration": 1.029377 },
-        { "offset": 378029, "size": 78038, "timecode": 5.010748, "duration": 1.030919 },
-        { "offset": 456067, "size": 82223, "timecode": 6.009206, "duration": 1.032461 },
-        { "offset": 538290, "size": 78331, "timecode": 7.007664, "duration": 1.034003 },
-        { "offset": 616621, "size": 80736, "timecode": 8.006122, "duration": 1.035545 },
-        { "offset": 697357, "size": 77752, "timecode": 9.004580, "duration": 1.044899 }
+        { "offset": 1231,   "size": 67526, "timecode": 0.000000, "duration": 1.041668 },
+        { "offset": 68757,  "size": 72683, "timecode": 1.016916, "duration": 1.024752 },
+        { "offset": 141440, "size": 78499, "timecode": 2.015374, "duration": 1.026294 },
+        { "offset": 219939, "size": 77358, "timecode": 3.013832, "duration": 1.027835 },
+        { "offset": 297297, "size": 80748, "timecode": 4.012290, "duration": 1.029377 },
+        { "offset": 378045, "size": 78038, "timecode": 5.010748, "duration": 1.030919 },
+        { "offset": 456083, "size": 82223, "timecode": 6.009206, "duration": 1.032461 },
+        { "offset": 538306, "size": 78331, "timecode": 7.007664, "duration": 1.034003 },
+        { "offset": 616637, "size": 80736, "timecode": 8.006122, "duration": 1.035545 },
+        { "offset": 697373, "size": 77752, "timecode": 9.004580, "duration": 1.044899 }
     ]
 }
index cfd57d4..6ce467b 100644 (file)
Binary files a/LayoutTests/media/media-source/content/test-fragmented.mp4 and b/LayoutTests/media/media-source/content/test-fragmented.mp4 differ
diff --git a/LayoutTests/media/media-source/media-source-init-segment-duration-expected.txt b/LayoutTests/media/media-source/media-source-init-segment-duration-expected.txt
new file mode 100644 (file)
index 0000000..6cceabd
--- /dev/null
@@ -0,0 +1,10 @@
+This tests the ability of the SourceBuffer to detect the movie fragment duration from a 'mvex' header.
+
+RUN(video.src = URL.createObjectURL(source))
+EVENT(sourceopen)
+RUN(sourceBuffer = source.addSourceBuffer(loader.type()))
+RUN(sourceBuffer.appendBuffer(loader.initSegment()))
+EVENT(update)
+EXPECTED (video.duration == '10') OK
+END OF TEST
+
diff --git a/LayoutTests/media/media-source/media-source-init-segment-duration.html b/LayoutTests/media/media-source/media-source-init-segment-duration.html
new file mode 100644 (file)
index 0000000..5633019
--- /dev/null
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>media-source-init-segment-duration</title>
+    <script src="media-source-loader.js"></script>
+    <script src="../video-test.js"></script>
+    <script>
+    var loader;
+    var source;
+    var sourceBuffer;
+
+    function runTest() {
+        findMediaElement();
+
+        loader = new MediaSourceLoader('content/test-fragmented-manifest.json');
+        loader.onload = mediaDataLoaded;
+        loader.onerror = mediaDataLoadingFailed;
+    }
+
+    function mediaDataLoadingFailed() {
+        failTest('Media data loading failed');
+    }
+
+    function mediaDataLoaded() {
+        source = new MediaSource();
+        waitForEvent('sourceopen', sourceOpen, false, false, source);
+        waitForEventAndFail('error');
+        run('video.src = URL.createObjectURL(source)');
+    }
+
+    function sourceOpen() {
+        run('sourceBuffer = source.addSourceBuffer(loader.type())');
+        waitForEventOn(sourceBuffer, 'update', sourceInitialized, false, true);
+        run('sourceBuffer.appendBuffer(loader.initSegment())');
+    }
+
+    function sourceInitialized() {
+        testExpected('video.duration', 10);
+        endTest();
+    }
+    </script>
+</head>
+<body onload="runTest()">
+    <div>
+        This tests the ability of the SourceBuffer to detect the movie fragment duration from a 'mvex' header.
+    </div>
+    <video controls></video>
+</body>
+</html>
\ No newline at end of file
index 7c19e37..c415a07 100644 (file)
@@ -1084,6 +1084,9 @@ webkit.org/b/161725 [ Yosemite+ ] imported/w3c/web-platform-tests/media-source/m
 
 # This test times out.
 [ Yosemite+ ] media/media-source/media-source-seek-complete.html [ Timeout ]
+
+# <rdar://problem/18858636>
+media/media-source/media-source-init-segment-duration.html
 # --- End Media Source Tests ---
 
 # These tests used to only fail with WK2, but on Yosemite, they also fail with WK1.
index eb4a4d5..c4d14c6 100644 (file)
@@ -1,3 +1,20 @@
+2016-10-19  Jer Noble  <jer.noble@apple.com>
+
+        [Mac][MSE] Movies with a 'mehd' box have a zero-duration
+        https://bugs.webkit.org/show_bug.cgi?id=163641
+
+        Reviewed by Darin Adler.
+
+        Test: media/media-source/media-source-init-segment-duration.html
+
+        The canonical (ISO/IEC 14496-12:2012) way to signal the duration of a fragmented media file is to add a
+        'mehd' box to the 'mvex' container box specifying the duration of the fragment. Support this through the
+        AVAsset -overallDurationHint property.
+
+        * platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm:
+        (WebCore::SourceBufferPrivateAVFObjC::didParseStreamDataAsAsset):
+        * platform/spi/mac/AVFoundationSPI.h:
+
 2016-10-18  Darin Adler  <darin@apple.com>
 
         Move many miscellaneous classes from ExceptionCode to Exception
index f0dc4c2..cd56547 100644 (file)
@@ -490,7 +490,12 @@ void SourceBufferPrivateAVFObjC::didParseStreamDataAsAsset(AVAsset* asset)
     m_audioTracks.clear();
 
     SourceBufferPrivateClient::InitializationSegment segment;
-    segment.duration = toMediaTime([m_asset duration]);
+
+    if ([m_asset respondsToSelector:@selector(overallDurationHint)])
+        segment.duration = toMediaTime([m_asset overallDurationHint]);
+
+    if (segment.duration.isInvalid() || segment.duration == MediaTime::zeroTime())
+        segment.duration = toMediaTime([m_asset duration]);
 
     for (AVAssetTrack* track in [m_asset tracks]) {
         if ([track hasMediaCharacteristic:AVMediaCharacteristicLegible]) {
index eaba816..be4839d 100644 (file)
@@ -23,6 +23,8 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#pragma once
+
 #import "SoftLinking.h"
 #import <objc/runtime.h>
 
@@ -144,6 +146,7 @@ NS_ASSUME_NONNULL_END
 #endif // !PLATFORM(IOS)
 
 // FIXME: Wrap in a #if USE(APPLE_INTERNAL_SDK) once these SPI land
+#import <AVFoundation/AVAsset.h>
 #import <AVFoundation/AVAssetResourceLoader.h>
 
 NS_ASSUME_NONNULL_BEGIN
@@ -154,4 +157,8 @@ NS_ASSUME_NONNULL_BEGIN
 @property (nonatomic, nullable, retain) NSURLSession *URLSession;
 @end
 
+@interface AVAsset (AVAssetFragmentsPrivate)
+@property (nonatomic, readonly) CMTime overallDurationHint;
+@end
+
 NS_ASSUME_NONNULL_END