size_t C2DColorConverter::calcSizeAlign(ColorConvertFormat format) {
    if (!isYUVSurface(format)) return 1; //no requirement

    switch (format) {
        case YCbCr420SP: //OR NV12
        case YCbCr420P:
        case NV12_2K:
          return ALIGN4K;
        default:
          ALOGE("unknown format passed for size alignment number");
          return 1;
    }
}
void* C2DColorConverter::getDummySurfaceDef(ColorConvertFormat format, size_t width, size_t height, bool isSource)
{
    if (isYUVSurface(format)) {
        C2D_YUV_SURFACE_DEF * surfaceDef = new C2D_YUV_SURFACE_DEF;
        surfaceDef->format = getC2DFormat(format);
        surfaceDef->width = width;
        surfaceDef->height = height;
        surfaceDef->plane0 = (void *)0xaaaaaaaa;
        surfaceDef->phys0 = (void *)0xaaaaaaaa;
        surfaceDef->stride0 = calcStride(format, width);
        surfaceDef->plane1 = (void *)0xaaaaaaaa;
        surfaceDef->phys1 = (void *)0xaaaaaaaa;
        surfaceDef->stride1 = calcStride(format, width);
        surfaceDef->stride2 = 0;

        if (format == YCbCr420P ||
            format == YCrCb420P) {
          printf("half stride for Cb Cr planes \n");
          surfaceDef->stride1 = calcStride(format, width) / 2;
          surfaceDef->phys2 = (void *)0xaaaaaaaa;
          surfaceDef->stride2 = calcStride(format, width) / 2;
        }
        mC2DCreateSurface(isSource ? &mSrcSurface : &mDstSurface, isSource ? C2D_SOURCE : C2D_TARGET,
                        (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY),
                        &(*surfaceDef));
        return ((void *)surfaceDef);
    } else {
        C2D_RGB_SURFACE_DEF * surfaceDef = new C2D_RGB_SURFACE_DEF;
        surfaceDef->format = getC2DFormat(format);
        surfaceDef->width = width;
        surfaceDef->height = height;
        surfaceDef->buffer = (void *)0xaaaaaaaa;
        surfaceDef->phys = (void *)0xaaaaaaaa;
        surfaceDef->stride = calcStride(format, width);
        mC2DCreateSurface(isSource ? &mSrcSurface : &mDstSurface, isSource ? C2D_SOURCE : C2D_TARGET,
                        (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY),
                        &(*surfaceDef));
        return ((void *)surfaceDef);
    }
}
int32_t C2DColorConverter::dumpOutput(char * filename, char mode) {
    int fd;
    size_t stride, sliceHeight;
    if (!filename) return -1;

    int flags = O_RDWR | O_CREAT;
    if (mode == 'a') {
      flags |= O_APPEND;
    }

    if ((fd = open(filename, flags)) < 0) {
        ALOGE("open dump file failed w/ errno %s", strerror(errno));
        return -1;
    }

    int ret = 0;
    if (isYUVSurface(mDstFormat)) {
      C2D_YUV_SURFACE_DEF * dstSurfaceDef = (C2D_YUV_SURFACE_DEF *)mDstSurfaceDef;
      uint8_t * base = (uint8_t *)dstSurfaceDef->plane0;
      stride = dstSurfaceDef->stride0;
      sliceHeight = dstSurfaceDef->height;
      /* dump luma */
      for (size_t i = 0; i < sliceHeight; i++) {
        ret = write(fd, base, mDstWidth); //will work only for the 420 ones
        if (ret < 0) goto cleanup;
        base += stride;
      }

      if (mDstFormat == YCbCr420P ||
          mDstFormat == YCrCb420P) {
          printf("Dump Cb and Cr separately for Planar\n");
          //dump Cb/Cr
          base = (uint8_t *)dstSurfaceDef->plane1;
          stride = dstSurfaceDef->stride1;
          for (size_t i = 0; i < sliceHeight/2;i++) { //will work only for the 420 ones
            ret = write(fd, base, mDstWidth/2);
            if (ret < 0) goto cleanup;
            base += stride;
          }

          //dump Cr/Cb
          base = (uint8_t *)dstSurfaceDef->plane2;
          stride = dstSurfaceDef->stride2;

          for (size_t i = 0; i < sliceHeight/2;i++) { //will work only for the 420 ones
            ret = write(fd, base, mDstWidth/2);
            if (ret < 0) goto cleanup;
            base += stride;
          }

      } else {
          /* dump chroma */
          base = (uint8_t *)dstSurfaceDef->plane1;
          stride = dstSurfaceDef->stride1;
          for (size_t i = 0; i < sliceHeight/2;i++) { //will work only for the 420 ones
            ret = write(fd, base, mDstWidth);
            if (ret < 0) goto cleanup;
            base += stride;
          }
      }
    } else {
      C2D_RGB_SURFACE_DEF * dstSurfaceDef = (C2D_RGB_SURFACE_DEF *)mDstSurfaceDef;
      uint8_t * base = (uint8_t *)dstSurfaceDef->buffer;
      stride = dstSurfaceDef->stride;
      sliceHeight = dstSurfaceDef->height;

      printf("rgb surface base is %p", base);
      printf("rgb surface dumpsslice height is %d\n", sliceHeight);
      printf("rgb surface dump stride is %d\n", stride);

      int bpp = 1; //bytes per pixel
      if (mDstFormat == RGB565) {
        bpp = 2;
      } else if (mDstFormat == RGBA8888) {
        bpp = 4;
      }

      int count = 0;
      for (size_t i = 0; i < sliceHeight; i++) {
        ret = write(fd, base, mDstWidth*bpp);
        if (ret < 0) {
          printf("write failed, count = %d\n", count);
          goto cleanup;
        }
        base += stride;
        count += stride;
      }
    }
 cleanup:
    if (ret < 0) {
      ALOGE("file write failed w/ errno %s", strerror(errno));
    }
    close(fd);
    return ret < 0 ? ret : 0;
}
int C2DColorConverter::convertC2D(int srcFd, void * srcData, int dstFd, void * dstData)
{
    C2D_STATUS ret;

    if (mError) {
        ALOGE("C2D library initialization failed\n");
        return mError;
    }

    if ((srcFd < 0) || (dstFd < 0) || (srcData == NULL) || (dstData == NULL)) {
        ALOGE("Incorrect input parameters\n");
        return -1;
    }

    if (isYUVSurface(mSrcFormat)) {
        ret = updateYUVSurfaceDef(srcFd, srcData, true);
    } else {
        ret = updateRGBSurfaceDef(srcFd, srcData, true);
    }

    if (ret != C2D_STATUS_OK) {
        ALOGE("Update src surface def failed\n");
        return -ret;
    }

    if (isYUVSurface(mDstFormat)) {
        ret = updateYUVSurfaceDef(dstFd, dstData, false);
    } else {
        ret = updateRGBSurfaceDef(dstFd, dstData, false);
    }

    if (ret != C2D_STATUS_OK) {
        ALOGE("Update dst surface def failed\n");
        return -ret;
    }

    mBlit.surface_id = mSrcSurface;
    ret = mC2DDraw(mDstSurface, C2D_TARGET_ROTATE_0, 0, 0, 0, &mBlit, 1);
    mC2DFinish(mDstSurface);

    bool unmappedSrcSuccess;
    if (isYUVSurface(mSrcFormat)) {
        unmappedSrcSuccess = unmapGPUAddr((uint32_t)((C2D_YUV_SURFACE_DEF *)mSrcSurfaceDef)->phys0);
    } else {
        unmappedSrcSuccess = unmapGPUAddr((uint32_t)((C2D_RGB_SURFACE_DEF *)mSrcSurfaceDef)->phys);
    }

    bool unmappedDstSuccess;
    if (isYUVSurface(mDstFormat)) {
        unmappedDstSuccess = unmapGPUAddr((uint32_t)((C2D_YUV_SURFACE_DEF *)mDstSurfaceDef)->phys0);
    } else {
        unmappedDstSuccess = unmapGPUAddr((uint32_t)((C2D_RGB_SURFACE_DEF *)mDstSurfaceDef)->phys);
    }

    if (ret != C2D_STATUS_OK) {
        ALOGE("C2D Draw failed\n");
        return -ret; //c2d err values are positive
    } else {
        if (!unmappedSrcSuccess || !unmappedDstSuccess) {
            ALOGE("unmapping GPU address failed\n");
            return -1;
        }
        return ret;
    }
}