From 2782f0dd0af04e1bdc226938298d8a6957523f3a Mon Sep 17 00:00:00 2001 From: msarett Date: Thu, 10 Mar 2016 10:17:40 -0800 Subject: [PATCH] Modify YUV codecs to match Skia's API change 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} --- DEPS | 2 +- .../compositor/decoding_image_generator.cc | 11 +- .../compositor/decoding_image_generator.h | 9 +- media/renderers/skcanvas_video_renderer.cc | 97 ++++++++++-------- .../images/resources/cropped_mandrill.jpg | Bin 0 -> 23220 bytes .../graphics/DecodingImageGenerator.cpp | 20 ++-- .../graphics/DecodingImageGenerator.h | 4 +- .../platform/graphics/ImageFrameGenerator.cpp | 21 ++-- .../platform/graphics/ImageFrameGenerator.h | 5 +- .../platform/image-decoders/ImageDecoder.cpp | 2 +- .../platform/image-decoders/ImageDecoder.h | 22 ++-- .../image-decoders/jpeg/JPEGImageDecoder.cpp | 74 ++++++------- .../image-decoders/jpeg/JPEGImageDecoder.h | 3 +- .../jpeg/JPEGImageDecoderTest.cpp | 36 ++++++- 14 files changed, 180 insertions(+), 126 deletions(-) create mode 100644 third_party/WebKit/LayoutTests/fast/images/resources/cropped_mandrill.jpg diff --git a/DEPS b/DEPS index 225131937e9076..77c21835ec48f3 100644 --- a/DEPS +++ b/DEPS @@ -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. diff --git a/blimp/client/feature/compositor/decoding_image_generator.cc b/blimp/client/feature/compositor/decoding_image_generator.cc index b2239c538ddd5a..692dd373c4df15 100644 --- a/blimp/client/feature/compositor/decoding_image_generator.cc +++ b/blimp/client/feature/compositor/decoding_image_generator.cc @@ -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; } diff --git a/blimp/client/feature/compositor/decoding_image_generator.h b/blimp/client/feature/compositor/decoding_image_generator.h index 1062cb85b236a1..3a3d2dea6113b8 100644 --- a/blimp/client/feature/compositor/decoding_image_generator.h +++ b/blimp/client/feature/compositor/decoding_image_generator.h @@ -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_; diff --git a/media/renderers/skcanvas_video_renderer.cc b/media/renderers/skcanvas_video_renderer.cc index d84f1529669225..0f51d55f976b24 100644 --- a/media/renderers/skcanvas_video_renderer.cc +++ b/media/renderers/skcanvas_video_renderer.cc @@ -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 @@ -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(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(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; } } } diff --git a/third_party/WebKit/LayoutTests/fast/images/resources/cropped_mandrill.jpg b/third_party/WebKit/LayoutTests/fast/images/resources/cropped_mandrill.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e1a233ad35e42a6bd8bb584a23c6dc29651ad2fb GIT binary patch literal 23220 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 - - if (requestingYUVSizes) - return m_frameGenerator->getYUVComponentSizes(sizes); + TRACE_EVENT1("blink", "DecodingImageGenerator::queryYUV8", "sizes", static_cast(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(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; diff --git a/third_party/WebKit/Source/platform/graphics/DecodingImageGenerator.h b/third_party/WebKit/Source/platform/graphics/DecodingImageGenerator.h index 64e08953cd90d2..65407af3f2df52 100644 --- a/third_party/WebKit/Source/platform/graphics/DecodingImageGenerator.h +++ b/third_party/WebKit/Source/platform/graphics/DecodingImageGenerator.h @@ -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 m_frameGenerator; diff --git a/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp b/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp index edb8bf46bced15..4800a3141ac197 100644 --- a/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp +++ b/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp @@ -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; } @@ -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); @@ -237,8 +240,7 @@ bool ImageFrameGenerator::decodeToYUV(size_t index, SkISize componentSizes[3], v OwnPtr 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 @@ -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()); @@ -410,8 +412,7 @@ bool ImageFrameGenerator::getYUVComponentSizes(SkISize componentSizes[3]) OwnPtr 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 diff --git a/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.h b/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.h index 71553cb4d5296b..bd52b9b87c5c47 100644 --- a/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.h +++ b/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.h @@ -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" @@ -80,7 +81,7 @@ class PLATFORM_EXPORT ImageFrameGenerator final : public ThreadSafeRefCounted, bool allDataReceived, bool isMultiFrame); diff --git a/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.cpp b/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.cpp index 75d70edf9113ec..dc92826df7f3ef 100644 --- a/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.cpp +++ b/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.cpp @@ -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]; diff --git a/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.h b/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.h index 2ebd7797caf998..518499f4cffb1b 100644 --- a/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.h +++ b/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.h @@ -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; @@ -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 { @@ -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 diff --git a/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp b/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp index a423aabab93b2c..11593f1b8b4c1d 100644 --- a/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp +++ b/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp @@ -233,14 +233,16 @@ static void readColorProfile(jpeg_decompress_struct* info, ColorProfile& colorPr } #endif -static IntSize computeYUVSize(const jpeg_decompress_struct* info, int component, ImageDecoder::SizeType sizeType) +static IntSize computeYUVSize(const jpeg_decompress_struct* info, int component) { - if (sizeType == ImageDecoder::SizeForMemoryAllocation) { - return IntSize(info->cur_comp_info[component]->width_in_blocks * DCTSIZE, info->cur_comp_info[component]->height_in_blocks * DCTSIZE); - } return IntSize(info->cur_comp_info[component]->downsampled_width, info->cur_comp_info[component]->downsampled_height); } +static size_t computeYUVWidthBytes(const jpeg_decompress_struct* info, int component) +{ + return info->cur_comp_info[component]->width_in_blocks * DCTSIZE; +} + static yuv_subsampling yuvSubsampling(const jpeg_decompress_struct& info) { if ((DCTSIZE == 8) @@ -494,7 +496,7 @@ class JPEGImageReader final { if (overrideColorSpace == JCS_YCbCr) { m_info.out_color_space = JCS_YCbCr; m_info.raw_data_out = TRUE; - m_uvSize = computeYUVSize(&m_info, 1, ImageDecoder::SizeForMemoryAllocation); // U size and V size have to be the same if we got here + m_uvSize = computeYUVSize(&m_info, 1); // U size and V size have to be the same if we got here } // Don't allocate a giant and superfluous memory buffer when the @@ -674,14 +676,18 @@ class JPEGImageReader final { if (turboSwizzled(m_info.out_color_space)) return nullptr; #endif - int width; - if (m_info.out_color_space == JCS_YCbCr) - width = computeYUVSize(&m_info, 0, ImageDecoder::SizeForMemoryAllocation).width(); - else - width = m_info.output_width; - - return (*m_info.mem->alloc_sarray)(reinterpret_cast_ptr(&m_info), JPOOL_IMAGE, width * 4, 1); + if (m_info.out_color_space != JCS_YCbCr) + return (*m_info.mem->alloc_sarray)(reinterpret_cast_ptr(&m_info), JPOOL_IMAGE, 4 * m_info.output_width, 1); + + // Compute the width of the Y plane in bytes. This may be larger than the output + // width, since the jpeg library requires that the allocated width be a multiple of + // DCTSIZE. Note that this buffer will be used as garbage memory for rows that + // extend below the actual height of the image. We can reuse the same memory for + // the U and V planes, since we are guaranteed that the Y plane width is at least + // as large as the U and V plane widths. + int widthBytes = computeYUVWidthBytes(&m_info, 0); + return (*m_info.mem->alloc_sarray)(reinterpret_cast_ptr(&m_info), JPOOL_IMAGE, widthBytes, 1); } void updateRestartPosition() @@ -802,13 +808,22 @@ void JPEGImageDecoder::setDecodedSize(unsigned width, unsigned height) m_decodedSize = IntSize(width, height); } -IntSize JPEGImageDecoder::decodedYUVSize(int component, ImageDecoder::SizeType sizeType) const +IntSize JPEGImageDecoder::decodedYUVSize(int component) const +{ + ASSERT((component >= 0) && (component <= 2) && m_reader); + const jpeg_decompress_struct* info = m_reader->info(); + + ASSERT(info->out_color_space == JCS_YCbCr); + return computeYUVSize(info, component); +} + +size_t JPEGImageDecoder::decodedYUVWidthBytes(int component) const { ASSERT((component >= 0) && (component <= 2) && m_reader); const jpeg_decompress_struct* info = m_reader->info(); ASSERT(info->out_color_space == JCS_YCbCr); - return computeYUVSize(info, component, sizeType); + return computeYUVWidthBytes(info, component); } unsigned JPEGImageDecoder::desiredScaleNumerator() const @@ -913,12 +928,10 @@ static bool outputRawData(JPEGImageReader* reader, ImagePlanes* imagePlanes) bufferraw[0] = &bufferraw2[0]; // Y channel rows (8 or 16) bufferraw[1] = &bufferraw2[16]; // U channel rows (8) bufferraw[2] = &bufferraw2[24]; // V channel rows (8) - int yWidth = info->output_width; int yHeight = info->output_height; - int yMaxH = yHeight - 1; int v = info->cur_comp_info[0]->v_samp_factor; IntSize uvSize = reader->uvSize(); - int uvMaxH = uvSize.height() - 1; + int uvHeight = uvSize.height(); JSAMPROW outputY = static_cast(imagePlanes->plane(0)); JSAMPROW outputU = static_cast(imagePlanes->plane(1)); JSAMPROW outputV = static_cast(imagePlanes->plane(2)); @@ -928,38 +941,25 @@ static bool outputRawData(JPEGImageReader* reader, ImagePlanes* imagePlanes) // Request 8 or 16 scanlines: returns 0 or more scanlines. int yScanlinesToRead = DCTSIZE * v; - JSAMPROW yLastRow = *samples; - JSAMPROW uLastRow = yLastRow + rowBytesY; - JSAMPROW vLastRow = uLastRow + rowBytesY; - JSAMPROW dummyRow = vLastRow + rowBytesY; - + JSAMPROW dummyRow = *samples; while (info->output_scanline < info->output_height) { // Assign 8 or 16 rows of memory to read the Y channel. - bool hasYLastRow = false; for (int i = 0; i < yScanlinesToRead; ++i) { int scanline = info->output_scanline + i; - if (scanline < yMaxH) { + if (scanline < yHeight) { bufferraw2[i] = &outputY[scanline * rowBytesY]; - } else if (scanline == yMaxH) { - bufferraw2[i] = yLastRow; - hasYLastRow = true; } else { bufferraw2[i] = dummyRow; } } // Assign 8 rows of memory to read the U and V channels. - bool hasUVLastRow = false; int scaledScanline = info->output_scanline / v; for (int i = 0; i < 8; ++i) { int scanline = scaledScanline + i; - if (scanline < uvMaxH) { + if (scanline < uvHeight) { bufferraw2[16 + i] = &outputU[scanline * rowBytesU]; bufferraw2[24 + i] = &outputV[scanline * rowBytesV]; - } else if (scanline == uvMaxH) { - bufferraw2[16 + i] = uLastRow; - bufferraw2[24 + i] = vLastRow; - hasUVLastRow = true; } else { bufferraw2[16 + i] = dummyRow; bufferraw2[24 + i] = dummyRow; @@ -969,14 +969,6 @@ static bool outputRawData(JPEGImageReader* reader, ImagePlanes* imagePlanes) JDIMENSION scanlinesRead = jpeg_read_raw_data(info, bufferraw, yScanlinesToRead); if (!scanlinesRead) return false; - - if (hasYLastRow) - memcpy(&outputY[yMaxH * rowBytesY], yLastRow, yWidth); - - if (hasUVLastRow) { - memcpy(&outputU[uvMaxH * rowBytesU], uLastRow, uvSize.width()); - memcpy(&outputV[uvMaxH * rowBytesV], vLastRow, uvSize.width()); - } } info->output_scanline = std::min(info->output_scanline, info->output_height); diff --git a/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.h b/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.h index 25aa80a4cef474..a092d495144f87 100644 --- a/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.h +++ b/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.h @@ -43,8 +43,9 @@ class PLATFORM_EXPORT JPEGImageDecoder final : public ImageDecoder { void onSetData(SharedBuffer* data) override; bool hasColorProfile() const override { return m_hasColorProfile; } IntSize decodedSize() const override { return m_decodedSize; } - IntSize decodedYUVSize(int component, SizeType) const override; bool setSize(unsigned width, unsigned height) override; + IntSize decodedYUVSize(int component) const override; + size_t decodedYUVWidthBytes(int component) const override; bool canDecodeToYUV() override; bool decodeToYUV() override; void setImagePlanes(PassOwnPtr) override; diff --git a/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoderTest.cpp b/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoderTest.cpp index 9f2c660ff300ac..305989a7f5d85b 100644 --- a/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoderTest.cpp +++ b/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoderTest.cpp @@ -36,6 +36,7 @@ #include "public/platform/WebData.h" #include "public/platform/WebSize.h" #include "testing/gtest/include/gtest/gtest.h" +#include "wtf/ArrayBuffer.h" #include "wtf/OwnPtr.h" #include "wtf/PassOwnPtr.h" @@ -80,15 +81,17 @@ void readYUV(size_t maxDecodedBytes, unsigned* outputYWidth, unsigned* outputYHe OwnPtr decoder = createDecoder(maxDecodedBytes); decoder->setData(data.get(), true); - OwnPtr imagePlanes = adoptPtr(new ImagePlanes()); - decoder->setImagePlanes(imagePlanes.release()); + // Setting a dummy ImagePlanes object signals to the decoder that we want to do YUV decoding. + OwnPtr dummyImagePlanes = adoptPtr(new ImagePlanes()); + decoder->setImagePlanes(dummyImagePlanes.release()); + bool sizeIsAvailable = decoder->isSizeAvailable(); ASSERT_TRUE(sizeIsAvailable); IntSize size = decoder->decodedSize(); - IntSize ySize = decoder->decodedYUVSize(0, ImageDecoder::ActualSize); - IntSize uSize = decoder->decodedYUVSize(1, ImageDecoder::ActualSize); - IntSize vSize = decoder->decodedYUVSize(2, ImageDecoder::ActualSize); + IntSize ySize = decoder->decodedYUVSize(0); + IntSize uSize = decoder->decodedYUVSize(1); + IntSize vSize = decoder->decodedYUVSize(2); ASSERT_TRUE(size.width() == ySize.width()); ASSERT_TRUE(size.height() == ySize.height()); @@ -99,6 +102,22 @@ void readYUV(size_t maxDecodedBytes, unsigned* outputYWidth, unsigned* outputYHe *outputYHeight = ySize.height(); *outputUVWidth = uSize.width(); *outputUVHeight = uSize.height(); + + size_t rowBytes[3]; + rowBytes[0] = decoder->decodedYUVWidthBytes(0); + rowBytes[1] = decoder->decodedYUVWidthBytes(1); + rowBytes[2] = decoder->decodedYUVWidthBytes(2); + + RefPtr buffer(ArrayBuffer::create(rowBytes[0] * ySize.height() + rowBytes[1] * uSize.height() + rowBytes[2] * vSize.height(), 1)); + void* planes[3]; + planes[0] = buffer->data(); + planes[1] = ((char*) planes[0]) + rowBytes[0] * ySize.height(); + planes[2] = ((char*) planes[1]) + rowBytes[1] * uSize.height(); + + OwnPtr imagePlanes = adoptPtr(new ImagePlanes(planes, rowBytes)); + decoder->setImagePlanes(imagePlanes.release()); + + ASSERT_TRUE(decoder->decodeToYUV()); } // Tests failure on a too big image. @@ -216,6 +235,13 @@ TEST(JPEGImageDecoderTest, yuv) EXPECT_EQ(128u, outputUVWidth); EXPECT_EQ(128u, outputUVHeight); + const char* jpegFileImageSizeNotMultipleOf8 = "/LayoutTests/fast/images/resources/cropped_mandrill.jpg"; // 439x154 + readYUV(LargeEnoughSize, &outputYWidth, &outputYHeight, &outputUVWidth, &outputUVHeight, jpegFileImageSizeNotMultipleOf8); + EXPECT_EQ(439u, outputYWidth); + EXPECT_EQ(154u, outputYHeight); + EXPECT_EQ(220u, outputUVWidth); + EXPECT_EQ(77u, outputUVHeight); + // Make sure we revert to RGBA decoding when we're about to downscale, // which can occur on memory-constrained android devices. RefPtr data = readFile(jpegFile);