| /* |
| * Copyright (C) 2020 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
| * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
| * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
| * THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "config.h" |
| #include "SourceBufferParser.h" |
| |
| #if ENABLE(MEDIA_SOURCE) |
| |
| #include "ContentType.h" |
| #include "SharedBuffer.h" |
| #include "SourceBufferParserAVFObjC.h" |
| #include "SourceBufferParserWebM.h" |
| #include <pal/spi/cocoa/MediaToolboxSPI.h> |
| #include <wtf/text/WTFString.h> |
| |
| #include <pal/cocoa/MediaToolboxSoftLink.h> |
| |
| namespace WebCore { |
| |
| MediaPlayerEnums::SupportsType SourceBufferParser::isContentTypeSupported(const ContentType& type) |
| { |
| MediaPlayerEnums::SupportsType supports = MediaPlayerEnums::SupportsType::IsNotSupported; |
| supports = std::max(supports, SourceBufferParserWebM::isContentTypeSupported(type)); |
| supports = std::max(supports, SourceBufferParserAVFObjC::isContentTypeSupported(type)); |
| return supports; |
| } |
| |
| RefPtr<SourceBufferParser> SourceBufferParser::create(const ContentType& type, bool webMParserEnabled) |
| { |
| if (SourceBufferParserWebM::isContentTypeSupported(type) != MediaPlayerEnums::SupportsType::IsNotSupported && webMParserEnabled) |
| return adoptRef(new SourceBufferParserWebM()); |
| |
| if (SourceBufferParserAVFObjC::isContentTypeSupported(type) != MediaPlayerEnums::SupportsType::IsNotSupported) |
| return adoptRef(new SourceBufferParserAVFObjC()); |
| |
| return nullptr; |
| } |
| |
| static SourceBufferParser::CallOnClientThreadCallback callOnMainThreadCallback() |
| { |
| return [](Function<void()>&& function) { |
| callOnMainThread(WTFMove(function)); |
| }; |
| } |
| |
| void SourceBufferParser::setCallOnClientThreadCallback(CallOnClientThreadCallback&& callback) |
| { |
| ASSERT(callback); |
| m_callOnClientThreadCallback = WTFMove(callback); |
| } |
| |
| SourceBufferParser::SourceBufferParser() |
| : m_callOnClientThreadCallback(callOnMainThreadCallback()) |
| { |
| } |
| |
| void SourceBufferParser::setMinimumAudioSampleDuration(float) |
| { |
| } |
| |
| SourceBufferParser::Segment::Segment(Ref<SharedBuffer>&& buffer) |
| : m_segment(WTFMove(buffer)) |
| { |
| } |
| |
| #if HAVE(MT_PLUGIN_FORMAT_READER) |
| SourceBufferParser::Segment::Segment(RetainPtr<MTPluginByteSourceRef>&& segment) |
| : m_segment(WTFMove(segment)) |
| { |
| } |
| #endif |
| |
| size_t SourceBufferParser::Segment::size() const |
| { |
| return WTF::switchOn(m_segment, |
| #if HAVE(MT_PLUGIN_FORMAT_READER) |
| [](const RetainPtr<MTPluginByteSourceRef>& byteSource) |
| { |
| return clampTo<size_t>(MTPluginByteSourceGetLength(byteSource.get())); |
| }, |
| #endif |
| [](const Ref<SharedBuffer>& buffer) |
| { |
| return buffer->size(); |
| } |
| ); |
| } |
| |
| auto SourceBufferParser::Segment::read(size_t position, size_t sizeToRead, uint8_t* destination) const -> ReadResult |
| { |
| size_t segmentSize = size(); |
| sizeToRead = std::min(sizeToRead, segmentSize - std::min(position, segmentSize)); |
| return WTF::switchOn(m_segment, |
| #if HAVE(MT_PLUGIN_FORMAT_READER) |
| [&](const RetainPtr<MTPluginByteSourceRef>& byteSource) -> ReadResult |
| { |
| size_t sizeRead = 0; |
| auto status = MTPluginByteSourceRead(byteSource.get(), sizeToRead, CheckedInt64(position), destination, &sizeRead); |
| if (status == noErr) |
| return sizeRead; |
| if (status == kMTPluginByteSourceError_EndOfStream) |
| return Unexpected<ReadError> { ReadError::EndOfFile }; |
| return Unexpected<ReadError> { ReadError::FatalError }; |
| }, |
| #endif |
| [&](const Ref<SharedBuffer>& buffer) -> ReadResult |
| { |
| buffer->copyTo(destination, position, sizeToRead); |
| return sizeToRead; |
| } |
| ); |
| } |
| |
| Ref<SharedBuffer> SourceBufferParser::Segment::takeSharedBuffer() |
| { |
| return WTF::switchOn(m_segment, |
| #if HAVE(MT_PLUGIN_FORMAT_READER) |
| [&](RetainPtr<MTPluginByteSourceRef>&) |
| { |
| Vector<uint8_t> vector(size()); |
| auto readResult = read(0, vector.size(), vector.data()); |
| if (!readResult.has_value()) |
| return SharedBuffer::create(); |
| vector.shrink(readResult.value()); |
| return SharedBuffer::create(WTFMove(vector)); |
| }, |
| #endif |
| [&](Ref<SharedBuffer>& buffer) |
| { |
| return std::exchange(buffer, SharedBuffer::create()); |
| } |
| ); |
| } |
| |
| RefPtr<SharedBuffer> SourceBufferParser::Segment::getSharedBuffer() const |
| { |
| return WTF::switchOn(m_segment, |
| #if HAVE(MT_PLUGIN_FORMAT_READER) |
| [&](const RetainPtr<MTPluginByteSourceRef>&) -> RefPtr<SharedBuffer> |
| { |
| return nullptr; |
| }, |
| #endif |
| [&](const Ref<SharedBuffer>& buffer) -> RefPtr<SharedBuffer> |
| { |
| return buffer.ptr(); |
| } |
| ); |
| } |
| |
| } // namespace WebCore |
| |
| #endif // ENABLE(MEDIA_SOURCE) |