2014-05-28 07:00:51 +00:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
|
|
|
|
*
|
|
|
|
|
* Use of this source code is governed by a BSD-style license
|
|
|
|
|
* that can be found in the LICENSE file in the root of the source
|
|
|
|
|
* tree. An additional intellectual property rights grant can be found
|
|
|
|
|
* in the file PATENTS. All contributing project authors may
|
|
|
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
|
|
|
*/
|
2015-06-26 06:58:16 +02:00
|
|
|
#include "webrtc/video/video_capture_input.h"
|
2014-05-28 07:00:51 +00:00
|
|
|
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
|
|
#include "testing/gmock/include/gmock/gmock.h"
|
|
|
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
2015-02-26 14:34:55 +00:00
|
|
|
#include "webrtc/base/scoped_ptr.h"
|
2014-05-28 07:00:51 +00:00
|
|
|
#include "webrtc/common.h"
|
2015-11-04 08:31:52 +01:00
|
|
|
#include "webrtc/modules/utility/include/mock/mock_process_thread.h"
|
2015-10-28 18:17:40 +01:00
|
|
|
#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
|
|
|
|
|
#include "webrtc/system_wrappers/include/event_wrapper.h"
|
|
|
|
|
#include "webrtc/system_wrappers/include/ref_count.h"
|
|
|
|
|
#include "webrtc/system_wrappers/include/scoped_vector.h"
|
2015-06-05 11:08:03 +02:00
|
|
|
#include "webrtc/test/fake_texture_frame.h"
|
2015-06-26 06:58:16 +02:00
|
|
|
#include "webrtc/video/send_statistics_proxy.h"
|
2014-05-28 07:00:51 +00:00
|
|
|
|
|
|
|
|
using ::testing::_;
|
|
|
|
|
using ::testing::Invoke;
|
|
|
|
|
using ::testing::NiceMock;
|
|
|
|
|
using ::testing::Return;
|
|
|
|
|
using ::testing::WithArg;
|
|
|
|
|
|
|
|
|
|
// If an output frame does not arrive in 500ms, the test will fail.
|
|
|
|
|
#define FRAME_TIMEOUT_MS 500
|
|
|
|
|
|
|
|
|
|
namespace webrtc {
|
|
|
|
|
|
2015-06-26 06:58:16 +02:00
|
|
|
class MockVideoCaptureCallback : public VideoCaptureCallback {
|
2015-05-21 17:00:24 +02:00
|
|
|
public:
|
2015-05-29 17:21:40 -07:00
|
|
|
MOCK_METHOD1(DeliverFrame, void(VideoFrame video_frame));
|
2015-05-21 17:00:24 +02:00
|
|
|
};
|
|
|
|
|
|
2015-05-29 17:21:40 -07:00
|
|
|
bool EqualFrames(const VideoFrame& frame1, const VideoFrame& frame2);
|
|
|
|
|
bool EqualTextureFrames(const VideoFrame& frame1, const VideoFrame& frame2);
|
|
|
|
|
bool EqualBufferFrames(const VideoFrame& frame1, const VideoFrame& frame2);
|
|
|
|
|
bool EqualFramesVector(const ScopedVector<VideoFrame>& frames1,
|
|
|
|
|
const ScopedVector<VideoFrame>& frames2);
|
|
|
|
|
VideoFrame* CreateVideoFrame(uint8_t length);
|
2014-05-28 07:00:51 +00:00
|
|
|
|
2015-06-26 06:58:16 +02:00
|
|
|
class VideoCaptureInputTest : public ::testing::Test {
|
2014-05-28 07:00:51 +00:00
|
|
|
protected:
|
2015-06-26 06:58:16 +02:00
|
|
|
VideoCaptureInputTest()
|
2015-05-12 16:51:11 +02:00
|
|
|
: mock_process_thread_(new NiceMock<MockProcessThread>),
|
2015-06-26 06:58:16 +02:00
|
|
|
mock_frame_callback_(new NiceMock<MockVideoCaptureCallback>),
|
|
|
|
|
output_frame_event_(EventWrapper::Create()),
|
|
|
|
|
stats_proxy_(Clock::GetRealTimeClock(),
|
2015-12-03 08:10:08 -08:00
|
|
|
webrtc::VideoSendStream::Config(nullptr),
|
|
|
|
|
webrtc::VideoEncoderConfig::ContentType::kRealtimeVideo) {}
|
2014-05-28 07:00:51 +00:00
|
|
|
|
|
|
|
|
virtual void SetUp() {
|
2015-05-21 17:00:24 +02:00
|
|
|
EXPECT_CALL(*mock_frame_callback_, DeliverFrame(_))
|
2014-05-28 07:00:51 +00:00
|
|
|
.WillRepeatedly(
|
2015-06-26 06:58:16 +02:00
|
|
|
WithArg<0>(Invoke(this, &VideoCaptureInputTest::AddOutputFrame)));
|
2014-05-28 07:00:51 +00:00
|
|
|
|
|
|
|
|
Config config;
|
2015-06-26 06:58:16 +02:00
|
|
|
input_.reset(new internal::VideoCaptureInput(
|
|
|
|
|
mock_process_thread_.get(), mock_frame_callback_.get(), nullptr,
|
Reland of Collecting encode_time_ms for each frame (patchset #1 id:1 of https://codereview.webrtc.org/1383283005/ )
Reason for revert:
The reverted commit didn't affect the tests, but the one before: https://codereview.webrtc.org/1385563005/
I've run the test that was failing (EndToEndTest.AssignsTransportSequenceNumbers) locally multiple times, and it works fine (finishes successfully in 150-170ms).
Original issue's description:
> Revert of Collecting encode_time_ms for each frame (patchset #13 id:220001 of https://codereview.webrtc.org/1374233002/ )
>
> Reason for revert:
> Breaks EndToEndTest.AssignsTransportSequenceNumbers in video_engine_tests
> on several bots:
> http://build.chromium.org/p/client.webrtc/builders/Linux64%20Debug/builds/5507
> http://build.chromium.org/p/client.webrtc/builders/Mac64%20Debug/builds/4815
> http://build.chromium.org/p/client.webrtc/builders/Win%20SyzyASan/builds/3272
> http://build.chromium.org/p/client.webrtc/builders/Linux%20Memcheck/builds/4414
>
> It seems very unfortunate that it breaks on _exactly_ the bot configs that aren't covered by the CQ trybots.
>
> Original issue's description:
> > Collecting encode_time_ms for each frame.
> >
> > Also, in Sample struct, replacing double with the original type.
> > It makes more sense to save the original data as truthful as possible, and then
> > convert it to double later if necessary (in the plot script).
> >
> > Committed: https://crrev.com/092b13384e57b33e2003d9736dfa1f491e76f938
> > Cr-Commit-Position: refs/heads/master@{#10184}
>
> TBR=sprang@webrtc.org,pbos@webrtc.org,mflodman@webrtc.org,asapersson@webrtc.org,ivica@webrtc.org
> NOPRESUBMIT=true
> NOTREECHECKS=true
> NOTRY=true
>
> Committed: https://crrev.com/810447972425e890bc7911af27f894b86e9b7e6f
> Cr-Commit-Position: refs/heads/master@{#10185}
TBR=sprang@webrtc.org,pbos@webrtc.org,mflodman@webrtc.org,asapersson@webrtc.org,kjellander@webrtc.org
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
Review URL: https://codereview.webrtc.org/1390163002
Cr-Commit-Position: refs/heads/master@{#10195}
2015-10-07 02:43:12 -07:00
|
|
|
&stats_proxy_, nullptr, nullptr));
|
2014-05-28 07:00:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void TearDown() {
|
2015-06-26 06:58:16 +02:00
|
|
|
// VideoCaptureInput accesses |mock_process_thread_| in destructor and
|
|
|
|
|
// should
|
2014-05-28 07:00:51 +00:00
|
|
|
// be deleted first.
|
2015-06-26 06:58:16 +02:00
|
|
|
input_.reset();
|
2014-05-28 07:00:51 +00:00
|
|
|
}
|
|
|
|
|
|
2015-05-29 17:21:40 -07:00
|
|
|
void AddInputFrame(VideoFrame* frame) {
|
2015-06-26 06:58:16 +02:00
|
|
|
input_->IncomingCapturedFrame(*frame);
|
2014-05-28 07:00:51 +00:00
|
|
|
}
|
|
|
|
|
|
2015-05-29 17:21:40 -07:00
|
|
|
void AddOutputFrame(const VideoFrame& frame) {
|
2015-04-07 14:07:41 +02:00
|
|
|
if (frame.native_handle() == NULL)
|
|
|
|
|
output_frame_ybuffers_.push_back(frame.buffer(kYPlane));
|
2015-05-29 17:21:40 -07:00
|
|
|
output_frames_.push_back(new VideoFrame(frame));
|
2014-05-28 07:00:51 +00:00
|
|
|
output_frame_event_->Set();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WaitOutputFrame() {
|
|
|
|
|
EXPECT_EQ(kEventSignaled, output_frame_event_->Wait(FRAME_TIMEOUT_MS));
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-26 14:34:55 +00:00
|
|
|
rtc::scoped_ptr<MockProcessThread> mock_process_thread_;
|
2015-06-26 06:58:16 +02:00
|
|
|
rtc::scoped_ptr<MockVideoCaptureCallback> mock_frame_callback_;
|
2014-05-28 07:00:51 +00:00
|
|
|
|
2015-06-26 06:58:16 +02:00
|
|
|
// Used to send input capture frames to VideoCaptureInput.
|
|
|
|
|
rtc::scoped_ptr<internal::VideoCaptureInput> input_;
|
2014-05-28 07:00:51 +00:00
|
|
|
|
2015-06-26 06:58:16 +02:00
|
|
|
// Input capture frames of VideoCaptureInput.
|
2015-05-29 17:21:40 -07:00
|
|
|
ScopedVector<VideoFrame> input_frames_;
|
2014-05-28 07:00:51 +00:00
|
|
|
|
|
|
|
|
// Indicate an output frame has arrived.
|
2015-02-26 14:34:55 +00:00
|
|
|
rtc::scoped_ptr<EventWrapper> output_frame_event_;
|
2014-05-28 07:00:51 +00:00
|
|
|
|
2015-06-26 06:58:16 +02:00
|
|
|
// Output delivered frames of VideoCaptureInput.
|
2015-05-29 17:21:40 -07:00
|
|
|
ScopedVector<VideoFrame> output_frames_;
|
2014-05-28 07:00:51 +00:00
|
|
|
|
|
|
|
|
// The pointers of Y plane buffers of output frames. This is used to verify
|
|
|
|
|
// the frame are swapped and not copied.
|
2015-02-25 14:49:48 +00:00
|
|
|
std::vector<const uint8_t*> output_frame_ybuffers_;
|
2015-06-26 06:58:16 +02:00
|
|
|
SendStatisticsProxy stats_proxy_;
|
2014-05-28 07:00:51 +00:00
|
|
|
};
|
|
|
|
|
|
2015-06-26 06:58:16 +02:00
|
|
|
TEST_F(VideoCaptureInputTest, DoesNotRetainHandleNorCopyBuffer) {
|
2015-03-11 11:02:52 +00:00
|
|
|
// Indicate an output frame has arrived.
|
|
|
|
|
rtc::scoped_ptr<EventWrapper> frame_destroyed_event(EventWrapper::Create());
|
|
|
|
|
class TestBuffer : public webrtc::I420Buffer {
|
|
|
|
|
public:
|
2015-06-26 06:58:16 +02:00
|
|
|
explicit TestBuffer(EventWrapper* event)
|
|
|
|
|
: I420Buffer(5, 5), event_(event) {}
|
2015-03-11 11:02:52 +00:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
friend class rtc::RefCountedObject<TestBuffer>;
|
|
|
|
|
~TestBuffer() override { event_->Set(); }
|
|
|
|
|
EventWrapper* event_;
|
|
|
|
|
};
|
|
|
|
|
|
2015-05-29 17:21:40 -07:00
|
|
|
VideoFrame frame(
|
2015-03-11 11:02:52 +00:00
|
|
|
new rtc::RefCountedObject<TestBuffer>(frame_destroyed_event.get()), 1, 1,
|
|
|
|
|
kVideoRotation_0);
|
|
|
|
|
|
|
|
|
|
AddInputFrame(&frame);
|
|
|
|
|
WaitOutputFrame();
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(output_frames_[0]->video_frame_buffer().get(),
|
|
|
|
|
frame.video_frame_buffer().get());
|
|
|
|
|
output_frames_.clear();
|
|
|
|
|
frame.Reset();
|
|
|
|
|
EXPECT_EQ(kEventSignaled, frame_destroyed_event->Wait(FRAME_TIMEOUT_MS));
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-26 06:58:16 +02:00
|
|
|
TEST_F(VideoCaptureInputTest, TestNtpTimeStampSetIfRenderTimeSet) {
|
2015-07-02 04:14:46 -07:00
|
|
|
input_frames_.push_back(CreateVideoFrame(0));
|
2015-03-18 09:51:05 +00:00
|
|
|
input_frames_[0]->set_render_time_ms(5);
|
|
|
|
|
input_frames_[0]->set_ntp_time_ms(0);
|
|
|
|
|
|
|
|
|
|
AddInputFrame(input_frames_[0]);
|
|
|
|
|
WaitOutputFrame();
|
|
|
|
|
EXPECT_GT(output_frames_[0]->ntp_time_ms(),
|
|
|
|
|
input_frames_[0]->render_time_ms());
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-26 06:58:16 +02:00
|
|
|
TEST_F(VideoCaptureInputTest, TestRtpTimeStampSet) {
|
2015-07-02 04:14:46 -07:00
|
|
|
input_frames_.push_back(CreateVideoFrame(0));
|
2015-03-18 09:51:05 +00:00
|
|
|
input_frames_[0]->set_render_time_ms(0);
|
|
|
|
|
input_frames_[0]->set_ntp_time_ms(1);
|
|
|
|
|
input_frames_[0]->set_timestamp(0);
|
|
|
|
|
|
|
|
|
|
AddInputFrame(input_frames_[0]);
|
|
|
|
|
WaitOutputFrame();
|
|
|
|
|
EXPECT_EQ(output_frames_[0]->timestamp(),
|
|
|
|
|
input_frames_[0]->ntp_time_ms() * 90);
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-02 04:14:46 -07:00
|
|
|
TEST_F(VideoCaptureInputTest, DropsFramesWithSameOrOldNtpTimestamp) {
|
|
|
|
|
input_frames_.push_back(CreateVideoFrame(0));
|
|
|
|
|
|
|
|
|
|
input_frames_[0]->set_ntp_time_ms(17);
|
|
|
|
|
AddInputFrame(input_frames_[0]);
|
|
|
|
|
WaitOutputFrame();
|
|
|
|
|
EXPECT_EQ(output_frames_[0]->timestamp(),
|
|
|
|
|
input_frames_[0]->ntp_time_ms() * 90);
|
|
|
|
|
|
|
|
|
|
// Repeat frame with the same NTP timestamp should drop.
|
|
|
|
|
AddInputFrame(input_frames_[0]);
|
|
|
|
|
EXPECT_EQ(kEventTimeout, output_frame_event_->Wait(FRAME_TIMEOUT_MS));
|
|
|
|
|
|
|
|
|
|
// As should frames with a decreased NTP timestamp.
|
|
|
|
|
input_frames_[0]->set_ntp_time_ms(input_frames_[0]->ntp_time_ms() - 1);
|
|
|
|
|
AddInputFrame(input_frames_[0]);
|
|
|
|
|
EXPECT_EQ(kEventTimeout, output_frame_event_->Wait(FRAME_TIMEOUT_MS));
|
|
|
|
|
|
|
|
|
|
// But delivering with an increased NTP timestamp should succeed.
|
|
|
|
|
input_frames_[0]->set_ntp_time_ms(4711);
|
|
|
|
|
AddInputFrame(input_frames_[0]);
|
|
|
|
|
WaitOutputFrame();
|
|
|
|
|
EXPECT_EQ(output_frames_[1]->timestamp(),
|
|
|
|
|
input_frames_[0]->ntp_time_ms() * 90);
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-26 06:58:16 +02:00
|
|
|
TEST_F(VideoCaptureInputTest, TestTextureFrames) {
|
2014-05-28 07:00:51 +00:00
|
|
|
const int kNumFrame = 3;
|
|
|
|
|
for (int i = 0 ; i < kNumFrame; ++i) {
|
2015-06-05 11:08:03 +02:00
|
|
|
test::FakeNativeHandle* dummy_handle = new test::FakeNativeHandle();
|
Revert 8599 "Revert 8580 "Unify underlying frame buffer in I420VideoFrame and...""
It's possible to build Chrome on Windows with this patch now.
BUG=1128
> This is unfortunately causing build problems in Chrome on Windows.
>> Unify underlying frame buffer in I420VideoFrame and WebRtcVideoFrame
>>
>> Currently, I420VideoFrame uses three webrtc::Plane to store pixel data, and WebRtcVideoFrame uses WebRtcVideoFrame::FrameBuffer/webrtc::VideoFrame. The two subclasses WebRtcTextureVideoFrame and TextureVideoFrame use a NativeHandle to store pixel data, and there is also a class WebRtcVideoRenderFrame that wraps an I420VideoFrame.
>>
>> This CL replaces these classes with a new interface VideoFrameBuffer that provides the common functionality. This makes it possible to remove deep frame copies between cricket::VideoFrame and I420VideoFrame.
>>
>> Some additional minor changes are:
>> * Disallow creation of 0x0 texture frames.
>> * Remove the half-implemented ref count functions in I420VideoFrame.
>> * Remove the Alias functionality in WebRtcVideoFrame
>>
>> The final goal is to eliminate all frame copies, but to limit the scope of this CL, some planned changes are postponed to follow-up CL:s (see planned changes in https://webrtc-codereview.appspot.com/38879004, or https://docs.google.com/document/d/1bxoJZNmlo-Z9GnQwIaWpEG6hDlL_W-bzka8Zb_K2NbA/preview). Specifically, this CL:
>> * Keeps empty subclasses WebRtcTextureVideoFrame and TextureVideoFrame, and just delegates the construction to the superclass.
>> * Keeps the deep copies from cricket::VideoFrame to I420VideoFrame.
>>
>> BUG=1128
>> R=mflodman@webrtc.org, pbos@webrtc.org, perkj@webrtc.org, tommi@webrtc.org
>>
>> Review URL: https://webrtc-codereview.appspot.com/42469004
R=pbos@webrtc.org
TBR=mflodman, pbos, perkj, tommi
Review URL: https://webrtc-codereview.appspot.com/45489004
Cr-Commit-Position: refs/heads/master@{#8616}
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8616 4adac7df-926f-26a2-2b94-8c16560cd09d
2015-03-05 14:03:08 +00:00
|
|
|
// Add one to |i| so that width/height > 0.
|
2015-06-05 11:08:03 +02:00
|
|
|
input_frames_.push_back(new VideoFrame(test::CreateFakeNativeHandleFrame(
|
|
|
|
|
dummy_handle, i + 1, i + 1, i + 1, i + 1, webrtc::kVideoRotation_0)));
|
2014-05-28 07:00:51 +00:00
|
|
|
AddInputFrame(input_frames_[i]);
|
|
|
|
|
WaitOutputFrame();
|
2015-04-09 13:44:16 +02:00
|
|
|
EXPECT_EQ(dummy_handle, output_frames_[i]->native_handle());
|
2014-05-28 07:00:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(EqualFramesVector(input_frames_, output_frames_));
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-26 06:58:16 +02:00
|
|
|
TEST_F(VideoCaptureInputTest, TestI420Frames) {
|
2014-05-28 07:00:51 +00:00
|
|
|
const int kNumFrame = 4;
|
2015-02-25 14:49:48 +00:00
|
|
|
std::vector<const uint8_t*> ybuffer_pointers;
|
2014-05-28 07:00:51 +00:00
|
|
|
for (int i = 0; i < kNumFrame; ++i) {
|
2015-05-29 17:21:40 -07:00
|
|
|
input_frames_.push_back(CreateVideoFrame(static_cast<uint8_t>(i + 1)));
|
|
|
|
|
const VideoFrame* const_input_frame = input_frames_[i];
|
2015-02-25 14:49:48 +00:00
|
|
|
ybuffer_pointers.push_back(const_input_frame->buffer(kYPlane));
|
2014-05-28 07:00:51 +00:00
|
|
|
AddInputFrame(input_frames_[i]);
|
|
|
|
|
WaitOutputFrame();
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-18 09:51:05 +00:00
|
|
|
EXPECT_TRUE(EqualFramesVector(input_frames_, output_frames_));
|
|
|
|
|
// Make sure the buffer is not copied.
|
2014-05-28 07:00:51 +00:00
|
|
|
for (int i = 0; i < kNumFrame; ++i)
|
|
|
|
|
EXPECT_EQ(ybuffer_pointers[i], output_frame_ybuffers_[i]);
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-26 06:58:16 +02:00
|
|
|
TEST_F(VideoCaptureInputTest, TestI420FrameAfterTextureFrame) {
|
2015-06-05 11:08:03 +02:00
|
|
|
test::FakeNativeHandle* dummy_handle = new test::FakeNativeHandle();
|
|
|
|
|
input_frames_.push_back(new VideoFrame(test::CreateFakeNativeHandleFrame(
|
|
|
|
|
dummy_handle, 1, 1, 1, 1, webrtc::kVideoRotation_0)));
|
2014-05-28 07:00:51 +00:00
|
|
|
AddInputFrame(input_frames_[0]);
|
|
|
|
|
WaitOutputFrame();
|
2015-04-09 13:44:16 +02:00
|
|
|
EXPECT_EQ(dummy_handle, output_frames_[0]->native_handle());
|
2014-05-28 07:00:51 +00:00
|
|
|
|
2015-05-29 17:21:40 -07:00
|
|
|
input_frames_.push_back(CreateVideoFrame(2));
|
2015-03-18 09:51:05 +00:00
|
|
|
AddInputFrame(input_frames_[1]);
|
2014-05-28 07:00:51 +00:00
|
|
|
WaitOutputFrame();
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(EqualFramesVector(input_frames_, output_frames_));
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-26 06:58:16 +02:00
|
|
|
TEST_F(VideoCaptureInputTest, TestTextureFrameAfterI420Frame) {
|
2015-05-29 17:21:40 -07:00
|
|
|
input_frames_.push_back(CreateVideoFrame(1));
|
2015-03-18 09:51:05 +00:00
|
|
|
AddInputFrame(input_frames_[0]);
|
2014-05-28 07:00:51 +00:00
|
|
|
WaitOutputFrame();
|
|
|
|
|
|
2015-06-05 11:08:03 +02:00
|
|
|
test::FakeNativeHandle* dummy_handle = new test::FakeNativeHandle();
|
|
|
|
|
input_frames_.push_back(new VideoFrame(test::CreateFakeNativeHandleFrame(
|
|
|
|
|
dummy_handle, 1, 1, 2, 2, webrtc::kVideoRotation_0)));
|
2014-05-28 07:00:51 +00:00
|
|
|
AddInputFrame(input_frames_[1]);
|
|
|
|
|
WaitOutputFrame();
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(EqualFramesVector(input_frames_, output_frames_));
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-29 17:21:40 -07:00
|
|
|
bool EqualFrames(const VideoFrame& frame1, const VideoFrame& frame2) {
|
2014-05-28 07:00:51 +00:00
|
|
|
if (frame1.native_handle() != NULL || frame2.native_handle() != NULL)
|
|
|
|
|
return EqualTextureFrames(frame1, frame2);
|
|
|
|
|
return EqualBufferFrames(frame1, frame2);
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-29 17:21:40 -07:00
|
|
|
bool EqualTextureFrames(const VideoFrame& frame1, const VideoFrame& frame2) {
|
2014-05-28 07:00:51 +00:00
|
|
|
return ((frame1.native_handle() == frame2.native_handle()) &&
|
|
|
|
|
(frame1.width() == frame2.width()) &&
|
|
|
|
|
(frame1.height() == frame2.height()) &&
|
|
|
|
|
(frame1.render_time_ms() == frame2.render_time_ms()));
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-29 17:21:40 -07:00
|
|
|
bool EqualBufferFrames(const VideoFrame& frame1, const VideoFrame& frame2) {
|
2014-05-28 07:00:51 +00:00
|
|
|
return ((frame1.width() == frame2.width()) &&
|
|
|
|
|
(frame1.height() == frame2.height()) &&
|
|
|
|
|
(frame1.stride(kYPlane) == frame2.stride(kYPlane)) &&
|
|
|
|
|
(frame1.stride(kUPlane) == frame2.stride(kUPlane)) &&
|
|
|
|
|
(frame1.stride(kVPlane) == frame2.stride(kVPlane)) &&
|
|
|
|
|
(frame1.render_time_ms() == frame2.render_time_ms()) &&
|
|
|
|
|
(frame1.allocated_size(kYPlane) == frame2.allocated_size(kYPlane)) &&
|
|
|
|
|
(frame1.allocated_size(kUPlane) == frame2.allocated_size(kUPlane)) &&
|
|
|
|
|
(frame1.allocated_size(kVPlane) == frame2.allocated_size(kVPlane)) &&
|
|
|
|
|
(memcmp(frame1.buffer(kYPlane), frame2.buffer(kYPlane),
|
|
|
|
|
frame1.allocated_size(kYPlane)) == 0) &&
|
|
|
|
|
(memcmp(frame1.buffer(kUPlane), frame2.buffer(kUPlane),
|
|
|
|
|
frame1.allocated_size(kUPlane)) == 0) &&
|
|
|
|
|
(memcmp(frame1.buffer(kVPlane), frame2.buffer(kVPlane),
|
|
|
|
|
frame1.allocated_size(kVPlane)) == 0));
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-29 17:21:40 -07:00
|
|
|
bool EqualFramesVector(const ScopedVector<VideoFrame>& frames1,
|
|
|
|
|
const ScopedVector<VideoFrame>& frames2) {
|
2014-05-28 07:00:51 +00:00
|
|
|
if (frames1.size() != frames2.size())
|
|
|
|
|
return false;
|
|
|
|
|
for (size_t i = 0; i < frames1.size(); ++i) {
|
|
|
|
|
if (!EqualFrames(*frames1[i], *frames2[i]))
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-29 17:21:40 -07:00
|
|
|
VideoFrame* CreateVideoFrame(uint8_t data) {
|
|
|
|
|
VideoFrame* frame = new VideoFrame();
|
2014-05-28 07:00:51 +00:00
|
|
|
const int width = 36;
|
|
|
|
|
const int height = 24;
|
|
|
|
|
const int kSizeY = width * height * 2;
|
|
|
|
|
uint8_t buffer[kSizeY];
|
|
|
|
|
memset(buffer, data, kSizeY);
|
2015-06-26 06:58:16 +02:00
|
|
|
frame->CreateFrame(buffer, buffer, buffer, width, height, width, width / 2,
|
|
|
|
|
width / 2);
|
2014-05-28 07:00:51 +00:00
|
|
|
frame->set_render_time_ms(data);
|
|
|
|
|
return frame;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace webrtc
|