| 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 |