Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(147)

Side by Side Diff: media/filters/skcanvas_video_renderer.cc

Issue 445013002: media: Optimize HW Video to 2D Canvas copy. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "media/filters/skcanvas_video_renderer.h"
6
7 #include "base/logging.h"
8 #include "media/base/video_frame.h"
9 #include "media/base/yuv_convert.h"
10 #include "third_party/libyuv/include/libyuv.h"
11 #include "third_party/skia/include/core/SkCanvas.h"
12
13 // Skia internal format depends on a platform. On Android it is ABGR, on others
14 // it is ARGB.
15 #if SK_B32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_R32_SHIFT == 16 && \
16 SK_A32_SHIFT == 24
17 #define LIBYUV_I420_TO_ARGB libyuv::I420ToARGB
18 #define LIBYUV_I422_TO_ARGB libyuv::I422ToARGB
19 #elif SK_R32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_B32_SHIFT == 16 && \
20 SK_A32_SHIFT == 24
21 #define LIBYUV_I420_TO_ARGB libyuv::I420ToABGR
22 #define LIBYUV_I422_TO_ARGB libyuv::I422ToABGR
23 #else
24 #error Unexpected Skia ARGB_8888 layout!
25 #endif
26
27 namespace media {
28
29 static bool IsYUV(media::VideoFrame::Format format) {
30 return format == media::VideoFrame::YV12 ||
31 format == media::VideoFrame::YV16 ||
32 format == media::VideoFrame::I420 ||
33 format == media::VideoFrame::YV12A ||
34 format == media::VideoFrame::YV12J ||
35 format == media::VideoFrame::YV24;
36 }
37
38 static bool IsYUVOrNative(media::VideoFrame::Format format) {
39 return IsYUV(format) || format == media::VideoFrame::NATIVE_TEXTURE;
40 }
41
42 // Converts a VideoFrame containing YUV data to a SkBitmap containing RGB data.
43 //
44 // |bitmap| will be (re)allocated to match the dimensions of |video_frame|.
45 static void ConvertVideoFrameToBitmap(
46 const scoped_refptr<media::VideoFrame>& video_frame,
47 SkBitmap* bitmap) {
48 DCHECK(IsYUVOrNative(video_frame->format()))
49 << video_frame->format();
50 if (IsYUV(video_frame->format())) {
51 DCHECK_EQ(video_frame->stride(media::VideoFrame::kUPlane),
52 video_frame->stride(media::VideoFrame::kVPlane));
53 }
54
55 // Check if |bitmap| needs to be (re)allocated.
56 if (bitmap->isNull() ||
57 bitmap->width() != video_frame->visible_rect().width() ||
58 bitmap->height() != video_frame->visible_rect().height()) {
59 bitmap->allocN32Pixels(video_frame->visible_rect().width(),
60 video_frame->visible_rect().height());
61 bitmap->setIsVolatile(true);
62 }
63
64 bitmap->lockPixels();
65
66 size_t y_offset = 0;
67 size_t uv_offset = 0;
68 if (IsYUV(video_frame->format())) {
69 int y_shift = (video_frame->format() == media::VideoFrame::YV16) ? 0 : 1;
70 // Use the "left" and "top" of the destination rect to locate the offset
71 // in Y, U and V planes.
72 y_offset = (video_frame->stride(media::VideoFrame::kYPlane) *
73 video_frame->visible_rect().y()) +
74 video_frame->visible_rect().x();
75 // For format YV12, there is one U, V value per 2x2 block.
76 // For format YV16, there is one U, V value per 2x1 block.
77 uv_offset = (video_frame->stride(media::VideoFrame::kUPlane) *
78 (video_frame->visible_rect().y() >> y_shift)) +
79 (video_frame->visible_rect().x() >> 1);
80 }
81
82 switch (video_frame->format()) {
83 case media::VideoFrame::YV12:
84 case media::VideoFrame::I420:
85 LIBYUV_I420_TO_ARGB(
86 video_frame->data(media::VideoFrame::kYPlane) + y_offset,
87 video_frame->stride(media::VideoFrame::kYPlane),
88 video_frame->data(media::VideoFrame::kUPlane) + uv_offset,
89 video_frame->stride(media::VideoFrame::kUPlane),
90 video_frame->data(media::VideoFrame::kVPlane) + uv_offset,
91 video_frame->stride(media::VideoFrame::kVPlane),
92 static_cast<uint8*>(bitmap->getPixels()),
93 bitmap->rowBytes(),
94 video_frame->visible_rect().width(),
95 video_frame->visible_rect().height());
96 break;
97
98 case media::VideoFrame::YV12J:
99 media::ConvertYUVToRGB32(
100 video_frame->data(media::VideoFrame::kYPlane) + y_offset,
101 video_frame->data(media::VideoFrame::kUPlane) + uv_offset,
102 video_frame->data(media::VideoFrame::kVPlane) + uv_offset,
103 static_cast<uint8*>(bitmap->getPixels()),
104 video_frame->visible_rect().width(),
105 video_frame->visible_rect().height(),
106 video_frame->stride(media::VideoFrame::kYPlane),
107 video_frame->stride(media::VideoFrame::kUPlane),
108 bitmap->rowBytes(),
109 media::YV12J);
110 break;
111
112 case media::VideoFrame::YV16:
113 LIBYUV_I422_TO_ARGB(
114 video_frame->data(media::VideoFrame::kYPlane) + y_offset,
115 video_frame->stride(media::VideoFrame::kYPlane),
116 video_frame->data(media::VideoFrame::kUPlane) + uv_offset,
117 video_frame->stride(media::VideoFrame::kUPlane),
118 video_frame->data(media::VideoFrame::kVPlane) + uv_offset,
119 video_frame->stride(media::VideoFrame::kVPlane),
120 static_cast<uint8*>(bitmap->getPixels()),
121 bitmap->rowBytes(),
122 video_frame->visible_rect().width(),
123 video_frame->visible_rect().height());
124 break;
125
126 case media::VideoFrame::YV12A:
127 // Since libyuv doesn't support YUVA, fallback to media, which is not ARM
128 // optimized.
129 // TODO(fbarchard, mtomasz): Use libyuv, then copy the alpha channel.
130 media::ConvertYUVAToARGB(
131 video_frame->data(media::VideoFrame::kYPlane) + y_offset,
132 video_frame->data(media::VideoFrame::kUPlane) + uv_offset,
133 video_frame->data(media::VideoFrame::kVPlane) + uv_offset,
134 video_frame->data(media::VideoFrame::kAPlane),
135 static_cast<uint8*>(bitmap->getPixels()),
136 video_frame->visible_rect().width(),
137 video_frame->visible_rect().height(),
138 video_frame->stride(media::VideoFrame::kYPlane),
139 video_frame->stride(media::VideoFrame::kUPlane),
140 video_frame->stride(media::VideoFrame::kAPlane),
141 bitmap->rowBytes(),
142 media::YV12);
143 break;
144
145 case media::VideoFrame::YV24:
146 libyuv::I444ToARGB(
147 video_frame->data(media::VideoFrame::kYPlane) + y_offset,
148 video_frame->stride(media::VideoFrame::kYPlane),
149 video_frame->data(media::VideoFrame::kUPlane) + uv_offset,
150 video_frame->stride(media::VideoFrame::kUPlane),
151 video_frame->data(media::VideoFrame::kVPlane) + uv_offset,
152 video_frame->stride(media::VideoFrame::kVPlane),
153 static_cast<uint8*>(bitmap->getPixels()),
154 bitmap->rowBytes(),
155 video_frame->visible_rect().width(),
156 video_frame->visible_rect().height());
157 #if SK_R32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_B32_SHIFT == 16 && \
158 SK_A32_SHIFT == 24
159 libyuv::ARGBToABGR(
160 static_cast<uint8*>(bitmap->getPixels()),
161 bitmap->rowBytes(),
162 static_cast<uint8*>(bitmap->getPixels()),
163 bitmap->rowBytes(),
164 video_frame->visible_rect().width(),
165 video_frame->visible_rect().height());
166 #endif
167 break;
168
169 case media::VideoFrame::NATIVE_TEXTURE:
170 DCHECK_EQ(video_frame->format(), media::VideoFrame::NATIVE_TEXTURE);
171 video_frame->ReadPixelsFromNativeTexture(*bitmap);
172 break;
173
174 default:
175 NOTREACHED();
176 break;
177 }
178 bitmap->notifyPixelsChanged();
179 bitmap->unlockPixels();
180 }
181
182 SkCanvasVideoRenderer::SkCanvasVideoRenderer()
183 : last_frame_timestamp_(media::kNoTimestamp()) {
184 }
185
186 SkCanvasVideoRenderer::~SkCanvasVideoRenderer() {}
187
188 void SkCanvasVideoRenderer::Paint(media::VideoFrame* video_frame,
189 SkCanvas* canvas,
190 const gfx::RectF& dest_rect,
191 uint8 alpha) {
192 if (alpha == 0) {
193 return;
194 }
195
196 SkRect dest;
197 dest.set(dest_rect.x(), dest_rect.y(), dest_rect.right(), dest_rect.bottom());
198
199 SkPaint paint;
200 paint.setAlpha(alpha);
201
202 // Paint black rectangle if there isn't a frame available or the
203 // frame has an unexpected format.
204 if (!video_frame || !IsYUVOrNative(video_frame->format())) {
205 canvas->drawRect(dest, paint);
206 return;
207 }
208
209 // Check if we should convert and update |last_frame_|.
210 if (last_frame_.isNull() ||
211 video_frame->timestamp() != last_frame_timestamp_) {
212 ConvertVideoFrameToBitmap(video_frame, &last_frame_);
213 last_frame_timestamp_ = video_frame->timestamp();
214 }
215
216 // Use SRC mode so we completely overwrite the buffer (in case we have alpha)
217 // this means we don't need the extra cost of clearing the buffer first.
218 paint.setXfermode(SkXfermode::Create(SkXfermode::kSrc_Mode));
219
220 // Paint using |last_frame_|.
221 paint.setFilterLevel(SkPaint::kLow_FilterLevel);
222 canvas->drawBitmapRect(last_frame_, NULL, dest, &paint);
223 }
224
225 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698