Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1b1aef25 authored by Harish Mahendrakar's avatar Harish Mahendrakar
Browse files

C2 Decoders: Move copy/convert functions to SimpleC2Component

VPx, AV1 and mpeg4 decoders had few copy/convert functions to
write data to graphic buffers from codec buffers.
These functions are now moved to SimpleC2Component.

Also added function to support conversion to P010 format for
10 bit YUV data.

Bug: 178229371
Test: atest CtsMediaV2TestCases -- --module-arg \
 CtsMediaV2TestCases:instrumentation-arg:codec-prefix:=c2.android.

Change-Id: Iec78a67f95bb514967403eb478ecf8e0f0a8fbf9
parent 0523f705
Loading
Loading
Loading
Loading
+5 −128
Original line number Diff line number Diff line
@@ -505,124 +505,6 @@ void C2SoftAomDec::process(const std::unique_ptr<C2Work>& work,
    }
}

static void copyOutputBufferToYuvPlanarFrame(
        uint8_t *dstY, uint8_t *dstU, uint8_t *dstV,
        const uint8_t *srcY, const uint8_t *srcU, const uint8_t *srcV,
        size_t srcYStride, size_t srcUStride, size_t srcVStride,
        size_t dstYStride, size_t dstUVStride,
        uint32_t width, uint32_t height) {

    for (size_t i = 0; i < height; ++i) {
        memcpy(dstY, srcY, width);
        srcY += srcYStride;
        dstY += dstYStride;
    }

    for (size_t i = 0; i < height / 2; ++i) {
        memcpy(dstV, srcV, width / 2);
        srcV += srcVStride;
        dstV += dstUVStride;
    }

    for (size_t i = 0; i < height / 2; ++i) {
        memcpy(dstU, srcU, width / 2);
        srcU += srcUStride;
        dstU += dstUVStride;
    }
}

static void convertYUV420Planar16ToY410(uint32_t *dst,
        const uint16_t *srcY, const uint16_t *srcU, const uint16_t *srcV,
        size_t srcYStride, size_t srcUStride, size_t srcVStride,
        size_t dstStride, size_t width, size_t height) {

    // Converting two lines at a time, slightly faster
    for (size_t y = 0; y < height; y += 2) {
        uint32_t *dstTop = (uint32_t *) dst;
        uint32_t *dstBot = (uint32_t *) (dst + dstStride);
        uint16_t *ySrcTop = (uint16_t*) srcY;
        uint16_t *ySrcBot = (uint16_t*) (srcY + srcYStride);
        uint16_t *uSrc = (uint16_t*) srcU;
        uint16_t *vSrc = (uint16_t*) srcV;

        uint32_t u01, v01, y01, y23, y45, y67, uv0, uv1;
        size_t x = 0;
        for (; x < width - 3; x += 4) {

            u01 = *((uint32_t*)uSrc); uSrc += 2;
            v01 = *((uint32_t*)vSrc); vSrc += 2;

            y01 = *((uint32_t*)ySrcTop); ySrcTop += 2;
            y23 = *((uint32_t*)ySrcTop); ySrcTop += 2;
            y45 = *((uint32_t*)ySrcBot); ySrcBot += 2;
            y67 = *((uint32_t*)ySrcBot); ySrcBot += 2;

            uv0 = (u01 & 0x3FF) | ((v01 & 0x3FF) << 20);
            uv1 = (u01 >> 16) | ((v01 >> 16) << 20);

            *dstTop++ = 3 << 30 | ((y01 & 0x3FF) << 10) | uv0;
            *dstTop++ = 3 << 30 | ((y01 >> 16) << 10) | uv0;
            *dstTop++ = 3 << 30 | ((y23 & 0x3FF) << 10) | uv1;
            *dstTop++ = 3 << 30 | ((y23 >> 16) << 10) | uv1;

            *dstBot++ = 3 << 30 | ((y45 & 0x3FF) << 10) | uv0;
            *dstBot++ = 3 << 30 | ((y45 >> 16) << 10) | uv0;
            *dstBot++ = 3 << 30 | ((y67 & 0x3FF) << 10) | uv1;
            *dstBot++ = 3 << 30 | ((y67 >> 16) << 10) | uv1;
        }

        // There should be at most 2 more pixels to process. Note that we don't
        // need to consider odd case as the buffer is always aligned to even.
        if (x < width) {
            u01 = *uSrc;
            v01 = *vSrc;
            y01 = *((uint32_t*)ySrcTop);
            y45 = *((uint32_t*)ySrcBot);
            uv0 = (u01 & 0x3FF) | ((v01 & 0x3FF) << 20);
            *dstTop++ = ((y01 & 0x3FF) << 10) | uv0;
            *dstTop++ = ((y01 >> 16) << 10) | uv0;
            *dstBot++ = ((y45 & 0x3FF) << 10) | uv0;
            *dstBot++ = ((y45 >> 16) << 10) | uv0;
        }

        srcY += srcYStride * 2;
        srcU += srcUStride;
        srcV += srcVStride;
        dst += dstStride * 2;
    }

    return;
}

static void convertYUV420Planar16ToYUV420Planar(
        uint8_t *dstY, uint8_t *dstU, uint8_t *dstV,
        const uint16_t *srcY, const uint16_t *srcU, const uint16_t *srcV,
        size_t srcYStride, size_t srcUStride, size_t srcVStride,
        size_t dstYStride, size_t dstUVStride,
        size_t width, size_t height) {

    for (size_t y = 0; y < height; ++y) {
        for (size_t x = 0; x < width; ++x) {
            dstY[x] = (uint8_t)(srcY[x] >> 2);
        }

        srcY += srcYStride;
        dstY += dstYStride;
    }

    for (size_t y = 0; y < (height + 1) / 2; ++y) {
        for (size_t x = 0; x < (width + 1) / 2; ++x) {
            dstU[x] = (uint8_t)(srcU[x] >> 2);
            dstV[x] = (uint8_t)(srcV[x] >> 2);
        }

        srcU += srcUStride;
        srcV += srcVStride;
        dstU += dstUVStride;
        dstV += dstUVStride;
    }
    return;
}
bool C2SoftAomDec::outputBuffer(
        const std::shared_ptr<C2BlockPool> &pool,
        const std::unique_ptr<C2Work> &work)
@@ -711,21 +593,16 @@ bool C2SoftAomDec::outputBuffer(
                                    dstYStride / sizeof(uint32_t),
                                    mWidth, mHeight);
        } else {
            convertYUV420Planar16ToYUV420Planar(dstY, dstU, dstV,
                                    srcY, srcU, srcV,
                                    srcYStride / 2, srcUStride / 2, srcVStride / 2,
                                    dstYStride, dstUVStride,
            convertYUV420Planar16ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride / 2,
                                        srcUStride / 2, srcVStride / 2, dstYStride, dstUVStride,
                                        mWidth, mHeight);
        }
    } else {
        const uint8_t *srcY = (const uint8_t *)img->planes[AOM_PLANE_Y];
        const uint8_t *srcU = (const uint8_t *)img->planes[AOM_PLANE_U];
        const uint8_t *srcV = (const uint8_t *)img->planes[AOM_PLANE_V];
        copyOutputBufferToYuvPlanarFrame(
                dstY, dstU, dstV, srcY, srcU, srcV,
                srcYStride, srcUStride, srcVStride,
                dstYStride, dstUVStride,
                mWidth, mHeight);
        convertYUV420Planar8ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride, srcUStride,
                                   srcVStride, dstYStride, dstUVStride, mWidth, mHeight);
    }
    finishWork(*(int64_t*)img->user_priv, work, std::move(block));
    block = nullptr;
+172 −0
Original line number Diff line number Diff line
@@ -29,7 +29,179 @@
#include <SimpleC2Component.h>

namespace android {
constexpr uint8_t kNeutralUVBitDepth8 = 128;
constexpr uint16_t kNeutralUVBitDepth10 = 512;

void convertYUV420Planar8ToYV12(uint8_t *dstY, uint8_t *dstU, uint8_t *dstV, const uint8_t *srcY,
                                const uint8_t *srcU, const uint8_t *srcV, size_t srcYStride,
                                size_t srcUStride, size_t srcVStride, size_t dstYStride,
                                size_t dstUVStride, uint32_t width, uint32_t height,
                                bool isMonochrome) {
    for (size_t i = 0; i < height; ++i) {
        memcpy(dstY, srcY, width);
        srcY += srcYStride;
        dstY += dstYStride;
    }

    if (isMonochrome) {
        // Fill with neutral U/V values.
        for (size_t i = 0; i < height / 2; ++i) {
            memset(dstV, kNeutralUVBitDepth8, width / 2);
            memset(dstU, kNeutralUVBitDepth8, width / 2);
            dstV += dstUVStride;
            dstU += dstUVStride;
        }
        return;
    }

    for (size_t i = 0; i < height / 2; ++i) {
        memcpy(dstV, srcV, width / 2);
        srcV += srcVStride;
        dstV += dstUVStride;
    }

    for (size_t i = 0; i < height / 2; ++i) {
        memcpy(dstU, srcU, width / 2);
        srcU += srcUStride;
        dstU += dstUVStride;
    }
}

void convertYUV420Planar16ToY410(uint32_t *dst, const uint16_t *srcY, const uint16_t *srcU,
                                 const uint16_t *srcV, size_t srcYStride, size_t srcUStride,
                                 size_t srcVStride, size_t dstStride, size_t width, size_t height) {
    // Converting two lines at a time, slightly faster
    for (size_t y = 0; y < height; y += 2) {
        uint32_t *dstTop = (uint32_t *)dst;
        uint32_t *dstBot = (uint32_t *)(dst + dstStride);
        uint16_t *ySrcTop = (uint16_t *)srcY;
        uint16_t *ySrcBot = (uint16_t *)(srcY + srcYStride);
        uint16_t *uSrc = (uint16_t *)srcU;
        uint16_t *vSrc = (uint16_t *)srcV;

        uint32_t u01, v01, y01, y23, y45, y67, uv0, uv1;
        size_t x = 0;
        for (; x < width - 3; x += 4) {
            u01 = *((uint32_t *)uSrc);
            uSrc += 2;
            v01 = *((uint32_t *)vSrc);
            vSrc += 2;

            y01 = *((uint32_t *)ySrcTop);
            ySrcTop += 2;
            y23 = *((uint32_t *)ySrcTop);
            ySrcTop += 2;
            y45 = *((uint32_t *)ySrcBot);
            ySrcBot += 2;
            y67 = *((uint32_t *)ySrcBot);
            ySrcBot += 2;

            uv0 = (u01 & 0x3FF) | ((v01 & 0x3FF) << 20);
            uv1 = (u01 >> 16) | ((v01 >> 16) << 20);

            *dstTop++ = 3 << 30 | ((y01 & 0x3FF) << 10) | uv0;
            *dstTop++ = 3 << 30 | ((y01 >> 16) << 10) | uv0;
            *dstTop++ = 3 << 30 | ((y23 & 0x3FF) << 10) | uv1;
            *dstTop++ = 3 << 30 | ((y23 >> 16) << 10) | uv1;

            *dstBot++ = 3 << 30 | ((y45 & 0x3FF) << 10) | uv0;
            *dstBot++ = 3 << 30 | ((y45 >> 16) << 10) | uv0;
            *dstBot++ = 3 << 30 | ((y67 & 0x3FF) << 10) | uv1;
            *dstBot++ = 3 << 30 | ((y67 >> 16) << 10) | uv1;
        }

        // There should be at most 2 more pixels to process. Note that we don't
        // need to consider odd case as the buffer is always aligned to even.
        if (x < width) {
            u01 = *uSrc;
            v01 = *vSrc;
            y01 = *((uint32_t *)ySrcTop);
            y45 = *((uint32_t *)ySrcBot);
            uv0 = (u01 & 0x3FF) | ((v01 & 0x3FF) << 20);
            *dstTop++ = ((y01 & 0x3FF) << 10) | uv0;
            *dstTop++ = ((y01 >> 16) << 10) | uv0;
            *dstBot++ = ((y45 & 0x3FF) << 10) | uv0;
            *dstBot++ = ((y45 >> 16) << 10) | uv0;
        }

        srcY += srcYStride * 2;
        srcU += srcUStride;
        srcV += srcVStride;
        dst += dstStride * 2;
    }
}

void convertYUV420Planar16ToYV12(uint8_t *dstY, uint8_t *dstU, uint8_t *dstV, const uint16_t *srcY,
                                 const uint16_t *srcU, const uint16_t *srcV, size_t srcYStride,
                                 size_t srcUStride, size_t srcVStride, size_t dstYStride,
                                 size_t dstUVStride, size_t width, size_t height,
                                 bool isMonochrome) {
    for (size_t y = 0; y < height; ++y) {
        for (size_t x = 0; x < width; ++x) {
            dstY[x] = (uint8_t)(srcY[x] >> 2);
        }
        srcY += srcYStride;
        dstY += dstYStride;
    }

    if (isMonochrome) {
        // Fill with neutral U/V values.
        for (size_t y = 0; y < (height + 1) / 2; ++y) {
            memset(dstV, kNeutralUVBitDepth8, (width + 1) / 2);
            memset(dstU, kNeutralUVBitDepth8, (width + 1) / 2);
            dstV += dstUVStride;
            dstU += dstUVStride;
        }
        return;
    }

    for (size_t y = 0; y < (height + 1) / 2; ++y) {
        for (size_t x = 0; x < (width + 1) / 2; ++x) {
            dstU[x] = (uint8_t)(srcU[x] >> 2);
            dstV[x] = (uint8_t)(srcV[x] >> 2);
        }
        srcU += srcUStride;
        srcV += srcVStride;
        dstU += dstUVStride;
        dstV += dstUVStride;
    }
}

void convertYUV420Planar16ToP010(uint16_t *dstY, uint16_t *dstUV, const uint16_t *srcY,
                                 const uint16_t *srcU, const uint16_t *srcV, size_t srcYStride,
                                 size_t srcUStride, size_t srcVStride, size_t dstYStride,
                                 size_t dstUVStride, size_t width, size_t height,
                                 bool isMonochrome) {
    for (size_t y = 0; y < height; ++y) {
        for (size_t x = 0; x < width; ++x) {
            dstY[x] = srcY[x] << 6;
        }
        srcY += srcYStride;
        dstY += dstYStride;
    }

    if (isMonochrome) {
        // Fill with neutral U/V values.
        for (size_t y = 0; y < (height + 1) / 2; ++y) {
            for (size_t x = 0; x < (width + 1) / 2; ++x) {
                dstUV[2 * x] = kNeutralUVBitDepth10 << 6;
                dstUV[2 * x + 1] = kNeutralUVBitDepth10 << 6;
            }
            dstUV += dstUVStride;
        }
        return;
    }

    for (size_t y = 0; y < (height + 1) / 2; ++y) {
        for (size_t x = 0; x < (width + 1) / 2; ++x) {
            dstUV[2 * x] = srcU[x] << 6;
            dstUV[2 * x + 1] = srcV[x] << 6;
        }
        srcU += srcUStride;
        srcV += srcVStride;
        dstUV += dstUVStride;
    }
}
std::unique_ptr<C2Work> SimpleC2Component::WorkQueue::pop_front() {
    std::unique_ptr<C2Work> work = std::move(mQueue.front().work);
    mQueue.pop_front();
+18 −0
Original line number Diff line number Diff line
@@ -28,6 +28,24 @@

namespace android {

void convertYUV420Planar8ToYV12(uint8_t *dstY, uint8_t *dstU, uint8_t *dstV, const uint8_t *srcY,
                                const uint8_t *srcU, const uint8_t *srcV, size_t srcYStride,
                                size_t srcUStride, size_t srcVStride, size_t dstYStride,
                                size_t dstUVStride, uint32_t width, uint32_t height,
                                bool isMonochrome = false);
void convertYUV420Planar16ToY410(uint32_t *dst, const uint16_t *srcY, const uint16_t *srcU,
                                 const uint16_t *srcV, size_t srcYStride, size_t srcUStride,
                                 size_t srcVStride, size_t dstStride, size_t width, size_t height);
void convertYUV420Planar16ToYV12(uint8_t *dstY, uint8_t *dstU, uint8_t *dstV, const uint16_t *srcY,
                                 const uint16_t *srcU, const uint16_t *srcV, size_t srcYStride,
                                 size_t srcUStride, size_t srcVStride, size_t dstYStride,
                                 size_t dstUVStride, size_t width, size_t height,
                                 bool isMonochrome = false);
void convertYUV420Planar16ToP010(uint16_t *dstY, uint16_t *dstUV, const uint16_t *srcY,
                                 const uint16_t *srcU, const uint16_t *srcV, size_t srcYStride,
                                 size_t srcUStride, size_t srcVStride, size_t dstYStride,
                                 size_t dstUVStride, size_t width, size_t height,
                                 bool isMonochrome = false);
class SimpleC2Component
        : public C2Component, public std::enable_shared_from_this<SimpleC2Component> {
public:
+12 −159
Original line number Diff line number Diff line
@@ -28,11 +28,6 @@
#include <media/stagefright/foundation/MediaDefs.h>

namespace android {
namespace {

constexpr uint8_t NEUTRAL_UV_VALUE = 128;

}  // namespace

// codecname set and passed in as a compile flag from Android.bp
constexpr char COMPONENT_NAME[] = CODECNAME;
@@ -545,150 +540,6 @@ void C2SoftGav1Dec::process(const std::unique_ptr<C2Work> &work,
  }
}

static void copyOutputBufferToYV12Frame(uint8_t *dstY, uint8_t *dstU, uint8_t *dstV,
                                        const uint8_t *srcY, const uint8_t *srcU, const uint8_t *srcV,
                                        size_t srcYStride, size_t srcUStride, size_t srcVStride,
                                        size_t dstYStride, size_t dstUVStride,
                                        uint32_t width, uint32_t height,
                                        bool isMonochrome) {

  for (size_t i = 0; i < height; ++i) {
    memcpy(dstY, srcY, width);
    srcY += srcYStride;
    dstY += dstYStride;
  }

  if (isMonochrome) {
    // Fill with neutral U/V values.
    for (size_t i = 0; i < height / 2; ++i) {
      memset(dstV, NEUTRAL_UV_VALUE, width / 2);
      memset(dstU, NEUTRAL_UV_VALUE, width / 2);
      dstV += dstUVStride;
      dstU += dstUVStride;
    }
    return;
  }

  for (size_t i = 0; i < height / 2; ++i) {
    memcpy(dstV, srcV, width / 2);
    srcV += srcVStride;
    dstV += dstUVStride;
  }

  for (size_t i = 0; i < height / 2; ++i) {
    memcpy(dstU, srcU, width / 2);
    srcU += srcUStride;
    dstU += dstUVStride;
  }
}

static void convertYUV420Planar16ToY410(uint32_t *dst, const uint16_t *srcY,
                                        const uint16_t *srcU,
                                        const uint16_t *srcV, size_t srcYStride,
                                        size_t srcUStride, size_t srcVStride,
                                        size_t dstStride, size_t width,
                                        size_t height) {
  // Converting two lines at a time, slightly faster
  for (size_t y = 0; y < height; y += 2) {
    uint32_t *dstTop = (uint32_t *)dst;
    uint32_t *dstBot = (uint32_t *)(dst + dstStride);
    uint16_t *ySrcTop = (uint16_t *)srcY;
    uint16_t *ySrcBot = (uint16_t *)(srcY + srcYStride);
    uint16_t *uSrc = (uint16_t *)srcU;
    uint16_t *vSrc = (uint16_t *)srcV;

    uint32_t u01, v01, y01, y23, y45, y67, uv0, uv1;
    size_t x = 0;
    for (; x < width - 3; x += 4) {
      u01 = *((uint32_t *)uSrc);
      uSrc += 2;
      v01 = *((uint32_t *)vSrc);
      vSrc += 2;

      y01 = *((uint32_t *)ySrcTop);
      ySrcTop += 2;
      y23 = *((uint32_t *)ySrcTop);
      ySrcTop += 2;
      y45 = *((uint32_t *)ySrcBot);
      ySrcBot += 2;
      y67 = *((uint32_t *)ySrcBot);
      ySrcBot += 2;

      uv0 = (u01 & 0x3FF) | ((v01 & 0x3FF) << 20);
      uv1 = (u01 >> 16) | ((v01 >> 16) << 20);

      *dstTop++ = 3 << 30 | ((y01 & 0x3FF) << 10) | uv0;
      *dstTop++ = 3 << 30 | ((y01 >> 16) << 10) | uv0;
      *dstTop++ = 3 << 30 | ((y23 & 0x3FF) << 10) | uv1;
      *dstTop++ = 3 << 30 | ((y23 >> 16) << 10) | uv1;

      *dstBot++ = 3 << 30 | ((y45 & 0x3FF) << 10) | uv0;
      *dstBot++ = 3 << 30 | ((y45 >> 16) << 10) | uv0;
      *dstBot++ = 3 << 30 | ((y67 & 0x3FF) << 10) | uv1;
      *dstBot++ = 3 << 30 | ((y67 >> 16) << 10) | uv1;
    }

    // There should be at most 2 more pixels to process. Note that we don't
    // need to consider odd case as the buffer is always aligned to even.
    if (x < width) {
      u01 = *uSrc;
      v01 = *vSrc;
      y01 = *((uint32_t *)ySrcTop);
      y45 = *((uint32_t *)ySrcBot);
      uv0 = (u01 & 0x3FF) | ((v01 & 0x3FF) << 20);
      *dstTop++ = ((y01 & 0x3FF) << 10) | uv0;
      *dstTop++ = ((y01 >> 16) << 10) | uv0;
      *dstBot++ = ((y45 & 0x3FF) << 10) | uv0;
      *dstBot++ = ((y45 >> 16) << 10) | uv0;
    }

    srcY += srcYStride * 2;
    srcU += srcUStride;
    srcV += srcVStride;
    dst += dstStride * 2;
  }
}

static void convertYUV420Planar16ToYUV420Planar(
    uint8_t *dstY, uint8_t *dstU, uint8_t *dstV,
    const uint16_t *srcY, const uint16_t *srcU, const uint16_t *srcV,
    size_t srcYStride, size_t srcUStride, size_t srcVStride,
    size_t dstYStride, size_t dstUVStride,
    size_t width, size_t height, bool isMonochrome) {

  for (size_t y = 0; y < height; ++y) {
    for (size_t x = 0; x < width; ++x) {
      dstY[x] = (uint8_t)(srcY[x] >> 2);
    }

    srcY += srcYStride;
    dstY += dstYStride;
  }

  if (isMonochrome) {
    // Fill with neutral U/V values.
    for (size_t y = 0; y < (height + 1) / 2; ++y) {
      memset(dstV, NEUTRAL_UV_VALUE, (width + 1) / 2);
      memset(dstU, NEUTRAL_UV_VALUE, (width + 1) / 2);
      dstV += dstUVStride;
      dstU += dstUVStride;
    }
    return;
  }

  for (size_t y = 0; y < (height + 1) / 2; ++y) {
    for (size_t x = 0; x < (width + 1) / 2; ++x) {
      dstU[x] = (uint8_t)(srcU[x] >> 2);
      dstV[x] = (uint8_t)(srcV[x] >> 2);
    }

    srcU += srcUStride;
    srcV += srcVStride;
    dstU += dstUVStride;
    dstV += dstUVStride;
  }
}

void C2SoftGav1Dec::getVuiParams(const libgav1::DecoderBuffer *buffer) {
    VuiColorAspects vuiColorAspects;
    vuiColorAspects.primaries = buffer->color_primary;
@@ -841,22 +692,24 @@ bool C2SoftGav1Dec::outputBuffer(const std::shared_ptr<C2BlockPool> &pool,
    const uint16_t *srcV = (const uint16_t *)buffer->plane[2];

    if (format == HAL_PIXEL_FORMAT_RGBA_1010102) {
      convertYUV420Planar16ToY410(
          (uint32_t *)dstY, srcY, srcU, srcV, srcYStride / 2, srcUStride / 2,
          srcVStride / 2, dstYStride / sizeof(uint32_t), mWidth, mHeight);
        convertYUV420Planar16ToY410((uint32_t *)dstY, srcY, srcU, srcV, srcYStride / 2,
                                    srcUStride / 2, srcVStride / 2, dstYStride / sizeof(uint32_t),
                                    mWidth, mHeight);
    } else if (format == HAL_PIXEL_FORMAT_YCBCR_P010) {
        convertYUV420Planar16ToP010((uint16_t *)dstY, (uint16_t *)dstU, srcY, srcU, srcV,
                                    srcYStride / 2, srcUStride / 2, srcVStride / 2, dstYStride / 2,
                                    dstUVStride / 2, mWidth, mHeight, isMonochrome);
    } else {
      convertYUV420Planar16ToYUV420Planar(
          dstY, dstU, dstV, srcY, srcU, srcV, srcYStride / 2, srcUStride / 2,
          srcVStride / 2, dstYStride, dstUVStride, mWidth, mHeight,
          isMonochrome);
        convertYUV420Planar16ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride / 2,
                                    srcUStride / 2, srcVStride / 2, dstYStride, dstUVStride, mWidth,
                                    mHeight, isMonochrome);
    }
  } else {
    const uint8_t *srcY = (const uint8_t *)buffer->plane[0];
    const uint8_t *srcU = (const uint8_t *)buffer->plane[1];
    const uint8_t *srcV = (const uint8_t *)buffer->plane[2];
    copyOutputBufferToYV12Frame(
        dstY, dstU, dstV, srcY, srcU, srcV, srcYStride, srcUStride, srcVStride,
        dstYStride, dstUVStride, mWidth, mHeight, isMonochrome);
    convertYUV420Planar8ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride, srcUStride,
                               srcVStride, dstYStride, dstUVStride, mWidth, mHeight, isMonochrome);
  }
  finishWork(buffer->user_private_data, work, std::move(block));
  block = nullptr;
+11 −39
Original line number Diff line number Diff line
@@ -419,40 +419,6 @@ bool C2SoftMpeg4Dec::handleResChange(const std::unique_ptr<C2Work> &work) {
    return resChanged;
}

/* TODO: can remove temporary copy after library supports writing to display
 * buffer Y, U and V plane pointers using stride info. */
static void copyOutputBufferToYuvPlanarFrame(
        uint8_t *dstY, uint8_t *dstU, uint8_t *dstV, uint8_t *src,
        size_t dstYStride, size_t dstUVStride,
        size_t srcYStride, uint32_t width,
        uint32_t height) {
    size_t srcUVStride = srcYStride / 2;
    uint8_t *srcStart = src;

    size_t vStride = align(height, 16);
    for (size_t i = 0; i < height; ++i) {
         memcpy(dstY, src, width);
         src += srcYStride;
         dstY += dstYStride;
    }

    /* U buffer */
    src = srcStart + vStride * srcYStride;
    for (size_t i = 0; i < height / 2; ++i) {
         memcpy(dstU, src, width / 2);
         src += srcUVStride;
         dstU += dstUVStride;
    }

    /* V buffer */
    src = srcStart + vStride * srcYStride * 5 / 4;
    for (size_t i = 0; i < height / 2; ++i) {
         memcpy(dstV, src, width / 2);
         src += srcUVStride;
         dstV += dstUVStride;
    }
}

void C2SoftMpeg4Dec::process(
        const std::unique_ptr<C2Work> &work,
        const std::shared_ptr<C2BlockPool> &pool) {
@@ -636,11 +602,17 @@ void C2SoftMpeg4Dec::process(
        C2PlanarLayout layout = wView.layout();
        size_t dstYStride = layout.planes[C2PlanarLayout::PLANE_Y].rowInc;
        size_t dstUVStride = layout.planes[C2PlanarLayout::PLANE_U].rowInc;
        (void)copyOutputBufferToYuvPlanarFrame(
                outputBufferY, outputBufferU, outputBufferV,
                mOutputBuffer[mNumSamplesOutput & 1],
                dstYStride, dstUVStride,
                align(mWidth, 16), mWidth, mHeight);
        size_t srcYStride = align(mWidth, 16);
        size_t srcUStride = srcYStride / 2;
        size_t srcVStride = srcYStride / 2;
        size_t vStride = align(mHeight, 16);
        const uint8_t *srcY = (const uint8_t *)mOutputBuffer[mNumSamplesOutput & 1];
        const uint8_t *srcU = (const uint8_t *)srcY + vStride * srcYStride;
        const uint8_t *srcV = (const uint8_t *)srcY + vStride * srcYStride * 5 / 4;

        convertYUV420Planar8ToYV12(outputBufferY, outputBufferU, outputBufferV, srcY, srcU, srcV,
                                   srcYStride, srcUStride, srcVStride, dstYStride, dstUVStride,
                                   mWidth, mHeight);

        inPos += inSize - (size_t)tmpInSize;
        finishWork(workIndex, work);
Loading