Skip to content

Commit

Permalink
Integrated video rotation piping into video layer {impl} and
Browse files Browse the repository at this point in the history
included the transform for fixing the video orientation.

BUG=47554

Review URL: https://codereview.chromium.org/388643002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@288194 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
suderman@chromium.org committed Aug 8, 2014
1 parent 63e18dd commit f78c3e8
Show file tree
Hide file tree
Showing 15 changed files with 294 additions and 37 deletions.
14 changes: 10 additions & 4 deletions cc/layers/video_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,24 @@

namespace cc {

scoped_refptr<VideoLayer> VideoLayer::Create(VideoFrameProvider* provider) {
return make_scoped_refptr(new VideoLayer(provider));
scoped_refptr<VideoLayer> VideoLayer::Create(
VideoFrameProvider* provider,
media::VideoRotation video_rotation) {
return make_scoped_refptr(new VideoLayer(provider, video_rotation));
}

VideoLayer::VideoLayer(VideoFrameProvider* provider) : provider_(provider) {
VideoLayer::VideoLayer(VideoFrameProvider* provider,
media::VideoRotation video_rotation)
: provider_(provider), video_rotation_(video_rotation) {
DCHECK(provider_);
}

VideoLayer::~VideoLayer() {}

scoped_ptr<LayerImpl> VideoLayer::CreateLayerImpl(LayerTreeImpl* tree_impl) {
return VideoLayerImpl::Create(tree_impl, id(), provider_).PassAs<LayerImpl>();
scoped_ptr<VideoLayerImpl> impl =
VideoLayerImpl::Create(tree_impl, id(), provider_, video_rotation_);
return impl.PassAs<LayerImpl>();
}

bool VideoLayer::Update(ResourceUpdateQueue* queue,
Expand Down
8 changes: 6 additions & 2 deletions cc/layers/video_layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "base/callback.h"
#include "cc/base/cc_export.h"
#include "cc/layers/layer.h"
#include "media/base/video_rotation.h"

namespace media { class VideoFrame; }

Expand All @@ -19,7 +20,8 @@ class VideoLayerImpl;
// A Layer that contains a Video element.
class CC_EXPORT VideoLayer : public Layer {
public:
static scoped_refptr<VideoLayer> Create(VideoFrameProvider* provider);
static scoped_refptr<VideoLayer> Create(VideoFrameProvider* provider,
media::VideoRotation video_rotation);

virtual scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl)
OVERRIDE;
Expand All @@ -28,13 +30,15 @@ class CC_EXPORT VideoLayer : public Layer {
const OcclusionTracker<Layer>* occlusion) OVERRIDE;

private:
explicit VideoLayer(VideoFrameProvider* provider);
VideoLayer(VideoFrameProvider* provider, media::VideoRotation video_rotation);
virtual ~VideoLayer();

// This pointer is only for passing to VideoLayerImpl's constructor. It should
// never be dereferenced by this class.
VideoFrameProvider* provider_;

media::VideoRotation video_rotation_;

DISALLOW_COPY_AND_ASSIGN(VideoLayer);
};

Expand Down
55 changes: 44 additions & 11 deletions cc/layers/video_layer_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,21 @@ namespace cc {
scoped_ptr<VideoLayerImpl> VideoLayerImpl::Create(
LayerTreeImpl* tree_impl,
int id,
VideoFrameProvider* provider) {
scoped_ptr<VideoLayerImpl> layer(new VideoLayerImpl(tree_impl, id));
VideoFrameProvider* provider,
media::VideoRotation video_rotation) {
scoped_ptr<VideoLayerImpl> layer(
new VideoLayerImpl(tree_impl, id, video_rotation));
layer->SetProviderClientImpl(VideoFrameProviderClientImpl::Create(provider));
DCHECK(tree_impl->proxy()->IsImplThread());
DCHECK(tree_impl->proxy()->IsMainThreadBlocked());
return layer.Pass();
}

VideoLayerImpl::VideoLayerImpl(LayerTreeImpl* tree_impl, int id)
: LayerImpl(tree_impl, id),
frame_(NULL) {}
VideoLayerImpl::VideoLayerImpl(LayerTreeImpl* tree_impl,
int id,
media::VideoRotation video_rotation)
: LayerImpl(tree_impl, id), frame_(NULL), video_rotation_(video_rotation) {
}

VideoLayerImpl::~VideoLayerImpl() {
if (!provider_client_impl_->Stopped()) {
Expand All @@ -55,7 +59,8 @@ VideoLayerImpl::~VideoLayerImpl() {

scoped_ptr<LayerImpl> VideoLayerImpl::CreateLayerImpl(
LayerTreeImpl* tree_impl) {
return scoped_ptr<LayerImpl>(new VideoLayerImpl(tree_impl, id()));
VideoLayerImpl* impl = new VideoLayerImpl(tree_impl, id(), video_rotation_);
return scoped_ptr<LayerImpl>(impl);
}

void VideoLayerImpl::PushPropertiesTo(LayerImpl* layer) {
Expand Down Expand Up @@ -130,20 +135,48 @@ void VideoLayerImpl::AppendQuads(
AppendQuadsData* append_quads_data) {
DCHECK(frame_.get());

gfx::Transform transform = draw_transform();
gfx::Size rotated_size = content_bounds();

switch (video_rotation_) {
case media::VIDEO_ROTATION_90:
rotated_size = gfx::Size(rotated_size.height(), rotated_size.width());
transform.Rotate(90.0);
transform.Translate(0.0, -rotated_size.height());
break;
case media::VIDEO_ROTATION_180:
transform.Rotate(180.0);
transform.Translate(-rotated_size.width(), -rotated_size.height());
break;
case media::VIDEO_ROTATION_270:
rotated_size = gfx::Size(rotated_size.height(), rotated_size.width());
transform.Rotate(270.0);
transform.Translate(-rotated_size.width(), 0);
case media::VIDEO_ROTATION_0:
break;
}

SharedQuadState* shared_quad_state =
render_pass->CreateAndAppendSharedQuadState();
PopulateSharedQuadState(shared_quad_state);
shared_quad_state->SetAll(transform,
rotated_size,
visible_content_rect(),
clip_rect(),
is_clipped(),
draw_opacity(),
blend_mode(),
sorting_context_id());

AppendDebugBorderQuad(
render_pass, content_bounds(), shared_quad_state, append_quads_data);
render_pass, rotated_size, shared_quad_state, append_quads_data);

gfx::Rect quad_rect(content_bounds());
gfx::Rect quad_rect(rotated_size);
gfx::Rect opaque_rect(contents_opaque() ? quad_rect : gfx::Rect());
gfx::Rect visible_rect = frame_->visible_rect();
gfx::Size coded_size = frame_->coded_size();

gfx::Rect visible_quad_rect = occlusion_tracker.UnoccludedContentRect(
quad_rect, draw_properties().target_space_transform);
gfx::Rect visible_quad_rect =
occlusion_tracker.UnoccludedContentRect(quad_rect, transform);
if (visible_quad_rect.IsEmpty())
return;

Expand Down
12 changes: 10 additions & 2 deletions cc/layers/video_layer_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "cc/layers/layer_impl.h"
#include "cc/resources/release_callback.h"
#include "cc/resources/video_resource_updater.h"
#include "media/base/video_rotation.h"

namespace media {
class VideoFrame;
Expand All @@ -24,7 +25,8 @@ class CC_EXPORT VideoLayerImpl : public LayerImpl {
public:
static scoped_ptr<VideoLayerImpl> Create(LayerTreeImpl* tree_impl,
int id,
VideoFrameProvider* provider);
VideoFrameProvider* provider,
media::VideoRotation video_rotation);
virtual ~VideoLayerImpl();

// LayerImpl implementation.
Expand All @@ -45,15 +47,21 @@ class CC_EXPORT VideoLayerImpl : public LayerImpl {
void SetProviderClientImpl(
scoped_refptr<VideoFrameProviderClientImpl> provider_client_impl);

media::VideoRotation video_rotation() const { return video_rotation_; }

private:
VideoLayerImpl(LayerTreeImpl* tree_impl, int id);
VideoLayerImpl(LayerTreeImpl* tree_impl,
int id,
media::VideoRotation video_rotation);

virtual const char* LayerTypeAsString() const OVERRIDE;

scoped_refptr<VideoFrameProviderClientImpl> provider_client_impl_;

scoped_refptr<media::VideoFrame> frame_;

media::VideoRotation video_rotation_;

scoped_ptr<VideoResourceUpdater> updater_;
VideoFrameExternalResources::ResourceType frame_resource_type_;
std::vector<ResourceProvider::ResourceId> frame_resources_;
Expand Down
149 changes: 147 additions & 2 deletions cc/layers/video_layer_impl_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "cc/layers/video_frame_provider_client_impl.h"
#include "cc/output/context_provider.h"
#include "cc/output/output_surface.h"
#include "cc/quads/draw_quad.h"
#include "cc/test/fake_video_frame_provider.h"
#include "cc/test/layer_test_common.h"
#include "cc/trees/single_thread_proxy.h"
Expand All @@ -33,7 +34,7 @@ TEST(VideoLayerImplTest, Occlusion) {
provider.set_frame(video_frame);

VideoLayerImpl* video_layer_impl =
impl.AddChildToRoot<VideoLayerImpl>(&provider);
impl.AddChildToRoot<VideoLayerImpl>(&provider, media::VIDEO_ROTATION_0);
video_layer_impl->SetBounds(layer_size);
video_layer_impl->SetContentBounds(layer_size);
video_layer_impl->SetDrawsContent(true);
Expand Down Expand Up @@ -82,7 +83,7 @@ TEST(VideoLayerImplTest, DidBecomeActiveShouldSetActiveVideoLayer) {

FakeVideoFrameProvider provider;
VideoLayerImpl* video_layer_impl =
impl.AddChildToRoot<VideoLayerImpl>(&provider);
impl.AddChildToRoot<VideoLayerImpl>(&provider, media::VIDEO_ROTATION_0);

VideoFrameProviderClientImpl* client =
static_cast<VideoFrameProviderClientImpl*>(provider.client());
Expand All @@ -93,5 +94,149 @@ TEST(VideoLayerImplTest, DidBecomeActiveShouldSetActiveVideoLayer) {
EXPECT_EQ(video_layer_impl, client->active_video_layer());
}

TEST(VideoLayerImplTest, Rotated0) {
gfx::Size layer_size(100, 50);
gfx::Size viewport_size(1000, 500);

LayerTestCommon::LayerImplTest impl;
DebugScopedSetImplThreadAndMainThreadBlocked thread(impl.proxy());

scoped_refptr<media::VideoFrame> video_frame =
media::VideoFrame::CreateFrame(media::VideoFrame::YV12,
gfx::Size(20, 10),
gfx::Rect(20, 10),
gfx::Size(20, 10),
base::TimeDelta());
FakeVideoFrameProvider provider;
provider.set_frame(video_frame);

VideoLayerImpl* video_layer_impl =
impl.AddChildToRoot<VideoLayerImpl>(&provider, media::VIDEO_ROTATION_0);
video_layer_impl->SetBounds(layer_size);
video_layer_impl->SetContentBounds(layer_size);
video_layer_impl->SetDrawsContent(true);

impl.CalcDrawProps(viewport_size);
gfx::Rect occluded;
impl.AppendQuadsWithOcclusion(video_layer_impl, occluded);

EXPECT_EQ(1u, impl.quad_list().size());

gfx::Point3F p1(0, impl.quad_list()[0]->rect.height(), 0);
gfx::Point3F p2(impl.quad_list()[0]->rect.width(), 0, 0);
impl.quad_list()[0]->quadTransform().TransformPoint(&p1);
impl.quad_list()[0]->quadTransform().TransformPoint(&p2);
EXPECT_EQ(gfx::Point3F(0, 50, 0), p1);
EXPECT_EQ(gfx::Point3F(100, 0, 0), p2);
}

TEST(VideoLayerImplTest, Rotated90) {
gfx::Size layer_size(100, 50);
gfx::Size viewport_size(1000, 500);

LayerTestCommon::LayerImplTest impl;
DebugScopedSetImplThreadAndMainThreadBlocked thread(impl.proxy());

scoped_refptr<media::VideoFrame> video_frame =
media::VideoFrame::CreateFrame(media::VideoFrame::YV12,
gfx::Size(20, 10),
gfx::Rect(20, 10),
gfx::Size(20, 10),
base::TimeDelta());
FakeVideoFrameProvider provider;
provider.set_frame(video_frame);

VideoLayerImpl* video_layer_impl =
impl.AddChildToRoot<VideoLayerImpl>(&provider, media::VIDEO_ROTATION_90);
video_layer_impl->SetBounds(layer_size);
video_layer_impl->SetContentBounds(layer_size);
video_layer_impl->SetDrawsContent(true);

impl.CalcDrawProps(viewport_size);
gfx::Rect occluded;
impl.AppendQuadsWithOcclusion(video_layer_impl, occluded);

EXPECT_EQ(1u, impl.quad_list().size());

gfx::Point3F p1(0, impl.quad_list()[0]->rect.height(), 0);
gfx::Point3F p2(impl.quad_list()[0]->rect.width(), 0, 0);
impl.quad_list()[0]->quadTransform().TransformPoint(&p1);
impl.quad_list()[0]->quadTransform().TransformPoint(&p2);
EXPECT_EQ(gfx::Point3F(0, 0, 0), p1);
EXPECT_EQ(gfx::Point3F(100, 50, 0), p2);
}

TEST(VideoLayerImplTest, Rotated180) {
gfx::Size layer_size(100, 50);
gfx::Size viewport_size(1000, 500);

LayerTestCommon::LayerImplTest impl;
DebugScopedSetImplThreadAndMainThreadBlocked thread(impl.proxy());

scoped_refptr<media::VideoFrame> video_frame =
media::VideoFrame::CreateFrame(media::VideoFrame::YV12,
gfx::Size(20, 10),
gfx::Rect(20, 10),
gfx::Size(20, 10),
base::TimeDelta());
FakeVideoFrameProvider provider;
provider.set_frame(video_frame);

VideoLayerImpl* video_layer_impl =
impl.AddChildToRoot<VideoLayerImpl>(&provider, media::VIDEO_ROTATION_180);
video_layer_impl->SetBounds(layer_size);
video_layer_impl->SetContentBounds(layer_size);
video_layer_impl->SetDrawsContent(true);

impl.CalcDrawProps(viewport_size);
gfx::Rect occluded;
impl.AppendQuadsWithOcclusion(video_layer_impl, occluded);

EXPECT_EQ(1u, impl.quad_list().size());

gfx::Point3F p1(0, impl.quad_list()[0]->rect.height(), 0);
gfx::Point3F p2(impl.quad_list()[0]->rect.width(), 0, 0);
impl.quad_list()[0]->quadTransform().TransformPoint(&p1);
impl.quad_list()[0]->quadTransform().TransformPoint(&p2);
EXPECT_EQ(gfx::Point3F(100, 0, 0), p1);
EXPECT_EQ(gfx::Point3F(0, 50, 0), p2);
}

TEST(VideoLayerImplTest, Rotated270) {
gfx::Size layer_size(100, 50);
gfx::Size viewport_size(1000, 500);

LayerTestCommon::LayerImplTest impl;
DebugScopedSetImplThreadAndMainThreadBlocked thread(impl.proxy());

scoped_refptr<media::VideoFrame> video_frame =
media::VideoFrame::CreateFrame(media::VideoFrame::YV12,
gfx::Size(20, 10),
gfx::Rect(20, 10),
gfx::Size(20, 10),
base::TimeDelta());
FakeVideoFrameProvider provider;
provider.set_frame(video_frame);

VideoLayerImpl* video_layer_impl =
impl.AddChildToRoot<VideoLayerImpl>(&provider, media::VIDEO_ROTATION_270);
video_layer_impl->SetBounds(layer_size);
video_layer_impl->SetContentBounds(layer_size);
video_layer_impl->SetDrawsContent(true);

impl.CalcDrawProps(viewport_size);
gfx::Rect occluded;
impl.AppendQuadsWithOcclusion(video_layer_impl, occluded);

EXPECT_EQ(1u, impl.quad_list().size());

gfx::Point3F p1(0, impl.quad_list()[0]->rect.height(), 0);
gfx::Point3F p2(impl.quad_list()[0]->rect.width(), 0, 0);
impl.quad_list()[0]->quadTransform().TransformPoint(&p1);
impl.quad_list()[0]->quadTransform().TransformPoint(&p2);
EXPECT_EQ(gfx::Point3F(100, 50, 0), p1);
EXPECT_EQ(gfx::Point3F(0, 0, 0), p2);
}

} // namespace
} // namespace cc
9 changes: 9 additions & 0 deletions cc/test/layer_test_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,15 @@ class LayerTestCommon {
return ptr;
}

template <typename T, typename A, typename B>
T* AddChildToRoot(const A& a, const B& b) {
scoped_ptr<T> layer =
T::Create(host_->host_impl()->active_tree(), 2, a, b);
T* ptr = layer.get();
root_layer_impl_->AddChild(layer.template PassAs<LayerImpl>());
return ptr;
}

template <typename T, typename A, typename B, typename C, typename D>
T* AddChildToRoot(const A& a, const B& b, const C& c, const D& d) {
scoped_ptr<T> layer =
Expand Down
Loading

0 comments on commit f78c3e8

Please sign in to comment.