Add SwapFrame() to VideoSendStreamInput.
Optionally prevents doing a frame copy when putting frames into a VideoSendStream. PutFrame() is still there, which copies the frame. Also removes time_since_capture_ms as a parameter, since I420VideoFrame::render_time_ms() denotes when the frame was captured. BUG=2657 R=mflodman@webrtc.org Review URL: https://webrtc-codereview.appspot.com/5119004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@5265 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
118
webrtc/test/frame_generator.cc
Normal file
118
webrtc/test/frame_generator.cc
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (c) 2013 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.
|
||||
*/
|
||||
#include "webrtc/test/frame_generator.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
namespace {
|
||||
|
||||
class ChromaGenerator : public FrameGenerator {
|
||||
public:
|
||||
ChromaGenerator(size_t width, size_t height)
|
||||
: angle_(0.0), width_(width), height_(height) {
|
||||
assert(width > 0);
|
||||
assert(height > 0);
|
||||
}
|
||||
|
||||
virtual I420VideoFrame* NextFrame() OVERRIDE {
|
||||
frame_.CreateEmptyFrame(static_cast<int>(width_),
|
||||
static_cast<int>(height_),
|
||||
static_cast<int>(width_),
|
||||
static_cast<int>((width_ + 1) / 2),
|
||||
static_cast<int>((width_ + 1) / 2));
|
||||
angle_ += 30.0;
|
||||
uint8_t u = fabs(sin(angle_)) * 0xFF;
|
||||
uint8_t v = fabs(cos(angle_)) * 0xFF;
|
||||
|
||||
memset(frame_.buffer(kYPlane), 0x80, frame_.allocated_size(kYPlane));
|
||||
memset(frame_.buffer(kUPlane), u, frame_.allocated_size(kUPlane));
|
||||
memset(frame_.buffer(kVPlane), v, frame_.allocated_size(kVPlane));
|
||||
return &frame_;
|
||||
}
|
||||
|
||||
private:
|
||||
double angle_;
|
||||
size_t width_;
|
||||
size_t height_;
|
||||
I420VideoFrame frame_;
|
||||
};
|
||||
|
||||
class YuvFileGenerator : public FrameGenerator {
|
||||
public:
|
||||
YuvFileGenerator(FILE* file, size_t width, size_t height)
|
||||
: file_(file), width_(width), height_(height) {
|
||||
assert(file);
|
||||
assert(width > 0);
|
||||
assert(height > 0);
|
||||
frame_size_ = CalcBufferSize(
|
||||
kI420, static_cast<int>(width_), static_cast<int>(height_));
|
||||
frame_buffer_ = new uint8_t[frame_size_];
|
||||
}
|
||||
|
||||
virtual ~YuvFileGenerator() {
|
||||
fclose(file_);
|
||||
delete[] frame_buffer_;
|
||||
}
|
||||
|
||||
virtual I420VideoFrame* NextFrame() OVERRIDE {
|
||||
size_t count = fread(frame_buffer_, 1, frame_size_, file_);
|
||||
if (count < frame_size_) {
|
||||
rewind(file_);
|
||||
return NextFrame();
|
||||
}
|
||||
|
||||
frame_.CreateEmptyFrame(static_cast<int>(width_),
|
||||
static_cast<int>(height_),
|
||||
static_cast<int>(width_),
|
||||
static_cast<int>((width_ + 1) / 2),
|
||||
static_cast<int>((width_ + 1) / 2));
|
||||
|
||||
ConvertToI420(kI420,
|
||||
frame_buffer_,
|
||||
0,
|
||||
0,
|
||||
static_cast<int>(width_),
|
||||
static_cast<int>(height_),
|
||||
0,
|
||||
kRotateNone,
|
||||
&frame_);
|
||||
return &frame_;
|
||||
}
|
||||
|
||||
private:
|
||||
FILE* file_;
|
||||
size_t width_;
|
||||
size_t height_;
|
||||
size_t frame_size_;
|
||||
uint8_t* frame_buffer_;
|
||||
I420VideoFrame frame_;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
FrameGenerator* FrameGenerator::Create(size_t width, size_t height) {
|
||||
return new ChromaGenerator(width, height);
|
||||
}
|
||||
|
||||
FrameGenerator* FrameGenerator::CreateFromYuvFile(const char* file,
|
||||
size_t width,
|
||||
size_t height) {
|
||||
FILE* file_handle = fopen(file, "rb");
|
||||
assert(file_handle);
|
||||
return new YuvFileGenerator(file_handle, width, height);
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
35
webrtc/test/frame_generator.h
Normal file
35
webrtc/test/frame_generator.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2013 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.
|
||||
*/
|
||||
#ifndef WEBRTC_COMMON_VIDEO_TEST_FRAME_GENERATOR_H_
|
||||
#define WEBRTC_COMMON_VIDEO_TEST_FRAME_GENERATOR_H_
|
||||
|
||||
#include "webrtc/common_video/interface/i420_video_frame.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
class FrameGenerator {
|
||||
public:
|
||||
FrameGenerator() {}
|
||||
virtual ~FrameGenerator() {}
|
||||
|
||||
// Returns video frame that remains valid until next call.
|
||||
virtual I420VideoFrame* NextFrame() = 0;
|
||||
|
||||
static FrameGenerator* Create(size_t width, size_t height);
|
||||
static FrameGenerator* CreateFromYuvFile(const char* file,
|
||||
size_t width,
|
||||
size_t height);
|
||||
};
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_COMMON_VIDEO_TEST_FRAME_GENERATOR_H_
|
||||
@ -10,7 +10,7 @@
|
||||
|
||||
#include "webrtc/test/frame_generator_capturer.h"
|
||||
|
||||
#include "webrtc/common_video/test/frame_generator.h"
|
||||
#include "webrtc/test/frame_generator.h"
|
||||
#include "webrtc/system_wrappers/interface/clock.h"
|
||||
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/event_wrapper.h"
|
||||
@ -111,11 +111,9 @@ void FrameGeneratorCapturer::InsertFrame() {
|
||||
{
|
||||
CriticalSectionScoped cs(lock_.get());
|
||||
if (sending_) {
|
||||
int64_t time_before = clock_->CurrentNtpInMilliseconds();
|
||||
I420VideoFrame& frame = frame_generator_->NextFrame();
|
||||
frame.set_render_time_ms(time_before);
|
||||
int64_t time_after = clock_->CurrentNtpInMilliseconds();
|
||||
input_->PutFrame(frame, static_cast<uint32_t>(time_after - time_before));
|
||||
I420VideoFrame* frame = frame_generator_->NextFrame();
|
||||
frame->set_render_time_ms(clock_->CurrentNtpInMilliseconds());
|
||||
input_->SwapFrame(frame);
|
||||
}
|
||||
}
|
||||
tick_->Wait(WEBRTC_EVENT_INFINITE);
|
||||
|
||||
@ -41,6 +41,17 @@
|
||||
'channel_transport/udp_transport_impl.h',
|
||||
],
|
||||
},
|
||||
{
|
||||
'target_name': 'frame_generator',
|
||||
'type': 'static_library',
|
||||
'sources': [
|
||||
'frame_generator.cc',
|
||||
'frame_generator.h',
|
||||
],
|
||||
'dependencies': [
|
||||
'<(webrtc_root)/common_video/common_video.gyp:common_video',
|
||||
],
|
||||
},
|
||||
{
|
||||
'target_name': 'test_support',
|
||||
'type': 'static_library',
|
||||
|
||||
@ -17,7 +17,7 @@ namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
VcmCapturer::VcmCapturer(webrtc::VideoSendStreamInput* input)
|
||||
: VideoCapturer(input), started_(false), vcm_(NULL), last_timestamp_(0) {}
|
||||
: VideoCapturer(input), started_(false), vcm_(NULL) {}
|
||||
|
||||
bool VcmCapturer::Init(size_t width, size_t height, size_t target_fps) {
|
||||
VideoCaptureModule::DeviceInfo* device_info =
|
||||
@ -88,14 +88,8 @@ VcmCapturer::~VcmCapturer() { Destroy(); }
|
||||
|
||||
void VcmCapturer::OnIncomingCapturedFrame(const int32_t id,
|
||||
I420VideoFrame& frame) {
|
||||
if (last_timestamp_ == 0 || frame.timestamp() < last_timestamp_) {
|
||||
last_timestamp_ = frame.timestamp();
|
||||
}
|
||||
|
||||
if (started_) {
|
||||
input_->PutFrame(frame, frame.timestamp() - last_timestamp_);
|
||||
}
|
||||
last_timestamp_ = frame.timestamp();
|
||||
if (started_)
|
||||
input_->SwapFrame(&frame);
|
||||
}
|
||||
|
||||
void VcmCapturer::OnCaptureDelayChanged(const int32_t id, const int32_t delay) {
|
||||
|
||||
@ -40,8 +40,6 @@ class VcmCapturer : public VideoCapturer, public VideoCaptureDataCallback {
|
||||
bool started_;
|
||||
VideoCaptureModule* vcm_;
|
||||
VideoCaptureCapability capability_;
|
||||
|
||||
uint32_t last_timestamp_;
|
||||
};
|
||||
} // test
|
||||
} // webrtc
|
||||
|
||||
@ -119,8 +119,8 @@
|
||||
'<(DEPTH)/third_party/gflags/gflags.gyp:gflags',
|
||||
'<(webrtc_root)/modules/modules.gyp:video_capture_module',
|
||||
'<(webrtc_root)/modules/modules.gyp:media_file',
|
||||
'<(webrtc_root)/test/test.gyp:frame_generator',
|
||||
'<(webrtc_root)/test/test.gyp:test_support',
|
||||
'<(webrtc_root)/common_video/common_video.gyp:frame_generator',
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user