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

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

Issue 7066071: Removing defunct OpenMAX code. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src
Patch Set: removed tab Created 9 years, 6 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/tools/omx_test/file_sink.cc ('k') | media/tools/player_x11/player_x11.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
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.
7 //
8 // Run the following command to see usage:
9 // ./omx_test
10
11 #include "base/at_exit.h"
12 #include "base/callback.h"
13 #include "base/command_line.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/message_loop.h"
16 #include "base/string_number_conversions.h"
17 #include "base/time.h"
18 #include "base/utf_string_conversions.h"
19 #include "media/base/data_buffer.h"
20 #include "media/base/media.h"
21 #include "media/base/video_frame.h"
22 #include "media/ffmpeg/ffmpeg_common.h"
23 #include "media/ffmpeg/file_protocol.h"
24 #include "media/filters/bitstream_converter.h"
25 #include "media/tools/omx_test/color_space_util.h"
26 #include "media/tools/omx_test/file_reader_util.h"
27 #include "media/tools/omx_test/file_sink.h"
28 #include "media/video/omx_video_decode_engine.h"
29
30 using media::BlockFileReader;
31 using media::Buffer;
32 using media::DataBuffer;
33 using media::FFmpegFileReader;
34 using media::FileReader;
35 using media::FileSink;
36 using media::H264FileReader;
37 using media::OmxConfigurator;
38 using media::OmxDecoderConfigurator;
39 using media::OmxEncoderConfigurator;
40 using media::OmxVideoDecodeEngine;
41 using media::PipelineStatistics;
42 using media::VideoFrame;
43 using media::YuvFileReader;
44
45 // This is the driver object to feed the decoder with data from a file.
46 // It also provides callbacks for the decoder to receive events from the
47 // decoder.
48 // TODO(wjia): AVStream should be replaced with a new structure which is
49 // neutral to any video decoder. Also change media.gyp correspondingly.
50 class TestApp : public base::RefCountedThreadSafe<TestApp>,
51 public media::VideoDecodeEngine::EventHandler {
52 public:
53 TestApp(AVStream* av_stream,
54 FileSink* file_sink,
55 FileReader* file_reader)
56 : av_stream_(av_stream),
57 file_reader_(file_reader),
58 file_sink_(file_sink),
59 stopped_(false),
60 error_(false) {
61 }
62
63 bool Initialize() {
64 if (!file_reader_->Initialize()) {
65 file_reader_.reset();
66 LOG(ERROR) << "can't initialize file reader";
67 return false;;
68 }
69
70 if (!file_sink_->Initialize()) {
71 LOG(ERROR) << "can't initialize output writer";
72 return false;
73 }
74 return true;
75 }
76
77 virtual void OnInitializeComplete(const media::VideoCodecInfo& info) {}
78
79 virtual void OnUninitializeComplete() {
80 // If this callback is received, mark the |stopped_| flag so that we don't
81 // feed more buffers into the decoder.
82 // We need to exit the current message loop because we have no more work
83 // to do on the message loop. This is done by calling
84 // message_loop_.Quit().
85 stopped_ = true;
86 message_loop_.Quit();
87 }
88
89 virtual void OnError() {
90 // In case of error, this method is called. Mark the error flag and
91 // exit the message loop because we have no more work to do.
92 LOG(ERROR) << "Error callback received!";
93 error_ = true;
94 message_loop_.Quit();
95 }
96
97 virtual void OnFlushComplete() {
98 NOTIMPLEMENTED();
99 }
100
101 virtual void OnSeekComplete() {
102 NOTIMPLEMENTED();
103 }
104
105 virtual void OnFormatChange(media::VideoStreamInfo stream_info) {
106 NOTIMPLEMENTED();
107 }
108
109 void FormatCallback(
110 const OmxConfigurator::MediaFormat& input_format,
111 const OmxConfigurator::MediaFormat& output_format) {
112 // This callback will be called when port reconfiguration is done.
113 // Input format and output format will be used in the codec.
114
115 DCHECK_EQ(input_format.video_header.width,
116 output_format.video_header.width);
117 DCHECK_EQ(input_format.video_header.height,
118 output_format.video_header.height);
119
120 file_sink_->UpdateSize(input_format.video_header.width,
121 input_format.video_header.height);
122 }
123
124 virtual void ProduceVideoSample(scoped_refptr<Buffer> buffer) {
125 // We receive this callback when the decoder has consumed an input buffer.
126 // In this case, delete the previous buffer and enqueue a new one.
127 // There are some conditions we don't want to enqueue, for example when
128 // the last buffer is an end-of-stream buffer, when we have stopped, and
129 // when we have received an error.
130 bool eos = buffer.get() && buffer->IsEndOfStream();
131 if (!eos && !stopped_ && !error_)
132 FeedInputBuffer();
133 }
134
135 virtual void ConsumeVideoFrame(scoped_refptr<VideoFrame> frame,
136 const PipelineStatistics& statistics) {
137 // This callback is received when the decoder has completed a decoding
138 // task and given us some output data. The frame is owned by the decoder.
139 if (stopped_ || error_)
140 return;
141
142 if (!frame_count_)
143 first_sample_delivered_time_ = base::TimeTicks::HighResNow();
144
145 // If we are reading to the end, then stop.
146 if (frame->IsEndOfStream()) {
147 engine_->Uninitialize();
148 return;
149 }
150
151 if (file_sink_.get()) {
152 for (size_t i = 0; i < frame->planes(); i++) {
153 int plane_size = frame->width() * frame->height();
154 if (i > 0) plane_size >>= 2;
155 file_sink_->BufferReady(plane_size, frame->data(i));
156 }
157 }
158
159 // could OMX IL return patial sample for decoder?
160 frame_count_++;
161 }
162
163 void FeedInputBuffer() {
164 uint8* data;
165 int read;
166 file_reader_->Read(&data, &read);
167 engine_->ConsumeVideoSample(new DataBuffer(data, read));
168 }
169
170 void Run() {
171 StartProfiler();
172
173 media::VideoDecoderConfig config(
174 media::CodecIDToVideoCodec(av_stream_->codec->codec_id),
175 av_stream_->codec->coded_width,
176 av_stream_->codec->coded_height,
177 av_stream_->r_frame_rate.num,
178 av_stream_->r_frame_rate.den,
179 av_stream_->codec->extradata,
180 av_stream_->codec->extradata_size);
181
182 engine_.reset(new OmxVideoDecodeEngine());
183 engine_->Initialize(&message_loop_, this, NULL, config);
184
185 // Execute the message loop so that we can run tasks on it. This call
186 // will return when we call message_loop_.Quit().
187 message_loop_.Run();
188
189 StopProfiler();
190 }
191
192 void StartProfiler() {
193 start_time_ = base::TimeTicks::HighResNow();
194 frame_count_ = 0;
195 }
196
197 void StopProfiler() {
198 base::TimeDelta duration = base::TimeTicks::HighResNow() - start_time_;
199 int64 duration_ms = duration.InMilliseconds();
200 int64 fps = 0;
201 if (duration_ms) {
202 fps = (static_cast<int64>(frame_count_) *
203 base::Time::kMillisecondsPerSecond) / duration_ms;
204 }
205 base::TimeDelta delay = first_sample_delivered_time_ - start_time_;
206 printf("\n<<< frame delivered : %d >>>", frame_count_);
207 printf("\n<<< time used(ms) : %d >>>", static_cast<int>(duration_ms));
208 printf("\n<<< fps : %d >>>", static_cast<int>(fps));
209 printf("\n<<< initial delay used(us): %d >>>",
210 static_cast<int>(delay.InMicroseconds()));
211 printf("\n");
212 }
213
214 scoped_ptr<OmxVideoDecodeEngine> engine_;
215 MessageLoop message_loop_;
216 scoped_ptr<AVStream> av_stream_;
217 scoped_ptr<FileReader> file_reader_;
218 scoped_ptr<FileSink> file_sink_;
219
220 // Internal states for execution.
221 bool stopped_;
222 bool error_;
223
224 // Counters for performance.
225 base::TimeTicks start_time_;
226 base::TimeTicks first_sample_delivered_time_;
227 int frame_count_;
228 };
229
230 static std::string GetStringSwitch(const char* name) {
231 return CommandLine::ForCurrentProcess()->GetSwitchValueASCII(name);
232 }
233
234 static bool HasSwitch(const char* name) {
235 return CommandLine::ForCurrentProcess()->HasSwitch(name);
236 }
237
238 static int GetIntSwitch(const char* name) {
239 if (HasSwitch(name)) {
240 int val;
241 base::StringToInt(GetStringSwitch(name), &val);
242 return val;
243 }
244 return 0;
245 }
246
247 static bool PrepareDecodeFormats(AVStream *av_stream) {
248 std::string codec = GetStringSwitch("codec");
249 av_stream->codec->codec_id = CODEC_ID_NONE;
250 if (codec == "h264") {
251 av_stream->codec->codec_id = CODEC_ID_H264;
252 } else if (codec == "mpeg4") {
253 av_stream->codec->codec_id = CODEC_ID_MPEG4;
254 } else if (codec == "h263") {
255 av_stream->codec->codec_id = CODEC_ID_H263;
256 } else if (codec == "vc1") {
257 av_stream->codec->codec_id = CODEC_ID_VC1;
258 } else {
259 LOG(ERROR) << "Unknown codec.";
260 return false;
261 }
262 return true;
263 }
264
265 static bool PrepareEncodeFormats(AVStream *av_stream) {
266 av_stream->codec->width = GetIntSwitch("width");
267 av_stream->codec->height = GetIntSwitch("height");
268 av_stream->avg_frame_rate.num = GetIntSwitch("framerate");
269 av_stream->avg_frame_rate.den = 1;
270
271 std::string codec = GetStringSwitch("codec");
272 av_stream->codec->codec_id = CODEC_ID_NONE;
273 if (codec == "h264") {
274 av_stream->codec->codec_id = CODEC_ID_H264;
275 } else if (codec == "mpeg4") {
276 av_stream->codec->codec_id = CODEC_ID_MPEG4;
277 } else if (codec == "h263") {
278 av_stream->codec->codec_id = CODEC_ID_H263;
279 } else if (codec == "vc1") {
280 av_stream->codec->codec_id = CODEC_ID_VC1;
281 } else {
282 LOG(ERROR) << "Unknown codec.";
283 return false;
284 }
285 // TODO(jiesun): assume constant bitrate now.
286 av_stream->codec->bit_rate = GetIntSwitch("bitrate");
287
288 // TODO(wjia): add more configurations needed by encoder
289 return true;
290 }
291
292 static bool InitFFmpeg() {
293 if (!media::InitializeMediaLibrary(FilePath()))
294 return false;
295 avcodec_init();
296 av_register_all();
297 av_register_protocol2(&kFFmpegFileProtocol, sizeof(kFFmpegFileProtocol));
298 return true;
299 }
300
301 static void PrintHelp() {
302 printf("Using for decoding...\n");
303 printf("\n");
304 printf("Usage: omx_test --input-file=FILE --codec=CODEC"
305 " [--output-file=FILE] [--enable-csc]"
306 " [--copy] [--use-ffmpeg]\n");
307 printf(" CODEC: h264/mpeg4/h263/vc1\n");
308 printf("\n");
309 printf("Optional Arguments\n");
310 printf(" --output-file Dump raw OMX output to file.\n");
311 printf(" --enable-csc Dump the CSCed output to file.\n");
312 printf(" --copy Simulate a memcpy from the output.\n");
313 printf(" --use-ffmpeg Use ffmpeg demuxer\n");
314 printf("\n");
315 printf("Using for encoding...\n");
316 printf("\n");
317 printf("Usage: omx_test --encoder --input-file=FILE --codec=CODEC"
318 " --width=PIXEL_WIDTH --height=PIXEL_HEIGHT"
319 " --bitrate=BIT_PER_SECOND --framerate=FRAME_PER_SECOND"
320 " [--output-file=FILE] [--enable-csc]"
321 " [--copy]\n");
322 printf(" CODEC: h264/mpeg4/h263/vc1\n");
323 printf("\n");
324 printf("Optional Arguments\n");
325 printf(" --output-file Dump raw OMX output to file.\n");
326 printf(" --enable-csc Dump the CSCed input from file.\n");
327 printf(" --copy Simulate a memcpy from the output.\n");
328 printf(" --loop=COUNT loop input streams\n");
329 }
330
331 int main(int argc, char** argv) {
332 base::AtExitManager at_exit_manager;
333 CommandLine::Init(argc, argv);
334
335 // Print help if there is not enough arguments.
336 if (argc == 1) {
337 PrintHelp();
338 return -1;
339 }
340
341 const CommandLine& cmd_line = *CommandLine::ForCurrentProcess();
342 // Read a bunch of parameters.
343 FilePath input_path = cmd_line.GetSwitchValuePath("input-file");
344 FilePath output_path = cmd_line.GetSwitchValuePath("output-file");
345 bool encoder = HasSwitch("encoder");
346 bool copy = HasSwitch("copy");
347 bool enable_csc = HasSwitch("enable-csc");
348 bool use_ffmpeg = HasSwitch("use-ffmpeg");
349 int loop_count = GetIntSwitch("loop");
350 if (loop_count == 0)
351 loop_count = 1;
352 DCHECK_GE(loop_count, 1);
353
354 // Initialize OpenMAX.
355 if (!media::InitializeOpenMaxLibrary(FilePath())) {
356 LOG(ERROR) << "Unable to initialize OpenMAX library.";
357 return false;
358 }
359
360 // If FFmpeg should be used for demuxing load the library here and do
361 // the initialization.
362 if (use_ffmpeg && !InitFFmpeg()) {
363 LOG(ERROR) << "Unable to initialize the media library.";
364 return -1;
365 }
366
367 // Create AVStream
368 AVStream *av_stream = new AVStream;
369 AVCodecContext *av_codec_context = new AVCodecContext;
370 memset(av_stream, 0, sizeof(AVStream));
371 memset(av_codec_context, 0, sizeof(AVCodecContext));
372 scoped_ptr<AVCodecContext> av_codec_context_deleter(av_codec_context);
373 av_stream->codec = av_codec_context;
374 av_codec_context->width = 320;
375 av_codec_context->height = 240;
376 if (encoder)
377 PrepareEncodeFormats(av_stream);
378 else
379 PrepareDecodeFormats(av_stream);
380
381 // Creates the FileReader to read input file.
382 FileReader* file_reader;
383 if (encoder) {
384 file_reader = new YuvFileReader(
385 input_path, av_stream->codec->width,
386 av_stream->codec->height, loop_count, enable_csc);
387 } else if (use_ffmpeg) {
388 // Use ffmepg for reading.
389 file_reader = new FFmpegFileReader(input_path);
390 } else if (input_path.Extension() == FILE_PATH_LITERAL(".264")) {
391 file_reader = new H264FileReader(input_path);
392 } else {
393 // Creates a reader that reads in blocks of 32KB.
394 const int kReadSize = 32768;
395 file_reader = new BlockFileReader(input_path, kReadSize);
396 }
397
398 // Create a file sink.
399 FileSink* file_sink = new FileSink(output_path, copy, enable_csc);
400
401 // Create a test app object and initialize it.
402 scoped_refptr<TestApp> test = new TestApp(av_stream, file_sink, file_reader);
403 if (!test->Initialize()) {
404 LOG(ERROR) << "can't initialize this application";
405 return -1;
406 }
407
408 // This will run the decoder until EOS is reached or an error
409 // is encountered.
410 test->Run();
411 return 0;
412 }
OLDNEW
« no previous file with comments | « media/tools/omx_test/file_sink.cc ('k') | media/tools/player_x11/player_x11.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698