15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/filters/skcanvas_video_renderer.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/video_frame.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/yuv_convert.h"
10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "third_party/libyuv/include/libyuv.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkCanvas.h"
121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "third_party/skia/include/core/SkImageGenerator.h"
136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "ui/gfx/skbitmap_operations.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Skia internal format depends on a platform. On Android it is ABGR, on others
16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// it is ARGB.
17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if SK_B32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_R32_SHIFT == 16 && \
18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    SK_A32_SHIFT == 24
19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#define LIBYUV_I420_TO_ARGB libyuv::I420ToARGB
20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#define LIBYUV_I422_TO_ARGB libyuv::I422ToARGB
21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#elif SK_R32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_B32_SHIFT == 16 && \
22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    SK_A32_SHIFT == 24
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#define LIBYUV_I420_TO_ARGB libyuv::I420ToABGR
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#define LIBYUV_I422_TO_ARGB libyuv::I422ToABGR
25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#else
26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#error Unexpected Skia ARGB_8888 layout!
27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif
28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochstatic bool IsYUV(media::VideoFrame::Format format) {
321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  switch (format) {
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case VideoFrame::YV12:
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case VideoFrame::YV16:
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case VideoFrame::I420:
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case VideoFrame::YV12A:
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case VideoFrame::YV12J:
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case VideoFrame::YV24:
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case VideoFrame::NV12:
401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return true;
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case VideoFrame::UNKNOWN:
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case VideoFrame::NATIVE_TEXTURE:
431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(VIDEO_HOLE)
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case VideoFrame::HOLE:
451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif  // defined(VIDEO_HOLE)
461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return false;
471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  NOTREACHED() << "Invalid videoframe format provided: " << format;
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return false;
501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistatic bool IsJPEGColorSpace(media::VideoFrame::Format format) {
531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  switch (format) {
541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case VideoFrame::YV12J:
551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return true;
561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case VideoFrame::YV12:
571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case VideoFrame::YV16:
581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case VideoFrame::I420:
591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case VideoFrame::YV12A:
601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case VideoFrame::YV24:
611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case VideoFrame::NV12:
621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case VideoFrame::UNKNOWN:
631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case VideoFrame::NATIVE_TEXTURE:
641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(VIDEO_HOLE)
651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case VideoFrame::HOLE:
661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif  // defined(VIDEO_HOLE)
671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return false;
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  NOTREACHED() << "Invalid videoframe format provided: " << format;
701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return false;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)static bool IsYUVOrNative(media::VideoFrame::Format format) {
74c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return IsYUV(format) || format == media::VideoFrame::NATIVE_TEXTURE;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Converts a |video_frame| to raw |rgb_pixels|.
781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistatic void ConvertVideoFrameToRGBPixels(
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const scoped_refptr<media::VideoFrame>& video_frame,
801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void* rgb_pixels,
811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    size_t row_bytes) {
8246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(IsYUVOrNative(video_frame->format()))
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << video_frame->format();
8446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (IsYUV(video_frame->format())) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(video_frame->stride(media::VideoFrame::kUPlane),
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              video_frame->stride(media::VideoFrame::kVPlane));
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  size_t y_offset = 0;
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  size_t uv_offset = 0;
9146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (IsYUV(video_frame->format())) {
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int y_shift = (video_frame->format() == media::VideoFrame::YV16) ? 0 : 1;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Use the "left" and "top" of the destination rect to locate the offset
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // in Y, U and V planes.
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    y_offset = (video_frame->stride(media::VideoFrame::kYPlane) *
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                video_frame->visible_rect().y()) +
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                video_frame->visible_rect().x();
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // For format YV12, there is one U, V value per 2x2 block.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // For format YV16, there is one U, V value per 2x1 block.
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    uv_offset = (video_frame->stride(media::VideoFrame::kUPlane) *
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                (video_frame->visible_rect().y() >> y_shift)) +
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                (video_frame->visible_rect().x() >> 1);
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  switch (video_frame->format()) {
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case media::VideoFrame::YV12:
107c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case media::VideoFrame::I420:
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      LIBYUV_I420_TO_ARGB(
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          video_frame->data(media::VideoFrame::kYPlane) + y_offset,
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          video_frame->stride(media::VideoFrame::kYPlane),
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          video_frame->data(media::VideoFrame::kUPlane) + uv_offset,
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          video_frame->stride(media::VideoFrame::kUPlane),
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          video_frame->data(media::VideoFrame::kVPlane) + uv_offset,
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          video_frame->stride(media::VideoFrame::kVPlane),
1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          static_cast<uint8*>(rgb_pixels),
1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          row_bytes,
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          video_frame->visible_rect().width(),
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          video_frame->visible_rect().height());
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
121010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    case media::VideoFrame::YV12J:
122010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      media::ConvertYUVToRGB32(
123010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          video_frame->data(media::VideoFrame::kYPlane) + y_offset,
124010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          video_frame->data(media::VideoFrame::kUPlane) + uv_offset,
125010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          video_frame->data(media::VideoFrame::kVPlane) + uv_offset,
1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          static_cast<uint8*>(rgb_pixels),
127010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          video_frame->visible_rect().width(),
128010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          video_frame->visible_rect().height(),
129010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          video_frame->stride(media::VideoFrame::kYPlane),
130010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          video_frame->stride(media::VideoFrame::kUPlane),
1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          row_bytes,
132010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          media::YV12J);
133010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      break;
134010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case media::VideoFrame::YV16:
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      LIBYUV_I422_TO_ARGB(
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          video_frame->data(media::VideoFrame::kYPlane) + y_offset,
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          video_frame->stride(media::VideoFrame::kYPlane),
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          video_frame->data(media::VideoFrame::kUPlane) + uv_offset,
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          video_frame->stride(media::VideoFrame::kUPlane),
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          video_frame->data(media::VideoFrame::kVPlane) + uv_offset,
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          video_frame->stride(media::VideoFrame::kVPlane),
1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          static_cast<uint8*>(rgb_pixels),
1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          row_bytes,
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          video_frame->visible_rect().width(),
146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          video_frame->visible_rect().height());
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case media::VideoFrame::YV12A:
150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // Since libyuv doesn't support YUVA, fallback to media, which is not ARM
151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // optimized.
152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // TODO(fbarchard, mtomasz): Use libyuv, then copy the alpha channel.
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      media::ConvertYUVAToARGB(
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          video_frame->data(media::VideoFrame::kYPlane) + y_offset,
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          video_frame->data(media::VideoFrame::kUPlane) + uv_offset,
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          video_frame->data(media::VideoFrame::kVPlane) + uv_offset,
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          video_frame->data(media::VideoFrame::kAPlane),
1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          static_cast<uint8*>(rgb_pixels),
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          video_frame->visible_rect().width(),
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          video_frame->visible_rect().height(),
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          video_frame->stride(media::VideoFrame::kYPlane),
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          video_frame->stride(media::VideoFrame::kUPlane),
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          video_frame->stride(media::VideoFrame::kAPlane),
1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          row_bytes,
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          media::YV12);
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
16846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case media::VideoFrame::YV24:
16946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      libyuv::I444ToARGB(
17046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          video_frame->data(media::VideoFrame::kYPlane) + y_offset,
17146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          video_frame->stride(media::VideoFrame::kYPlane),
17246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          video_frame->data(media::VideoFrame::kUPlane) + uv_offset,
17346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          video_frame->stride(media::VideoFrame::kUPlane),
17446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          video_frame->data(media::VideoFrame::kVPlane) + uv_offset,
17546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          video_frame->stride(media::VideoFrame::kVPlane),
1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          static_cast<uint8*>(rgb_pixels),
1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          row_bytes,
17846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          video_frame->visible_rect().width(),
17946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          video_frame->visible_rect().height());
18046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#if SK_R32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_B32_SHIFT == 16 && \
18146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    SK_A32_SHIFT == 24
1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      libyuv::ARGBToABGR(static_cast<uint8*>(rgb_pixels),
1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                         row_bytes,
1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                         static_cast<uint8*>(rgb_pixels),
1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                         row_bytes,
1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                         video_frame->visible_rect().width(),
1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                         video_frame->visible_rect().height());
18846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#endif
18946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      break;
19046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case media::VideoFrame::NATIVE_TEXTURE: {
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      DCHECK_EQ(video_frame->format(), media::VideoFrame::NATIVE_TEXTURE);
1931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      SkBitmap tmp;
1941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      tmp.installPixels(
1951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          SkImageInfo::MakeN32Premul(video_frame->visible_rect().width(),
1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                     video_frame->visible_rect().height()),
1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          rgb_pixels,
1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          row_bytes);
1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      video_frame->ReadPixelsFromNativeTexture(tmp);
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    default:
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      NOTREACHED();
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Generates an RGB image from a VideoFrame.
2091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass VideoImageGenerator : public SkImageGenerator {
2101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public:
2111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  VideoImageGenerator(const scoped_refptr<VideoFrame>& frame) : frame_(frame) {}
2121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual ~VideoImageGenerator() {}
2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void set_frame(const scoped_refptr<VideoFrame>& frame) { frame_ = frame; }
2151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci protected:
2171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual bool onGetInfo(SkImageInfo* info) OVERRIDE {
2181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    info->fWidth = frame_->visible_rect().width();
2191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    info->fHeight = frame_->visible_rect().height();
2201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    info->fColorType = kN32_SkColorType;
2211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    info->fAlphaType = kPremul_SkAlphaType;
2221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return true;
2231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
2241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual bool onGetPixels(const SkImageInfo& info,
2261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                           void* pixels,
2271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                           size_t row_bytes,
2281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                           SkPMColor ctable[],
2291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                           int* ctable_count) OVERRIDE {
2301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!frame_.get())
2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return false;
2321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!pixels)
2331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return true;
2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // If skia couldn't do the YUV conversion, we will.
2351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ConvertVideoFrameToRGBPixels(frame_, pixels, row_bytes);
2361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    frame_ = NULL;
2371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return true;
2381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
2391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual bool onGetYUV8Planes(SkISize sizes[3],
2411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               void* planes[3],
2421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               size_t row_bytes[3],
2431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               SkYUVColorSpace* color_space) OVERRIDE {
2441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!frame_.get() || !IsYUV(frame_->format()))
2451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return false;
2461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (color_space) {
2481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (IsJPEGColorSpace(frame_->format()))
2491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        *color_space = kJPEG_SkYUVColorSpace;
2501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      else
2511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        *color_space = kRec601_SkYUVColorSpace;
2521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
2531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    for (int plane = VideoFrame::kYPlane; plane <= VideoFrame::kVPlane;
2551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci         ++plane) {
2561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (sizes) {
2571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        gfx::Size size;
2581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        size =
2591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            VideoFrame::PlaneSize(frame_->format(),
2601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                  plane,
2611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                  gfx::Size(frame_->visible_rect().width(),
2621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                            frame_->visible_rect().height()));
2631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        sizes[plane].set(size.width(), size.height());
2641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
2651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (row_bytes && planes) {
2661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        size_t offset;
2671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        int y_shift = (frame_->format() == media::VideoFrame::YV16) ? 0 : 1;
2681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        if (plane == media::VideoFrame::kYPlane) {
2691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          offset = (frame_->stride(media::VideoFrame::kYPlane) *
2701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    frame_->visible_rect().y()) +
2711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                   frame_->visible_rect().x();
2721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        } else {
2731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          offset = (frame_->stride(media::VideoFrame::kUPlane) *
2741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    (frame_->visible_rect().y() >> y_shift)) +
2751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                   (frame_->visible_rect().x() >> 1);
2761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        }
2771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        row_bytes[plane] = static_cast<size_t>(frame_->stride(plane));
2781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        planes[plane] = frame_->data(plane) + offset;
2791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
2801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
2811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (planes && row_bytes)
2821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      frame_ = NULL;
2831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return true;
2841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
2851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private:
2871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_refptr<VideoFrame> frame_;
2881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci};
2891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkCanvasVideoRenderer::SkCanvasVideoRenderer()
2911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    : generator_(NULL), last_frame_timestamp_(media::kNoTimestamp()) {
2921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  last_frame_.setIsVolatile(true);
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkCanvasVideoRenderer::~SkCanvasVideoRenderer() {}
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SkCanvasVideoRenderer::Paint(const scoped_refptr<VideoFrame>& video_frame,
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  SkCanvas* canvas,
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const gfx::RectF& dest_rect,
3006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                  uint8 alpha,
30103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                  SkXfermode::Mode mode,
3026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                  VideoRotation video_rotation) {
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (alpha == 0) {
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkRect dest;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dest.set(dest_rect.x(), dest_rect.y(), dest_rect.right(), dest_rect.bottom());
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkPaint paint;
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  paint.setAlpha(alpha);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Paint black rectangle if there isn't a frame available or the
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // frame has an unexpected format.
3151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!video_frame.get() || !IsYUVOrNative(video_frame->format())) {
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    canvas->drawRect(dest, paint);
3171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    canvas->flush();
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check if we should convert and update |last_frame_|.
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (last_frame_.isNull() ||
323c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      video_frame->timestamp() != last_frame_timestamp_) {
3241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    generator_ = new VideoImageGenerator(video_frame);
3256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Note: This takes ownership of |generator_|.
3271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!SkInstallDiscardablePixelRef(generator_, &last_frame_)) {
3281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      NOTREACHED();
3291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
3301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // TODO(rileya): Perform this rotation on the canvas, rather than allocating
3321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // a new bitmap and copying.
3336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    switch (video_rotation) {
3346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      case VIDEO_ROTATION_0:
3356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        break;
3366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      case VIDEO_ROTATION_90:
3376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        last_frame_ = SkBitmapOperations::Rotate(
3386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            last_frame_, SkBitmapOperations::ROTATION_90_CW);
3396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        break;
3406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      case VIDEO_ROTATION_180:
3416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        last_frame_ = SkBitmapOperations::Rotate(
3426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            last_frame_, SkBitmapOperations::ROTATION_180_CW);
3436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        break;
3446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      case VIDEO_ROTATION_270:
3456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        last_frame_ = SkBitmapOperations::Rotate(
3466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            last_frame_, SkBitmapOperations::ROTATION_270_CW);
3476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        break;
3486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
3496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // We copied the frame into a new bitmap and threw out the old one, so we
3511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // no longer have a |generator_| around. This should be removed when the
3521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // above TODO is addressed.
3531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (video_rotation != VIDEO_ROTATION_0)
3541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      generator_ = NULL;
3551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
356c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    last_frame_timestamp_ = video_frame->timestamp();
3571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  } else if (generator_) {
3581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    generator_->set_frame(video_frame);
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  paint.setXfermodeMode(mode);
362116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
36346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Paint using |last_frame_|.
364cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  paint.setFilterLevel(SkPaint::kLow_FilterLevel);
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  canvas->drawBitmapRect(last_frame_, NULL, dest, &paint);
3661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  canvas->flush();
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SkCanvasVideoRenderer::Copy(const scoped_refptr<VideoFrame>& video_frame,
37003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                 SkCanvas* canvas) {
37103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  Paint(video_frame,
37203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        canvas,
37303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        video_frame->visible_rect(),
37403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        0xff,
37503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        SkXfermode::kSrc_Mode,
37603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        media::VIDEO_ROTATION_0);
37703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
37803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace media
380