Title: [267521] trunk/Source/WebCore
Revision
267521
Author
[email protected]
Date
2020-09-24 00:10:26 -0700 (Thu, 24 Sep 2020)

Log Message

REGRESSION (iOS/Safari 14): MediaRecorder produces invalid video files
https://bugs.webkit.org/show_bug.cgi?id=216832
<rdar://problem/69377550>

Reviewed by Eric Carlson.

Start the audio and video timestamps at zero.
Compute the audio timestamp based on the sample count and the video timestamp based
on the time at which the video sample is received.

Covered by manually testing Safari generated videos on VLC, Chrome and Firefox.

* platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.h:
* platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.mm:
(WebCore::MediaRecorderPrivateWriter::initialize):
(WebCore::MediaRecorderPrivateWriter::startAssetWriter):
(WebCore::copySampleBufferWithCurrentTimeStamp):
(WebCore::MediaRecorderPrivateWriter::appendVideoSampleBuffer):
(WebCore::createAudioSampleBuffer):
(WebCore::MediaRecorderPrivateWriter::appendAudioSampleBuffer):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (267520 => 267521)


--- trunk/Source/WebCore/ChangeLog	2020-09-24 07:01:36 UTC (rev 267520)
+++ trunk/Source/WebCore/ChangeLog	2020-09-24 07:10:26 UTC (rev 267521)
@@ -1,3 +1,26 @@
+2020-09-24  Youenn Fablet  <[email protected]>
+
+        REGRESSION (iOS/Safari 14): MediaRecorder produces invalid video files
+        https://bugs.webkit.org/show_bug.cgi?id=216832
+        <rdar://problem/69377550>
+
+        Reviewed by Eric Carlson.
+
+        Start the audio and video timestamps at zero.
+        Compute the audio timestamp based on the sample count and the video timestamp based
+        on the time at which the video sample is received.
+
+        Covered by manually testing Safari generated videos on VLC, Chrome and Firefox.
+
+        * platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.h:
+        * platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.mm:
+        (WebCore::MediaRecorderPrivateWriter::initialize):
+        (WebCore::MediaRecorderPrivateWriter::startAssetWriter):
+        (WebCore::copySampleBufferWithCurrentTimeStamp):
+        (WebCore::MediaRecorderPrivateWriter::appendVideoSampleBuffer):
+        (WebCore::createAudioSampleBuffer):
+        (WebCore::MediaRecorderPrivateWriter::appendAudioSampleBuffer):
+
 2020-09-23  Peng Liu  <[email protected]>
 
         Add feature flags for GPU Process features

Modified: trunk/Source/WebCore/platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.h (267520 => 267521)


--- trunk/Source/WebCore/platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.h	2020-09-24 07:01:36 UTC (rev 267520)
+++ trunk/Source/WebCore/platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.h	2020-09-24 07:10:26 UTC (rev 267521)
@@ -131,6 +131,8 @@
     bool m_isFlushingSamples { false };
     bool m_shouldStopAfterFlushingSamples { false };
     bool m_firstVideoFrame { false };
+    CMTime m_firstVideoSampleTime { kCMTimeZero };
+    CMTime m_currentAudioSampleTime { kCMTimeZero };
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.mm (267520 => 267521)


--- trunk/Source/WebCore/platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.mm	2020-09-24 07:01:36 UTC (rev 267520)
+++ trunk/Source/WebCore/platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.mm	2020-09-24 07:10:26 UTC (rev 267521)
@@ -399,9 +399,8 @@
 }
 
 
-static inline RetainPtr<CMSampleBufferRef> copySampleBufferWithCurrentTimeStamp(CMSampleBufferRef originalBuffer)
+static inline RetainPtr<CMSampleBufferRef> copySampleBufferWithCurrentTimeStamp(CMSampleBufferRef originalBuffer, CMTime startTime)
 {
-    CMTime startTime = CMClockGetTime(CMClockGetHostTimeClock());
     CMItemCount count = 0;
     CMSampleBufferGetSampleTimingInfoArray(originalBuffer, 0, nil, &count);
 
@@ -425,6 +424,7 @@
 {
     if (!m_firstVideoFrame) {
         m_firstVideoFrame = true;
+        m_firstVideoSampleTime = CMClockGetTime(CMClockGetHostTimeClock());
         if (sample.videoRotation() != MediaSample::VideoRotation::None || sample.videoMirrored()) {
             auto videoTransform = CGAffineTransformMakeRotation(static_cast<int>(sample.videoRotation()) * M_PI / 180);
             if (sample.videoMirrored())
@@ -432,8 +432,9 @@
             m_videoAssetWriterInput.get().transform = videoTransform;
         }
     }
-    // FIXME: We should not set the timestamps if they are already set.
-    if (auto bufferWithCurrentTime = copySampleBufferWithCurrentTimeStamp(sample.platformSample().sample.cmSampleBuffer))
+
+    CMTime sampleTime = CMTimeSubtract(CMClockGetTime(CMClockGetHostTimeClock()), m_firstVideoSampleTime);
+    if (auto bufferWithCurrentTime = copySampleBufferWithCurrentTimeStamp(sample.platformSample().sample.cmSampleBuffer, sampleTime))
         m_videoCompressor->addSampleBuffer(bufferWithCurrentTime.get());
 }
 
@@ -449,7 +450,7 @@
     return adoptCF(format);
 }
 
-static inline RetainPtr<CMSampleBufferRef> createAudioSampleBuffer(const PlatformAudioData& data, const AudioStreamDescription& description, const WTF::MediaTime& time, size_t sampleCount)
+static inline RetainPtr<CMSampleBufferRef> createAudioSampleBuffer(const PlatformAudioData& data, const AudioStreamDescription& description, CMTime time, size_t sampleCount)
 {
     auto format = createAudioFormatDescription(description);
     if (!format)
@@ -456,7 +457,7 @@
         return nullptr;
 
     CMSampleBufferRef sampleBuffer = nullptr;
-    auto error = CMAudioSampleBufferCreateWithPacketDescriptions(kCFAllocatorDefault, NULL, false, NULL, NULL, format.get(), sampleCount, toCMTime(time), NULL, &sampleBuffer);
+    auto error = CMAudioSampleBufferCreateWithPacketDescriptions(kCFAllocatorDefault, NULL, false, NULL, NULL, format.get(), sampleCount, time, NULL, &sampleBuffer);
     if (error) {
         RELEASE_LOG_ERROR(MediaStream, "MediaRecorderPrivateWriter createAudioSampleBufferWithPacketDescriptions failed with %d", error);
         return nullptr;
@@ -471,10 +472,11 @@
     return buffer;
 }
 
-void MediaRecorderPrivateWriter::appendAudioSampleBuffer(const PlatformAudioData& data, const AudioStreamDescription& description, const WTF::MediaTime& time, size_t sampleCount)
+void MediaRecorderPrivateWriter::appendAudioSampleBuffer(const PlatformAudioData& data, const AudioStreamDescription& description, const WTF::MediaTime&, size_t sampleCount)
 {
-    if (auto sampleBuffer = createAudioSampleBuffer(data, description, time, sampleCount))
+    if (auto sampleBuffer = createAudioSampleBuffer(data, description, m_currentAudioSampleTime, sampleCount))
         m_audioCompressor->addSampleBuffer(sampleBuffer.get());
+    m_currentAudioSampleTime = CMTimeAdd(m_currentAudioSampleTime, toCMTime(MediaTime(sampleCount, description.sampleRate())));
 }
 
 void MediaRecorderPrivateWriter::finishedFlushingSamples()
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to