Diff
Modified: trunk/LayoutTests/ChangeLog (227630 => 227631)
--- trunk/LayoutTests/ChangeLog 2018-01-25 22:27:27 UTC (rev 227630)
+++ trunk/LayoutTests/ChangeLog 2018-01-25 22:29:55 UTC (rev 227631)
@@ -1,3 +1,12 @@
+2018-01-25 Jer Noble <[email protected]>
+
+ Move ImageDecoderAVFObjC from using AVSampleBufferGenerator to AVAssetReaderOutput for parsing
+ https://bugs.webkit.org/show_bug.cgi?id=182091
+
+ Reviewed by Eric Carlson.
+
+ * platform/ios/imported/w3c/web-platform-tests/html/semantics/embedded-content/the-img-element/update-the-source-set-expected.txt: Added.
+
2018-01-25 Antoine Quint <[email protected]>
[Web Animations] Account for provided easings when computing progress and resolving keyframe effect values
Added: trunk/LayoutTests/platform/ios/imported/w3c/web-platform-tests/html/semantics/embedded-content/the-img-element/update-the-source-set-expected.txt (0 => 227631)
--- trunk/LayoutTests/platform/ios/imported/w3c/web-platform-tests/html/semantics/embedded-content/the-img-element/update-the-source-set-expected.txt (rev 0)
+++ trunk/LayoutTests/platform/ios/imported/w3c/web-platform-tests/html/semantics/embedded-content/the-img-element/update-the-source-set-expected.txt 2018-01-25 22:29:55 UTC (rev 227631)
@@ -0,0 +1,180 @@
+
+PASS <img data-expect="">
+FAIL <img src="" data-expect=""> assert_equals: expected "" but got "http://localhost:8800/html/semantics/embedded-content/the-img-element/update-the-source-set.html"
+PASS <img src="" data-expect="data:,a">
+PASS <img srcset="" src="" data-expect="data:,a">
+PASS <img srcset="data:,b" src="" data-expect="data:,b">
+PASS <img src="" srcset="data:,b" data-expect="data:,b"><!-- srcset after src -->
+PASS <img src="" srcset="data:,b 1x" data-expect="data:,b">
+PASS <img src="" srcset="data:,b 1.0x" data-expect="data:,b">
+PASS <img src="" srcset="data:,b 1e0x" data-expect="data:,b">
+PASS <img src="" srcset="data:,b 10000w" sizes="1px" data-expect="data:,b">
+PASS <img src="" srcset="data:,b 10000w, data:,c 10000x" sizes="1px" data-expect="data:,b">
+PASS <img src="" srcset="data:,b 10000x, data:,c 10000w" sizes="1px" data-expect="data:,b">
+PASS <img src="" srcset="data:,b 1w" sizes="10000px" data-expect="data:,b">
+PASS <img src="" srcset="data:,b 1w, data:,c 0.0001x" sizes="10000px" data-expect="data:,b">
+PASS <img src="" srcset="data:,b 0.0001x, data:,c 1w" sizes="10000px" data-expect="data:,b">
+PASS <img srcset="data:,a" data-expect="data:,a">
+PASS <picture>foo<img src="" data-expect="data:,a"></picture>
+PASS <picture><!--foo--><img src="" data-expect="data:,a"></picture>
+PASS <picture><br><img src="" data-expect="data:,a"></picture>
+PASS <picture><p></p><img src="" data-expect="data:,a"></picture>
+PASS <picture><video><source srcset="data:,b"></video><img src="" data-expect="data:,a"></picture>
+PASS <picture><span><source srcset="data:,b"></span><img src="" data-expect="data:,a"></picture>
+PASS <picture><svg><source srcset="data:,b"></source></svg><img src="" data-expect="data:,a"></picture>
+PASS <picture><svg></svg><source srcset="data:,b"><img src="" data-expect="data:,b"></picture>
+PASS <picture><svg><font></font><source srcset="data:,b"></source></svg><img src="" data-expect="data:,a"></picture>
+PASS <picture><svg><!--<font face> tag breaks out of svg--></svg><font face=""></font><source srcset="data:,b"><img src="" data-expect="data:,b"></picture>
+PASS <picture><img src="" src="" data-expect="data:,b"></picture>
+PASS <picture><source><img src="" data-expect="data:,a"></picture>
+PASS <picture><source src="" src="" data-expect="data:,a"></picture>
+PASS <picture><source srcset=""><img src="" data-expect="data:,a"></picture>
+PASS <picture><source srcset=", ,"><img src="" data-expect="data:,a"></picture>
+PASS <picture><source srcset="data:,b 1x 1x"><img src="" data-expect="data:,a"></picture>
+PASS <picture><source srcset="data:,b" media=""><img src="" data-expect="data:,b"></picture>
+PASS <picture><source srcset="data:,b" media="all"><img src="" data-expect="data:,b"></picture>
+PASS <picture><source srcset="data:,b" media="all and (min-width:0)"><img src="" data-expect="data:,b"></picture>
+PASS <picture><source srcset="data:,b" media="all and !"><img src="" data-expect="data:,a"></picture>
+PASS <picture><source srcset="data:,b" media="all and (!)"><img src="" data-expect="data:,a"></picture>
+PASS <picture><source srcset="data:,b" media="not all"><img src="" data-expect="data:,a"></picture>
+PASS <picture><source srcset="data:,b" media="not all and (min-width:0)"><img src="" data-expect="data:,a"></picture>
+PASS <picture><source srcset="data:,b" media="not all and (max-width:0)"><img src="" data-expect="data:,b"></picture>
+PASS <picture><source srcset="data:,b" media="not all and !"><img src="" data-expect="data:,a"></picture>
+PASS <picture><source srcset="data:,b" media="not all and (!)"><img src="" data-expect="data:,a"></picture>
+PASS <picture><source srcset="data:,b" media="all, !"><img src="" data-expect="data:,b"></picture>
+PASS <picture><source srcset="data:,b" media=","><img src="" data-expect="data:,a"></picture>
+PASS <picture><source srcset="data:,b" media=", all"><img src="" data-expect="data:,b"></picture>
+PASS <picture><source srcset="data:,b" type=""><img src="" data-expect="data:,b"></picture>
+PASS <picture><source srcset="data:,b" type=" "><img src="" data-expect="data:,b"></picture>
+PASS <picture><source srcset="data:,b" type="image/gif"><img src="" data-expect="data:,b"></picture>
+PASS <picture><source srcset="data:,b" type=" image/gif"><img src="" data-expect="data:,b"></picture>
+PASS <picture><source srcset="data:,b" type="image/gif "><img src="" data-expect="data:,b"></picture>
+PASS <picture><source srcset="data:,b" type="image/gif;"><img src="" data-expect="data:,b"></picture>
+PASS <picture><source srcset="data:,b" type="image/gif;encodings"><img src="" data-expect="data:,b"></picture>
+PASS <picture><source srcset="data:,b" type="image/gif;encodings="><img src="" data-expect="data:,b"></picture>
+PASS <picture><source srcset="data:,b" type="image/gif;encodings=foobar"><img src="" data-expect="data:,b"></picture>
+PASS <picture><source srcset="data:,b" type="image/png"><img src="" data-expect="data:,b"></picture>
+PASS <picture><source srcset="data:,b" type="image/jpeg"><img src="" data-expect="data:,b"></picture>
+PASS <picture><source srcset="data:,b" type="image/svg+xml"><img src="" data-expect="data:,b"></picture>
+PASS <picture><source srcset="data:,b" type="image/x-icon"><img src="" data-expect="data:,b"></picture>
+PASS <picture><source srcset="data:,b" type="text/xml"><img src="" data-expect="data:,a"></picture>
+PASS <picture><source srcset="data:,b" type="text/html"><img src="" data-expect="data:,a"></picture>
+PASS <picture><source srcset="data:,b" type="text/plain"><img src="" data-expect="data:,a"></picture>
+PASS <picture><source srcset="data:,b" type="text/css"><img src="" data-expect="data:,a"></picture>
+FAIL <picture><source srcset="data:,b" type="video/mp4"><img src="" data-expect="data:,a"></picture> assert_equals: expected "data:,a" but got "data:,b"
+PASS <picture><source srcset="data:,b" type="video/ogg"><img src="" data-expect="data:,a"></picture>
+PASS <picture><source srcset="data:,b" type="video/webm"><img src="" data-expect="data:,a"></picture>
+PASS <picture><source srcset="data:,b" type="unknown/unknown"><img src="" data-expect="data:,a"></picture>
+PASS <picture><source srcset="data:,b" type="application/octet-stream"><img src="" data-expect="data:,a"></picture>
+PASS <picture><source srcset="data:,b" type="application/x-shockwave-flash"><img src="" data-expect="data:,a"></picture>
+PASS <picture><source srcset="data:,b" type="image\gif"><img src="" data-expect="data:,a"></picture>
+PASS <picture><source srcset="data:,b" type="gif"><img src="" data-expect="data:,a"></picture>
+PASS <picture><source srcset="data:,b" type=".gif"><img src="" data-expect="data:,a"></picture>
+PASS <picture><source srcset="data:,b" type="*"><img src="" data-expect="data:,a"></picture>
+PASS <picture><source srcset="data:,b" type="*/*"><img src="" data-expect="data:,a"></picture>
+PASS <picture><source srcset="data:,b" type="image/*"><img src="" data-expect="data:,a"></picture>
+PASS <picture><source srcset="data:,b" type=","><img src="" data-expect="data:,a"></picture>
+PASS <picture><source srcset="data:,b" type="image/gif, image/png"><img src="" data-expect="data:,a"></picture>
+PASS <picture><source srcset="data:,b" type="image/gif image/png"><img src="" data-expect="data:,a"></picture>
+PASS <picture><source srcset="data:,b" type="image/foobarbaz"><img src="" data-expect="data:,a"></picture>
+PASS <picture><img src="" data-expect="data:,a">foo</picture>
+PASS <picture><img src="" data-expect="data:,a"><br></picture>
+PASS <picture><img src="" data-expect="data:,a"><!--foo--></picture>
+PASS <picture><img src="" data-expect="data:,a"><img src=""
+PASS <picture><img data-expect=""><img src=""
+PASS <picture><img src="" data-expect="data:,a"><source srcset="data:,b"></picture>
+PASS <picture><img data-expect=""><source srcset="data:,b"></picture>
+PASS <picture><span><source srcset="data:,b"><img data-expect=""></span></picture>
+PASS <picture><span><source srcset="data:,b"><img src="" data-expect="data:,a"></span></picture>
+PASS <picture><source srcset="data:,b"><span><img src="" data-expect="data:,a"></span></picture>
+PASS <picture><source srcset="data:,b"><img data-expect="data:,b"></picture>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+foo
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+foo
+
+
+
+
+
+
+
+
+
+
Modified: trunk/Source/WTF/ChangeLog (227630 => 227631)
--- trunk/Source/WTF/ChangeLog 2018-01-25 22:27:27 UTC (rev 227630)
+++ trunk/Source/WTF/ChangeLog 2018-01-25 22:29:55 UTC (rev 227631)
@@ -1,3 +1,12 @@
+2018-01-25 Jer Noble <[email protected]>
+
+ Move ImageDecoderAVFObjC from using AVSampleBufferGenerator to AVAssetReaderOutput for parsing
+ https://bugs.webkit.org/show_bug.cgi?id=182091
+
+ Reviewed by Eric Carlson.
+
+ * wtf/Platform.h:
+
2018-01-25 Mark Lam <[email protected]>
Rename the Poisoned::isPoisoned constant to Poisoned::isPoisonedType.
Modified: trunk/Source/WTF/wtf/Platform.h (227630 => 227631)
--- trunk/Source/WTF/wtf/Platform.h 2018-01-25 22:27:27 UTC (rev 227630)
+++ trunk/Source/WTF/wtf/Platform.h 2018-01-25 22:29:55 UTC (rev 227631)
@@ -1166,8 +1166,8 @@
#define USE_INSERTION_UNDO_GROUPING 1
#endif
-#if PLATFORM(MAC)
-#define HAVE_AVSAMPLEBUFFERGENERATOR 1
+#if PLATFORM(MAC) || PLATFORM(IOS)
+#define HAVE_AVASSETREADER 1
#endif
#if PLATFORM(COCOA)
Modified: trunk/Source/WebCore/ChangeLog (227630 => 227631)
--- trunk/Source/WebCore/ChangeLog 2018-01-25 22:27:27 UTC (rev 227630)
+++ trunk/Source/WebCore/ChangeLog 2018-01-25 22:29:55 UTC (rev 227631)
@@ -1,3 +1,54 @@
+2018-01-25 Jer Noble <[email protected]>
+
+ Move ImageDecoderAVFObjC from using AVSampleBufferGenerator to AVAssetReaderOutput for parsing
+ https://bugs.webkit.org/show_bug.cgi?id=182091
+
+ Reviewed by Eric Carlson.
+
+ No new tests; should be covered by existing tests.
+
+ AVSampleBufferGenerator is not available on iOS, so in order to enable ImageDecoderAVFObjC there,
+ we must adopt a similar API which is available both on iOS and macOS: AVAssetReaderOutput. Unlike
+ the generator, AVAssetReaderOutput doesn't necessarily generate samples in decode order, so we'll
+ repurpose the SampleMap from EME to hold the decoded samples as well as their generated images.
+
+ * Modules/mediasource/SampleMap.cpp:
+ * Modules/mediasource/SampleMap.h:
+ (WebCore::SampleMap::size const):
+ * platform/MIMETypeRegistry.cpp:
+ (WebCore::MIMETypeRegistry::isSupportedImageVideoOrSVGMIMEType):
+ * platform/MediaSample.h:
+ (WebCore::MediaSample::hasAlpha const):
+ * platform/graphics/ImageDecoder.cpp:
+ (WebCore::ImageDecoder::create):
+ (WebCore::ImageDecoder::supportsMediaType):
+ * platform/graphics/avfoundation/MediaSampleAVFObjC.h: Make non-final.
+ (WebCore::MediaSampleAVFObjC::sampleBuffer const):
+ (WebCore::MediaSampleAVFObjC::MediaSampleAVFObjC):
+ * platform/graphics/avfoundation/objc/ImageDecoderAVFObjC.h:
+ * platform/graphics/avfoundation/objc/ImageDecoderAVFObjC.mm:
+ (WebCore::ImageDecoderAVFObjCSample::create):
+ (WebCore::ImageDecoderAVFObjCSample::sampleBuffer const):
+ (WebCore::ImageDecoderAVFObjCSample::image const):
+ (WebCore::ImageDecoderAVFObjCSample::setImage):
+ (WebCore::ImageDecoderAVFObjCSample::ImageDecoderAVFObjCSample):
+ (WebCore::ImageDecoderAVFObjCSample::cacheMetadata):
+ (WebCore::toSample):
+ (WebCore::ImageDecoderAVFObjC::readSamples):
+ (WebCore::ImageDecoderAVFObjC::storeSampleBuffer):
+ (WebCore::ImageDecoderAVFObjC::advanceCursor):
+ (WebCore::ImageDecoderAVFObjC::setTrack):
+ (WebCore::ImageDecoderAVFObjC::encodedDataStatus const):
+ (WebCore::ImageDecoderAVFObjC::repetitionCount const):
+ (WebCore::ImageDecoderAVFObjC::frameIsCompleteAtIndex const):
+ (WebCore::ImageDecoderAVFObjC::frameDurationAtIndex const):
+ (WebCore::ImageDecoderAVFObjC::frameHasAlphaAtIndex const):
+ (WebCore::ImageDecoderAVFObjC::createFrameImageAtIndex):
+ (WebCore::ImageDecoderAVFObjC::setData):
+ (WebCore::ImageDecoderAVFObjC::clearFrameBufferCache):
+ (WebCore::ImageDecoderAVFObjC::sampleAtIndex const):
+ (WebCore::ImageDecoderAVFObjC::readSampleMetadata): Deleted.
+
2018-01-25 Youenn Fablet <[email protected]>
DocumentThreadableLoader should ensure service worker is not reused if redirection comes from the network
Modified: trunk/Source/WebCore/Modules/mediasource/SampleMap.cpp (227630 => 227631)
--- trunk/Source/WebCore/Modules/mediasource/SampleMap.cpp 2018-01-25 22:27:27 UTC (rev 227630)
+++ trunk/Source/WebCore/Modules/mediasource/SampleMap.cpp 2018-01-25 22:29:55 UTC (rev 227631)
@@ -26,8 +26,6 @@
#include "config.h"
#include "SampleMap.h"
-#if ENABLE(MEDIA_SOURCE)
-
#include "MediaSample.h"
namespace WebCore {
@@ -310,5 +308,3 @@
}
}
-
-#endif
Modified: trunk/Source/WebCore/Modules/mediasource/SampleMap.h (227630 => 227631)
--- trunk/Source/WebCore/Modules/mediasource/SampleMap.h 2018-01-25 22:27:27 UTC (rev 227630)
+++ trunk/Source/WebCore/Modules/mediasource/SampleMap.h 2018-01-25 22:29:55 UTC (rev 227631)
@@ -25,8 +25,6 @@
#pragma once
-#if ENABLE(MEDIA_SOURCE)
-
#include <map>
#include <wtf/MediaTime.h>
#include <wtf/RefPtr.h>
@@ -45,6 +43,7 @@
typedef MapType::reverse_iterator reverse_iterator;
typedef MapType::const_reverse_iterator const_reverse_iterator;
typedef std::pair<iterator, iterator> iterator_range;
+ typedef MapType::value_type value_type;
iterator begin() { return m_samples.begin(); }
const_iterator begin() const { return m_samples.begin(); }
@@ -79,6 +78,7 @@
typedef MapType::reverse_iterator reverse_iterator;
typedef MapType::const_reverse_iterator const_reverse_iterator;
typedef std::pair<reverse_iterator, reverse_iterator> reverse_iterator_range;
+ typedef MapType::value_type value_type;
iterator begin() { return m_samples.begin(); }
const_iterator begin() const { return m_samples.begin(); }
@@ -107,6 +107,7 @@
SampleMap() = default;
WEBCORE_EXPORT bool empty() const;
+ size_t size() const { return m_decodeOrder.m_samples.size(); }
WEBCORE_EXPORT void clear();
WEBCORE_EXPORT void addSample(MediaSample&);
WEBCORE_EXPORT void removeSample(MediaSample*);
@@ -133,5 +134,3 @@
}
} // namespace WebCore
-
-#endif // ENABLE(MEDIA_SOURCE)
Modified: trunk/Source/WebCore/platform/MIMETypeRegistry.cpp (227630 => 227631)
--- trunk/Source/WebCore/platform/MIMETypeRegistry.cpp 2018-01-25 22:27:27 UTC (rev 227630)
+++ trunk/Source/WebCore/platform/MIMETypeRegistry.cpp 2018-01-25 22:29:55 UTC (rev 227631)
@@ -55,7 +55,7 @@
#include "ArchiveFactory.h"
#endif
-#if HAVE(AVSAMPLEBUFFERGENERATOR)
+#if HAVE(AVASSETREADER)
#include "ContentType.h"
#include "ImageDecoderAVFObjC.h"
#endif
@@ -460,7 +460,7 @@
if (isSupportedImageMIMEType(mimeType) || equalLettersIgnoringASCIICase(mimeType, "image/svg+xml"))
return true;
-#if HAVE(AVSAMPLEBUFFERGENERATOR)
+#if HAVE(AVASSETREADER)
if (ImageDecoderAVFObjC::supportsContentType(ContentType(mimeType)))
return true;
#endif
Modified: trunk/Source/WebCore/platform/MediaSample.h (227630 => 227631)
--- trunk/Source/WebCore/platform/MediaSample.h 2018-01-25 22:27:27 UTC (rev 227630)
+++ trunk/Source/WebCore/platform/MediaSample.h 2018-01-25 22:29:55 UTC (rev 227631)
@@ -79,6 +79,7 @@
None = 0,
IsSync = 1 << 0,
IsNonDisplaying = 1 << 1,
+ HasAlpha = 1 << 2,
};
virtual SampleFlags flags() const = 0;
virtual PlatformSample platformSample() = 0;
@@ -94,6 +95,7 @@
bool isSync() const { return flags() & IsSync; }
bool isNonDisplaying() const { return flags() & IsNonDisplaying; }
+ bool hasAlpha() const { return flags() & HasAlpha; }
virtual void dump(PrintStream&) const = 0;
};
Modified: trunk/Source/WebCore/platform/graphics/ImageDecoder.cpp (227630 => 227631)
--- trunk/Source/WebCore/platform/graphics/ImageDecoder.cpp 2018-01-25 22:27:27 UTC (rev 227630)
+++ trunk/Source/WebCore/platform/graphics/ImageDecoder.cpp 2018-01-25 22:29:55 UTC (rev 227631)
@@ -34,7 +34,7 @@
#include "ScalableImageDecoder.h"
#endif
-#if HAVE(AVSAMPLEBUFFERGENERATOR)
+#if HAVE(AVASSETREADER)
#include "ImageDecoderAVFObjC.h"
#endif
@@ -42,7 +42,7 @@
RefPtr<ImageDecoder> ImageDecoder::create(SharedBuffer& data, const String& mimeType, AlphaOption alphaOption, GammaAndColorProfileOption gammaAndColorProfileOption)
{
-#if HAVE(AVSAMPLEBUFFERGENERATOR)
+#if HAVE(AVASSETREADER)
if (ImageDecoderAVFObjC::canDecodeType(mimeType))
return ImageDecoderAVFObjC::create(data, mimeType, alphaOption, gammaAndColorProfileOption);
#else
@@ -61,7 +61,7 @@
bool ImageDecoder::supportsMediaType(MediaType type)
{
bool supports = false;
-#if HAVE(AVSAMPLEBUFFERGENERATOR)
+#if HAVE(AVASSETREADER)
if (ImageDecoderAVFObjC::supportsMediaType(type))
supports = true;
#endif
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/MediaSampleAVFObjC.h (227630 => 227631)
--- trunk/Source/WebCore/platform/graphics/avfoundation/MediaSampleAVFObjC.h 2018-01-25 22:27:27 UTC (rev 227630)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/MediaSampleAVFObjC.h 2018-01-25 22:29:55 UTC (rev 227631)
@@ -33,7 +33,7 @@
namespace WebCore {
-class MediaSampleAVFObjC final : public MediaSample {
+class MediaSampleAVFObjC : public MediaSample {
public:
static Ref<MediaSampleAVFObjC> create(CMSampleBufferRef sample, int trackID) { return adoptRef(*new MediaSampleAVFObjC(sample, trackID)); }
static Ref<MediaSampleAVFObjC> create(CMSampleBufferRef sample, AtomicString trackID) { return adoptRef(*new MediaSampleAVFObjC(sample, trackID)); }
@@ -41,9 +41,39 @@
static RefPtr<MediaSampleAVFObjC> createImageSample(Ref<JSC::Uint8ClampedArray>&&, unsigned long width, unsigned long height);
static RefPtr<MediaSampleAVFObjC> createImageSample(Vector<uint8_t>&&, unsigned long width, unsigned long height);
- RefPtr<JSC::Uint8ClampedArray> getRGBAImageData() const final;
+ RefPtr<JSC::Uint8ClampedArray> getRGBAImageData() const override;
-private:
+ MediaTime presentationTime() const override;
+ MediaTime outputPresentationTime() const override;
+ MediaTime decodeTime() const override;
+ MediaTime duration() const override;
+ MediaTime outputDuration() const override;
+
+ AtomicString trackID() const override { return m_id; }
+ void setTrackID(const String& id) override { m_id = id; }
+
+ size_t sizeInBytes() const override;
+ FloatSize presentationSize() const override;
+
+ SampleFlags flags() const override;
+ PlatformSample platformSample() override;
+ void dump(PrintStream&) const override;
+ void offsetTimestampsBy(const MediaTime&) override;
+ void setTimestamps(const MediaTime&, const MediaTime&) override;
+ bool isDivisable() const override;
+ std::pair<RefPtr<MediaSample>, RefPtr<MediaSample>> divide(const MediaTime& presentationTime) override;
+ Ref<MediaSample> createNonDisplayingCopy() const override;
+
+ VideoRotation videoRotation() const override { return m_rotation; }
+ bool videoMirrored() const override { return m_mirrored; }
+
+ CMSampleBufferRef sampleBuffer() const { return m_sample.get(); }
+
+protected:
+ MediaSampleAVFObjC(RetainPtr<CMSampleBufferRef>&& sample)
+ : m_sample(WTFMove(sample))
+ {
+ }
MediaSampleAVFObjC(CMSampleBufferRef sample)
: m_sample(sample)
{
@@ -66,31 +96,6 @@
}
virtual ~MediaSampleAVFObjC() = default;
-
- MediaTime presentationTime() const override;
- MediaTime outputPresentationTime() const override;
- MediaTime decodeTime() const override;
- MediaTime duration() const override;
- MediaTime outputDuration() const override;
-
- AtomicString trackID() const override { return m_id; }
- void setTrackID(const String& id) override { m_id = id; }
-
- size_t sizeInBytes() const override;
- FloatSize presentationSize() const override;
-
- SampleFlags flags() const override;
- PlatformSample platformSample() override;
- void dump(PrintStream&) const override;
- void offsetTimestampsBy(const MediaTime&) override;
- void setTimestamps(const MediaTime&, const MediaTime&) override;
- bool isDivisable() const override;
- std::pair<RefPtr<MediaSample>, RefPtr<MediaSample>> divide(const MediaTime& presentationTime) override;
- Ref<MediaSample> createNonDisplayingCopy() const override;
-
- VideoRotation videoRotation() const final { return m_rotation; }
- bool videoMirrored() const final { return m_mirrored; }
-
RetainPtr<CMSampleBufferRef> m_sample;
AtomicString m_id;
VideoRotation m_rotation { VideoRotation::None };
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/ImageDecoderAVFObjC.h (227630 => 227631)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/ImageDecoderAVFObjC.h 2018-01-25 22:27:27 UTC (rev 227630)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/ImageDecoderAVFObjC.h 2018-01-25 22:29:55 UTC (rev 227631)
@@ -25,9 +25,10 @@
#pragma once
-#if HAVE(AVSAMPLEBUFFERGENERATOR)
+#if HAVE(AVASSETREADER)
#include "ImageDecoder.h"
+#include "SampleMap.h"
#include <map>
#include <wtf/Lock.h>
#include <wtf/Vector.h>
@@ -34,8 +35,8 @@
#include <wtf/text/WTFString.h>
OBJC_CLASS AVAssetTrack;
-OBJC_CLASS AVSampleBufferGenerator;
-OBJC_CLASS AVSampleCursor;
+OBJC_CLASS AVAssetReader;
+OBJC_CLASS AVAssetReaderTrackOutput;
OBJC_CLASS AVURLAsset;
OBJC_CLASS WebCoreSharedBufferResourceLoaderDelegate;
typedef struct opaqueCMSampleBuffer* CMSampleBufferRef;
@@ -49,6 +50,7 @@
namespace WebCore {
class ContentType;
+class ImageDecoderAVFObjCSample;
class PixelBufferConformerCV;
class WebCoreDecompressionSession;
@@ -101,26 +103,25 @@
ImageDecoderAVFObjC(SharedBuffer&, const String& mimeType, AlphaOption, GammaAndColorProfileOption);
AVAssetTrack *firstEnabledTrack();
- void readSampleMetadata();
+ void readSamples();
void readTrackMetadata();
bool storeSampleBuffer(CMSampleBufferRef);
void advanceCursor();
void setTrack(AVAssetTrack *);
+ const ImageDecoderAVFObjCSample* sampleAtIndex(size_t) const;
+
String m_mimeType;
String m_uti;
RetainPtr<AVURLAsset> m_asset;
RetainPtr<AVAssetTrack> m_track;
- RetainPtr<AVSampleCursor> m_cursor;
- RetainPtr<AVSampleBufferGenerator> m_generator;
RetainPtr<WebCoreSharedBufferResourceLoaderDelegate> m_loader;
RetainPtr<VTImageRotationSessionRef> m_rotationSession;
RetainPtr<CVPixelBufferPoolRef> m_rotationPool;
Ref<WebCoreDecompressionSession> m_decompressionSession;
- struct SampleData;
- std::map<WTF::MediaTime, size_t> m_presentationTimeToIndex;
- Vector<SampleData> m_sampleData;
+ SampleMap m_sampleData;
+ DecodeOrderSampleMap::iterator m_cursor;
Lock m_sampleGeneratorLock;
bool m_isAllDataReceived { false };
std::optional<IntSize> m_size;
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/ImageDecoderAVFObjC.mm (227630 => 227631)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/ImageDecoderAVFObjC.mm 2018-01-25 22:27:27 UTC (rev 227630)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/ImageDecoderAVFObjC.mm 2018-01-25 22:29:55 UTC (rev 227631)
@@ -26,7 +26,7 @@
#import "config.h"
#import "ImageDecoderAVFObjC.h"
-#if HAVE(AVSAMPLEBUFFERGENERATOR)
+#if HAVE(AVASSETREADER)
#import "AVFoundationMIMETypeCache.h"
#import "AffineTransform.h"
@@ -36,14 +36,15 @@
#import "FloatSize.h"
#import "Logging.h"
#import "MIMETypeRegistry.h"
+#import "MediaSampleAVFObjC.h"
#import "SharedBuffer.h"
#import "UTIUtilities.h"
#import "WebCoreDecompressionSession.h"
#import <AVFoundation/AVAsset.h>
+#import <AVFoundation/AVAssetReader.h>
+#import <AVFoundation/AVAssetReaderOutput.h>
#import <AVFoundation/AVAssetResourceLoader.h>
#import <AVFoundation/AVAssetTrack.h>
-#import <AVFoundation/AVSampleBufferGenerator.h>
-#import <AVFoundation/AVSampleCursor.h>
#import <AVFoundation/AVTime.h>
#import <VideoToolbox/VTUtilities.h>
#import <map>
@@ -56,6 +57,7 @@
#import <wtf/Vector.h>
#import <pal/cf/CoreMediaSoftLink.h>
+#import "CoreVideoSoftLink.h"
#import "VideoToolboxSoftLink.h"
#pragma mark - Soft Linking
@@ -62,8 +64,8 @@
SOFT_LINK_FRAMEWORK_OPTIONAL(AVFoundation)
SOFT_LINK_CLASS_OPTIONAL(AVFoundation, AVURLAsset)
-SOFT_LINK_CLASS_OPTIONAL(AVFoundation, AVSampleBufferGenerator)
-SOFT_LINK_CLASS_OPTIONAL(AVFoundation, AVSampleBufferRequest)
+SOFT_LINK_CLASS_OPTIONAL(AVFoundation, AVAssetReader)
+SOFT_LINK_CLASS_OPTIONAL(AVFoundation, AVAssetReaderTrackOutput)
SOFT_LINK_POINTER_OPTIONAL(AVFoundation, AVMediaCharacteristicVisual, NSString *)
SOFT_LINK_POINTER_OPTIONAL(AVFoundation, AVURLAssetReferenceRestrictionsKey, NSString *)
SOFT_LINK_POINTER_OPTIONAL(AVFoundation, AVURLAssetUsesNoPersistentCacheKey, NSString *)
@@ -267,16 +269,52 @@
return rotation;
}
-struct ImageDecoderAVFObjC::SampleData {
- Seconds duration { 0 };
- bool hasAlpha { false };
- IntSize frameSize;
- RetainPtr<CMSampleBufferRef> sample;
- RetainPtr<CGImageRef> image;
- MediaTime decodeTime;
- MediaTime presentationTime;
+class ImageDecoderAVFObjCSample : public MediaSampleAVFObjC {
+public:
+ static Ref<ImageDecoderAVFObjCSample> create(RetainPtr<CMSampleBufferRef>&& sampleBuffer)
+ {
+ return adoptRef(*new ImageDecoderAVFObjCSample(WTFMove(sampleBuffer)));
+ }
+
+ CGImageRef image() const { return m_image.get(); }
+ void setImage(RetainPtr<CGImageRef>&& image)
+ {
+ m_image = WTFMove(image);
+ if (!m_image) {
+ m_hasAlpha = false;
+ return;
+ }
+
+ auto alphaInfo = CGImageGetAlphaInfo(m_image.get());
+ m_hasAlpha = alphaInfo != kCGImageAlphaNone && alphaInfo != kCGImageAlphaNoneSkipLast && alphaInfo != kCGImageAlphaNoneSkipFirst;
+ }
+
+ SampleFlags flags() const override
+ {
+ return (SampleFlags)(MediaSampleAVFObjC::flags() | (m_hasAlpha ? HasAlpha : 0));
+ }
+
+private:
+ ImageDecoderAVFObjCSample(RetainPtr<CMSampleBufferRef>&& sample)
+ : MediaSampleAVFObjC(WTFMove(sample))
+ {
+ }
+
+ RetainPtr<CGImageRef> m_image;
+ bool m_hasAlpha { false };
};
+static ImageDecoderAVFObjCSample* toSample(PresentationOrderSampleMap::value_type pair)
+{
+ return (ImageDecoderAVFObjCSample*)pair.second.get();
+}
+
+template <typename Iterator>
+ImageDecoderAVFObjCSample* toSample(Iterator iter)
+{
+ return (ImageDecoderAVFObjCSample*)iter->second.get();
+}
+
#pragma mark - ImageDecoderAVFObjC
RefPtr<ImageDecoderAVFObjC> ImageDecoderAVFObjC::create(SharedBuffer& data, const String& mimeType, AlphaOption alphaOption, GammaAndColorProfileOption gammaAndColorProfileOption)
@@ -348,37 +386,24 @@
return [videoTracks objectAtIndex:firstEnabledIndex];
}
-void ImageDecoderAVFObjC::readSampleMetadata()
+void ImageDecoderAVFObjC::readSamples()
{
- if (!m_sampleData.isEmpty())
+ if (!m_sampleData.empty())
return;
- // NOTE: there is no API to return the number of samples in the sample table. Instead,
- // simply increment the sample in decode order by an arbitrarily large number.
- RetainPtr<AVSampleCursor> cursor = [m_track makeSampleCursorAtFirstSampleInDecodeOrder];
- int64_t sampleCount = 0;
- if (cursor)
- sampleCount = 1 + [cursor stepInDecodeOrderByCount:std::numeric_limits<int32_t>::max()];
+ auto assetReader = adoptNS([allocAVAssetReaderInstance() initWithAsset:m_asset.get() error:nil]);
+ auto assetReaderOutput = adoptNS([allocAVAssetReaderTrackOutputInstance() initWithTrack:m_track.get() outputSettings:nil]);
- // NOTE: there is no API to return the first sample cursor in presentation order. Instead,
- // simply decrement sample in presentation order by an arbitrarily large number.
- [cursor stepInPresentationOrderByCount:std::numeric_limits<int32_t>::min()];
+ assetReaderOutput.get().alwaysCopiesSampleData = NO;
+ [assetReader addOutput:assetReaderOutput.get()];
+ [assetReader startReading];
- ASSERT(sampleCount >= 0);
- m_sampleData.resize(static_cast<size_t>(sampleCount));
-
- if (!m_generator)
- m_generator = adoptNS([allocAVSampleBufferGeneratorInstance() initWithAsset:m_asset.get() timebase:nil]);
-
- for (size_t index = 0; index < static_cast<size_t>(sampleCount); ++index) {
- auto& sampleData = m_sampleData[index];
- sampleData.duration = Seconds(PAL::CMTimeGetSeconds([cursor currentSampleDuration]));
- sampleData.decodeTime = PAL::toMediaTime([cursor decodeTimeStamp]);
- sampleData.presentationTime = PAL::toMediaTime([cursor presentationTimeStamp]);
- auto request = adoptNS([allocAVSampleBufferRequestInstance() initWithStartCursor:cursor.get()]);
- sampleData.sample = adoptCF([m_generator createSampleBufferForRequest:request.get()]);
- m_presentationTimeToIndex.insert(std::make_pair(sampleData.presentationTime, index));
- [cursor stepInPresentationOrderByCount:1];
+ while (auto sampleBuffer = adoptCF([assetReaderOutput copyNextSampleBuffer])) {
+ // NOTE: Some samples emitted by the AVAssetReader simply denote the boundary of edits
+ // and do not carry media data.
+ if (!(PAL::CMSampleBufferGetNumSamples(sampleBuffer.get())))
+ continue;
+ m_sampleData.addSample(ImageDecoderAVFObjCSample::create(WTFMove(sampleBuffer)).get());
}
}
@@ -406,7 +431,7 @@
}
auto presentationTime = PAL::toMediaTime(PAL::CMSampleBufferGetPresentationTimeStamp(sampleBuffer));
- auto indexIter = m_presentationTimeToIndex.find(presentationTime);
+ auto iter = m_sampleData.presentationOrder().findSampleWithPresentationTime(presentationTime);
if (m_rotation && !m_rotation.value().isIdentity()) {
auto& rotation = m_rotation.value();
@@ -447,21 +472,16 @@
return false;
}
- ASSERT(indexIter->second < m_sampleData.size());
- auto& sampleData = m_sampleData[indexIter->second];
- sampleData.image = adoptCF(rawImage);
- sampleData.sample = nullptr;
+ ASSERT(iter != m_sampleData.presentationOrder().end());
+ toSample(iter)->setImage(adoptCF(rawImage));
- auto alphaInfo = CGImageGetAlphaInfo(rawImage);
- sampleData.hasAlpha = (alphaInfo != kCGImageAlphaNone && alphaInfo != kCGImageAlphaNoneSkipLast && alphaInfo != kCGImageAlphaNoneSkipFirst);
-
return true;
}
void ImageDecoderAVFObjC::advanceCursor()
{
- if (![m_cursor stepInDecodeOrderByCount:1])
- m_cursor = [m_track makeSampleCursorAtFirstSampleInDecodeOrder];
+ if (m_cursor == m_sampleData.decodeOrder().end() || ++m_cursor == m_sampleData.decodeOrder().end())
+ m_cursor = m_sampleData.decodeOrder().begin();
}
void ImageDecoderAVFObjC::setTrack(AVAssetTrack *track)
@@ -474,14 +494,13 @@
m_sampleData.clear();
m_size.reset();
m_rotation.reset();
- m_cursor = nullptr;
- m_generator = nullptr;
+ m_cursor = m_sampleData.decodeOrder().end();
m_rotationSession = nullptr;
[track loadValuesAsynchronouslyForKeys:@[@"naturalSize", @"preferredTransform"] completionHandler:[protectedThis = makeRefPtr(this)] () mutable {
callOnMainThread([protectedThis = WTFMove(protectedThis)] {
protectedThis->readTrackMetadata();
- protectedThis->readSampleMetadata();
+ protectedThis->readSamples();
});
}];
}
@@ -488,7 +507,7 @@
EncodedDataStatus ImageDecoderAVFObjC::encodedDataStatus() const
{
- if (m_sampleData.isEmpty())
+ if (m_sampleData.empty())
return EncodedDataStatus::Unknown;
return EncodedDataStatus::Complete;
}
@@ -510,7 +529,7 @@
// In the absence of instructions to the contrary, assume all media formats repeat infinitely.
// FIXME: Future media formats may embed repeat count information, and when that is available
// through AVAsset, account for it here.
- return RepetitionCountInfinite;
+ return frameCount() > 1 ? RepetitionCountInfinite : RepetitionCountNone;
}
String ImageDecoderAVFObjC::uti() const
@@ -530,14 +549,11 @@
bool ImageDecoderAVFObjC::frameIsCompleteAtIndex(size_t index) const
{
- if (index >= m_sampleData.size())
+ auto* sampleData = sampleAtIndex(index);
+ if (!sampleData)
return false;
- auto sampleData = m_sampleData[index];
- if (!sampleData.sample)
- return false;
-
- return PAL::CMSampleBufferDataIsReady(sampleData.sample.get());
+ return PAL::CMSampleBufferDataIsReady(sampleData->sampleBuffer());
}
ImageOrientation ImageDecoderAVFObjC::frameOrientationAtIndex(size_t) const
@@ -547,16 +563,17 @@
Seconds ImageDecoderAVFObjC::frameDurationAtIndex(size_t index) const
{
- if (index < m_sampleData.size())
- return m_sampleData[index].duration;
- return { };
+ auto* sampleData = sampleAtIndex(index);
+ if (!sampleData)
+ return { };
+
+ return Seconds(sampleData->duration().toDouble());
}
bool ImageDecoderAVFObjC::frameHasAlphaAtIndex(size_t index) const
{
- if (index < m_sampleData.size())
- return m_sampleData[index].hasAlpha;
- return false;
+ auto* sampleData = sampleAtIndex(index);
+ return sampleData ? sampleData->hasAlpha() : false;
}
bool ImageDecoderAVFObjC::frameAllowSubsamplingAtIndex(size_t index) const
@@ -577,57 +594,42 @@
{
LockHolder holder { m_sampleGeneratorLock };
- if (index >= m_sampleData.size())
+ auto* sampleData = sampleAtIndex(index);
+ if (!sampleData)
return nullptr;
- auto& sampleData = m_sampleData[index];
- if (sampleData.image)
- return sampleData.image;
+ if (auto image = sampleData->image())
+ return image;
- if (!m_cursor)
- m_cursor = [m_track makeSampleCursorAtFirstSampleInDecodeOrder];
+ if (m_cursor == m_sampleData.decodeOrder().end())
+ m_cursor = m_sampleData.decodeOrder().begin();
- auto frameCursor = [m_track makeSampleCursorWithPresentationTimeStamp:PAL::toCMTime(sampleData.presentationTime)];
- if ([frameCursor comparePositionInDecodeOrderWithPositionOfCursor:m_cursor.get()] == NSOrderedAscending) {
+ auto decodeTime = sampleData->decodeTime();
+
+ if (decodeTime < m_cursor->second->decodeTime()) {
// Rewind cursor to the last sync sample to begin decoding
- m_cursor = adoptNS([frameCursor copy]);
+ m_cursor = m_sampleData.decodeOrder().findSampleWithDecodeKey({decodeTime, sampleData->presentationTime()});
do {
- if ([m_cursor currentSampleSyncInfo].sampleIsFullSync)
+ if (m_cursor->second->isSync())
break;
- } while ([m_cursor stepInDecodeOrderByCount:-1] == -1);
-
+ } while (--m_cursor != m_sampleData.decodeOrder().begin());
}
- if (!m_generator)
- m_generator = adoptNS([allocAVSampleBufferGeneratorInstance() initWithAsset:m_asset.get() timebase:nil]);
-
RetainPtr<CGImageRef> image;
while (true) {
- if ([frameCursor comparePositionInDecodeOrderWithPositionOfCursor:m_cursor.get()] == NSOrderedAscending)
+ if (decodeTime < m_cursor->second->decodeTime())
return nullptr;
- auto presentationTime = PAL::toMediaTime(m_cursor.get().presentationTimeStamp);
- auto indexIter = m_presentationTimeToIndex.find(presentationTime);
-
- if (indexIter == m_presentationTimeToIndex.end())
+ auto cursorSample = toSample(m_cursor)->sampleBuffer();
+ if (!cursorSample)
break;
- auto& cursorSampleData = m_sampleData[indexIter->second];
-
- if (!cursorSampleData.sample) {
- auto request = adoptNS([allocAVSampleBufferRequestInstance() initWithStartCursor:m_cursor.get()]);
- cursorSampleData.sample = adoptCF([m_generator createSampleBufferForRequest:request.get()]);
- }
-
- if (!cursorSampleData.sample)
+ if (!storeSampleBuffer(cursorSample))
break;
- if (!storeSampleBuffer(cursorSampleData.sample.get()))
- break;
-
advanceCursor();
- if (sampleData.image)
- return sampleData.image;
+ if (auto image = sampleData->image())
+ return image;
}
advanceCursor();
@@ -649,17 +651,39 @@
if (!m_track)
setTrack(firstEnabledTrack());
+ if (!m_track)
+ return;
+
readTrackMetadata();
- readSampleMetadata();
+ readSamples();
}
}
void ImageDecoderAVFObjC::clearFrameBufferCache(size_t index)
{
- for (size_t i = 0; i < index; ++i)
- m_sampleData[i].image = nullptr;
+ size_t i = 0;
+ for (auto& samplePair : m_sampleData.presentationOrder()) {
+ toSample(samplePair)->setImage(nullptr);
+ if (++i > index)
+ break;
+ }
}
+const ImageDecoderAVFObjCSample* ImageDecoderAVFObjC::sampleAtIndex(size_t index) const
+{
+ if (index >= m_sampleData.size())
+ return nullptr;
+
+ // FIXME: std::map is not random-accessible; this can get expensive if callers repeatedly call
+ // with monotonically increasing indexes. Investigate adding an O(1) side structure to make this
+ // style of access faster.
+ auto iter = m_sampleData.presentationOrder().begin();
+ for (size_t i = 0; i != index; ++i)
+ ++iter;
+
+ return toSample(iter);
}
+}
+
#endif