Changeset 282196 in webkit


Ignore:
Timestamp:
Sep 9, 2021 12:02:21 AM (10 months ago)
Author:
Jean-Yves Avenard
Message:

[WebAudio/WebM] Incorrect number of frames returned if decoding frame rate doesn't match original
https://bugs.webkit.org/show_bug.cgi?id=229251
rdar://problem/82095650

Source/WebCore:

Reviewed by Eric Carlson..

We can't rely on CoreMedia to performed the trimming correctly when resampling is also to be done.
It gives unexpected results. Let's do it ourselves instead.
Test: webaudio/decode-audio-data-webm-opus-resample.html

  • platform/audio/cocoa/AudioFileReaderCocoa.cpp:

(WebCore::AudioFileReader::decodeWebMData const):

LayoutTests:

Reviewed by Eric Carlson.

  • webaudio/decode-audio-data-webm-opus-resample-expected.txt: Added.
  • webaudio/decode-audio-data-webm-opus-resample.html: Added.
Location:
trunk
Files:
2 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r282195 r282196  
     12021-09-09  Jean-Yves Avenard  <jya@apple.com>
     2
     3        [WebAudio/WebM] Incorrect number of frames returned if decoding frame rate doesn't match original
     4        https://bugs.webkit.org/show_bug.cgi?id=229251
     5        rdar://problem/82095650
     6
     7        Reviewed by Eric Carlson.
     8
     9        * webaudio/decode-audio-data-webm-opus-resample-expected.txt: Added.
     10        * webaudio/decode-audio-data-webm-opus-resample.html: Added.
     11
    1122021-09-07  Tim Nguyen  <ntim@apple.com>
    213
  • trunk/LayoutTests/platform/mac/TestExpectations

    r282192 r282196  
    17131713[ Catalina Mojave BigSur ] media/media-source/media-webm-opus-partial-abort.html [ Skip ]
    17141714[ Catalina Mojave BigSur ] webaudio/decode-audio-data-webm-opus.html [ Skip ]
     1715[ Catalina Mojave BigSur ] webaudio/decode-audio-data-webm-opus-resample.html [ Skip ]
    17151716[ Catalina Mojave BigSur ] webaudio/decode-audio-data-webm-vorbis.html [ Skip ]
    17161717
  • trunk/Source/WebCore/ChangeLog

    r282194 r282196  
     12021-09-09  Jean-Yves Avenard  <jya@apple.com>
     2
     3        [WebAudio/WebM] Incorrect number of frames returned if decoding frame rate doesn't match original
     4        https://bugs.webkit.org/show_bug.cgi?id=229251
     5        rdar://problem/82095650
     6
     7        Reviewed by Eric Carlson..
     8
     9        We can't rely on CoreMedia to performed the trimming correctly when resampling is also to be done.
     10        It gives unexpected results. Let's do it ourselves instead.
     11        Test: webaudio/decode-audio-data-webm-opus-resample.html
     12
     13        * platform/audio/cocoa/AudioFileReaderCocoa.cpp:
     14        (WebCore::AudioFileReader::decodeWebMData const):
     15
    1162021-09-08  Youenn Fablet  <youenn@apple.com>
    217
  • trunk/Source/WebCore/platform/audio/cocoa/AudioFileReaderCocoa.cpp

    r280948 r282196  
    319319        PAL::AudioConverterSetProperty(converter, kAudioConverterDecompressionMagicCookie, magicCookieSize, magicCookie);
    320320
    321     AudioConverterPrimeInfo primeInfo = { UInt32(m_webmData->m_track->codecDelay().value_or(MediaTime()).toDouble() * outFormat.mSampleRate), 0 };
    322     INFO_LOG(LOGIDENTIFIER, "Will drop %u leading frames out of %llu", primeInfo.leadingFrames, numberOfFrames);
     321    AudioBufferListHolder decodedBufferList(inFormat.mChannelsPerFrame);
     322    if (!decodedBufferList) {
     323        RELEASE_LOG_FAULT(WebAudio, "Unable to create decoder");
     324        return { };
     325    }
     326
     327    // Instruct the decoder to not drop any frames
     328    // (by default the Opus decoder assumes that SampleRate / 400 frames are to be dropped.
     329    AudioConverterPrimeInfo primeInfo = { 0, 0 };
    323330    PAL::AudioConverterSetProperty(converter, kAudioConverterPrimeInfo, sizeof(primeInfo), &primeInfo);
    324331    UInt32 primeMethod = kConverterPrimeMethod_None;
    325332    PAL::AudioConverterSetProperty(converter, kAudioConverterPrimeMethod, sizeof(primeMethod), &primeMethod);
    326333
    327     AudioBufferListHolder decodedBufferList(inFormat.mChannelsPerFrame);
    328     if (!decodedBufferList) {
    329         RELEASE_LOG_FAULT(WebAudio, "Unable to create decoder");
    330         return { };
    331     }
     334    uint32_t leadingTrim = m_webmData->m_track->codecDelay().value_or(MediaTime::zeroTime()).toDouble() * outFormat.mSampleRate;
     335    // Calculate the number of trailing frames to be trimmed by rounding to nearest integer while minimizing cummulative rounding errors.
     336    uint32_t trailingTrim = (m_webmData->m_track->codecDelay().value_or(MediaTime::zeroTime()) + m_webmData->m_track->discardPadding().value_or(MediaTime::zeroTime())).toDouble() * outFormat.mSampleRate - leadingTrim + 0.5;
     337    INFO_LOG(LOGIDENTIFIER, "Will drop ", leadingTrim, " leading and ", trailingTrim, " trailing frames out of ", numberOfFrames);
    332338
    333339    size_t decodedFrames = 0;
     340    size_t totalDecodedFrames = 0;
    334341    OSStatus status;
    335342    for (size_t i = 0; i < m_webmData->m_samples.size(); i++) {
     
    358365        do {
    359366            if (numberOfFrames < decodedFrames) {
    360                 RELEASE_LOG_FAULT(WebAudio, "Decoded more frames than first calculated");
     367                RELEASE_LOG_FAULT(WebAudio, "Decoded more frames than first calculated, no available space left");
    361368                return { };
    362369            }
    363370            // in: the max number of packets we can handle from the decoder.
    364371            // out: the number of packets the decoder is actually returning.
    365             UInt32 numFrames = std::min<uint32_t>(std::numeric_limits<int32_t>::max() / sizeof(float), numberOfFrames - decodedFrames);
     372            // The AudioConverter will sometimes pad with trailing silence if we set the free space to what it actually is (numberOfFrames - decodedFrames).
     373            // So we set it to what there is left to decode instead.
     374            UInt32 numFrames = std::min<uint32_t>(std::numeric_limits<int32_t>::max() / sizeof(float), numberOfFrames - totalDecodedFrames);
    366375
    367376            for (UInt32 i = 0; i < inFormat.mChannelsPerFrame; i++) {
     
    375384                return { };
    376385            }
     386            totalDecodedFrames += numFrames;
     387            if (leadingTrim > 0) {
     388                UInt32 toTrim = std::min(leadingTrim, numFrames);
     389                for (UInt32 i = 0; i < outFormat.mChannelsPerFrame; i++)
     390                    memcpy(decodedBufferList->mBuffers[i].mData, static_cast<float*>(decodedBufferList->mBuffers[i].mData) + toTrim, (numFrames - toTrim) * sizeof(float));
     391                leadingTrim -= toTrim;
     392                numFrames -= toTrim;
     393            }
    377394            decodedFrames += numFrames;
    378395        } while (status != kNoMoreDataErr && status != noErr);
    379396    }
    380     size_t paddingFrames = m_webmData->m_track->discardPadding().value_or(MediaTime()).toDouble() * outFormat.mSampleRate;
    381     if (decodedFrames > paddingFrames)
    382         return decodedFrames - paddingFrames;
     397    if (decodedFrames > trailingTrim)
     398        return decodedFrames - trailingTrim;
    383399    return 0;
    384400}
Note: See TracChangeset for help on using the changeset viewer.