Skip to content

Commit

Permalink
Modify YUV codecs to match Skia's API change
Browse files Browse the repository at this point in the history
This includes a manual roll to:
4984c3c95f18eda44492a2126c9958e447f2cca8

The Skia change is here:
https://codereview.chromium.org/1716523002/

This should also save a few rows of memory
per image.

BUG=

Review URL: https://codereview.chromium.org/1719533002

Cr-Commit-Position: refs/heads/master@{#380432}
  • Loading branch information
mattsarett authored and Commit bot committed Mar 10, 2016
1 parent 79aba5a commit 2782f0d
Show file tree
Hide file tree
Showing 14 changed files with 180 additions and 126 deletions.
2 changes: 1 addition & 1 deletion DEPS
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ vars = {
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling Skia
# and whatever else without interference from each other.
'skia_revision': '0d996868c3dd5af2ccb6fced488edb335185c107',
'skia_revision': '4984c3c95f18eda44492a2126c9958e447f2cca8',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling V8
# and whatever else without interference from each other.
Expand Down
11 changes: 7 additions & 4 deletions blimp/client/feature/compositor/decoding_image_generator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,13 @@ bool DecodingImageGenerator::onGetPixels(const SkImageInfo& info,
return true;
}

bool DecodingImageGenerator::onGetYUV8Planes(SkISize sizes[3],
void* planes[3],
size_t rowBytes[3],
SkYUVColorSpace*) {
bool DecodingImageGenerator::onQueryYUV8(SkYUVSizeInfo* sizeInfo,
SkYUVColorSpace* colorSpace) const {
return false;
}

bool DecodingImageGenerator::onGetYUV8Planes(const SkYUVSizeInfo& sizeInfo,
void* planes[3]) {
return false;
}

Expand Down
9 changes: 5 additions & 4 deletions blimp/client/feature/compositor/decoding_image_generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,11 @@ class DecodingImageGenerator : public SkImageGenerator {
SkPMColor table[],
int* tableCount) override;

bool onGetYUV8Planes(SkISize sizes[3],
void* planes[3],
size_t rowBytes[3],
SkYUVColorSpace*) override;
bool onQueryYUV8(SkYUVSizeInfo* sizeInfo,
SkYUVColorSpace* colorSpace) const override;

bool onGetYUV8Planes(const SkYUVSizeInfo&,
void* planes[3]) override;

private:
SkBitmap decoded_bitmap_;
Expand Down
97 changes: 55 additions & 42 deletions media/renderers/skcanvas_video_renderer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -227,10 +227,8 @@ class VideoImageGenerator : public SkImageGenerator {
return true;
}

bool onGetYUV8Planes(SkISize sizes[3],
void* planes[3],
size_t row_bytes[3],
SkYUVColorSpace* color_space) override {
bool onQueryYUV8(SkYUVSizeInfo* sizeInfo,
SkYUVColorSpace* color_space) const override {
if (!media::IsYuvPlanar(frame_->format()) ||
// TODO(rileya): Skia currently doesn't support YUVA conversion. Remove
// this case once it does. As-is we will fall back on the pure-software
Expand All @@ -250,46 +248,61 @@ class VideoImageGenerator : public SkImageGenerator {

for (int plane = VideoFrame::kYPlane; plane <= VideoFrame::kVPlane;
++plane) {
if (sizes) {
const gfx::Size size =
VideoFrame::PlaneSize(frame_->format(), plane,
gfx::Size(frame_->visible_rect().width(),
frame_->visible_rect().height()));
sizes[plane].set(size.width(), size.height());
const gfx::Size size = VideoFrame::PlaneSize(
frame_->format(), plane, gfx::Size(frame_->visible_rect().width(),
frame_->visible_rect().height()));
sizeInfo->fSizes[plane].set(size.width(), size.height());
sizeInfo->fWidthBytes[plane] = size.width();
}

return true;
}

bool onGetYUV8Planes(const SkYUVSizeInfo& sizeInfo,
void* planes[3]) override {
media::VideoPixelFormat format = frame_->format();
DCHECK(media::IsYuvPlanar(format) && format != PIXEL_FORMAT_YV12A);

for (int plane = VideoFrame::kYPlane; plane <= VideoFrame::kVPlane;
++plane) {
const gfx::Size size = VideoFrame::PlaneSize(
frame_->format(), plane, gfx::Size(frame_->visible_rect().width(),
frame_->visible_rect().height()));
if (size.width() != sizeInfo.fSizes[plane].width() ||
size.height() != sizeInfo.fSizes[plane].height()) {
return false;
}

size_t offset;
const int y_shift =
(frame_->format() == media::PIXEL_FORMAT_YV16) ? 0 : 1;
if (plane == VideoFrame::kYPlane) {
offset =
(frame_->stride(VideoFrame::kYPlane) * frame_->visible_rect().y()) +
frame_->visible_rect().x();
} else {
offset = (frame_->stride(VideoFrame::kUPlane) *
(frame_->visible_rect().y() >> y_shift)) +
(frame_->visible_rect().x() >> 1);
}
if (row_bytes && planes) {
size_t offset;
const int y_shift =
(frame_->format() == media::PIXEL_FORMAT_YV16) ? 0 : 1;
if (plane == VideoFrame::kYPlane) {
offset = (frame_->stride(VideoFrame::kYPlane) *
frame_->visible_rect().y()) +
frame_->visible_rect().x();
} else {
offset = (frame_->stride(VideoFrame::kUPlane) *
(frame_->visible_rect().y() >> y_shift)) +
(frame_->visible_rect().x() >> 1);
}

// Copy the frame to the supplied memory.
// TODO: Find a way (API change?) to avoid this copy.
char* out_line = static_cast<char*>(planes[plane]);
int out_line_stride = row_bytes[plane];
uint8_t* in_line = frame_->data(plane) + offset;
int in_line_stride = frame_->stride(plane);
int plane_height = sizes[plane].height();
if (in_line_stride == out_line_stride) {
memcpy(out_line, in_line, plane_height * in_line_stride);
} else {
// Different line padding so need to copy one line at a time.
int bytes_to_copy_per_line = out_line_stride < in_line_stride
? out_line_stride
: in_line_stride;
for (int line_no = 0; line_no < plane_height; line_no++) {
memcpy(out_line, in_line, bytes_to_copy_per_line);
in_line += in_line_stride;
out_line += out_line_stride;
}
// Copy the frame to the supplied memory.
// TODO: Find a way (API change?) to avoid this copy.
char* out_line = static_cast<char*>(planes[plane]);
int out_line_stride = sizeInfo.fWidthBytes[plane];
uint8_t* in_line = frame_->data(plane) + offset;
int in_line_stride = frame_->stride(plane);
int plane_height = sizeInfo.fSizes[plane].height();
if (in_line_stride == out_line_stride) {
memcpy(out_line, in_line, plane_height * in_line_stride);
} else {
// Different line padding so need to copy one line at a time.
int bytes_to_copy_per_line =
out_line_stride < in_line_stride ? out_line_stride : in_line_stride;
for (int line_no = 0; line_no < plane_height; line_no++) {
memcpy(out_line, in_line, bytes_to_copy_per_line);
in_line += in_line_stride;
out_line += out_line_stride;
}
}
}
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -75,23 +75,27 @@ bool DecodingImageGenerator::onGetPixels(const SkImageInfo& info, void* pixels,
return decoded;
}

bool DecodingImageGenerator::onGetYUV8Planes(SkISize sizes[3], void* planes[3], size_t rowBytes[3], SkYUVColorSpace* colorSpace)
bool DecodingImageGenerator::onQueryYUV8(SkYUVSizeInfo* sizeInfo, SkYUVColorSpace* colorSpace) const
{
if (!m_canYUVDecode)
return false;

bool requestingYUVSizes = !planes || !planes[0];

TRACE_EVENT1("blink", "DecodingImageGenerator::getYUV8Planes", requestingYUVSizes ? "sizes" : "frame index", static_cast<int>(m_frameIndex));

if (requestingYUVSizes)
return m_frameGenerator->getYUVComponentSizes(sizes);
TRACE_EVENT1("blink", "DecodingImageGenerator::queryYUV8", "sizes", static_cast<int>(m_frameIndex));

if (colorSpace)
*colorSpace = kJPEG_SkYUVColorSpace;

return m_frameGenerator->getYUVComponentSizes(sizeInfo);
}

bool DecodingImageGenerator::onGetYUV8Planes(const SkYUVSizeInfo& sizeInfo, void* planes[3])
{
ASSERT(m_canYUVDecode);

TRACE_EVENT1("blink", "DecodingImageGenerator::getYUV8Planes", "frame index", static_cast<int>(m_frameIndex));

PlatformInstrumentation::willDecodeLazyPixelRef(m_generationId);
bool decoded = m_frameGenerator->decodeToYUV(m_frameIndex, sizes, planes, rowBytes);
bool decoded = m_frameGenerator->decodeToYUV(m_frameIndex, sizeInfo.fSizes, planes, sizeInfo.fWidthBytes);
PlatformInstrumentation::didDecodeLazyPixelRef();

return decoded;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ class PLATFORM_EXPORT DecodingImageGenerator final : public SkImageGenerator {

bool onGetPixels(const SkImageInfo&, void* pixels, size_t rowBytes, SkPMColor table[], int* tableCount) override;

bool onGetYUV8Planes(SkISize sizes[3], void* planes[3], size_t rowBytes[3], SkYUVColorSpace*) override;
bool onQueryYUV8(SkYUVSizeInfo*, SkYUVColorSpace*) const override;

bool onGetYUV8Planes(const SkYUVSizeInfo&, void* planes[3]) override;

private:
RefPtr<ImageFrameGenerator> m_frameGenerator;
Expand Down
21 changes: 11 additions & 10 deletions third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,17 +84,20 @@ class ImageFrameGenerator::ExternalMemoryAllocator final : public SkBitmap::Allo
size_t m_rowBytes;
};

static bool updateYUVComponentSizes(ImageDecoder* decoder, SkISize componentSizes[3], ImageDecoder::SizeType sizeType)
static bool updateYUVComponentSizes(ImageDecoder* decoder, SkISize componentSizes[3], size_t componentWidthBytes[3])
{
if (!decoder->canDecodeToYUV())
return false;

IntSize size = decoder->decodedYUVSize(0, sizeType);
IntSize size = decoder->decodedYUVSize(0);
componentSizes[0].set(size.width(), size.height());
size = decoder->decodedYUVSize(1, sizeType);
componentWidthBytes[0] = decoder->decodedYUVWidthBytes(0);
size = decoder->decodedYUVSize(1);
componentSizes[1].set(size.width(), size.height());
size = decoder->decodedYUVSize(2, sizeType);
componentWidthBytes[1] = decoder->decodedYUVWidthBytes(1);
size = decoder->decodedYUVSize(2);
componentSizes[2].set(size.width(), size.height());
componentWidthBytes[2] = decoder->decodedYUVWidthBytes(2);
return true;
}

Expand Down Expand Up @@ -206,7 +209,7 @@ bool ImageFrameGenerator::decodeAndScale(size_t index, const SkImageInfo& info,
return true;
}

bool ImageFrameGenerator::decodeToYUV(size_t index, SkISize componentSizes[3], void* planes[3], size_t rowBytes[3])
bool ImageFrameGenerator::decodeToYUV(size_t index, const SkISize componentSizes[3], void* planes[3], const size_t rowBytes[3])
{
// Prevent concurrent decode or scale operations on the same image data.
MutexLocker lock(m_decodeMutex);
Expand Down Expand Up @@ -237,8 +240,7 @@ bool ImageFrameGenerator::decodeToYUV(size_t index, SkISize componentSizes[3], v
OwnPtr<ImagePlanes> imagePlanes = adoptPtr(new ImagePlanes(planes, rowBytes));
decoder->setImagePlanes(imagePlanes.release());

bool sizeUpdated = updateYUVComponentSizes(decoder.get(), componentSizes, ImageDecoder::ActualSize);
RELEASE_ASSERT(sizeUpdated);
ASSERT(decoder->canDecodeToYUV());

if (decoder->decodeToYUV()) {
setHasAlpha(0, false); // YUV is always opaque
Expand Down Expand Up @@ -389,7 +391,7 @@ bool ImageFrameGenerator::hasAlpha(size_t index)
return true;
}

bool ImageFrameGenerator::getYUVComponentSizes(SkISize componentSizes[3])
bool ImageFrameGenerator::getYUVComponentSizes(SkYUVSizeInfo* sizeInfo)
{
TRACE_EVENT2("blink", "ImageFrameGenerator::getYUVComponentSizes", "width", m_fullSize.width(), "height", m_fullSize.height());

Expand All @@ -410,8 +412,7 @@ bool ImageFrameGenerator::getYUVComponentSizes(SkISize componentSizes[3])
OwnPtr<ImagePlanes> dummyImagePlanes = adoptPtr(new ImagePlanes);
decoder->setImagePlanes(dummyImagePlanes.release());

ASSERT(componentSizes);
return updateYUVComponentSizes(decoder.get(), componentSizes, ImageDecoder::SizeForMemoryAllocation);
return updateYUVComponentSizes(decoder.get(), sizeInfo->fSizes, sizeInfo->fWidthBytes);
}

} // namespace blink
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkSize.h"
#include "third_party/skia/include/core/SkTypes.h"
#include "third_party/skia/include/core/SkYUVSizeInfo.h"
#include "wtf/Allocator.h"
#include "wtf/Noncopyable.h"
#include "wtf/PassOwnPtr.h"
Expand Down Expand Up @@ -80,7 +81,7 @@ class PLATFORM_EXPORT ImageFrameGenerator final : public ThreadSafeRefCounted<Im
bool decodeAndScale(size_t index, const SkImageInfo&, void* pixels, size_t rowBytes);

// Decodes YUV components directly into the provided memory planes.
bool decodeToYUV(size_t index, SkISize componentSizes[3], void* planes[3], size_t rowBytes[3]);
bool decodeToYUV(size_t index, const SkISize componentSizes[3], void* planes[3], const size_t rowBytes[3]);

const SkISize& getFullSize() const { return m_fullSize; }

Expand All @@ -89,7 +90,7 @@ class PLATFORM_EXPORT ImageFrameGenerator final : public ThreadSafeRefCounted<Im

bool hasAlpha(size_t index);

bool getYUVComponentSizes(SkISize componentSizes[3]);
bool getYUVComponentSizes(SkYUVSizeInfo*);

private:
ImageFrameGenerator(const SkISize& fullSize, PassRefPtr<SharedBuffer>, bool allDataReceived, bool isMultiFrame);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ ImagePlanes::ImagePlanes()
}
}

ImagePlanes::ImagePlanes(void* planes[3], size_t rowBytes[3])
ImagePlanes::ImagePlanes(void* planes[3], const size_t rowBytes[3])
{
for (int i = 0; i < 3; ++i) {
m_planes[i] = planes[i];
Expand Down
22 changes: 16 additions & 6 deletions third_party/WebKit/Source/platform/image-decoders/ImageDecoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class PLATFORM_EXPORT ImagePlanes final {
WTF_MAKE_NONCOPYABLE(ImagePlanes);
public:
ImagePlanes();
ImagePlanes(void* planes[3], size_t rowBytes[3]);
ImagePlanes(void* planes[3], const size_t rowBytes[3]);

void* plane(int);
size_t rowBytes(int) const;
Expand All @@ -71,8 +71,6 @@ class PLATFORM_EXPORT ImagePlanes final {
class PLATFORM_EXPORT ImageDecoder {
WTF_MAKE_NONCOPYABLE(ImageDecoder); USING_FAST_MALLOC(ImageDecoder);
public:
enum SizeType { ActualSize, SizeForMemoryAllocation };

static const size_t noDecodedImageByteLimit = Platform::noDecodedImageByteLimit;

enum AlphaOption {
Expand Down Expand Up @@ -136,9 +134,21 @@ class PLATFORM_EXPORT ImageDecoder {
// return the actual decoded size.
virtual IntSize decodedSize() const { return size(); }

// Decoders which support YUV decoding can override this to
// give potentially different sizes per component.
virtual IntSize decodedYUVSize(int component, SizeType) const { return decodedSize(); }
// Image decoders that support YUV decoding must override this to
// provide the size of each component.
virtual IntSize decodedYUVSize(int component) const
{
ASSERT(false);
return IntSize();
}

// Image decoders that support YUV decoding must override this to
// return the width of each row of the memory allocation.
virtual size_t decodedYUVWidthBytes(int component) const
{
ASSERT(false);
return 0;
}

// This will only differ from size() for ICO (where each frame is a
// different icon) or other formats where different frames are different
Expand Down
Loading

0 comments on commit 2782f0d

Please sign in to comment.