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:
pbos@webrtc.org
2013-12-11 16:26:16 +00:00
parent 4c3faa9d73
commit 724947b8ef
21 changed files with 199 additions and 164 deletions

View 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

View 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_

View File

@ -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);

View File

@ -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',

View File

@ -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) {

View File

@ -40,8 +40,6 @@ class VcmCapturer : public VideoCapturer, public VideoCaptureDataCallback {
bool started_;
VideoCaptureModule* vcm_;
VideoCaptureCapability capability_;
uint32_t last_timestamp_;
};
} // test
} // webrtc

View File

@ -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',
],
},
],