⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 267521 in webkit


Ignore:
Timestamp:
Sep 24, 2020, 12:10:26 AM (6 years ago)
Author:
youenn@apple.com
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):

Location:
trunk/Source/WebCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r267516 r267521  
     12020-09-24  Youenn Fablet  <youenn@apple.com>
     2
     3        REGRESSION (iOS/Safari 14): MediaRecorder produces invalid video files
     4        https://bugs.webkit.org/show_bug.cgi?id=216832
     5        <rdar://problem/69377550>
     6
     7        Reviewed by Eric Carlson.
     8
     9        Start the audio and video timestamps at zero.
     10        Compute the audio timestamp based on the sample count and the video timestamp based
     11        on the time at which the video sample is received.
     12
     13        Covered by manually testing Safari generated videos on VLC, Chrome and Firefox.
     14
     15        * platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.h:
     16        * platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.mm:
     17        (WebCore::MediaRecorderPrivateWriter::initialize):
     18        (WebCore::MediaRecorderPrivateWriter::startAssetWriter):
     19        (WebCore::copySampleBufferWithCurrentTimeStamp):
     20        (WebCore::MediaRecorderPrivateWriter::appendVideoSampleBuffer):
     21        (WebCore::createAudioSampleBuffer):
     22        (WebCore::MediaRecorderPrivateWriter::appendAudioSampleBuffer):
     23
    1242020-09-23  Peng Liu  <peng.liu6@apple.com>
    225
  • trunk/Source/WebCore/platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.h

    r267366 r267521  
    132132    bool m_shouldStopAfterFlushingSamples { false };
    133133    bool m_firstVideoFrame { false };
     134    CMTime m_firstVideoSampleTime { kCMTimeZero };
     135    CMTime m_currentAudioSampleTime { kCMTimeZero };
    134136};
    135137
  • trunk/Source/WebCore/platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.mm

    r267366 r267521  
    400400
    401401
    402 static inline RetainPtr<CMSampleBufferRef> copySampleBufferWithCurrentTimeStamp(CMSampleBufferRef originalBuffer)
    403 {
    404     CMTime startTime = CMClockGetTime(CMClockGetHostTimeClock());
     402static inline RetainPtr<CMSampleBufferRef> copySampleBufferWithCurrentTimeStamp(CMSampleBufferRef originalBuffer, CMTime startTime)
     403{
    405404    CMItemCount count = 0;
    406405    CMSampleBufferGetSampleTimingInfoArray(originalBuffer, 0, nil, &count);
     
    426425    if (!m_firstVideoFrame) {
    427426        m_firstVideoFrame = true;
     427        m_firstVideoSampleTime = CMClockGetTime(CMClockGetHostTimeClock());
    428428        if (sample.videoRotation() != MediaSample::VideoRotation::None || sample.videoMirrored()) {
    429429            auto videoTransform = CGAffineTransformMakeRotation(static_cast<int>(sample.videoRotation()) * M_PI / 180);
     
    433433        }
    434434    }
    435     // FIXME: We should not set the timestamps if they are already set.
    436     if (auto bufferWithCurrentTime = copySampleBufferWithCurrentTimeStamp(sample.platformSample().sample.cmSampleBuffer))
     435
     436    CMTime sampleTime = CMTimeSubtract(CMClockGetTime(CMClockGetHostTimeClock()), m_firstVideoSampleTime);
     437    if (auto bufferWithCurrentTime = copySampleBufferWithCurrentTimeStamp(sample.platformSample().sample.cmSampleBuffer, sampleTime))
    437438        m_videoCompressor->addSampleBuffer(bufferWithCurrentTime.get());
    438439}
     
    450451}
    451452
    452 static inline RetainPtr<CMSampleBufferRef> createAudioSampleBuffer(const PlatformAudioData& data, const AudioStreamDescription& description, const WTF::MediaTime& time, size_t sampleCount)
     453static inline RetainPtr<CMSampleBufferRef> createAudioSampleBuffer(const PlatformAudioData& data, const AudioStreamDescription& description, CMTime time, size_t sampleCount)
    453454{
    454455    auto format = createAudioFormatDescription(description);
     
    457458
    458459    CMSampleBufferRef sampleBuffer = nullptr;
    459     auto error = CMAudioSampleBufferCreateWithPacketDescriptions(kCFAllocatorDefault, NULL, false, NULL, NULL, format.get(), sampleCount, toCMTime(time), NULL, &sampleBuffer);
     460    auto error = CMAudioSampleBufferCreateWithPacketDescriptions(kCFAllocatorDefault, NULL, false, NULL, NULL, format.get(), sampleCount, time, NULL, &sampleBuffer);
    460461    if (error) {
    461462        RELEASE_LOG_ERROR(MediaStream, "MediaRecorderPrivateWriter createAudioSampleBufferWithPacketDescriptions failed with %d", error);
     
    472473}
    473474
    474 void MediaRecorderPrivateWriter::appendAudioSampleBuffer(const PlatformAudioData& data, const AudioStreamDescription& description, const WTF::MediaTime& time, size_t sampleCount)
    475 {
    476     if (auto sampleBuffer = createAudioSampleBuffer(data, description, time, sampleCount))
     475void MediaRecorderPrivateWriter::appendAudioSampleBuffer(const PlatformAudioData& data, const AudioStreamDescription& description, const WTF::MediaTime&, size_t sampleCount)
     476{
     477    if (auto sampleBuffer = createAudioSampleBuffer(data, description, m_currentAudioSampleTime, sampleCount))
    477478        m_audioCompressor->addSampleBuffer(sampleBuffer.get());
     479    m_currentAudioSampleTime = CMTimeAdd(m_currentAudioSampleTime, toCMTime(MediaTime(sampleCount, description.sampleRate())));
    478480}
    479481
Note: See TracChangeset for help on using the changeset viewer.