OLD | NEW |
1 // Copyright 2011 The Chromium Authors. All rights reserved. | 1 // Copyright 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "config.h" | 5 #include "config.h" |
6 | 6 |
7 #include "cc/video_layer_impl.h" | 7 #include "cc/video_layer_impl.h" |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "cc/io_surface_draw_quad.h" | 10 #include "cc/io_surface_draw_quad.h" |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
149 } | 149 } |
150 | 150 |
151 m_webFrame = m_provider->getCurrentFrame(); | 151 m_webFrame = m_provider->getCurrentFrame(); |
152 m_frame = m_unwrapper.Run(m_webFrame); | 152 m_frame = m_unwrapper.Run(m_webFrame); |
153 | 153 |
154 if (!m_frame) | 154 if (!m_frame) |
155 return; | 155 return; |
156 | 156 |
157 m_format = convertVFCFormatToGLenum(*m_frame); | 157 m_format = convertVFCFormatToGLenum(*m_frame); |
158 | 158 |
| 159 // If these fail, we'll have to add draw logic that handles offset bitmap/ |
| 160 // texture UVs. For now, just expect (0, 0) offset, since all our decoders |
| 161 // so far don't offset. |
| 162 DCHECK_EQ(m_frame->visible_rect().x(), 0); |
| 163 DCHECK_EQ(m_frame->visible_rect().y(), 0); |
| 164 |
159 if (m_format == GL_INVALID_VALUE) { | 165 if (m_format == GL_INVALID_VALUE) { |
160 m_provider->putCurrentFrame(m_webFrame); | 166 m_provider->putCurrentFrame(m_webFrame); |
161 m_frame = 0; | 167 m_frame = 0; |
162 return; | 168 return; |
163 } | 169 } |
164 | 170 |
165 // FIXME: If we're in software compositing mode, we do the YUV -> RGB | 171 // FIXME: If we're in software compositing mode, we do the YUV -> RGB |
166 // conversion here. That involves an extra copy of each frame to a bitmap. | 172 // conversion here. That involves an extra copy of each frame to a bitmap. |
167 // Obviously, this is suboptimal and should be addressed once ubercompositor | 173 // Obviously, this is suboptimal and should be addressed once ubercompositor |
168 // starts shaping up. | 174 // starts shaping up. |
(...skipping 27 matching lines...) Expand all Loading... |
196 if (!m_frame) | 202 if (!m_frame) |
197 return; | 203 return; |
198 | 204 |
199 SharedQuadState* sharedQuadState = quadSink.useSharedQuadState(createSharedQ
uadState()); | 205 SharedQuadState* sharedQuadState = quadSink.useSharedQuadState(createSharedQ
uadState()); |
200 appendDebugBorderQuad(quadSink, sharedQuadState, appendQuadsData); | 206 appendDebugBorderQuad(quadSink, sharedQuadState, appendQuadsData); |
201 | 207 |
202 // FIXME: When we pass quads out of process, we need to double-buffer, or | 208 // FIXME: When we pass quads out of process, we need to double-buffer, or |
203 // otherwise synchonize use of all textures in the quad. | 209 // otherwise synchonize use of all textures in the quad. |
204 | 210 |
205 gfx::Rect quadRect(gfx::Point(), contentBounds()); | 211 gfx::Rect quadRect(gfx::Point(), contentBounds()); |
| 212 gfx::Rect visibleRect = m_frame->visible_rect(); |
| 213 gfx::Size codedSize = m_frame->coded_size(); |
| 214 |
| 215 // pixels for macroblocked formats. |
| 216 const float texWidthScale = |
| 217 static_cast<float>(visibleRect.width()) / codedSize.width(); |
| 218 const float texHeightScale = |
| 219 static_cast<float>(visibleRect.height()) / codedSize.height(); |
206 | 220 |
207 switch (m_format) { | 221 switch (m_format) { |
208 case GL_LUMINANCE: { | 222 case GL_LUMINANCE: { |
209 // YUV software decoder. | 223 // YUV software decoder. |
210 const FramePlane& yPlane = m_framePlanes[media::VideoFrame::kYPlane]; | 224 const FramePlane& yPlane = m_framePlanes[media::VideoFrame::kYPlane]; |
211 const FramePlane& uPlane = m_framePlanes[media::VideoFrame::kUPlane]; | 225 const FramePlane& uPlane = m_framePlanes[media::VideoFrame::kUPlane]; |
212 const FramePlane& vPlane = m_framePlanes[media::VideoFrame::kVPlane]; | 226 const FramePlane& vPlane = m_framePlanes[media::VideoFrame::kVPlane]; |
213 scoped_ptr<YUVVideoDrawQuad> yuvVideoQuad = YUVVideoDrawQuad::create(sha
redQuadState, quadRect, yPlane, uPlane, vPlane); | 227 gfx::SizeF texScale(texWidthScale, texHeightScale); |
| 228 scoped_ptr<YUVVideoDrawQuad> yuvVideoQuad = YUVVideoDrawQuad::create( |
| 229 sharedQuadState, quadRect, texScale, yPlane, uPlane, vPlane); |
214 quadSink.append(yuvVideoQuad.PassAs<DrawQuad>(), appendQuadsData); | 230 quadSink.append(yuvVideoQuad.PassAs<DrawQuad>(), appendQuadsData); |
215 break; | 231 break; |
216 } | 232 } |
217 case GL_RGBA: { | 233 case GL_RGBA: { |
218 // RGBA software decoder. | 234 // RGBA software decoder. |
219 const FramePlane& plane = m_framePlanes[media::VideoFrame::kRGBPlane]; | 235 const FramePlane& plane = m_framePlanes[media::VideoFrame::kRGBPlane]; |
220 bool premultipliedAlpha = true; | 236 bool premultipliedAlpha = true; |
221 float widthScaleFactor = static_cast<float>(plane.visibleSize.width()) /
plane.size.width(); | 237 gfx::RectF uvRect(0, 0, texWidthScale, texHeightScale); |
222 gfx::RectF uvRect(widthScaleFactor, 1); | |
223 bool flipped = false; | 238 bool flipped = false; |
224 scoped_ptr<TextureDrawQuad> textureQuad = TextureDrawQuad::create(shared
QuadState, quadRect, plane.resourceId, premultipliedAlpha, uvRect, flipped); | 239 scoped_ptr<TextureDrawQuad> textureQuad = TextureDrawQuad::create(shared
QuadState, quadRect, plane.resourceId, premultipliedAlpha, uvRect, flipped); |
225 quadSink.append(textureQuad.PassAs<DrawQuad>(), appendQuadsData); | 240 quadSink.append(textureQuad.PassAs<DrawQuad>(), appendQuadsData); |
226 break; | 241 break; |
227 } | 242 } |
228 case GL_TEXTURE_2D: { | 243 case GL_TEXTURE_2D: { |
229 // NativeTexture hardware decoder. | 244 // NativeTexture hardware decoder. |
230 bool premultipliedAlpha = true; | 245 bool premultipliedAlpha = true; |
231 gfx::RectF uvRect(1, 1); | 246 gfx::RectF uvRect(0, 0, texWidthScale, texHeightScale); |
232 bool flipped = false; | 247 bool flipped = false; |
233 scoped_ptr<TextureDrawQuad> textureQuad = TextureDrawQuad::create(shared
QuadState, quadRect, m_externalTextureResource, premultipliedAlpha, uvRect, flip
ped); | 248 scoped_ptr<TextureDrawQuad> textureQuad = TextureDrawQuad::create(shared
QuadState, quadRect, m_externalTextureResource, premultipliedAlpha, uvRect, flip
ped); |
234 quadSink.append(textureQuad.PassAs<DrawQuad>(), appendQuadsData); | 249 quadSink.append(textureQuad.PassAs<DrawQuad>(), appendQuadsData); |
235 break; | 250 break; |
236 } | 251 } |
237 case GL_TEXTURE_RECTANGLE_ARB: { | 252 case GL_TEXTURE_RECTANGLE_ARB: { |
238 scoped_ptr<IOSurfaceDrawQuad> ioSurfaceQuad = IOSurfaceDrawQuad::create(
sharedQuadState, quadRect, m_frame->data_size(), m_frame->texture_id(), IOSurfac
eDrawQuad::Unflipped); | 253 gfx::Size visibleSize(visibleRect.width(), visibleRect.height()); |
| 254 scoped_ptr<IOSurfaceDrawQuad> ioSurfaceQuad = IOSurfaceDrawQuad::create(
sharedQuadState, quadRect, visibleSize, m_frame->texture_id(), IOSurfaceDrawQuad
::Unflipped); |
239 quadSink.append(ioSurfaceQuad.PassAs<DrawQuad>(), appendQuadsData); | 255 quadSink.append(ioSurfaceQuad.PassAs<DrawQuad>(), appendQuadsData); |
240 break; | 256 break; |
241 } | 257 } |
242 case GL_TEXTURE_EXTERNAL_OES: { | 258 case GL_TEXTURE_EXTERNAL_OES: { |
243 // StreamTexture hardware decoder. | 259 // StreamTexture hardware decoder. |
244 scoped_ptr<StreamVideoDrawQuad> streamVideoQuad = StreamVideoDrawQuad::c
reate(sharedQuadState, quadRect, m_frame->texture_id(), m_streamTextureMatrix); | 260 WebKit::WebTransformationMatrix transform(m_streamTextureMatrix); |
| 261 transform.scaleNonUniform(texWidthScale, texHeightScale); |
| 262 scoped_ptr<StreamVideoDrawQuad> streamVideoQuad = |
| 263 StreamVideoDrawQuad::create(sharedQuadState, quadRect, |
| 264 m_frame->texture_id(), |
| 265 transform); |
245 quadSink.append(streamVideoQuad.PassAs<DrawQuad>(), appendQuadsData); | 266 quadSink.append(streamVideoQuad.PassAs<DrawQuad>(), appendQuadsData); |
246 break; | 267 break; |
247 } | 268 } |
248 default: | 269 default: |
249 NOTREACHED(); // Someone updated convertVFCFormatToGLenum above but upd
ate this! | 270 NOTREACHED(); // Someone updated convertVFCFormatToGLenum above but upd
ate this! |
250 break; | 271 break; |
251 } | 272 } |
252 } | 273 } |
253 | 274 |
254 void VideoLayerImpl::didDraw(ResourceProvider* resourceProvider) | 275 void VideoLayerImpl::didDraw(ResourceProvider* resourceProvider) |
(...skipping 13 matching lines...) Expand all Loading... |
268 resourceProvider->deleteResource(m_externalTextureResource); | 289 resourceProvider->deleteResource(m_externalTextureResource); |
269 m_externalTextureResource = 0; | 290 m_externalTextureResource = 0; |
270 } | 291 } |
271 | 292 |
272 m_provider->putCurrentFrame(m_webFrame); | 293 m_provider->putCurrentFrame(m_webFrame); |
273 m_frame = 0; | 294 m_frame = 0; |
274 | 295 |
275 m_providerLock.Release(); | 296 m_providerLock.Release(); |
276 } | 297 } |
277 | 298 |
278 static int videoFrameDimension(int originalDimension, size_t plane, int format) | 299 static gfx::Size videoFrameDimension(media::VideoFrame* frame, int plane) { |
279 { | 300 gfx::Size dimensions = frame->coded_size(); |
280 if (format == media::VideoFrame::YV12 && plane != media::VideoFrame::kYPlane
) | 301 switch (frame->format()) { |
281 return originalDimension / 2; | 302 case media::VideoFrame::YV12: |
282 return originalDimension; | 303 if (plane != media::VideoFrame::kYPlane) { |
| 304 dimensions.set_width(dimensions.width() / 2); |
| 305 dimensions.set_height(dimensions.height() / 2); |
| 306 } |
| 307 break; |
| 308 case media::VideoFrame::YV16: |
| 309 if (plane != media::VideoFrame::kYPlane) { |
| 310 dimensions.set_width(dimensions.width() / 2); |
| 311 } |
| 312 break; |
| 313 default: |
| 314 break; |
| 315 } |
| 316 return dimensions; |
283 } | 317 } |
284 | 318 |
285 static bool hasPaddingBytes(const media::VideoFrame& frame, size_t plane) | 319 bool VideoLayerImpl::FramePlane::allocateData( |
286 { | 320 ResourceProvider* resourceProvider) |
287 return frame.stride(plane) > videoFrameDimension(frame.data_size().width(),
plane, frame.format()); | |
288 } | |
289 | |
290 gfx::Size computeVisibleSize(const media::VideoFrame& frame, size_t plane) | |
291 { | |
292 int visibleWidth = videoFrameDimension(frame.data_size().width(), plane, fra
me.format()); | |
293 int originalWidth = visibleWidth; | |
294 int visibleHeight = videoFrameDimension(frame.data_size().height(), plane, f
rame.format()); | |
295 | |
296 // When there are dead pixels at the edge of the texture, decrease | |
297 // the frame width by 1 to prevent the rightmost pixels from | |
298 // interpolating with the dead pixels. | |
299 if (hasPaddingBytes(frame, plane)) | |
300 --visibleWidth; | |
301 | |
302 // In YV12, every 2x2 square of Y values corresponds to one U and | |
303 // one V value. If we decrease the width of the UV plane, we must decrease t
he | |
304 // width of the Y texture by 2 for proper alignment. This must happen | |
305 // always, even if Y's texture does not have padding bytes. | |
306 if (plane == media::VideoFrame::kYPlane && frame.format() == media::VideoFra
me::YV12) { | |
307 if (hasPaddingBytes(frame, media::VideoFrame::kUPlane)) | |
308 visibleWidth = originalWidth - 2; | |
309 } | |
310 | |
311 return gfx::Size(visibleWidth, visibleHeight); | |
312 } | |
313 | |
314 bool VideoLayerImpl::FramePlane::allocateData(ResourceProvider* resourceProvider
) | |
315 { | 321 { |
316 if (resourceId) | 322 if (resourceId) |
317 return true; | 323 return true; |
318 | 324 |
319 resourceId = resourceProvider->createResource(Renderer::ImplPool, size, form
at, ResourceProvider::TextureUsageAny); | 325 resourceId = resourceProvider->createResource(Renderer::ImplPool, size, form
at, ResourceProvider::TextureUsageAny); |
320 return resourceId; | 326 return resourceId; |
321 } | 327 } |
322 | 328 |
323 void VideoLayerImpl::FramePlane::freeData(ResourceProvider* resourceProvider) | 329 void VideoLayerImpl::FramePlane::freeData(ResourceProvider* resourceProvider) |
324 { | 330 { |
325 if (!resourceId) | 331 if (!resourceId) |
326 return; | 332 return; |
327 | 333 |
328 resourceProvider->deleteResource(resourceId); | 334 resourceProvider->deleteResource(resourceId); |
329 resourceId = 0; | 335 resourceId = 0; |
330 } | 336 } |
331 | 337 |
332 bool VideoLayerImpl::allocatePlaneData(ResourceProvider* resourceProvider) | 338 bool VideoLayerImpl::allocatePlaneData(ResourceProvider* resourceProvider) |
333 { | 339 { |
334 const int maxTextureSize = resourceProvider->maxTextureSize(); | 340 const int maxTextureSize = resourceProvider->maxTextureSize(); |
335 const size_t planeCount = numPlanes(); | 341 const size_t planeCount = numPlanes(); |
336 for (size_t planeIndex = 0; planeIndex < planeCount; ++planeIndex) { | 342 for (unsigned planeIdx = 0; planeIdx < planeCount; ++planeIdx) { |
337 VideoLayerImpl::FramePlane& plane = m_framePlanes[planeIndex]; | 343 VideoLayerImpl::FramePlane& plane = m_framePlanes[planeIdx]; |
338 | 344 |
339 gfx::Size requiredTextureSize(m_frame->stride(planeIndex), videoFrameDim
ension(m_frame->data_size().height(), planeIndex, m_frame->format())); | 345 gfx::Size requiredTextureSize = videoFrameDimension(m_frame, planeIdx); |
340 // FIXME: Remove the test against maxTextureSize when tiled layers are i
mplemented. | 346 // FIXME: Remove the test against maxTextureSize when tiled layers are |
341 if (requiredTextureSize.IsEmpty() || requiredTextureSize.width() > maxTe
xtureSize || requiredTextureSize.height() > maxTextureSize) | 347 // implemented. |
| 348 if (requiredTextureSize.IsEmpty() || |
| 349 requiredTextureSize.width() > maxTextureSize || |
| 350 requiredTextureSize.height() > maxTextureSize) |
342 return false; | 351 return false; |
343 | 352 |
344 if (plane.size != requiredTextureSize || plane.format != m_format) { | 353 if (plane.size != requiredTextureSize || plane.format != m_format) { |
345 plane.freeData(resourceProvider); | 354 plane.freeData(resourceProvider); |
346 plane.size = requiredTextureSize; | 355 plane.size = requiredTextureSize; |
347 plane.format = m_format; | 356 plane.format = m_format; |
348 } | 357 } |
349 | 358 |
350 if (!plane.resourceId) { | 359 if (!plane.allocateData(resourceProvider)) |
351 if (!plane.allocateData(resourceProvider)) | 360 return false; |
352 return false; | |
353 plane.visibleSize = computeVisibleSize(*m_frame, planeIndex); | |
354 } | |
355 } | 361 } |
356 return true; | 362 return true; |
357 } | 363 } |
358 | 364 |
359 bool VideoLayerImpl::copyPlaneData(ResourceProvider* resourceProvider) | 365 bool VideoLayerImpl::copyPlaneData(ResourceProvider* resourceProvider) |
360 { | 366 { |
361 const size_t planeCount = numPlanes(); | 367 const size_t planeCount = numPlanes(); |
362 if (!planeCount) | 368 if (!planeCount) |
363 return true; | 369 return true; |
364 | 370 |
365 if (m_convertYUV) { | 371 if (m_convertYUV) { |
366 if (!m_videoRenderer) | 372 if (!m_videoRenderer) |
367 m_videoRenderer.reset(new media::SkCanvasVideoRenderer); | 373 m_videoRenderer.reset(new media::SkCanvasVideoRenderer); |
368 VideoLayerImpl::FramePlane& plane = m_framePlanes[media::VideoFrame::kRG
BPlane]; | 374 VideoLayerImpl::FramePlane& plane = m_framePlanes[media::VideoFrame::kRG
BPlane]; |
369 ResourceProvider::ScopedWriteLockSoftware lock(resourceProvider, plane.r
esourceId); | 375 ResourceProvider::ScopedWriteLockSoftware lock(resourceProvider, plane.r
esourceId); |
370 m_videoRenderer->Paint(m_frame, lock.skCanvas(), gfx::Rect(plane.size),
0xFF); | 376 m_videoRenderer->Paint(m_frame, lock.skCanvas(), m_frame->visible_rect()
, 0xFF); |
371 return true; | 377 return true; |
372 } | 378 } |
373 | 379 |
374 for (size_t planeIndex = 0; planeIndex < planeCount; ++planeIndex) { | 380 for (size_t planeIndex = 0; planeIndex < planeCount; ++planeIndex) { |
375 VideoLayerImpl::FramePlane& plane = m_framePlanes[planeIndex]; | 381 VideoLayerImpl::FramePlane& plane = m_framePlanes[planeIndex]; |
| 382 // Only non-FormatNativeTexture planes should need upload. |
| 383 DCHECK_EQ(plane.format, GL_LUMINANCE); |
376 const uint8_t* softwarePlanePixels = m_frame->data(planeIndex); | 384 const uint8_t* softwarePlanePixels = m_frame->data(planeIndex); |
377 gfx::Rect planeRect(gfx::Point(), plane.size); | 385 gfx::Rect planeRect(gfx::Point(), plane.size); |
378 resourceProvider->setPixels(plane.resourceId, softwarePlanePixels, plane
Rect, planeRect, gfx::Vector2d()); | 386 resourceProvider->setPixels(plane.resourceId, softwarePlanePixels, plane
Rect, planeRect, gfx::Vector2d()); |
379 } | 387 } |
380 return true; | 388 return true; |
381 } | 389 } |
382 | 390 |
383 void VideoLayerImpl::freePlaneData(ResourceProvider* resourceProvider) | 391 void VideoLayerImpl::freePlaneData(ResourceProvider* resourceProvider) |
384 { | 392 { |
385 for (size_t i = 0; i < media::VideoFrame::kMaxPlanes; ++i) | 393 for (size_t i = 0; i < media::VideoFrame::kMaxPlanes; ++i) |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
424 str->append("video layer\n"); | 432 str->append("video layer\n"); |
425 LayerImpl::dumpLayerProperties(str, indent); | 433 LayerImpl::dumpLayerProperties(str, indent); |
426 } | 434 } |
427 | 435 |
428 const char* VideoLayerImpl::layerTypeAsString() const | 436 const char* VideoLayerImpl::layerTypeAsString() const |
429 { | 437 { |
430 return "VideoLayer"; | 438 return "VideoLayer"; |
431 } | 439 } |
432 | 440 |
433 } // namespace cc | 441 } // namespace cc |
OLD | NEW |