diff options
author | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-28 22:19:48 +0000 |
---|---|---|
committer | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-28 22:19:48 +0000 |
commit | df10bf173f91818f1f03d409ec8d60265b44675f (patch) | |
tree | 27dc201712833ce527da84b15e0e4df73bdd56ec | |
parent | b045a7405237ec931bf137f2c555960fa64a9523 (diff) | |
download | chromium_src-df10bf173f91818f1f03d409ec8d60265b44675f.zip chromium_src-df10bf173f91818f1f03d409ec8d60265b44675f.tar.gz chromium_src-df10bf173f91818f1f03d409ec8d60265b44675f.tar.bz2 |
Implement VP8 encoder for chromoting
Added EncoderVp8 with test for chromoting.
TEST=remoting_unittests
BUG=50235
Review URL: http://codereview.chromium.org/3005036
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@60854 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | media/base/media.h | 8 | ||||
-rw-r--r-- | media/base/media_posix.cc | 21 | ||||
-rw-r--r-- | media/base/media_win.cc | 18 | ||||
-rw-r--r-- | remoting/base/codec_test.cc | 5 | ||||
-rw-r--r-- | remoting/base/encoder_vp8.cc | 205 | ||||
-rw-r--r-- | remoting/base/encoder_vp8.h | 43 | ||||
-rw-r--r-- | remoting/base/encoder_vp8_unittest.cc | 62 | ||||
-rw-r--r-- | remoting/base/protocol/chromotocol.proto | 1 | ||||
-rw-r--r-- | remoting/remoting.gyp | 13 | ||||
-rw-r--r-- | remoting/run_all_unittests.cc | 13 | ||||
-rw-r--r-- | third_party/libvpx/libvpx.gyp | 90 |
12 files changed, 311 insertions, 170 deletions
@@ -74,6 +74,8 @@ /third_party/hunspell_dictionaries /third_party/icu /third_party/libjingle/source +/third_party/libvpx/lib +/third_party/libvpx/include /third_party/libsrtp/src /third_party/libvpx /third_party/lighttpd diff --git a/media/base/media.h b/media/base/media.h index 3d1a83a..fd3269e 100644 --- a/media/base/media.h +++ b/media/base/media.h @@ -25,6 +25,14 @@ bool InitializeMediaLibrary(const FilePath& module_dir); // Returns true if OpenMAX was successfully initialized and loaded. bool InitializeOpenMaxLibrary(const FilePath& module_dir); +// This is temporary to get the address of vpx_codec_vp8_cx_algo in FFmpeg. +// This method should only be called after media library is loaded. + +// TODO(hclam): Remove this after we have a getter function for the same +// purpose in libvpx. +// See bug: http://code.google.com/p/webm/issues/detail?id=169 +void* GetVp8CxAlgoAddress(); + } // namespace media #endif // MEDIA_BASE_MEDIA_H_ diff --git a/media/base/media_posix.cc b/media/base/media_posix.cc index eebae5e..d5137eb 100644 --- a/media/base/media_posix.cc +++ b/media/base/media_posix.cc @@ -10,6 +10,7 @@ #include "base/file_path.h" #include "base/logging.h" +#include "base/native_library.h" #include "base/path_service.h" #include "media/ffmpeg/ffmpeg_common.h" #include "third_party/ffmpeg/ffmpeg_stubs.h" @@ -69,6 +70,9 @@ std::string GetDSOName(tp_ffmpeg::StubModules stub_key) { } // namespace +// Address of vpx_codec_vp8_cx_algo. +static void* vp8_cx_algo_address = NULL; + // Attempts to initialize the media library (loading DSOs, etc.). // Returns true if everything was successfully initialized, false otherwise. bool InitializeMediaLibrary(const FilePath& module_dir) { @@ -85,7 +89,18 @@ bool InitializeMediaLibrary(const FilePath& module_dir) { paths[module].push_back(path.value()); } - return tp_ffmpeg::InitializeStubs(paths); + bool ret = tp_ffmpeg::InitializeStubs(paths); + + // TODO(hclam): This is temporary to obtain address of + // vpx_codec_vp8_cx_algo. This should be removed once libvpx has a + // getter method for it. + base::NativeLibrary sumo_lib = + base::LoadNativeLibrary(module_dir.Append(sumo_name)); + if (sumo_lib) { + vp8_cx_algo_address = base::GetFunctionPointerFromNativeLibrary( + sumo_lib, "vpx_codec_vp8_cx_algo"); + } + return ret; } #if defined(OS_LINUX) @@ -114,4 +129,8 @@ bool InitializeOpenMaxLibrary(const FilePath& module_dir) { } #endif +void* GetVp8CxAlgoAddress() { + return vp8_cx_algo_address; +} + } // namespace media diff --git a/media/base/media_win.cc b/media/base/media_win.cc index 6f9e0f8..f31ab5b 100644 --- a/media/base/media_win.cc +++ b/media/base/media_win.cc @@ -8,6 +8,7 @@ #include "base/file_path.h" #include "base/logging.h" +#include "base/native_library.h" #include "base/path_service.h" #include "base/scoped_ptr.h" @@ -47,6 +48,9 @@ FilePath::CharType* GetDLLName(FFmpegDLLKeys dll_key) { } // namespace +// Address of vpx_codec_vp8_cx_algo. +static void* vp8_cx_algo_address = NULL; + // Attempts to initialize the media library (loading DLLs, DSOs, etc.). // Returns true if everything was successfully initialized, false otherwise. bool InitializeMediaLibrary(const FilePath& base_path) { @@ -78,6 +82,16 @@ bool InitializeMediaLibrary(const FilePath& base_path) { #endif } + // TODO(hclam): This is temporary to obtain address of + // vpx_codec_vp8_cx_algo. This should be removed once libvpx has a + // getter method for it. + base::NativeLibrary avcodec_lib = + base::LoadNativeLibrary(FilePath(GetDLLName(media::FILE_LIBAVCODEC))); + if (avcodec_lib) { + vp8_cx_algo_address = base::GetFunctionPointerFromNativeLibrary( + avcodec_lib, "vpx_codec_vp8_cx_algo"); + } + // Check that we loaded all libraries successfully. We only need to check the // last array element because the loop above will break without initializing // it on any prior error. @@ -97,4 +111,8 @@ bool InitializeOpenMaxLibrary(const FilePath& module_dir) { return false; } +void* GetVp8CxAlgoAddress() { + return vp8_cx_algo_address; +} + } // namespace media diff --git a/remoting/base/codec_test.cc b/remoting/base/codec_test.cc index 40c42ed..e8f17ca 100644 --- a/remoting/base/codec_test.cc +++ b/remoting/base/codec_test.cc @@ -78,9 +78,10 @@ class EncoderMessageTester { ~EncoderMessageTester() { EXPECT_EQ(begin_rect_, end_rect_); + EXPECT_GT(begin_rect_, 0); EXPECT_EQ(kWaitingForBeginRect, state_); - if (strict_){ - EXPECT_EQ(begin_rect_, added_rects_); + if (strict_) { + EXPECT_EQ(added_rects_, begin_rect_); } } diff --git a/remoting/base/encoder_vp8.cc b/remoting/base/encoder_vp8.cc index 231acd5..eec6ed5 100644 --- a/remoting/base/encoder_vp8.cc +++ b/remoting/base/encoder_vp8.cc @@ -5,129 +5,190 @@ #include "base/logging.h" #include "media/base/callback.h" #include "media/base/data_buffer.h" -#include "remoting/host/encoder_vp8.h" +#include "media/base/media.h" +#include "remoting/base/capture_data.h" +#include "remoting/base/encoder_vp8.h" extern "C" { -// TODO(garykac): Rix with correct path to vp8 header. -#include "remoting/third_party/on2/include/vp8cx.h" +#define VPX_CODEC_DISABLE_COMPAT 1 +#include "third_party/libvpx/include/vpx/vpx_codec.h" +#include "third_party/libvpx/include/vpx/vpx_encoder.h" +#include "third_party/libvpx/include/vpx/vp8cx.h" } namespace remoting { EncoderVp8::EncoderVp8() : initialized_(false), + codec_(NULL), + image_(NULL), last_timestamp_(0) { } EncoderVp8::~EncoderVp8() { + if (initialized_) { + vpx_codec_err_t ret = vpx_codec_destroy(codec_.get()); + DCHECK(ret == VPX_CODEC_OK) << "Failed to destroy codec"; + } } -bool EncoderVp8::Init() { - // TODO(hclam): Now always assume we receive YV12. May need to extend this - // so we can do color space conversion manually. - image_.fmt = IMG_FMT_YV12; - image_.w = width_; - image_.h = height_; - - on2_codec_enc_cfg_t config; - on2_codec_err_t result = on2_codec_enc_config_default(&on2_codec_vp8_cx_algo, - &config, 0); - - // TODO(hclam): Adjust the parameters. - config.g_w = width_; - config.g_h = height_; - config.g_pass = ON2_RC_ONE_PASS; +bool EncoderVp8::Init(int width, int height) { + codec_.reset(new vpx_codec_ctx_t()); + image_.reset(new vpx_image_t()); + memset(image_.get(), 0, sizeof(vpx_image_t)); + + image_->fmt = VPX_IMG_FMT_YV12; + + // libvpx seems to require both to be assigned. + image_->d_w = width; + image_->w = width; + image_->d_h = height; + image_->h = height; + + vpx_codec_enc_cfg_t config; + const vpx_codec_iface_t* algo = + (const vpx_codec_iface_t*)media::GetVp8CxAlgoAddress(); + vpx_codec_err_t ret = vpx_codec_enc_config_default(algo, &config, 0); + if (ret != VPX_CODEC_OK) + return false; + + // TODO(hclam): Tune the parameters to better suit the application. + config.rc_target_bitrate = width * height * config.rc_target_bitrate + / config.g_w / config.g_h; + config.g_w = width; + config.g_h = height; + config.g_pass = VPX_RC_ONE_PASS; config.g_profile = 1; config.g_threads = 2; - config.rc_target_bitrate = 1000000; config.rc_min_quantizer = 0; config.rc_max_quantizer = 15; config.g_timebase.num = 1; config.g_timebase.den = 30; - if (on2_codec_enc_init(&codec_, &on2_codec_vp8_cx_algo, &config, 0)) + if (vpx_codec_enc_init(codec_.get(), algo, &config, 0)) return false; + return true; +} + +bool EncoderVp8::PrepareImage(scoped_refptr<CaptureData> capture_data) { + if (!yuv_image_.get()) { + const int plane_size = capture_data->width() * capture_data->height(); + + // YUV image size is 1.5 times of a plane. Multiplication is performed first + // to avoid rounding error. + const int size = plane_size * 3 / 2; + + yuv_image_.reset(new uint8[size]); + + // Reset image value to 128 so we just need to fill in the y plane. + memset(yuv_image_.get(), 128, size); + + // Fill in the information for |image_|. + unsigned char* image = reinterpret_cast<unsigned char*>(yuv_image_.get()); + image_->planes[0] = image; + image_->planes[1] = image + plane_size; + + // The V plane starts from 1.25 of the plane size. + image_->planes[2] = image + plane_size + plane_size / 4; - on2_codec_control_(&codec_, VP8E_SET_CPUUSED, -15); + // In YV12 Y plane has full width, UV plane has half width because of + // subsampling. + image_->stride[0] = image_->w; + image_->stride[1] = image_->w / 2; + image_->stride[2] = image_->w / 2; + } + + // And then do RGB->YUV conversion. + // Currently we just produce the Y channel as the average of RGB. This will + // give a gray scale image after conversion. + // TODO(hclam): Implement the actual color space conversion. + DCHECK(capture_data->pixel_format() == PixelFormatRgb32) + << "Only RGB32 is supported"; + uint8* in = capture_data->data_planes().data[0]; + const int in_stride = capture_data->data_planes().strides[0]; + uint8* out = yuv_image_.get(); + const int out_stride = image_->stride[0]; + for (int i = 0; i < capture_data->height(); ++i) { + for (int j = 0; j < capture_data->width(); ++j) { + // Since the input pixel format is RGB32, there are 4 bytes per pixel. + uint8* pixel = in + 4 * j; + out[j] = (pixel[0] + pixel[1] + pixel[2]) / 3; + } + in += in_stride; + out += out_stride; + } return true; } -void EncoderVp8::Encode(const DirtyRects& dirty_rects, - const uint8** input_data, - const int* strides, +void EncoderVp8::Encode(scoped_refptr<CaptureData> capture_data, bool key_frame, - UpdateStreamPacketHeader* header, - scoped_refptr<media::DataBuffer>* output_data, - bool* encode_done, - Task* data_available_task) { - // This will allow the task be called when this method exits. - media::AutoTaskRunner task(data_available_task); - *encode_done = false; - - // TODO(hclam): We only initialize the encoder once. We may have to - // allow encoder be initialized with difference sizes. + DataAvailableCallback* data_available_callback) { if (!initialized_) { - if (!Init()) { - LOG(ERROR) << "Can't initialize VP8 encoder"; - return; - } - initialized_ = true; + bool ret = Init(capture_data->width(), capture_data->height()); + // TODO(hclam): Handle error better. + DCHECK(ret) << "Initialization of encoder failed"; + initialized_ = ret; } - // Assume the capturer has done the color space conversion. - if (!input_data || !strides) - return; - - image_.planes[0] = (unsigned char*)input_data[0]; - image_.planes[1] = (unsigned char*)input_data[1]; - image_.planes[2] = (unsigned char*)input_data[2]; - image_.stride[0] = strides[0]; - image_.stride[1] = strides[1]; - image_.stride[2] = strides[2]; + if (!PrepareImage(capture_data)) { + NOTREACHED() << "Can't image data for encoding"; + } // Do the actual encoding. - if (on2_codec_encode(&codec_, &image_, - last_timestamp_, 1, 0, ON2_DL_REALTIME)) { - return; - } + vpx_codec_err_t ret = vpx_codec_encode(codec_.get(), image_.get(), + last_timestamp_, + 1, 0, VPX_DL_REALTIME); + DCHECK(ret == VPX_CODEC_OK) << "Encoding error: " + << vpx_codec_err_to_string(ret) + << "\n" + << "Details: " + << vpx_codec_error(codec_.get()) + << "\n" + << vpx_codec_error_detail(codec_.get()); // TODO(hclam): fix this. last_timestamp_ += 100; // Read the encoded data. - on2_codec_iter_t iter = NULL; + vpx_codec_iter_t iter = NULL; bool got_data = false; - // TODO(hclam: We assume one frame of input will get exactly one frame of - // output. This assumption may not be valid. + // TODO(hclam): Make sure we get exactly one frame from the packet. + // TODO(hclam): We should provide the output buffer to avoid one copy. + ChromotingHostMessage* message = new ChromotingHostMessage(); + UpdateStreamPacketMessage* packet = message->mutable_update_stream_packet(); + + // Prepare the begin rect. + packet->mutable_begin_rect()->set_x(0); + packet->mutable_begin_rect()->set_y(0); + packet->mutable_begin_rect()->set_width(capture_data->width()); + packet->mutable_begin_rect()->set_height(capture_data->height()); + packet->mutable_begin_rect()->set_encoding(EncodingVp8); + packet->mutable_begin_rect()->set_pixel_format(PixelFormatYv12); + while (!got_data) { - on2_codec_cx_pkt_t* packet = on2_codec_get_cx_data(&codec_, &iter); + const vpx_codec_cx_pkt_t* packet = vpx_codec_get_cx_data(codec_.get(), + &iter); if (!packet) continue; switch (packet->kind) { - case ON2_CODEC_CX_FRAME_PKT: + case VPX_CODEC_CX_FRAME_PKT: got_data = true; - *encode_done = true; - *output_data = new media::DataBuffer(packet->data.frame.sz); - memcpy((*output_data)->GetWritableData(), - packet->data.frame.buf, - packet->data.frame.sz); + message->mutable_update_stream_packet()->mutable_rect_data()->set_data( + packet->data.frame.buf, packet->data.frame.sz); break; default: break; } } - return; -} - -void EncoderVp8::SetSize(int width, int height) { - width_ = width; - height_ = height; -} -void EncoderVp8::SetPixelFormat(PixelFormat pixel_format) { - pixel_format_ = pixel_format; + // Enter the end rect. + message->mutable_update_stream_packet()->mutable_end_rect(); + data_available_callback->Run( + message, + EncodingStarting | EncodingInProgress | EncodingEnded); + delete data_available_callback; } } // namespace remoting diff --git a/remoting/base/encoder_vp8.h b/remoting/base/encoder_vp8.h index 4b8b539..ae29c63 100644 --- a/remoting/base/encoder_vp8.h +++ b/remoting/base/encoder_vp8.h @@ -5,20 +5,11 @@ #ifndef REMOTING_BASE_ENCODER_VP8_H_ #define REMOTING_BASE_ENCODER_VP8_H_ -#include "remoting/host/encoder.h" - +#include "remoting/base/encoder.h" #include "remoting/base/protocol/chromotocol.pb.h" -extern "C" { -// TODO(garykac): fix this link with the correct path to on2 -#include "remoting/third_party/on2/include/on2_encoder.h" -} // extern "C" - -namespace media { - -class DataBuffer; - -} // namespace media +typedef struct vpx_codec_ctx vpx_codec_ctx_t; +typedef struct vpx_image vpx_image_t; namespace remoting { @@ -28,31 +19,27 @@ class EncoderVp8 : public Encoder { EncoderVp8(); virtual ~EncoderVp8(); - virtual void Encode(const DirtyRects& dirty_rects, - const uint8** input_data, - const int* strides, + virtual void Encode(scoped_refptr<CaptureData> capture_data, bool key_frame, - UpdateStreamPacketHeader* header, - scoped_refptr<media::DataBuffer>* output_data, - bool* encode_done, - Task* data_available_task); - virtual void SetSize(int width, int height); - virtual void SetPixelFormat(PixelFormat pixel_format); + DataAvailableCallback* data_available_callback); private: - // Setup the VP8 encoder. - bool Init(); + // Initialize the encoder. Returns true if successful. + bool Init(int width, int height); + + // Prepare |image_| for encoding. Returns true if successful. + bool PrepareImage(scoped_refptr<CaptureData> capture_data); // True if the encoder is initialized. bool initialized_; - int width_; - int height_; - PixelFormat pixel_format_; - on2_codec_ctx_t codec_; - on2_image_t image_; + scoped_ptr<vpx_codec_ctx_t> codec_; + scoped_ptr<vpx_image_t> image_; int last_timestamp_; + // Buffer for storing the yuv image. + scoped_array<uint8> yuv_image_; + DISALLOW_COPY_AND_ASSIGN(EncoderVp8); }; diff --git a/remoting/base/encoder_vp8_unittest.cc b/remoting/base/encoder_vp8_unittest.cc index 0b29830..353b82b 100644 --- a/remoting/base/encoder_vp8_unittest.cc +++ b/remoting/base/encoder_vp8_unittest.cc @@ -2,67 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "media/base/data_buffer.h" -#include "remoting/base/pixel_format.h" -#include "remoting/host/encoder_vp8.h" -#include "testing/gmock/include/gmock/gmock.h" +#include "remoting/base/codec_test.h" +#include "remoting/base/encoder_vp8.h" +#include "testing/gtest/include/gtest/gtest.h" namespace remoting { -static const int kWidth = 1024; -static const int kHeight = 768; -static const PixelFormat kPixelFormat = kPixelFormat_YV12; - -static void GenerateData(uint8* data, int size) { - for (int i = 0; i < size; ++i) { - data[i] = i; - } -} - -class EncodeDoneHandler - : public base::RefCountedThreadSafe<EncodeDoneHandler> { - public: - MOCK_METHOD0(EncodeDone, void()); -}; - -TEST(EncoderVp8Test, SimpleEncode) { +TEST(EncoderVp8Test, TestEncoder) { EncoderVp8 encoder; - encoder.SetSize(kWidth, kHeight); - encoder.SetPixelFormat(kPixelFormat); - - DirtyRects rects; - rects.push_back(gfx::Rect(kWidth, kHeight)); - - // Prepare memory for encoding. - int strides[3]; - strides[0] = kWidth; - strides[1] = strides[2] = kWidth / 2; - - uint8* planes[3]; - planes[0] = new uint8[kWidth * kHeight]; - planes[1] = new uint8[kWidth * kHeight / 4]; - planes[2] = new uint8[kWidth * kHeight / 4]; - GenerateData(planes[0], kWidth * kHeight); - GenerateData(planes[1], kWidth * kHeight / 4); - GenerateData(planes[2], kWidth * kHeight / 4); - - scoped_refptr<EncodeDoneHandler> handler = new EncodeDoneHandler(); - UpdateStreamPacketHeader* header = new UpdateStreamPacketHeader(); - scoped_refptr<media::DataBuffer> encoded_data; - bool encode_done = false; - EXPECT_CALL(*handler, EncodeDone()); - encoder.Encode(rects, const_cast<const uint8**>(planes), - strides, true, header, &encoded_data, &encode_done, - NewRunnableMethod(handler.get(), - &EncodeDoneHandler::EncodeDone)); - - EXPECT_TRUE(encode_done); - ASSERT_TRUE(encoded_data.get()); - EXPECT_NE(0u, encoded_data->GetBufferSize()); - - delete [] planes[0]; - delete [] planes[1]; - delete [] planes[2]; + TestEncoder(&encoder, false); } } // namespace remoting diff --git a/remoting/base/protocol/chromotocol.proto b/remoting/base/protocol/chromotocol.proto index 865fd3f..00986ac 100644 --- a/remoting/base/protocol/chromotocol.proto +++ b/remoting/base/protocol/chromotocol.proto @@ -34,6 +34,7 @@ enum UpdateStreamEncoding { EncodingInvalid = -1; EncodingNone = 0; EncodingZlib = 1; + EncodingVp8 = 2; } // Identifies the pixel format. diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp index 203ec43..33339cb 100644 --- a/remoting/remoting.gyp +++ b/remoting/remoting.gyp @@ -114,18 +114,15 @@ '../gfx/gfx.gyp:gfx', '../media/media.gyp:media', '../third_party/protobuf2/protobuf.gyp:protobuf_lite', + '../third_party/libvpx/libvpx.gyp:libvpx_include', '../third_party/zlib/zlib.gyp:zlib', 'base/protocol/chromotocol.gyp:chromotocol_proto_lib', 'base/protocol/chromotocol.gyp:trace_proto_lib', 'chromoting_jingle_glue', - # TODO(hclam): Enable VP8 in the build. - #'third_party/on2/on2.gyp:vp8', ], 'export_dependent_settings': [ '../third_party/protobuf2/protobuf.gyp:protobuf_lite', 'base/protocol/chromotocol.gyp:chromotocol_proto_lib', - # TODO(hclam): Enable VP8 in the build. - #'third_party/on2/on2.gyp:vp8', ], # This target needs a hard dependency because dependent targets # depend on chromotocol_proto_lib for headers. @@ -148,11 +145,10 @@ 'base/encoder.h', 'base/encoder_verbatim.cc', 'base/encoder_verbatim.h', + 'base/encoder_vp8.cc', + 'base/encoder_vp8.h', 'base/encoder_zlib.cc', 'base/encoder_zlib.h', - # TODO(hclam): Enable VP8 in the build. - #'base/encoder_vp8.cc', - #'base/encoder_vp8.h', 'base/multiple_array_input_stream.cc', 'base/multiple_array_input_stream.h', 'base/protocol_decoder.cc', @@ -407,8 +403,7 @@ 'base/decoder_zlib_unittest.cc', 'base/decompressor_zlib_unittest.cc', 'base/encoder_verbatim_unittest.cc', - # TODO(hclam): Enable VP8 in the build. - #'base/encoder_vp8_unittest.cc', + 'base/encoder_vp8_unittest.cc', 'base/encoder_zlib_unittest.cc', 'base/mock_objects.h', 'base/multiple_array_input_stream_unittest.cc', diff --git a/remoting/run_all_unittests.cc b/remoting/run_all_unittests.cc index 2571950..16e4f74 100644 --- a/remoting/run_all_unittests.cc +++ b/remoting/run_all_unittests.cc @@ -2,8 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/file_path.h" +#include "base/logging.h" +#include "base/path_service.h" #include "base/test/test_suite.h" +#include "media/base/media.h" int main(int argc, char** argv) { - return base::TestSuite(argc, argv).Run(); + base::TestSuite test_suite(argc, argv); + + // Load the media library so we can use libvpx. + FilePath path; + PathService::Get(base::DIR_MODULE, &path); + CHECK(media::InitializeMediaLibrary(path)) + << "Cannot load media library"; + return test_suite.Run(); } diff --git a/third_party/libvpx/libvpx.gyp b/third_party/libvpx/libvpx.gyp new file mode 100644 index 0000000..f0e5f34 --- /dev/null +++ b/third_party/libvpx/libvpx.gyp @@ -0,0 +1,90 @@ +# 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. + +{ + 'targets': [ + # libvpx_lib is currently not being used since we use libvpx inside + # libavcodec. Keeping this just in case we need this later. + { + 'target_name': 'libvpx_lib', + 'type': 'none', + 'variables': { + 'libvpx_lib': 'libvpx.a', + }, + 'conditions': [ + # This section specifies the folder for looking for libvpx.a. + # + ['OS=="linux" and target_arch=="ia32"', { + 'variables': { + 'libvpx_path': 'lib/linux/ia32', + }, + }], + ['OS=="linux" and target_arch=="x64"', { + 'variables': { + 'libvpx_path': 'lib/linux/x64', + }, + }], + ['OS=="linux" and target_arch=="arm" and arm_neon==1', { + 'variables': { + 'libvpx_path': 'lib/linux/arm-neon', + }, + }], + ['OS=="linux" and target_arch=="arm" and arm_neon==0', { + 'variables': { + 'libvpx_path': 'lib/linux/arm', + }, + }], + ['OS=="win"', { + 'variables': { + 'libvpx_path': 'lib/win/ia32', + }, + }], + ['OS=="mac"', { + 'variables': { + 'libvpx_path': 'lib/mac/ia32', + }, + }], + ], + 'actions': [ + { + 'action_name': 'copy_lib', + 'inputs': [ + '<(libvpx_path)/<(libvpx_lib)', + ], + 'outputs': [ + '<(SHARED_INTERMEDIATE_DIR)/<(libvpx_lib)', + ], + 'action': [ + 'cp', + '<(libvpx_path)/<(libvpx_lib)', + '<(SHARED_INTERMEDIATE_DIR)/<(libvpx_lib)', + ], + 'message': 'Copying libvpx.a into <(SHARED_INTERMEDIATE_DIR)', + }, + ], + 'all_dependent_settings': { + 'link_settings': { + 'libraries': [ + '<(SHARED_INTERMEDIATE_DIR)/<(libvpx_lib)', + ], + }, + }, + }, + { + 'target_name': 'libvpx_include', + 'type': 'none', + 'direct_dependent_settings': { + 'include_dirs': [ + 'include', + ], + }, + } + ], +} + +# Local Variables: +# tab-width:2 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=2 shiftwidth=2: |