Add I420Buffer::Copy method taking plane pointers as input.

BUG=None.

Review-Url: https://codereview.webrtc.org/2528153002
Cr-Commit-Position: refs/heads/master@{#15259}
This commit is contained in:
nisse 2016-11-28 03:47:52 -08:00 committed by Commit bot
parent e441bdb744
commit 2f58ec82fc
3 changed files with 89 additions and 74 deletions

View File

@ -151,16 +151,12 @@ TEST(TestVideoFrame, ShallowCopy) {
memset(buffer_y, 16, kSizeY);
memset(buffer_u, 8, kSizeU);
memset(buffer_v, 4, kSizeV);
// TODO(nisse): This new + Copy looks quite awkward. Consider adding
// an alternative I420Buffer::Create method.
VideoFrame frame1(
I420Buffer::Copy(*rtc::scoped_refptr<VideoFrameBuffer>(
new rtc::RefCountedObject<webrtc::WrappedI420Buffer>(
width, height,
buffer_y, stride_y,
buffer_u, stride_u,
buffer_v, stride_v,
rtc::Callback0<void>([](){})))),
I420Buffer::Copy(width, height,
buffer_y, stride_y,
buffer_u, stride_u,
buffer_v, stride_v),
kRotation, 0);
frame1.set_timestamp(timestamp);
frame1.set_ntp_time_ms(ntp_time_ms);

View File

@ -58,9 +58,6 @@ class VideoFrameBuffer : public rtc::RefCountInterface {
// Plain I420 buffer in standard memory.
class I420Buffer : public VideoFrameBuffer {
public:
I420Buffer(int width, int height);
I420Buffer(int width, int height, int stride_y, int stride_u, int stride_v);
static rtc::scoped_refptr<I420Buffer> Create(int width, int height);
static rtc::scoped_refptr<I420Buffer> Create(int width,
int height,
@ -68,6 +65,24 @@ class I420Buffer : public VideoFrameBuffer {
int stride_u,
int stride_v);
// Create a new buffer and copy the pixel data.
static rtc::scoped_refptr<I420Buffer> Copy(const VideoFrameBuffer& buffer);
static rtc::scoped_refptr<I420Buffer> Copy(
int width, int height,
const uint8_t* data_y, int stride_y,
const uint8_t* data_u, int stride_u,
const uint8_t* data_v, int stride_v);
// Returns a rotated versions of |src|. Native buffers are not
// supported. The reason this function doesn't return an I420Buffer,
// is that it returns |src| unchanged in case |rotation| is zero.
// TODO(nisse): Consider dropping the special handling of zero
// rotation, and leave any optimizing that case to the caller.
static rtc::scoped_refptr<VideoFrameBuffer> Rotate(
rtc::scoped_refptr<VideoFrameBuffer> src,
VideoRotation rotation);
// Sets all three planes to all zeros. Used to work around for
// quirks in memory checkers
// (https://bugs.chromium.org/p/libyuv/issues/detail?id=377) and
@ -95,9 +110,6 @@ class I420Buffer : public VideoFrameBuffer {
void* native_handle() const override;
rtc::scoped_refptr<VideoFrameBuffer> NativeToI420Buffer() override;
// Create a new buffer and copy the pixel data.
static rtc::scoped_refptr<I420Buffer> Copy(const VideoFrameBuffer& buffer);
// Scale the cropped area of |src| to the size of |this| buffer, and
// write the result into |this|.
void CropAndScaleFrom(const VideoFrameBuffer& src,
@ -133,14 +145,10 @@ class I420Buffer : public VideoFrameBuffer {
ScaleFrom(*src);
}
// Returns a rotated versions of |src|. Native buffers are not
// supported. The reason this function doesn't return an I420Buffer,
// is that it returns |src| unchanged in case |rotation| is zero.
static rtc::scoped_refptr<VideoFrameBuffer> Rotate(
rtc::scoped_refptr<VideoFrameBuffer> src,
VideoRotation rotation);
protected:
I420Buffer(int width, int height);
I420Buffer(int width, int height, int stride_y, int stride_u, int stride_v);
~I420Buffer() override;
private:

View File

@ -61,10 +61,12 @@ I420Buffer::I420Buffer(int width,
I420Buffer::~I420Buffer() {
}
// static
rtc::scoped_refptr<I420Buffer> I420Buffer::Create(int width, int height) {
return new rtc::RefCountedObject<I420Buffer>(width, height);
}
// static
rtc::scoped_refptr<I420Buffer> I420Buffer::Create(int width,
int height,
int stride_y,
@ -74,6 +76,67 @@ rtc::scoped_refptr<I420Buffer> I420Buffer::Create(int width,
width, height, stride_y, stride_u, stride_v);
}
// static
rtc::scoped_refptr<I420Buffer> I420Buffer::Copy(
const VideoFrameBuffer& source) {
return Copy(source.width(), source.height(),
source.DataY(), source.StrideY(),
source.DataU(), source.StrideU(),
source.DataV(), source.StrideV());
}
// static
rtc::scoped_refptr<I420Buffer> I420Buffer::Copy(
int width, int height,
const uint8_t* data_y, int stride_y,
const uint8_t* data_u, int stride_u,
const uint8_t* data_v, int stride_v) {
// Note: May use different strides than the input data.
rtc::scoped_refptr<I420Buffer> buffer = Create(width, height);
RTC_CHECK_EQ(0, libyuv::I420Copy(data_y, stride_y,
data_u, stride_u,
data_v, stride_v,
buffer->MutableDataY(), buffer->StrideY(),
buffer->MutableDataU(), buffer->StrideU(),
buffer->MutableDataV(), buffer->StrideV(),
width, height));
return buffer;
}
// static
rtc::scoped_refptr<VideoFrameBuffer> I420Buffer::Rotate(
rtc::scoped_refptr<VideoFrameBuffer> src,
VideoRotation rotation) {
RTC_CHECK(src->DataY());
RTC_CHECK(src->DataU());
RTC_CHECK(src->DataV());
if (rotation == webrtc::kVideoRotation_0) {
return src;
}
int rotated_width = src->width();
int rotated_height = src->height();
if (rotation == webrtc::kVideoRotation_90 ||
rotation == webrtc::kVideoRotation_270) {
std::swap(rotated_width, rotated_height);
}
rtc::scoped_refptr<webrtc::I420Buffer> buffer =
I420Buffer::Create(rotated_width, rotated_height);
RTC_CHECK_EQ(0, libyuv::I420Rotate(
src->DataY(), src->StrideY(),
src->DataU(), src->StrideU(),
src->DataV(), src->StrideV(),
buffer->MutableDataY(), buffer->StrideY(), buffer->MutableDataU(),
buffer->StrideU(), buffer->MutableDataV(), buffer->StrideV(),
src->width(), src->height(),
static_cast<libyuv::RotationMode>(rotation)));
return buffer;
}
void I420Buffer::InitializeData() {
memset(data_.get(), 0,
I420DataSize(height_, stride_y_, stride_u_, stride_v_));
@ -126,23 +189,6 @@ rtc::scoped_refptr<VideoFrameBuffer> I420Buffer::NativeToI420Buffer() {
return nullptr;
}
// static
rtc::scoped_refptr<I420Buffer> I420Buffer::Copy(
const VideoFrameBuffer& source) {
int width = source.width();
int height = source.height();
rtc::scoped_refptr<I420Buffer> target = I420Buffer::Create(width, height);
RTC_CHECK(libyuv::I420Copy(source.DataY(), source.StrideY(),
source.DataU(), source.StrideU(),
source.DataV(), source.StrideV(),
target->MutableDataY(), target->StrideY(),
target->MutableDataU(), target->StrideU(),
target->MutableDataV(), target->StrideV(),
width, height) == 0);
return target;
}
void I420Buffer::SetToBlack() {
RTC_CHECK(libyuv::I420Rect(MutableDataY(), StrideY(),
MutableDataU(), StrideU(),
@ -205,41 +251,6 @@ void I420Buffer::ScaleFrom(const VideoFrameBuffer& src) {
CropAndScaleFrom(src, 0, 0, src.width(), src.height());
}
// static
rtc::scoped_refptr<VideoFrameBuffer> I420Buffer::Rotate(
rtc::scoped_refptr<VideoFrameBuffer> src,
VideoRotation rotation) {
RTC_DCHECK(src->DataY());
RTC_DCHECK(src->DataU());
RTC_DCHECK(src->DataV());
if (rotation == webrtc::kVideoRotation_0) {
return src;
}
int rotated_width = src->width();
int rotated_height = src->height();
if (rotation == webrtc::kVideoRotation_90 ||
rotation == webrtc::kVideoRotation_270) {
std::swap(rotated_width, rotated_height);
}
rtc::scoped_refptr<webrtc::I420Buffer> buffer =
I420Buffer::Create(rotated_width, rotated_height);
int res = libyuv::I420Rotate(
src->DataY(), src->StrideY(),
src->DataU(), src->StrideU(),
src->DataV(), src->StrideV(),
buffer->MutableDataY(), buffer->StrideY(), buffer->MutableDataU(),
buffer->StrideU(), buffer->MutableDataV(), buffer->StrideV(),
src->width(), src->height(),
static_cast<libyuv::RotationMode>(rotation));
RTC_DCHECK_EQ(res, 0);
return buffer;
}
NativeHandleBuffer::NativeHandleBuffer(void* native_handle,
int width,
int height)