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