Made ViEToFileRenderer use a separate thread for rendering frames to file.
Review URL: https://webrtc-codereview.appspot.com/1021011 git-svn-id: http://webrtc.googlecode.com/svn/trunk@3373 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
a22a9bd9ca
commit
77a584be1d
@ -8,15 +8,56 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "video_engine/test/libvietest/include/vie_to_file_renderer.h"
|
||||
#include "webrtc/video_engine/test/libvietest/include/vie_to_file_renderer.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/event_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/thread_wrapper.h"
|
||||
|
||||
namespace test {
|
||||
struct Frame {
|
||||
public:
|
||||
Frame(unsigned char* buffer,
|
||||
int buffer_size,
|
||||
uint32_t timestamp,
|
||||
int64_t render_time)
|
||||
: buffer(new unsigned char[buffer_size]),
|
||||
buffer_size(buffer_size),
|
||||
timestamp(timestamp),
|
||||
render_time(render_time) {
|
||||
memcpy(this->buffer.get(), buffer, buffer_size);
|
||||
}
|
||||
|
||||
webrtc::scoped_array<unsigned char> buffer;
|
||||
int buffer_size;
|
||||
uint32_t timestamp;
|
||||
int64_t render_time;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(Frame);
|
||||
};
|
||||
}; // namespace test
|
||||
|
||||
ViEToFileRenderer::ViEToFileRenderer()
|
||||
: output_file_(NULL) {
|
||||
: output_file_(NULL),
|
||||
output_path_(),
|
||||
output_filename_(),
|
||||
thread_(webrtc::ThreadWrapper::CreateThread(
|
||||
ViEToFileRenderer::RunRenderThread,
|
||||
this, webrtc::kNormalPriority, "ViEToFileRendererThread")),
|
||||
frame_queue_cs_(webrtc::CriticalSectionWrapper::CreateCriticalSection()),
|
||||
frame_render_event_(webrtc::EventWrapper::Create()),
|
||||
render_queue_(),
|
||||
free_frame_queue_() {
|
||||
}
|
||||
|
||||
ViEToFileRenderer::~ViEToFileRenderer() {
|
||||
while (!free_frame_queue_.empty()) {
|
||||
delete free_frame_queue_.front();
|
||||
free_frame_queue_.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
bool ViEToFileRenderer::PrepareForRendering(
|
||||
@ -32,11 +73,19 @@ bool ViEToFileRenderer::PrepareForRendering(
|
||||
|
||||
output_filename_ = output_filename;
|
||||
output_path_ = output_path;
|
||||
return true;
|
||||
unsigned int tid;
|
||||
return thread_->Start(tid);
|
||||
}
|
||||
|
||||
void ViEToFileRenderer::StopRendering() {
|
||||
assert(output_file_ != NULL);
|
||||
if (thread_.get() != NULL) {
|
||||
thread_->SetNotAlive();
|
||||
// Signal that a frame is ready to be written to file.
|
||||
frame_render_event_->Set();
|
||||
// Call Stop() repeatedly, waiting for ProcessRenderQueue() to finish.
|
||||
while (!thread_->Stop()) continue;
|
||||
}
|
||||
std::fclose(output_file_);
|
||||
output_file_ = NULL;
|
||||
}
|
||||
@ -75,16 +124,26 @@ int ViEToFileRenderer::DeliverFrame(unsigned char *buffer,
|
||||
int buffer_size,
|
||||
uint32_t time_stamp,
|
||||
int64_t render_time) {
|
||||
assert(output_file_ != NULL);
|
||||
|
||||
int written = std::fwrite(buffer, sizeof(unsigned char),
|
||||
buffer_size, output_file_);
|
||||
|
||||
if (written == buffer_size) {
|
||||
return 0;
|
||||
webrtc::CriticalSectionScoped lock(frame_queue_cs_.get());
|
||||
test::Frame* frame;
|
||||
if (free_frame_queue_.empty()) {
|
||||
frame = new test::Frame(buffer, buffer_size, time_stamp, render_time);
|
||||
} else {
|
||||
return -1;
|
||||
// Reuse an already allocated frame.
|
||||
frame = free_frame_queue_.front();
|
||||
free_frame_queue_.pop_front();
|
||||
if (frame->buffer_size < buffer_size) {
|
||||
frame->buffer.reset(new unsigned char[buffer_size]);
|
||||
}
|
||||
memcpy(frame->buffer.get(), buffer, buffer_size);
|
||||
frame->buffer_size = buffer_size;
|
||||
frame->timestamp = time_stamp;
|
||||
frame->render_time = render_time;
|
||||
}
|
||||
render_queue_.push_back(frame);
|
||||
// Signal that a frame is ready to be written to file.
|
||||
frame_render_event_->Set();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ViEToFileRenderer::FrameSizeChange(unsigned int width,
|
||||
@ -92,3 +151,35 @@ int ViEToFileRenderer::FrameSizeChange(unsigned int width,
|
||||
unsigned int number_of_streams) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ViEToFileRenderer::RunRenderThread(void* obj) {
|
||||
assert(obj);
|
||||
ViEToFileRenderer* renderer = static_cast<ViEToFileRenderer*>(obj);
|
||||
return renderer->ProcessRenderQueue();
|
||||
}
|
||||
|
||||
bool ViEToFileRenderer::ProcessRenderQueue() {
|
||||
// Wait for a frame to be rendered.
|
||||
frame_render_event_->Wait(WEBRTC_EVENT_INFINITE);
|
||||
frame_queue_cs_->Enter();
|
||||
// Render all frames in the queue.
|
||||
while (!render_queue_.empty()) {
|
||||
test::Frame* frame = render_queue_.front();
|
||||
render_queue_.pop_front();
|
||||
// Leave the critical section before writing to file to not block calls to
|
||||
// the renderer.
|
||||
frame_queue_cs_->Leave();
|
||||
assert(output_file_);
|
||||
int written = std::fwrite(frame->buffer.get(), sizeof(unsigned char),
|
||||
frame->buffer_size, output_file_);
|
||||
frame_queue_cs_->Enter();
|
||||
// Return the frame.
|
||||
free_frame_queue_.push_front(frame);
|
||||
if (written != frame->buffer_size) {
|
||||
frame_queue_cs_->Leave();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
frame_queue_cs_->Leave();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -8,13 +8,27 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef SRC_VIDEO_ENGINE_TEST_AUTO_TEST_HELPERS_VIE_TO_FILE_RENDERER_H_
|
||||
#define SRC_VIDEO_ENGINE_TEST_AUTO_TEST_HELPERS_VIE_TO_FILE_RENDERER_H_
|
||||
#ifndef WEBRTC_VIDEO_ENGINE_TEST_LIBVIETEST_INCLUDE_VIE_TO_FILE_RENDERER_H_
|
||||
#define WEBRTC_VIDEO_ENGINE_TEST_LIBVIETEST_INCLUDE_VIE_TO_FILE_RENDERER_H_
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
#include "video_engine/include/vie_render.h"
|
||||
#include "webrtc/video_engine/include/vie_render.h"
|
||||
#include "webrtc/system_wrappers/interface/constructor_magic.h"
|
||||
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
||||
|
||||
namespace webrtc {
|
||||
class CriticalSectionWrapper;
|
||||
class EventWrapper;
|
||||
class ThreadWrapper;
|
||||
}; // namespace webrtc
|
||||
|
||||
namespace test {
|
||||
struct Frame;
|
||||
}; // namespace test
|
||||
|
||||
class ViEToFileRenderer: public webrtc::ExternalRenderer {
|
||||
public:
|
||||
@ -50,11 +64,20 @@ class ViEToFileRenderer: public webrtc::ExternalRenderer {
|
||||
const std::string GetFullOutputPath() const;
|
||||
|
||||
private:
|
||||
typedef std::list<test::Frame*> FrameQueue;
|
||||
|
||||
static bool RunRenderThread(void* obj);
|
||||
void ForgetOutputFile();
|
||||
bool ProcessRenderQueue();
|
||||
|
||||
std::FILE* output_file_;
|
||||
std::string output_path_;
|
||||
std::string output_filename_;
|
||||
webrtc::scoped_ptr<webrtc::ThreadWrapper> thread_;
|
||||
webrtc::scoped_ptr<webrtc::CriticalSectionWrapper> frame_queue_cs_;
|
||||
webrtc::scoped_ptr<webrtc::EventWrapper> frame_render_event_;
|
||||
FrameQueue render_queue_;
|
||||
FrameQueue free_frame_queue_;
|
||||
};
|
||||
|
||||
#endif // SRC_VIDEO_ENGINE_TEST_AUTO_TEST_HELPERS_VIE_TO_FILE_RENDERER_H_
|
||||
#endif // WEBRTC_VIDEO_ENGINE_TEST_LIBVIETEST_INCLUDE_VIE_TO_FILE_RENDERER_H_
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user