| Index: cc/video_layer_impl.cc
 | 
| diff --git a/cc/video_layer_impl.cc b/cc/video_layer_impl.cc
 | 
| index 86cf037eb8baa87676451710629a73fdde0bc619..43e88646bd223d296eb23b8eaa249ff3b27af31f 100644
 | 
| --- a/cc/video_layer_impl.cc
 | 
| +++ b/cc/video_layer_impl.cc
 | 
| @@ -6,7 +6,7 @@
 | 
|  
 | 
|  #include "cc/video_layer_impl.h"
 | 
|  
 | 
| -#include "NotImplemented.h"
 | 
| +#include "base/logging.h"
 | 
|  #include "cc/io_surface_draw_quad.h"
 | 
|  #include "cc/layer_tree_host_impl.h"
 | 
|  #include "cc/proxy.h"
 | 
| @@ -15,16 +15,21 @@
 | 
|  #include "cc/stream_video_draw_quad.h"
 | 
|  #include "cc/texture_draw_quad.h"
 | 
|  #include "cc/yuv_video_draw_quad.h"
 | 
| +#include "media/filters/skcanvas_video_renderer.h"
 | 
|  #include "third_party/khronos/GLES2/gl2.h"
 | 
|  #include "third_party/khronos/GLES2/gl2ext.h"
 | 
| -#include <public/WebVideoFrame.h>
 | 
|  
 | 
|  namespace cc {
 | 
|  
 | 
| -VideoLayerImpl::VideoLayerImpl(int id, WebKit::WebVideoFrameProvider* provider)
 | 
| +VideoLayerImpl::VideoLayerImpl(int id, WebKit::WebVideoFrameProvider* provider,
 | 
| +                               const FrameUnwrapper& unwrapper)
 | 
|      : LayerImpl(id)
 | 
|      , m_provider(provider)
 | 
| +    , m_unwrapper(unwrapper)
 | 
| +    , m_webFrame(0)
 | 
|      , m_frame(0)
 | 
| +    , m_format(GL_INVALID_VALUE)
 | 
| +    , m_convertYUV(false)
 | 
|      , m_externalTextureResource(0)
 | 
|  {
 | 
|      // This matrix is the default transformation for stream textures, and flips on the Y axis.
 | 
| @@ -53,8 +58,8 @@ VideoLayerImpl::~VideoLayerImpl()
 | 
|      freePlaneData(layerTreeHostImpl()->resourceProvider());
 | 
|  
 | 
|  #ifndef NDEBUG
 | 
| -    for (unsigned i = 0; i < WebKit::WebVideoFrame::maxPlanes; ++i)
 | 
| -      DCHECK(!m_framePlanes[i].resourceId);
 | 
| +    for (size_t i = 0; i < media::VideoFrame::kMaxPlanes; ++i)
 | 
| +        DCHECK(!m_framePlanes[i].resourceId);
 | 
|      DCHECK(!m_externalTextureResource);
 | 
|  #endif
 | 
|  }
 | 
| @@ -68,24 +73,50 @@ void VideoLayerImpl::stopUsingProvider()
 | 
|      m_provider = 0;
 | 
|  }
 | 
|  
 | 
| -// Convert WebKit::WebVideoFrame::Format to GraphicsContext3D's format enum values.
 | 
| -static GLenum convertVFCFormatToGC3DFormat(const WebKit::WebVideoFrame& frame)
 | 
| +// Convert media::VideoFrame::Format to OpenGL enum values.
 | 
| +static GLenum convertVFCFormatToGLenum(const media::VideoFrame& frame)
 | 
|  {
 | 
|      switch (frame.format()) {
 | 
| -    case WebKit::WebVideoFrame::FormatYV12:
 | 
| -    case WebKit::WebVideoFrame::FormatYV16:
 | 
| +    case media::VideoFrame::YV12:
 | 
| +    case media::VideoFrame::YV16:
 | 
|          return GL_LUMINANCE;
 | 
| -    case WebKit::WebVideoFrame::FormatNativeTexture:
 | 
| -        return frame.textureTarget();
 | 
| -    case WebKit::WebVideoFrame::FormatInvalid:
 | 
| -    case WebKit::WebVideoFrame::FormatRGB32:
 | 
| -    case WebKit::WebVideoFrame::FormatEmpty:
 | 
| -    case WebKit::WebVideoFrame::FormatI420:
 | 
| -        notImplemented();
 | 
| +    case media::VideoFrame::NATIVE_TEXTURE:
 | 
| +        return frame.texture_target();
 | 
| +    case media::VideoFrame::INVALID:
 | 
| +    case media::VideoFrame::RGB32:
 | 
| +    case media::VideoFrame::EMPTY:
 | 
| +    case media::VideoFrame::I420:
 | 
| +        NOTREACHED();
 | 
| +        break;
 | 
|      }
 | 
|      return GL_INVALID_VALUE;
 | 
|  }
 | 
|  
 | 
| +size_t VideoLayerImpl::numPlanes() const
 | 
| +{
 | 
| +    if (!m_frame)
 | 
| +        return 0;
 | 
| +
 | 
| +    if (m_convertYUV)
 | 
| +        return 1;
 | 
| +
 | 
| +    switch (m_frame->format()) {
 | 
| +    case media::VideoFrame::RGB32:
 | 
| +        return 1;
 | 
| +    case media::VideoFrame::YV12:
 | 
| +    case media::VideoFrame::YV16:
 | 
| +        return 3;
 | 
| +    case media::VideoFrame::INVALID:
 | 
| +    case media::VideoFrame::EMPTY:
 | 
| +    case media::VideoFrame::I420:
 | 
| +        break;
 | 
| +    case media::VideoFrame::NATIVE_TEXTURE:
 | 
| +        return 0;
 | 
| +    }
 | 
| +    NOTREACHED();
 | 
| +    return 0;
 | 
| +}
 | 
| +
 | 
|  void VideoLayerImpl::willDraw(ResourceProvider* resourceProvider)
 | 
|  {
 | 
|      DCHECK(Proxy::isImplThread());
 | 
| @@ -117,39 +148,45 @@ void VideoLayerImpl::willDrawInternal(ResourceProvider* resourceProvider)
 | 
|          return;
 | 
|      }
 | 
|  
 | 
| -    m_frame = m_provider->getCurrentFrame();
 | 
| +    m_webFrame = m_provider->getCurrentFrame();
 | 
| +    m_frame = m_unwrapper.Run(m_webFrame);
 | 
|  
 | 
|      if (!m_frame)
 | 
|          return;
 | 
|  
 | 
| -    m_format = convertVFCFormatToGC3DFormat(*m_frame);
 | 
| +    m_format = convertVFCFormatToGLenum(*m_frame);
 | 
|  
 | 
|      if (m_format == GL_INVALID_VALUE) {
 | 
| -        m_provider->putCurrentFrame(m_frame);
 | 
| +        m_provider->putCurrentFrame(m_webFrame);
 | 
|          m_frame = 0;
 | 
|          return;
 | 
|      }
 | 
|  
 | 
| -    if (m_frame->planes() > WebKit::WebVideoFrame::maxPlanes) {
 | 
| -        m_provider->putCurrentFrame(m_frame);
 | 
| -        m_frame = 0;
 | 
| -        return;
 | 
| -    }
 | 
| +    // FIXME: If we're in software compositing mode, we do the YUV -> RGB
 | 
| +    // conversion here. That involves an extra copy of each frame to a bitmap.
 | 
| +    // Obviously, this is suboptimal and should be addressed once ubercompositor
 | 
| +    // starts shaping up.
 | 
| +    m_convertYUV = resourceProvider->defaultResourceType() == ResourceProvider::Bitmap &&
 | 
| +        (m_frame->format() == media::VideoFrame::YV12 ||
 | 
| +         m_frame->format() == media::VideoFrame::YV16);
 | 
| +
 | 
| +    if (m_convertYUV)
 | 
| +        m_format = GL_RGBA;
 | 
|  
 | 
|      if (!allocatePlaneData(resourceProvider)) {
 | 
| -        m_provider->putCurrentFrame(m_frame);
 | 
| +        m_provider->putCurrentFrame(m_webFrame);
 | 
|          m_frame = 0;
 | 
|          return;
 | 
|      }
 | 
|  
 | 
|      if (!copyPlaneData(resourceProvider)) {
 | 
| -        m_provider->putCurrentFrame(m_frame);
 | 
| +        m_provider->putCurrentFrame(m_webFrame);
 | 
|          m_frame = 0;
 | 
|          return;
 | 
|      }
 | 
|  
 | 
|      if (m_format == GL_TEXTURE_2D)
 | 
| -        m_externalTextureResource = resourceProvider->createResourceFromExternalTexture(m_frame->textureId());
 | 
| +        m_externalTextureResource = resourceProvider->createResourceFromExternalTexture(m_frame->texture_id());
 | 
|  }
 | 
|  
 | 
|  void VideoLayerImpl::appendQuads(QuadSink& quadSink, AppendQuadsData& appendQuadsData)
 | 
| @@ -165,25 +202,24 @@ void VideoLayerImpl::appendQuads(QuadSink& quadSink, AppendQuadsData& appendQuad
 | 
|      // FIXME: When we pass quads out of process, we need to double-buffer, or
 | 
|      // otherwise synchonize use of all textures in the quad.
 | 
|  
 | 
| -    IntRect quadRect(IntPoint(), contentBounds());
 | 
| +    gfx::Rect quadRect(contentBounds());
 | 
|  
 | 
|      switch (m_format) {
 | 
|      case GL_LUMINANCE: {
 | 
|          // YUV software decoder.
 | 
| -        const FramePlane& yPlane = m_framePlanes[WebKit::WebVideoFrame::yPlane];
 | 
| -        const FramePlane& uPlane = m_framePlanes[WebKit::WebVideoFrame::uPlane];
 | 
| -        const FramePlane& vPlane = m_framePlanes[WebKit::WebVideoFrame::vPlane];
 | 
| +        const FramePlane& yPlane = m_framePlanes[media::VideoFrame::kYPlane];
 | 
| +        const FramePlane& uPlane = m_framePlanes[media::VideoFrame::kUPlane];
 | 
| +        const FramePlane& vPlane = m_framePlanes[media::VideoFrame::kVPlane];
 | 
|          scoped_ptr<YUVVideoDrawQuad> yuvVideoQuad = YUVVideoDrawQuad::create(sharedQuadState, quadRect, yPlane, uPlane, vPlane);
 | 
|          quadSink.append(yuvVideoQuad.PassAs<DrawQuad>(), appendQuadsData);
 | 
|          break;
 | 
|      }
 | 
|      case GL_RGBA: {
 | 
|          // RGBA software decoder.
 | 
| -        const FramePlane& plane = m_framePlanes[WebKit::WebVideoFrame::rgbPlane];
 | 
| -        float widthScaleFactor = static_cast<float>(plane.visibleSize.width()) / plane.size.width();
 | 
| -
 | 
| +        const FramePlane& plane = m_framePlanes[media::VideoFrame::kRGBPlane];
 | 
|          bool premultipliedAlpha = true;
 | 
| -        FloatRect uvRect(0, 0, widthScaleFactor, 1);
 | 
| +        float widthScaleFactor = static_cast<float>(plane.visibleSize.width()) / plane.size.width();
 | 
| +        gfx::RectF uvRect(widthScaleFactor, 1);
 | 
|          bool flipped = false;
 | 
|          scoped_ptr<TextureDrawQuad> textureQuad = TextureDrawQuad::create(sharedQuadState, quadRect, plane.resourceId, premultipliedAlpha, uvRect, flipped);
 | 
|          quadSink.append(textureQuad.PassAs<DrawQuad>(), appendQuadsData);
 | 
| @@ -192,26 +228,26 @@ void VideoLayerImpl::appendQuads(QuadSink& quadSink, AppendQuadsData& appendQuad
 | 
|      case GL_TEXTURE_2D: {
 | 
|          // NativeTexture hardware decoder.
 | 
|          bool premultipliedAlpha = true;
 | 
| -        FloatRect uvRect(0, 0, 1, 1);
 | 
| +        gfx::RectF uvRect(1, 1);
 | 
|          bool flipped = false;
 | 
|          scoped_ptr<TextureDrawQuad> textureQuad = TextureDrawQuad::create(sharedQuadState, quadRect, m_externalTextureResource, premultipliedAlpha, uvRect, flipped);
 | 
|          quadSink.append(textureQuad.PassAs<DrawQuad>(), appendQuadsData);
 | 
|          break;
 | 
|      }
 | 
|      case GL_TEXTURE_RECTANGLE_ARB: {
 | 
| -        IntSize textureSize(m_frame->width(), m_frame->height()); 
 | 
| -        scoped_ptr<IOSurfaceDrawQuad> ioSurfaceQuad = IOSurfaceDrawQuad::create(sharedQuadState, quadRect, textureSize, m_frame->textureId(), IOSurfaceDrawQuad::Unflipped);
 | 
| +        scoped_ptr<IOSurfaceDrawQuad> ioSurfaceQuad = IOSurfaceDrawQuad::create(sharedQuadState, quadRect, m_frame->data_size(), m_frame->texture_id(), IOSurfaceDrawQuad::Unflipped);
 | 
|          quadSink.append(ioSurfaceQuad.PassAs<DrawQuad>(), appendQuadsData);
 | 
|          break;
 | 
|      }
 | 
|      case GL_TEXTURE_EXTERNAL_OES: {
 | 
|          // StreamTexture hardware decoder.
 | 
| -        scoped_ptr<StreamVideoDrawQuad> streamVideoQuad = StreamVideoDrawQuad::create(sharedQuadState, quadRect, m_frame->textureId(), m_streamTextureMatrix);
 | 
| +        scoped_ptr<StreamVideoDrawQuad> streamVideoQuad = StreamVideoDrawQuad::create(sharedQuadState, quadRect, m_frame->texture_id(), m_streamTextureMatrix);
 | 
|          quadSink.append(streamVideoQuad.PassAs<DrawQuad>(), appendQuadsData);
 | 
|          break;
 | 
|      }
 | 
|      default:
 | 
| -        CRASH(); // Someone updated convertVFCFormatToGC3DFormat above but update this!
 | 
| +        NOTREACHED();  // Someone updated convertVFCFormatToGLenum above but update this!
 | 
| +        break;
 | 
|      }
 | 
|  }
 | 
|  
 | 
| @@ -233,29 +269,29 @@ void VideoLayerImpl::didDraw(ResourceProvider* resourceProvider)
 | 
|          m_externalTextureResource = 0;
 | 
|      }
 | 
|  
 | 
| -    m_provider->putCurrentFrame(m_frame);
 | 
| +    m_provider->putCurrentFrame(m_webFrame);
 | 
|      m_frame = 0;
 | 
|  
 | 
|      m_providerLock.Release();
 | 
|  }
 | 
|  
 | 
| -static int videoFrameDimension(int originalDimension, unsigned plane, int format)
 | 
| +static int videoFrameDimension(int originalDimension, size_t plane, int format)
 | 
|  {
 | 
| -    if (format == WebKit::WebVideoFrame::FormatYV12 && plane != WebKit::WebVideoFrame::yPlane)
 | 
| +    if (format == media::VideoFrame::YV12 && plane != media::VideoFrame::kYPlane)
 | 
|          return originalDimension / 2;
 | 
|      return originalDimension;
 | 
|  }
 | 
|  
 | 
| -static bool hasPaddingBytes(const WebKit::WebVideoFrame& frame, unsigned plane)
 | 
| +static bool hasPaddingBytes(const media::VideoFrame& frame, size_t plane)
 | 
|  {
 | 
| -    return frame.stride(plane) > videoFrameDimension(frame.width(), plane, frame.format());
 | 
| +    return frame.stride(plane) > videoFrameDimension(frame.data_size().width(), plane, frame.format());
 | 
|  }
 | 
|  
 | 
| -IntSize VideoLayerImpl::computeVisibleSize(const WebKit::WebVideoFrame& frame, unsigned plane)
 | 
| +IntSize computeVisibleSize(const media::VideoFrame& frame, size_t plane)
 | 
|  {
 | 
| -    int visibleWidth = videoFrameDimension(frame.width(), plane, frame.format());
 | 
| +    int visibleWidth = videoFrameDimension(frame.data_size().width(), plane, frame.format());
 | 
|      int originalWidth = visibleWidth;
 | 
| -    int visibleHeight = videoFrameDimension(frame.height(), plane, frame.format());
 | 
| +    int visibleHeight = videoFrameDimension(frame.data_size().height(), plane, frame.format());
 | 
|  
 | 
|      // When there are dead pixels at the edge of the texture, decrease
 | 
|      // the frame width by 1 to prevent the rightmost pixels from
 | 
| @@ -267,8 +303,8 @@ IntSize VideoLayerImpl::computeVisibleSize(const WebKit::WebVideoFrame& frame, u
 | 
|      // one V value. If we decrease the width of the UV plane, we must decrease the
 | 
|      // width of the Y texture by 2 for proper alignment. This must happen
 | 
|      // always, even if Y's texture does not have padding bytes.
 | 
| -    if (plane == WebKit::WebVideoFrame::yPlane && frame.format() == WebKit::WebVideoFrame::FormatYV12) {
 | 
| -        if (hasPaddingBytes(frame, WebKit::WebVideoFrame::uPlane))
 | 
| +    if (plane == media::VideoFrame::kYPlane && frame.format() == media::VideoFrame::YV12) {
 | 
| +        if (hasPaddingBytes(frame, media::VideoFrame::kUPlane))
 | 
|              visibleWidth = originalWidth - 2;
 | 
|      }
 | 
|  
 | 
| @@ -295,11 +331,12 @@ void VideoLayerImpl::FramePlane::freeData(ResourceProvider* resourceProvider)
 | 
|  
 | 
|  bool VideoLayerImpl::allocatePlaneData(ResourceProvider* resourceProvider)
 | 
|  {
 | 
| -    int maxTextureSize = resourceProvider->maxTextureSize();
 | 
| -    for (unsigned planeIndex = 0; planeIndex < m_frame->planes(); ++planeIndex) {
 | 
| +    const int maxTextureSize = resourceProvider->maxTextureSize();
 | 
| +    const size_t planeCount = numPlanes();
 | 
| +    for (size_t planeIndex = 0; planeIndex < planeCount; ++planeIndex) {
 | 
|          VideoLayerImpl::FramePlane& plane = m_framePlanes[planeIndex];
 | 
|  
 | 
| -        IntSize requiredTextureSize(m_frame->stride(planeIndex), videoFrameDimension(m_frame->height(), planeIndex, m_frame->format()));
 | 
| +        IntSize requiredTextureSize(m_frame->stride(planeIndex), videoFrameDimension(m_frame->data_size().height(), planeIndex, m_frame->format()));
 | 
|          // FIXME: Remove the test against maxTextureSize when tiled layers are implemented.
 | 
|          if (requiredTextureSize.isZero() || requiredTextureSize.width() > maxTextureSize || requiredTextureSize.height() > maxTextureSize)
 | 
|              return false;
 | 
| @@ -321,13 +358,22 @@ bool VideoLayerImpl::allocatePlaneData(ResourceProvider* resourceProvider)
 | 
|  
 | 
|  bool VideoLayerImpl::copyPlaneData(ResourceProvider* resourceProvider)
 | 
|  {
 | 
| -    size_t softwarePlaneCount = m_frame->planes();
 | 
| -    if (!softwarePlaneCount)
 | 
| +    const size_t planeCount = numPlanes();
 | 
| +    if (!planeCount)
 | 
|          return true;
 | 
|  
 | 
| -    for (size_t softwarePlaneIndex = 0; softwarePlaneIndex < softwarePlaneCount; ++softwarePlaneIndex) {
 | 
| -        VideoLayerImpl::FramePlane& plane = m_framePlanes[softwarePlaneIndex];
 | 
| -        const uint8_t* softwarePlanePixels = static_cast<const uint8_t*>(m_frame->data(softwarePlaneIndex));
 | 
| +    if (m_convertYUV) {
 | 
| +        if (!m_videoRenderer)
 | 
| +            m_videoRenderer.reset(new media::SkCanvasVideoRenderer);
 | 
| +        VideoLayerImpl::FramePlane& plane = m_framePlanes[media::VideoFrame::kRGBPlane];
 | 
| +        ResourceProvider::ScopedWriteLockSoftware lock(resourceProvider, plane.resourceId);
 | 
| +        m_videoRenderer->Paint(m_frame, lock.skCanvas(), gfx::Rect(plane.size), 0xFF);
 | 
| +        return true;
 | 
| +    }
 | 
| +
 | 
| +    for (size_t planeIndex = 0; planeIndex < planeCount; ++planeIndex) {
 | 
| +        VideoLayerImpl::FramePlane& plane = m_framePlanes[planeIndex];
 | 
| +        const uint8_t* softwarePlanePixels = m_frame->data(planeIndex);
 | 
|          IntRect planeRect(IntPoint(), plane.size);
 | 
|          resourceProvider->upload(plane.resourceId, softwarePlanePixels, planeRect, planeRect, IntSize());
 | 
|      }
 | 
| @@ -336,14 +382,14 @@ bool VideoLayerImpl::copyPlaneData(ResourceProvider* resourceProvider)
 | 
|  
 | 
|  void VideoLayerImpl::freePlaneData(ResourceProvider* resourceProvider)
 | 
|  {
 | 
| -    for (unsigned i = 0; i < WebKit::WebVideoFrame::maxPlanes; ++i)
 | 
| +    for (size_t i = 0; i < media::VideoFrame::kMaxPlanes; ++i)
 | 
|          m_framePlanes[i].freeData(resourceProvider);
 | 
|  }
 | 
|  
 | 
|  void VideoLayerImpl::freeUnusedPlaneData(ResourceProvider* resourceProvider)
 | 
|  {
 | 
| -    unsigned firstUnusedPlane = m_frame ? m_frame->planes() : 0;
 | 
| -    for (unsigned i = firstUnusedPlane; i < WebKit::WebVideoFrame::maxPlanes; ++i)
 | 
| +    size_t firstUnusedPlane = numPlanes();
 | 
| +    for (size_t i = firstUnusedPlane; i < media::VideoFrame::kMaxPlanes; ++i)
 | 
|          m_framePlanes[i].freeData(resourceProvider);
 | 
|  }
 | 
|  
 | 
| 
 |