blob: bb3171768cc799fbc5f5f10d21de2dfc70b1bb14 [file] [log] [blame]
magjed712338e2017-05-11 05:11:57 -07001/*
2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "webrtc/api/video/video_frame_buffer.h"
12
magjedeaf4a1e2017-05-30 01:21:59 -070013#include "libyuv/convert.h"
magjed712338e2017-05-11 05:11:57 -070014#include "webrtc/api/video/i420_buffer.h"
15#include "webrtc/base/checks.h"
16
17namespace webrtc {
18
19namespace {
20
21// TODO(magjed): Remove this class. It is only used for providing a default
22// implementation of ToI420() until external clients are updated. ToI420() will
23// then be made pure virtual. This adapter adapts a VideoFrameBuffer (which is
magjedeaf4a1e2017-05-30 01:21:59 -070024// expected to be in I420 format) to I420BufferInterface. The reason this is
25// needed is because of the return type mismatch in NativeToI420Buffer (returns
26// VideoFrameBuffer) vs ToI420 (returns I420BufferInterface).
27class I420InterfaceAdapter : public I420BufferInterface {
magjed712338e2017-05-11 05:11:57 -070028 public:
magjedeaf4a1e2017-05-30 01:21:59 -070029 explicit I420InterfaceAdapter(rtc::scoped_refptr<VideoFrameBuffer> buffer)
magjed712338e2017-05-11 05:11:57 -070030 : buffer_(buffer) {}
31
magjed712338e2017-05-11 05:11:57 -070032 int width() const override { return buffer_->width(); }
33 int height() const override { return buffer_->height(); }
34
35 const uint8_t* DataY() const override { return buffer_->DataY(); }
36 const uint8_t* DataU() const override { return buffer_->DataU(); }
37 const uint8_t* DataV() const override { return buffer_->DataV(); }
38
39 int StrideY() const override { return buffer_->StrideY(); }
40 int StrideU() const override { return buffer_->StrideU(); }
41 int StrideV() const override { return buffer_->StrideV(); }
42
43 private:
44 rtc::scoped_refptr<VideoFrameBuffer> buffer_;
45};
46
47} // namespace
48
49// TODO(magjed): The default implementations in VideoFrameBuffer are provided in
50// order to support the deprecated interface until external clients are updated.
51// Remove once done.
52VideoFrameBuffer::Type VideoFrameBuffer::type() const {
53 return native_handle() ? Type::kNative : Type::kI420;
54}
55
56const uint8_t* VideoFrameBuffer::DataY() const {
57 return const_cast<VideoFrameBuffer*>(this)->GetI420()->DataY();
58}
59
60const uint8_t* VideoFrameBuffer::DataU() const {
61 return const_cast<VideoFrameBuffer*>(this)->GetI420()->DataU();
62}
63
64const uint8_t* VideoFrameBuffer::DataV() const {
65 return const_cast<VideoFrameBuffer*>(this)->GetI420()->DataV();
66}
67
68// Returns the number of bytes between successive rows for a given plane.
69int VideoFrameBuffer::StrideY() const {
70 return const_cast<VideoFrameBuffer*>(this)->GetI420()->StrideY();
71}
72
73int VideoFrameBuffer::StrideU() const {
74 return const_cast<VideoFrameBuffer*>(this)->GetI420()->StrideU();
75}
76
77int VideoFrameBuffer::StrideV() const {
78 return const_cast<VideoFrameBuffer*>(this)->GetI420()->StrideV();
79}
80
81void* VideoFrameBuffer::native_handle() const {
82 RTC_DCHECK(type() != Type::kNative);
83 return nullptr;
84}
85
86rtc::scoped_refptr<VideoFrameBuffer> VideoFrameBuffer::NativeToI420Buffer() {
87 return ToI420();
88}
89
magjedeaf4a1e2017-05-30 01:21:59 -070090rtc::scoped_refptr<I420BufferInterface> VideoFrameBuffer::ToI420() {
91 return new rtc::RefCountedObject<I420InterfaceAdapter>(NativeToI420Buffer());
magjed712338e2017-05-11 05:11:57 -070092}
93
magjedeaf4a1e2017-05-30 01:21:59 -070094rtc::scoped_refptr<I420BufferInterface> VideoFrameBuffer::GetI420() {
magjed712338e2017-05-11 05:11:57 -070095 RTC_CHECK(type() == Type::kI420);
magjedeaf4a1e2017-05-30 01:21:59 -070096 // TODO(magjed): static_cast to I420BufferInterface instead once external
97 // clients are updated.
98 return new rtc::RefCountedObject<I420InterfaceAdapter>(this);
magjed712338e2017-05-11 05:11:57 -070099}
100
magjedeaf4a1e2017-05-30 01:21:59 -0700101rtc::scoped_refptr<I444BufferInterface> VideoFrameBuffer::GetI444() {
magjed712338e2017-05-11 05:11:57 -0700102 RTC_CHECK(type() == Type::kI444);
magjedeaf4a1e2017-05-30 01:21:59 -0700103 return static_cast<I444BufferInterface*>(this);
magjed712338e2017-05-11 05:11:57 -0700104}
105
magjedeaf4a1e2017-05-30 01:21:59 -0700106VideoFrameBuffer::Type I420BufferInterface::type() const {
107 return Type::kI420;
magjed712338e2017-05-11 05:11:57 -0700108}
109
magjedeaf4a1e2017-05-30 01:21:59 -0700110int I420BufferInterface::ChromaWidth() const {
111 return (width() + 1) / 2;
magjed712338e2017-05-11 05:11:57 -0700112}
113
magjedeaf4a1e2017-05-30 01:21:59 -0700114int I420BufferInterface::ChromaHeight() const {
115 return (height() + 1) / 2;
116}
117
118rtc::scoped_refptr<I420BufferInterface> I420BufferInterface::ToI420() {
119 return this;
120}
121
122VideoFrameBuffer::Type I444BufferInterface::type() const {
123 return Type::kI444;
124}
125
126int I444BufferInterface::ChromaWidth() const {
127 return width();
128}
129
130int I444BufferInterface::ChromaHeight() const {
131 return height();
132}
133
134rtc::scoped_refptr<I420BufferInterface> I444BufferInterface::ToI420() {
135 rtc::scoped_refptr<I420Buffer> i420_buffer =
136 I420Buffer::Create(width(), height());
137 libyuv::I444ToI420(DataY(), StrideY(), DataU(), StrideU(), DataV(), StrideV(),
138 i420_buffer->MutableDataY(), i420_buffer->StrideY(),
139 i420_buffer->MutableDataU(), i420_buffer->StrideU(),
140 i420_buffer->MutableDataV(), i420_buffer->StrideV(),
141 width(), height());
142 return i420_buffer;
magjed712338e2017-05-11 05:11:57 -0700143}
144
145} // namespace webrtc