Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2012 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * | 7 * |
| 8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 24 */ | 24 */ |
| 25 | 25 |
| 26 #include "platform/graphics/ImageFrameGenerator.h" | 26 #include "platform/graphics/ImageFrameGenerator.h" |
| 27 | 27 |
| 28 #include "platform/SharedBuffer.h" | 28 #include "platform/SharedBuffer.h" |
| 29 #include "platform/Task.h" | 29 #include "platform/Task.h" |
| 30 #include "platform/ThreadSafeFunctional.h" | 30 #include "platform/ThreadSafeFunctional.h" |
| 31 #include "platform/graphics/ImageDecodingStore.h" | 31 #include "platform/graphics/ImageDecodingStore.h" |
| 32 #include "platform/graphics/test/MockImageDecoder.h" | 32 #include "platform/graphics/test/MockImageDecoder.h" |
| 33 #include "platform/image-decoders/SharedBufferSegmentReader.h" | |
| 33 #include "public/platform/Platform.h" | 34 #include "public/platform/Platform.h" |
| 34 #include "public/platform/WebThread.h" | 35 #include "public/platform/WebThread.h" |
| 35 #include "public/platform/WebTraceLocation.h" | 36 #include "public/platform/WebTraceLocation.h" |
| 36 #include "testing/gtest/include/gtest/gtest.h" | 37 #include "testing/gtest/include/gtest/gtest.h" |
| 37 | 38 |
| 38 namespace blink { | 39 namespace blink { |
| 39 | 40 |
| 40 namespace { | 41 namespace { |
| 41 | 42 |
| 42 // Helper methods to generate standard sizes. | 43 // Helper methods to generate standard sizes. |
| 43 SkISize fullSize() { return SkISize::Make(100, 100); } | 44 SkISize fullSize() { return SkISize::Make(100, 100); } |
| 44 | 45 |
| 45 SkImageInfo imageInfo() | 46 SkImageInfo imageInfo() |
| 46 { | 47 { |
| 47 return SkImageInfo::Make(100, 100, kBGRA_8888_SkColorType, kOpaque_SkAlphaTy pe); | 48 return SkImageInfo::Make(100, 100, kBGRA_8888_SkColorType, kOpaque_SkAlphaTy pe); |
| 48 } | 49 } |
| 49 | 50 |
| 50 } // namespace | 51 } // namespace |
| 51 | 52 |
| 52 class ImageFrameGeneratorTest : public ::testing::Test, public MockImageDecoderC lient { | 53 class ImageFrameGeneratorTest : public ::testing::Test, public MockImageDecoderC lient { |
| 53 public: | 54 public: |
| 54 void SetUp() override | 55 void SetUp() override |
| 55 { | 56 { |
| 56 ImageDecodingStore::instance().setCacheLimitInBytes(1024 * 1024); | 57 ImageDecodingStore::instance().setCacheLimitInBytes(1024 * 1024); |
| 58 m_generator = ImageFrameGenerator::create(fullSize(), false); | |
| 57 m_data = SharedBuffer::create(); | 59 m_data = SharedBuffer::create(); |
| 58 m_generator = ImageFrameGenerator::create(fullSize(), m_data, false); | 60 m_segmentReader = adoptRef(new SharedBufferSegmentReader(m_data)); |
| 59 useMockImageDecoderFactory(); | 61 useMockImageDecoderFactory(); |
| 60 m_decodersDestroyed = 0; | 62 m_decodersDestroyed = 0; |
| 61 m_decodeRequestCount = 0; | 63 m_decodeRequestCount = 0; |
| 62 m_status = ImageFrame::FrameEmpty; | 64 m_status = ImageFrame::FrameEmpty; |
| 63 m_frameCount = 1; | 65 m_frameCount = 1; |
| 64 } | 66 } |
| 65 | 67 |
| 66 void TearDown() override | 68 void TearDown() override |
| 67 { | 69 { |
| 68 ImageDecodingStore::instance().clear(); | 70 ImageDecodingStore::instance().clear(); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 88 size_t frameCount() override { return m_frameCount; } | 90 size_t frameCount() override { return m_frameCount; } |
| 89 int repetitionCount() const override { return m_frameCount == 1 ? cAnimation None:cAnimationLoopOnce; } | 91 int repetitionCount() const override { return m_frameCount == 1 ? cAnimation None:cAnimationLoopOnce; } |
| 90 float frameDuration() const override { return 0; } | 92 float frameDuration() const override { return 0; } |
| 91 | 93 |
| 92 protected: | 94 protected: |
| 93 void useMockImageDecoderFactory() | 95 void useMockImageDecoderFactory() |
| 94 { | 96 { |
| 95 m_generator->setImageDecoderFactory(MockImageDecoderFactory::create(this , fullSize())); | 97 m_generator->setImageDecoderFactory(MockImageDecoderFactory::create(this , fullSize())); |
| 96 } | 98 } |
| 97 | 99 |
| 98 void addNewData(bool allDataReceived = false) | 100 void addNewData() |
| 99 { | 101 { |
| 100 m_data->append("g", 1); | 102 m_data->append("g", 1); |
| 101 m_generator->setData(m_data, allDataReceived); | |
| 102 } | 103 } |
| 103 | 104 |
| 104 void setFrameStatus(ImageFrame::Status status) { m_status = m_nextFrameStat us = status; } | 105 void setFrameStatus(ImageFrame::Status status) { m_status = m_nextFrameStat us = status; } |
| 105 void setNextFrameStatus(ImageFrame::Status status) { m_nextFrameStatus = st atus; } | 106 void setNextFrameStatus(ImageFrame::Status status) { m_nextFrameStatus = st atus; } |
| 106 void setFrameCount(size_t count) | 107 void setFrameCount(size_t count) |
| 107 { | 108 { |
| 108 m_frameCount = count; | 109 m_frameCount = count; |
| 109 if (count > 1) { | 110 if (count > 1) { |
| 110 m_generator.clear(); | 111 m_generator.clear(); |
| 111 m_generator = ImageFrameGenerator::create(fullSize(), m_data, true, true); | 112 m_generator = ImageFrameGenerator::create(fullSize(), true); |
| 112 useMockImageDecoderFactory(); | 113 useMockImageDecoderFactory(); |
| 113 } | 114 } |
| 114 } | 115 } |
| 115 | 116 |
| 116 RefPtr<SharedBuffer> m_data; | 117 RefPtr<SharedBuffer> m_data; |
| 118 RefPtr<SegmentReader> m_segmentReader; | |
| 117 RefPtr<ImageFrameGenerator> m_generator; | 119 RefPtr<ImageFrameGenerator> m_generator; |
| 118 int m_decodersDestroyed; | 120 int m_decodersDestroyed; |
| 119 int m_decodeRequestCount; | 121 int m_decodeRequestCount; |
| 120 ImageFrame::Status m_status; | 122 ImageFrame::Status m_status; |
| 121 ImageFrame::Status m_nextFrameStatus; | 123 ImageFrame::Status m_nextFrameStatus; |
| 122 size_t m_frameCount; | 124 size_t m_frameCount; |
| 123 }; | 125 }; |
| 124 | 126 |
| 125 TEST_F(ImageFrameGeneratorTest, incompleteDecode) | 127 TEST_F(ImageFrameGeneratorTest, incompleteDecode) |
| 126 { | 128 { |
| 127 setFrameStatus(ImageFrame::FramePartial); | 129 setFrameStatus(ImageFrame::FramePartial); |
| 128 | 130 |
| 129 char buffer[100 * 100 * 4]; | 131 char buffer[100 * 100 * 4]; |
| 130 m_generator->decodeAndScale(0, imageInfo(), buffer, 100 * 4); | 132 m_generator->decodeAndScale(m_segmentReader.get(), false, 0, imageInfo(), bu ffer, 100 * 4); |
| 131 EXPECT_EQ(1, m_decodeRequestCount); | 133 EXPECT_EQ(1, m_decodeRequestCount); |
| 132 | 134 |
| 133 addNewData(); | 135 addNewData(); |
| 134 m_generator->decodeAndScale(0, imageInfo(), buffer, 100 * 4); | 136 m_generator->decodeAndScale(m_segmentReader.get(), false, 0, imageInfo(), bu ffer, 100 * 4); |
| 135 EXPECT_EQ(2, m_decodeRequestCount); | 137 EXPECT_EQ(2, m_decodeRequestCount); |
| 136 EXPECT_EQ(0, m_decodersDestroyed); | 138 EXPECT_EQ(0, m_decodersDestroyed); |
| 137 } | 139 } |
| 138 | 140 |
| 139 TEST_F(ImageFrameGeneratorTest, incompleteDecodeBecomesComplete) | 141 TEST_F(ImageFrameGeneratorTest, incompleteDecodeBecomesComplete) |
| 140 { | 142 { |
| 141 setFrameStatus(ImageFrame::FramePartial); | 143 setFrameStatus(ImageFrame::FramePartial); |
| 142 | 144 |
| 143 char buffer[100 * 100 * 4]; | 145 char buffer[100 * 100 * 4]; |
| 144 m_generator->decodeAndScale(0, imageInfo(), buffer, 100 * 4); | 146 m_generator->decodeAndScale(m_segmentReader.get(), false, 0, imageInfo(), bu ffer, 100 * 4); |
| 145 EXPECT_EQ(1, m_decodeRequestCount); | 147 EXPECT_EQ(1, m_decodeRequestCount); |
| 146 EXPECT_EQ(0, m_decodersDestroyed); | 148 EXPECT_EQ(0, m_decodersDestroyed); |
| 147 | 149 |
| 148 setFrameStatus(ImageFrame::FrameComplete); | 150 setFrameStatus(ImageFrame::FrameComplete); |
| 149 addNewData(); | 151 addNewData(); |
| 150 | 152 |
| 151 m_generator->decodeAndScale(0, imageInfo(), buffer, 100 * 4); | 153 m_generator->decodeAndScale(m_segmentReader.get(), false, 0, imageInfo(), bu ffer, 100 * 4); |
| 152 EXPECT_EQ(2, m_decodeRequestCount); | 154 EXPECT_EQ(2, m_decodeRequestCount); |
| 153 EXPECT_EQ(1, m_decodersDestroyed); | 155 EXPECT_EQ(1, m_decodersDestroyed); |
| 154 | 156 |
| 155 // Decoder created again. | 157 // Decoder created again. |
| 156 m_generator->decodeAndScale(0, imageInfo(), buffer, 100 * 4); | 158 m_generator->decodeAndScale(m_segmentReader.get(), false, 0, imageInfo(), bu ffer, 100 * 4); |
| 157 EXPECT_EQ(3, m_decodeRequestCount); | 159 EXPECT_EQ(3, m_decodeRequestCount); |
| 158 } | 160 } |
| 159 | 161 |
| 160 static void decodeThreadMain(ImageFrameGenerator* generator) | 162 static void decodeThreadMain(ImageFrameGenerator* generator, SegmentReader* segm entReader) |
| 161 { | 163 { |
| 162 char buffer[100 * 100 * 4]; | 164 char buffer[100 * 100 * 4]; |
| 163 generator->decodeAndScale(0, imageInfo(), buffer, 100 * 4); | 165 generator->decodeAndScale(segmentReader, false, 0, imageInfo(), buffer, 100 * 4); |
| 164 } | |
| 165 | |
| 166 static void decodeThreadWithRefEncodedMain(ImageFrameGenerator* generator) | |
| 167 { | |
| 168 // Image must be complete - refEncodedData otherwise returns null. | |
| 169 char buffer[100 * 100 * 4]; | |
| 170 SkData* data = generator->refEncodedData(); | |
| 171 generator->decodeAndScale(0, imageInfo(), buffer, 100 * 4); | |
| 172 data->unref(); | |
| 173 } | 166 } |
| 174 | 167 |
| 175 TEST_F(ImageFrameGeneratorTest, incompleteDecodeBecomesCompleteMultiThreaded) | 168 TEST_F(ImageFrameGeneratorTest, incompleteDecodeBecomesCompleteMultiThreaded) |
| 176 { | 169 { |
| 177 setFrameStatus(ImageFrame::FramePartial); | 170 setFrameStatus(ImageFrame::FramePartial); |
| 178 | 171 |
| 179 char buffer[100 * 100 * 4]; | 172 char buffer[100 * 100 * 4]; |
| 180 m_generator->decodeAndScale(0, imageInfo(), buffer, 100 * 4); | 173 m_generator->decodeAndScale(m_segmentReader.get(), false, 0, imageInfo(), bu ffer, 100 * 4); |
| 181 EXPECT_EQ(1, m_decodeRequestCount); | 174 EXPECT_EQ(1, m_decodeRequestCount); |
| 182 EXPECT_EQ(0, m_decodersDestroyed); | 175 EXPECT_EQ(0, m_decodersDestroyed); |
| 183 SkData* data = m_generator->refEncodedData(); | |
| 184 EXPECT_EQ(nullptr, data); | |
| 185 | 176 |
| 186 // LocalFrame can now be decoded completely. | 177 // LocalFrame can now be decoded completely. |
| 187 setFrameStatus(ImageFrame::FrameComplete); | 178 setFrameStatus(ImageFrame::FrameComplete); |
| 188 addNewData(); | 179 addNewData(); |
| 189 // addNewData is calling m_generator->setData with allDataReceived == false, which means that | |
| 190 // refEncodedData should return null. | |
| 191 data = m_generator->refEncodedData(); | |
| 192 EXPECT_EQ(nullptr, data); | |
| 193 OwnPtr<WebThread> thread = adoptPtr(Platform::current()->createThread("Decod eThread")); | 180 OwnPtr<WebThread> thread = adoptPtr(Platform::current()->createThread("Decod eThread")); |
| 194 thread->taskRunner()->postTask(BLINK_FROM_HERE, new Task(threadSafeBind(&dec odeThreadMain, AllowCrossThreadAccess(m_generator.get())))); | 181 thread->taskRunner()->postTask(BLINK_FROM_HERE, new Task(threadSafeBind(&dec odeThreadMain, AllowCrossThreadAccess(m_generator.get()), AllowCrossThreadAccess (m_segmentReader.get())))); |
| 195 thread.clear(); | 182 thread.clear(); |
| 196 EXPECT_EQ(2, m_decodeRequestCount); | 183 EXPECT_EQ(2, m_decodeRequestCount); |
| 197 EXPECT_EQ(1, m_decodersDestroyed); | 184 EXPECT_EQ(1, m_decodersDestroyed); |
| 198 | 185 |
| 199 // Decoder created again. | 186 // Decoder created again. |
| 200 m_generator->decodeAndScale(0, imageInfo(), buffer, 100 * 4); | 187 m_generator->decodeAndScale(m_segmentReader.get(), false, 0, imageInfo(), bu ffer, 100 * 4); |
| 201 EXPECT_EQ(3, m_decodeRequestCount); | 188 EXPECT_EQ(3, m_decodeRequestCount); |
| 202 | 189 |
| 203 addNewData(true); | 190 addNewData(); |
| 204 data = m_generator->refEncodedData(); | |
| 205 ASSERT_TRUE(data); | |
| 206 // To prevent data writting, SkData::unique() should be false. | |
| 207 ASSERT_TRUE(!data->unique()); | |
| 208 | 191 |
| 209 // Thread will also ref and unref the data. | 192 // Delete generator |
|
Peter Kasting
2016/03/23 02:42:58
Nit: Period
scroggo_chromium
2016/03/24 13:59:45
Done.
| |
| 210 thread = adoptPtr(Platform::current()->createThread("RefEncodedDataThread")) ; | |
| 211 thread->taskRunner()->postTask(BLINK_FROM_HERE, new Task(threadSafeBind(&dec odeThreadWithRefEncodedMain, AllowCrossThreadAccess(m_generator.get())))); | |
| 212 thread.clear(); | |
| 213 EXPECT_EQ(4, m_decodeRequestCount); | |
| 214 | |
| 215 data->unref(); | |
| 216 // m_generator is holding the only reference to SkData now. | |
| 217 ASSERT_TRUE(data->unique()); | |
| 218 | |
| 219 data = m_generator->refEncodedData(); | |
| 220 ASSERT_TRUE(data && !data->unique()); | |
| 221 | |
| 222 // Delete generator, and SkData should have the only reference. | |
| 223 m_generator = nullptr; | 193 m_generator = nullptr; |
| 224 ASSERT_TRUE(data->unique()); | |
| 225 data->unref(); | |
| 226 } | 194 } |
| 227 | 195 |
| 228 TEST_F(ImageFrameGeneratorTest, frameHasAlpha) | 196 TEST_F(ImageFrameGeneratorTest, frameHasAlpha) |
| 229 { | 197 { |
| 230 setFrameStatus(ImageFrame::FramePartial); | 198 setFrameStatus(ImageFrame::FramePartial); |
| 231 | 199 |
| 232 char buffer[100 * 100 * 4]; | 200 char buffer[100 * 100 * 4]; |
| 233 m_generator->decodeAndScale(0, imageInfo(), buffer, 100 * 4); | 201 m_generator->decodeAndScale(m_segmentReader.get(), false, 0, imageInfo(), bu ffer, 100 * 4); |
| 234 EXPECT_TRUE(m_generator->hasAlpha(0)); | 202 EXPECT_TRUE(m_generator->hasAlpha(0)); |
| 235 EXPECT_EQ(1, m_decodeRequestCount); | 203 EXPECT_EQ(1, m_decodeRequestCount); |
| 236 | 204 |
| 237 ImageDecoder* tempDecoder = 0; | 205 ImageDecoder* tempDecoder = 0; |
| 238 EXPECT_TRUE(ImageDecodingStore::instance().lockDecoder(m_generator.get(), fu llSize(), &tempDecoder)); | 206 EXPECT_TRUE(ImageDecodingStore::instance().lockDecoder(m_generator.get(), fu llSize(), &tempDecoder)); |
| 239 ASSERT_TRUE(tempDecoder); | 207 ASSERT_TRUE(tempDecoder); |
| 240 tempDecoder->frameBufferAtIndex(0)->setHasAlpha(false); | 208 tempDecoder->frameBufferAtIndex(0)->setHasAlpha(false); |
| 241 ImageDecodingStore::instance().unlockDecoder(m_generator.get(), tempDecoder) ; | 209 ImageDecodingStore::instance().unlockDecoder(m_generator.get(), tempDecoder) ; |
| 242 EXPECT_EQ(2, m_decodeRequestCount); | 210 EXPECT_EQ(2, m_decodeRequestCount); |
| 243 | 211 |
| 244 setFrameStatus(ImageFrame::FrameComplete); | 212 setFrameStatus(ImageFrame::FrameComplete); |
| 245 m_generator->decodeAndScale(0, imageInfo(), buffer, 100 * 4); | 213 m_generator->decodeAndScale(m_segmentReader.get(), false, 0, imageInfo(), bu ffer, 100 * 4); |
| 246 EXPECT_EQ(3, m_decodeRequestCount); | 214 EXPECT_EQ(3, m_decodeRequestCount); |
| 247 EXPECT_FALSE(m_generator->hasAlpha(0)); | 215 EXPECT_FALSE(m_generator->hasAlpha(0)); |
| 248 } | 216 } |
| 249 | 217 |
| 250 TEST_F(ImageFrameGeneratorTest, removeMultiFrameDecoder) | 218 TEST_F(ImageFrameGeneratorTest, removeMultiFrameDecoder) |
| 251 { | 219 { |
| 252 setFrameCount(3); | 220 setFrameCount(3); |
| 253 setFrameStatus(ImageFrame::FrameComplete); | 221 setFrameStatus(ImageFrame::FrameComplete); |
| 254 | 222 |
| 255 char buffer[100 * 100 * 4]; | 223 char buffer[100 * 100 * 4]; |
| 256 m_generator->decodeAndScale(0, imageInfo(), buffer, 100 * 4); | 224 m_generator->decodeAndScale(m_segmentReader.get(), true, 0, imageInfo(), buf fer, 100 * 4); |
| 257 EXPECT_EQ(1, m_decodeRequestCount); | 225 EXPECT_EQ(1, m_decodeRequestCount); |
| 258 EXPECT_EQ(0, m_decodersDestroyed); | 226 EXPECT_EQ(0, m_decodersDestroyed); |
| 259 | 227 |
| 260 setFrameStatus(ImageFrame::FrameComplete); | 228 setFrameStatus(ImageFrame::FrameComplete); |
| 261 | 229 |
| 262 m_generator->decodeAndScale(1, imageInfo(), buffer, 100 * 4); | 230 m_generator->decodeAndScale(m_segmentReader.get(), true, 1, imageInfo(), buf fer, 100 * 4); |
| 263 EXPECT_EQ(2, m_decodeRequestCount); | 231 EXPECT_EQ(2, m_decodeRequestCount); |
| 264 EXPECT_EQ(0, m_decodersDestroyed); | 232 EXPECT_EQ(0, m_decodersDestroyed); |
| 265 | 233 |
| 266 setFrameStatus(ImageFrame::FrameComplete); | 234 setFrameStatus(ImageFrame::FrameComplete); |
| 267 | 235 |
| 268 // Multi frame decoder should be removed. | 236 // Multi frame decoder should be removed. |
| 269 m_generator->decodeAndScale(2, imageInfo(), buffer, 100 * 4); | 237 m_generator->decodeAndScale(m_segmentReader.get(), true, 2, imageInfo(), buf fer, 100 * 4); |
| 270 EXPECT_EQ(3, m_decodeRequestCount); | 238 EXPECT_EQ(3, m_decodeRequestCount); |
| 271 EXPECT_EQ(1, m_decodersDestroyed); | 239 EXPECT_EQ(1, m_decodersDestroyed); |
| 272 } | 240 } |
| 273 | 241 |
| 274 } // namespace blink | 242 } // namespace blink |
| OLD | NEW |