<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[179564] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/179564">179564</a></dd>
<dt>Author</dt> <dd>jer.noble@apple.com</dd>
<dt>Date</dt> <dd>2015-02-03 13:09:15 -0800 (Tue, 03 Feb 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>[MSE] Setting timestampOffset does not change the timestamps in the actual sample, leading to visual and audible errors.
https://bugs.webkit.org/show_bug.cgi?id=140929

Reviewed by Darin Adler.

Source/WebCore:

Test: media/media-source/media-source-timeoffset.html

Changing timestampOffset will correctly offset the presentation and decode times within SourceBuffer and
will correctly modify things like buffered ranges. But those changes need to be reflected in the underlying
MediaSample for decoders to decode and display the samples at the correct times.

Add a method to MediaSample which allows the caller to offset timestamps of the underlying PlatformMediaSample.

* Modules/mediasource/SourceBuffer.cpp:
(WebCore::SourceBuffer::sourceBufferPrivateDidReceiveSample): Call offsetTimestampsBy() on the sample.
* platform/MediaSample.h:
* platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm:
(WebCore::MediaSampleAVFObjC::offsetTimestampsBy): Create a new sample with the same underlying data
    but with a new timing info array, each timing info offset by the requested amount.
* platform/mock/mediasource/MockBox.h:
(WebCore::MockBox::offsetTimestampsBy): Offset m_presentationTimestamp and m_decodeTimestamp;
* platform/mock/mediasource/MockSourceBufferPrivate.cpp:
(WebCore::MockMediaSample::offsetTimestampsBy): Pass to MockBox.

LayoutTests:

* media/media-source/media-source-timeoffset-expected.txt: Added.
* media/media-source/media-source-timeoffset.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreModulesmediasourceSourceBuffercpp">trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformMediaSampleh">trunk/Source/WebCore/platform/MediaSample.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsavfoundationobjcSourceBufferPrivateAVFObjCmm">trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformmockmediasourceMockBoxh">trunk/Source/WebCore/platform/mock/mediasource/MockBox.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmockmediasourceMockSourceBufferPrivatecpp">trunk/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsmediamediasourcemediasourcetimeoffsetexpectedtxt">trunk/LayoutTests/media/media-source/media-source-timeoffset-expected.txt</a></li>
<li><a href="#trunkLayoutTestsmediamediasourcemediasourcetimeoffsethtml">trunk/LayoutTests/media/media-source/media-source-timeoffset.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (179563 => 179564)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-02-03 21:06:33 UTC (rev 179563)
+++ trunk/LayoutTests/ChangeLog        2015-02-03 21:09:15 UTC (rev 179564)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2015-02-03  Jer Noble  &lt;jer.noble@apple.com&gt;
+
+        [MSE] Setting timestampOffset does not change the timestamps in the actual sample, leading to visual and audible errors.
+        https://bugs.webkit.org/show_bug.cgi?id=140929
+
+        Reviewed by Darin Adler.
+
+        * media/media-source/media-source-timeoffset-expected.txt: Added.
+        * media/media-source/media-source-timeoffset.html: Added.
+
</ins><span class="cx"> 2015-02-03  Brent Fulgham  &lt;bfulgham@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [WIn] Unreviewed test updates.
</span></span></pre></div>
<a id="trunkLayoutTestsmediamediasourcemediasourcetimeoffsetexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/media/media-source/media-source-timeoffset-expected.txt (0 => 179564)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/media/media-source/media-source-timeoffset-expected.txt                                (rev 0)
+++ trunk/LayoutTests/media/media-source/media-source-timeoffset-expected.txt        2015-02-03 21:09:15 UTC (rev 179564)
</span><span class="lines">@@ -0,0 +1,18 @@
</span><ins>+
+RUN(video.src = URL.createObjectURL(source))
+EVENT(sourceopen)
+RUN(sourceBuffer = source.addSourceBuffer(&quot;video/mock; codecs=mock&quot;))
+RUN(sourceBuffer.appendBuffer(initSegment))
+EVENT(updateend)
+RUN(sourceBuffer.timestampOffset = 10)
+RUN(sourceBuffer.appendBuffer(samples))
+EVENT(updateend)
+EXPECTED (bufferedSamples.length == '6') OK
+{PTS({100000000/10000000, 10.000000}), DTS({100000000/10000000, 10.000000}), duration({1000/1000, 1.000000}), flags(1), generation(0)}
+{PTS({110000000/10000000, 11.000000}), DTS({110000000/10000000, 11.000000}), duration({1000/1000, 1.000000}), flags(0), generation(0)}
+{PTS({120000000/10000000, 12.000000}), DTS({120000000/10000000, 12.000000}), duration({1000/1000, 1.000000}), flags(0), generation(0)}
+{PTS({130000000/10000000, 13.000000}), DTS({130000000/10000000, 13.000000}), duration({1000/1000, 1.000000}), flags(1), generation(0)}
+{PTS({140000000/10000000, 14.000000}), DTS({140000000/10000000, 14.000000}), duration({1000/1000, 1.000000}), flags(0), generation(0)}
+{PTS({150000000/10000000, 15.000000}), DTS({150000000/10000000, 15.000000}), duration({1000/1000, 1.000000}), flags(0), generation(0)}
+END OF TEST
+
</ins></span></pre></div>
<a id="trunkLayoutTestsmediamediasourcemediasourcetimeoffsethtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/media/media-source/media-source-timeoffset.html (0 => 179564)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/media/media-source/media-source-timeoffset.html                                (rev 0)
+++ trunk/LayoutTests/media/media-source/media-source-timeoffset.html        2015-02-03 21:09:15 UTC (rev 179564)
</span><span class="lines">@@ -0,0 +1,61 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+    &lt;title&gt;media-source-timeoffset&lt;/title&gt;
+    &lt;script src=&quot;mock-media-source.js&quot;&gt;&lt;/script&gt;
+    &lt;script src=&quot;../video-test.js&quot;&gt;&lt;/script&gt;
+    &lt;script&gt;
+    var source;
+    var sourceBuffer;
+    var initSegment;
+    var samples;
+    var bufferedSamples;
+
+    if (window.internals)
+        internals.initializeMockMediaSource();
+
+    function runTest()
+    {
+        findMediaElement();
+
+        source = new MediaSource();
+        waitForEventOn(source, 'sourceopen', sourceOpen);
+        run('video.src = URL.createObjectURL(source)');
+    }
+
+    function sourceOpen()
+    {
+        run('sourceBuffer = source.addSourceBuffer(&quot;video/mock; codecs=mock&quot;)');
+        waitForEventOn(sourceBuffer, 'updateend', loadSamples, false, true);
+        initSegment = makeAInit(8, [makeATrack(1, 'mock', TRACK_KIND.VIDEO)]);
+        run('sourceBuffer.appendBuffer(initSegment)');
+    }
+
+    function loadSamples()
+    {
+       samples = concatenateSamples([
+            makeASample(0, 0, 1, 1, SAMPLE_FLAG.SYNC, 0),
+            makeASample(1, 1, 1, 1, SAMPLE_FLAG.NONE, 0),
+            makeASample(2, 2, 1, 1, SAMPLE_FLAG.NONE, 0),
+            makeASample(3, 3, 1, 1, SAMPLE_FLAG.SYNC, 0),
+            makeASample(4, 4, 1, 1, SAMPLE_FLAG.NONE, 0),
+            makeASample(5, 5, 1, 1, SAMPLE_FLAG.NONE, 0),
+        ]);
+        waitForEventOn(sourceBuffer, 'updateend', samplesAdded, false, true);
+        run('sourceBuffer.timestampOffset = 10');
+        run('sourceBuffer.appendBuffer(samples)');
+    }
+
+    function samplesAdded()
+    {
+        bufferedSamples = internals.bufferedSamplesForTrackID(sourceBuffer, 1);
+        testExpected(&quot;bufferedSamples.length&quot;, 6);
+        bufferedSamples.forEach(consoleWrite);
+
+        endTest();
+    }
+    &lt;/script&gt;
+&lt;/head&gt;
+&lt;body onload=&quot;runTest()&quot;&gt;
+    &lt;video&gt;&lt;/video&gt;
+&lt;/body&gt;
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (179563 => 179564)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-02-03 21:06:33 UTC (rev 179563)
+++ trunk/Source/WebCore/ChangeLog        2015-02-03 21:09:15 UTC (rev 179564)
</span><span class="lines">@@ -1,5 +1,31 @@
</span><span class="cx"> 2015-02-03  Jer Noble  &lt;jer.noble@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        [MSE] Setting timestampOffset does not change the timestamps in the actual sample, leading to visual and audible errors.
+        https://bugs.webkit.org/show_bug.cgi?id=140929
+
+        Reviewed by Darin Adler.
+
+        Test: media/media-source/media-source-timeoffset.html
+
+        Changing timestampOffset will correctly offset the presentation and decode times within SourceBuffer and
+        will correctly modify things like buffered ranges. But those changes need to be reflected in the underlying
+        MediaSample for decoders to decode and display the samples at the correct times.
+
+        Add a method to MediaSample which allows the caller to offset timestamps of the underlying PlatformMediaSample.
+
+        * Modules/mediasource/SourceBuffer.cpp:
+        (WebCore::SourceBuffer::sourceBufferPrivateDidReceiveSample): Call offsetTimestampsBy() on the sample.
+        * platform/MediaSample.h:
+        * platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm:
+        (WebCore::MediaSampleAVFObjC::offsetTimestampsBy): Create a new sample with the same underlying data
+            but with a new timing info array, each timing info offset by the requested amount.
+        * platform/mock/mediasource/MockBox.h:
+        (WebCore::MockBox::offsetTimestampsBy): Offset m_presentationTimestamp and m_decodeTimestamp;
+        * platform/mock/mediasource/MockSourceBufferPrivate.cpp:
+        (WebCore::MockMediaSample::offsetTimestampsBy): Pass to MockBox.
+
+2015-02-03  Jer Noble  &lt;jer.noble@apple.com&gt;
+
</ins><span class="cx">         [Mac][EME] Crash in CDMSessionMediaSourceAVFObjC::layerDidReceiveError() - NSError not KVO compliant for key NSUnderlyingError.
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=140529
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediasourceSourceBuffercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp (179563 => 179564)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp        2015-02-03 21:06:33 UTC (rev 179563)
+++ trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp        2015-02-03 21:09:15 UTC (rev 179564)
</span><span class="lines">@@ -1352,6 +1352,9 @@
</span><span class="cx"> 
</span><span class="cx">             // 1.4.2 Add timestampOffset to the decode timestamp.
</span><span class="cx">             decodeTimestamp += m_timestampOffset;
</span><ins>+
+            // Reflect the new timestamps back into the sample.
+            sample-&gt;offsetTimestampsBy(m_timestampOffset);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // 1.5 Let track buffer equal the track buffer that the coded frame will be added to.
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformMediaSampleh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/MediaSample.h (179563 => 179564)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/MediaSample.h        2015-02-03 21:06:33 UTC (rev 179563)
+++ trunk/Source/WebCore/platform/MediaSample.h        2015-02-03 21:09:15 UTC (rev 179564)
</span><span class="lines">@@ -58,6 +58,7 @@
</span><span class="cx">     virtual AtomicString trackID() const = 0;
</span><span class="cx">     virtual size_t sizeInBytes() const = 0;
</span><span class="cx">     virtual FloatSize presentationSize() const = 0;
</span><ins>+    virtual void offsetTimestampsBy(const MediaTime&amp;) = 0;
</ins><span class="cx"> 
</span><span class="cx">     enum SampleFlags {
</span><span class="cx">         None = 0,
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationobjcSourceBufferPrivateAVFObjCmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm (179563 => 179564)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm        2015-02-03 21:06:33 UTC (rev 179563)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm        2015-02-03 21:09:15 UTC (rev 179564)
</span><span class="lines">@@ -87,12 +87,14 @@
</span><span class="cx"> SOFT_LINK(CoreMedia, CMFormatDescriptionGetMediaType, CMMediaType, (CMFormatDescriptionRef desc), (desc))
</span><span class="cx"> SOFT_LINK(CoreMedia, CMSampleBufferCreate, OSStatus, (CFAllocatorRef allocator, CMBlockBufferRef dataBuffer, Boolean dataReady, CMSampleBufferMakeDataReadyCallback makeDataReadyCallback, void *makeDataReadyRefcon, CMFormatDescriptionRef formatDescription, CMItemCount numSamples, CMItemCount numSampleTimingEntries, const CMSampleTimingInfo *sampleTimingArray, CMItemCount numSampleSizeEntries, const size_t *sampleSizeArray, CMSampleBufferRef *sBufOut), (allocator, dataBuffer, dataReady, makeDataReadyCallback, makeDataReadyRefcon, formatDescription, numSamples, numSampleTimingEntries, sampleTimingArray, numSampleSizeEntries, sampleSizeArray, sBufOut))
</span><span class="cx"> SOFT_LINK(CoreMedia, CMSampleBufferCreateCopy, OSStatus, (CFAllocatorRef allocator, CMSampleBufferRef sbuf, CMSampleBufferRef *sbufCopyOut), (allocator, sbuf, sbufCopyOut))
</span><ins>+SOFT_LINK(CoreMedia, CMSampleBufferCreateCopyWithNewTiming, OSStatus, (CFAllocatorRef allocator, CMSampleBufferRef originalSBuf, CMItemCount numSampleTimingEntries, const CMSampleTimingInfo *sampleTimingArray, CMSampleBufferRef *sBufCopyOut), (allocator, originalSBuf, numSampleTimingEntries, sampleTimingArray, sBufCopyOut))
</ins><span class="cx"> SOFT_LINK(CoreMedia, CMSampleBufferCallForEachSample, OSStatus, (CMSampleBufferRef sbuf, OSStatus (*callback)( CMSampleBufferRef sampleBuffer, CMItemCount index, void *refcon), void *refcon), (sbuf, callback, refcon))
</span><span class="cx"> SOFT_LINK(CoreMedia, CMSampleBufferGetDecodeTimeStamp, CMTime, (CMSampleBufferRef sbuf), (sbuf))
</span><span class="cx"> SOFT_LINK(CoreMedia, CMSampleBufferGetDuration, CMTime, (CMSampleBufferRef sbuf), (sbuf))
</span><span class="cx"> SOFT_LINK(CoreMedia, CMSampleBufferGetFormatDescription, CMFormatDescriptionRef, (CMSampleBufferRef sbuf), (sbuf))
</span><span class="cx"> SOFT_LINK(CoreMedia, CMSampleBufferGetPresentationTimeStamp, CMTime, (CMSampleBufferRef sbuf), (sbuf))
</span><span class="cx"> SOFT_LINK(CoreMedia, CMSampleBufferGetSampleAttachmentsArray, CFArrayRef, (CMSampleBufferRef sbuf, Boolean createIfNecessary), (sbuf, createIfNecessary))
</span><ins>+SOFT_LINK(CoreMedia,  CMSampleBufferGetSampleTimingInfoArray, OSStatus, (CMSampleBufferRef sbuf, CMItemCount timingArrayEntries, CMSampleTimingInfo *timingArrayOut, CMItemCount *timingArrayEntriesNeededOut), (sbuf, timingArrayEntries, timingArrayOut, timingArrayEntriesNeededOut))
</ins><span class="cx"> SOFT_LINK(CoreMedia, CMSampleBufferGetTotalSampleSize, size_t, (CMSampleBufferRef sbuf), (sbuf))
</span><span class="cx"> SOFT_LINK(CoreMedia, CMFormatDescriptionGetMediaSubType, FourCharCode, (CMFormatDescriptionRef desc), (desc))
</span><span class="cx"> SOFT_LINK(CoreMedia, CMSetAttachment, void, (CMAttachmentBearerRef target, CFStringRef key, CFTypeRef value, CMAttachmentMode attachmentMode), (target, key, value, attachmentMode))
</span><span class="lines">@@ -488,6 +490,7 @@
</span><span class="cx">     virtual SampleFlags flags() const override;
</span><span class="cx">     virtual PlatformSample platformSample() override;
</span><span class="cx">     virtual void dump(PrintStream&amp;) const override;
</span><ins>+    virtual void offsetTimestampsBy(const MediaTime&amp;) override;
</ins><span class="cx"> 
</span><span class="cx">     RetainPtr&lt;CMSampleBufferRef&gt; m_sample;
</span><span class="cx">     AtomicString m_id;
</span><span class="lines">@@ -537,6 +540,29 @@
</span><span class="cx">     out.print(&quot;{PTS(&quot;, presentationTime(), &quot;), DTS(&quot;, decodeTime(), &quot;), duration(&quot;, duration(), &quot;), flags(&quot;, (int)flags(), &quot;), presentationSize(&quot;, presentationSize(), &quot;)}&quot;);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void MediaSampleAVFObjC::offsetTimestampsBy(const MediaTime&amp; offset)
+{
+    CMItemCount itemCount = 0;
+    if (noErr != CMSampleBufferGetSampleTimingInfoArray(m_sample.get(), 0, nullptr, &amp;itemCount))
+        return;
+
+    Vector&lt;CMSampleTimingInfo&gt; timingInfoArray;
+    timingInfoArray.grow(itemCount);
+    if (noErr != CMSampleBufferGetSampleTimingInfoArray(m_sample.get(), itemCount, timingInfoArray.data(), nullptr))
+        return;
+
+    for (auto&amp; timing : timingInfoArray) {
+        timing.presentationTimeStamp = toCMTime(toMediaTime(timing.presentationTimeStamp) + offset);
+        timing.decodeTimeStamp = toCMTime(toMediaTime(timing.decodeTimeStamp) + offset);
+    }
+
+    CMSampleBufferRef newSample;
+    if (noErr != CMSampleBufferCreateCopyWithNewTiming(kCFAllocatorDefault, m_sample.get(), itemCount, timingInfoArray.data(), &amp;newSample))
+        return;
+
+    m_sample = adoptCF(newSample);
+}
+
</ins><span class="cx"> #pragma mark -
</span><span class="cx"> #pragma mark MediaDescriptionAVFObjC
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmockmediasourceMockBoxh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mock/mediasource/MockBox.h (179563 => 179564)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mock/mediasource/MockBox.h        2015-02-03 21:06:33 UTC (rev 179563)
+++ trunk/Source/WebCore/platform/mock/mediasource/MockBox.h        2015-02-03 21:09:15 UTC (rev 179564)
</span><span class="lines">@@ -130,6 +130,11 @@
</span><span class="cx">     int32_t trackID() const { return m_trackID; }
</span><span class="cx">     uint8_t flags() const { return m_flags; }
</span><span class="cx">     uint8_t generation() const { return m_generation; }
</span><ins>+    void offsetTimestampsBy(const MediaTime&amp; offset)
+    {
+        m_presentationTimestamp += offset;
+        m_decodeTimestamp += offset;
+    }
</ins><span class="cx"> 
</span><span class="cx">     enum {
</span><span class="cx">         IsSync = 1 &lt;&lt; 0,
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmockmediasourceMockSourceBufferPrivatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.cpp (179563 => 179564)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.cpp        2015-02-03 21:06:33 UTC (rev 179563)
+++ trunk/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.cpp        2015-02-03 21:09:15 UTC (rev 179564)
</span><span class="lines">@@ -63,6 +63,7 @@
</span><span class="cx">     virtual PlatformSample platformSample() override;
</span><span class="cx">     virtual FloatSize presentationSize() const override { return FloatSize(); }
</span><span class="cx">     virtual void dump(PrintStream&amp;) const override;
</span><ins>+    virtual void offsetTimestampsBy(const MediaTime&amp; offset) override { m_box.offsetTimestampsBy(offset); }
</ins><span class="cx"> 
</span><span class="cx">     unsigned generation() const { return m_box.generation(); }
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>