Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(76)

Side by Side Diff: media/omx/omx_codec.cc

Issue 1786001: remove omx_sink and buffer merge (Closed)
Patch Set: one more missing Created 10 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/omx/omx_codec.h ('k') | media/omx/omx_codec_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <algorithm> 5 #include <algorithm>
6 #include <string> 6 #include <string>
7 7
8 #include "base/callback.h" 8 #include "base/callback.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/message_loop.h" 10 #include "base/message_loop.h"
11 #include "base/stl_util-inl.h" 11 #include "base/stl_util-inl.h"
12 #include "base/string_util.h" 12 #include "base/string_util.h"
13 #include "media/omx/omx_codec.h" 13 #include "media/omx/omx_codec.h"
14 #include "media/base/buffers.h" 14 #include "media/base/buffers.h"
15 #include "media/omx/omx_output_sink.h"
16 15
17 namespace media { 16 namespace media {
18 17
19 #if !defined(COMPILER_MSVC) 18 #if !defined(COMPILER_MSVC)
20 int const OmxCodec::kEosBuffer; 19 int const OmxCodec::kEosBuffer;
21 #endif 20 #endif
22 21
23 template <typename T> 22 template <typename T>
24 static void ResetPortHeader(const OmxCodec& dec, T* param) { 23 static void ResetPortHeader(const OmxCodec& dec, T* param) {
25 memset(param, 0, sizeof(T)); 24 memset(param, 0, sizeof(T));
(...skipping 14 matching lines...) Expand all
40 next_state_(kEmpty), 39 next_state_(kEmpty),
41 component_handle_(NULL), 40 component_handle_(NULL),
42 message_loop_(message_loop) { 41 message_loop_(message_loop) {
43 } 42 }
44 43
45 OmxCodec::~OmxCodec() { 44 OmxCodec::~OmxCodec() {
46 DCHECK(state_ == kError || state_ == kEmpty); 45 DCHECK(state_ == kError || state_ == kEmpty);
47 DCHECK_EQ(0u, input_buffers_.size()); 46 DCHECK_EQ(0u, input_buffers_.size());
48 DCHECK_EQ(0u, output_buffers_.size()); 47 DCHECK_EQ(0u, output_buffers_.size());
49 DCHECK(available_input_buffers_.empty()); 48 DCHECK(available_input_buffers_.empty());
50 DCHECK(output_buffers_in_use_.empty());
51 DCHECK(pending_input_queue_.empty()); 49 DCHECK(pending_input_queue_.empty());
52 DCHECK(output_queue_.empty()); 50 DCHECK(output_queue_.empty());
53 DCHECK(processing_input_queue_.empty()); 51 DCHECK(processing_input_queue_.empty());
54 } 52 }
55 53
56 void OmxCodec::Setup(OmxConfigurator* configurator, 54 void OmxCodec::Setup(OmxConfigurator* configurator) {
57 OmxOutputSink* output_sink) {
58 DCHECK_EQ(kEmpty, state_); 55 DCHECK_EQ(kEmpty, state_);
59
60 CHECK(configurator); 56 CHECK(configurator);
61 CHECK(output_sink);
62
63 configurator_ = configurator; 57 configurator_ = configurator;
64 output_sink_ = output_sink;
65 } 58 }
66 59
67 void OmxCodec::SetErrorCallback(Callback* callback) { 60 void OmxCodec::SetErrorCallback(Callback* callback) {
68 DCHECK_EQ(kEmpty, state_); 61 DCHECK_EQ(kEmpty, state_);
69 error_callback_.reset(callback); 62 error_callback_.reset(callback);
70 } 63 }
71 64
72 void OmxCodec::SetFormatCallback(FormatCallback* callback) { 65 void OmxCodec::SetFormatCallback(FormatCallback* callback) {
73 DCHECK_EQ(kEmpty, state_); 66 DCHECK_EQ(kEmpty, state_);
74 format_callback_.reset(callback); 67 format_callback_.reset(callback);
75 } 68 }
76 69
77 void OmxCodec::Start() { 70 void OmxCodec::Start() {
78 CHECK(configurator_); 71 CHECK(configurator_);
79 CHECK(output_sink_);
80 72
81 message_loop_->PostTask( 73 message_loop_->PostTask(
82 FROM_HERE, 74 FROM_HERE,
83 NewRunnableMethod(this, &OmxCodec::StartTask)); 75 NewRunnableMethod(this, &OmxCodec::StartTask));
84 } 76 }
85 77
86 void OmxCodec::Stop(Callback* callback) { 78 void OmxCodec::Stop(Callback* callback) {
87 message_loop_->PostTask( 79 message_loop_->PostTask(
88 FROM_HERE, 80 FROM_HERE,
89 NewRunnableMethod(this, &OmxCodec::StopTask, callback)); 81 NewRunnableMethod(this, &OmxCodec::StopTask, callback));
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 StateTransitionTask(kLoaded); 151 StateTransitionTask(kLoaded);
160 else if (GetState() == kLoaded) 152 else if (GetState() == kLoaded)
161 StateTransitionTask(kEmpty); 153 StateTransitionTask(kEmpty);
162 } 154 }
163 155
164 void OmxCodec::ReadTask(ReadCallback* callback) { 156 void OmxCodec::ReadTask(ReadCallback* callback) {
165 DCHECK_EQ(message_loop_, MessageLoop::current()); 157 DCHECK_EQ(message_loop_, MessageLoop::current());
166 158
167 // Don't accept read request on error state. 159 // Don't accept read request on error state.
168 if (!CanAcceptOutput()) { 160 if (!CanAcceptOutput()) {
169 callback->Run( 161 callback->Run(static_cast<OMX_BUFFERHEADERTYPE*>(NULL));
170 kEosBuffer,
171 static_cast<OmxOutputSink::BufferUsedCallback*>(NULL));
172 delete callback; 162 delete callback;
173 return; 163 return;
174 } 164 }
175 165
176 // If output has been reached then enqueue an end-of-stream buffer. 166 // If output has been reached then enqueue an end-of-stream buffer.
177 if (output_eos_) 167 if (output_eos_)
178 output_buffers_ready_.push(kEosBuffer); 168 output_buffers_ready_.push(kEosBuffer);
179 169
180 // Queue this request. 170 // Queue this request.
181 output_queue_.push(callback); 171 output_queue_.push(callback);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
225 } 215 }
226 216
227 // This method assumes OMX_AllocateBuffer() will allocate buffer 217 // This method assumes OMX_AllocateBuffer() will allocate buffer
228 // header internally. In additional to that memory that holds the 218 // header internally. In additional to that memory that holds the
229 // header, the same method call will allocate memory for holding 219 // header, the same method call will allocate memory for holding
230 // output data. If we use EGL images for holding output data, 220 // output data. If we use EGL images for holding output data,
231 // the memory allocation will be done externally. 221 // the memory allocation will be done externally.
232 bool OmxCodec::AllocateOutputBuffers() { 222 bool OmxCodec::AllocateOutputBuffers() {
233 DCHECK_EQ(message_loop_, MessageLoop::current()); 223 DCHECK_EQ(message_loop_, MessageLoop::current());
234 224
235 if (output_sink_->ProvidesEGLImages()) { 225 for (int i = 0; i < output_buffer_count_; ++i) {
236 // TODO(hclam): Do the following things here: 226 OMX_BUFFERHEADERTYPE* buffer;
237 // 1. Call output_sink_->AllocateEGLImages() to allocate some 227 OMX_ERRORTYPE error =
238 // EGL images from the sink component. 228 OMX_AllocateBuffer(component_handle_, &buffer, output_port_,
239 // 2. Call OMX_UseEGLImage() to assign the images to the output 229 NULL, output_buffer_size_);
240 // port. 230 if (error != OMX_ErrorNone)
241 NOTIMPLEMENTED(); 231 return false;
242 } else { 232 output_buffers_.push_back(buffer);
243 for (int i = 0; i < output_buffer_count_; ++i) {
244 OMX_BUFFERHEADERTYPE* buffer;
245 OMX_ERRORTYPE error =
246 OMX_AllocateBuffer(component_handle_, &buffer, output_port_,
247 NULL, output_buffer_size_);
248 if (error != OMX_ErrorNone)
249 return false;
250 output_buffers_.push_back(buffer);
251 }
252 }
253
254 // Tell the sink component to use the buffers for output.
255 for (size_t i = 0; i < output_buffers_.size(); ++i) {
256 output_sink_->UseThisBuffer(static_cast<int>(i),
257 output_buffers_[i]);
258 } 233 }
259 234
260 return true; 235 return true;
261 } 236 }
262 237
263 void OmxCodec::FreeInputBuffers() { 238 void OmxCodec::FreeInputBuffers() {
264 DCHECK_EQ(message_loop_, MessageLoop::current()); 239 DCHECK_EQ(message_loop_, MessageLoop::current());
265 240
266 // Calls to OMX to free buffers. 241 // Calls to OMX to free buffers.
267 for (size_t i = 0; i < input_buffers_.size(); ++i) 242 for (size_t i = 0; i < input_buffers_.size(); ++i)
268 OMX_FreeBuffer(component_handle_, input_port_, input_buffers_[i]); 243 OMX_FreeBuffer(component_handle_, input_port_, input_buffers_[i]);
269 input_buffers_.clear(); 244 input_buffers_.clear();
270 245
271 // Empty available buffer queue. 246 // Empty available buffer queue.
272 while (!available_input_buffers_.empty()) { 247 while (!available_input_buffers_.empty()) {
273 available_input_buffers_.pop(); 248 available_input_buffers_.pop();
274 } 249 }
275 } 250 }
276 251
277 void OmxCodec::FreeOutputBuffers() { 252 void OmxCodec::FreeOutputBuffers() {
278 DCHECK_EQ(message_loop_, MessageLoop::current()); 253 DCHECK_EQ(message_loop_, MessageLoop::current());
279 254
280 // First we need to make sure output sink is not using the buffer so
281 // tell it to stop using our buffer headers.
282 // TODO(hclam): We should make this an asynchronous call so that
283 // we'll wait until all buffers are not used.
284 for (size_t i = 0; i < output_buffers_.size(); ++i)
285 output_sink_->StopUsingThisBuffer(static_cast<int>(i));
286
287 // Calls to OMX to free buffers. 255 // Calls to OMX to free buffers.
288 for (size_t i = 0; i < output_buffers_.size(); ++i) 256 for (size_t i = 0; i < output_buffers_.size(); ++i)
289 OMX_FreeBuffer(component_handle_, output_port_, output_buffers_[i]); 257 OMX_FreeBuffer(component_handle_, output_port_, output_buffers_[i]);
290 output_buffers_.clear(); 258 output_buffers_.clear();
291
292 // If we have asked the sink component to provide us EGL images for
293 // output we need to tell it we are done with those images.
294 // TODO(hclam): Implement this correctly.
295 if (output_sink_->ProvidesEGLImages()) {
296 std::vector<EGLImageKHR> images;
297 output_sink_->ReleaseEGLImages(images);
298 }
299 } 259 }
300 260
301 void OmxCodec::FreeInputQueue() { 261 void OmxCodec::FreeInputQueue() {
302 DCHECK_EQ(message_loop_, MessageLoop::current()); 262 DCHECK_EQ(message_loop_, MessageLoop::current());
303 263
304 while (!pending_input_queue_.empty()) { 264 while (!pending_input_queue_.empty()) {
305 scoped_refptr<Buffer> buffer = pending_input_queue_.front().first; 265 scoped_refptr<Buffer> buffer = pending_input_queue_.front().first;
306 FeedCallback* callback = pending_input_queue_.front().second; 266 FeedCallback* callback = pending_input_queue_.front().second;
307 callback->Run(buffer); 267 callback->Run(buffer);
308 delete callback; 268 delete callback;
(...skipping 803 matching lines...) Expand 10 before | Expand all | Expand 10 after
1112 1072
1113 if (!output_queue_.empty() && !output_buffers_ready_.empty()) { 1073 if (!output_queue_.empty() && !output_buffers_ready_.empty()) {
1114 int buffer_id = output_buffers_ready_.front(); 1074 int buffer_id = output_buffers_ready_.front();
1115 output_buffers_ready_.pop(); 1075 output_buffers_ready_.pop();
1116 ReadCallback* callback = output_queue_.front(); 1076 ReadCallback* callback = output_queue_.front();
1117 output_queue_.pop(); 1077 output_queue_.pop();
1118 1078
1119 // If the buffer is real then save it to the in-use list. 1079 // If the buffer is real then save it to the in-use list.
1120 // Otherwise if it is an end-of-stream buffer then just drop it. 1080 // Otherwise if it is an end-of-stream buffer then just drop it.
1121 if (buffer_id != kEosBuffer) { 1081 if (buffer_id != kEosBuffer) {
1122 output_buffers_in_use_.push_back(buffer_id); 1082 callback->Run(output_buffers_[buffer_id]);
1123 callback->Run(buffer_id, 1083 BufferUsedCallback(buffer_id); //hack, we will change this really soon.
1124 NewCallback(this, &OmxCodec::BufferUsedCallback));
1125 } else { 1084 } else {
1126 callback->Run(kEosBuffer, 1085 callback->Run(static_cast<OMX_BUFFERHEADERTYPE*>(NULL));
1127 static_cast<OmxOutputSink::BufferUsedCallback*>(NULL));
1128 } 1086 }
1129 delete callback; 1087 delete callback;
1130 } 1088 }
1131 } 1089 }
1132 1090
1133 void OmxCodec::BufferUsedCallback(int buffer_id) { 1091 void OmxCodec::BufferUsedCallback(int buffer_id) {
1134 // If this method is called on the message loop where OmxCodec belongs, we 1092 // If this method is called on the message loop where OmxCodec belongs, we
1135 // execute the task directly to save posting another task. 1093 // execute the task directly to save posting another task.
1136 if (message_loop_ == MessageLoop::current()) { 1094 if (message_loop_ == MessageLoop::current()) {
1137 BufferUsedTask(buffer_id); 1095 BufferUsedTask(buffer_id);
(...skipping 13 matching lines...) Expand all
1151 // receive end-of-stream buffers from OpenMAX. 1109 // receive end-of-stream buffers from OpenMAX.
1152 // It is possible to not submit FillThisBuffer() after the first 1110 // It is possible to not submit FillThisBuffer() after the first
1153 // end-of-stream buffer is received from OpenMAX, but that will complicate 1111 // end-of-stream buffer is received from OpenMAX, but that will complicate
1154 // the logic and so we rely on OpenMAX to do the right thing. 1112 // the logic and so we rely on OpenMAX to do the right thing.
1155 void OmxCodec::BufferUsedTask(int buffer_id) { 1113 void OmxCodec::BufferUsedTask(int buffer_id) {
1156 DCHECK_EQ(message_loop_, MessageLoop::current()); 1114 DCHECK_EQ(message_loop_, MessageLoop::current());
1157 1115
1158 // Make sure an end-of-stream buffer id is not received here. 1116 // Make sure an end-of-stream buffer id is not received here.
1159 CHECK(buffer_id != kEosBuffer); 1117 CHECK(buffer_id != kEosBuffer);
1160 1118
1161 // The use of |output_buffers_in_use_| is just a precaution. So we can
1162 // actually move it to a debugging section.
1163 OutputBuffersInUseSet::iterator iter =
1164 std::find(output_buffers_in_use_.begin(),
1165 output_buffers_in_use_.end(),
1166 buffer_id);
1167
1168 if (iter == output_buffers_in_use_.end()) {
1169 LOG(ERROR) << "Received an unknown buffer id: " << buffer_id;
1170 StateTransitionTask(kError);
1171 }
1172 output_buffers_in_use_.erase(iter);
1173
1174 // We'll try to issue more FillThisBuffer() to the decoder. 1119 // We'll try to issue more FillThisBuffer() to the decoder.
1175 // If we can't do it now then just return. 1120 // If we can't do it now then just return.
1176 if (!CanFillBuffer()) 1121 if (!CanFillBuffer())
1177 return; 1122 return;
1178 1123
1179 CHECK(buffer_id >= 0 && 1124 CHECK(buffer_id >= 0 &&
1180 buffer_id < static_cast<int>(output_buffers_.size())); 1125 buffer_id < static_cast<int>(output_buffers_.size()));
1181 OMX_BUFFERHEADERTYPE* omx_buffer = output_buffers_[buffer_id]; 1126 OMX_BUFFERHEADERTYPE* omx_buffer = output_buffers_[buffer_id];
1182 1127
1183 omx_buffer->nOutputPortIndex = output_port_; 1128 omx_buffer->nOutputPortIndex = output_port_;
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
1305 OMX_ERRORTYPE OmxCodec::FillBufferCallback( 1250 OMX_ERRORTYPE OmxCodec::FillBufferCallback(
1306 OMX_HANDLETYPE component, 1251 OMX_HANDLETYPE component,
1307 OMX_PTR priv_data, 1252 OMX_PTR priv_data,
1308 OMX_BUFFERHEADERTYPE* buffer) { 1253 OMX_BUFFERHEADERTYPE* buffer) {
1309 OmxCodec* decoder = static_cast<OmxCodec*>(priv_data); 1254 OmxCodec* decoder = static_cast<OmxCodec*>(priv_data);
1310 decoder->FillBufferCallbackInternal(component, buffer); 1255 decoder->FillBufferCallbackInternal(component, buffer);
1311 return OMX_ErrorNone; 1256 return OMX_ErrorNone;
1312 } 1257 }
1313 1258
1314 } // namespace media 1259 } // namespace media
OLDNEW
« no previous file with comments | « media/omx/omx_codec.h ('k') | media/omx/omx_codec_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698