Revert "Add concept of whether video renderer supports rotation."
This reverts commit 0ad48935fc5b92be6e10924a9ee3b0dc39c79104. TBR=guoweis@webrtc.org BUG= Review URL: https://webrtc-codereview.appspot.com/41199004 Cr-Commit-Position: refs/heads/master@{#8663} git-svn-id: http://webrtc.googlecode.com/svn/trunk@8663 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
@ -41,7 +41,8 @@ public class VideoCapturerAndroidTest extends ActivityTestCase {
|
|||||||
private int framesRendered = 0;
|
private int framesRendered = 0;
|
||||||
private Object frameLock = 0;
|
private Object frameLock = 0;
|
||||||
|
|
||||||
private void setSize(int width, int height) {
|
@Override
|
||||||
|
public void setSize(int width, int height) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -528,14 +528,10 @@ public class VideoRendererGui implements GLSurfaceView.Renderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setSize(final int width, final int height) {
|
@Override
|
||||||
if (width == videoWidth && height == videoHeight) {
|
public void setSize(final int width, final int height) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.d(TAG, "ID: " + id + ". YuvImageRenderer.setSize: " +
|
Log.d(TAG, "ID: " + id + ". YuvImageRenderer.setSize: " +
|
||||||
width + " x " + height);
|
width + " x " + height);
|
||||||
|
|
||||||
videoWidth = width;
|
videoWidth = width;
|
||||||
videoHeight = height;
|
videoHeight = height;
|
||||||
int[] strides = { width, width / 2, width / 2 };
|
int[] strides = { width, width / 2, width / 2 };
|
||||||
@ -554,7 +550,6 @@ public class VideoRendererGui implements GLSurfaceView.Renderer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void renderFrame(I420Frame frame) {
|
public synchronized void renderFrame(I420Frame frame) {
|
||||||
setSize(frame.width, frame.height);
|
|
||||||
long now = System.nanoTime();
|
long now = System.nanoTime();
|
||||||
framesReceived++;
|
framesReceived++;
|
||||||
// Skip rendering of this frame if setSize() was not called.
|
// Skip rendering of this frame if setSize() was not called.
|
||||||
|
@ -696,23 +696,21 @@ class VideoRendererWrapper : public VideoRendererInterface {
|
|||||||
|
|
||||||
virtual ~VideoRendererWrapper() {}
|
virtual ~VideoRendererWrapper() {}
|
||||||
|
|
||||||
// This wraps VideoRenderer which still has SetSize.
|
void SetSize(int width, int height) override {
|
||||||
void RenderFrame(const cricket::VideoFrame* video_frame) override {
|
ScopedLocalRefFrame local_ref_frame(AttachCurrentThreadIfNeeded());
|
||||||
|
const bool kNotReserved = false; // What does this param mean??
|
||||||
|
renderer_->SetSize(width, height, kNotReserved);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderFrame(const cricket::VideoFrame* frame) override {
|
||||||
ScopedLocalRefFrame local_ref_frame(AttachCurrentThreadIfNeeded());
|
ScopedLocalRefFrame local_ref_frame(AttachCurrentThreadIfNeeded());
|
||||||
const cricket::VideoFrame* frame =
|
|
||||||
video_frame->GetCopyWithRotationApplied();
|
|
||||||
if (width_ != frame->GetWidth() || height_ != frame->GetHeight()) {
|
|
||||||
width_ = frame->GetWidth();
|
|
||||||
height_ = frame->GetHeight();
|
|
||||||
renderer_->SetSize(width_, height_, 0);
|
|
||||||
}
|
|
||||||
renderer_->RenderFrame(frame);
|
renderer_->RenderFrame(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit VideoRendererWrapper(cricket::VideoRenderer* renderer)
|
explicit VideoRendererWrapper(cricket::VideoRenderer* renderer)
|
||||||
: renderer_(renderer), width_(0), height_(0) {}
|
: renderer_(renderer) {}
|
||||||
int width_, height_;
|
|
||||||
scoped_ptr<cricket::VideoRenderer> renderer_;
|
scoped_ptr<cricket::VideoRenderer> renderer_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -722,6 +720,8 @@ class JavaVideoRendererWrapper : public VideoRendererInterface {
|
|||||||
public:
|
public:
|
||||||
JavaVideoRendererWrapper(JNIEnv* jni, jobject j_callbacks)
|
JavaVideoRendererWrapper(JNIEnv* jni, jobject j_callbacks)
|
||||||
: j_callbacks_(jni, j_callbacks),
|
: j_callbacks_(jni, j_callbacks),
|
||||||
|
j_set_size_id_(GetMethodID(
|
||||||
|
jni, GetObjectClass(jni, j_callbacks), "setSize", "(II)V")),
|
||||||
j_render_frame_id_(GetMethodID(
|
j_render_frame_id_(GetMethodID(
|
||||||
jni, GetObjectClass(jni, j_callbacks), "renderFrame",
|
jni, GetObjectClass(jni, j_callbacks), "renderFrame",
|
||||||
"(Lorg/webrtc/VideoRenderer$I420Frame;)V")),
|
"(Lorg/webrtc/VideoRenderer$I420Frame;)V")),
|
||||||
@ -738,13 +738,14 @@ class JavaVideoRendererWrapper : public VideoRendererInterface {
|
|||||||
|
|
||||||
virtual ~JavaVideoRendererWrapper() {}
|
virtual ~JavaVideoRendererWrapper() {}
|
||||||
|
|
||||||
void RenderFrame(const cricket::VideoFrame* video_frame) override {
|
void SetSize(int width, int height) override {
|
||||||
ScopedLocalRefFrame local_ref_frame(jni());
|
ScopedLocalRefFrame local_ref_frame(jni());
|
||||||
|
jni()->CallVoidMethod(*j_callbacks_, j_set_size_id_, width, height);
|
||||||
|
CHECK_EXCEPTION(jni());
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(guoweis): Remove once the java implementation supports rotation.
|
void RenderFrame(const cricket::VideoFrame* frame) override {
|
||||||
const cricket::VideoFrame* frame =
|
ScopedLocalRefFrame local_ref_frame(jni());
|
||||||
video_frame->GetCopyWithRotationApplied();
|
|
||||||
|
|
||||||
if (frame->GetNativeHandle() != NULL) {
|
if (frame->GetNativeHandle() != NULL) {
|
||||||
jobject j_frame = CricketToJavaTextureFrame(frame);
|
jobject j_frame = CricketToJavaTextureFrame(frame);
|
||||||
jni()->CallVoidMethod(*j_callbacks_, j_render_frame_id_, j_frame);
|
jni()->CallVoidMethod(*j_callbacks_, j_render_frame_id_, j_frame);
|
||||||
@ -797,6 +798,7 @@ class JavaVideoRendererWrapper : public VideoRendererInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ScopedGlobalRef<jobject> j_callbacks_;
|
ScopedGlobalRef<jobject> j_callbacks_;
|
||||||
|
jmethodID j_set_size_id_;
|
||||||
jmethodID j_render_frame_id_;
|
jmethodID j_render_frame_id_;
|
||||||
ScopedGlobalRef<jclass> j_frame_class_;
|
ScopedGlobalRef<jclass> j_frame_class_;
|
||||||
jmethodID j_i420_frame_ctor_id_;
|
jmethodID j_i420_frame_ctor_id_;
|
||||||
|
@ -144,8 +144,7 @@ public class VideoRenderer {
|
|||||||
|
|
||||||
/** The real meat of VideoRendererInterface. */
|
/** The real meat of VideoRendererInterface. */
|
||||||
public static interface Callbacks {
|
public static interface Callbacks {
|
||||||
// |frame| might have pending rotation and implementation of Callbacks
|
public void setSize(int width, int height);
|
||||||
// should handle that by applying rotation during rendering.
|
|
||||||
public void renderFrame(I420Frame frame);
|
public void renderFrame(I420Frame frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,6 +59,7 @@ public class PeerConnectionTest {
|
|||||||
private int expectedIceCandidates = 0;
|
private int expectedIceCandidates = 0;
|
||||||
private int expectedErrors = 0;
|
private int expectedErrors = 0;
|
||||||
private int expectedRenegotiations = 0;
|
private int expectedRenegotiations = 0;
|
||||||
|
private int expectedSetSize = 0;
|
||||||
private int previouslySeenWidth = 0;
|
private int previouslySeenWidth = 0;
|
||||||
private int previouslySeenHeight = 0;
|
private int previouslySeenHeight = 0;
|
||||||
private int expectedFramesDelivered = 0;
|
private int expectedFramesDelivered = 0;
|
||||||
@ -112,8 +113,19 @@ public class PeerConnectionTest {
|
|||||||
gotIceCandidates.add(candidate);
|
gotIceCandidates.add(candidate);
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void setSize(int width, int height) {
|
public synchronized void expectSetSize() {
|
||||||
|
if (RENDER_TO_GUI) {
|
||||||
|
// When new frames are delivered to the GUI renderer we don't get
|
||||||
|
// notified of frame size info.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
++expectedSetSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void setSize(int width, int height) {
|
||||||
assertFalse(RENDER_TO_GUI);
|
assertFalse(RENDER_TO_GUI);
|
||||||
|
assertTrue(--expectedSetSize >= 0);
|
||||||
// Because different camera devices (fake & physical) produce different
|
// Because different camera devices (fake & physical) produce different
|
||||||
// resolutions, we only sanity-check the set sizes,
|
// resolutions, we only sanity-check the set sizes,
|
||||||
assertTrue(width > 0);
|
assertTrue(width > 0);
|
||||||
@ -134,7 +146,6 @@ public class PeerConnectionTest {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void renderFrame(VideoRenderer.I420Frame frame) {
|
public synchronized void renderFrame(VideoRenderer.I420Frame frame) {
|
||||||
setSize(frame.width, frame.height);
|
|
||||||
--expectedFramesDelivered;
|
--expectedFramesDelivered;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,6 +315,9 @@ public class PeerConnectionTest {
|
|||||||
stillWaitingForExpectations.add(
|
stillWaitingForExpectations.add(
|
||||||
"expectedRemoveStreamLabels: " + expectedRemoveStreamLabels.size());
|
"expectedRemoveStreamLabels: " + expectedRemoveStreamLabels.size());
|
||||||
}
|
}
|
||||||
|
if (expectedSetSize != 0) {
|
||||||
|
stillWaitingForExpectations.add("expectedSetSize");
|
||||||
|
}
|
||||||
if (expectedFramesDelivered > 0) {
|
if (expectedFramesDelivered > 0) {
|
||||||
stillWaitingForExpectations.add(
|
stillWaitingForExpectations.add(
|
||||||
"expectedFramesDelivered: " + expectedFramesDelivered);
|
"expectedFramesDelivered: " + expectedFramesDelivered);
|
||||||
@ -422,7 +436,8 @@ public class PeerConnectionTest {
|
|||||||
public int height = -1;
|
public int height = -1;
|
||||||
public int numFramesDelivered = 0;
|
public int numFramesDelivered = 0;
|
||||||
|
|
||||||
private void setSize(int width, int height) {
|
@Override
|
||||||
|
public void setSize(int width, int height) {
|
||||||
assertEquals(this.width, -1);
|
assertEquals(this.width, -1);
|
||||||
assertEquals(this.height, -1);
|
assertEquals(this.height, -1);
|
||||||
this.width = width;
|
this.width = width;
|
||||||
@ -527,6 +542,7 @@ public class PeerConnectionTest {
|
|||||||
VideoSource videoSource = factory.createVideoSource(
|
VideoSource videoSource = factory.createVideoSource(
|
||||||
VideoCapturer.create(""), new MediaConstraints());
|
VideoCapturer.create(""), new MediaConstraints());
|
||||||
|
|
||||||
|
offeringExpectations.expectSetSize();
|
||||||
offeringExpectations.expectRenegotiationNeeded();
|
offeringExpectations.expectRenegotiationNeeded();
|
||||||
WeakReference<MediaStream> oLMS = addTracksToPC(
|
WeakReference<MediaStream> oLMS = addTracksToPC(
|
||||||
factory, offeringPC, videoSource, "offeredMediaStream",
|
factory, offeringPC, videoSource, "offeredMediaStream",
|
||||||
@ -558,6 +574,7 @@ public class PeerConnectionTest {
|
|||||||
assertTrue(sdpLatch.await());
|
assertTrue(sdpLatch.await());
|
||||||
assertNull(sdpLatch.getSdp());
|
assertNull(sdpLatch.getSdp());
|
||||||
|
|
||||||
|
answeringExpectations.expectSetSize();
|
||||||
answeringExpectations.expectRenegotiationNeeded();
|
answeringExpectations.expectRenegotiationNeeded();
|
||||||
WeakReference<MediaStream> aLMS = addTracksToPC(
|
WeakReference<MediaStream> aLMS = addTracksToPC(
|
||||||
factory, answeringPC, videoSource, "answeredMediaStream",
|
factory, answeringPC, videoSource, "answeredMediaStream",
|
||||||
@ -619,6 +636,8 @@ public class PeerConnectionTest {
|
|||||||
// chosen arbitrarily).
|
// chosen arbitrarily).
|
||||||
offeringExpectations.expectFramesDelivered(10);
|
offeringExpectations.expectFramesDelivered(10);
|
||||||
answeringExpectations.expectFramesDelivered(10);
|
answeringExpectations.expectFramesDelivered(10);
|
||||||
|
offeringExpectations.expectSetSize();
|
||||||
|
answeringExpectations.expectSetSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
offeringExpectations.expectStateChange(DataChannel.State.OPEN);
|
offeringExpectations.expectStateChange(DataChannel.State.OPEN);
|
||||||
|
@ -115,27 +115,9 @@ class MediaStreamTrackInterface : public rtc::RefCountInterface,
|
|||||||
// Interface for rendering VideoFrames from a VideoTrack
|
// Interface for rendering VideoFrames from a VideoTrack
|
||||||
class VideoRendererInterface {
|
class VideoRendererInterface {
|
||||||
public:
|
public:
|
||||||
// TODO(guoweis): Remove this function. Obsolete. The implementation of
|
virtual void SetSize(int width, int height) = 0;
|
||||||
// VideoRendererInterface should be able to handle different frame size as
|
|
||||||
// well as pending rotation. If it can't apply the frame rotation by itself,
|
|
||||||
// it should call |frame|.GetCopyWithRotationApplied() to get a frame that has
|
|
||||||
// the rotation applied.
|
|
||||||
virtual void SetSize(int width, int height) {}
|
|
||||||
|
|
||||||
// |frame| may have pending rotation. For clients which can't apply rotation,
|
|
||||||
// |frame|->GetCopyWithRotationApplied() will return a frame that has the
|
|
||||||
// rotation applied.
|
|
||||||
virtual void RenderFrame(const cricket::VideoFrame* frame) = 0;
|
virtual void RenderFrame(const cricket::VideoFrame* frame) = 0;
|
||||||
|
|
||||||
// TODO(guoweis): Remove this function. This is added as a temporary solution
|
|
||||||
// until chrome renderers can apply rotation.
|
|
||||||
// Whether the VideoRenderer has the ability to rotate the frame before being
|
|
||||||
// displayed. The rotation of a frame is carried by
|
|
||||||
// VideoFrame.GetVideoRotation() and is the clockwise angle the frames must be
|
|
||||||
// rotated in order to display the frames correctly. If returning false, the
|
|
||||||
// frame's rotation must be applied before being delivered by RenderFrame.
|
|
||||||
virtual bool CanApplyRotation() { return false; }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// The destructor is protected to prevent deletion via the interface.
|
// The destructor is protected to prevent deletion via the interface.
|
||||||
// This is so that we allow reference counted classes, where the destructor
|
// This is so that we allow reference counted classes, where the destructor
|
||||||
|
@ -35,55 +35,34 @@ namespace webrtc {
|
|||||||
|
|
||||||
class FakeVideoTrackRenderer : public VideoRendererInterface {
|
class FakeVideoTrackRenderer : public VideoRendererInterface {
|
||||||
public:
|
public:
|
||||||
FakeVideoTrackRenderer(VideoTrackInterface* video_track)
|
explicit FakeVideoTrackRenderer(VideoTrackInterface* video_track)
|
||||||
: video_track_(video_track),
|
: video_track_(video_track) {
|
||||||
can_apply_rotation_(true),
|
|
||||||
last_frame_(NULL) {
|
|
||||||
video_track_->AddRenderer(this);
|
|
||||||
}
|
|
||||||
FakeVideoTrackRenderer(VideoTrackInterface* video_track,
|
|
||||||
bool can_apply_rotation)
|
|
||||||
: video_track_(video_track),
|
|
||||||
can_apply_rotation_(can_apply_rotation),
|
|
||||||
last_frame_(NULL) {
|
|
||||||
video_track_->AddRenderer(this);
|
video_track_->AddRenderer(this);
|
||||||
}
|
}
|
||||||
~FakeVideoTrackRenderer() {
|
~FakeVideoTrackRenderer() {
|
||||||
video_track_->RemoveRenderer(this);
|
video_track_->RemoveRenderer(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void RenderFrame(const cricket::VideoFrame* video_frame) override {
|
// Implements VideoRendererInterface
|
||||||
last_frame_ = const_cast<cricket::VideoFrame*>(video_frame);
|
virtual void SetSize(int width, int height) {
|
||||||
|
fake_renderer_.SetSize(width, height, 0);
|
||||||
const cricket::VideoFrame* frame =
|
|
||||||
can_apply_rotation_ ? video_frame
|
|
||||||
: video_frame->GetCopyWithRotationApplied();
|
|
||||||
|
|
||||||
if (!fake_renderer_.SetSize(static_cast<int>(frame->GetWidth()),
|
|
||||||
static_cast<int>(frame->GetHeight()), 0)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fake_renderer_.RenderFrame(frame);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool CanApplyRotation() override { return can_apply_rotation_; }
|
virtual void RenderFrame(const cricket::VideoFrame* frame) {
|
||||||
|
fake_renderer_.RenderFrame(frame);
|
||||||
|
}
|
||||||
|
|
||||||
int errors() const { return fake_renderer_.errors(); }
|
int errors() const { return fake_renderer_.errors(); }
|
||||||
int width() const { return fake_renderer_.width(); }
|
int width() const { return fake_renderer_.width(); }
|
||||||
int height() const { return fake_renderer_.height(); }
|
int height() const { return fake_renderer_.height(); }
|
||||||
|
int num_set_sizes() const { return fake_renderer_.num_set_sizes(); }
|
||||||
int num_rendered_frames() const {
|
int num_rendered_frames() const {
|
||||||
return fake_renderer_.num_rendered_frames();
|
return fake_renderer_.num_rendered_frames();
|
||||||
}
|
}
|
||||||
const cricket::VideoFrame* last_frame() const { return last_frame_; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
cricket::FakeVideoRenderer fake_renderer_;
|
cricket::FakeVideoRenderer fake_renderer_;
|
||||||
rtc::scoped_refptr<VideoTrackInterface> video_track_;
|
rtc::scoped_refptr<VideoTrackInterface> video_track_;
|
||||||
bool can_apply_rotation_;
|
|
||||||
|
|
||||||
// Weak reference for frame pointer comparison only.
|
|
||||||
cricket::VideoFrame* last_frame_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -43,132 +43,57 @@ using webrtc::VideoSource;
|
|||||||
using webrtc::VideoTrack;
|
using webrtc::VideoTrack;
|
||||||
using webrtc::VideoTrackInterface;
|
using webrtc::VideoTrackInterface;
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
class WebRtcVideoTestFrame : public cricket::WebRtcVideoFrame {
|
|
||||||
public:
|
|
||||||
using cricket::WebRtcVideoFrame::SetRotation;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
class VideoTrackTest : public testing::Test {
|
|
||||||
public:
|
|
||||||
VideoTrackTest() {
|
|
||||||
static const char kVideoTrackId[] = "track_id";
|
|
||||||
|
|
||||||
channel_manager_.reset(new cricket::ChannelManager(
|
|
||||||
new cricket::FakeMediaEngine(), new cricket::FakeDeviceManager(),
|
|
||||||
rtc::Thread::Current()));
|
|
||||||
EXPECT_TRUE(channel_manager_->Init());
|
|
||||||
video_track_ = VideoTrack::Create(
|
|
||||||
kVideoTrackId,
|
|
||||||
VideoSource::Create(channel_manager_.get(),
|
|
||||||
new webrtc::RemoteVideoCapturer(), NULL));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
rtc::scoped_ptr<cricket::ChannelManager> channel_manager_;
|
|
||||||
rtc::scoped_refptr<VideoTrackInterface> video_track_;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Test adding renderers to a video track and render to them by providing
|
// Test adding renderers to a video track and render to them by providing
|
||||||
// frames to the source.
|
// frames to the source.
|
||||||
TEST_F(VideoTrackTest, RenderVideo) {
|
TEST(VideoTrack, RenderVideo) {
|
||||||
// FakeVideoTrackRenderer register itself to |video_track_|
|
static const char kVideoTrackId[] = "track_id";
|
||||||
rtc::scoped_ptr<FakeVideoTrackRenderer> renderer_1(
|
|
||||||
new FakeVideoTrackRenderer(video_track_.get()));
|
|
||||||
|
|
||||||
cricket::VideoRenderer* renderer_input =
|
rtc::scoped_ptr<cricket::ChannelManager> channel_manager_;
|
||||||
video_track_->GetSource()->FrameInput();
|
channel_manager_.reset(
|
||||||
ASSERT_FALSE(renderer_input == NULL);
|
new cricket::ChannelManager(new cricket::FakeMediaEngine(),
|
||||||
|
new cricket::FakeDeviceManager(),
|
||||||
|
rtc::Thread::Current()));
|
||||||
|
ASSERT_TRUE(channel_manager_->Init());
|
||||||
|
rtc::scoped_refptr<VideoTrackInterface> video_track(
|
||||||
|
VideoTrack::Create(kVideoTrackId,
|
||||||
|
VideoSource::Create(channel_manager_.get(),
|
||||||
|
new webrtc::RemoteVideoCapturer(),
|
||||||
|
NULL)));
|
||||||
|
// FakeVideoTrackRenderer register itself to |video_track|
|
||||||
|
rtc::scoped_ptr<FakeVideoTrackRenderer> renderer_1(
|
||||||
|
new FakeVideoTrackRenderer(video_track.get()));
|
||||||
|
|
||||||
|
cricket::VideoRenderer* render_input = video_track->GetSource()->FrameInput();
|
||||||
|
ASSERT_FALSE(render_input == NULL);
|
||||||
|
|
||||||
cricket::WebRtcVideoFrame frame;
|
cricket::WebRtcVideoFrame frame;
|
||||||
frame.InitToBlack(123, 123, 1, 1, 0, 0);
|
frame.InitToBlack(123, 123, 1, 1, 0, 0);
|
||||||
renderer_input->RenderFrame(&frame);
|
render_input->RenderFrame(&frame);
|
||||||
EXPECT_EQ(1, renderer_1->num_rendered_frames());
|
EXPECT_EQ(1, renderer_1->num_rendered_frames());
|
||||||
|
|
||||||
|
EXPECT_EQ(1, renderer_1->num_set_sizes());
|
||||||
EXPECT_EQ(123, renderer_1->width());
|
EXPECT_EQ(123, renderer_1->width());
|
||||||
EXPECT_EQ(123, renderer_1->height());
|
EXPECT_EQ(123, renderer_1->height());
|
||||||
|
|
||||||
// FakeVideoTrackRenderer register itself to |video_track_|
|
// FakeVideoTrackRenderer register itself to |video_track|
|
||||||
rtc::scoped_ptr<FakeVideoTrackRenderer> renderer_2(
|
rtc::scoped_ptr<FakeVideoTrackRenderer> renderer_2(
|
||||||
new FakeVideoTrackRenderer(video_track_.get()));
|
new FakeVideoTrackRenderer(video_track.get()));
|
||||||
|
|
||||||
renderer_input->RenderFrame(&frame);
|
render_input->RenderFrame(&frame);
|
||||||
|
|
||||||
|
EXPECT_EQ(1, renderer_1->num_set_sizes());
|
||||||
EXPECT_EQ(123, renderer_1->width());
|
EXPECT_EQ(123, renderer_1->width());
|
||||||
EXPECT_EQ(123, renderer_1->height());
|
EXPECT_EQ(123, renderer_1->height());
|
||||||
|
EXPECT_EQ(1, renderer_2->num_set_sizes());
|
||||||
EXPECT_EQ(123, renderer_2->width());
|
EXPECT_EQ(123, renderer_2->width());
|
||||||
EXPECT_EQ(123, renderer_2->height());
|
EXPECT_EQ(123, renderer_2->height());
|
||||||
|
|
||||||
EXPECT_EQ(2, renderer_1->num_rendered_frames());
|
EXPECT_EQ(2, renderer_1->num_rendered_frames());
|
||||||
EXPECT_EQ(1, renderer_2->num_rendered_frames());
|
EXPECT_EQ(1, renderer_2->num_rendered_frames());
|
||||||
|
|
||||||
video_track_->RemoveRenderer(renderer_1.get());
|
video_track->RemoveRenderer(renderer_1.get());
|
||||||
renderer_input->RenderFrame(&frame);
|
render_input->RenderFrame(&frame);
|
||||||
|
|
||||||
EXPECT_EQ(2, renderer_1->num_rendered_frames());
|
EXPECT_EQ(2, renderer_1->num_rendered_frames());
|
||||||
EXPECT_EQ(2, renderer_2->num_rendered_frames());
|
EXPECT_EQ(2, renderer_2->num_rendered_frames());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test adding renderers which support and don't support rotation and receive
|
|
||||||
// the right frame.
|
|
||||||
TEST_F(VideoTrackTest, RenderVideoWithPendingRotation) {
|
|
||||||
const size_t kWidth = 800;
|
|
||||||
const size_t kHeight = 400;
|
|
||||||
|
|
||||||
// Add a renderer which supports rotation.
|
|
||||||
rtc::scoped_ptr<FakeVideoTrackRenderer> rotating_renderer(
|
|
||||||
new FakeVideoTrackRenderer(video_track_.get(), true));
|
|
||||||
|
|
||||||
cricket::VideoRenderer* renderer_input =
|
|
||||||
video_track_->GetSource()->FrameInput();
|
|
||||||
ASSERT_FALSE(renderer_input == NULL);
|
|
||||||
|
|
||||||
// Create a frame with rotation 90 degree.
|
|
||||||
WebRtcVideoTestFrame frame;
|
|
||||||
frame.InitToBlack(kWidth, kHeight, 1, 1, 0, 0);
|
|
||||||
frame.SetRotation(webrtc::kVideoRotation_90);
|
|
||||||
|
|
||||||
// rotating_renderer should see the frame unrotated.
|
|
||||||
renderer_input->RenderFrame(&frame);
|
|
||||||
EXPECT_EQ(1, rotating_renderer->num_rendered_frames());
|
|
||||||
EXPECT_EQ(kWidth, rotating_renderer->width());
|
|
||||||
EXPECT_EQ(kHeight, rotating_renderer->height());
|
|
||||||
EXPECT_EQ(&frame, rotating_renderer->last_frame());
|
|
||||||
|
|
||||||
// Add 2nd renderer which doesn't support rotation.
|
|
||||||
rtc::scoped_ptr<FakeVideoTrackRenderer> non_rotating_renderer(
|
|
||||||
new FakeVideoTrackRenderer(video_track_.get(), false));
|
|
||||||
|
|
||||||
// Render the same 90 degree frame.
|
|
||||||
renderer_input->RenderFrame(&frame);
|
|
||||||
|
|
||||||
// rotating_renderer should see the same frame.
|
|
||||||
EXPECT_EQ(kWidth, rotating_renderer->width());
|
|
||||||
EXPECT_EQ(kHeight, rotating_renderer->height());
|
|
||||||
EXPECT_EQ(&frame, rotating_renderer->last_frame());
|
|
||||||
|
|
||||||
// non_rotating_renderer should see the frame rotated.
|
|
||||||
EXPECT_EQ(kHeight, non_rotating_renderer->width());
|
|
||||||
EXPECT_EQ(kWidth, non_rotating_renderer->height());
|
|
||||||
EXPECT_NE(&frame, non_rotating_renderer->last_frame());
|
|
||||||
|
|
||||||
// Render the same 90 degree frame the 3rd time.
|
|
||||||
renderer_input->RenderFrame(&frame);
|
|
||||||
|
|
||||||
// Now render a frame without rotation.
|
|
||||||
frame.SetRotation(webrtc::kVideoRotation_0);
|
|
||||||
renderer_input->RenderFrame(&frame);
|
|
||||||
|
|
||||||
// rotating_renderer should still only have 1 setsize.
|
|
||||||
EXPECT_EQ(kWidth, rotating_renderer->width());
|
|
||||||
EXPECT_EQ(kHeight, rotating_renderer->height());
|
|
||||||
EXPECT_EQ(&frame, rotating_renderer->last_frame());
|
|
||||||
|
|
||||||
// render_2 should have a new size but should have the same frame.
|
|
||||||
EXPECT_EQ(kWidth, non_rotating_renderer->width());
|
|
||||||
EXPECT_EQ(kHeight, non_rotating_renderer->height());
|
|
||||||
EXPECT_EQ(&frame, non_rotating_renderer->last_frame());
|
|
||||||
}
|
|
||||||
|
@ -26,21 +26,19 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "talk/app/webrtc/videotrackrenderers.h"
|
#include "talk/app/webrtc/videotrackrenderers.h"
|
||||||
#include "talk/media/base/videoframe.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
VideoTrackRenderers::VideoTrackRenderers()
|
VideoTrackRenderers::VideoTrackRenderers()
|
||||||
: enabled_(true) {
|
: width_(0),
|
||||||
|
height_(0),
|
||||||
|
enabled_(true) {
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoTrackRenderers::~VideoTrackRenderers() {
|
VideoTrackRenderers::~VideoTrackRenderers() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoTrackRenderers::AddRenderer(VideoRendererInterface* renderer) {
|
void VideoTrackRenderers::AddRenderer(VideoRendererInterface* renderer) {
|
||||||
if (!renderer) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
rtc::CritScope cs(&critical_section_);
|
rtc::CritScope cs(&critical_section_);
|
||||||
std::vector<RenderObserver>::iterator it = renderers_.begin();
|
std::vector<RenderObserver>::iterator it = renderers_.begin();
|
||||||
for (; it != renderers_.end(); ++it) {
|
for (; it != renderers_.end(); ++it) {
|
||||||
@ -67,6 +65,14 @@ void VideoTrackRenderers::SetEnabled(bool enable) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool VideoTrackRenderers::SetSize(int width, int height, int reserved) {
|
bool VideoTrackRenderers::SetSize(int width, int height, int reserved) {
|
||||||
|
rtc::CritScope cs(&critical_section_);
|
||||||
|
width_ = width;
|
||||||
|
height_ = height;
|
||||||
|
std::vector<RenderObserver>::iterator it = renderers_.begin();
|
||||||
|
for (; it != renderers_.end(); ++it) {
|
||||||
|
it->renderer_->SetSize(width, height);
|
||||||
|
it->size_set_ = true;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,14 +81,13 @@ bool VideoTrackRenderers::RenderFrame(const cricket::VideoFrame* frame) {
|
|||||||
if (!enabled_) {
|
if (!enabled_) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<RenderObserver>::iterator it = renderers_.begin();
|
std::vector<RenderObserver>::iterator it = renderers_.begin();
|
||||||
for (; it != renderers_.end(); ++it) {
|
for (; it != renderers_.end(); ++it) {
|
||||||
if (it->can_apply_rotation_) {
|
if (!it->size_set_) {
|
||||||
it->renderer_->RenderFrame(frame);
|
it->renderer_->SetSize(width_, height_);
|
||||||
} else {
|
it->size_set_ = true;
|
||||||
it->renderer_->RenderFrame(frame->GetCopyWithRotationApplied());
|
|
||||||
}
|
}
|
||||||
|
it->renderer_->RenderFrame(frame);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,6 @@
|
|||||||
#include "talk/app/webrtc/mediastreaminterface.h"
|
#include "talk/app/webrtc/mediastreaminterface.h"
|
||||||
#include "talk/media/base/videorenderer.h"
|
#include "talk/media/base/videorenderer.h"
|
||||||
#include "webrtc/base/criticalsection.h"
|
#include "webrtc/base/criticalsection.h"
|
||||||
#include "webrtc/base/scoped_ptr.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
@ -59,11 +58,14 @@ class VideoTrackRenderers : public cricket::VideoRenderer {
|
|||||||
struct RenderObserver {
|
struct RenderObserver {
|
||||||
explicit RenderObserver(VideoRendererInterface* renderer)
|
explicit RenderObserver(VideoRendererInterface* renderer)
|
||||||
: renderer_(renderer),
|
: renderer_(renderer),
|
||||||
can_apply_rotation_(renderer->CanApplyRotation()) {}
|
size_set_(false) {
|
||||||
|
}
|
||||||
VideoRendererInterface* renderer_;
|
VideoRendererInterface* renderer_;
|
||||||
bool can_apply_rotation_;
|
bool size_set_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int width_;
|
||||||
|
int height_;
|
||||||
bool enabled_;
|
bool enabled_;
|
||||||
std::vector<RenderObserver> renderers_;
|
std::vector<RenderObserver> renderers_;
|
||||||
|
|
||||||
|
@ -98,7 +98,8 @@ public class PeerConnectionClientTest extends InstrumentationTestCase
|
|||||||
doneRendering = new CountDownLatch(expectedFrames);
|
doneRendering = new CountDownLatch(expectedFrames);
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void setSize(int width, int height) {
|
@Override
|
||||||
|
public synchronized void setSize(int width, int height) {
|
||||||
Log.d(TAG, "Set size: " + width + " x " + height);
|
Log.d(TAG, "Set size: " + width + " x " + height);
|
||||||
this.width = width;
|
this.width = width;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
|
@ -33,9 +33,7 @@
|
|||||||
#include "libyuv/planar_functions.h"
|
#include "libyuv/planar_functions.h"
|
||||||
#include "libyuv/scale.h"
|
#include "libyuv/scale.h"
|
||||||
#include "talk/media/base/videocommon.h"
|
#include "talk/media/base/videocommon.h"
|
||||||
#include "webrtc/base/checks.h"
|
|
||||||
#include "webrtc/base/logging.h"
|
#include "webrtc/base/logging.h"
|
||||||
#include "webrtc/base/scoped_ptr.h"
|
|
||||||
|
|
||||||
namespace cricket {
|
namespace cricket {
|
||||||
|
|
||||||
@ -122,51 +120,6 @@ void VideoFrame::CopyToFrame(VideoFrame* dst) const {
|
|||||||
dst->GetYPitch(), dst->GetUPitch(), dst->GetVPitch());
|
dst->GetYPitch(), dst->GetUPitch(), dst->GetVPitch());
|
||||||
}
|
}
|
||||||
|
|
||||||
const VideoFrame* VideoFrame::GetCopyWithRotationApplied() const {
|
|
||||||
// If the frame is not rotated, the caller should reuse this frame instead of
|
|
||||||
// making a redundant copy.
|
|
||||||
if (GetVideoRotation() == webrtc::kVideoRotation_0) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the video frame is backed up by a native handle, it resides in the GPU
|
|
||||||
// memory which we can't rotate here. The assumption is that the renderers
|
|
||||||
// which uses GPU to render should be able to rotate themselves.
|
|
||||||
DCHECK(!GetNativeHandle());
|
|
||||||
|
|
||||||
if (rotated_frame_) {
|
|
||||||
return rotated_frame_.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
int width = static_cast<int>(GetWidth());
|
|
||||||
int height = static_cast<int>(GetHeight());
|
|
||||||
|
|
||||||
int rotated_width = width;
|
|
||||||
int rotated_height = height;
|
|
||||||
if (GetVideoRotation() == webrtc::kVideoRotation_90 ||
|
|
||||||
GetVideoRotation() == webrtc::kVideoRotation_270) {
|
|
||||||
rotated_width = height;
|
|
||||||
rotated_height = width;
|
|
||||||
}
|
|
||||||
|
|
||||||
rotated_frame_.reset(CreateEmptyFrame(rotated_width, rotated_height,
|
|
||||||
GetPixelWidth(), GetPixelHeight(),
|
|
||||||
GetElapsedTime(), GetTimeStamp()));
|
|
||||||
|
|
||||||
// TODO(guoweis): Add a function in webrtc_libyuv.cc to convert from
|
|
||||||
// VideoRotation to libyuv::RotationMode.
|
|
||||||
int ret = libyuv::I420Rotate(
|
|
||||||
GetYPlane(), GetYPitch(), GetUPlane(), GetUPitch(), GetVPlane(),
|
|
||||||
GetVPitch(), rotated_frame_->GetYPlane(), rotated_frame_->GetYPitch(),
|
|
||||||
rotated_frame_->GetUPlane(), rotated_frame_->GetUPitch(),
|
|
||||||
rotated_frame_->GetVPlane(), rotated_frame_->GetVPitch(), width, height,
|
|
||||||
static_cast<libyuv::RotationMode>(GetVideoRotation()));
|
|
||||||
if (ret == 0) {
|
|
||||||
return rotated_frame_.get();
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t VideoFrame::ConvertToRgbBuffer(uint32 to_fourcc,
|
size_t VideoFrame::ConvertToRgbBuffer(uint32 to_fourcc,
|
||||||
uint8* buffer,
|
uint8* buffer,
|
||||||
size_t size,
|
size_t size,
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
#define TALK_MEDIA_BASE_VIDEOFRAME_H_
|
#define TALK_MEDIA_BASE_VIDEOFRAME_H_
|
||||||
|
|
||||||
#include "webrtc/base/basictypes.h"
|
#include "webrtc/base/basictypes.h"
|
||||||
#include "webrtc/base/scoped_ptr.h"
|
|
||||||
#include "webrtc/base/stream.h"
|
#include "webrtc/base/stream.h"
|
||||||
#include "webrtc/common_video/rotation.h"
|
#include "webrtc/common_video/rotation.h"
|
||||||
|
|
||||||
@ -160,10 +159,6 @@ class VideoFrame {
|
|||||||
// Writes the frame into the target VideoFrame.
|
// Writes the frame into the target VideoFrame.
|
||||||
virtual void CopyToFrame(VideoFrame* target) const;
|
virtual void CopyToFrame(VideoFrame* target) const;
|
||||||
|
|
||||||
// Return a copy of frame which has its pending rotation applied. The
|
|
||||||
// ownership of the returned frame is held by this frame.
|
|
||||||
virtual const VideoFrame* GetCopyWithRotationApplied() const;
|
|
||||||
|
|
||||||
// Writes the frame into the given stream and returns the StreamResult.
|
// Writes the frame into the given stream and returns the StreamResult.
|
||||||
// See webrtc/base/stream.h for a description of StreamResult and error.
|
// See webrtc/base/stream.h for a description of StreamResult and error.
|
||||||
// Error may be NULL. If a non-success value is returned from
|
// Error may be NULL. If a non-success value is returned from
|
||||||
@ -228,11 +223,6 @@ class VideoFrame {
|
|||||||
size_t pixel_height,
|
size_t pixel_height,
|
||||||
int64_t elapsed_time,
|
int64_t elapsed_time,
|
||||||
int64_t time_stamp) const = 0;
|
int64_t time_stamp) const = 0;
|
||||||
|
|
||||||
private:
|
|
||||||
// This is mutable as the calculation is expensive but once calculated, it
|
|
||||||
// remains const.
|
|
||||||
mutable rtc::scoped_ptr<VideoFrame> rotated_frame_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace cricket
|
} // namespace cricket
|
||||||
|
@ -42,10 +42,7 @@ class VideoFrame;
|
|||||||
class VideoRenderer {
|
class VideoRenderer {
|
||||||
public:
|
public:
|
||||||
virtual ~VideoRenderer() {}
|
virtual ~VideoRenderer() {}
|
||||||
// Called when the video has changed size. This is also used as an
|
// Called when the video has changed size.
|
||||||
// initialization method to set the UI size before any video frame
|
|
||||||
// rendered. webrtc::ExternalRenderer's FrameSizeChange will invoke this when
|
|
||||||
// it's called or later when a VideoRenderer is attached.
|
|
||||||
virtual bool SetSize(int width, int height, int reserved) = 0;
|
virtual bool SetSize(int width, int height, int reserved) = 0;
|
||||||
// Called when a new frame is available for display.
|
// Called when a new frame is available for display.
|
||||||
virtual bool RenderFrame(const VideoFrame *frame) = 0;
|
virtual bool RenderFrame(const VideoFrame *frame) = 0;
|
||||||
|
@ -122,17 +122,11 @@ bool CarbonVideoRenderer::SetSize(int width, int height, int reserved) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CarbonVideoRenderer::RenderFrame(const VideoFrame* video_frame) {
|
bool CarbonVideoRenderer::RenderFrame(const VideoFrame* frame) {
|
||||||
if (!video_frame) {
|
if (!frame) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const VideoFrame* frame = video_frame->GetCopyWithRotationApplied();
|
|
||||||
|
|
||||||
if (!SetSize(frame->GetWidth(), frame->GetHeight(), 0)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Grab the image lock so we are not trashing up the image being drawn.
|
// Grab the image lock so we are not trashing up the image being drawn.
|
||||||
rtc::CritScope cs(&image_crit_);
|
rtc::CritScope cs(&image_crit_);
|
||||||
frame->ConvertToRgbBuffer(cricket::FOURCC_ABGR,
|
frame->ConvertToRgbBuffer(cricket::FOURCC_ABGR,
|
||||||
|
9
talk/media/devices/gdivideorenderer.cc
Normal file → Executable file
9
talk/media/devices/gdivideorenderer.cc
Normal file → Executable file
@ -146,18 +146,11 @@ bool GdiVideoRenderer::VideoWindow::SetSize(int width, int height) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GdiVideoRenderer::VideoWindow::RenderFrame(const VideoFrame* video_frame) {
|
bool GdiVideoRenderer::VideoWindow::RenderFrame(const VideoFrame* frame) {
|
||||||
if (!handle()) {
|
if (!handle()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const VideoFrame* frame = video_frame->GetCopyWithRotationApplied();
|
|
||||||
|
|
||||||
if (!SetSize(static_cast<int>(frame->GetWidth()),
|
|
||||||
static_cast<int>(frame->GetHeight()))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
SendMessage(handle(), kRenderFrameMsg, reinterpret_cast<WPARAM>(frame), 0);
|
SendMessage(handle(), kRenderFrameMsg, reinterpret_cast<WPARAM>(frame), 0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -53,9 +53,7 @@ GtkVideoRenderer::GtkVideoRenderer(int x, int y)
|
|||||||
: window_(NULL),
|
: window_(NULL),
|
||||||
draw_area_(NULL),
|
draw_area_(NULL),
|
||||||
initial_x_(x),
|
initial_x_(x),
|
||||||
initial_y_(y),
|
initial_y_(y) {
|
||||||
width_(0),
|
|
||||||
height_(0) {
|
|
||||||
g_type_init();
|
g_type_init();
|
||||||
// g_thread_init API is deprecated since glib 2.31.0, see release note:
|
// g_thread_init API is deprecated since glib 2.31.0, see release note:
|
||||||
// http://mail.gnome.org/archives/gnome-announce-list/2011-October/msg00041.html
|
// http://mail.gnome.org/archives/gnome-announce-list/2011-October/msg00041.html
|
||||||
@ -79,11 +77,6 @@ GtkVideoRenderer::~GtkVideoRenderer() {
|
|||||||
bool GtkVideoRenderer::SetSize(int width, int height, int reserved) {
|
bool GtkVideoRenderer::SetSize(int width, int height, int reserved) {
|
||||||
ScopedGdkLock lock;
|
ScopedGdkLock lock;
|
||||||
|
|
||||||
// If the dimension is the same, no-op.
|
|
||||||
if (width_ == width && height_ == height) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For the first frame, initialize the GTK window
|
// For the first frame, initialize the GTK window
|
||||||
if ((!window_ && !Initialize(width, height)) || IsClosed()) {
|
if ((!window_ && !Initialize(width, height)) || IsClosed()) {
|
||||||
return false;
|
return false;
|
||||||
@ -91,21 +84,11 @@ bool GtkVideoRenderer::SetSize(int width, int height, int reserved) {
|
|||||||
|
|
||||||
image_.reset(new uint8[width * height * 4]);
|
image_.reset(new uint8[width * height * 4]);
|
||||||
gtk_widget_set_size_request(draw_area_, width, height);
|
gtk_widget_set_size_request(draw_area_, width, height);
|
||||||
|
|
||||||
width_ = width;
|
|
||||||
height_ = height;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GtkVideoRenderer::RenderFrame(const VideoFrame* video_frame) {
|
bool GtkVideoRenderer::RenderFrame(const VideoFrame* frame) {
|
||||||
if (!video_frame) {
|
if (!frame) {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const VideoFrame* frame = video_frame->GetCopyWithRotationApplied();
|
|
||||||
|
|
||||||
// Need to set size as the frame might be rotated.
|
|
||||||
if (!SetSize(frame->GetWidth(), frame->GetHeight(), 0)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,9 +64,6 @@ class GtkVideoRenderer : public VideoRenderer {
|
|||||||
// The initial position of the window.
|
// The initial position of the window.
|
||||||
int initial_x_;
|
int initial_x_;
|
||||||
int initial_y_;
|
int initial_y_;
|
||||||
|
|
||||||
int width_;
|
|
||||||
int height_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace cricket
|
} // namespace cricket
|
||||||
|
@ -124,9 +124,6 @@ class WebRtcVideoFrame : public VideoFrame {
|
|||||||
virtual size_t ConvertToRgbBuffer(uint32 to_fourcc, uint8* buffer,
|
virtual size_t ConvertToRgbBuffer(uint32 to_fourcc, uint8* buffer,
|
||||||
size_t size, int stride_rgb) const;
|
size_t size, int stride_rgb) const;
|
||||||
|
|
||||||
protected:
|
|
||||||
void SetRotation(webrtc::VideoRotation rotation) { rotation_ = rotation; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual VideoFrame* CreateEmptyFrame(int w, int h, size_t pixel_width,
|
virtual VideoFrame* CreateEmptyFrame(int w, int h, size_t pixel_width,
|
||||||
size_t pixel_height,
|
size_t pixel_height,
|
||||||
|
@ -43,27 +43,6 @@ class NativeHandleImpl : public webrtc::NativeHandle {
|
|||||||
int32_t ref_count_;
|
int32_t ref_count_;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
class WebRtcVideoTestFrame : public cricket::WebRtcVideoFrame {
|
|
||||||
public:
|
|
||||||
using cricket::WebRtcVideoFrame::SetRotation;
|
|
||||||
|
|
||||||
virtual VideoFrame* CreateEmptyFrame(int w,
|
|
||||||
int h,
|
|
||||||
size_t pixel_width,
|
|
||||||
size_t pixel_height,
|
|
||||||
int64_t elapsed_time,
|
|
||||||
int64_t time_stamp) const override {
|
|
||||||
WebRtcVideoTestFrame* frame = new WebRtcVideoTestFrame();
|
|
||||||
frame->InitToBlack(w, h, pixel_width, pixel_height, elapsed_time,
|
|
||||||
time_stamp);
|
|
||||||
return frame;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
class WebRtcVideoFrameTest : public VideoFrameTest<cricket::WebRtcVideoFrame> {
|
class WebRtcVideoFrameTest : public VideoFrameTest<cricket::WebRtcVideoFrame> {
|
||||||
public:
|
public:
|
||||||
WebRtcVideoFrameTest() {
|
WebRtcVideoFrameTest() {
|
||||||
@ -364,31 +343,3 @@ TEST_F(WebRtcVideoFrameTest, CopyTextureFrame) {
|
|||||||
EXPECT_EQ(frame1.GetTimeStamp(), frame2->GetTimeStamp());
|
EXPECT_EQ(frame1.GetTimeStamp(), frame2->GetTimeStamp());
|
||||||
delete frame2;
|
delete frame2;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WebRtcVideoFrameTest, ApplyRotationToFrame) {
|
|
||||||
WebRtcVideoTestFrame applied0;
|
|
||||||
EXPECT_TRUE(IsNull(applied0));
|
|
||||||
rtc::scoped_ptr<rtc::MemoryStream> ms(CreateYuvSample(kWidth, kHeight, 12));
|
|
||||||
EXPECT_TRUE(
|
|
||||||
LoadFrame(ms.get(), cricket::FOURCC_I420, kWidth, kHeight, &applied0));
|
|
||||||
|
|
||||||
// Claim that this frame needs to be rotated for 90 degree.
|
|
||||||
applied0.SetRotation(webrtc::kVideoRotation_90);
|
|
||||||
|
|
||||||
// Apply rotation on frame 1. Output should be different from frame 1.
|
|
||||||
WebRtcVideoTestFrame* applied90 = const_cast<WebRtcVideoTestFrame*>(
|
|
||||||
static_cast<const WebRtcVideoTestFrame*>(
|
|
||||||
applied0.GetCopyWithRotationApplied()));
|
|
||||||
EXPECT_TRUE(applied90);
|
|
||||||
EXPECT_EQ(applied90->GetVideoRotation(), webrtc::kVideoRotation_0);
|
|
||||||
EXPECT_FALSE(IsEqual(applied0, *applied90, 0));
|
|
||||||
|
|
||||||
// Claim the frame 2 needs to be rotated for another 270 degree. The output
|
|
||||||
// from frame 2 rotation should be the same as frame 1.
|
|
||||||
applied90->SetRotation(webrtc::kVideoRotation_270);
|
|
||||||
const cricket::VideoFrame* applied360 =
|
|
||||||
applied90->GetCopyWithRotationApplied();
|
|
||||||
EXPECT_TRUE(applied360);
|
|
||||||
EXPECT_EQ(applied360->GetVideoRotation(), webrtc::kVideoRotation_0);
|
|
||||||
EXPECT_TRUE(IsEqual(applied0, *applied360, 0));
|
|
||||||
}
|
|
||||||
|
Reference in New Issue
Block a user