Bug 1194058 (Part 1) - Add Deinterlacer to allow Downscaler to work with interlaced images. r=tn
authorSeth Fowler <mark.seth.fowler@gmail.com>
Thu, 17 Sep 2015 15:03:31 -0700
changeset 295765 5fefb6834270963e280b838fe66ace3efcdf3ef9
parent 295764 80f0d809263aa58e3eec17326135f1db2aa891ac
child 295766 3c9f7ca5a12f9b61db3c4cbe1bbf948427ed24dc
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstn
bugs1194058
milestone43.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1194058 (Part 1) - Add Deinterlacer to allow Downscaler to work with interlaced images. r=tn
image/Downscaler.cpp
image/Downscaler.h
--- a/image/Downscaler.cpp
+++ b/image/Downscaler.cpp
@@ -276,10 +276,41 @@ Downscaler::DownscaleInputLine()
   // Shift the buffer. We're just moving pointers here, so this is cheap.
   mLinesInBuffer -= diff;
   mLinesInBuffer = max(mLinesInBuffer, 0);
   for (int32_t i = 0; i < mLinesInBuffer; ++i) {
     swap(mWindow[i], mWindow[filterLength - mLinesInBuffer + i]);
   }
 }
 
+Deinterlacer::Deinterlacer(const nsIntSize& aImageSize)
+  : mImageSize(aImageSize)
+  , mBuffer(MakeUnique<uint8_t[]>(mImageSize.width *
+                                  mImageSize.height *
+                                  sizeof(uint32_t)))
+{ }
+
+uint32_t
+Deinterlacer::RowSize() const
+{
+  return mImageSize.width * sizeof(uint32_t);
+}
+
+uint8_t*
+Deinterlacer::RowBuffer(uint32_t aRow)
+{
+  uint32_t offset = aRow * RowSize();
+  MOZ_ASSERT(offset < mImageSize.width * mImageSize.height * sizeof(uint32_t),
+             "Row is outside of image");
+  return mBuffer.get() + offset;
+}
+
+void
+Deinterlacer::PropagatePassToDownscaler(Downscaler& aDownscaler)
+{
+  for (int32_t row = 0 ; row < mImageSize.height ; ++row) {
+    memcpy(aDownscaler.RowBuffer(), RowBuffer(row), RowSize());
+    aDownscaler.CommitRow();
+  }
+}
+
 } // namespace image
 } // namespace mozilla
--- a/image/Downscaler.h
+++ b/image/Downscaler.h
@@ -157,12 +157,40 @@ public:
   void CommitRow() { }
   bool HasInvalidation() const { return false; }
   DownscalerInvalidRect TakeInvalidRect() { return DownscalerInvalidRect(); }
   void ResetForNextProgressivePass() { }
 };
 
 #endif // MOZ_ENABLE_SKIA
 
+/**
+ * Deinterlacer is a utility class to allow Downscaler to work with interlaced
+ * images.
+
+ * Since Downscaler needs to receive rows in top-to-bottom or
+ * bottom-to-top order, it can't natively handle interlaced images, in which the
+ * rows arrive in an interleaved order. Deinterlacer solves this problem by
+ * acting as an intermediate buffer that records decoded rows. Unlike
+ * Downscaler, it allows the rows to be written in arbitrary order. After each
+ * pass, calling PropagatePassToDownscaler() will downscale every buffered row
+ * in a single operation. The rows remain in the buffer, so rows that were
+ * written in one pass will be included in subsequent passes.
+ */
+class Deinterlacer
+{
+public:
+  explicit Deinterlacer(const nsIntSize& aImageSize);
+
+  uint8_t* RowBuffer(uint32_t aRow);
+  void PropagatePassToDownscaler(Downscaler& aDownscaler);
+
+private:
+  uint32_t RowSize() const;
+
+  nsIntSize mImageSize;
+  UniquePtr<uint8_t[]> mBuffer;
+};
+
 } // namespace image
 } // namespace mozilla
 
 #endif // mozilla_image_Downscaler_h