Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / video_engine / test / libvietest / helpers / vie_to_file_renderer.cc
1 /*
2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10
11 #include "webrtc/video_engine/test/libvietest/include/vie_to_file_renderer.h"
12
13 #include <assert.h>
14
15 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
16 #include "webrtc/system_wrappers/interface/event_wrapper.h"
17 #include "webrtc/system_wrappers/interface/thread_wrapper.h"
18
19 namespace test {
20 struct Frame {
21  public:
22   Frame(unsigned char* buffer,
23         int buffer_size,
24         uint32_t timestamp,
25         int64_t render_time)
26       : buffer(new unsigned char[buffer_size]),
27         buffer_size(buffer_size),
28         timestamp(timestamp),
29         render_time(render_time) {
30     memcpy(this->buffer.get(), buffer, buffer_size);
31   }
32
33   webrtc::scoped_ptr<unsigned char[]> buffer;
34   int buffer_size;
35   uint32_t timestamp;
36   int64_t render_time;
37
38  private:
39   DISALLOW_COPY_AND_ASSIGN(Frame);
40 };
41 };  // namespace test
42
43 ViEToFileRenderer::ViEToFileRenderer()
44     : output_file_(NULL),
45       output_path_(),
46       output_filename_(),
47       thread_(webrtc::ThreadWrapper::CreateThread(
48           ViEToFileRenderer::RunRenderThread,
49           this, webrtc::kNormalPriority, "ViEToFileRendererThread")),
50       frame_queue_cs_(webrtc::CriticalSectionWrapper::CreateCriticalSection()),
51       frame_render_event_(webrtc::EventWrapper::Create()),
52       render_queue_(),
53       free_frame_queue_() {
54 }
55
56 ViEToFileRenderer::~ViEToFileRenderer() {
57   while (!free_frame_queue_.empty()) {
58     delete free_frame_queue_.front();
59     free_frame_queue_.pop_front();
60   }
61 }
62
63 bool ViEToFileRenderer::PrepareForRendering(
64     const std::string& output_path,
65     const std::string& output_filename) {
66
67   assert(output_file_ == NULL);
68
69   output_file_ = fopen((output_path + output_filename).c_str(), "wb");
70   if (output_file_ == NULL) {
71     return false;
72   }
73
74   output_filename_ = output_filename;
75   output_path_ = output_path;
76   unsigned int tid;
77   return thread_->Start(tid);
78 }
79
80 void ViEToFileRenderer::StopRendering() {
81   assert(output_file_ != NULL);
82   if (thread_.get() != NULL) {
83     thread_->SetNotAlive();
84     // Signal that a frame is ready to be written to file.
85     frame_render_event_->Set();
86     // Call Stop() repeatedly, waiting for ProcessRenderQueue() to finish.
87     while (!thread_->Stop()) continue;
88   }
89   fclose(output_file_);
90   output_file_ = NULL;
91 }
92
93 bool ViEToFileRenderer::SaveOutputFile(const std::string& prefix) {
94   assert(output_file_ == NULL && output_filename_ != "");
95   if (rename((output_path_ + output_filename_).c_str(),
96                   (output_path_ + prefix + output_filename_).c_str()) != 0) {
97     perror("Failed to rename output file");
98     return false;
99   }
100   ForgetOutputFile();
101   return true;
102 }
103
104 bool ViEToFileRenderer::DeleteOutputFile() {
105   assert(output_file_ == NULL && output_filename_ != "");
106   if (remove((output_path_ + output_filename_).c_str()) != 0) {
107     perror("Failed to delete output file");
108     return false;
109   }
110   ForgetOutputFile();
111   return true;
112 }
113
114 const std::string ViEToFileRenderer::GetFullOutputPath() const {
115   return output_path_ + output_filename_;
116 }
117
118 void ViEToFileRenderer::ForgetOutputFile() {
119   output_filename_ = "";
120   output_path_ = "";
121 }
122
123 int ViEToFileRenderer::DeliverFrame(unsigned char *buffer,
124                                     int buffer_size,
125                                     uint32_t time_stamp,
126                                     int64_t ntp_time_ms,
127                                     int64_t render_time,
128                                     void* /*handle*/) {
129   webrtc::CriticalSectionScoped lock(frame_queue_cs_.get());
130   test::Frame* frame;
131   if (free_frame_queue_.empty()) {
132     frame = new test::Frame(buffer, buffer_size, time_stamp, render_time);
133   } else {
134     // Reuse an already allocated frame.
135     frame = free_frame_queue_.front();
136     free_frame_queue_.pop_front();
137     if (frame->buffer_size < buffer_size) {
138       frame->buffer.reset(new unsigned char[buffer_size]);
139     }
140     memcpy(frame->buffer.get(), buffer, buffer_size);
141     frame->buffer_size = buffer_size;
142     frame->timestamp = time_stamp;
143     frame->render_time = render_time;
144   }
145   render_queue_.push_back(frame);
146   // Signal that a frame is ready to be written to file.
147   frame_render_event_->Set();
148   return 0;
149 }
150
151 bool ViEToFileRenderer::IsTextureSupported() { return false; }
152
153 int ViEToFileRenderer::FrameSizeChange(unsigned int width,
154                                        unsigned int height,
155                                        unsigned int number_of_streams) {
156   return 0;
157 }
158
159 bool ViEToFileRenderer::RunRenderThread(void* obj) {
160   assert(obj);
161   ViEToFileRenderer* renderer = static_cast<ViEToFileRenderer*>(obj);
162   return renderer->ProcessRenderQueue();
163 }
164
165 bool ViEToFileRenderer::ProcessRenderQueue() {
166   // Wait for a frame to be rendered.
167   frame_render_event_->Wait(WEBRTC_EVENT_INFINITE);
168   frame_queue_cs_->Enter();
169   // Render all frames in the queue.
170   while (!render_queue_.empty()) {
171     test::Frame* frame = render_queue_.front();
172     render_queue_.pop_front();
173     // Leave the critical section before writing to file to not block calls to
174     // the renderer.
175     frame_queue_cs_->Leave();
176     assert(output_file_);
177     int written = fwrite(frame->buffer.get(), sizeof(unsigned char),
178                               frame->buffer_size, output_file_);
179     frame_queue_cs_->Enter();
180     // Return the frame.
181     free_frame_queue_.push_front(frame);
182     if (written != frame->buffer_size) {
183       frame_queue_cs_->Leave();
184       return false;
185     }
186   }
187   frame_queue_cs_->Leave();
188   return true;
189 }