// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/renderers/paint_canvas_video_renderer.h"

#include <GLES3/gl3.h>
#include <limits>

#include "base/bind.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "cc/paint/paint_canvas.h"
#include "cc/paint/paint_flags.h"
#include "cc/paint/paint_image.h"
#include "cc/paint/paint_image_builder.h"
#include "components/viz/common/gpu/context_provider.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/context_support.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/common/capabilities.h"
#include "gpu/command_buffer/common/mailbox_holder.h"
#include "media/base/data_buffer.h"
#include "media/base/video_frame.h"
#include "third_party/libyuv/include/libyuv.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/core/SkImageGenerator.h"
#include "third_party/skia/include/gpu/GrBackendSurface.h"
#include "third_party/skia/include/gpu/GrContext.h"
#include "third_party/skia/include/gpu/gl/GrGLTypes.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/skia_util.h"

// Skia internal format depends on a platform. On Android it is ABGR, on others
// it is ARGB.
#if SK_B32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_R32_SHIFT == 16 && \
    SK_A32_SHIFT == 24
#define LIBYUV_I420_TO_ARGB libyuv::I420ToARGB
#define LIBYUV_I422_TO_ARGB libyuv::I422ToARGB
#define LIBYUV_I444_TO_ARGB libyuv::I444ToARGB
#define LIBYUV_I420ALPHA_TO_ARGB libyuv::I420AlphaToARGB
#define LIBYUV_J420_TO_ARGB libyuv::J420ToARGB
#define LIBYUV_H420_TO_ARGB libyuv::H420ToARGB
#define LIBYUV_I010_TO_ARGB libyuv::I010ToARGB
#define LIBYUV_H010_TO_ARGB libyuv::H010ToARGB
#define LIBYUV_NV12_TO_ARGB libyuv::NV12ToARGB
#elif SK_R32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_B32_SHIFT == 16 && \
    SK_A32_SHIFT == 24
#define LIBYUV_I420_TO_ARGB libyuv::I420ToABGR
#define LIBYUV_I422_TO_ARGB libyuv::I422ToABGR
#define LIBYUV_I444_TO_ARGB libyuv::I444ToABGR
#define LIBYUV_I420ALPHA_TO_ARGB libyuv::I420AlphaToABGR
#define LIBYUV_J420_TO_ARGB libyuv::J420ToABGR
#define LIBYUV_H420_TO_ARGB libyuv::H420ToABGR
#define LIBYUV_I010_TO_ARGB libyuv::I010ToABGR
#define LIBYUV_H010_TO_ARGB libyuv::H010ToABGR
#define LIBYUV_NV12_TO_ARGB libyuv::NV12ToABGR
#else
#error Unexpected Skia ARGB_8888 layout!
#endif

namespace media {

namespace {

// This class keeps the last image drawn.
// We delete the temporary resource if it is not used for 3 seconds.
const int kTemporaryResourceDeletionDelay = 3;  // Seconds;

class SyncTokenClientImpl : public VideoFrame::SyncTokenClient {
 public:
  explicit SyncTokenClientImpl(gpu::gles2::GLES2Interface* gl) : gl_(gl) {}
  ~SyncTokenClientImpl() override = default;
  void GenerateSyncToken(gpu::SyncToken* sync_token) override {
    gl_->GenSyncTokenCHROMIUM(sync_token->GetData());
  }
  void WaitSyncToken(const gpu::SyncToken& sync_token) override {
    gl_->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
  }

 private:
  gpu::gles2::GLES2Interface* gl_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(SyncTokenClientImpl);
};

sk_sp<SkImage> YUVGrBackendTexturesToSkImage(
    GrContext* gr_context,
    gfx::ColorSpace video_color_space,
    VideoPixelFormat video_format,
    GrBackendTexture* yuv_textures,
    GrBackendTexture* result_texture = nullptr) {
  // TODO(hubbe): This should really default to rec709.
  // https://crbug.com/828599
  SkYUVColorSpace color_space = kRec601_SkYUVColorSpace;
  video_color_space.ToSkYUVColorSpace(&color_space);

  switch (video_format) {
    case PIXEL_FORMAT_NV12:
      if (result_texture) {
        return SkImage::MakeFromNV12TexturesCopyWithExternalBackend(
            gr_context, color_space, yuv_textures, kTopLeft_GrSurfaceOrigin,
            result_texture[0]);
      } else {
        return SkImage::MakeFromNV12TexturesCopy(
            gr_context, color_space, yuv_textures, kTopLeft_GrSurfaceOrigin);
      }
    case PIXEL_FORMAT_I420:
      if (result_texture) {
        return SkImage::MakeFromYUVTexturesCopyWithExternalBackend(
            gr_context, color_space, yuv_textures, kTopLeft_GrSurfaceOrigin,
            result_texture[0]);
      } else {
        return SkImage::MakeFromYUVTexturesCopy(
            gr_context, color_space, yuv_textures, kTopLeft_GrSurfaceOrigin);
      }
    default:
      NOTREACHED();
      return nullptr;
  }
}

static constexpr size_t kNumYUVPlanes = 3;
struct YUVPlaneTextureInfo {
  GrGLTextureInfo texture = {0, 0};
  GLint minFilter = 0;
  GLint magFilter = 0;
};
using YUVTexturesInfo = std::array<YUVPlaneTextureInfo, kNumYUVPlanes>;

YUVTexturesInfo GetYUVTexturesInfo(const VideoFrame* video_frame,
                                   viz::ContextProvider* context_provider) {
  YUVTexturesInfo yuv_textures_info;

  gpu::gles2::GLES2Interface* gl = context_provider->ContextGL();
  DCHECK(gl);
  // TODO(bsalomon): Use GL_RGB8 once Skia supports it.
  // skbug.com/7533
  GrGLenum skia_texture_format =
      video_frame->format() == PIXEL_FORMAT_NV12 ? GL_RGBA8 : GL_R8_EXT;
  for (size_t i = 0; i < video_frame->NumTextures(); ++i) {
    // Get the texture from the mailbox and wrap it in a GrTexture.
    const gpu::MailboxHolder& mailbox_holder = video_frame->mailbox_holder(i);
    DCHECK(mailbox_holder.texture_target == GL_TEXTURE_2D ||
           mailbox_holder.texture_target == GL_TEXTURE_EXTERNAL_OES ||
           mailbox_holder.texture_target == GL_TEXTURE_RECTANGLE_ARB)
        << "Unsupported texture target " << std::hex << std::showbase
        << mailbox_holder.texture_target;
    gl->WaitSyncTokenCHROMIUM(mailbox_holder.sync_token.GetConstData());
    yuv_textures_info[i].texture.fID =
        gl->CreateAndConsumeTextureCHROMIUM(mailbox_holder.mailbox.name);
    yuv_textures_info[i].texture.fTarget = mailbox_holder.texture_target;
    yuv_textures_info[i].texture.fFormat = skia_texture_format;

    gl->BindTexture(mailbox_holder.texture_target,
                    yuv_textures_info[i].texture.fID);
    gl->GetTexParameteriv(mailbox_holder.texture_target, GL_TEXTURE_MIN_FILTER,
                          &yuv_textures_info[i].minFilter);
    gl->GetTexParameteriv(mailbox_holder.texture_target, GL_TEXTURE_MAG_FILTER,
                          &yuv_textures_info[i].magFilter);
    // TODO(dcastagna): avoid this copy once Skia supports native textures
    // with a GL_TEXTURE_RECTANGLE_ARB texture target.
    // crbug.com/505026
    if (mailbox_holder.texture_target == GL_TEXTURE_RECTANGLE_ARB) {
      unsigned texture_copy = 0;
      gl->GenTextures(1, &texture_copy);
      DCHECK(texture_copy);
      gl->BindTexture(GL_TEXTURE_2D, texture_copy);
      gl->CopyTextureCHROMIUM(yuv_textures_info[i].texture.fID, 0,
                              GL_TEXTURE_2D, texture_copy, 0, GL_RGB,
                              GL_UNSIGNED_BYTE, false, true, false);

      gl->DeleteTextures(1, &yuv_textures_info[i].texture.fID);
      yuv_textures_info[i].texture.fID = texture_copy;
      yuv_textures_info[i].texture.fTarget = GL_TEXTURE_2D;
    }
  }

  return yuv_textures_info;
}

void DeleteYUVTextures(const VideoFrame* video_frame,
                       viz::ContextProvider* context_provider,
                       const YUVTexturesInfo& yuv_textures_info) {
  gpu::gles2::GLES2Interface* gl = context_provider->ContextGL();
  DCHECK(gl);

  for (size_t i = 0; i < video_frame->NumTextures(); ++i) {
    gl->BindTexture(yuv_textures_info[i].texture.fTarget,
                    yuv_textures_info[i].texture.fID);
    gl->TexParameteri(yuv_textures_info[i].texture.fTarget,
                      GL_TEXTURE_MIN_FILTER, yuv_textures_info[i].minFilter);
    gl->TexParameteri(yuv_textures_info[i].texture.fTarget,
                      GL_TEXTURE_MAG_FILTER, yuv_textures_info[i].magFilter);
    gl->DeleteTextures(1, &yuv_textures_info[i].texture.fID);
  }
}

sk_sp<SkImage> NewSkImageFromVideoFrameYUVTextures(
    const VideoFrame* video_frame,
    viz::ContextProvider* context_provider) {
  DCHECK(video_frame->HasTextures());
  GrContext* gr_context = context_provider->GrContext();
  DCHECK(gr_context);
  // TODO: We should compare the DCHECK vs when UpdateLastImage calls this
  // function. (crbug.com/674185)
  DCHECK(video_frame->format() == PIXEL_FORMAT_I420 ||
         video_frame->format() == PIXEL_FORMAT_NV12);

  gfx::Size ya_tex_size = video_frame->coded_size();
  gfx::Size uv_tex_size((ya_tex_size.width() + 1) / 2,
                        (ya_tex_size.height() + 1) / 2);

  YUVTexturesInfo yuv_textures_info =
      GetYUVTexturesInfo(video_frame, context_provider);

  GrBackendTexture yuv_textures[3] = {
      GrBackendTexture(ya_tex_size.width(), ya_tex_size.height(),
                       GrMipMapped::kNo, yuv_textures_info[0].texture),
      GrBackendTexture(uv_tex_size.width(), uv_tex_size.height(),
                       GrMipMapped::kNo, yuv_textures_info[1].texture),
      GrBackendTexture(uv_tex_size.width(), uv_tex_size.height(),
                       GrMipMapped::kNo, yuv_textures_info[2].texture),
  };

  sk_sp<SkImage> img =
      YUVGrBackendTexturesToSkImage(gr_context, video_frame->ColorSpace(),
                                    video_frame->format(), yuv_textures);
  gr_context->flush();

  DeleteYUVTextures(video_frame, context_provider, yuv_textures_info);

  return img;
}

sk_sp<SkImage> NewSkImageFromVideoFrameYUVTexturesWithExternalBackend(
    const VideoFrame* video_frame,
    viz::ContextProvider* context_provider,
    unsigned int texture_target,
    unsigned int texture_id) {
  DCHECK(video_frame->HasTextures());
  GrContext* gr_context = context_provider->GrContext();
  DCHECK(gr_context);
  // TODO: We should compare the DCHECK vs when UpdateLastImage calls this
  // function. (https://crbug.com/674185)
  DCHECK(video_frame->format() == PIXEL_FORMAT_I420 ||
         video_frame->format() == PIXEL_FORMAT_NV12);

  gfx::Size ya_tex_size = video_frame->coded_size();
  gfx::Size uv_tex_size((ya_tex_size.width() + 1) / 2,
                        (ya_tex_size.height() + 1) / 2);

  GrGLTextureInfo backend_texture{};

  YUVTexturesInfo yuv_textures_info =
      GetYUVTexturesInfo(video_frame, context_provider);

  GrBackendTexture yuv_textures[3] = {
      GrBackendTexture(ya_tex_size.width(), ya_tex_size.height(),
                       GrMipMapped::kNo, yuv_textures_info[0].texture),
      GrBackendTexture(uv_tex_size.width(), uv_tex_size.height(),
                       GrMipMapped::kNo, yuv_textures_info[1].texture),
      GrBackendTexture(uv_tex_size.width(), uv_tex_size.height(),
                       GrMipMapped::kNo, yuv_textures_info[2].texture),
  };
  backend_texture.fID = texture_id;
  backend_texture.fTarget = texture_target;
  backend_texture.fFormat = GL_RGBA8;
  GrBackendTexture result_texture[1] = {
      GrBackendTexture(video_frame->coded_size().width(),
                       video_frame->coded_size().height(), GrMipMapped::kNo,
                       backend_texture),
  };

  sk_sp<SkImage> img = YUVGrBackendTexturesToSkImage(
      gr_context, video_frame->ColorSpace(), video_frame->format(),
      yuv_textures, result_texture);
  gr_context->flush();

  DeleteYUVTextures(video_frame, context_provider, yuv_textures_info);

  return img;
}

// Creates a SkImage from a |video_frame| backed by native resources.
// The SkImage will take ownership of the underlying resource.
sk_sp<SkImage> NewSkImageFromVideoFrameNative(
    VideoFrame* video_frame,
    viz::ContextProvider* context_provider,
    bool allow_wrap_texture,
    bool* wrapped_video_frame_texture) {
  DCHECK(PIXEL_FORMAT_ARGB == video_frame->format() ||
         PIXEL_FORMAT_XRGB == video_frame->format() ||
         PIXEL_FORMAT_RGB24 == video_frame->format() ||
         PIXEL_FORMAT_RGB32 == video_frame->format() ||
         PIXEL_FORMAT_NV12 == video_frame->format() ||
         PIXEL_FORMAT_UYVY == video_frame->format())
      << "Format: " << (int)video_frame->format();

  const gpu::MailboxHolder& mailbox_holder = video_frame->mailbox_holder(0);
  DCHECK(mailbox_holder.texture_target == GL_TEXTURE_2D ||
         mailbox_holder.texture_target == GL_TEXTURE_RECTANGLE_ARB ||
         mailbox_holder.texture_target == GL_TEXTURE_EXTERNAL_OES)
      << "Unsupported texture target " << std::hex << std::showbase
      << mailbox_holder.texture_target;

  gpu::gles2::GLES2Interface* gl = context_provider->ContextGL();
  unsigned source_texture = 0;
  gfx::ColorSpace color_space_for_skia;
  *wrapped_video_frame_texture =
      mailbox_holder.texture_target == GL_TEXTURE_2D && allow_wrap_texture;
  if (*wrapped_video_frame_texture) {
    // Fast path where we can avoid a copy, by having last_image_ directly wrap
    // the VideoFrame texture.
    gl->WaitSyncTokenCHROMIUM(mailbox_holder.sync_token.GetConstData());
    source_texture =
        gl->CreateAndConsumeTextureCHROMIUM(mailbox_holder.mailbox.name);
    color_space_for_skia = video_frame->ColorSpace();
  } else {
    // TODO(dcastagna): At the moment Skia doesn't support targets different
    // than GL_TEXTURE_2D.  Avoid this copy once
    // https://code.google.com/p/skia/issues/detail?id=3868 is addressed, when
    // we allow wrapping.
    gl->GenTextures(1, &source_texture);
    DCHECK(source_texture);
    gl->BindTexture(GL_TEXTURE_2D, source_texture);
    PaintCanvasVideoRenderer::CopyVideoFrameSingleTextureToGLTexture(
        gl, video_frame, GL_TEXTURE_2D, source_texture, GL_RGBA, GL_RGBA,
        GL_UNSIGNED_BYTE, 0, false, false);
  }
  GrGLTextureInfo source_texture_info;
  source_texture_info.fID = source_texture;
  source_texture_info.fTarget = GL_TEXTURE_2D;
  // TODO(bsalomon): GrGLTextureInfo::fFormat and SkColorType passed to SkImage
  // factory should reflect video_frame->format(). Update once Skia supports
  // GL_RGB.
  // skbug.com/7533
  source_texture_info.fFormat = GL_RGBA8_OES;
  GrBackendTexture source_backend_texture(
      video_frame->coded_size().width(), video_frame->coded_size().height(),
      GrMipMapped::kNo, source_texture_info);
  return SkImage::MakeFromAdoptedTexture(
      context_provider->GrContext(), source_backend_texture,
      kTopLeft_GrSurfaceOrigin, kRGBA_8888_SkColorType, kPremul_SkAlphaType,
      color_space_for_skia.ToSkColorSpace());
}

void VideoFrameCopyTextureOrSubTexture(gpu::gles2::GLES2Interface* gl,
                                       const gfx::Size& coded_size,
                                       const gfx::Rect& visible_rect,
                                       GLuint source_texture,
                                       unsigned int target,
                                       unsigned int texture,
                                       unsigned int internal_format,
                                       unsigned int format,
                                       unsigned int type,
                                       int level,
                                       bool premultiply_alpha,
                                       bool flip_y) {
  // The video is stored in a unmultiplied format, so premultiply if necessary.
  // Application itself needs to take care of setting the right |flip_y|
  // value down to get the expected result.
  // "flip_y == true" means to reverse the video orientation while
  // "flip_y == false" means to keep the intrinsic orientation.
  if (visible_rect != gfx::Rect(coded_size)) {
    // Must reallocate the destination texture and copy only a sub-portion.

    // There should always be enough data in the source texture to
    // cover this copy.
    DCHECK_LE(visible_rect.width(), coded_size.width());
    DCHECK_LE(visible_rect.height(), coded_size.height());

    gl->BindTexture(target, texture);
    gl->TexImage2D(target, level, internal_format, visible_rect.width(),
                   visible_rect.height(), 0, format, type, nullptr);
    gl->CopySubTextureCHROMIUM(source_texture, 0, target, texture, level, 0, 0,
                               visible_rect.x(), visible_rect.y(),
                               visible_rect.width(), visible_rect.height(),
                               flip_y, premultiply_alpha, false);

  } else {
    gl->CopyTextureCHROMIUM(source_texture, 0, target, texture, level,
                            internal_format, type, flip_y, premultiply_alpha,
                            false);
  }
}

void OnQueryDone(scoped_refptr<VideoFrame> video_frame,
                 gpu::gles2::GLES2Interface* gl,
                 unsigned query_id) {
  gl->DeleteQueriesEXT(1, &query_id);
  // |video_frame| is dropped here.
}

void SynchronizeVideoFrameRead(scoped_refptr<VideoFrame> video_frame,
                               gpu::gles2::GLES2Interface* gl,
                               gpu::ContextSupport* context_support) {
  DCHECK(gl);
  SyncTokenClientImpl client(gl);
  video_frame->UpdateReleaseSyncToken(&client);

  if (video_frame->metadata()->IsTrue(
          VideoFrameMetadata::READ_LOCK_FENCES_ENABLED)) {
    // |video_frame| must be kept alive during read operations.
    DCHECK(context_support);
    unsigned query_id = 0;
    gl->GenQueriesEXT(1, &query_id);
    DCHECK(query_id);
    gl->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, query_id);
    gl->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM);
    context_support->SignalQuery(
        query_id, base::BindOnce(&OnQueryDone, video_frame, gl, query_id));
  }
}

}  // anonymous namespace

// Generates an RGB image from a VideoFrame. Convert YUV to RGB plain on GPU.
class VideoImageGenerator : public cc::PaintImageGenerator {
 public:
  VideoImageGenerator(scoped_refptr<VideoFrame> frame)
      : cc::PaintImageGenerator(
            SkImageInfo::MakeN32Premul(frame->visible_rect().width(),
                                       frame->visible_rect().height())),
        frame_(std::move(frame)) {
    DCHECK(!frame_->HasTextures());
  }
  ~VideoImageGenerator() override = default;

  bool IsEligibleForAcceleratedDecoding() const override { return false; }

  sk_sp<SkData> GetEncodedData() const override { return nullptr; }

  bool GetPixels(const SkImageInfo& info,
                 void* pixels,
                 size_t row_bytes,
                 size_t frame_index,
                 cc::PaintImage::GeneratorClientId client_id,
                 uint32_t lazy_pixel_ref) override {
    DCHECK_EQ(frame_index, 0u);

    // If skia couldn't do the YUV conversion on GPU, we will on CPU.
    PaintCanvasVideoRenderer::ConvertVideoFrameToRGBPixels(frame_.get(), pixels,
                                                           row_bytes);
    return true;
  }

  bool QueryYUVA8(SkYUVASizeInfo* sizeInfo,
                  SkYUVAIndex indices[SkYUVAIndex::kIndexCount],
                  SkYUVColorSpace* color_space) const override {
    // Temporarily disabling this path to avoid creating YUV ImageData in
    // GpuImageDecodeCache.
    // TODO(crbug.com/921636): Restore the code below once YUV rendering support
    // is added for VideoImageGenerator.
    return false;
#if 0
    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
        // path in this case.
        frame_->format() == PIXEL_FORMAT_I420A) {
      return false;
    }

    if (color_space) {
      if (!frame_->ColorSpace().ToSkYUVColorSpace(color_space)) {
        // TODO(hubbe): This really should default to rec709
        // https://crbug.com/828599
        *color_space = kRec601_SkYUVColorSpace;
      }
    }

    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()));
      sizeInfo->fSizes[plane].set(size.width(), size.height());
      sizeInfo->fWidthBytes[plane] = size.width();
    }
    sizeInfo->fSizes[VideoFrame::kAPlane] = SkISize::MakeEmpty();
    sizeInfo->fWidthBytes[VideoFrame::kAPlane] = 0;

    indices[SkYUVAIndex::kY_Index] = {VideoFrame::kYPlane, SkColorChannel::kR};
    indices[SkYUVAIndex::kU_Index] = {VideoFrame::kUPlane, SkColorChannel::kR};
    indices[SkYUVAIndex::kV_Index] = {VideoFrame::kVPlane, SkColorChannel::kR};
    indices[SkYUVAIndex::kA_Index] = {-1, SkColorChannel::kR};

    return true;
#endif
  }

  bool GetYUVA8Planes(const SkYUVASizeInfo& sizeInfo,
                      const SkYUVAIndex indices[SkYUVAIndex::kIndexCount],
                      void* planes[4],
                      size_t frame_index,
                      uint32_t lazy_pixel_ref) override {
    DCHECK_EQ(frame_index, 0u);

    media::VideoPixelFormat format = frame_->format();
    DCHECK(media::IsYuvPlanar(format) && format != PIXEL_FORMAT_I420A);

    for (int i = 0; i <= VideoFrame::kVPlane; ++i) {
      if (sizeInfo.fSizes[i].isEmpty() || !sizeInfo.fWidthBytes[i]) {
        return false;
      }
    }
    if (!sizeInfo.fSizes[VideoFrame::kAPlane].isEmpty() ||
        sizeInfo.fWidthBytes[VideoFrame::kAPlane]) {
      return false;
    }
    int numPlanes;
    if (!SkYUVAIndex::AreValidIndices(indices, &numPlanes) || numPlanes != 3) {
      return false;
    }

    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_I422) ? 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<char*>(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;
        }
      }
    }
    return true;
  }

 private:
  scoped_refptr<VideoFrame> frame_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(VideoImageGenerator);
};

PaintCanvasVideoRenderer::PaintCanvasVideoRenderer()
    : last_image_deleting_timer_(
          FROM_HERE,
          base::TimeDelta::FromSeconds(kTemporaryResourceDeletionDelay),
          this,
          &PaintCanvasVideoRenderer::ResetCache),
      renderer_stable_id_(cc::PaintImage::GetNextId()) {}

PaintCanvasVideoRenderer::~PaintCanvasVideoRenderer() {
  ResetCache();
}

void PaintCanvasVideoRenderer::Paint(scoped_refptr<VideoFrame> video_frame,
                                     cc::PaintCanvas* canvas,
                                     const gfx::RectF& dest_rect,
                                     cc::PaintFlags& flags,
                                     VideoTransformation video_transformation,
                                     viz::ContextProvider* context_provider) {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (flags.getAlpha() == 0) {
    return;
  }

  SkRect dest;
  dest.set(dest_rect.x(), dest_rect.y(), dest_rect.right(), dest_rect.bottom());

  // Paint black rectangle if there isn't a frame available or the
  // frame has an unexpected format.
  if (!video_frame.get() || video_frame->natural_size().IsEmpty() ||
      !(media::IsYuvPlanar(video_frame->format()) ||
        video_frame->format() == media::PIXEL_FORMAT_Y16 ||
        video_frame->HasTextures())) {
    cc::PaintFlags black_with_alpha_flags;
    black_with_alpha_flags.setAlpha(flags.getAlpha());
    canvas->drawRect(dest, black_with_alpha_flags);
    canvas->flush();
    return;
  }

  // Don't allow wrapping the VideoFrame texture, as we want to be able to cache
  // the PaintImage, to avoid redundant readbacks if the canvas is software.
  if (!UpdateLastImage(video_frame, context_provider,
                       false /* allow_wrap_texture */))
    return;

  cc::PaintFlags video_flags;
  video_flags.setAlpha(flags.getAlpha());
  video_flags.setBlendMode(flags.getBlendMode());
  video_flags.setFilterQuality(flags.getFilterQuality());

  const bool need_rotation = video_transformation.rotation != VIDEO_ROTATION_0;
  const bool need_scaling =
      dest_rect.size() != gfx::SizeF(last_image_.width(), last_image_.height());
  const bool need_translation = !dest_rect.origin().IsOrigin();
  // TODO(tmathmeyer): apply horizontal / vertical mirroring if needed.
  bool need_transform = need_rotation || need_scaling || need_translation;
  if (need_transform) {
    canvas->save();
    canvas->translate(
        SkFloatToScalar(dest_rect.x() + (dest_rect.width() * 0.5f)),
        SkFloatToScalar(dest_rect.y() + (dest_rect.height() * 0.5f)));
    SkScalar angle = SkFloatToScalar(0.0f);
    switch (video_transformation.rotation) {
      case VIDEO_ROTATION_0:
        break;
      case VIDEO_ROTATION_90:
        angle = SkFloatToScalar(90.0f);
        break;
      case VIDEO_ROTATION_180:
        angle = SkFloatToScalar(180.0f);
        break;
      case VIDEO_ROTATION_270:
        angle = SkFloatToScalar(270.0f);
        break;
    }
    canvas->rotate(angle);

    gfx::SizeF rotated_dest_size = dest_rect.size();
    if (video_transformation.rotation == VIDEO_ROTATION_90 ||
        video_transformation.rotation == VIDEO_ROTATION_270) {
      rotated_dest_size =
          gfx::SizeF(rotated_dest_size.height(), rotated_dest_size.width());
    }
    canvas->scale(
        SkFloatToScalar(rotated_dest_size.width() / last_image_.width()),
        SkFloatToScalar(rotated_dest_size.height() / last_image_.height()));
    canvas->translate(-SkFloatToScalar(last_image_.width() * 0.5f),
                      -SkFloatToScalar(last_image_.height() * 0.5f));
  }

  // This is a workaround for crbug.com/524717. A texture backed image is not
  // safe to access on another thread or GL context. So if we're drawing into a
  // recording canvas we read the texture back into CPU memory and record that
  // sw image into the SkPicture. The long term solution is for Skia to provide
  // a SkPicture filter that makes a picture safe for multiple CPU raster
  // threads. (skbug.com/4321).
  cc::PaintImage image = last_image_;
  if (canvas->imageInfo().colorType() == kUnknown_SkColorType) {
    sk_sp<SkImage> non_texture_image =
        last_image_.GetSkImage()->makeNonTextureImage();
    image =
        cc::PaintImageBuilder::WithProperties(last_image_)
            .set_image(std::move(non_texture_image), last_image_.content_id())
            .TakePaintImage();
  }
  canvas->drawImage(image, 0, 0, &video_flags);

  if (need_transform)
    canvas->restore();
  // Make sure to flush so we can remove the videoframe from the generator.
  canvas->flush();

  if (video_frame->HasTextures()) {
    // Synchronize |video_frame| with the read operations in UpdateLastImage(),
    // which are triggered by canvas->flush().
    SynchronizeVideoFrameRead(std::move(video_frame),
                              context_provider->ContextGL(),
                              context_provider->ContextSupport());
  }
  // Because we are not retaining a reference to the VideoFrame, it would be
  // invalid for last_image_ to directly wrap its texture(s), as they will be
  // recycled.
  DCHECK(!last_image_wraps_video_frame_texture_);
}

void PaintCanvasVideoRenderer::Copy(scoped_refptr<VideoFrame> video_frame,
                                    cc::PaintCanvas* canvas,
                                    viz::ContextProvider* context_provider) {
  cc::PaintFlags flags;
  flags.setBlendMode(SkBlendMode::kSrc);
  flags.setFilterQuality(kLow_SkFilterQuality);

  auto dest_rect = gfx::RectF(gfx::SizeF(video_frame->visible_rect().size()));
  Paint(std::move(video_frame), canvas, dest_rect, flags,
        media::kNoTransformation, context_provider);
}

namespace {

// libyuv doesn't support all 9-, 10- nor 12-bit pixel formats yet. This
// function creates a regular 8-bit video frame which we can give to libyuv.
scoped_refptr<VideoFrame> DownShiftHighbitVideoFrame(
    const VideoFrame* video_frame) {
  VideoPixelFormat format;
  switch (video_frame->format()) {
    case PIXEL_FORMAT_YUV420P12:
    case PIXEL_FORMAT_YUV420P9:
      format = PIXEL_FORMAT_I420;
      break;

    case PIXEL_FORMAT_YUV422P12:
    case PIXEL_FORMAT_YUV422P10:
    case PIXEL_FORMAT_YUV422P9:
      format = PIXEL_FORMAT_I422;
      break;

    case PIXEL_FORMAT_YUV444P12:
    case PIXEL_FORMAT_YUV444P10:
    case PIXEL_FORMAT_YUV444P9:
      format = PIXEL_FORMAT_I444;
      break;

    default:
      NOTREACHED();
      return nullptr;
  }
  const int shift = video_frame->BitDepth() - 8;
  scoped_refptr<VideoFrame> ret = VideoFrame::CreateFrame(
      format, video_frame->coded_size(), video_frame->visible_rect(),
      video_frame->natural_size(), video_frame->timestamp());

  ret->set_color_space(video_frame->ColorSpace());
  // Copy all metadata.
  // (May be enough to copy color space)
  ret->metadata()->MergeMetadataFrom(video_frame->metadata());

  for (int plane = VideoFrame::kYPlane; plane <= VideoFrame::kVPlane; ++plane) {
    int width = ret->row_bytes(plane);
    const uint16_t* src =
        reinterpret_cast<const uint16_t*>(video_frame->data(plane));
    uint8_t* dst = ret->data(plane);
    for (int row = 0; row < video_frame->rows(plane); row++) {
      for (int x = 0; x < width; x++) {
        dst[x] = src[x] >> shift;
      }
      src += video_frame->stride(plane) / 2;
      dst += ret->stride(plane);
    }
  }
  return ret;
}

// Converts 16-bit data to |out| buffer of specified GL |type|.
// When the |format| is RGBA, the converted value is fed as luminance.
void FlipAndConvertY16(const VideoFrame* video_frame,
                       uint8_t* out,
                       unsigned format,
                       unsigned type,
                       bool flip_y,
                       size_t output_row_bytes) {
  const uint8_t* row_head = video_frame->visible_data(0);
  const size_t stride = video_frame->stride(0);
  const int height = video_frame->visible_rect().height();
  for (int i = 0; i < height; ++i, row_head += stride) {
    uint8_t* out_row_head = flip_y ? out + output_row_bytes * (height - i - 1)
                                   : out + output_row_bytes * i;
    const uint16_t* row = reinterpret_cast<const uint16_t*>(row_head);
    const uint16_t* row_end = row + video_frame->visible_rect().width();
    if (type == GL_FLOAT) {
      float* out_row = reinterpret_cast<float*>(out_row_head);
      if (format == GL_RGBA) {
        while (row < row_end) {
          float gray_value = *row++ / 65535.f;
          *out_row++ = gray_value;
          *out_row++ = gray_value;
          *out_row++ = gray_value;
          *out_row++ = 1.0f;
        }
        continue;
      } else if (format == GL_RED) {
        while (row < row_end)
          *out_row++ = *row++ / 65535.f;
        continue;
      }
      // For other formats, hit NOTREACHED below.
    } else if (type == GL_UNSIGNED_BYTE) {
      // We take the upper 8 bits of 16-bit data and convert it as luminance to
      // ARGB.  We loose the precision here, but it is important not to render
      // Y16 as RG_88.  To get the full precision use float textures with WebGL1
      // and e.g. R16UI or R32F textures with WebGL2.
      DCHECK_EQ(static_cast<unsigned>(GL_RGBA), format);
      uint32_t* rgba = reinterpret_cast<uint32_t*>(out_row_head);
      while (row < row_end) {
        uint32_t gray_value = *row++ >> 8;
        *rgba++ = SkColorSetRGB(gray_value, gray_value, gray_value);
      }
      continue;
    }
    NOTREACHED() << "Unsupported Y16 conversion for format: 0x" << std::hex
                 << format << " and type: 0x" << std::hex << type;
  }
}

// Common functionality of PaintCanvasVideoRenderer's TexImage2D and
// TexSubImage2D. Allocates a buffer required for conversion and converts
// |frame| content to desired |format|. Returns true if calling glTex(Sub)Image
// is supported for provided |frame| format and parameters.
bool TexImageHelper(VideoFrame* frame,
                    unsigned format,
                    unsigned type,
                    bool flip_y,
                    scoped_refptr<DataBuffer>* temp_buffer) {
  unsigned output_bytes_per_pixel = 0;
  switch (frame->format()) {
    case PIXEL_FORMAT_Y16:
      // Converting single component unsigned short here to FLOAT luminance.
      switch (format) {
        case GL_RGBA:
          if (type == GL_FLOAT) {
            output_bytes_per_pixel = 4 * sizeof(GLfloat);
            break;
          }
          return false;
        case GL_RED:
          if (type == GL_FLOAT) {
            output_bytes_per_pixel = sizeof(GLfloat);
            break;
          }
          return false;
        default:
          return false;
      }
      break;
    default:
      return false;
  }

  size_t output_row_bytes =
      frame->visible_rect().width() * output_bytes_per_pixel;
  *temp_buffer =
      new DataBuffer(output_row_bytes * frame->visible_rect().height());
  FlipAndConvertY16(frame, (*temp_buffer)->writable_data(), format, type,
                    flip_y, output_row_bytes);
  return true;
}

// Upload the |frame| data to temporary texture of |temp_format|,
// |temp_internalformat| and |temp_type| and then copy intermediate texture
// subimage to destination |texture|. The destination |texture| is bound to the
// |target| before the call.
void TextureSubImageUsingIntermediate(unsigned target,
                                      unsigned texture,
                                      gpu::gles2::GLES2Interface* gl,
                                      VideoFrame* frame,
                                      int temp_internalformat,
                                      unsigned temp_format,
                                      unsigned temp_type,
                                      int level,
                                      int xoffset,
                                      int yoffset,
                                      bool flip_y,
                                      bool premultiply_alpha) {
  unsigned temp_texture = 0;
  gl->GenTextures(1, &temp_texture);
  gl->BindTexture(target, temp_texture);
  gl->TexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  gl->TexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  gl->TexImage2D(target, 0, temp_internalformat, frame->visible_rect().width(),
                 frame->visible_rect().height(), 0, temp_format, temp_type,
                 frame->visible_data(0));
  gl->BindTexture(target, texture);
  gl->CopySubTextureCHROMIUM(temp_texture, 0, target, texture, level, 0, 0,
                             xoffset, yoffset, frame->visible_rect().width(),
                             frame->visible_rect().height(), flip_y,
                             premultiply_alpha, false);
  gl->DeleteTextures(1, &temp_texture);
}

}  // anonymous namespace

// static
void PaintCanvasVideoRenderer::ConvertVideoFrameToRGBPixels(
    const VideoFrame* video_frame,
    void* rgb_pixels,
    size_t row_bytes) {
  if (!video_frame->IsMappable()) {
    NOTREACHED() << "Cannot extract pixels from non-CPU frame formats.";
    return;
  }

  // TODO(hubbe): This should really default to the rec709 colorspace.
  // https://crbug.com/828599
  SkYUVColorSpace color_space = kRec601_SkYUVColorSpace;
  video_frame->ColorSpace().ToSkYUVColorSpace(&color_space);

  switch (video_frame->format()) {
    case PIXEL_FORMAT_YV12:
    case PIXEL_FORMAT_I420:
      switch (color_space) {
        case kJPEG_SkYUVColorSpace:
          LIBYUV_J420_TO_ARGB(video_frame->visible_data(VideoFrame::kYPlane),
                              video_frame->stride(VideoFrame::kYPlane),
                              video_frame->visible_data(VideoFrame::kUPlane),
                              video_frame->stride(VideoFrame::kUPlane),
                              video_frame->visible_data(VideoFrame::kVPlane),
                              video_frame->stride(VideoFrame::kVPlane),
                              static_cast<uint8_t*>(rgb_pixels), row_bytes,
                              video_frame->visible_rect().width(),
                              video_frame->visible_rect().height());
          break;
        case kRec709_SkYUVColorSpace:
          LIBYUV_H420_TO_ARGB(video_frame->visible_data(VideoFrame::kYPlane),
                              video_frame->stride(VideoFrame::kYPlane),
                              video_frame->visible_data(VideoFrame::kUPlane),
                              video_frame->stride(VideoFrame::kUPlane),
                              video_frame->visible_data(VideoFrame::kVPlane),
                              video_frame->stride(VideoFrame::kVPlane),
                              static_cast<uint8_t*>(rgb_pixels), row_bytes,
                              video_frame->visible_rect().width(),
                              video_frame->visible_rect().height());
          break;
        case kRec601_SkYUVColorSpace:
          LIBYUV_I420_TO_ARGB(video_frame->visible_data(VideoFrame::kYPlane),
                              video_frame->stride(VideoFrame::kYPlane),
                              video_frame->visible_data(VideoFrame::kUPlane),
                              video_frame->stride(VideoFrame::kUPlane),
                              video_frame->visible_data(VideoFrame::kVPlane),
                              video_frame->stride(VideoFrame::kVPlane),
                              static_cast<uint8_t*>(rgb_pixels), row_bytes,
                              video_frame->visible_rect().width(),
                              video_frame->visible_rect().height());
          break;
        default:
          NOTREACHED();
      }
      break;
    case PIXEL_FORMAT_I422:
      LIBYUV_I422_TO_ARGB(video_frame->visible_data(VideoFrame::kYPlane),
                          video_frame->stride(VideoFrame::kYPlane),
                          video_frame->visible_data(VideoFrame::kUPlane),
                          video_frame->stride(VideoFrame::kUPlane),
                          video_frame->visible_data(VideoFrame::kVPlane),
                          video_frame->stride(VideoFrame::kVPlane),
                          static_cast<uint8_t*>(rgb_pixels), row_bytes,
                          video_frame->visible_rect().width(),
                          video_frame->visible_rect().height());
      break;

    case PIXEL_FORMAT_I420A:
      LIBYUV_I420ALPHA_TO_ARGB(
          video_frame->visible_data(VideoFrame::kYPlane),
          video_frame->stride(VideoFrame::kYPlane),
          video_frame->visible_data(VideoFrame::kUPlane),
          video_frame->stride(VideoFrame::kUPlane),
          video_frame->visible_data(VideoFrame::kVPlane),
          video_frame->stride(VideoFrame::kVPlane),
          video_frame->visible_data(VideoFrame::kAPlane),
          video_frame->stride(VideoFrame::kAPlane),
          static_cast<uint8_t*>(rgb_pixels), row_bytes,
          video_frame->visible_rect().width(),
          video_frame->visible_rect().height(),
          1);  // 1 = enable RGB premultiplication by Alpha.
      break;

    case PIXEL_FORMAT_I444:
      LIBYUV_I444_TO_ARGB(video_frame->visible_data(VideoFrame::kYPlane),
                          video_frame->stride(VideoFrame::kYPlane),
                          video_frame->visible_data(VideoFrame::kUPlane),
                          video_frame->stride(VideoFrame::kUPlane),
                          video_frame->visible_data(VideoFrame::kVPlane),
                          video_frame->stride(VideoFrame::kVPlane),
                          static_cast<uint8_t*>(rgb_pixels), row_bytes,
                          video_frame->visible_rect().width(),
                          video_frame->visible_rect().height());
      break;

    case PIXEL_FORMAT_YUV420P10:
      if (color_space == kRec709_SkYUVColorSpace) {
        LIBYUV_H010_TO_ARGB(reinterpret_cast<const uint16_t*>(
                                video_frame->visible_data(VideoFrame::kYPlane)),
                            video_frame->stride(VideoFrame::kYPlane) / 2,
                            reinterpret_cast<const uint16_t*>(
                                video_frame->visible_data(VideoFrame::kUPlane)),
                            video_frame->stride(VideoFrame::kUPlane) / 2,
                            reinterpret_cast<const uint16_t*>(
                                video_frame->visible_data(VideoFrame::kVPlane)),
                            video_frame->stride(VideoFrame::kVPlane) / 2,
                            static_cast<uint8_t*>(rgb_pixels), row_bytes,
                            video_frame->visible_rect().width(),
                            video_frame->visible_rect().height());
      } else {
        LIBYUV_I010_TO_ARGB(reinterpret_cast<const uint16_t*>(
                                video_frame->visible_data(VideoFrame::kYPlane)),
                            video_frame->stride(VideoFrame::kYPlane) / 2,
                            reinterpret_cast<const uint16_t*>(
                                video_frame->visible_data(VideoFrame::kUPlane)),
                            video_frame->stride(VideoFrame::kUPlane) / 2,
                            reinterpret_cast<const uint16_t*>(
                                video_frame->visible_data(VideoFrame::kVPlane)),
                            video_frame->stride(VideoFrame::kVPlane) / 2,
                            static_cast<uint8_t*>(rgb_pixels), row_bytes,
                            video_frame->visible_rect().width(),
                            video_frame->visible_rect().height());
      }
      break;

    case PIXEL_FORMAT_YUV420P9:
    case PIXEL_FORMAT_YUV422P9:
    case PIXEL_FORMAT_YUV444P9:
    case PIXEL_FORMAT_YUV422P10:
    case PIXEL_FORMAT_YUV444P10:
    case PIXEL_FORMAT_YUV420P12:
    case PIXEL_FORMAT_YUV422P12:
    case PIXEL_FORMAT_YUV444P12: {
      scoped_refptr<VideoFrame> temporary_frame =
          DownShiftHighbitVideoFrame(video_frame);
      ConvertVideoFrameToRGBPixels(temporary_frame.get(), rgb_pixels,
                                   row_bytes);
      break;
    }

    case PIXEL_FORMAT_Y16:
      // Since it is grayscale conversion, we disregard SK_PMCOLOR_BYTE_ORDER
      // and always use GL_RGBA.
      FlipAndConvertY16(video_frame, static_cast<uint8_t*>(rgb_pixels), GL_RGBA,
                        GL_UNSIGNED_BYTE, false /*flip_y*/, row_bytes);
      break;

    case PIXEL_FORMAT_NV12:
      LIBYUV_NV12_TO_ARGB(video_frame->visible_data(VideoFrame::kYPlane),
                          video_frame->stride(VideoFrame::kYPlane),
                          video_frame->visible_data(VideoFrame::kUVPlane),
                          video_frame->stride(VideoFrame::kUVPlane),
                          static_cast<uint8_t*>(rgb_pixels), row_bytes,
                          video_frame->visible_rect().width(),
                          video_frame->visible_rect().height());
      break;

    case PIXEL_FORMAT_NV21:
    case PIXEL_FORMAT_UYVY:
    case PIXEL_FORMAT_YUY2:
    case PIXEL_FORMAT_ARGB:
    case PIXEL_FORMAT_XRGB:
    case PIXEL_FORMAT_RGB24:
    case PIXEL_FORMAT_RGB32:
    case PIXEL_FORMAT_MJPEG:
    case PIXEL_FORMAT_MT21:
    case PIXEL_FORMAT_ABGR:
    case PIXEL_FORMAT_XBGR:
    case PIXEL_FORMAT_P016LE:
    case PIXEL_FORMAT_UNKNOWN:
      NOTREACHED() << "Only YUV formats and Y16 are supported, got: "
                   << media::VideoPixelFormatToString(video_frame->format());
  }
}

// static
void PaintCanvasVideoRenderer::CopyVideoFrameSingleTextureToGLTexture(
    gpu::gles2::GLES2Interface* gl,
    VideoFrame* video_frame,
    unsigned int target,
    unsigned int texture,
    unsigned int internal_format,
    unsigned int format,
    unsigned int type,
    int level,
    bool premultiply_alpha,
    bool flip_y) {
  DCHECK(video_frame);
  DCHECK(video_frame->HasTextures());

  const gpu::MailboxHolder& mailbox_holder = video_frame->mailbox_holder(0);
  DCHECK(mailbox_holder.texture_target == GL_TEXTURE_2D ||
         mailbox_holder.texture_target == GL_TEXTURE_RECTANGLE_ARB ||
         mailbox_holder.texture_target == GL_TEXTURE_EXTERNAL_OES)
      << mailbox_holder.texture_target;

  gl->WaitSyncTokenCHROMIUM(mailbox_holder.sync_token.GetConstData());
  uint32_t source_texture =
      gl->CreateAndConsumeTextureCHROMIUM(mailbox_holder.mailbox.name);
  VideoFrameCopyTextureOrSubTexture(gl, video_frame->coded_size(),
                                    video_frame->visible_rect(), source_texture,
                                    target, texture, internal_format, format,
                                    type, level, premultiply_alpha, flip_y);
  gl->DeleteTextures(1, &source_texture);
  gl->ShallowFlushCHROMIUM();
  // The caller must call SynchronizeVideoFrameRead() after this operation, but
  // we can't do that because we don't have the ContextSupport.
}

bool PaintCanvasVideoRenderer::CopyVideoFrameTexturesToGLTexture(
    viz::ContextProvider* context_provider,
    gpu::gles2::GLES2Interface* destination_gl,
    scoped_refptr<VideoFrame> video_frame,
    unsigned int target,
    unsigned int texture,
    unsigned int internal_format,
    unsigned int format,
    unsigned int type,
    int level,
    bool premultiply_alpha,
    bool flip_y) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(video_frame);
  DCHECK(video_frame->HasTextures());
  if (video_frame->NumTextures() > 1 ||
      video_frame->metadata()->IsTrue(
          VideoFrameMetadata::READ_LOCK_FENCES_ENABLED)) {
    if (!context_provider)
      return false;
    GrContext* gr_context = context_provider->GrContext();
    if (!gr_context)
      return false;
    if (!UpdateLastImage(video_frame, context_provider,
                         true /* allow_wrap_texture */)) {
      return false;
    }

    GrBackendTexture backend_texture =
        last_image_.GetSkImage()->getBackendTexture(true);
    if (!backend_texture.isValid())
      return false;
    GrGLTextureInfo texture_info;
    if (!backend_texture.getGLTextureInfo(&texture_info))
      return false;

    gpu::gles2::GLES2Interface* canvas_gl = context_provider->ContextGL();
    gpu::MailboxHolder mailbox_holder;
    mailbox_holder.texture_target = texture_info.fTarget;
    canvas_gl->ProduceTextureDirectCHROMIUM(texture_info.fID,
                                            mailbox_holder.mailbox.name);

    // Wait for mailbox creation on canvas context before consuming it and
    // copying from it on the consumer context.
    canvas_gl->GenUnverifiedSyncTokenCHROMIUM(
        mailbox_holder.sync_token.GetData());

    destination_gl->WaitSyncTokenCHROMIUM(
        mailbox_holder.sync_token.GetConstData());
    uint32_t intermediate_texture =
        destination_gl->CreateAndConsumeTextureCHROMIUM(
            mailbox_holder.mailbox.name);

    destination_gl->CopyTextureCHROMIUM(intermediate_texture, 0, target,
                                        texture, level, internal_format, type,
                                        flip_y, premultiply_alpha, false);

    destination_gl->DeleteTextures(1, &intermediate_texture);

    // Wait for destination context to consume mailbox before deleting it in
    // canvas context.
    gpu::SyncToken dest_sync_token;
    destination_gl->GenUnverifiedSyncTokenCHROMIUM(dest_sync_token.GetData());
    canvas_gl->WaitSyncTokenCHROMIUM(dest_sync_token.GetConstData());

    // Because we are not retaining a reference to the VideoFrame, it would be
    // invalid to keep last_image_ around if it directly wraps the VideoFrame
    // texture(s), as they will be recycled.
    if (last_image_wraps_video_frame_texture_)
      ResetCache();

    // Synchronize |video_frame| with the read operations in UpdateLastImage(),
    // which are triggered by getBackendTexture() or CopyTextureCHROMIUM (in the
    // case last_image_ was referencing its texture(s) directly).
    SynchronizeVideoFrameRead(std::move(video_frame), canvas_gl,
                              context_provider->ContextSupport());
  } else {
    CopyVideoFrameSingleTextureToGLTexture(
        destination_gl, video_frame.get(), target, texture, internal_format,
        format, type, level, premultiply_alpha, flip_y);
    SynchronizeVideoFrameRead(std::move(video_frame), destination_gl, nullptr);
  }
  DCHECK(!last_image_wraps_video_frame_texture_);

  return true;
}

bool PaintCanvasVideoRenderer::PrepareVideoFrameForWebGL(
    viz::ContextProvider* context_provider,
    gpu::gles2::GLES2Interface* destination_gl,
    scoped_refptr<VideoFrame> video_frame,
    unsigned int target,
    unsigned int texture) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(video_frame);
  DCHECK(video_frame->HasTextures());
  if (video_frame->NumTextures() == 1) {
    if (target == GL_TEXTURE_EXTERNAL_OES) {
      // We don't support Android now.
      // TODO(crbug.com/776222): support Android.
      return false;
    }
    // We don't support sharing single video frame texture now.
    // TODO(crbug.com/776222): deal with single video frame texture.
    return false;
  }

  if (!context_provider || !context_provider->GrContext())
    return false;

  // Take webgl video texture as 2D texture. Setting it as external render
  // target backend for skia.
  destination_gl->BindTexture(target, texture);
  destination_gl->TexImage2D(target, 0, GL_RGBA,
                             video_frame->coded_size().width(),
                             video_frame->coded_size().height(), 0, GL_RGBA,
                             GL_UNSIGNED_BYTE, nullptr);

  gpu::gles2::GLES2Interface* source_gl = context_provider->ContextGL();
  gpu::MailboxHolder mailbox_holder;
  mailbox_holder.texture_target = target;
  destination_gl->ProduceTextureDirectCHROMIUM(texture,
                                               mailbox_holder.mailbox.name);

  destination_gl->GenUnverifiedSyncTokenCHROMIUM(
      mailbox_holder.sync_token.GetData());

  source_gl->WaitSyncTokenCHROMIUM(mailbox_holder.sync_token.GetConstData());

  uint32_t shared_texture =
      source_gl->CreateAndConsumeTextureCHROMIUM(mailbox_holder.mailbox.name);

  if (!PrepareVideoFrame(video_frame, context_provider, target,
                         shared_texture)) {
    return false;
  }

  // Warning : This approach has failed previously. The history is
  // https://chromium-review.googlesource.com/c/chromium/src/+/1251321.
  // It failed to execute texture copy on mac.
  // The possible solution is here:
  // https://chromium-review.googlesource.com/c/chromium/src/+/1258212
  // make a copy of the video texture in that case so that the copy
  // could be done in |destination_gl|.
  source_gl->ProduceTextureDirectCHROMIUM(shared_texture,
                                          mailbox_holder.mailbox.name);

  // Wait for mailbox creation on canvas context before consuming it and
  // copying from it on the consumer context.
  source_gl->GenUnverifiedSyncTokenCHROMIUM(
      mailbox_holder.sync_token.GetData());

  destination_gl->WaitSyncTokenCHROMIUM(
      mailbox_holder.sync_token.GetConstData());

  SyncTokenClientImpl client(source_gl);
  video_frame->UpdateReleaseSyncToken(&client);

  DCHECK(!last_image_wraps_video_frame_texture_);
  return true;
}

bool PaintCanvasVideoRenderer::CopyVideoFrameYUVDataToGLTexture(
    viz::ContextProvider* context_provider,
    gpu::gles2::GLES2Interface* destination_gl,
    const VideoFrame& video_frame,
    unsigned int target,
    unsigned int texture,
    unsigned int internal_format,
    unsigned int format,
    unsigned int type,
    int level,
    bool premultiply_alpha,
    bool flip_y) {
  DCHECK(context_provider);
  GrContext* gr_context = context_provider->GrContext();
  if (!gr_context) {
    return false;
  }

  if (!video_frame.IsMappable()) {
    return false;
  }

  if (video_frame.format() != media::PIXEL_FORMAT_I420) {
    return false;
  }
  // Could handle NV12 here as well. See NewSkImageFromVideoFrameYUVTextures.

  static constexpr size_t kNumPlanes = 3;
  DCHECK_EQ(video_frame.NumPlanes(video_frame.format()), kNumPlanes);
  // Y,U,V GPU-side SkImages. (These must outlive the yuv_textures).
  sk_sp<SkImage> yuv_images[kNumPlanes]{};
  // Y,U,V GPU textures from those SkImages.
  // (A GrBackendTexture is a non-owned reference to the SkImage's texture.)
  GrBackendTexture yuv_textures[kNumPlanes]{};

  // Upload the whole coded image area (not visible rect).
  gfx::Size y_tex_size = video_frame.coded_size();
  gfx::Size uv_tex_size((y_tex_size.width() + 1) / 2,
                        (y_tex_size.height() + 1) / 2);

  for (size_t plane = 0; plane < kNumPlanes; ++plane) {
    const uint8_t* data = video_frame.data(plane);
    int plane_stride = video_frame.stride(plane);

    bool is_y_plane = plane == media::VideoFrame::kYPlane;
    gfx::Size tex_size = is_y_plane ? y_tex_size : uv_tex_size;
    int data_size = plane_stride * (tex_size.height() - 1) + tex_size.width();

    // Create a CPU-side SkImage from the channel.
    sk_sp<SkData> sk_data = SkData::MakeWithoutCopy(data, data_size);
    DCHECK(sk_data);
    SkImageInfo image_info =
        SkImageInfo::Make(tex_size.width(), tex_size.height(),
                          kGray_8_SkColorType, kUnknown_SkAlphaType);
    sk_sp<SkImage> plane_image_cpu =
        SkImage::MakeRasterData(image_info, sk_data, plane_stride);
    DCHECK(plane_image_cpu);

    // Upload the CPU-side SkImage into a GPU-side SkImage.
    // (Note the original video_frame data is no longer used after this point.)
    yuv_images[plane] = plane_image_cpu->makeTextureImage(gr_context, nullptr);
    DCHECK(yuv_images[plane]);

    // Extract the backend texture from the GPU-side image.
    yuv_textures[plane] = yuv_images[plane]->getBackendTexture(false);
  }

  // Decode 3 GPU-side Y,U,V SkImages into a GPU-side RGB SkImage.
  sk_sp<SkImage> yuv_image = YUVGrBackendTexturesToSkImage(
      gr_context, video_frame.ColorSpace(), video_frame.format(), yuv_textures);
  if (!yuv_image) {
    return false;
  }

  GrGLTextureInfo src_texture_info{};
  yuv_image->getBackendTexture(true).getGLTextureInfo(&src_texture_info);

  gpu::gles2::GLES2Interface* source_gl = context_provider->ContextGL();
  gpu::MailboxHolder mailbox_holder;
  mailbox_holder.texture_target = src_texture_info.fTarget;
  source_gl->ProduceTextureDirectCHROMIUM(src_texture_info.fID,
                                          mailbox_holder.mailbox.name);

  // Wait for mailbox creation on source context before consuming it and
  // copying from it on the consumer context.
  source_gl->GenUnverifiedSyncTokenCHROMIUM(
      mailbox_holder.sync_token.GetData());

  destination_gl->WaitSyncTokenCHROMIUM(
      mailbox_holder.sync_token.GetConstData());
  uint32_t intermediate_texture =
      destination_gl->CreateAndConsumeTextureCHROMIUM(
          mailbox_holder.mailbox.name);
  VideoFrameCopyTextureOrSubTexture(
      destination_gl, video_frame.coded_size(), video_frame.visible_rect(),
      intermediate_texture, target, texture, internal_format, format, type,
      level, premultiply_alpha, flip_y);
  destination_gl->DeleteTextures(1, &intermediate_texture);

  // Wait for destination context to consume mailbox before deleting it in
  // source context.
  gpu::SyncToken dest_sync_token;
  destination_gl->GenUnverifiedSyncTokenCHROMIUM(dest_sync_token.GetData());
  source_gl->WaitSyncTokenCHROMIUM(dest_sync_token.GetConstData());

  // video_frame->UpdateReleaseSyncToken is not necessary since the video frame
  // data we used was CPU-side (IsMappable) to begin with. If there were any
  // textures, we didn't use them.

  // The temporary SkImages should be automatically cleaned up here.
  return true;
}

bool PaintCanvasVideoRenderer::TexImage2D(
    unsigned target,
    unsigned texture,
    gpu::gles2::GLES2Interface* gl,
    const gpu::Capabilities& gpu_capabilities,
    VideoFrame* frame,
    int level,
    int internalformat,
    unsigned format,
    unsigned type,
    bool flip_y,
    bool premultiply_alpha) {
  DCHECK(frame);
  DCHECK(!frame->HasTextures());

  // Note: CopyTextureCHROMIUM uses mediump for color computation. Don't use
  // it if the precision would lead to data loss when converting 16-bit
  // normalized to float. medium_float.precision > 15 means that the approach
  // below is not used on Android, where the extension EXT_texture_norm16 is
  // not widely supported. It is used on Windows, Linux and OSX.
  // Android support is not required for now because Tango depth camera already
  // provides floating point data (projected point cloud). See crbug.com/674440.
  if (gpu_capabilities.texture_norm16 &&
      gpu_capabilities.fragment_shader_precisions.medium_float.precision > 15 &&
      target == GL_TEXTURE_2D &&
      (type == GL_FLOAT || type == GL_UNSIGNED_BYTE)) {
    // TODO(aleksandar.stojiljkovic): Extend the approach to TexSubImage2D
    // implementation and other types. See https://crbug.com/624436.

    // Allocate the destination texture.
    gl->TexImage2D(target, level, internalformat, frame->visible_rect().width(),
                   frame->visible_rect().height(), 0, format, type, nullptr);
    // We use sized internal format GL_R16_EXT instead of unsized GL_RED.
    // See angleproject:1952
    TextureSubImageUsingIntermediate(target, texture, gl, frame, GL_R16_EXT,
                                     GL_RED, GL_UNSIGNED_SHORT, level, 0, 0,
                                     flip_y, premultiply_alpha);
    return true;
  }
  scoped_refptr<DataBuffer> temp_buffer;
  if (!TexImageHelper(frame, format, type, flip_y, &temp_buffer))
    return false;

  gl->TexImage2D(target, level, internalformat, frame->visible_rect().width(),
                 frame->visible_rect().height(), 0, format, type,
                 temp_buffer->data());
  return true;
}

bool PaintCanvasVideoRenderer::TexSubImage2D(unsigned target,
                                             gpu::gles2::GLES2Interface* gl,
                                             VideoFrame* frame,
                                             int level,
                                             unsigned format,
                                             unsigned type,
                                             int xoffset,
                                             int yoffset,
                                             bool flip_y,
                                             bool premultiply_alpha) {
  DCHECK(frame);
  DCHECK(!frame->HasTextures());

  scoped_refptr<DataBuffer> temp_buffer;
  if (!TexImageHelper(frame, format, type, flip_y, &temp_buffer))
    return false;

  gl->TexSubImage2D(
      target, level, xoffset, yoffset, frame->visible_rect().width(),
      frame->visible_rect().height(), format, type, temp_buffer->data());
  return true;
}

void PaintCanvasVideoRenderer::ResetCache() {
  DCHECK(thread_checker_.CalledOnValidThread());
  // Clear cached values.
  last_image_ = cc::PaintImage();
  last_id_.reset();
  last_image_wraps_video_frame_texture_ = false;
}

bool PaintCanvasVideoRenderer::UpdateLastImage(
    scoped_refptr<VideoFrame> video_frame,
    viz::ContextProvider* context_provider,
    bool allow_wrap_texture) {
  DCHECK(!last_image_wraps_video_frame_texture_);
  if (!last_image_ || video_frame->unique_id() != last_id_ ||
      !last_image_.GetSkImage()->getBackendTexture(true).isValid()) {
    ResetCache();

    auto paint_image_builder =
        cc::PaintImageBuilder::WithDefault()
            .set_id(renderer_stable_id_)
            .set_animation_type(cc::PaintImage::AnimationType::VIDEO)
            .set_completion_state(cc::PaintImage::CompletionState::DONE);

    // Generate a new image.
    // Note: Skia will hold onto |video_frame| via |video_generator| only when
    // |video_frame| is software.
    // Holding |video_frame| longer than this call when using GPUVideoDecoder
    // could cause problems since the pool of VideoFrames has a fixed size.
    if (video_frame->HasTextures()) {
      DCHECK(context_provider);
      DCHECK(context_provider->GrContext());
      DCHECK(context_provider->ContextGL());
      if (video_frame->NumTextures() > 1) {
        paint_image_builder.set_image(NewSkImageFromVideoFrameYUVTextures(
                                          video_frame.get(), context_provider),
                                      cc::PaintImage::GetNextContentId());
      } else {
        paint_image_builder.set_image(
            NewSkImageFromVideoFrameNative(
                video_frame.get(), context_provider, allow_wrap_texture,
                &last_image_wraps_video_frame_texture_),
            cc::PaintImage::GetNextContentId());
      }
    } else {
      paint_image_builder.set_paint_image_generator(
          sk_make_sp<VideoImageGenerator>(video_frame));
    }
    last_image_ = paint_image_builder.TakePaintImage();
    CorrectLastImageDimensions(gfx::RectToSkIRect(video_frame->visible_rect()));
    if (!last_image_)  // Couldn't create the SkImage.
      return false;
    last_id_ = video_frame->unique_id();
  }

  DCHECK(last_image_);
  last_image_deleting_timer_.Reset();
  return true;
}

bool PaintCanvasVideoRenderer::PrepareVideoFrame(
    scoped_refptr<VideoFrame> video_frame,
    viz::ContextProvider* context_provider,
    unsigned int textureTarget,
    unsigned int texture) {
  // We are about to replace last_image_, make sure to reset related state such
  // as last_id_ or last_image_wraps_video_frame_texture_.
  ResetCache();
  auto paint_image_builder =
      cc::PaintImageBuilder::WithDefault()
          .set_id(renderer_stable_id_)
          .set_animation_type(cc::PaintImage::AnimationType::VIDEO)
          .set_completion_state(cc::PaintImage::CompletionState::DONE);

  // Generate a new image.
  // Note: Skia will hold onto |video_frame| via |video_generator| only when
  // |video_frame| is software.
  // Holding |video_frame| longer than this call when using GPUVideoDecoder
  // could cause problems since the pool of VideoFrames has a fixed size.
  if (video_frame->HasTextures()) {
    DCHECK(context_provider);
    DCHECK(context_provider->GrContext());
    DCHECK(context_provider->ContextGL());
    if (video_frame->NumTextures() > 1) {
      paint_image_builder.set_image(
          NewSkImageFromVideoFrameYUVTexturesWithExternalBackend(
              video_frame.get(), context_provider, textureTarget, texture),
          cc::PaintImage::GetNextContentId());
    } else {
      // We don't support Android now.
      return false;
    }
  } else {
    paint_image_builder.set_paint_image_generator(
        sk_make_sp<VideoImageGenerator>(video_frame));
  }
  last_image_ = paint_image_builder.TakePaintImage();
  CorrectLastImageDimensions(gfx::RectToSkIRect(video_frame->visible_rect()));
  if (!last_image_)  // Couldn't create the SkImage.
    return false;
  last_id_ = video_frame->unique_id();
  last_image_deleting_timer_.Reset();
  DCHECK(!!last_image_);
  return true;
}

void PaintCanvasVideoRenderer::CorrectLastImageDimensions(
    const SkIRect& visible_rect) {
  last_image_dimensions_for_testing_ = visible_rect.size();
  if (!last_image_)
    return;
  SkIRect bounds = SkIRect::MakeWH(last_image_.width(), last_image_.height());
  if (bounds.size() != visible_rect.size() && bounds.contains(visible_rect)) {
    last_image_ = cc::PaintImageBuilder::WithCopy(std::move(last_image_))
                      .make_subset(gfx::SkIRectToRect(visible_rect))
                      .TakePaintImage();
  }
}

SkISize PaintCanvasVideoRenderer::LastImageDimensionsForTesting() {
  return last_image_dimensions_for_testing_;
}

}  // namespace media
