BufferImpl.cpp revision a5a96828cf0791b9342e4edbb3f2b2c4760c5020
1/*
2 * Copyright 2016, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "BufferImpl"
19#include <utils/Log.h>
20
21#include <binder/IMemory.h>
22#include <media/stagefright/foundation/ABuffer.h>
23#include <media/stagefright/foundation/AMessage.h>
24#include <media/ICrypto.h>
25#include <utils/NativeHandle.h>
26
27#include "include/Codec2Buffer.h"
28#include "include/SecureBuffer.h"
29#include "include/SharedMemoryBuffer.h"
30
31namespace android {
32
33// SharedMemoryBuffer
34
35SharedMemoryBuffer::SharedMemoryBuffer(const sp<AMessage> &format, const sp<IMemory> &mem)
36    : MediaCodecBuffer(format, new ABuffer(mem->pointer(), mem->size())),
37      mMemory(mem) {
38}
39
40SharedMemoryBuffer::SharedMemoryBuffer(const sp<AMessage> &format, const sp<TMemory> &mem)
41    : MediaCodecBuffer(format, new ABuffer(mem->getPointer(), mem->getSize())),
42      mTMemory(mem) {
43}
44
45// SecureBuffer
46
47SecureBuffer::SecureBuffer(const sp<AMessage> &format, const void *ptr, size_t size)
48    : MediaCodecBuffer(format, new ABuffer(nullptr, size)),
49      mPointer(ptr) {
50}
51
52SecureBuffer::SecureBuffer(
53        const sp<AMessage> &format, const sp<NativeHandle> &handle, size_t size)
54    : MediaCodecBuffer(format, new ABuffer(nullptr, size)),
55      mPointer(nullptr),
56      mHandle(handle) {
57}
58
59void *SecureBuffer::getDestinationPointer() {
60    return (void *)(mHandle == nullptr ? mPointer : mHandle->handle());
61}
62
63ICrypto::DestinationType SecureBuffer::getDestinationType() {
64    return ICrypto::kDestinationTypeNativeHandle;
65}
66
67// Codec2Buffer
68
69bool Codec2Buffer::canCopyLinear(const std::shared_ptr<C2Buffer> &buffer) const {
70    if (const_cast<Codec2Buffer *>(this)->base() == nullptr) {
71        return false;
72    }
73    if (buffer->data().type() != C2BufferData::LINEAR) {
74        return false;
75    }
76    if (buffer->data().linearBlocks().size() == 0u) {
77        // Nothing to copy, so we can copy by doing nothing.
78        return true;
79    } else if (buffer->data().linearBlocks().size() > 1u) {
80        // We don't know how to copy more than one blocks.
81        return false;
82    }
83    if (buffer->data().linearBlocks()[0].size() > capacity()) {
84        // It won't fit.
85        return false;
86    }
87    return true;
88}
89
90bool Codec2Buffer::copyLinear(const std::shared_ptr<C2Buffer> &buffer) {
91    // We assume that all canCopyLinear() checks passed.
92    if (buffer->data().linearBlocks().size() == 0u) {
93        setRange(0, 0);
94        return true;
95    }
96    C2ReadView view = buffer->data().linearBlocks()[0].map().get();
97    if (view.error() != C2_OK) {
98        ALOGD("Error while mapping: %d", view.error());
99        return false;
100    }
101    if (view.capacity() > capacity()) {
102        ALOGD("C2ConstLinearBlock lied --- it actually doesn't fit: view(%u) > this(%zu)",
103                view.capacity(), capacity());
104        return false;
105    }
106    memcpy(base(), view.data(), view.capacity());
107    setRange(0, view.capacity());
108    return true;
109}
110
111// LocalLinearBuffer
112
113bool LocalLinearBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
114    return canCopyLinear(buffer);
115}
116
117bool LocalLinearBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
118    return copyLinear(buffer);
119}
120
121// DummyContainerBuffer
122
123DummyContainerBuffer::DummyContainerBuffer(
124        const sp<AMessage> &format, const std::shared_ptr<C2Buffer> &buffer)
125    : Codec2Buffer(format, new ABuffer(nullptr, 1)),
126      mBufferRef(buffer) {
127    setRange(0, buffer ? 1 : 0);
128}
129
130std::shared_ptr<C2Buffer> DummyContainerBuffer::asC2Buffer() {
131    return std::move(mBufferRef);
132}
133
134bool DummyContainerBuffer::canCopy(const std::shared_ptr<C2Buffer> &) const {
135    return !mBufferRef;
136}
137
138bool DummyContainerBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
139    mBufferRef = buffer;
140    setRange(0, mBufferRef ? 1 : 0);
141    return true;
142}
143
144// LinearBlockBuffer
145
146// static
147sp<LinearBlockBuffer> LinearBlockBuffer::Allocate(
148        const sp<AMessage> &format, const std::shared_ptr<C2LinearBlock> &block) {
149    C2WriteView writeView(block->map().get());
150    if (writeView.error() != C2_OK) {
151        return nullptr;
152    }
153    return new LinearBlockBuffer(format, std::move(writeView), block);
154}
155
156std::shared_ptr<C2Buffer> LinearBlockBuffer::asC2Buffer() {
157    return C2Buffer::CreateLinearBuffer(mBlock->share(offset(), size(), C2Fence()));
158}
159
160bool LinearBlockBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
161    return canCopyLinear(buffer);
162}
163
164bool LinearBlockBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
165    return copyLinear(buffer);
166}
167
168LinearBlockBuffer::LinearBlockBuffer(
169        const sp<AMessage> &format,
170        C2WriteView&& writeView,
171        const std::shared_ptr<C2LinearBlock> &block)
172    : Codec2Buffer(format, new ABuffer(writeView.data(), writeView.size())),
173      mWriteView(writeView),
174      mBlock(block) {
175}
176
177// ConstLinearBlockBuffer
178
179// static
180sp<ConstLinearBlockBuffer> ConstLinearBlockBuffer::Allocate(
181        const sp<AMessage> &format, const std::shared_ptr<C2Buffer> &buffer) {
182    if (!buffer
183            || buffer->data().type() != C2BufferData::LINEAR
184            || buffer->data().linearBlocks().size() != 1u) {
185        return nullptr;
186    }
187    C2ReadView readView(buffer->data().linearBlocks()[0].map().get());
188    if (readView.error() != C2_OK) {
189        return nullptr;
190    }
191    return new ConstLinearBlockBuffer(format, std::move(readView), buffer);
192}
193
194ConstLinearBlockBuffer::ConstLinearBlockBuffer(
195        const sp<AMessage> &format,
196        C2ReadView&& readView,
197        const std::shared_ptr<C2Buffer> &buffer)
198    : Codec2Buffer(format, new ABuffer(
199            // NOTE: ABuffer only takes non-const pointer but this data is
200            //       supposed to be read-only.
201            const_cast<uint8_t *>(readView.data()), readView.capacity())),
202      mReadView(readView),
203      mBufferRef(buffer) {
204}
205
206std::shared_ptr<C2Buffer> ConstLinearBlockBuffer::asC2Buffer() {
207    return std::move(mBufferRef);
208}
209
210}  // namespace android
211