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

Side by Side Diff: media/tools/omx_test/omx_test.cc

Issue 2255005: move from omx_codec to new omx_video_decode_engine... (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: remove omx_code, update omx_test to use omx engine Created 10 years, 7 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 | Annotate | Revision Log
« no previous file with comments | « media/omx/omx_codec_unittest.cc ('k') | no next file » | 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 // A test program that drives an OpenMAX video decoder module. This program 5 // A test program that drives an OpenMAX video decoder module. This program
6 // will take video in elementary stream and read into the decoder. 6 // will take video in elementary stream and read into the decoder.
7 // 7 //
8 // Run the following command to see usage: 8 // Run the following command to see usage:
9 // ./omx_test 9 // ./omx_test
10 10
11 #include "base/at_exit.h" 11 #include "base/at_exit.h"
12 #include "base/callback.h" 12 #include "base/callback.h"
13 #include "base/command_line.h" 13 #include "base/command_line.h"
14 #include "base/message_loop.h" 14 #include "base/message_loop.h"
15 #include "base/scoped_ptr.h" 15 #include "base/scoped_ptr.h"
16 #include "base/time.h" 16 #include "base/time.h"
17 #include "media/base/data_buffer.h"
17 #include "media/base/media.h" 18 #include "media/base/media.h"
19 #include "media/base/video_frame.h"
18 #include "media/ffmpeg/ffmpeg_common.h" 20 #include "media/ffmpeg/ffmpeg_common.h"
19 #include "media/ffmpeg/file_protocol.h" 21 #include "media/ffmpeg/file_protocol.h"
20 #include "media/filters/bitstream_converter.h" 22 #include "media/filters/bitstream_converter.h"
21 #include "media/omx/omx_codec.h" 23 #include "media/filters/omx_video_decode_engine.h"
22 #include "media/base/data_buffer.h"
23 #include "media/tools/omx_test/color_space_util.h" 24 #include "media/tools/omx_test/color_space_util.h"
24 #include "media/tools/omx_test/file_reader_util.h" 25 #include "media/tools/omx_test/file_reader_util.h"
25 #include "media/tools/omx_test/file_sink.h" 26 #include "media/tools/omx_test/file_sink.h"
26 27
27 using media::BlockFileReader; 28 using media::BlockFileReader;
29 using media::Buffer;
30 using media::DataBuffer;
28 using media::FFmpegFileReader; 31 using media::FFmpegFileReader;
29 using media::FileReader; 32 using media::FileReader;
30 using media::FileSink; 33 using media::FileSink;
31 using media::H264FileReader; 34 using media::H264FileReader;
32 using media::OmxCodec;
33 using media::OmxConfigurator; 35 using media::OmxConfigurator;
34 using media::OmxDecoderConfigurator; 36 using media::OmxDecoderConfigurator;
35 using media::OmxEncoderConfigurator; 37 using media::OmxEncoderConfigurator;
38 using media::OmxVideoDecodeEngine;
39 using media::VideoFrame;
36 using media::YuvFileReader; 40 using media::YuvFileReader;
37 using media::Buffer;
38 using media::DataBuffer;
39 41
40 // This is the driver object to feed the decoder with data from a file. 42 // This is the driver object to feed the decoder with data from a file.
41 // It also provides callbacks for the decoder to receive events from the 43 // It also provides callbacks for the decoder to receive events from the
42 // decoder. 44 // decoder.
43 class TestApp { 45 // TODO(wjia): AVStream should be replaced with a new structure which is
46 // neutral to any video decoder. Also change media.gyp correspondingly.
47 class TestApp : public base::RefCountedThreadSafe<TestApp> {
44 public: 48 public:
45 TestApp(OmxConfigurator* configurator, FileSink* file_sink, 49 TestApp(AVStream* av_stream,
50 FileSink* file_sink,
46 FileReader* file_reader) 51 FileReader* file_reader)
47 : configurator_(configurator), 52 : av_stream_(av_stream),
48 file_reader_(file_reader), 53 file_reader_(file_reader),
49 file_sink_(file_sink), 54 file_sink_(file_sink),
50 stopped_(false), 55 stopped_(false),
51 error_(false) { 56 error_(false) {
52 } 57 }
53 58
54 bool Initialize() { 59 bool Initialize() {
55 if (!file_reader_->Initialize()) { 60 if (!file_reader_->Initialize()) {
56 file_reader_.reset(); 61 file_reader_.reset();
57 LOG(ERROR) << "can't initialize file reader"; 62 LOG(ERROR) << "can't initialize file reader";
58 return false;; 63 return false;;
59 } 64 }
60 65
61 if (!file_sink_->Initialize()) { 66 if (!file_sink_->Initialize()) {
62 LOG(ERROR) << "can't initialize output writer"; 67 LOG(ERROR) << "can't initialize output writer";
63 return false; 68 return false;
64 } 69 }
65 return true; 70 return true;
66 } 71 }
67 72
73 void InitializeDoneCallback() {
74 }
75
68 void StopCallback() { 76 void StopCallback() {
69 // If this callback is received, mark the |stopped_| flag so that we don't 77 // If this callback is received, mark the |stopped_| flag so that we don't
70 // feed more buffers into the decoder. 78 // feed more buffers into the decoder.
71 // We need to exit the current message loop because we have no more work 79 // We need to exit the current message loop because we have no more work
72 // to do on the message loop. This is done by calling 80 // to do on the message loop. This is done by calling
73 // message_loop_.Quit(). 81 // message_loop_.Quit().
74 stopped_ = true; 82 stopped_ = true;
75 message_loop_.Quit(); 83 message_loop_.Quit();
76 } 84 }
77 85
(...skipping 13 matching lines...) Expand all
91 99
92 DCHECK_EQ(input_format.video_header.width, 100 DCHECK_EQ(input_format.video_header.width,
93 output_format.video_header.width); 101 output_format.video_header.width);
94 DCHECK_EQ(input_format.video_header.height, 102 DCHECK_EQ(input_format.video_header.height,
95 output_format.video_header.height); 103 output_format.video_header.height);
96 104
97 file_sink_->UpdateSize(input_format.video_header.width, 105 file_sink_->UpdateSize(input_format.video_header.width,
98 input_format.video_header.height); 106 input_format.video_header.height);
99 } 107 }
100 108
101 void FeedCompleteCallback(scoped_refptr<Buffer> buffer) { 109 void FeedDoneCallback(scoped_refptr<Buffer> buffer) {
102 // We receive this callback when the decoder has consumed an input buffer. 110 // We receive this callback when the decoder has consumed an input buffer.
103 // In this case, delete the previous buffer and enqueue a new one. 111 // In this case, delete the previous buffer and enqueue a new one.
104 // There are some conditions we don't want to enqueue, for example when 112 // There are some conditions we don't want to enqueue, for example when
105 // the last buffer is an end-of-stream buffer, when we have stopped, and 113 // the last buffer is an end-of-stream buffer, when we have stopped, and
106 // when we have received an error. 114 // when we have received an error.
107 bool eos = buffer->IsEndOfStream(); 115 bool eos = buffer->IsEndOfStream();
108 if (!eos && !stopped_ && !error_) 116 if (!eos && !stopped_ && !error_)
109 FeedInputBuffer(); 117 FeedInputBuffer();
110 } 118 }
111 119
112 void ReadCompleteCallback(OMX_BUFFERHEADERTYPE* buffer) { 120 void DecodeDoneCallback(scoped_refptr<VideoFrame> frame) {
113 // This callback is received when the decoder has completed a decoding 121 // This callback is received when the decoder has completed a decoding
114 // task and given us some output data. The buffer is owned by the decoder. 122 // task and given us some output data. The frame is owned by the decoder.
115 if (stopped_ || error_) 123 if (stopped_ || error_)
116 return; 124 return;
117 125
118 if (!frame_count_) 126 if (!frame_count_)
119 first_sample_delivered_time_ = base::TimeTicks::HighResNow(); 127 first_sample_delivered_time_ = base::TimeTicks::HighResNow();
120 128
121 // If we are readding to the end, then stop. 129 // If we are readding to the end, then stop.
122 if (buffer == NULL) { 130 if (frame.get() == NULL) {
123 codec_->Stop(NewCallback(this, &TestApp::StopCallback)); 131 engine_->Stop(NewCallback(this, &TestApp::StopCallback));
124 return; 132 return;
125 } 133 }
126 134
127 if (file_sink_.get()) 135 if (file_sink_.get()) {
128 file_sink_->BufferReady(buffer->nFilledLen, buffer->pBuffer); 136 for (size_t i = 0; i < frame->planes(); i++) {
137 int plane_size = frame->width() * frame->height();
138 if (i > 0) plane_size >>= 2;
139 file_sink_->BufferReady(plane_size, frame->data(i));
140 }
141 }
129 142
130 // could OMX IL return patial sample for decoder? 143 // could OMX IL return patial sample for decoder?
131 frame_count_++; 144 frame_count_++;
132 } 145 }
133 146
134 void FeedInputBuffer() { 147 void FeedInputBuffer() {
135 uint8* data; 148 uint8* data;
136 int read; 149 int read;
137 file_reader_->Read(&data, &read); 150 file_reader_->Read(&data, &read);
138 codec_->Feed(new DataBuffer(data, read)); 151 engine_->EmptyThisBuffer(new DataBuffer(data, read));
139 } 152 }
140 153
141 void Run() { 154 void Run() {
142 StartProfiler(); 155 StartProfiler();
143 156
144 // Setup the |codec_| with the message loop of the current thread. Also 157 // Setup the |engine_| with the message loop of the current thread. Also
145 // setup component name, codec format and callbacks. 158 // setup codec format and callbacks.
146 codec_ = new OmxCodec(&message_loop_); 159 engine_ = new OmxVideoDecodeEngine();
147 codec_->Setup(configurator_.get(), 160 engine_->Initialize(&message_loop_,
148 NewCallback(this, &TestApp::FeedCompleteCallback), 161 av_stream_.get(),
149 NewCallback(this, &TestApp::ReadCompleteCallback)); 162 NewCallback(this, &TestApp::FeedDoneCallback),
150 codec_->SetErrorCallback(NewCallback(this, &TestApp::ErrorCallback)); 163 NewCallback(this, &TestApp::DecodeDoneCallback),
151 codec_->SetFormatCallback(NewCallback(this, &TestApp::FormatCallback)); 164 NewRunnableMethod(this,
165 &TestApp::InitializeDoneCallback));
152 166
153 // Start the |codec_|.
154 codec_->Start();
155 for (int i = 0; i < 20; ++i) 167 for (int i = 0; i < 20; ++i)
156 FeedInputBuffer(); 168 FeedInputBuffer();
157 169
158 // Execute the message loop so that we can run tasks on it. This call 170 // Execute the message loop so that we can run tasks on it. This call
159 // will return when we call message_loop_.Quit(). 171 // will return when we call message_loop_.Quit().
160 message_loop_.Run(); 172 message_loop_.Run();
161 173
162 StopProfiler(); 174 StopProfiler();
163 } 175 }
164 176
(...skipping 12 matching lines...) Expand all
177 } 189 }
178 base::TimeDelta delay = first_sample_delivered_time_ - start_time_; 190 base::TimeDelta delay = first_sample_delivered_time_ - start_time_;
179 printf("\n<<< frame delivered : %d >>>", frame_count_); 191 printf("\n<<< frame delivered : %d >>>", frame_count_);
180 printf("\n<<< time used(ms) : %d >>>", static_cast<int>(duration_ms)); 192 printf("\n<<< time used(ms) : %d >>>", static_cast<int>(duration_ms));
181 printf("\n<<< fps : %d >>>", static_cast<int>(fps)); 193 printf("\n<<< fps : %d >>>", static_cast<int>(fps));
182 printf("\n<<< initial delay used(us): %d >>>", 194 printf("\n<<< initial delay used(us): %d >>>",
183 static_cast<int>(delay.InMicroseconds())); 195 static_cast<int>(delay.InMicroseconds()));
184 printf("\n"); 196 printf("\n");
185 } 197 }
186 198
187 scoped_refptr<OmxCodec> codec_; 199 scoped_refptr<OmxVideoDecodeEngine> engine_;
188 MessageLoop message_loop_; 200 MessageLoop message_loop_;
189 scoped_ptr<OmxConfigurator> configurator_; 201 scoped_ptr<AVStream> av_stream_;
190 scoped_ptr<FileReader> file_reader_; 202 scoped_ptr<FileReader> file_reader_;
191 scoped_ptr<FileSink> file_sink_; 203 scoped_ptr<FileSink> file_sink_;
192 204
193 // Internal states for execution. 205 // Internal states for execution.
194 bool stopped_; 206 bool stopped_;
195 bool error_; 207 bool error_;
196 208
197 // Counters for performance. 209 // Counters for performance.
198 base::TimeTicks start_time_; 210 base::TimeTicks start_time_;
199 base::TimeTicks first_sample_delivered_time_; 211 base::TimeTicks first_sample_delivered_time_;
200 int frame_count_; 212 int frame_count_;
201 }; 213 };
202 214
203 static std::string GetStringSwitch(const char* name) { 215 static std::string GetStringSwitch(const char* name) {
204 return CommandLine::ForCurrentProcess()->GetSwitchValueASCII(name); 216 return CommandLine::ForCurrentProcess()->GetSwitchValueASCII(name);
205 } 217 }
206 218
207 static bool HasSwitch(const char* name) { 219 static bool HasSwitch(const char* name) {
208 return CommandLine::ForCurrentProcess()->HasSwitch(name); 220 return CommandLine::ForCurrentProcess()->HasSwitch(name);
209 } 221 }
210 222
211 static int GetIntSwitch(const char* name) { 223 static int GetIntSwitch(const char* name) {
212 if (HasSwitch(name)) 224 if (HasSwitch(name))
213 return StringToInt(GetStringSwitch(name)); 225 return StringToInt(GetStringSwitch(name));
214 return 0; 226 return 0;
215 } 227 }
216 228
217 static bool PrepareDecodeFormats(OmxConfigurator::MediaFormat* input, 229 static bool PrepareDecodeFormats(AVStream *av_stream) {
218 OmxConfigurator::MediaFormat* output) {
219 std::string codec = GetStringSwitch("codec"); 230 std::string codec = GetStringSwitch("codec");
220 input->codec = OmxConfigurator::kCodecNone; 231 av_stream->codec->codec_id = CODEC_ID_NONE;
221 if (codec == "h264") { 232 if (codec == "h264") {
222 input->codec = OmxConfigurator::kCodecH264; 233 av_stream->codec->codec_id = CODEC_ID_H264;
223 } else if (codec == "mpeg4") { 234 } else if (codec == "mpeg4") {
224 input->codec = OmxConfigurator::kCodecMpeg4; 235 av_stream->codec->codec_id = CODEC_ID_MPEG4;
225 } else if (codec == "h263") { 236 } else if (codec == "h263") {
226 input->codec = OmxConfigurator::kCodecH263; 237 av_stream->codec->codec_id = CODEC_ID_H263;
227 } else if (codec == "vc1") { 238 } else if (codec == "vc1") {
228 input->codec = OmxConfigurator::kCodecVc1; 239 av_stream->codec->codec_id = CODEC_ID_VC1;
229 } else { 240 } else {
230 LOG(ERROR) << "Unknown codec."; 241 LOG(ERROR) << "Unknown codec.";
231 return false; 242 return false;
232 } 243 }
233 output->codec = OmxConfigurator::kCodecRaw;
234 return true; 244 return true;
235 } 245 }
236 246
237 static bool PrepareEncodeFormats(OmxConfigurator::MediaFormat* input, 247 static bool PrepareEncodeFormats(AVStream *av_stream) {
238 OmxConfigurator::MediaFormat* output) { 248 av_stream->codec->width = GetIntSwitch("width");
239 input->codec = OmxConfigurator::kCodecRaw; 249 av_stream->codec->height = GetIntSwitch("height");
240 input->video_header.width = GetIntSwitch("width"); 250 av_stream->avg_frame_rate.num = GetIntSwitch("framerate");
241 input->video_header.height = GetIntSwitch("height"); 251 av_stream->avg_frame_rate.den = 1;
242 input->video_header.frame_rate = GetIntSwitch("framerate"); 252
243 // TODO(jiesun): make other format available. 253 std::string codec = GetStringSwitch("codec");
244 output->codec = OmxConfigurator::kCodecMpeg4; 254 av_stream->codec->codec_id = CODEC_ID_NONE;
245 output->video_header.width = GetIntSwitch("width"); 255 if (codec == "h264") {
246 output->video_header.height = GetIntSwitch("height"); 256 av_stream->codec->codec_id = CODEC_ID_H264;
247 output->video_header.frame_rate = GetIntSwitch("framerate"); 257 } else if (codec == "mpeg4") {
258 av_stream->codec->codec_id = CODEC_ID_MPEG4;
259 } else if (codec == "h263") {
260 av_stream->codec->codec_id = CODEC_ID_H263;
261 } else if (codec == "vc1") {
262 av_stream->codec->codec_id = CODEC_ID_VC1;
263 } else {
264 LOG(ERROR) << "Unknown codec.";
265 return false;
266 }
248 // TODO(jiesun): assume constant bitrate now. 267 // TODO(jiesun): assume constant bitrate now.
249 output->video_header.bit_rate = GetIntSwitch("bitrate"); 268 av_stream->codec->bit_rate = GetIntSwitch("bitrate");
250 // TODO(jiesun): one I frame per second now. make it configurable. 269
251 output->video_header.i_dist = output->video_header.frame_rate; 270 // TODO(wjia): add more configurations needed by encoder
252 // TODO(jiesun): disable B frame now. does they support it?
253 output->video_header.p_dist = 0;
254 return true; 271 return true;
255 } 272 }
256 273
257 static bool InitFFmpeg() { 274 static bool InitFFmpeg() {
258 if (!media::InitializeMediaLibrary(FilePath())) 275 if (!media::InitializeMediaLibrary(FilePath()))
259 return false; 276 return false;
260 avcodec_init(); 277 avcodec_init();
261 av_register_all(); 278 av_register_all();
262 av_register_protocol(&kFFmpegFileProtocol); 279 av_register_protocol(&kFFmpegFileProtocol);
263 return true; 280 return true;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 return false; 338 return false;
322 } 339 }
323 340
324 // If FFmpeg should be used for demuxing load the library here and do 341 // If FFmpeg should be used for demuxing load the library here and do
325 // the initialization. 342 // the initialization.
326 if (use_ffmpeg && !InitFFmpeg()) { 343 if (use_ffmpeg && !InitFFmpeg()) {
327 LOG(ERROR) << "Unable to initialize the media library."; 344 LOG(ERROR) << "Unable to initialize the media library.";
328 return -1; 345 return -1;
329 } 346 }
330 347
331 // Set the media formats for I/O. 348 // Create AVStream
332 OmxConfigurator::MediaFormat input, output; 349 AVStream *av_stream = new AVStream;
333 memset(&input, 0, sizeof(input)); 350 AVCodecContext *av_codec_context = new AVCodecContext;
334 memset(&output, 0, sizeof(output)); 351 memset(av_stream, 0, sizeof(AVStream));
352 memset(av_codec_context, 0, sizeof(AVCodecContext));
353 scoped_ptr<AVCodecContext> av_codec_context_deleter(av_codec_context);
354 av_stream->codec = av_codec_context;
355 av_codec_context->width = 320;
356 av_codec_context->height = 240;
335 if (encoder) 357 if (encoder)
336 PrepareEncodeFormats(&input, &output); 358 PrepareEncodeFormats(av_stream);
337 else 359 else
338 PrepareDecodeFormats(&input, &output); 360 PrepareDecodeFormats(av_stream);
339 361
340 // Creates the FileReader to read input file. 362 // Creates the FileReader to read input file.
341 FileReader* file_reader; 363 FileReader* file_reader;
342 if (encoder) { 364 if (encoder) {
343 file_reader = new YuvFileReader( 365 file_reader = new YuvFileReader(
344 input_filename.c_str(), input.video_header.width, 366 input_filename.c_str(), av_stream->codec->width,
345 input.video_header.height, loop_count, enable_csc); 367 av_stream->codec->height, loop_count, enable_csc);
346 } else if (use_ffmpeg) { 368 } else if (use_ffmpeg) {
347 // Use ffmepg for reading. 369 // Use ffmepg for reading.
348 file_reader = new FFmpegFileReader(input_filename.c_str()); 370 file_reader = new FFmpegFileReader(input_filename.c_str());
349 } else if (EndsWith(input_filename, ".264", false)) { 371 } else if (EndsWith(input_filename, ".264", false)) {
350 file_reader = new H264FileReader(input_filename.c_str()); 372 file_reader = new H264FileReader(input_filename.c_str());
351 } else { 373 } else {
352 // Creates a reader that reads in blocks of 32KB. 374 // Creates a reader that reads in blocks of 32KB.
353 const int kReadSize = 32768; 375 const int kReadSize = 32768;
354 file_reader = new BlockFileReader(input_filename.c_str(), kReadSize); 376 file_reader = new BlockFileReader(input_filename.c_str(), kReadSize);
355 } 377 }
356 378
357 // Create the configurator.
358 OmxConfigurator* configurator;
359 if (encoder)
360 configurator = new OmxEncoderConfigurator(input, output);
361 else
362 configurator = new OmxDecoderConfigurator(input, output);
363
364 // Create a file sink. 379 // Create a file sink.
365 FileSink* file_sink = new FileSink(output_filename, copy, enable_csc); 380 FileSink* file_sink = new FileSink(output_filename, copy, enable_csc);
366 381
367 // Create a test app object and initialize it. 382 // Create a test app object and initialize it.
368 TestApp test(configurator, file_sink, file_reader); 383 scoped_refptr<TestApp> test = new TestApp(av_stream, file_sink, file_reader);
369 if (!test.Initialize()) { 384 if (!test->Initialize()) {
370 LOG(ERROR) << "can't initialize this application"; 385 LOG(ERROR) << "can't initialize this application";
371 return -1; 386 return -1;
372 } 387 }
373 388
374 // This will run the decoder until EOS is reached or an error 389 // This will run the decoder until EOS is reached or an error
375 // is encountered. 390 // is encountered.
376 test.Run(); 391 test->Run();
377 return 0; 392 return 0;
378 } 393 }
OLDNEW
« no previous file with comments | « media/omx/omx_codec_unittest.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698