Add DesktopCapturer interface for desktop capturers.

The new DesktopCapturer interface will be used for screen and window
captures. Beside DesktopCapturer itself also added classes/interfaces
that it depends on.

R=alexeypa@chromium.org, tommi@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/1322007

git-svn-id: http://webrtc.googlecode.com/svn/trunk@3917 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
sergeyu@chromium.org 2013-04-29 20:10:57 +00:00
parent 865ada3a52
commit 15e32ccd30
13 changed files with 772 additions and 2 deletions

View File

@ -14,9 +14,42 @@
'dependencies': [
'<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers',
],
'direct_dependent_settings': {
# Headers may use include path relative to webrtc root and depend on
# WEBRTC_WIN define, so we need to make sure dependent targets have
# these settings.
#
# TODO(sergeyu): Move these settings to common.gypi
'include_dirs': [
'../../..',
],
'conditions': [
['OS=="win"', {
'defines': [
'WEBRTC_WIN',
],
}],
],
},
'sources': [
# TODO(sergeyu): Add source files here once they are moved from
# chromium.
"desktop_capturer.h",
"desktop_frame.cc",
"desktop_frame.h",
"desktop_frame_win.cc",
"desktop_frame_win.h",
"desktop_geometry.cc",
"desktop_geometry.h",
"desktop_region.cc",
"desktop_region.h",
"shared_memory.cc",
"shared_memory.h",
],
'conditions': [
['OS!="win"', {
'sources/': [
['exclude', '_win(_unittest)?\\.(cc|h)$'],
],
}],
],
},
], # targets

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_CAPTURER_H_
#define WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_CAPTURER_H_
namespace webrtc {
class DesktopFrame;
class DesktopRegion;
class SharedMemory;
// Abstract interface for screen and window capturers.
class DesktopCapturer {
public:
// Interface that must be implemented by the DesktopCapturer consumers.
class Callback {
public:
// Creates a new shared memory buffer for a frame create by the capturer.
// Should return null shared memory is not used for captured frames (in that
// case the capturer will allocate memory on the heap).
virtual SharedMemory* CreateSharedMemory(size_t size) = 0;
// Called after a frame has been captured. Handler must take ownership of
// |frame|. If capture has failed for any reason |frame| is set to NULL
// (e.g. the window has been closed).
virtual void OnCaptureCompleted(DesktopFrame* frame) = 0;
protected:
virtual ~Callback() {}
};
virtual ~DesktopCapturer() {}
// Called at the beginning of a capturing session. |callback| must remain
// valid until capturer is destroyed.
virtual void Start(Callback* callback) = 0;
// Captures next frame. |region| specifies region of the capture target that
// should be fresh in the resulting frame. The frame may also include fresh
// data for areas outside |region|. In that case capturer will include these
// areas in updated_region() of the frame. |region| is specified relative to
// the top left corner of the capture target. Pending capture operations are
// canceled when DesktopCapturer is deleted.
virtual void Capture(const DesktopRegion& region) = 0;
};
} // namespace webrtc
#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_CAPTURER_H_

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/modules/desktop_capture/desktop_frame.h"
namespace webrtc {
DesktopFrame::DesktopFrame(DesktopSize size,
int stride,
uint8_t* data,
SharedMemory* shared_memory)
: size_(size),
stride_(stride),
data_(data),
shared_memory_(shared_memory),
capture_time_ms_(0) {
}
DesktopFrame::~DesktopFrame() {}
BasicDesktopFrame::BasicDesktopFrame(DesktopSize size)
: DesktopFrame(size, kBytesPerPixel * size.width(),
new uint8_t[kBytesPerPixel * size.width() * size.height()],
NULL) {
}
BasicDesktopFrame::~BasicDesktopFrame() {
delete[] data_;
}
SharedMemoryDesktopFrame::SharedMemoryDesktopFrame(
DesktopSize size,
int stride,
SharedMemory* shared_memory)
: DesktopFrame(size, stride,
reinterpret_cast<uint8_t*>(shared_memory->data()),
shared_memory) {
}
SharedMemoryDesktopFrame::~SharedMemoryDesktopFrame() {
delete shared_memory_;
}
} // namespace webrtc

View File

@ -0,0 +1,106 @@
/*
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_FRAME_H_
#define WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_FRAME_H_
#include "webrtc/modules/desktop_capture/desktop_geometry.h"
#include "webrtc/modules/desktop_capture/desktop_region.h"
#include "webrtc/modules/desktop_capture/shared_memory.h"
#include "webrtc/typedefs.h"
namespace webrtc {
// DesktopFrame represents a video frame captured from the screen.
class DesktopFrame {
public:
// DesktopFrame objects always hold RGBA data.
static const int kBytesPerPixel = 4;
virtual ~DesktopFrame();
// Size of the frame.
const DesktopSize& size() const { return size_; }
// Distance in the buffer between two neighboring rows in bytes.
int stride() const { return stride_; }
// Data buffer used for the frame.
uint8_t* data() const { return data_; }
// SharedMemory used for the buffer or NULL if memory is allocated on the
// heap. The result is guaranteed to be deleted only after the frame is
// deleted (classes that inherit from DesktopFrame must ensure it).
SharedMemory* shared_memory() const { return shared_memory_; }
// Indicates region of the screen that has changed since the previous frame.
const DesktopRegion& updated_region() const { return updated_region_; }
DesktopRegion* mutable_updated_region() { return &updated_region_; }
// DPI of the screen being captured. May be set to zero, e.g. if DPI is
// unknown.
const DesktopVector& dpi() const { return dpi_; }
void set_dpi(const DesktopVector& dpi) { dpi_ = dpi; }
// Time taken to capture the frame in milliseconds.
int32_t capture_time_ms() const { return capture_time_ms_; }
void set_capture_time_ms(int32_t time_ms) { capture_time_ms_ = time_ms; }
protected:
DesktopFrame(DesktopSize size,
int stride,
uint8_t* data,
SharedMemory* shared_memory);
const DesktopSize size_;
const int stride_;
// Ownership of the buffers is defined by the classes that inherit from this
// class. They must guarantee that the buffer is not deleted before the frame
// is deleted.
uint8_t* const data_;
SharedMemory* const shared_memory_;
DesktopRegion updated_region_;
DesktopVector dpi_;
int32_t capture_time_ms_;
private:
DISALLOW_COPY_AND_ASSIGN(DesktopFrame);
};
// A DesktopFrame that stores data in the heap.
class BasicDesktopFrame : public DesktopFrame {
public:
explicit BasicDesktopFrame(DesktopSize size);
virtual ~BasicDesktopFrame();
private:
DISALLOW_COPY_AND_ASSIGN(BasicDesktopFrame);
};
// A DesktopFrame that stores data in shared memory.
class SharedMemoryDesktopFrame : public DesktopFrame {
public:
// Takes ownership of |shared_memory|.
SharedMemoryDesktopFrame(DesktopSize size,
int stride,
SharedMemory* shared_memory);
virtual ~SharedMemoryDesktopFrame();
private:
DISALLOW_COPY_AND_ASSIGN(SharedMemoryDesktopFrame);
};
} // namespace webrtc
#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_FRAME_H_

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/modules/desktop_capture/desktop_frame_win.h"
namespace webrtc {
DesktopFrameWin::DesktopFrameWin(DesktopSize size,
int stride,
uint8_t* data,
SharedMemory* shared_memory,
HBITMAP bitmap)
: DesktopFrame(size, stride, data, shared_memory),
bitmap_(bitmap),
owned_shared_memory_(shared_memory_) {
}
DesktopFrameWin::~DesktopFrameWin() {
DeleteObject(bitmap_);
}
// static
DesktopFrameWin* DesktopFrameWin::Create(DesktopSize size,
SharedMemory* shared_memory,
HDC hdc) {
int bytes_per_row = size.width() * kBytesPerPixel;
// Describe a device independent bitmap (DIB) that is the size of the desktop.
BITMAPINFO bmi = {0};
bmi.bmiHeader.biHeight = -size.height();
bmi.bmiHeader.biWidth = size.width();
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = DesktopFrameWin::kBytesPerPixel * 8;
bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
bmi.bmiHeader.biSizeImage = bytes_per_row * size.height();
HANDLE section_handle = NULL;
if (shared_memory)
section_handle = shared_memory->handle();
void* data = NULL;
HBITMAP bitmap = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, &data,
section_handle, 0);
if (!bitmap) {
delete shared_memory;
return NULL;
}
return new DesktopFrameWin(size, bytes_per_row,
reinterpret_cast<uint8_t*>(data),
shared_memory, bitmap);
}
} // namespace webrtc

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_FRAME_WIN_H_
#define WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_FRAME_WIN_H_
#include <windows.h>
#include "webrtc/modules/desktop_capture/desktop_frame.h"
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
#include "webrtc/typedefs.h"
namespace webrtc {
// DesktopFrame implementation used by screen and window captures on Windows.
// Frame data is stored in a GDI bitmap.
class DesktopFrameWin : public DesktopFrame {
public:
virtual ~DesktopFrameWin();
static DesktopFrameWin* Create(DesktopSize size,
SharedMemory* shared_memory,
HDC hdc);
HBITMAP bitmap() { return bitmap_; }
private:
DesktopFrameWin(DesktopSize size,
int stride,
uint8_t* data,
SharedMemory* shared_memory,
HBITMAP bitmap);
HBITMAP bitmap_;
scoped_ptr<SharedMemory> owned_shared_memory_;
DISALLOW_COPY_AND_ASSIGN(DesktopFrameWin);
};
} // namespace webrtc
#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_FRAME_WIN_H_

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/modules/desktop_capture/desktop_geometry.h"
#include <algorithm>
namespace webrtc {
void DesktopRect::IntersectWith(const DesktopRect& rect) {
left_ = std::max(left(), rect.left());
top_ = std::max(top(), rect.top());
right_ = std::min(right(), rect.right());
bottom_ = std::min(bottom(), rect.top());
if (is_empty()) {
left_ = 0;
top_ = 0;
right_ = 0;
bottom_ = 0;
}
}
void DesktopRect::Translate(int32_t dx, int32_t dy) {
left_ += dx;
top_ += dy;
right_ += dx;
bottom_ += dy;
}
} // namespace webrtc

View File

@ -0,0 +1,124 @@
/*
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_GEOMETRY_H_
#define WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_GEOMETRY_H_
#include "webrtc/typedefs.h"
#include "webrtc/system_wrappers/interface/constructor_magic.h"
namespace webrtc {
// A vector in the 2D integer space. E.g. can be used to represent screen DPI.
class DesktopVector {
public:
DesktopVector() : x_(0), y_(0) {}
DesktopVector(int32_t x, int32_t y) : x_(x), y_(y) {}
int32_t x() const { return x_; }
int32_t y() const { return y_; }
bool is_zero() const { return x_ == 0 && y_ == 0; }
bool equals(const DesktopVector& other) const {
return x_ == other.x_ && y_ == other.y_;
}
void set(int32_t x, int32_t y) {
x_ = x;
y_ = y;
}
private:
int32_t x_;
int32_t y_;
};
// Type used to represent screen/window size.
class DesktopSize {
public:
DesktopSize() : width_(0), height_(0) {}
DesktopSize(int32_t width, int32_t height)
: width_(width), height_(height) {
}
int32_t width() const { return width_; }
int32_t height() const { return height_; }
bool is_empty() const { return width_ <= 0 && height_ <= 0; }
bool equals(const DesktopSize& other) const {
return width_ == other.width_ && height_ == other.height_;
}
void set(int32_t width, int32_t height) {
width_ = width;
height_ = height;
}
private:
int32_t width_;
int32_t height_;
};
// Represents a rectangle on the screen.
class DesktopRect {
public:
static DesktopRect MakeSize(const DesktopSize& size) {
return DesktopRect(0, 0, size.width(), size.height());
}
static DesktopRect MakeWH(int32_t width, int32_t height) {
return DesktopRect(0, 0, width, height);
}
static DesktopRect MakeXYWH(int32_t x, int32_t y,
int32_t width, int32_t height) {
return DesktopRect(x, y, x + width, y + height);
}
static DesktopRect MakeLTRB(int32_t left, int32_t top,
int32_t right, int32_t bottom) {
return DesktopRect(left, top, right, bottom);
}
DesktopRect() : left_(0), top_(0), right_(0), bottom_(0) {}
int32_t left() const { return left_; }
int32_t top() const { return top_; }
int32_t right() const { return right_; }
int32_t bottom() const { return bottom_; }
int32_t width() const { return right_ - left_; }
int32_t height() const { return bottom_ - top_; }
bool is_empty() const { return left_ >= right_ || top_ >= bottom_; }
bool equals(const DesktopRect& other) const {
return left_ == other.left_ && top_ == other.top_ &&
right_ == other.right_ && bottom_ == other.bottom_;
}
// Finds intersection with |rect|.
void IntersectWith(const DesktopRect& rect);
// Adds (dx, dy) to the position of the rectangle.
void Translate(int32_t dx, int32_t dy);
private:
DesktopRect(int32_t left, int32_t top, int32_t right, int32_t bottom)
: left_(left), top_(top), right_(right), bottom_(bottom) {
}
int32_t left_;
int32_t top_;
int32_t right_;
int32_t bottom_;
};
} // namespace webrtc
#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_GEOMETRY_H_

View File

@ -0,0 +1,83 @@
/*
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/modules/desktop_capture/desktop_region.h"
namespace webrtc {
DesktopRegion::DesktopRegion() {}
DesktopRegion::DesktopRegion(const DesktopRegion& other)
: rects_(other.rects_) {
}
DesktopRegion::~DesktopRegion() {}
void DesktopRegion::Clear() {
rects_.clear();
}
void DesktopRegion::SetRect(const DesktopRect& rect) {
Clear();
AddRect(rect);
}
void DesktopRegion::AddRect(const DesktopRect& rect) {
if (!rect.is_empty())
rects_.push_back(rect);
}
void DesktopRegion::AddRegion(const DesktopRegion& region) {
for (Iterator it(region); !it.IsAtEnd(); it.Advance()) {
AddRect(it.rect());
}
}
void DesktopRegion::IntersectWith(const DesktopRect& rect) {
bool remove_empty_rects = false;
for (RectsList::iterator it = rects_.begin(); it != rects_.end(); ++it) {
it->IntersectWith(rect);
remove_empty_rects = remove_empty_rects | it->is_empty();
}
if (remove_empty_rects) {
RectsList new_rects(rects_.size());
for (RectsList::iterator it = rects_.begin(); it != rects_.end(); ++it) {
if (!it->is_empty())
new_rects.push_back(*it);
}
rects_.swap(new_rects);
}
}
void DesktopRegion::Translate(int32_t dx, int32_t dy) {
for (RectsList::iterator it = rects_.begin(); it != rects_.end(); ++it) {
it->Translate(dx, dy);
}
}
void DesktopRegion::Swap(DesktopRegion* region) {
rects_.swap(region->rects_);
}
DesktopRegion::Iterator::Iterator(const DesktopRegion& region)
: region_(region),
it_(region.rects_.begin()) {
}
bool DesktopRegion::Iterator::IsAtEnd() const {
return it_ == region_.rects_.end();
}
void DesktopRegion::Iterator::Advance() {
++it_;
}
} // namespace webrtc

View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_REGION_H_
#define WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_REGION_H_
#include <vector>
#include "webrtc/modules/desktop_capture/desktop_geometry.h"
#include "webrtc/system_wrappers/interface/constructor_magic.h"
#include "webrtc/typedefs.h"
namespace webrtc {
// DesktopRegion represents a region of the screen or window.
//
// TODO(sergeyu): Current implementation just stores list of rectangles that may
// overlap. Optimize it.
class DesktopRegion {
public:
// Iterator that can be used to iterate over rectangles of a DesktopRegion.
// The region must not be mutated while the iterator is used.
class Iterator {
public:
explicit Iterator(const DesktopRegion& target);
bool IsAtEnd() const;
void Advance();
const DesktopRect& rect() const { return *it_; }
private:
const DesktopRegion& region_;
std::vector<DesktopRect>::const_iterator it_;
};
DesktopRegion();
DesktopRegion(const DesktopRegion& other);
~DesktopRegion();
bool is_empty() const { return rects_.empty(); }
void Clear();
void SetRect(const DesktopRect& rect);
void AddRect(const DesktopRect& rect);
void AddRegion(const DesktopRegion& region);
// Clips the region by the |rect|.
void IntersectWith(const DesktopRect& rect);
// Adds (dx, dy) to the position of the region.
void Translate(int32_t dx, int32_t dy);
void Swap(DesktopRegion* region);
private:
typedef std::vector<DesktopRect> RectsList;
RectsList rects_;
};
} // namespace webrtc
#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_REGION_H_

View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/modules/desktop_capture/shared_memory.h"
namespace webrtc {
#if defined(WEBRTC_WIN)
const SharedMemory::Handle SharedMemory::kInvalidHandle = NULL;
#else
const SharedMemory::Handle SharedMemory::kInvalidHandle = -1;
#endif
SharedMemory::SharedMemory(void* data, size_t size, Handle handle, int id)
: data_(data),
size_(size),
handle_(handle),
id_(id) {
}
} // namespace webrtc

View File

@ -0,0 +1,68 @@
/*
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_SHARED_MEMORY_H_
#define WEBRTC_MODULES_DESKTOP_CAPTURE_SHARED_MEMORY_H_
#include <stddef.h>
#if defined(WEBRTC_WIN)
#include <windows.h>
#endif
#include "webrtc/typedefs.h"
#include "webrtc/system_wrappers/interface/constructor_magic.h"
namespace webrtc {
// SharedMemory is a base class for shared memory. It stores all required
// parameters of the buffer, but doesn't have any logic to allocate or destroy
// the actual buffer. DesktopCapturer consumers that need to use shared memory
// for video frames must extend this class with creation and destruction logic
// specific for the target platform and then implement
// DesktopCapturer::Delegate::CreateSharedMemory() as appropriate.
class SharedMemory {
public:
#if defined(WEBRTC_WIN)
typedef HANDLE Handle;
static const Handle kInvalidHandle;
#else
typedef int Handle;
static const Handle kInvalidHandle;
#endif
void* data() const { return data_; }
size_t size() const { return size_; }
// Platform-specific handle of the buffer.
Handle handle() const { return handle_; }
// Integer identifier that can be used used by consumers of DesktopCapturer
// interface to identify shared memory buffers it created.
int id() const { return id_; }
virtual ~SharedMemory() {}
protected:
SharedMemory(void* data, size_t size, Handle handle, int id);
void* const data_;
const size_t size_;
const Handle handle_;
const int id_;
private:
DISALLOW_COPY_AND_ASSIGN(SharedMemory);
};
} // namespace webrtc
#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_SHARED_MEMORY_H_

View File

@ -23,6 +23,7 @@
'audio_device/audio_device.gypi',
'audio_processing/audio_processing.gypi',
'bitrate_controller/bitrate_controller.gypi',
'desktop_capture/desktop_capture.gypi',
'media_file/source/media_file.gypi',
'pacing/pacing.gypi',
'remote_bitrate_estimator/remote_bitrate_estimator.gypi',