blob: 3fc442b217f47c9a732328f14f44adb287b14b30 [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
Magnus Jedvertf1e34832017-06-29 13:39:20 +000019namespace {
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
24// 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 {
28 public:
29 explicit I420InterfaceAdapter(const VideoFrameBuffer* buffer)
30 : buffer_(buffer) {}
31
32 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<const 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 GetI420()->DataY();
58}
59
60const uint8_t* VideoFrameBuffer::DataU() const {
61 return GetI420()->DataU();
62}
63
64const uint8_t* VideoFrameBuffer::DataV() const {
65 return GetI420()->DataV();
66}
67
68// Returns the number of bytes between successive rows for a given plane.
69int VideoFrameBuffer::StrideY() const {
70 return GetI420()->StrideY();
71}
72
73int VideoFrameBuffer::StrideU() const {
74 return GetI420()->StrideU();
75}
76
77int VideoFrameBuffer::StrideV() const {
78 return 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
90rtc::scoped_refptr<I420BufferInterface> VideoFrameBuffer::ToI420() {
91 return new rtc::RefCountedObject<I420InterfaceAdapter>(NativeToI420Buffer());
92}
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);
Magnus Jedvertf1e34832017-06-29 13:39:20 +000096 // 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
magjed3f075492017-06-01 10:02:26 -0700101rtc::scoped_refptr<const I420BufferInterface> VideoFrameBuffer::GetI420()
102 const {
103 RTC_CHECK(type() == Type::kI420);
Magnus Jedvertf1e34832017-06-29 13:39:20 +0000104 // TODO(magjed): static_cast to I420BufferInterface instead once external
105 // clients are updated.
106 return new rtc::RefCountedObject<I420InterfaceAdapter>(this);
magjed3f075492017-06-01 10:02:26 -0700107}
108
109I444BufferInterface* VideoFrameBuffer::GetI444() {
magjed712338e2017-05-11 05:11:57 -0700110 RTC_CHECK(type() == Type::kI444);
magjedeaf4a1e2017-05-30 01:21:59 -0700111 return static_cast<I444BufferInterface*>(this);
magjed712338e2017-05-11 05:11:57 -0700112}
113
magjed3f075492017-06-01 10:02:26 -0700114const I444BufferInterface* VideoFrameBuffer::GetI444() const {
115 RTC_CHECK(type() == Type::kI444);
116 return static_cast<const I444BufferInterface*>(this);
117}
118
magjedeaf4a1e2017-05-30 01:21:59 -0700119VideoFrameBuffer::Type I420BufferInterface::type() const {
120 return Type::kI420;
magjed712338e2017-05-11 05:11:57 -0700121}
122
magjedeaf4a1e2017-05-30 01:21:59 -0700123int I420BufferInterface::ChromaWidth() const {
124 return (width() + 1) / 2;
magjed712338e2017-05-11 05:11:57 -0700125}
126
magjedeaf4a1e2017-05-30 01:21:59 -0700127int I420BufferInterface::ChromaHeight() const {
128 return (height() + 1) / 2;
129}
130
131rtc::scoped_refptr<I420BufferInterface> I420BufferInterface::ToI420() {
132 return this;
133}
134
135VideoFrameBuffer::Type I444BufferInterface::type() const {
136 return Type::kI444;
137}
138
139int I444BufferInterface::ChromaWidth() const {
140 return width();
141}
142
143int I444BufferInterface::ChromaHeight() const {
144 return height();
145}
146
147rtc::scoped_refptr<I420BufferInterface> I444BufferInterface::ToI420() {
148 rtc::scoped_refptr<I420Buffer> i420_buffer =
149 I420Buffer::Create(width(), height());
150 libyuv::I444ToI420(DataY(), StrideY(), DataU(), StrideU(), DataV(), StrideV(),
151 i420_buffer->MutableDataY(), i420_buffer->StrideY(),
152 i420_buffer->MutableDataU(), i420_buffer->StrideU(),
153 i420_buffer->MutableDataV(), i420_buffer->StrideV(),
154 width(), height());
155 return i420_buffer;
magjed712338e2017-05-11 05:11:57 -0700156}
157
158} // namespace webrtc