summaryrefslogtreecommitdiffstats
path: root/media/omx/omx_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'media/omx/omx_test.cc')
-rw-r--r--media/omx/omx_test.cc208
1 files changed, 184 insertions, 24 deletions
diff --git a/media/omx/omx_test.cc b/media/omx/omx_test.cc
index 0a44a70..08d91f0 100644
--- a/media/omx/omx_test.cc
+++ b/media/omx/omx_test.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this
+// Copyright (c) 2010 The Chromium Authors. All rights reserved. Use of this
// source code is governed by a BSD-style license that can be found in the
// LICENSE file.
@@ -15,6 +15,7 @@
#include "base/file_util.h"
#include "base/message_loop.h"
#include "base/scoped_ptr.h"
+#include "base/time.h"
#include "media/omx/input_buffer.h"
#include "media/omx/omx_codec.h"
@@ -23,15 +24,21 @@
// decoder.
class TestApp {
public:
- TestApp(const char* filename,
+ TestApp(const char* input_filename,
+ const char* output_filename,
const char* component,
- media::OmxCodec::Codec codec,
+ media::OmxCodec::OmxMediaFormat& input_format,
+ media::OmxCodec::OmxMediaFormat& output_format,
bool simulate_copy)
- : filename_(filename),
+ : input_filename_(input_filename),
+ output_filename_(output_filename),
component_(component),
- codec_(codec),
+ input_format_(input_format),
+ output_format_(output_format),
simulate_copy_(simulate_copy),
copy_buf_size_(0),
+ input_file_(NULL),
+ output_file_(NULL),
stopped_(false),
error_(false) {
}
@@ -82,36 +89,52 @@ class TestApp {
decoder_->Read(NewCallback(this, &TestApp::ReadCompleteCallback));
// Copy the output of the decoder to user memory.
- if (simulate_copy_) {
+ if (simulate_copy_ || output_file_) { // |output_file_| implies a copy.
if (size > copy_buf_size_) {
copy_buf_.reset(new uint8[size]);
copy_buf_size_ = size;
}
memcpy(copy_buf_.get(), buffer, size);
+ if (output_file_)
+ fwrite(copy_buf_.get(), sizeof(uint8), size, output_file_);
}
+
+ // could OMX IL return patial sample for decoder?
+ frame_count_++;
+ bit_count_ += size << 3;
}
void FeedDecoder() {
// This method feeds the decoder with 32KB of input data.
const int kSize = 32768;
uint8* data = new uint8[kSize];
- int read = fread(data, 1, kSize, file_);
+ int read = fread(data, 1, kSize, input_file_);
decoder_->Feed(new media::InputBuffer(data, read),
NewCallback(this, &TestApp::FeedCallback));
}
void Run() {
// Open the input file.
- file_ = file_util::OpenFile(filename_, "rb");
- if (!file_) {
- printf("Error - can't open file %s\n", filename_);
+ input_file_ = file_util::OpenFile(input_filename_, "rb");
+ if (!input_file_) {
+ printf("Error - can't open file %s\n", input_filename_);
return;
}
+ // Open the dump file.
+ if (strlen(output_filename_)) {
+ output_file_ = file_util::OpenFile(output_filename_, "wb");
+ if (!input_file_) {
+ fclose(input_file_);
+ printf("Error - can't open dump file %s\n", output_filename_);
+ return;
+ }
+ }
+
// Setup the decoder with the message loop of the current thread. Also
// setup component name, codec and callbacks.
decoder_ = new media::OmxCodec(&message_loop_);
- decoder_->Setup(component_, codec_);
+ decoder_->Setup(component_, input_format_, output_format_);
decoder_->SetErrorCallback(NewCallback(this, &TestApp::ErrorCallback));
// Start the decoder.
@@ -123,21 +146,100 @@ class TestApp {
// Execute the message loop so that we can run tasks on it. This call
// will return when we call message_loop_.Quit().
message_loop_.Run();
+
+ fclose(input_file_);
+ if (output_file_)
+ fclose(output_file_);
+ }
+
+ void StartProfiler() {
+ start_time_ = base::Time::Now();
+ frame_count_ = 0;
+ bit_count_ = 0;
+ }
+
+ void StopProfiler() {
+ base::Time stop_time = base::Time::Now();
+ base::TimeDelta duration = stop_time - start_time_;
+ int micro_sec = static_cast<int>(duration.InMicroseconds());
+ printf("\n<<< frame delivered : %d >>>", frame_count_);
+ printf("\n<<< time used(us) : %d >>>", micro_sec);
+ printf("\n<<< fps : %d >>>", frame_count_ * 1000000 / micro_sec);
+ // printf("\n<<< bitrate>>> : %I64d\n", bit_count_ * 1000000 / micro_sec);
+ printf("\n");
}
scoped_refptr<media::OmxCodec> decoder_;
MessageLoop message_loop_;
- const char* filename_;
+ const char* input_filename_;
+ const char* output_filename_;
const char* component_;
- media::OmxCodec::Codec codec_;
+ media::OmxCodec::OmxMediaFormat input_format_;
+ media::OmxCodec::OmxMediaFormat output_format_;
bool simulate_copy_;
scoped_array<uint8> copy_buf_;
int copy_buf_size_;
- FILE* file_;
+ FILE *input_file_, *output_file_;
bool stopped_;
bool error_;
+ base::Time start_time_;
+ int frame_count_;
+ int bit_count_;
};
+// Not intended to be used in production.
+void NV21toI420(uint8* nv21, uint8* i420, int width, int height) {
+ memcpy(i420, nv21, width * height * sizeof(uint8));
+ i420 += width * height;
+ nv21 += width * height;
+ uint8* u = i420;
+ uint8* v = i420 + width * height / 4;
+
+ for (int i = 0; i < width * height / 4; ++i) {
+ *v++ = *nv21++;
+ *u++ = *nv21++;
+ }
+}
+
+void NV21toYV12(uint8* nv21, uint8* yv12, int width, int height) {
+ memcpy(yv12, nv21, width * height * sizeof(uint8));
+ yv12 += width * height;
+ nv21 += width * height;
+ uint8* v = yv12;
+ uint8* u = yv12 + width * height / 4;
+
+ for (int i = 0; i < width * height / 4; ++i) {
+ *v++ = *nv21++;
+ *u++ = *nv21++;
+ }
+}
+
+void I420toNV21(uint8* i420, uint8* nv21, int width, int height) {
+ memcpy(nv21, i420, width * height * sizeof(uint8));
+ i420 += width * height;
+ nv21 += width * height;
+ uint8* u = i420;
+ uint8* v = i420 + width * height / 4;
+
+ for (int i = 0; i < width * height / 4; ++i) {
+ *nv21++ = *v++;
+ *nv21++ = *u++;
+ }
+}
+
+void YV12toNV21(uint8* yv12, uint8* nv21, int width, int height) {
+ memcpy(nv21, yv12, width * height * sizeof(uint8));
+ yv12 += width * height;
+ nv21 += width * height;
+ uint8* v = yv12;
+ uint8* u = yv12 + width * height / 4;
+
+ for (int i = 0; i < width * height / 4; ++i) {
+ *nv21++ = *v++;
+ *nv21++ = *u++;
+ }
+}
+
int main(int argc, char** argv) {
base::AtExitManager at_exit_manager;
@@ -145,40 +247,98 @@ int main(int argc, char** argv) {
const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
if (argc < 2) {
- printf("Usage: omx_test --file=FILE --component=COMPONENT --codec=CODEC"
- " [--copy]\n");
+ printf("Usage: omx_test --input-file=FILE"
+ " --component=COMPONENT --codec=CODEC"
+ " [--output-file=FILE] [--enable-csc=FILE]"
+ " [--copy] [--measure-fps]\n");
printf(" COMPONENT: OpenMAX component name\n");
printf(" CODEC: h264/mpeg4/h263/vc1\n");
printf("\n");
printf("Optional Arguments\n");
- printf(" --copy Simulate a memcpy from the output of decoder.\n");
+ printf(" --output-file Dump raw OMX output to file.\n");
+ printf(" --enable-csc Dump the CSCed output to file.\n");
+ printf(" --copy Simulate a memcpy from the output of decoder.\n");
+ printf(" --measure-fps Measuring performance in fps\n");
return 1;
}
- std::string filename = cmd_line->GetSwitchValueASCII("file");
+ std::string input_filename = cmd_line->GetSwitchValueASCII("input-file");
+ std::string output_filename = cmd_line->GetSwitchValueASCII("output-file");
std::string component = cmd_line->GetSwitchValueASCII("component");
std::string codec = cmd_line->GetSwitchValueASCII("codec");
bool copy = cmd_line->HasSwitch("copy");
+ bool measure_fps = cmd_line->HasSwitch("measure-fps");
+
- media::OmxCodec::Codec codec_id = media::OmxCodec::kCodecNone;
+ media::OmxCodec::OmxMediaFormat input, output;
+ input.codec = media::OmxCodec::kCodecNone;
if (codec == "h264")
- codec_id = media::OmxCodec::kCodecH264;
+ input.codec = media::OmxCodec::kCodecH264;
else if (codec == "mpeg4")
- codec_id = media::OmxCodec::kCodecMpeg4;
+ input.codec = media::OmxCodec::kCodecMpeg4;
else if (codec == "h263")
- codec_id = media::OmxCodec::kCodecH263;
+ input.codec = media::OmxCodec::kCodecH263;
else if (codec == "vc1")
- codec_id = media::OmxCodec::kCodecVc1;
+ input.codec = media::OmxCodec::kCodecVc1;
else {
printf("Unknown codec.\n");
return 1;
}
+ output.codec = media::OmxCodec::kCodecRaw;
// Create a TestApp object and run the decoder.
- TestApp test(filename.c_str(), component.c_str(), codec_id, copy);
+ TestApp test(input_filename.c_str(),
+ output_filename.c_str(),
+ component.c_str(),
+ input,
+ output,
+ copy);
+
+
+ if (measure_fps)
+ test.StartProfiler();
// This call will run the decoder until EOS is reached or an error
// is encountered.
test.Run();
+
+ if (measure_fps)
+ test.StopProfiler();
+
+ // Color space conversion.
+ if (!output_filename.empty()) {
+ std::string dumpyuv_name = cmd_line->GetSwitchValueASCII("enable-csc");
+ if (!dumpyuv_name.empty()) {
+ // now assume the raw output is NV21;
+ // now assume decoder.
+ FILE* dump_raw = file_util::OpenFile(output_filename.c_str(), "rb");
+ FILE* dump_yuv = file_util::OpenFile(dumpyuv_name.c_str(), "wb");
+ if (!dump_raw || !dump_yuv) {
+ printf("Error - can't open file for color conversion %s\n",
+ dumpyuv_name.c_str());
+ } else {
+ // TODO(jiesun): get rid of hard coded value when Startup()
+ // call back function is ready.
+ int width = 352;
+ int height = 288;
+ int frame_size = width * height * 3 / 2; // assume 4:2:0 chroma format.
+ scoped_array<uint8> in_buffer(new uint8[frame_size]);
+ scoped_array<uint8> out_buffer(new uint8[frame_size]);
+ while (true) {
+ int read;
+ read = fread(in_buffer.get(), sizeof(uint8), frame_size, dump_raw);
+ if (read != frame_size)
+ break;
+ NV21toI420(in_buffer.get(), out_buffer.get(), width, height);
+ fwrite(out_buffer.get(), sizeof(uint8), frame_size, dump_yuv);
+ }
+ }
+ if (dump_raw)
+ fclose(dump_raw);
+ if (dump_yuv)
+ fclose(dump_yuv);
+ }
+ }
+
return 0;
}