ACodecBufferChannel.cpp revision de7268d8e20b883ec88a7ff19ad560a665373484
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 "ACodecBufferChannel"
19#include <utils/Log.h>
20
21#include <numeric>
22
23#include <android/media/IDescrambler.h>
24#include <binder/MemoryDealer.h>
25#include <media/openmax/OMX_Core.h>
26#include <media/stagefright/foundation/AMessage.h>
27#include <media/stagefright/foundation/AUtils.h>
28#include <media/stagefright/MediaCodec.h>
29#include <media/MediaCodecBuffer.h>
30#include <system/window.h>
31
32#include "include/ACodecBufferChannel.h"
33#include "include/SecureBuffer.h"
34#include "include/SharedMemoryBuffer.h"
35
36namespace android {
37using binder::Status;
38using MediaDescrambler::DescrambleInfo;
39using BufferInfo = ACodecBufferChannel::BufferInfo;
40using BufferInfoIterator = std::vector<const BufferInfo>::const_iterator;
41
42static BufferInfoIterator findClientBuffer(
43        const std::shared_ptr<const std::vector<const BufferInfo>> &array,
44        const sp<MediaCodecBuffer> &buffer) {
45    return std::find_if(
46            array->begin(), array->end(),
47            [buffer](const BufferInfo &info) { return info.mClientBuffer == buffer; });
48}
49
50static BufferInfoIterator findBufferId(
51        const std::shared_ptr<const std::vector<const BufferInfo>> &array,
52        IOMX::buffer_id bufferId) {
53    return std::find_if(
54            array->begin(), array->end(),
55            [bufferId](const BufferInfo &info) { return bufferId == info.mBufferId; });
56}
57
58ACodecBufferChannel::BufferInfo::BufferInfo(
59        const sp<MediaCodecBuffer> &buffer,
60        IOMX::buffer_id bufferId,
61        const sp<IMemory> &sharedEncryptedBuffer)
62    : mClientBuffer(
63          (sharedEncryptedBuffer == nullptr)
64          ? buffer
65          : new SharedMemoryBuffer(buffer->format(), sharedEncryptedBuffer)),
66      mCodecBuffer(buffer),
67      mBufferId(bufferId),
68      mSharedEncryptedBuffer(sharedEncryptedBuffer) {
69}
70
71ACodecBufferChannel::ACodecBufferChannel(
72        const sp<AMessage> &inputBufferFilled, const sp<AMessage> &outputBufferDrained)
73    : mInputBufferFilled(inputBufferFilled),
74      mOutputBufferDrained(outputBufferDrained) {
75}
76
77status_t ACodecBufferChannel::queueInputBuffer(const sp<MediaCodecBuffer> &buffer) {
78    std::shared_ptr<const std::vector<const BufferInfo>> array(
79            std::atomic_load(&mInputBuffers));
80    BufferInfoIterator it = findClientBuffer(array, buffer);
81    if (it == array->end()) {
82        return -ENOENT;
83    }
84    ALOGV("queueInputBuffer #%d", it->mBufferId);
85    sp<AMessage> msg = mInputBufferFilled->dup();
86    msg->setObject("buffer", it->mCodecBuffer);
87    msg->setInt32("buffer-id", it->mBufferId);
88    msg->post();
89    return OK;
90}
91
92status_t ACodecBufferChannel::queueSecureInputBuffer(
93        const sp<MediaCodecBuffer> &buffer, bool secure, const uint8_t *key,
94        const uint8_t *iv, CryptoPlugin::Mode mode, CryptoPlugin::Pattern pattern,
95        const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
96        AString *errorDetailMsg) {
97    if (!hasCryptoOrDescrambler()) {
98        return -ENOSYS;
99    }
100    std::shared_ptr<const std::vector<const BufferInfo>> array(
101            std::atomic_load(&mInputBuffers));
102    BufferInfoIterator it = findClientBuffer(array, buffer);
103    if (it == array->end()) {
104        return -ENOENT;
105    }
106
107    ICrypto::DestinationBuffer destination;
108    if (secure) {
109        sp<SecureBuffer> secureData =
110                static_cast<SecureBuffer *>(it->mCodecBuffer.get());
111        destination.mType = secureData->getDestinationType();
112        if (destination.mType != ICrypto::kDestinationTypeNativeHandle) {
113            return BAD_VALUE;
114        }
115        destination.mHandle =
116                static_cast<native_handle_t *>(secureData->getDestinationPointer());
117    } else {
118        destination.mType = ICrypto::kDestinationTypeSharedMemory;
119        destination.mSharedMemory = mDecryptDestination;
120    }
121
122    ssize_t result = -1;
123    if (mCrypto != NULL) {
124        result = mCrypto->decrypt(key, iv, mode, pattern,
125                    it->mSharedEncryptedBuffer, it->mClientBuffer->offset(),
126                    subSamples, numSubSamples, destination, errorDetailMsg);
127    } else {
128        DescrambleInfo descrambleInfo;
129        descrambleInfo.dstType = destination.mType ==
130                ICrypto::kDestinationTypeSharedMemory ?
131                DescrambleInfo::kDestinationTypeVmPointer :
132                DescrambleInfo::kDestinationTypeNativeHandle;
133        descrambleInfo.scramblingControl = key != NULL ?
134                (DescramblerPlugin::ScramblingControl)key[0] :
135                DescramblerPlugin::kScrambling_Unscrambled;
136        descrambleInfo.numSubSamples = numSubSamples;
137        descrambleInfo.subSamples = (DescramblerPlugin::SubSample *)subSamples;
138        descrambleInfo.srcMem = it->mSharedEncryptedBuffer;
139        descrambleInfo.srcOffset = 0;
140        descrambleInfo.dstPtr = NULL;
141        descrambleInfo.dstOffset = 0;
142
143        int32_t descrambleResult = -1;
144        Status status = mDescrambler->descramble(descrambleInfo, &descrambleResult);
145
146        if (status.isOk()) {
147            result = descrambleResult;
148        }
149
150        if (result < 0) {
151            ALOGE("descramble failed, exceptionCode=%d, err=%d, result=%zd",
152                    status.exceptionCode(), status.transactionError(), result);
153        } else {
154            ALOGV("descramble succeeded, result=%zd", result);
155        }
156
157        if (result > 0 && destination.mType == ICrypto::kDestinationTypeSharedMemory) {
158            memcpy(destination.mSharedMemory->pointer(),
159                    (uint8_t*)it->mSharedEncryptedBuffer->pointer(), result);
160        }
161    }
162
163    if (result < 0) {
164        return result;
165    }
166
167    if (destination.mType == ICrypto::kDestinationTypeSharedMemory) {
168        memcpy(it->mCodecBuffer->base(), destination.mSharedMemory->pointer(), result);
169    }
170
171    it->mCodecBuffer->setRange(0, result);
172
173    // Copy metadata from client to codec buffer.
174    it->mCodecBuffer->meta()->clear();
175    int64_t timeUs;
176    CHECK(it->mClientBuffer->meta()->findInt64("timeUs", &timeUs));
177    it->mCodecBuffer->meta()->setInt64("timeUs", timeUs);
178    int32_t eos;
179    if (it->mClientBuffer->meta()->findInt32("eos", &eos)) {
180        it->mCodecBuffer->meta()->setInt32("eos", eos);
181    }
182    int32_t csd;
183    if (it->mClientBuffer->meta()->findInt32("csd", &csd)) {
184        it->mCodecBuffer->meta()->setInt32("csd", csd);
185    }
186
187    ALOGV("queueSecureInputBuffer #%d", it->mBufferId);
188    sp<AMessage> msg = mInputBufferFilled->dup();
189    msg->setObject("buffer", it->mCodecBuffer);
190    msg->setInt32("buffer-id", it->mBufferId);
191    msg->post();
192    return OK;
193}
194
195status_t ACodecBufferChannel::renderOutputBuffer(
196        const sp<MediaCodecBuffer> &buffer, int64_t timestampNs) {
197    std::shared_ptr<const std::vector<const BufferInfo>> array(
198            std::atomic_load(&mOutputBuffers));
199    BufferInfoIterator it = findClientBuffer(array, buffer);
200    if (it == array->end()) {
201        return -ENOENT;
202    }
203
204    ALOGV("renderOutputBuffer #%d", it->mBufferId);
205    sp<AMessage> msg = mOutputBufferDrained->dup();
206    msg->setObject("buffer", buffer);
207    msg->setInt32("buffer-id", it->mBufferId);
208    msg->setInt32("render", true);
209    msg->setInt64("timestampNs", timestampNs);
210    msg->post();
211    return OK;
212}
213
214status_t ACodecBufferChannel::discardBuffer(const sp<MediaCodecBuffer> &buffer) {
215    std::shared_ptr<const std::vector<const BufferInfo>> array(
216            std::atomic_load(&mInputBuffers));
217    bool input = true;
218    BufferInfoIterator it = findClientBuffer(array, buffer);
219    if (it == array->end()) {
220        array = std::atomic_load(&mOutputBuffers);
221        input = false;
222        it = findClientBuffer(array, buffer);
223        if (it == array->end()) {
224            return -ENOENT;
225        }
226    }
227    ALOGV("discardBuffer #%d", it->mBufferId);
228    sp<AMessage> msg = input ? mInputBufferFilled->dup() : mOutputBufferDrained->dup();
229    msg->setObject("buffer", it->mCodecBuffer);
230    msg->setInt32("buffer-id", it->mBufferId);
231    msg->setInt32("discarded", true);
232    msg->post();
233    return OK;
234}
235
236void ACodecBufferChannel::getInputBufferArray(Vector<sp<MediaCodecBuffer>> *array) {
237    std::shared_ptr<const std::vector<const BufferInfo>> inputBuffers(
238            std::atomic_load(&mInputBuffers));
239    array->clear();
240    for (const BufferInfo &elem : *inputBuffers) {
241        array->push_back(elem.mClientBuffer);
242    }
243}
244
245void ACodecBufferChannel::getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) {
246    std::shared_ptr<const std::vector<const BufferInfo>> outputBuffers(
247            std::atomic_load(&mOutputBuffers));
248    array->clear();
249    for (const BufferInfo &elem : *outputBuffers) {
250        array->push_back(elem.mClientBuffer);
251    }
252}
253
254void ACodecBufferChannel::setInputBufferArray(const std::vector<BufferAndId> &array) {
255    if (hasCryptoOrDescrambler()) {
256        size_t totalSize = std::accumulate(
257                array.begin(), array.end(), 0u,
258                [alignment = MemoryDealer::getAllocationAlignment()]
259                (size_t sum, const BufferAndId& elem) {
260                    return sum + align(elem.mBuffer->capacity(), alignment);
261                });
262        size_t maxSize = std::accumulate(
263                array.begin(), array.end(), 0u,
264                [alignment = MemoryDealer::getAllocationAlignment()]
265                (size_t max, const BufferAndId& elem) {
266                    return std::max(max, align(elem.mBuffer->capacity(), alignment));
267                });
268        mDealer = new MemoryDealer(totalSize + maxSize, "ACodecBufferChannel");
269        mDecryptDestination = mDealer->allocate(maxSize);
270    }
271    std::vector<const BufferInfo> inputBuffers;
272    for (const BufferAndId &elem : array) {
273        sp<IMemory> sharedEncryptedBuffer;
274        if (hasCryptoOrDescrambler()) {
275            sharedEncryptedBuffer = mDealer->allocate(elem.mBuffer->capacity());
276        }
277        inputBuffers.emplace_back(elem.mBuffer, elem.mBufferId, sharedEncryptedBuffer);
278    }
279    std::atomic_store(
280            &mInputBuffers,
281            std::make_shared<const std::vector<const BufferInfo>>(inputBuffers));
282}
283
284void ACodecBufferChannel::setOutputBufferArray(const std::vector<BufferAndId> &array) {
285    std::vector<const BufferInfo> outputBuffers;
286    for (const BufferAndId &elem : array) {
287        outputBuffers.emplace_back(elem.mBuffer, elem.mBufferId, nullptr);
288    }
289    std::atomic_store(
290            &mOutputBuffers,
291            std::make_shared<const std::vector<const BufferInfo>>(outputBuffers));
292}
293
294void ACodecBufferChannel::fillThisBuffer(IOMX::buffer_id bufferId) {
295    ALOGV("fillThisBuffer #%d", bufferId);
296    std::shared_ptr<const std::vector<const BufferInfo>> array(
297            std::atomic_load(&mInputBuffers));
298    BufferInfoIterator it = findBufferId(array, bufferId);
299
300    if (it == array->end()) {
301        ALOGE("fillThisBuffer: unrecognized buffer #%d", bufferId);
302        return;
303    }
304    if (it->mClientBuffer != it->mCodecBuffer) {
305        it->mClientBuffer->setFormat(it->mCodecBuffer->format());
306    }
307
308    mCallback->onInputBufferAvailable(
309            std::distance(array->begin(), it),
310            it->mClientBuffer);
311}
312
313void ACodecBufferChannel::drainThisBuffer(
314        IOMX::buffer_id bufferId,
315        OMX_U32 omxFlags) {
316    ALOGV("drainThisBuffer #%d", bufferId);
317    std::shared_ptr<const std::vector<const BufferInfo>> array(
318            std::atomic_load(&mOutputBuffers));
319    BufferInfoIterator it = findBufferId(array, bufferId);
320
321    if (it == array->end()) {
322        ALOGE("drainThisBuffer: unrecognized buffer #%d", bufferId);
323        return;
324    }
325    if (it->mClientBuffer != it->mCodecBuffer) {
326        it->mClientBuffer->setFormat(it->mCodecBuffer->format());
327    }
328
329    uint32_t flags = 0;
330    if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) {
331        flags |= MediaCodec::BUFFER_FLAG_SYNCFRAME;
332    }
333    if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
334        flags |= MediaCodec::BUFFER_FLAG_CODECCONFIG;
335    }
336    if (omxFlags & OMX_BUFFERFLAG_EOS) {
337        flags |= MediaCodec::BUFFER_FLAG_EOS;
338    }
339    it->mClientBuffer->meta()->setInt32("flags", flags);
340
341    mCallback->onOutputBufferAvailable(
342            std::distance(array->begin(), it),
343            it->mClientBuffer);
344}
345
346}  // namespace android
347