summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cc/draw_quad_unittest.cc10
-rw-r--r--cc/gl_renderer.cc7
-rw-r--r--cc/layer_tree_host_impl_unittest.cc24
-rw-r--r--cc/resource_provider.cc1
-rw-r--r--cc/shader.cc31
-rw-r--r--cc/shader.h6
-rw-r--r--cc/video_layer_impl.cc112
-rw-r--r--cc/video_layer_impl.h1
-rw-r--r--cc/yuv_video_draw_quad.cc25
-rw-r--r--cc/yuv_video_draw_quad.h23
-rw-r--r--content/renderer/media/local_video_capture.cc4
-rw-r--r--content/renderer/media/rtc_video_decoder.cc1
-rw-r--r--content/renderer/media/rtc_video_decoder_unittest.cc16
-rw-r--r--content/renderer/media/rtc_video_renderer.cc1
-rw-r--r--media/base/video_decoder_config.cc3
-rw-r--r--media/base/video_frame.cc57
-rw-r--r--media/base/video_frame.h43
-rw-r--r--media/base/video_frame_unittest.cc42
-rw-r--r--media/base/video_util_unittest.cc2
-rw-r--r--media/filters/ffmpeg_video_decoder.cc5
-rw-r--r--media/filters/ffmpeg_video_decoder_unittest.cc10
-rw-r--r--media/filters/gpu_video_decoder.cc27
-rw-r--r--media/filters/gpu_video_decoder.h5
-rw-r--r--media/filters/skcanvas_video_renderer.cc71
-rw-r--r--media/filters/skcanvas_video_renderer_unittest.cc150
-rw-r--r--media/filters/video_frame_generator.cc3
-rw-r--r--media/filters/video_renderer_base_unittest.cc3
-rw-r--r--media/tools/player_wtl/view.h25
-rw-r--r--media/tools/player_x11/gl_video_renderer.cc19
-rw-r--r--media/tools/player_x11/gl_video_renderer.h4
-rw-r--r--media/tools/player_x11/x11_video_renderer.cc47
-rw-r--r--media/tools/player_x11/x11_video_renderer.h4
-rw-r--r--media/tools/scaler_bench/scaler_bench.cc6
-rw-r--r--media/tools/shader_bench/cpu_color_painter.cc14
-rw-r--r--media/tools/shader_bench/gpu_color_painter.cc5
-rw-r--r--media/tools/shader_bench/shader_bench.cc3
-rw-r--r--webkit/media/android/webmediaplayer_android.cc4
-rw-r--r--webkit/media/simple_video_frame_provider.cc1
-rw-r--r--webkit/media/webvideoframe_impl.cc30
-rw-r--r--webkit/media/webvideoframe_impl.h7
-rw-r--r--webkit/plugins/ppapi/content_decryptor_delegate.cc2
41 files changed, 572 insertions, 282 deletions
diff --git a/cc/draw_quad_unittest.cc b/cc/draw_quad_unittest.cc
index 2d7055e..a73bbec 100644
--- a/cc/draw_quad_unittest.cc
+++ b/cc/draw_quad_unittest.cc
@@ -278,36 +278,32 @@ TEST(DrawQuadTest, copyTileDrawQuad)
TEST(DrawQuadTest, copyYUVVideoDrawQuad)
{
+ gfx::SizeF texScale(0.75, 0.5);
VideoLayerImpl::FramePlane yPlane;
yPlane.resourceId = 45;
yPlane.size = gfx::Size(34, 23);
yPlane.format = 8;
- yPlane.visibleSize = gfx::Size(623, 235);
VideoLayerImpl::FramePlane uPlane;
uPlane.resourceId = 532;
uPlane.size = gfx::Size(134, 16);
uPlane.format = 2;
- uPlane.visibleSize = gfx::Size(126, 27);
VideoLayerImpl::FramePlane vPlane;
vPlane.resourceId = 4;
vPlane.size = gfx::Size(456, 486);
vPlane.format = 46;
- vPlane.visibleSize = gfx::Size(19, 45);
CREATE_SHARED_STATE();
- CREATE_QUAD_3(YUVVideoDrawQuad, yPlane, uPlane, vPlane);
+ CREATE_QUAD_4(YUVVideoDrawQuad, texScale, yPlane, uPlane, vPlane);
+ EXPECT_EQ(texScale, copyQuad->texScale());
EXPECT_EQ(yPlane.resourceId, copyQuad->yPlane().resourceId);
EXPECT_EQ(yPlane.size, copyQuad->yPlane().size);
EXPECT_EQ(yPlane.format, copyQuad->yPlane().format);
- EXPECT_EQ(yPlane.visibleSize, copyQuad->yPlane().visibleSize);
EXPECT_EQ(uPlane.resourceId, copyQuad->uPlane().resourceId);
EXPECT_EQ(uPlane.size, copyQuad->uPlane().size);
EXPECT_EQ(uPlane.format, copyQuad->uPlane().format);
- EXPECT_EQ(uPlane.visibleSize, copyQuad->uPlane().visibleSize);
EXPECT_EQ(vPlane.resourceId, copyQuad->vPlane().resourceId);
EXPECT_EQ(vPlane.size, copyQuad->vPlane().size);
EXPECT_EQ(vPlane.format, copyQuad->vPlane().format);
- EXPECT_EQ(vPlane.visibleSize, copyQuad->vPlane().visibleSize);
}
} // anonymous namespace
diff --git a/cc/gl_renderer.cc b/cc/gl_renderer.cc
index e5e4347..55e2846 100644
--- a/cc/gl_renderer.cc
+++ b/cc/gl_renderer.cc
@@ -879,12 +879,7 @@ void GLRenderer::drawYUVVideoQuad(const DrawingFrame& frame, const YUVVideoDrawQ
GLC(context(), context()->useProgram(program->program()));
- float yWidthScaleFactor = static_cast<float>(yPlane.visibleSize.width()) / yPlane.size.width();
- // Arbitrarily take the u sizes because u and v dimensions are identical.
- float uvWidthScaleFactor = static_cast<float>(uPlane.visibleSize.width()) / uPlane.size.width();
- GLC(context(), context()->uniform1f(program->vertexShader().yWidthScaleFactorLocation(), yWidthScaleFactor));
- GLC(context(), context()->uniform1f(program->vertexShader().uvWidthScaleFactorLocation(), uvWidthScaleFactor));
-
+ GLC(context(), context()->uniform2f(program->vertexShader().texScaleLocation(), quad->texScale().width(), quad->texScale().height()));
GLC(context(), context()->uniform1i(program->fragmentShader().yTextureLocation(), 1));
GLC(context(), context()->uniform1i(program->fragmentShader().uTextureLocation(), 2));
GLC(context(), context()->uniform1i(program->fragmentShader().vTextureLocation(), 3));
diff --git a/cc/layer_tree_host_impl_unittest.cc b/cc/layer_tree_host_impl_unittest.cc
index ed7ef13..723fcbdc 100644
--- a/cc/layer_tree_host_impl_unittest.cc
+++ b/cc/layer_tree_host_impl_unittest.cc
@@ -2565,6 +2565,8 @@ public:
virtual const void* data(unsigned plane) const { NOTREACHED(); return NULL; }
virtual unsigned textureId() const { NOTREACHED(); return 0; }
virtual unsigned textureTarget() const { NOTREACHED(); return 0; }
+ virtual WebKit::WebRect visibleRect() const { NOTREACHED(); return WebKit::WebRect(0, 0, 0, 0); }
+ virtual WebKit::WebSize textureSize() const { NOTREACHED(); return WebKit::WebSize(4, 4); }
static VideoFrame* toVideoFrame(WebVideoFrame* web_video_frame) {
FakeVideoFrame* wrapped_frame =
@@ -2735,6 +2737,15 @@ TEST_P(LayerTreeHostImplTest, dontUseOldResourcesAfterLostContext)
videoLayer->setLayerTreeHostImpl(m_hostImpl.get());
rootLayer->addChild(videoLayer.PassAs<LayerImpl>());
+ FakeVideoFrameProvider providerScaled;
+ scoped_ptr<VideoLayerImpl> videoLayerScaled = VideoLayerImpl::create(layerId++, &providerScaled, unwrapper);
+ videoLayerScaled->setBounds(gfx::Size(10, 10));
+ videoLayerScaled->setAnchorPoint(gfx::PointF(0, 0));
+ videoLayerScaled->setContentBounds(gfx::Size(10, 10));
+ videoLayerScaled->setDrawsContent(true);
+ videoLayerScaled->setLayerTreeHostImpl(m_hostImpl.get());
+ rootLayer->addChild(videoLayerScaled.PassAs<LayerImpl>());
+
FakeVideoFrameProvider hwProvider;
scoped_ptr<VideoLayerImpl> hwVideoLayer = VideoLayerImpl::create(layerId++, &hwProvider, unwrapper);
hwVideoLayer->setBounds(gfx::Size(10, 10));
@@ -2787,10 +2798,18 @@ TEST_P(LayerTreeHostImplTest, dontUseOldResourcesAfterLostContext)
VideoFrame::WrapNativeTexture(
m_hostImpl->resourceProvider()->graphicsContext3D()->createTexture(),
GL_TEXTURE_2D,
- gfx::Size(4, 4), gfx::Size(4, 4), base::TimeDelta(),
+ gfx::Size(4, 4), gfx::Rect(0, 0, 4, 4), gfx::Size(4, 4), base::TimeDelta(),
VideoFrame::ReadPixelsCB(), base::Closure()));
hwProvider.setFrame(&hwVideoFrame);
+ FakeVideoFrame videoFrameScaled(
+ VideoFrame::WrapNativeTexture(
+ m_hostImpl->resourceProvider()->graphicsContext3D()->createTexture(),
+ GL_TEXTURE_2D,
+ gfx::Size(4, 4), gfx::Rect(0, 0, 3, 2), gfx::Size(4, 4), base::TimeDelta(),
+ VideoFrame::ReadPixelsCB(), base::Closure()));
+ providerScaled.setFrame(&videoFrameScaled);
+
m_hostImpl->setRootLayer(rootLayer.Pass());
LayerTreeHostImpl::FrameData frame;
@@ -2813,6 +2832,7 @@ TEST_P(LayerTreeHostImplTest, dontUseOldResourcesAfterLostContext)
// The WebVideoFrameProvider is expected to recreate its textures after a
// lost context (or not serve a frame).
hwProvider.setFrame(0);
+ providerScaled.setFrame(0);
EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
m_hostImpl->drawLayers(frame);
@@ -2823,7 +2843,7 @@ TEST_P(LayerTreeHostImplTest, dontUseOldResourcesAfterLostContext)
VideoFrame::WrapNativeTexture(
m_hostImpl->resourceProvider()->graphicsContext3D()->createTexture(),
GL_TEXTURE_2D,
- gfx::Size(4, 4), gfx::Size(4, 4), base::TimeDelta(),
+ gfx::Size(4, 4), gfx::Rect(0, 0, 4, 4), gfx::Size(4, 4), base::TimeDelta(),
VideoFrame::ReadPixelsCB(), base::Closure()));
hwProvider.setFrame(&hwVideoFrame2);
diff --git a/cc/resource_provider.cc b/cc/resource_provider.cc
index ec88bb7..3c134ef 100644
--- a/cc/resource_provider.cc
+++ b/cc/resource_provider.cc
@@ -283,6 +283,7 @@ void ResourceProvider::setPixels(ResourceId id, const uint8_t* image, const gfx:
}
if (resource->pixels) {
+ DCHECK(resource->format == GL_RGBA);
SkBitmap srcFull;
srcFull.setConfig(SkBitmap::kARGB_8888_Config, imageRect.width(), imageRect.height());
srcFull.setPixels(const_cast<uint8_t*>(image));
diff --git a/cc/shader.cc b/cc/shader.cc
index 4bed89e..567d56c 100644
--- a/cc/shader.cc
+++ b/cc/shader.cc
@@ -69,8 +69,7 @@ std::string VertexShaderPosTex::getShaderString() const
VertexShaderPosTexYUVStretch::VertexShaderPosTexYUVStretch()
: m_matrixLocation(-1)
- , m_yWidthScaleFactorLocation(-1)
- , m_uvWidthScaleFactorLocation(-1)
+ , m_texScaleLocation(-1)
{
}
@@ -78,17 +77,15 @@ void VertexShaderPosTexYUVStretch::init(WebGraphicsContext3D* context, unsigned
{
static const char* shaderUniforms[] = {
"matrix",
- "y_widthScaleFactor",
- "uv_widthScaleFactor",
+ "texScale",
};
- int locations[3];
+ int locations[2];
getProgramUniformLocations(context, program, shaderUniforms, arraysize(shaderUniforms), arraysize(locations), locations, usingBindUniform, baseUniformIndex);
m_matrixLocation = locations[0];
- m_yWidthScaleFactorLocation = locations[1];
- m_uvWidthScaleFactorLocation = locations[2];
- DCHECK(m_matrixLocation != -1 && m_yWidthScaleFactorLocation != -1 && m_uvWidthScaleFactorLocation != -1);
+ m_texScaleLocation = locations[1];
+ DCHECK(m_matrixLocation != -1 && m_texScaleLocation != -1);
}
std::string VertexShaderPosTexYUVStretch::getShaderString() const
@@ -98,15 +95,12 @@ std::string VertexShaderPosTexYUVStretch::getShaderString() const
attribute vec4 a_position;
attribute vec2 a_texCoord;
uniform mat4 matrix;
- varying vec2 y_texCoord;
- varying vec2 uv_texCoord;
- uniform float y_widthScaleFactor;
- uniform float uv_widthScaleFactor;
+ varying vec2 v_texCoord;
+ uniform vec2 texScale;
void main()
{
gl_Position = matrix * a_position;
- y_texCoord = vec2(y_widthScaleFactor * a_texCoord.x, a_texCoord.y);
- uv_texCoord = vec2(uv_widthScaleFactor * a_texCoord.x, a_texCoord.y);
+ v_texCoord = a_texCoord * texScale;
}
);
}
@@ -782,8 +776,7 @@ std::string FragmentShaderYUVVideo::getShaderString() const
return SHADER(
precision mediump float;
precision mediump int;
- varying vec2 y_texCoord;
- varying vec2 uv_texCoord;
+ varying vec2 v_texCoord;
uniform sampler2D y_texture;
uniform sampler2D u_texture;
uniform sampler2D v_texture;
@@ -792,9 +785,9 @@ std::string FragmentShaderYUVVideo::getShaderString() const
uniform mat3 yuv_matrix;
void main()
{
- float y_raw = texture2D(y_texture, y_texCoord).x;
- float u_unsigned = texture2D(u_texture, uv_texCoord).x;
- float v_unsigned = texture2D(v_texture, uv_texCoord).x;
+ float y_raw = texture2D(y_texture, v_texCoord).x;
+ float u_unsigned = texture2D(u_texture, v_texCoord).x;
+ float v_unsigned = texture2D(v_texture, v_texCoord).x;
vec3 yuv = vec3(y_raw, u_unsigned, v_unsigned) + yuv_adj;
vec3 rgb = yuv_matrix * yuv;
gl_FragColor = vec4(rgb, float(1)) * alpha;
diff --git a/cc/shader.h b/cc/shader.h
index a691712..67e93cb 100644
--- a/cc/shader.h
+++ b/cc/shader.h
@@ -35,13 +35,11 @@ public:
std::string getShaderString() const;
int matrixLocation() const { return m_matrixLocation; }
- int yWidthScaleFactorLocation() const { return m_yWidthScaleFactorLocation; }
- int uvWidthScaleFactorLocation() const { return m_uvWidthScaleFactorLocation; }
+ int texScaleLocation() const { return m_texScaleLocation; }
private:
int m_matrixLocation;
- int m_yWidthScaleFactorLocation;
- int m_uvWidthScaleFactorLocation;
+ int m_texScaleLocation;
};
class VertexShaderPos {
diff --git a/cc/video_layer_impl.cc b/cc/video_layer_impl.cc
index c23225e..3b2e3a9 100644
--- a/cc/video_layer_impl.cc
+++ b/cc/video_layer_impl.cc
@@ -151,6 +151,12 @@ void VideoLayerImpl::willDrawInternal(ResourceProvider* resourceProvider)
m_format = convertVFCFormatToGLenum(*m_frame);
+ // If these fail, we'll have to add draw logic that handles offset bitmap/
+ // texture UVs. For now, just expect (0, 0) offset, since all our decoders
+ // so far don't offset.
+ DCHECK_EQ(m_frame->visible_rect().x(), 0);
+ DCHECK_EQ(m_frame->visible_rect().y(), 0);
+
if (m_format == GL_INVALID_VALUE) {
m_provider->putCurrentFrame(m_webFrame);
m_frame = 0;
@@ -196,6 +202,14 @@ void VideoLayerImpl::appendQuads(QuadSink& quadSink, AppendQuadsData& appendQuad
// otherwise synchonize use of all textures in the quad.
gfx::Rect quadRect(gfx::Point(), contentBounds());
+ gfx::Rect visibleRect = m_frame->visible_rect();
+ gfx::Size codedSize = m_frame->coded_size();
+
+ // pixels for macroblocked formats.
+ const float texWidthScale =
+ static_cast<float>(visibleRect.width()) / codedSize.width();
+ const float texHeightScale =
+ static_cast<float>(visibleRect.height()) / codedSize.height();
switch (m_format) {
case GL_LUMINANCE: {
@@ -203,7 +217,9 @@ void VideoLayerImpl::appendQuads(QuadSink& quadSink, AppendQuadsData& appendQuad
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);
+ gfx::SizeF texScale(texWidthScale, texHeightScale);
+ scoped_ptr<YUVVideoDrawQuad> yuvVideoQuad = YUVVideoDrawQuad::create(
+ sharedQuadState, quadRect, texScale, yPlane, uPlane, vPlane);
quadSink.append(yuvVideoQuad.PassAs<DrawQuad>(), appendQuadsData);
break;
}
@@ -211,8 +227,7 @@ void VideoLayerImpl::appendQuads(QuadSink& quadSink, AppendQuadsData& appendQuad
// RGBA software decoder.
const FramePlane& plane = m_framePlanes[media::VideoFrame::kRGBPlane];
bool premultipliedAlpha = true;
- float widthScaleFactor = static_cast<float>(plane.visibleSize.width()) / plane.size.width();
- gfx::RectF uvRect(widthScaleFactor, 1);
+ gfx::RectF uvRect(0, 0, texWidthScale, texHeightScale);
bool flipped = false;
scoped_ptr<TextureDrawQuad> textureQuad = TextureDrawQuad::create(sharedQuadState, quadRect, plane.resourceId, premultipliedAlpha, uvRect, flipped);
quadSink.append(textureQuad.PassAs<DrawQuad>(), appendQuadsData);
@@ -221,20 +236,26 @@ void VideoLayerImpl::appendQuads(QuadSink& quadSink, AppendQuadsData& appendQuad
case GL_TEXTURE_2D: {
// NativeTexture hardware decoder.
bool premultipliedAlpha = true;
- gfx::RectF uvRect(1, 1);
+ gfx::RectF uvRect(0, 0, texWidthScale, texHeightScale);
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: {
- scoped_ptr<IOSurfaceDrawQuad> ioSurfaceQuad = IOSurfaceDrawQuad::create(sharedQuadState, quadRect, m_frame->data_size(), m_frame->texture_id(), IOSurfaceDrawQuad::Unflipped);
+ gfx::Size visibleSize(visibleRect.width(), visibleRect.height());
+ scoped_ptr<IOSurfaceDrawQuad> ioSurfaceQuad = IOSurfaceDrawQuad::create(sharedQuadState, quadRect, visibleSize, 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->texture_id(), m_streamTextureMatrix);
+ WebKit::WebTransformationMatrix transform(m_streamTextureMatrix);
+ transform.scaleNonUniform(texWidthScale, texHeightScale);
+ scoped_ptr<StreamVideoDrawQuad> streamVideoQuad =
+ StreamVideoDrawQuad::create(sharedQuadState, quadRect,
+ m_frame->texture_id(),
+ transform);
quadSink.append(streamVideoQuad.PassAs<DrawQuad>(), appendQuadsData);
break;
}
@@ -267,43 +288,28 @@ void VideoLayerImpl::didDraw(ResourceProvider* resourceProvider)
m_providerLock.Release();
}
-static int videoFrameDimension(int originalDimension, size_t plane, int format)
-{
- if (format == media::VideoFrame::YV12 && plane != media::VideoFrame::kYPlane)
- return originalDimension / 2;
- return originalDimension;
-}
-
-static bool hasPaddingBytes(const media::VideoFrame& frame, size_t plane)
-{
- return frame.stride(plane) > videoFrameDimension(frame.data_size().width(), plane, frame.format());
-}
-
-gfx::Size computeVisibleSize(const media::VideoFrame& frame, size_t plane)
-{
- int visibleWidth = videoFrameDimension(frame.data_size().width(), plane, frame.format());
- int originalWidth = visibleWidth;
- 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
- // interpolating with the dead pixels.
- if (hasPaddingBytes(frame, plane))
- --visibleWidth;
-
- // In YV12, every 2x2 square of Y values corresponds to one U and
- // 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 == media::VideoFrame::kYPlane && frame.format() == media::VideoFrame::YV12) {
- if (hasPaddingBytes(frame, media::VideoFrame::kUPlane))
- visibleWidth = originalWidth - 2;
+static gfx::Size videoFrameDimension(media::VideoFrame* frame, int plane) {
+ gfx::Size dimensions = frame->coded_size();
+ switch (frame->format()) {
+ case media::VideoFrame::YV12:
+ if (plane != media::VideoFrame::kYPlane) {
+ dimensions.set_width(dimensions.width() / 2);
+ dimensions.set_height(dimensions.height() / 2);
+ }
+ break;
+ case media::VideoFrame::YV16:
+ if (plane != media::VideoFrame::kYPlane) {
+ dimensions.set_width(dimensions.width() / 2);
+ }
+ break;
+ default:
+ break;
}
-
- return gfx::Size(visibleWidth, visibleHeight);
+ return dimensions;
}
-bool VideoLayerImpl::FramePlane::allocateData(ResourceProvider* resourceProvider)
+bool VideoLayerImpl::FramePlane::allocateData(
+ ResourceProvider* resourceProvider)
{
if (resourceId)
return true;
@@ -325,12 +331,15 @@ bool VideoLayerImpl::allocatePlaneData(ResourceProvider* resourceProvider)
{
const int maxTextureSize = resourceProvider->maxTextureSize();
const size_t planeCount = numPlanes();
- for (size_t planeIndex = 0; planeIndex < planeCount; ++planeIndex) {
- VideoLayerImpl::FramePlane& plane = m_framePlanes[planeIndex];
-
- gfx::Size 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.IsEmpty() || requiredTextureSize.width() > maxTextureSize || requiredTextureSize.height() > maxTextureSize)
+ for (unsigned planeIdx = 0; planeIdx < planeCount; ++planeIdx) {
+ VideoLayerImpl::FramePlane& plane = m_framePlanes[planeIdx];
+
+ gfx::Size requiredTextureSize = videoFrameDimension(m_frame, planeIdx);
+ // FIXME: Remove the test against maxTextureSize when tiled layers are
+ // implemented.
+ if (requiredTextureSize.IsEmpty() ||
+ requiredTextureSize.width() > maxTextureSize ||
+ requiredTextureSize.height() > maxTextureSize)
return false;
if (plane.size != requiredTextureSize || plane.format != m_format) {
@@ -339,11 +348,8 @@ bool VideoLayerImpl::allocatePlaneData(ResourceProvider* resourceProvider)
plane.format = m_format;
}
- if (!plane.resourceId) {
- if (!plane.allocateData(resourceProvider))
- return false;
- plane.visibleSize = computeVisibleSize(*m_frame, planeIndex);
- }
+ if (!plane.allocateData(resourceProvider))
+ return false;
}
return true;
}
@@ -359,12 +365,14 @@ bool VideoLayerImpl::copyPlaneData(ResourceProvider* resourceProvider)
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);
+ m_videoRenderer->Paint(m_frame, lock.skCanvas(), m_frame->visible_rect(), 0xFF);
return true;
}
for (size_t planeIndex = 0; planeIndex < planeCount; ++planeIndex) {
VideoLayerImpl::FramePlane& plane = m_framePlanes[planeIndex];
+ // Only non-FormatNativeTexture planes should need upload.
+ DCHECK_EQ(plane.format, GL_LUMINANCE);
const uint8_t* softwarePlanePixels = m_frame->data(planeIndex);
gfx::Rect planeRect(gfx::Point(), plane.size);
resourceProvider->setPixels(plane.resourceId, softwarePlanePixels, planeRect, planeRect, gfx::Vector2d());
diff --git a/cc/video_layer_impl.h b/cc/video_layer_impl.h
index 85e6f37..6291ae1 100644
--- a/cc/video_layer_impl.h
+++ b/cc/video_layer_impl.h
@@ -57,7 +57,6 @@ public:
ResourceProvider::ResourceId resourceId;
gfx::Size size;
GLenum format;
- gfx::Size visibleSize;
FramePlane() : resourceId(0) { }
diff --git a/cc/yuv_video_draw_quad.cc b/cc/yuv_video_draw_quad.cc
index 38ba85f..ff60e1e 100644
--- a/cc/yuv_video_draw_quad.cc
+++ b/cc/yuv_video_draw_quad.cc
@@ -10,19 +10,38 @@
namespace cc {
-scoped_ptr<YUVVideoDrawQuad> YUVVideoDrawQuad::create(const SharedQuadState* sharedQuadState, const gfx::Rect& quadRect, const VideoLayerImpl::FramePlane& yPlane, const VideoLayerImpl::FramePlane& uPlane, const VideoLayerImpl::FramePlane& vPlane)
+scoped_ptr<YUVVideoDrawQuad> YUVVideoDrawQuad::create(
+ const SharedQuadState* sharedQuadState,
+ const gfx::Rect& quadRect,
+ const gfx::SizeF& texScale,
+ const VideoLayerImpl::FramePlane& yPlane,
+ const VideoLayerImpl::FramePlane& uPlane,
+ const VideoLayerImpl::FramePlane& vPlane)
{
- return make_scoped_ptr(new YUVVideoDrawQuad(sharedQuadState, quadRect, yPlane, uPlane, vPlane));
+ return make_scoped_ptr(new YUVVideoDrawQuad(sharedQuadState,
+ quadRect, texScale,
+ yPlane, uPlane, vPlane));
}
-YUVVideoDrawQuad::YUVVideoDrawQuad(const SharedQuadState* sharedQuadState, const gfx::Rect& quadRect, const VideoLayerImpl::FramePlane& yPlane, const VideoLayerImpl::FramePlane& uPlane, const VideoLayerImpl::FramePlane& vPlane)
+YUVVideoDrawQuad::YUVVideoDrawQuad(
+ const SharedQuadState* sharedQuadState,
+ const gfx::Rect& quadRect,
+ const gfx::SizeF& texScale,
+ const VideoLayerImpl::FramePlane& yPlane,
+ const VideoLayerImpl::FramePlane& uPlane,
+ const VideoLayerImpl::FramePlane& vPlane)
: DrawQuad(sharedQuadState, DrawQuad::YUVVideoContent, quadRect)
+ , m_texScale(texScale)
, m_yPlane(yPlane)
, m_uPlane(uPlane)
, m_vPlane(vPlane)
{
}
+YUVVideoDrawQuad::~YUVVideoDrawQuad()
+{
+}
+
const YUVVideoDrawQuad* YUVVideoDrawQuad::materialCast(const DrawQuad* quad)
{
DCHECK(quad->material() == DrawQuad::YUVVideoContent);
diff --git a/cc/yuv_video_draw_quad.h b/cc/yuv_video_draw_quad.h
index 6894c95..8b1ac63 100644
--- a/cc/yuv_video_draw_quad.h
+++ b/cc/yuv_video_draw_quad.h
@@ -15,7 +15,17 @@ namespace cc {
class CC_EXPORT YUVVideoDrawQuad : public DrawQuad {
public:
- static scoped_ptr<YUVVideoDrawQuad> create(const SharedQuadState*, const gfx::Rect&, const VideoLayerImpl::FramePlane& yPlane, const VideoLayerImpl::FramePlane& uPlane, const VideoLayerImpl::FramePlane& vPlane);
+ static scoped_ptr<YUVVideoDrawQuad> create(
+ const SharedQuadState* sharedQuadState,
+ const gfx::Rect& quadRect,
+ const gfx::SizeF& texScale,
+ const VideoLayerImpl::FramePlane& yPlane,
+ const VideoLayerImpl::FramePlane& uPlane,
+ const VideoLayerImpl::FramePlane& vPlane);
+
+ ~YUVVideoDrawQuad();
+
+ const gfx::SizeF& texScale() const { return m_texScale; }
const VideoLayerImpl::FramePlane& yPlane() const { return m_yPlane; }
const VideoLayerImpl::FramePlane& uPlane() const { return m_uPlane; }
@@ -23,8 +33,15 @@ public:
static const YUVVideoDrawQuad* materialCast(const DrawQuad*);
private:
- YUVVideoDrawQuad(const SharedQuadState*, const gfx::Rect&, const VideoLayerImpl::FramePlane& yPlane, const VideoLayerImpl::FramePlane& uPlane, const VideoLayerImpl::FramePlane& vPlane);
-
+ YUVVideoDrawQuad(
+ const SharedQuadState* sharedQuadState,
+ const gfx::Rect& quadRect,
+ const gfx::SizeF& texScale,
+ const VideoLayerImpl::FramePlane& yPlane,
+ const VideoLayerImpl::FramePlane& uPlane,
+ const VideoLayerImpl::FramePlane& vPlane);
+
+ gfx::SizeF m_texScale;
VideoLayerImpl::FramePlane m_yPlane;
VideoLayerImpl::FramePlane m_uPlane;
VideoLayerImpl::FramePlane m_vPlane;
diff --git a/content/renderer/media/local_video_capture.cc b/content/renderer/media/local_video_capture.cc
index b08f221..f4bc376 100644
--- a/content/renderer/media/local_video_capture.cc
+++ b/content/renderer/media/local_video_capture.cc
@@ -128,8 +128,8 @@ void LocalVideoCapture::OnBufferReady(
gfx::Size natural_size(buf->width, buf->height);
scoped_refptr<media::VideoFrame> current_frame =
- media::VideoFrame::CreateFrame(media::VideoFrame::YV12,
- natural_size, natural_size,
+ media::VideoFrame::CreateFrame(media::VideoFrame::YV12, natural_size,
+ gfx::Rect(natural_size), natural_size,
buf->timestamp - base::Time());
uint8* buffer = buf->memory_pointer;
diff --git a/content/renderer/media/rtc_video_decoder.cc b/content/renderer/media/rtc_video_decoder.cc
index 2ca2379..d795daf 100644
--- a/content/renderer/media/rtc_video_decoder.cc
+++ b/content/renderer/media/rtc_video_decoder.cc
@@ -147,6 +147,7 @@ void RTCVideoDecoder::RenderFrame(const cricket::VideoFrame* frame) {
scoped_refptr<media::VideoFrame> video_frame =
media::VideoFrame::CreateFrame(media::VideoFrame::YV12,
visible_size_,
+ gfx::Rect(visible_size_),
visible_size_,
timestamp - start_time_);
last_frame_timestamp_ = timestamp;
diff --git a/content/renderer/media/rtc_video_decoder_unittest.cc b/content/renderer/media/rtc_video_decoder_unittest.cc
index c13b255..ab54037 100644
--- a/content/renderer/media/rtc_video_decoder_unittest.cc
+++ b/content/renderer/media/rtc_video_decoder_unittest.cc
@@ -251,12 +251,20 @@ const int RTCVideoDecoderTest::kHeight = 480;
const PipelineStatistics RTCVideoDecoderTest::kStatistics;
MATCHER_P2(HasSize, width, height, "") {
- EXPECT_EQ(arg->data_size().width(), width);
- EXPECT_EQ(arg->data_size().height(), height);
+ EXPECT_EQ(arg->coded_size().width(), width);
+ EXPECT_EQ(arg->coded_size().height(), height);
+ EXPECT_EQ(arg->visible_rect().x(), 0);
+ EXPECT_EQ(arg->visible_rect().y(), 0);
+ EXPECT_EQ(arg->visible_rect().width(), width);
+ EXPECT_EQ(arg->visible_rect().height(), height);
EXPECT_EQ(arg->natural_size().width(), width);
EXPECT_EQ(arg->natural_size().height(), height);
- return (arg->data_size().width() == width) &&
- (arg->data_size().height() == height) &&
+ return (arg->coded_size().width() == width) &&
+ (arg->coded_size().height() == height) &&
+ (arg->visible_rect().x() == 0) &&
+ (arg->visible_rect().y() == 0) &&
+ (arg->visible_rect().width() == width) &&
+ (arg->visible_rect().height() == height) &&
(arg->natural_size().width() == width) &&
(arg->natural_size().height() == height);
}
diff --git a/content/renderer/media/rtc_video_renderer.cc b/content/renderer/media/rtc_video_renderer.cc
index 14444fa..68d1c97 100644
--- a/content/renderer/media/rtc_video_renderer.cc
+++ b/content/renderer/media/rtc_video_renderer.cc
@@ -75,6 +75,7 @@ void RTCVideoRenderer::RenderFrame(const cricket::VideoFrame* frame) {
scoped_refptr<media::VideoFrame> video_frame =
media::VideoFrame::CreateFrame(media::VideoFrame::YV12,
size,
+ gfx::Rect(size),
size,
timestamp);
diff --git a/media/base/video_decoder_config.cc b/media/base/video_decoder_config.cc
index a42808fc..93f05b7 100644
--- a/media/base/video_decoder_config.cc
+++ b/media/base/video_decoder_config.cc
@@ -114,7 +114,8 @@ bool VideoDecoderConfig::IsValidConfig() const {
return codec_ != kUnknownVideoCodec &&
natural_size_.width() > 0 &&
natural_size_.height() > 0 &&
- VideoFrame::IsValidConfig(format_, visible_rect().size(), natural_size_);
+ VideoFrame::IsValidConfig(format_, coded_size_, visible_rect_,
+ natural_size_);
}
bool VideoDecoderConfig::Matches(const VideoDecoderConfig& config) const {
diff --git a/media/base/video_frame.cc b/media/base/video_frame.cc
index 6303f09b..3d76410 100644
--- a/media/base/video_frame.cc
+++ b/media/base/video_frame.cc
@@ -19,12 +19,13 @@ namespace media {
// static
scoped_refptr<VideoFrame> VideoFrame::CreateFrame(
VideoFrame::Format format,
- const gfx::Size& data_size,
+ const gfx::Size& coded_size,
+ const gfx::Rect& visible_rect,
const gfx::Size& natural_size,
base::TimeDelta timestamp) {
- DCHECK(IsValidConfig(format, data_size, natural_size));
+ DCHECK(IsValidConfig(format, coded_size, visible_rect, natural_size));
scoped_refptr<VideoFrame> frame(new VideoFrame(
- format, data_size, natural_size, timestamp));
+ format, coded_size, visible_rect, natural_size, timestamp));
switch (format) {
case VideoFrame::RGB32:
frame->AllocateRGB(4u);
@@ -41,30 +42,37 @@ scoped_refptr<VideoFrame> VideoFrame::CreateFrame(
// static
bool VideoFrame::IsValidConfig(VideoFrame::Format format,
- const gfx::Size& data_size,
+ const gfx::Size& coded_size,
+ const gfx::Rect& visible_rect,
const gfx::Size& natural_size) {
return (format != VideoFrame::INVALID &&
- data_size.width() > 0 && data_size.height() > 0 &&
- data_size.width() <= limits::kMaxDimension &&
- data_size.height() <= limits::kMaxDimension &&
- data_size.width() * data_size.height() <= limits::kMaxCanvas &&
- natural_size.width() > 0 && natural_size.height() > 0 &&
+ !coded_size.IsEmpty() &&
+ coded_size.GetArea() <= limits::kMaxCanvas &&
+ coded_size.width() <= limits::kMaxDimension &&
+ coded_size.height() <= limits::kMaxDimension &&
+ !visible_rect.IsEmpty() &&
+ visible_rect.x() >= 0 && visible_rect.y() >= 0 &&
+ visible_rect.right() <= coded_size.width() &&
+ visible_rect.bottom() <= coded_size.height() &&
+ !natural_size.IsEmpty() &&
+ natural_size.GetArea() <= limits::kMaxCanvas &&
natural_size.width() <= limits::kMaxDimension &&
- natural_size.height() <= limits::kMaxDimension &&
- natural_size.width() * natural_size.height() <= limits::kMaxCanvas);
+ natural_size.height() <= limits::kMaxDimension);
}
// static
scoped_refptr<VideoFrame> VideoFrame::WrapNativeTexture(
uint32 texture_id,
uint32 texture_target,
- const gfx::Size& data_size,
+ const gfx::Size& coded_size,
+ const gfx::Rect& visible_rect,
const gfx::Size& natural_size,
base::TimeDelta timestamp,
const ReadPixelsCB& read_pixels_cb,
const base::Closure& no_longer_needed) {
scoped_refptr<VideoFrame> frame(
- new VideoFrame(NATIVE_TEXTURE, data_size, natural_size, timestamp));
+ new VideoFrame(NATIVE_TEXTURE, coded_size, visible_rect, natural_size,
+ timestamp));
frame->texture_id_ = texture_id;
frame->texture_target_ = texture_target;
frame->read_pixels_cb_ = read_pixels_cb;
@@ -81,7 +89,8 @@ void VideoFrame::ReadPixelsFromNativeTexture(void* pixels) {
// static
scoped_refptr<VideoFrame> VideoFrame::CreateEmptyFrame() {
return new VideoFrame(
- VideoFrame::EMPTY, gfx::Size(), gfx::Size(), base::TimeDelta());
+ VideoFrame::EMPTY, gfx::Size(), gfx::Rect(), gfx::Size(),
+ base::TimeDelta());
}
// static
@@ -89,9 +98,9 @@ scoped_refptr<VideoFrame> VideoFrame::CreateColorFrame(
const gfx::Size& size,
uint8 y, uint8 u, uint8 v,
base::TimeDelta timestamp) {
- DCHECK(IsValidConfig(VideoFrame::YV12, size, size));
+ DCHECK(IsValidConfig(VideoFrame::YV12, size, gfx::Rect(size), size));
scoped_refptr<VideoFrame> frame = VideoFrame::CreateFrame(
- VideoFrame::YV12, size, size, timestamp);
+ VideoFrame::YV12, size, gfx::Rect(size), size, timestamp);
FillYUV(frame, y, u, v);
return frame;
}
@@ -117,9 +126,9 @@ static const int kFramePadBytes = 15;
void VideoFrame::AllocateRGB(size_t bytes_per_pixel) {
// Round up to align at least at a 16-byte boundary for each row.
// This is sufficient for MMX and SSE2 reads (movq/movdqa).
- size_t bytes_per_row = RoundUp(data_size_.width(),
+ size_t bytes_per_row = RoundUp(coded_size_.width(),
kFrameSizeAlignment) * bytes_per_pixel;
- size_t aligned_height = RoundUp(data_size_.height(), kFrameSizeAlignment);
+ size_t aligned_height = RoundUp(coded_size_.height(), kFrameSizeAlignment);
strides_[VideoFrame::kRGBPlane] = bytes_per_row;
#if !defined(OS_ANDROID)
// TODO(dalecurtis): use DataAligned or so, so this #ifdef hackery
@@ -151,7 +160,7 @@ void VideoFrame::AllocateYUV() {
// The *2 here is because some formats (e.g. h264) allow interlaced coding,
// and then the size needs to be a multiple of two macroblocks (vertically).
// See libavcodec/utils.c:avcodec_align_dimensions2().
- size_t y_height = RoundUp(data_size_.height(), kFrameSizeAlignment * 2);
+ size_t y_height = RoundUp(coded_size_.height(), kFrameSizeAlignment * 2);
size_t uv_height = format_ == VideoFrame::YV12 ? y_height / 2 : y_height;
size_t y_bytes = y_height * y_stride;
size_t uv_bytes = uv_height * uv_stride;
@@ -178,11 +187,13 @@ void VideoFrame::AllocateYUV() {
}
VideoFrame::VideoFrame(VideoFrame::Format format,
- const gfx::Size& data_size,
+ const gfx::Size& coded_size,
+ const gfx::Rect& visible_rect,
const gfx::Size& natural_size,
base::TimeDelta timestamp)
: format_(format),
- data_size_(data_size),
+ coded_size_(coded_size),
+ visible_rect_(visible_rect),
natural_size_(natural_size),
texture_id_(0),
texture_target_(0),
@@ -238,7 +249,7 @@ int VideoFrame::stride(size_t plane) const {
int VideoFrame::row_bytes(size_t plane) const {
DCHECK(IsValidPlane(plane));
- int width = data_size_.width();
+ int width = coded_size_.width();
switch (format_) {
// 32bpp.
case RGB32:
@@ -262,7 +273,7 @@ int VideoFrame::row_bytes(size_t plane) const {
int VideoFrame::rows(size_t plane) const {
DCHECK(IsValidPlane(plane));
- int height = data_size_.height();
+ int height = coded_size_.height();
switch (format_) {
case RGB32:
case YV16:
diff --git a/media/base/video_frame.h b/media/base/video_frame.h
index 0840839..effdafd 100644
--- a/media/base/video_frame.h
+++ b/media/base/video_frame.h
@@ -8,6 +8,7 @@
#include "base/callback.h"
#include "base/md5.h"
#include "media/base/buffers.h"
+#include "ui/gfx/rect.h"
#include "ui/gfx/size.h"
namespace media {
@@ -40,19 +41,23 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> {
// Creates a new frame in system memory with given parameters. Buffers for
// the frame are allocated but not initialized.
- // |data_size| is the width and height of the frame data in pixels.
+ // |coded_size| is the width and height of the frame data in pixels.
+ // |visible_rect| is the visible portion of |coded_size|, after cropping (if
+ // any) is applied.
// |natural_size| is the width and height of the frame when the frame's aspect
- // ratio is applied to |data_size|.
+ // ratio is applied to |visible_rect|.
static scoped_refptr<VideoFrame> CreateFrame(
Format format,
- const gfx::Size& data_size,
+ const gfx::Size& coded_size,
+ const gfx::Rect& visible_rect,
const gfx::Size& natural_size,
base::TimeDelta timestamp);
// Call prior to CreateFrame to ensure validity of frame configuration. Called
// automatically by VideoDecoderConfig::IsValidConfig().
// TODO(scherkus): VideoDecoderConfig shouldn't call this method
- static bool IsValidConfig(Format format, const gfx::Size& data_size,
+ static bool IsValidConfig(Format format, const gfx::Size& coded_size,
+ const gfx::Rect& visible_rect,
const gfx::Size& natural_size);
// CB to write pixels from the texture backing this frame into the
@@ -61,15 +66,18 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> {
// Wraps a native texture of the given parameters with a VideoFrame. When the
// frame is destroyed |no_longer_needed.Run()| will be called.
- // |data_size| is the width and height of the frame data in pixels.
+ // |coded_size| is the width and height of the frame data in pixels.
+ // |visible_rect| is the visible portion of |coded_size|, after cropping (if
+ // any) is applied.
// |natural_size| is the width and height of the frame when the frame's aspect
- // ratio is applied to |size|.
+ // ratio is applied to |visible_rect|.
// |read_pixels_cb| may be used to do (slow!) readbacks from the
// texture to main memory.
static scoped_refptr<VideoFrame> WrapNativeTexture(
uint32 texture_id,
uint32 texture_target,
- const gfx::Size& data_size,
+ const gfx::Size& coded_size,
+ const gfx::Rect& visible_rect,
const gfx::Size& natural_size,
base::TimeDelta timestamp,
const ReadPixelsCB& read_pixels_cb,
@@ -77,7 +85,7 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> {
// Read pixels from the native texture backing |*this| and write
// them to |*pixels| as BGRA. |pixels| must point to a buffer at
- // least as large as 4*data_size().width()*data_size().height().
+ // least as large as 4*visible_rect().width()*visible_rect().height().
void ReadPixelsFromNativeTexture(void* pixels);
// Creates a frame with format equals to VideoFrame::EMPTY, width, height,
@@ -86,7 +94,7 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> {
// Allocates YV12 frame based on |size|, and sets its data to the YUV(y,u,v).
static scoped_refptr<VideoFrame> CreateColorFrame(
- const gfx::Size& data_size,
+ const gfx::Size& size,
uint8 y, uint8 u, uint8 v,
base::TimeDelta timestamp);
@@ -96,7 +104,8 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> {
Format format() const { return format_; }
- const gfx::Size& data_size() const { return data_size_; }
+ const gfx::Size& coded_size() const { return coded_size_; }
+ const gfx::Rect& visible_rect() const { return visible_rect_; }
const gfx::Size& natural_size() const { return natural_size_; }
int stride(size_t plane) const;
@@ -104,7 +113,7 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> {
// Returns the number of bytes per row and number of rows for a given plane.
//
// As opposed to stride(), row_bytes() refers to the bytes representing
- // visible pixels.
+ // frame data scanlines (coded_size.width() pixels, without stride padding).
int row_bytes(size_t plane) const;
int rows(size_t plane) const;
@@ -137,7 +146,8 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> {
friend class base::RefCountedThreadSafe<VideoFrame>;
// Clients must use the static CreateFrame() method to create a new frame.
VideoFrame(Format format,
- const gfx::Size& size,
+ const gfx::Size& coded_size,
+ const gfx::Rect& visible_rect,
const gfx::Size& natural_size,
base::TimeDelta timestamp);
virtual ~VideoFrame();
@@ -153,10 +163,13 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> {
Format format_;
// Width and height of the video frame.
- gfx::Size data_size_;
+ gfx::Size coded_size_;
- // Width and height of the video frame with aspect ratio taken
- // into account.
+ // Width, height, and offsets of the visible portion of the video frame.
+ gfx::Rect visible_rect_;
+
+ // Width and height of the visible portion of the video frame with aspect
+ // ratio taken into account.
gfx::Size natural_size_;
// Array of strides for each plane, typically greater or equal to the width
diff --git a/media/base/video_frame_unittest.cc b/media/base/video_frame_unittest.cc
index ebbf92b..18cc1d3 100644
--- a/media/base/video_frame_unittest.cc
+++ b/media/base/video_frame_unittest.cc
@@ -20,19 +20,19 @@ using base::MD5DigestToBase16;
// frame will be black, if 1 then the entire frame will be white.
void InitializeYV12Frame(VideoFrame* frame, double white_to_black) {
EXPECT_EQ(VideoFrame::YV12, frame->format());
- int first_black_row = static_cast<int>(frame->data_size().height() *
+ int first_black_row = static_cast<int>(frame->coded_size().height() *
white_to_black);
uint8* y_plane = frame->data(VideoFrame::kYPlane);
- for (int row = 0; row < frame->data_size().height(); ++row) {
+ for (int row = 0; row < frame->coded_size().height(); ++row) {
int color = (row < first_black_row) ? 0xFF : 0x00;
- memset(y_plane, color, frame->data_size().width());
+ memset(y_plane, color, frame->stride(VideoFrame::kYPlane));
y_plane += frame->stride(VideoFrame::kYPlane);
}
uint8* u_plane = frame->data(VideoFrame::kUPlane);
uint8* v_plane = frame->data(VideoFrame::kVPlane);
- for (int row = 0; row < frame->data_size().height(); row += 2) {
- memset(u_plane, 0x80, frame->data_size().width() / 2);
- memset(v_plane, 0x80, frame->data_size().width() / 2);
+ for (int row = 0; row < frame->coded_size().height(); row += 2) {
+ memset(u_plane, 0x80, frame->stride(VideoFrame::kUPlane));
+ memset(v_plane, 0x80, frame->stride(VideoFrame::kVPlane));
u_plane += frame->stride(VideoFrame::kUPlane);
v_plane += frame->stride(VideoFrame::kVPlane);
}
@@ -47,29 +47,32 @@ void ExpectFrameColor(media::VideoFrame* yv12_frame, uint32 expect_rgb_color) {
scoped_refptr<media::VideoFrame> rgb_frame;
rgb_frame = media::VideoFrame::CreateFrame(VideoFrame::RGB32,
- yv12_frame->data_size(),
+ yv12_frame->coded_size(),
+ yv12_frame->visible_rect(),
yv12_frame->natural_size(),
yv12_frame->GetTimestamp());
- ASSERT_EQ(yv12_frame->data_size().width(), rgb_frame->data_size().width());
- ASSERT_EQ(yv12_frame->data_size().height(), rgb_frame->data_size().height());
+ ASSERT_EQ(yv12_frame->coded_size().width(),
+ rgb_frame->coded_size().width());
+ ASSERT_EQ(yv12_frame->coded_size().height(),
+ rgb_frame->coded_size().height());
media::ConvertYUVToRGB32(yv12_frame->data(VideoFrame::kYPlane),
yv12_frame->data(VideoFrame::kUPlane),
yv12_frame->data(VideoFrame::kVPlane),
rgb_frame->data(VideoFrame::kRGBPlane),
- rgb_frame->data_size().width(),
- rgb_frame->data_size().height(),
+ rgb_frame->coded_size().width(),
+ rgb_frame->coded_size().height(),
yv12_frame->stride(VideoFrame::kYPlane),
yv12_frame->stride(VideoFrame::kUPlane),
rgb_frame->stride(VideoFrame::kRGBPlane),
media::YV12);
- for (int row = 0; row < rgb_frame->data_size().height(); ++row) {
+ for (int row = 0; row < rgb_frame->coded_size().height(); ++row) {
uint32* rgb_row_data = reinterpret_cast<uint32*>(
rgb_frame->data(VideoFrame::kRGBPlane) +
(rgb_frame->stride(VideoFrame::kRGBPlane) * row));
- for (int col = 0; col < rgb_frame->data_size().width(); ++col) {
+ for (int col = 0; col < rgb_frame->coded_size().width(); ++col) {
SCOPED_TRACE(
base::StringPrintf("Checking (%d, %d)", row, col));
EXPECT_EQ(expect_rgb_color, rgb_row_data[col]);
@@ -89,7 +92,7 @@ void ExpectFrameExtents(VideoFrame::Format format, int planes,
gfx::Size size(kWidth, kHeight);
scoped_refptr<VideoFrame> frame = VideoFrame::CreateFrame(
- format, size, size, kTimestamp);
+ format, size, gfx::Rect(size), size, kTimestamp);
ASSERT_TRUE(frame);
for(int plane = 0; plane < planes; plane++) {
@@ -124,7 +127,8 @@ TEST(VideoFrame, CreateFrame) {
// Create a YV12 Video Frame.
gfx::Size size(kWidth, kHeight);
scoped_refptr<media::VideoFrame> frame =
- VideoFrame::CreateFrame(media::VideoFrame::YV12, size, size, kTimestamp);
+ VideoFrame::CreateFrame(media::VideoFrame::YV12, size, gfx::Rect(size),
+ size, kTimestamp);
ASSERT_TRUE(frame);
// Test VideoFrame implementation.
@@ -171,19 +175,19 @@ TEST(VideoFrame, CreateBlackFrame) {
// Test |frame| properties.
EXPECT_EQ(VideoFrame::YV12, frame->format());
- EXPECT_EQ(kWidth, frame->data_size().width());
- EXPECT_EQ(kHeight, frame->data_size().height());
+ EXPECT_EQ(kWidth, frame->coded_size().width());
+ EXPECT_EQ(kHeight, frame->coded_size().height());
// Test frames themselves.
uint8* y_plane = frame->data(VideoFrame::kYPlane);
- for (int y = 0; y < frame->data_size().height(); ++y) {
+ for (int y = 0; y < frame->coded_size().height(); ++y) {
EXPECT_EQ(0, memcmp(kExpectedYRow, y_plane, arraysize(kExpectedYRow)));
y_plane += frame->stride(VideoFrame::kYPlane);
}
uint8* u_plane = frame->data(VideoFrame::kUPlane);
uint8* v_plane = frame->data(VideoFrame::kVPlane);
- for (int y = 0; y < frame->data_size().height() / 2; ++y) {
+ for (int y = 0; y < frame->coded_size().height() / 2; ++y) {
EXPECT_EQ(0, memcmp(kExpectedUVRow, u_plane, arraysize(kExpectedUVRow)));
EXPECT_EQ(0, memcmp(kExpectedUVRow, v_plane, arraysize(kExpectedUVRow)));
u_plane += frame->stride(VideoFrame::kUPlane);
diff --git a/media/base/video_util_unittest.cc b/media/base/video_util_unittest.cc
index 326907d..d4f2e29 100644
--- a/media/base/video_util_unittest.cc
+++ b/media/base/video_util_unittest.cc
@@ -39,7 +39,7 @@ class VideoUtilTest : public testing::Test {
void CreateDestinationFrame(int width, int height) {
gfx::Size size(width, height);
destination_frame_ =
- VideoFrame::CreateFrame(VideoFrame::YV12, size, size,
+ VideoFrame::CreateFrame(VideoFrame::YV12, size, gfx::Rect(size), size,
base::TimeDelta());
}
diff --git a/media/filters/ffmpeg_video_decoder.cc b/media/filters/ffmpeg_video_decoder.cc
index aaf7bd7..d75782f 100644
--- a/media/filters/ffmpeg_video_decoder.cc
+++ b/media/filters/ffmpeg_video_decoder.cc
@@ -91,11 +91,12 @@ int FFmpegVideoDecoder::GetVideoBuffer(AVCodecContext* codec_context,
natural_size = demuxer_stream_->video_decoder_config().natural_size();
}
- if (!VideoFrame::IsValidConfig(format, size, natural_size))
+ if (!VideoFrame::IsValidConfig(format, size, gfx::Rect(size), natural_size))
return AVERROR(EINVAL);
scoped_refptr<VideoFrame> video_frame =
- VideoFrame::CreateFrame(format, size, natural_size, kNoTimestamp());
+ VideoFrame::CreateFrame(format, size, gfx::Rect(size), natural_size,
+ kNoTimestamp());
for (int i = 0; i < 3; i++) {
frame->base[i] = video_frame->data(i);
diff --git a/media/filters/ffmpeg_video_decoder_unittest.cc b/media/filters/ffmpeg_video_decoder_unittest.cc
index 9d9c24d..52e02d2 100644
--- a/media/filters/ffmpeg_video_decoder_unittest.cc
+++ b/media/filters/ffmpeg_video_decoder_unittest.cc
@@ -218,10 +218,12 @@ class FFmpegVideoDecoderTest : public testing::Test {
EXPECT_EQ(VideoDecoder::kOk, status_b);
ASSERT_TRUE(video_frame_a);
ASSERT_TRUE(video_frame_b);
- EXPECT_EQ(original_size.width(), video_frame_a->data_size().width());
- EXPECT_EQ(original_size.height(), video_frame_a->data_size().height());
- EXPECT_EQ(expected_width, video_frame_b->data_size().width());
- EXPECT_EQ(expected_height, video_frame_b->data_size().height());
+ EXPECT_EQ(original_size.width(),
+ video_frame_a->visible_rect().size().width());
+ EXPECT_EQ(original_size.height(),
+ video_frame_a->visible_rect().size().height());
+ EXPECT_EQ(expected_width, video_frame_b->visible_rect().size().width());
+ EXPECT_EQ(expected_height, video_frame_b->visible_rect().size().height());
}
void Read(VideoDecoder::Status* status,
diff --git a/media/filters/gpu_video_decoder.cc b/media/filters/gpu_video_decoder.cc
index 092e127..d59364b 100644
--- a/media/filters/gpu_video_decoder.cc
+++ b/media/filters/gpu_video_decoder.cc
@@ -42,8 +42,9 @@ GpuVideoDecoder::BufferPair::BufferPair(
GpuVideoDecoder::BufferPair::~BufferPair() {}
GpuVideoDecoder::BufferData::BufferData(
- int32 bbid, base::TimeDelta ts, const gfx::Size& ns)
- : bitstream_buffer_id(bbid), timestamp(ts), natural_size(ns) {
+ int32 bbid, base::TimeDelta ts, const gfx::Rect& vr, const gfx::Size& ns)
+ : bitstream_buffer_id(bbid), timestamp(ts), visible_rect(vr),
+ natural_size(ns) {
}
GpuVideoDecoder::BufferData::~BufferData() {}
@@ -325,6 +326,7 @@ void GpuVideoDecoder::RecordBufferData(
const BitstreamBuffer& bitstream_buffer, const Buffer& buffer) {
input_buffer_data_.push_front(BufferData(
bitstream_buffer.id(), buffer.GetTimestamp(),
+ demuxer_stream_->video_decoder_config().visible_rect(),
demuxer_stream_->video_decoder_config().natural_size()));
// Why this value? Because why not. avformat.h:MAX_REORDER_DELAY is 16, but
// that's too small for some pathological B-frame test videos. The cost of
@@ -337,6 +339,7 @@ void GpuVideoDecoder::RecordBufferData(
}
void GpuVideoDecoder::GetBufferData(int32 id, base::TimeDelta* timestamp,
+ gfx::Rect* visible_rect,
gfx::Size* natural_size) {
for (std::list<BufferData>::const_iterator it =
input_buffer_data_.begin(); it != input_buffer_data_.end();
@@ -344,6 +347,7 @@ void GpuVideoDecoder::GetBufferData(int32 id, base::TimeDelta* timestamp,
if (it->bitstream_buffer_id != id)
continue;
*timestamp = it->timestamp;
+ *visible_rect = it->visible_rect;
*natural_size = it->natural_size;
return;
}
@@ -425,16 +429,19 @@ void GpuVideoDecoder::PictureReady(const media::Picture& picture) {
// Update frame's timestamp.
base::TimeDelta timestamp;
+ gfx::Rect visible_rect;
gfx::Size natural_size;
- GetBufferData(picture.bitstream_buffer_id(), &timestamp, &natural_size);
+ GetBufferData(picture.bitstream_buffer_id(), &timestamp, &visible_rect,
+ &natural_size);
DCHECK(decoder_texture_target_);
- scoped_refptr<VideoFrame> frame(VideoFrame::WrapNativeTexture(
- pb.texture_id(), decoder_texture_target_, pb.size(), natural_size,
- timestamp,
- base::Bind(&Factories::ReadPixels, factories_, pb.texture_id(),
- decoder_texture_target_, pb.size()),
- base::Bind(&GpuVideoDecoder::ReusePictureBuffer, this,
- picture.picture_buffer_id())));
+ scoped_refptr<VideoFrame> frame(
+ VideoFrame::WrapNativeTexture(
+ pb.texture_id(), decoder_texture_target_, pb.size(), visible_rect,
+ natural_size, timestamp,
+ base::Bind(&Factories::ReadPixels, factories_, pb.texture_id(),
+ decoder_texture_target_, pb.size()),
+ base::Bind(&GpuVideoDecoder::ReusePictureBuffer, this,
+ picture.picture_buffer_id())));
EnqueueFrameAndTriggerFrameDelivery(frame);
}
diff --git a/media/filters/gpu_video_decoder.h b/media/filters/gpu_video_decoder.h
index 745505f..da3248c 100644
--- a/media/filters/gpu_video_decoder.h
+++ b/media/filters/gpu_video_decoder.h
@@ -127,7 +127,7 @@ class MEDIA_EXPORT GpuVideoDecoder
void RecordBufferData(
const BitstreamBuffer& bitstream_buffer, const Buffer& buffer);
void GetBufferData(int32 id, base::TimeDelta* timetamp,
- gfx::Size* natural_size);
+ gfx::Rect* visible_rect, gfx::Size* natural_size);
// Set |vda_| and |weak_vda_| on the VDA thread (in practice the render
// thread).
@@ -208,11 +208,12 @@ class MEDIA_EXPORT GpuVideoDecoder
uint32 decoder_texture_target_;
struct BufferData {
- BufferData(int32 bbid, base::TimeDelta ts,
+ BufferData(int32 bbid, base::TimeDelta ts, const gfx::Rect& visible_rect,
const gfx::Size& natural_size);
~BufferData();
int32 bitstream_buffer_id;
base::TimeDelta timestamp;
+ gfx::Rect visible_rect;
gfx::Size natural_size;
};
std::list<BufferData> input_buffer_data_;
diff --git a/media/filters/skcanvas_video_renderer.cc b/media/filters/skcanvas_video_renderer.cc
index bef015e..53b5b2d 100644
--- a/media/filters/skcanvas_video_renderer.cc
+++ b/media/filters/skcanvas_video_renderer.cc
@@ -68,9 +68,12 @@ static void FastPaint(
video_frame->stride(media::VideoFrame::kVPlane));
const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(true);
- media::YUVType yuv_type = (video_frame->format() == media::VideoFrame::YV12) ?
- media::YV12 : media::YV16;
- int y_shift = yuv_type; // 1 for YV12, 0 for YV16.
+ media::YUVType yuv_type = media::YV16;
+ int y_shift = 0;
+ if (video_frame->format() == media::VideoFrame::YV12) {
+ yuv_type = media::YV12;
+ y_shift = 1;
+ }
// Transform the destination rectangle to local coordinates.
const SkMatrix& local_matrix = canvas->getTotalMatrix();
@@ -109,27 +112,29 @@ static void FastPaint(
DCHECK_NE(0, dest_rect.width());
DCHECK_NE(0, dest_rect.height());
size_t frame_clip_width = local_dest_irect.width() *
- video_frame->data_size().width() / local_dest_irect_saved.width();
+ video_frame->visible_rect().width() / local_dest_irect_saved.width();
size_t frame_clip_height = local_dest_irect.height() *
- video_frame->data_size().height() / local_dest_irect_saved.height();
+ video_frame->visible_rect().height() / local_dest_irect_saved.height();
// Project the "left" and "top" of the final destination rect to local
// coordinates of the video frame, use these values to find the offsets
// in the video frame to start reading.
size_t frame_clip_left =
+ video_frame->visible_rect().x() +
(local_dest_irect.fLeft - local_dest_irect_saved.fLeft) *
- video_frame->data_size().width() / local_dest_irect_saved.width();
+ video_frame->visible_rect().width() / local_dest_irect_saved.width();
size_t frame_clip_top =
+ video_frame->visible_rect().y() +
(local_dest_irect.fTop - local_dest_irect_saved.fTop) *
- video_frame->data_size().height() / local_dest_irect_saved.height();
+ video_frame->visible_rect().height() / local_dest_irect_saved.height();
// Use the "left" and "top" of the destination rect to locate the offset
// in Y, U and V planes.
- size_t y_offset = video_frame->stride(media::VideoFrame::kYPlane) *
- frame_clip_top + frame_clip_left;
+ size_t y_offset = (video_frame->stride(media::VideoFrame::kYPlane) *
+ frame_clip_top) + frame_clip_left;
// For format YV12, there is one U, V value per 2x2 block.
- // For format YV16, there is one u, V value per 2x1 block.
+ // For format YV16, there is one U, V value per 2x1 block.
size_t uv_offset = (video_frame->stride(media::VideoFrame::kUPlane) *
(frame_clip_top >> y_shift)) + (frame_clip_left >> 1);
uint8* frame_clip_y =
@@ -174,26 +179,48 @@ static void ConvertVideoFrameToBitmap(
// Check if |bitmap| needs to be (re)allocated.
if (bitmap->isNull() ||
- bitmap->width() != video_frame->data_size().width() ||
- bitmap->height() != video_frame->data_size().height()) {
+ bitmap->width() != video_frame->visible_rect().width() ||
+ bitmap->height() != video_frame->visible_rect().height()) {
bitmap->setConfig(SkBitmap::kARGB_8888_Config,
- video_frame->data_size().width(),
- video_frame->data_size().height());
+ video_frame->visible_rect().width(),
+ video_frame->visible_rect().height());
bitmap->allocPixels();
bitmap->setIsVolatile(true);
}
bitmap->lockPixels();
if (IsEitherYV12OrYV16(video_frame->format())) {
- media::YUVType yuv_type =
- (video_frame->format() == media::VideoFrame::YV12) ?
- media::YV12 : media::YV16;
- media::ConvertYUVToRGB32(video_frame->data(media::VideoFrame::kYPlane),
- video_frame->data(media::VideoFrame::kUPlane),
- video_frame->data(media::VideoFrame::kVPlane),
+ media::YUVType yuv_type = media::YV16;
+ int y_shift = 0;
+ if (video_frame->format() == media::VideoFrame::YV12) {
+ yuv_type = media::YV12;
+ y_shift = 1;
+ }
+
+ // Use the "left" and "top" of the destination rect to locate the offset
+ // in Y, U and V planes.
+ size_t y_offset = (video_frame->stride(media::VideoFrame::kYPlane) *
+ video_frame->visible_rect().y()) +
+ video_frame->visible_rect().x();
+
+ // For format YV12, there is one U, V value per 2x2 block.
+ // For format YV16, there is one U, V value per 2x1 block.
+ size_t uv_offset = (video_frame->stride(media::VideoFrame::kUPlane) *
+ (video_frame->visible_rect().y() >> y_shift)) +
+ (video_frame->visible_rect().x() >> 1);
+ uint8* frame_clip_y =
+ video_frame->data(media::VideoFrame::kYPlane) + y_offset;
+ uint8* frame_clip_u =
+ video_frame->data(media::VideoFrame::kUPlane) + uv_offset;
+ uint8* frame_clip_v =
+ video_frame->data(media::VideoFrame::kVPlane) + uv_offset;
+
+ media::ConvertYUVToRGB32(frame_clip_y,
+ frame_clip_u,
+ frame_clip_v,
static_cast<uint8*>(bitmap->getPixels()),
- video_frame->data_size().width(),
- video_frame->data_size().height(),
+ video_frame->visible_rect().width(),
+ video_frame->visible_rect().height(),
video_frame->stride(media::VideoFrame::kYPlane),
video_frame->stride(media::VideoFrame::kUPlane),
bitmap->rowBytes(),
diff --git a/media/filters/skcanvas_video_renderer_unittest.cc b/media/filters/skcanvas_video_renderer_unittest.cc
index a7ac30c..a50f266 100644
--- a/media/filters/skcanvas_video_renderer_unittest.cc
+++ b/media/filters/skcanvas_video_renderer_unittest.cc
@@ -26,18 +26,24 @@ void FillCanvas(SkCanvas* canvas, SkColor color) {
}
// Helper for returning the color of a solid |canvas|.
-SkColor GetColor(SkCanvas* canvas) {
+SkColor GetColorAt(SkCanvas* canvas, int x, int y) {
const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(false);
bitmap.lockPixels();
- SkColor c = bitmap.getColor(0, 0);
+ SkColor c = bitmap.getColor(x, y);
bitmap.unlockPixels();
return c;
}
+SkColor GetColor(SkCanvas* canvas) {
+ return GetColorAt(canvas, 0, 0);
+}
+
class SkCanvasVideoRendererTest : public testing::Test {
public:
enum Color {
+ kNone,
kRed,
+ kGreen,
kBlue,
};
@@ -55,6 +61,7 @@ class SkCanvasVideoRendererTest : public testing::Test {
VideoFrame* natural_frame() { return natural_frame_; }
VideoFrame* larger_frame() { return larger_frame_; }
VideoFrame* smaller_frame() { return smaller_frame_; }
+ VideoFrame* cropped_frame() { return cropped_frame_; }
// Getters for canvases that trigger the various painting paths.
SkCanvas* fast_path_canvas() { return &fast_path_canvas_; }
@@ -66,6 +73,7 @@ class SkCanvasVideoRendererTest : public testing::Test {
scoped_refptr<VideoFrame> natural_frame_;
scoped_refptr<VideoFrame> larger_frame_;
scoped_refptr<VideoFrame> smaller_frame_;
+ scoped_refptr<VideoFrame> cropped_frame_;
SkDevice fast_path_device_;
SkCanvas fast_path_canvas_;
@@ -81,6 +89,12 @@ SkCanvasVideoRendererTest::SkCanvasVideoRendererTest()
gfx::Size(kWidth * 2, kHeight * 2))),
smaller_frame_(VideoFrame::CreateBlackFrame(
gfx::Size(kWidth / 2, kHeight / 2))),
+ cropped_frame_(VideoFrame::CreateFrame(
+ VideoFrame::YV12,
+ gfx::Size(16, 16),
+ gfx::Rect(6, 6, 8, 6),
+ gfx::Size(8, 6),
+ base::TimeDelta::FromMilliseconds(4))),
fast_path_device_(SkBitmap::kARGB_8888_Config, kWidth, kHeight, true),
fast_path_canvas_(&fast_path_device_),
slow_path_device_(SkBitmap::kARGB_8888_Config, kWidth, kHeight, false),
@@ -89,6 +103,86 @@ SkCanvasVideoRendererTest::SkCanvasVideoRendererTest()
natural_frame_->SetTimestamp(base::TimeDelta::FromMilliseconds(1));
larger_frame_->SetTimestamp(base::TimeDelta::FromMilliseconds(2));
smaller_frame_->SetTimestamp(base::TimeDelta::FromMilliseconds(3));
+
+ // Make sure the cropped video frame's aspect ratio matches the output device.
+ // Update cropped_frame_'s crop dimensions if this is not the case.
+ EXPECT_EQ(cropped_frame()->natural_size().width() * kHeight,
+ cropped_frame()->natural_size().height() * kWidth);
+
+ // Fill in the cropped frame's entire data with colors:
+ //
+ // Bl Bl Bl Bl Bl Bl Bl Bl R R R R R R R R
+ // Bl Bl Bl Bl Bl Bl Bl Bl R R R R R R R R
+ // Bl Bl Bl Bl Bl Bl Bl Bl R R R R R R R R
+ // Bl Bl Bl Bl Bl Bl Bl Bl R R R R R R R R
+ // Bl Bl Bl Bl Bl Bl Bl Bl R R R R R R R R
+ // Bl Bl Bl Bl Bl Bl Bl Bl R R R R R R R R
+ // Bl Bl Bl Bl Bl Bl Bl Bl R R R R R R R R
+ // Bl Bl Bl Bl Bl Bl Bl Bl R R R R R R R R
+ // G G G G G G G G B B B B B B B B
+ // G G G G G G G G B B B B B B B B
+ // G G G G G G G G B B B B B B B B
+ // G G G G G G G G B B B B B B B B
+ // G G G G G G G G B B B B B B B B
+ // G G G G G G G G B B B B B B B B
+ // G G G G G G G G B B B B B B B B
+ // G G G G G G G G B B B B B B B B
+ //
+ // The visible crop of the frame (as set by its visible_rect_) has contents:
+ //
+ // Bl Bl R R R R R R
+ // Bl Bl R R R R R R
+ // G G B B B B B B
+ // G G B B B B B B
+ // G G B B B B B B
+ // G G B B B B B B
+ //
+ // Each color region in the cropped frame is on a 2x2 block granularity, to
+ // avoid sharing UV samples between regions.
+
+ static const uint8 cropped_y_plane[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 76, 76, 76, 76, 76, 76, 76, 76,
+ 0, 0, 0, 0, 0, 0, 0, 0, 76, 76, 76, 76, 76, 76, 76, 76,
+ 0, 0, 0, 0, 0, 0, 0, 0, 76, 76, 76, 76, 76, 76, 76, 76,
+ 0, 0, 0, 0, 0, 0, 0, 0, 76, 76, 76, 76, 76, 76, 76, 76,
+ 0, 0, 0, 0, 0, 0, 0, 0, 76, 76, 76, 76, 76, 76, 76, 76,
+ 0, 0, 0, 0, 0, 0, 0, 0, 76, 76, 76, 76, 76, 76, 76, 76,
+ 0, 0, 0, 0, 0, 0, 0, 0, 76, 76, 76, 76, 76, 76, 76, 76,
+ 0, 0, 0, 0, 0, 0, 0, 0, 76, 76, 76, 76, 76, 76, 76, 76,
+ 149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29,
+ 149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29,
+ 149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29,
+ 149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29,
+ 149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29,
+ 149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29,
+ 149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29,
+ 149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29,
+ };
+
+ static const uint8 cropped_u_plane[] = {
+ 128, 128, 128, 128, 84, 84, 84, 84,
+ 128, 128, 128, 128, 84, 84, 84, 84,
+ 128, 128, 128, 128, 84, 84, 84, 84,
+ 128, 128, 128, 128, 84, 84, 84, 84,
+ 43, 43, 43, 43, 255, 255, 255, 255,
+ 43, 43, 43, 43, 255, 255, 255, 255,
+ 43, 43, 43, 43, 255, 255, 255, 255,
+ 43, 43, 43, 43, 255, 255, 255, 255,
+ };
+ static const uint8 cropped_v_plane[] = {
+ 128, 128, 128, 128, 255, 255, 255, 255,
+ 128, 128, 128, 128, 255, 255, 255, 255,
+ 128, 128, 128, 128, 255, 255, 255, 255,
+ 128, 128, 128, 128, 255, 255, 255, 255,
+ 21, 21, 21, 21, 107, 107, 107, 107,
+ 21, 21, 21, 21, 107, 107, 107, 107,
+ 21, 21, 21, 21, 107, 107, 107, 107,
+ 21, 21, 21, 21, 107, 107, 107, 107,
+ };
+
+ media::CopyYPlane(cropped_y_plane, 16, 16, cropped_frame());
+ media::CopyUPlane(cropped_u_plane, 8, 8, cropped_frame());
+ media::CopyVPlane(cropped_v_plane, 8, 8, cropped_frame());
}
SkCanvasVideoRendererTest::~SkCanvasVideoRendererTest() {}
@@ -101,9 +195,14 @@ void SkCanvasVideoRendererTest::Paint(VideoFrame* video_frame,
SkCanvas* canvas,
Color color) {
switch (color) {
+ case kNone:
+ break;
case kRed:
media::FillYUV(video_frame, 76, 84, 255);
break;
+ case kGreen:
+ media::FillYUV(video_frame, 149, 43, 21);
+ break;
case kBlue:
media::FillYUV(video_frame, 29, 255, 107);
break;
@@ -199,4 +298,51 @@ TEST_F(SkCanvasVideoRendererTest, SlowPaint_SameVideoFrame) {
EXPECT_EQ(SK_ColorRED, GetColor(slow_path_canvas()));
}
+TEST_F(SkCanvasVideoRendererTest, FastPaint_CroppedFrame) {
+ Paint(cropped_frame(), fast_path_canvas(), kNone);
+ // Check the corners.
+ EXPECT_EQ(SK_ColorBLACK, GetColorAt(fast_path_canvas(), 0, 0));
+ EXPECT_EQ(SK_ColorRED, GetColorAt(fast_path_canvas(), kWidth - 1, 0));
+ EXPECT_EQ(SK_ColorGREEN, GetColorAt(fast_path_canvas(), 0, kHeight - 1));
+ EXPECT_EQ(SK_ColorBLUE, GetColorAt(fast_path_canvas(), kWidth - 1,
+ kHeight - 1));
+ // Check the interior along the border between color regions. Note that we're
+ // bilinearly upscaling, so we'll need to take care to pick sample points that
+ // are just outside the "zone of resampling".
+ // TODO(sheu): commenting out two checks due to http://crbug.com/158462.
+#if 0
+ EXPECT_EQ(SK_ColorBLACK, GetColorAt(fast_path_canvas(), kWidth * 1 / 8 - 1,
+ kHeight * 1 / 6 - 1));
+#endif
+ EXPECT_EQ(SK_ColorRED, GetColorAt(fast_path_canvas(), kWidth * 3 / 8,
+ kHeight * 1 / 6 - 1));
+#if 0
+ EXPECT_EQ(SK_ColorGREEN, GetColorAt(fast_path_canvas(), kWidth * 1 / 8 - 1,
+ kHeight * 3 / 6));
+#endif
+ EXPECT_EQ(SK_ColorBLUE, GetColorAt(fast_path_canvas(), kWidth * 3 / 8,
+ kHeight * 3 / 6));
+}
+
+TEST_F(SkCanvasVideoRendererTest, SlowPaint_CroppedFrame) {
+ Paint(cropped_frame(), slow_path_canvas(), kNone);
+ // Check the corners.
+ EXPECT_EQ(SK_ColorBLACK, GetColorAt(slow_path_canvas(), 0, 0));
+ EXPECT_EQ(SK_ColorRED, GetColorAt(slow_path_canvas(), kWidth - 1, 0));
+ EXPECT_EQ(SK_ColorGREEN, GetColorAt(slow_path_canvas(), 0, kHeight - 1));
+ EXPECT_EQ(SK_ColorBLUE, GetColorAt(slow_path_canvas(), kWidth - 1,
+ kHeight - 1));
+ // Check the interior along the border between color regions. Note that we're
+ // bilinearly upscaling, so we'll need to take care to pick sample points that
+ // are just outside the "zone of resampling".
+ EXPECT_EQ(SK_ColorBLACK, GetColorAt(slow_path_canvas(), kWidth * 1 / 8 - 1,
+ kHeight * 1 / 6 - 1));
+ EXPECT_EQ(SK_ColorRED, GetColorAt(slow_path_canvas(), kWidth * 3 / 8,
+ kHeight * 1 / 6 - 1));
+ EXPECT_EQ(SK_ColorGREEN, GetColorAt(slow_path_canvas(), kWidth * 1 / 8 - 1,
+ kHeight * 3 / 6));
+ EXPECT_EQ(SK_ColorBLUE, GetColorAt(slow_path_canvas(), kWidth * 3 / 8,
+ kHeight * 3 / 6));
+}
+
} // namespace media
diff --git a/media/filters/video_frame_generator.cc b/media/filters/video_frame_generator.cc
index 4429c19..c72fe13 100644
--- a/media/filters/video_frame_generator.cc
+++ b/media/filters/video_frame_generator.cc
@@ -72,7 +72,8 @@ void VideoFrameGenerator::ReadOnDecoderThread(const ReadCB& read_cb) {
//
// TODO(scherkus): migrate this to proper buffer recycling.
scoped_refptr<VideoFrame> video_frame =
- VideoFrame::CreateFrame(VideoFrame::YV12, size_, size_, current_time_);
+ VideoFrame::CreateFrame(VideoFrame::YV12, size_, gfx::Rect(size_), size_,
+ current_time_);
current_time_ += frame_duration_;
// TODO(wjia): set pixel data to pre-defined patterns if it's desired to
diff --git a/media/filters/video_renderer_base_unittest.cc b/media/filters/video_renderer_base_unittest.cc
index b81c40d..9ce8a9c 100644
--- a/media/filters/video_renderer_base_unittest.cc
+++ b/media/filters/video_renderer_base_unittest.cc
@@ -287,7 +287,8 @@ class VideoRendererBaseTest : public ::testing::Test {
// Creates a frame with given timestamp.
scoped_refptr<VideoFrame> CreateFrame(int timestamp) {
scoped_refptr<VideoFrame> frame =
- VideoFrame::CreateFrame(VideoFrame::RGB32, kNaturalSize, kNaturalSize,
+ VideoFrame::CreateFrame(VideoFrame::RGB32, kNaturalSize,
+ gfx::Rect(kNaturalSize), kNaturalSize,
base::TimeDelta::FromMilliseconds(timestamp));
return frame;
}
diff --git a/media/tools/player_wtl/view.h b/media/tools/player_wtl/view.h
index b0e4737..cc34aa8 100644
--- a/media/tools/player_wtl/view.h
+++ b/media/tools/player_wtl/view.h
@@ -144,11 +144,12 @@ class WtlVideoWindow : public CScrollWindowImpl<WtlVideoWindow> {
uint8 *movie_dib_bits = reinterpret_cast<uint8 *>(bm.bmBits) +
bm.bmWidthBytes * (bm.bmHeight - 1);
int dibrowbytes = -bm.bmWidthBytes;
- int clipped_width = video_frame->data_size().width();
+ // Not accounting for cropping presently.
+ int clipped_width = video_frame->coded_size().width();
if (dibwidth < clipped_width) {
clipped_width = dibwidth;
}
- int clipped_height = video_frame->data_size().height();
+ int clipped_height = video_frame->coded_size().height();
if (dibheight < clipped_height) {
clipped_height = dibheight;
}
@@ -243,7 +244,7 @@ class WtlVideoWindow : public CScrollWindowImpl<WtlVideoWindow> {
if (frame) {
// Size the window the first time we get a frame.
if (!last_frame_)
- SetSize(frame->data_size().width(), frame->data_size().height());
+ SetSize(frame->coded_size().width(), frame->coded_size().height());
base::TimeDelta frame_timestamp = frame->GetTimestamp();
if (frame != last_frame_ || frame_timestamp != last_timestamp_) {
@@ -436,24 +437,24 @@ class WtlVideoWindow : public CScrollWindowImpl<WtlVideoWindow> {
if (file_yuv != NULL) {
fseek(file_yuv, 0, SEEK_END);
const int frame_size =
- video_frame->data_size().width() * video_frame->data_size().height();
- for (int y = 0; y < video_frame->data_size().height(); ++y)
+ video_frame->coded_size().width() * video_frame->coded_size().height();
+ for (int y = 0; y < video_frame->coded_size().height(); ++y)
fwrite(video_frame->data(0) + video_frame->stride(0)*y,
- video_frame->data_size().width(), sizeof(uint8), file_yuv);
- for (int y = 0; y < video_frame->data_size().height()/2; ++y)
+ video_frame->coded_size().width(), sizeof(uint8), file_yuv);
+ for (int y = 0; y < video_frame->coded_size().height()/2; ++y)
fwrite(video_frame->data(1) + video_frame->stride(1)*y,
- video_frame->data_size().width() / 2, sizeof(uint8), file_yuv);
- for (int y = 0; y < video_frame->data_size().height()/2; ++y)
+ video_frame->coded_size().width() / 2, sizeof(uint8), file_yuv);
+ for (int y = 0; y < video_frame->coded_size().height()/2; ++y)
fwrite(video_frame->data(2) + video_frame->stride(2)*y,
- video_frame->data_size().width() / 2, sizeof(uint8), file_yuv);
+ video_frame->coded_size().width() / 2, sizeof(uint8), file_yuv);
fclose(file_yuv);
#if TESTING
static int frame_dump_count = 0;
char outputbuf[512];
_snprintf_s(outputbuf, sizeof(outputbuf), "yuvdump %4d %dx%d stride %d\n",
- frame_dump_count, video_frame->data_size().width(),
- video_frame->data_size().height(),
+ frame_dump_count, video_frame->coded_size().width(),
+ video_frame->coded_size().height(),
video_frame->stride(0));
OutputDebugStringA(outputbuf);
++frame_dump_count;
diff --git a/media/tools/player_x11/gl_video_renderer.cc b/media/tools/player_x11/gl_video_renderer.cc
index 50abdd9..334dfad 100644
--- a/media/tools/player_x11/gl_video_renderer.cc
+++ b/media/tools/player_x11/gl_video_renderer.cc
@@ -121,8 +121,7 @@ GlVideoRenderer::~GlVideoRenderer() {
void GlVideoRenderer::Paint(media::VideoFrame* video_frame) {
if (!gl_context_)
- Initialize(video_frame->data_size().width(),
- video_frame->data_size().height());
+ Initialize(video_frame->coded_size(), video_frame->visible_rect());
// Convert YUV frame to RGB.
DCHECK(video_frame->format() == media::VideoFrame::YV12 ||
@@ -147,12 +146,12 @@ void GlVideoRenderer::Paint(media::VideoFrame* video_frame) {
glXSwapBuffers(display_, window_);
}
-void GlVideoRenderer::Initialize(int width, int height) {
+void GlVideoRenderer::Initialize(gfx::Size coded_size, gfx::Rect visible_rect) {
CHECK(!gl_context_);
LOG(INFO) << "Initializing GL Renderer...";
// Resize the window to fit that of the video.
- XResizeWindow(display_, window_, width, height);
+ XResizeWindow(display_, window_, visible_rect.width(), visible_rect.height());
gl_context_ = InitGLContext(display_, window_);
CHECK(gl_context_) << "Failed to initialize GL context";
@@ -241,8 +240,16 @@ void GlVideoRenderer::Initialize(int width, int height) {
int tc_location = glGetAttribLocation(program, "in_tc");
glEnableVertexAttribArray(tc_location);
- glVertexAttribPointer(tc_location, 2, GL_FLOAT, GL_FALSE, 0,
- kTextureCoords);
+ float verts[8];
+ float x0 = static_cast<float>(visible_rect.x()) / coded_size.width();
+ float y0 = static_cast<float>(visible_rect.y()) / coded_size.height();
+ float x1 = static_cast<float>(visible_rect.right()) / coded_size.width();
+ float y1 = static_cast<float>(visible_rect.bottom()) / coded_size.height();
+ verts[0] = x0; verts[1] = y0;
+ verts[2] = x0; verts[3] = y1;
+ verts[4] = x1; verts[5] = y0;
+ verts[6] = x1; verts[7] = y1;
+ glVertexAttribPointer(tc_location, 2, GL_FLOAT, GL_FALSE, 0, verts);
// We are getting called on a thread. Release the context so that it can be
// made current on the main thread.
diff --git a/media/tools/player_x11/gl_video_renderer.h b/media/tools/player_x11/gl_video_renderer.h
index 28d3ffb..b8818a1 100644
--- a/media/tools/player_x11/gl_video_renderer.h
+++ b/media/tools/player_x11/gl_video_renderer.h
@@ -7,6 +7,8 @@
#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/size.h"
#include "ui/gl/gl_bindings.h"
class MessageLoop;
@@ -27,7 +29,7 @@ class GlVideoRenderer : public base::RefCountedThreadSafe<GlVideoRenderer> {
private:
// Initializes GL rendering for the given dimensions.
- void Initialize(int width, int height);
+ void Initialize(gfx::Size coded_size, gfx::Rect visible_rect);
Display* display_;
Window window_;
diff --git a/media/tools/player_x11/x11_video_renderer.cc b/media/tools/player_x11/x11_video_renderer.cc
index d259d6b..43a18cd 100644
--- a/media/tools/player_x11/x11_video_renderer.cc
+++ b/media/tools/player_x11/x11_video_renderer.cc
@@ -84,16 +84,18 @@ X11VideoRenderer::~X11VideoRenderer() {
}
void X11VideoRenderer::Paint(media::VideoFrame* video_frame) {
- int width = video_frame->data_size().width();
- int height = video_frame->data_size().height();
-
if (!image_)
- Initialize(width, height);
+ Initialize(video_frame->coded_size(), video_frame->visible_rect());
+
+ const int coded_width = video_frame->coded_size().width();
+ const int coded_height = video_frame->coded_size().height();
+ const int visible_width = video_frame->visible_rect().width();
+ const int visible_height = video_frame->visible_rect().height();
// Check if we need to reallocate our XImage.
- if (image_->width != width || image_->height != height) {
+ if (image_->width != coded_width || image_->height != coded_height) {
XDestroyImage(image_);
- image_ = CreateImage(display_, width, height);
+ image_ = CreateImage(display_, coded_width, coded_height);
}
// Convert YUV frame to RGB.
@@ -109,9 +111,7 @@ void X11VideoRenderer::Paint(media::VideoFrame* video_frame) {
media::ConvertYUVToRGB32(video_frame->data(media::VideoFrame::kYPlane),
video_frame->data(media::VideoFrame::kUPlane),
video_frame->data(media::VideoFrame::kVPlane),
- (uint8*)image_->data,
- video_frame->data_size().width(),
- video_frame->data_size().height(),
+ (uint8*)image_->data, coded_width, coded_height,
video_frame->stride(media::VideoFrame::kYPlane),
video_frame->stride(media::VideoFrame::kUPlane),
image_->bytes_per_line,
@@ -125,8 +125,8 @@ void X11VideoRenderer::Paint(media::VideoFrame* video_frame) {
// Creates a XImage.
XImage image;
memset(&image, 0, sizeof(image));
- image.width = width;
- image.height = height;
+ image.width = coded_width;
+ image.height = coded_height;
image.depth = 32;
image.bits_per_pixel = 32;
image.format = ZPixmap;
@@ -140,15 +140,15 @@ void X11VideoRenderer::Paint(media::VideoFrame* video_frame) {
image.data = image_->data;
// Creates a pixmap and uploads from the XImage.
- unsigned long pixmap = XCreatePixmap(display_,
- window_,
- width,
- height,
+ unsigned long pixmap = XCreatePixmap(display_, window_,
+ visible_width, visible_height,
32);
GC gc = XCreateGC(display_, pixmap, 0, NULL);
XPutImage(display_, pixmap, gc, &image,
- 0, 0, 0, 0,
- width, height);
+ video_frame->visible_rect().x(),
+ video_frame->visible_rect().y(),
+ 0, 0,
+ visible_width, visible_height);
XFreeGC(display_, gc);
// Creates the picture representing the pixmap.
@@ -158,7 +158,7 @@ void X11VideoRenderer::Paint(media::VideoFrame* video_frame) {
// Composite the picture over the picture representing the window.
XRenderComposite(display_, PictOpSrc, picture, 0,
picture_, 0, 0, 0, 0, 0, 0,
- width, height);
+ visible_width, visible_height);
XRenderFreePicture(display_, picture);
XFreePixmap(display_, pixmap);
@@ -171,18 +171,21 @@ void X11VideoRenderer::Paint(media::VideoFrame* video_frame) {
// to the window.
GC gc = XCreateGC(display_, window_, 0, NULL);
XPutImage(display_, window_, gc, image_,
- 0, 0, 0, 0, width, height);
+ video_frame->visible_rect().x(),
+ video_frame->visible_rect().y(),
+ 0, 0, visible_width, visible_height);
XFlush(display_);
XFreeGC(display_, gc);
}
-void X11VideoRenderer::Initialize(int width, int height) {
+void X11VideoRenderer::Initialize(gfx::Size coded_size,
+ gfx::Rect visible_rect) {
CHECK(!image_);
LOG(INFO) << "Initializing X11 Renderer...";
// Resize the window to fit that of the video.
- XResizeWindow(display_, window_, width, height);
- image_ = CreateImage(display_, width, height);
+ XResizeWindow(display_, window_, visible_rect.width(), visible_rect.height());
+ image_ = CreateImage(display_, coded_size.width(), coded_size.height());
// Testing XRender support. We'll use the very basic of XRender
// so if it presents it is already good enough. We don't need
diff --git a/media/tools/player_x11/x11_video_renderer.h b/media/tools/player_x11/x11_video_renderer.h
index b91c565..05c624c 100644
--- a/media/tools/player_x11/x11_video_renderer.h
+++ b/media/tools/player_x11/x11_video_renderer.h
@@ -9,6 +9,8 @@
#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/size.h"
class MessageLoop;
@@ -28,7 +30,7 @@ class X11VideoRenderer : public base::RefCountedThreadSafe<X11VideoRenderer> {
private:
// Initializes X11 rendering for the given dimensions.
- void Initialize(int width, int height);
+ void Initialize(gfx::Size coded_size, gfx::Rect visible_rect);
Display* display_;
Window window_;
diff --git a/media/tools/scaler_bench/scaler_bench.cc b/media/tools/scaler_bench/scaler_bench.cc
index d8525d1..18c4ca1 100644
--- a/media/tools/scaler_bench/scaler_bench.cc
+++ b/media/tools/scaler_bench/scaler_bench.cc
@@ -122,7 +122,8 @@ static double BenchmarkFilter(media::ScaleFilter filter) {
gfx::Size dest_size(dest_width, dest_height);
dest_frames.push_back(
- VideoFrame::CreateFrame(VideoFrame::RGB32, dest_size, dest_size,
+ VideoFrame::CreateFrame(VideoFrame::RGB32, dest_size,
+ gfx::Rect(dest_size), dest_size,
TimeDelta::FromSeconds(0)));
}
@@ -160,7 +161,8 @@ static double BenchmarkScaleWithRect() {
gfx::Size dest_size(dest_width, dest_height);
dest_frames.push_back(
- VideoFrame::CreateFrame(VideoFrame::RGB32, dest_size, dest_size,
+ VideoFrame::CreateFrame(VideoFrame::RGB32, dest_size,
+ gfx::Rect(dest_size), dest_size,
TimeDelta::FromSeconds(0)));
}
diff --git a/media/tools/shader_bench/cpu_color_painter.cc b/media/tools/shader_bench/cpu_color_painter.cc
index b99b803..a7cb570 100644
--- a/media/tools/shader_bench/cpu_color_painter.cc
+++ b/media/tools/shader_bench/cpu_color_painter.cc
@@ -67,7 +67,8 @@ void CPUColorPainter::Paint(scoped_refptr<media::VideoFrame> video_frame) {
// Convert to RGB32 frame.
scoped_refptr<media::VideoFrame> rgba_frame =
media::VideoFrame::CreateFrame(media::VideoFrame::RGB32,
- video_frame->data_size(),
+ video_frame->coded_size(),
+ video_frame->visible_rect(),
video_frame->natural_size(),
base::TimeDelta());
@@ -75,16 +76,19 @@ void CPUColorPainter::Paint(scoped_refptr<media::VideoFrame> video_frame) {
video_frame->data(media::VideoFrame::kUPlane),
video_frame->data(media::VideoFrame::kVPlane),
rgba_frame->data(0),
- video_frame->data_size().width(),
- video_frame->data_size().height(),
+ video_frame->coded_size().width(),
+ video_frame->coded_size().height(),
video_frame->stride(media::VideoFrame::kYPlane),
video_frame->stride(media::VideoFrame::kUPlane),
rgba_frame->stride(0),
media::YV12);
glBindTexture(GL_TEXTURE_2D, textures_[0]);
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, rgba_frame->data_size().width(),
- rgba_frame->data_size().height(), GL_RGBA, GL_UNSIGNED_BYTE,
+ // Not accounting for x/y offset presently.
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
+ rgba_frame->visible_rect().width(),
+ rgba_frame->visible_rect().height(),
+ GL_RGBA, GL_UNSIGNED_BYTE,
rgba_frame->data(0));
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
diff --git a/media/tools/shader_bench/gpu_color_painter.cc b/media/tools/shader_bench/gpu_color_painter.cc
index a408de2..17155ee 100644
--- a/media/tools/shader_bench/gpu_color_painter.cc
+++ b/media/tools/shader_bench/gpu_color_painter.cc
@@ -104,8 +104,9 @@ void GPUColorWithLuminancePainter::Initialize(int width, int height) {
void GPUColorWithLuminancePainter::Paint(
scoped_refptr<media::VideoFrame> video_frame) {
- int width = video_frame->data_size().width();
- int height = video_frame->data_size().height();
+ // Not accounting for x/y offset presently.
+ int width = video_frame->visible_rect().width();
+ int height = video_frame->visible_rect().height();
for (unsigned int i = 0; i < kNumYUVPlanes; ++i) {
unsigned int plane_width =
(i == media::VideoFrame::kYPlane) ? width : width / 2;
diff --git a/media/tools/shader_bench/shader_bench.cc b/media/tools/shader_bench/shader_bench.cc
index 17a45a4..897e588 100644
--- a/media/tools/shader_bench/shader_bench.cc
+++ b/media/tools/shader_bench/shader_bench.cc
@@ -53,7 +53,8 @@ void GetFrames(std::string file_name,
gfx::Size size(width, height);
for (int i = 0; i < num_frames; i++) {
scoped_refptr<media::VideoFrame> video_frame =
- media::VideoFrame::CreateFrame(media::VideoFrame::YV12, size, size,
+ media::VideoFrame::CreateFrame(media::VideoFrame::YV12, size,
+ gfx::Rect(size), size,
base::TimeDelta());
long bytes_read =
fread(video_frame->data(0), 1, frame_size, file_handle);
diff --git a/webkit/media/android/webmediaplayer_android.cc b/webkit/media/android/webmediaplayer_android.cc
index 468e180..6c0722c 100644
--- a/webkit/media/android/webmediaplayer_android.cc
+++ b/webkit/media/android/webmediaplayer_android.cc
@@ -376,8 +376,8 @@ void WebMediaPlayerAndroid::WillDestroyCurrentMessageLoop() {
void WebMediaPlayerAndroid::ReallocateVideoFrame() {
if (texture_id_) {
video_frame_.reset(new WebVideoFrameImpl(VideoFrame::WrapNativeTexture(
- texture_id_, kGLTextureExternalOES, natural_size_, natural_size_,
- base::TimeDelta(),
+ texture_id_, kGLTextureExternalOES, natural_size_,
+ gfx::Rect(natural_size_), natural_size_, base::TimeDelta(),
VideoFrame::ReadPixelsCB(),
base::Closure())));
}
diff --git a/webkit/media/simple_video_frame_provider.cc b/webkit/media/simple_video_frame_provider.cc
index afdf3f8..8cffc03 100644
--- a/webkit/media/simple_video_frame_provider.cc
+++ b/webkit/media/simple_video_frame_provider.cc
@@ -66,6 +66,7 @@ void SimpleVideoFrameProvider::GenerateFrame() {
scoped_refptr<media::VideoFrame> video_frame =
media::VideoFrame::CreateFrame(media::VideoFrame::YV12,
size_,
+ gfx::Rect(size_),
size_,
current_time_);
diff --git a/webkit/media/webvideoframe_impl.cc b/webkit/media/webvideoframe_impl.cc
index 6d26ac6..16e04fa 100644
--- a/webkit/media/webvideoframe_impl.cc
+++ b/webkit/media/webvideoframe_impl.cc
@@ -37,18 +37,6 @@ WebVideoFrame::Format WebVideoFrameImpl::format() const {
return WebVideoFrame::FormatInvalid;
}
-unsigned WebVideoFrameImpl::width() const {
- if (video_frame_.get())
- return video_frame_->data_size().width();
- return 0;
-}
-
-unsigned WebVideoFrameImpl::height() const {
- if (video_frame_.get())
- return video_frame_->data_size().height();
- return 0;
-}
-
unsigned WebVideoFrameImpl::planes() const {
if (!video_frame_.get())
return 0;
@@ -69,12 +57,6 @@ unsigned WebVideoFrameImpl::planes() const {
return 0;
}
-int WebVideoFrameImpl::stride(unsigned plane) const {
- if (video_frame_.get())
- return static_cast<int>(video_frame_->stride(plane));
- return 0;
-}
-
const void* WebVideoFrameImpl::data(unsigned plane) const {
if (!video_frame_.get() || format() == FormatNativeTexture)
return NULL;
@@ -93,4 +75,16 @@ unsigned WebVideoFrameImpl::textureTarget() const {
return video_frame_->texture_target();
}
+WebKit::WebRect WebVideoFrameImpl::visibleRect() const {
+ if (!video_frame_.get())
+ return WebKit::WebRect(0, 0, 0, 0);
+ return WebKit::WebRect(video_frame_->visible_rect());
+}
+
+WebKit::WebSize WebVideoFrameImpl::textureSize() const {
+ if (!video_frame_.get() || format() != FormatNativeTexture)
+ return WebKit::WebSize(0, 0);
+ return WebKit::WebSize(video_frame_->coded_size());
+}
+
} // namespace webkit_media
diff --git a/webkit/media/webvideoframe_impl.h b/webkit/media/webvideoframe_impl.h
index 5125112..b2eed0c 100644
--- a/webkit/media/webvideoframe_impl.h
+++ b/webkit/media/webvideoframe_impl.h
@@ -7,6 +7,8 @@
#include "base/compiler_specific.h"
#include "media/base/video_frame.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebRect.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSize.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebVideoFrame.h"
namespace webkit_media {
@@ -20,13 +22,12 @@ class WebVideoFrameImpl : public WebKit::WebVideoFrame {
WebVideoFrameImpl(scoped_refptr<media::VideoFrame> video_frame);
virtual ~WebVideoFrameImpl();
virtual WebVideoFrame::Format format() const;
- virtual unsigned width() const;
- virtual unsigned height() const;
virtual unsigned planes() const;
- virtual int stride(unsigned plane) const;
virtual const void* data(unsigned plane) const;
virtual unsigned textureId() const;
virtual unsigned textureTarget() const;
+ virtual WebKit::WebRect visibleRect() const;
+ virtual WebKit::WebSize textureSize() const;
private:
scoped_refptr<media::VideoFrame> video_frame_;
diff --git a/webkit/plugins/ppapi/content_decryptor_delegate.cc b/webkit/plugins/ppapi/content_decryptor_delegate.cc
index 3c55b6c..9b350ab 100644
--- a/webkit/plugins/ppapi/content_decryptor_delegate.cc
+++ b/webkit/plugins/ppapi/content_decryptor_delegate.cc
@@ -785,7 +785,7 @@ void ContentDecryptorDelegate::DeliverFrame(
// managed by the PPB_Buffer_Dev, and avoid the extra copy.
scoped_refptr<media::VideoFrame> decoded_frame(
media::VideoFrame::CreateFrame(
- format, frame_size, frame_size,
+ format, frame_size, gfx::Rect(frame_size), frame_size,
base::TimeDelta::FromMicroseconds(
frame_info->tracking_info.timestamp)));