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/hardware/cas/native/1.0/IDescrambler.h>
24#include <binder/MemoryDealer.h>
25#include <hidlmemory/FrameworkUtils.h>
26#include <media/openmax/OMX_Core.h>
27#include <media/stagefright/foundation/AMessage.h>
28#include <media/stagefright/foundation/AUtils.h>
29#include <media/stagefright/MediaCodec.h>
30#include <media/MediaCodecBuffer.h>
31#include <system/window.h>
32
33#include "include/ACodecBufferChannel.h"
34#include "include/SecureBuffer.h"
35#include "include/SharedMemoryBuffer.h"
36
37namespace android {
38using hardware::fromHeap;
39using hardware::hidl_handle;
40using hardware::hidl_string;
41using hardware::hidl_vec;
42using namespace hardware::cas::V1_0;
43using namespace hardware::cas::native::V1_0;
44using BufferInfo = ACodecBufferChannel::BufferInfo;
45using BufferInfoIterator = std::vector<const BufferInfo>::const_iterator;
46
47ACodecBufferChannel::~ACodecBufferChannel() {
48    if (mCrypto != nullptr && mDealer != nullptr && mHeapSeqNum >= 0) {
49        mCrypto->unsetHeap(mHeapSeqNum);
50    }
51}
52
53static BufferInfoIterator findClientBuffer(
54        const std::shared_ptr<const std::vector<const BufferInfo>> &array,
55        const sp<MediaCodecBuffer> &buffer) {
56    return std::find_if(
57            array->begin(), array->end(),
58            [buffer](const BufferInfo &info) { return info.mClientBuffer == buffer; });
59}
60
61static BufferInfoIterator findBufferId(
62        const std::shared_ptr<const std::vector<const BufferInfo>> &array,
63        IOMX::buffer_id bufferId) {
64    return std::find_if(
65            array->begin(), array->end(),
66            [bufferId](const BufferInfo &info) { return bufferId == info.mBufferId; });
67}
68
69ACodecBufferChannel::BufferInfo::BufferInfo(
70        const sp<MediaCodecBuffer> &buffer,
71        IOMX::buffer_id bufferId,
72        const sp<IMemory> &sharedEncryptedBuffer)
73    : mClientBuffer(
74          (sharedEncryptedBuffer == nullptr)
75          ? buffer
76          : new SharedMemoryBuffer(buffer->format(), sharedEncryptedBuffer)),
77      mCodecBuffer(buffer),
78      mBufferId(bufferId),
79      mSharedEncryptedBuffer(sharedEncryptedBuffer) {
80}
81
82ACodecBufferChannel::ACodecBufferChannel(
83        const sp<AMessage> &inputBufferFilled, const sp<AMessage> &outputBufferDrained)
84    : mInputBufferFilled(inputBufferFilled),
85      mOutputBufferDrained(outputBufferDrained),
86      mHeapSeqNum(-1) {
87}
88
89status_t ACodecBufferChannel::queueInputBuffer(const sp<MediaCodecBuffer> &buffer) {
90    if (mDealer != nullptr) {
91        return -ENOSYS;
92    }
93    std::shared_ptr<const std::vector<const BufferInfo>> array(
94            std::atomic_load(&mInputBuffers));
95    BufferInfoIterator it = findClientBuffer(array, buffer);
96    if (it == array->end()) {
97        return -ENOENT;
98    }
99    ALOGV("queueInputBuffer #%d", it->mBufferId);
100    sp<AMessage> msg = mInputBufferFilled->dup();
101    msg->setObject("buffer", it->mCodecBuffer);
102    msg->setInt32("buffer-id", it->mBufferId);
103    msg->post();
104    return OK;
105}
106
107status_t ACodecBufferChannel::queueSecureInputBuffer(
108        const sp<MediaCodecBuffer> &buffer, bool secure, const uint8_t *key,
109        const uint8_t *iv, CryptoPlugin::Mode mode, CryptoPlugin::Pattern pattern,
110        const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
111        AString *errorDetailMsg) {
112    if (!hasCryptoOrDescrambler() || mDealer == nullptr) {
113        return -ENOSYS;
114    }
115    std::shared_ptr<const std::vector<const BufferInfo>> array(
116            std::atomic_load(&mInputBuffers));
117    BufferInfoIterator it = findClientBuffer(array, buffer);
118    if (it == array->end()) {
119        return -ENOENT;
120    }
121
122    native_handle_t *secureHandle = NULL;
123    if (secure) {
124        sp<SecureBuffer> secureData =
125                static_cast<SecureBuffer *>(it->mCodecBuffer.get());
126        if (secureData->getDestinationType() != ICrypto::kDestinationTypeNativeHandle) {
127            return BAD_VALUE;
128        }
129        secureHandle = static_cast<native_handle_t *>(secureData->getDestinationPointer());
130    }
131    ssize_t result = -1;
132    if (mCrypto != NULL) {
133        ICrypto::DestinationBuffer destination;
134        if (secure) {
135            destination.mType = ICrypto::kDestinationTypeNativeHandle;
136            destination.mHandle = secureHandle;
137        } else {
138            destination.mType = ICrypto::kDestinationTypeSharedMemory;
139            destination.mSharedMemory = mDecryptDestination;
140        }
141
142        ICrypto::SourceBuffer source;
143        source.mSharedMemory = it->mSharedEncryptedBuffer;
144        source.mHeapSeqNum = mHeapSeqNum;
145
146        result = mCrypto->decrypt(key, iv, mode, pattern,
147                source, it->mClientBuffer->offset(),
148                subSamples, numSubSamples, destination, errorDetailMsg);
149
150        if (result < 0) {
151            return result;
152        }
153
154        if (destination.mType == ICrypto::kDestinationTypeSharedMemory) {
155            memcpy(it->mCodecBuffer->base(), destination.mSharedMemory->pointer(), result);
156        }
157    } else {
158        // Here we cast CryptoPlugin::SubSample to hardware::cas::native::V1_0::SubSample
159        // directly, the structure definitions should match as checked in DescramblerImpl.cpp.
160        hidl_vec<SubSample> hidlSubSamples;
161        hidlSubSamples.setToExternal((SubSample *)subSamples, numSubSamples, false /*own*/);
162
163        ssize_t offset;
164        size_t size;
165        it->mSharedEncryptedBuffer->getMemory(&offset, &size);
166        hardware::cas::native::V1_0::SharedBuffer srcBuffer = {
167                .heapBase = *mHidlMemory,
168                .offset = (uint64_t) offset,
169                .size = size
170        };
171
172        DestinationBuffer dstBuffer;
173        if (secure) {
174            dstBuffer.type = BufferType::NATIVE_HANDLE;
175            dstBuffer.secureMemory = hidl_handle(secureHandle);
176        } else {
177            dstBuffer.type = BufferType::SHARED_MEMORY;
178            dstBuffer.nonsecureMemory = srcBuffer;
179        }
180
181        Status status = Status::OK;
182        hidl_string detailedError;
183
184        auto returnVoid = mDescrambler->descramble(
185                key != NULL ? (ScramblingControl)key[0] : ScramblingControl::UNSCRAMBLED,
186                hidlSubSamples,
187                srcBuffer,
188                0,
189                dstBuffer,
190                0,
191                [&status, &result, &detailedError] (
192                        Status _status, uint32_t _bytesWritten,
193                        const hidl_string& _detailedError) {
194                    status = _status;
195                    result = (ssize_t)_bytesWritten;
196                    detailedError = _detailedError;
197                });
198
199        if (!returnVoid.isOk() || status != Status::OK || result < 0) {
200            ALOGE("descramble failed, trans=%s, status=%d, result=%zd",
201                    returnVoid.description().c_str(), status, result);
202            return UNKNOWN_ERROR;
203        }
204
205        ALOGV("descramble succeeded, %zd bytes", result);
206
207        if (dstBuffer.type == BufferType::SHARED_MEMORY) {
208            memcpy(it->mCodecBuffer->base(),
209                    (uint8_t*)it->mSharedEncryptedBuffer->pointer(), result);
210        }
211    }
212
213    it->mCodecBuffer->setRange(0, result);
214
215    // Copy metadata from client to codec buffer.
216    it->mCodecBuffer->meta()->clear();
217    int64_t timeUs;
218    CHECK(it->mClientBuffer->meta()->findInt64("timeUs", &timeUs));
219    it->mCodecBuffer->meta()->setInt64("timeUs", timeUs);
220    int32_t eos;
221    if (it->mClientBuffer->meta()->findInt32("eos", &eos)) {
222        it->mCodecBuffer->meta()->setInt32("eos", eos);
223    }
224    int32_t csd;
225    if (it->mClientBuffer->meta()->findInt32("csd", &csd)) {
226        it->mCodecBuffer->meta()->setInt32("csd", csd);
227    }
228
229    ALOGV("queueSecureInputBuffer #%d", it->mBufferId);
230    sp<AMessage> msg = mInputBufferFilled->dup();
231    msg->setObject("buffer", it->mCodecBuffer);
232    msg->setInt32("buffer-id", it->mBufferId);
233    msg->post();
234    return OK;
235}
236
237status_t ACodecBufferChannel::renderOutputBuffer(
238        const sp<MediaCodecBuffer> &buffer, int64_t timestampNs) {
239    std::shared_ptr<const std::vector<const BufferInfo>> array(
240            std::atomic_load(&mOutputBuffers));
241    BufferInfoIterator it = findClientBuffer(array, buffer);
242    if (it == array->end()) {
243        return -ENOENT;
244    }
245
246    ALOGV("renderOutputBuffer #%d", it->mBufferId);
247    sp<AMessage> msg = mOutputBufferDrained->dup();
248    msg->setObject("buffer", buffer);
249    msg->setInt32("buffer-id", it->mBufferId);
250    msg->setInt32("render", true);
251    msg->setInt64("timestampNs", timestampNs);
252    msg->post();
253    return OK;
254}
255
256status_t ACodecBufferChannel::discardBuffer(const sp<MediaCodecBuffer> &buffer) {
257    std::shared_ptr<const std::vector<const BufferInfo>> array(
258            std::atomic_load(&mInputBuffers));
259    bool input = true;
260    BufferInfoIterator it = findClientBuffer(array, buffer);
261    if (it == array->end()) {
262        array = std::atomic_load(&mOutputBuffers);
263        input = false;
264        it = findClientBuffer(array, buffer);
265        if (it == array->end()) {
266            return -ENOENT;
267        }
268    }
269    ALOGV("discardBuffer #%d", it->mBufferId);
270    sp<AMessage> msg = input ? mInputBufferFilled->dup() : mOutputBufferDrained->dup();
271    msg->setObject("buffer", it->mCodecBuffer);
272    msg->setInt32("buffer-id", it->mBufferId);
273    msg->setInt32("discarded", true);
274    msg->post();
275    return OK;
276}
277
278void ACodecBufferChannel::getInputBufferArray(Vector<sp<MediaCodecBuffer>> *array) {
279    std::shared_ptr<const std::vector<const BufferInfo>> inputBuffers(
280            std::atomic_load(&mInputBuffers));
281    array->clear();
282    for (const BufferInfo &elem : *inputBuffers) {
283        array->push_back(elem.mClientBuffer);
284    }
285}
286
287void ACodecBufferChannel::getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) {
288    std::shared_ptr<const std::vector<const BufferInfo>> outputBuffers(
289            std::atomic_load(&mOutputBuffers));
290    array->clear();
291    for (const BufferInfo &elem : *outputBuffers) {
292        array->push_back(elem.mClientBuffer);
293    }
294}
295
296sp<MemoryDealer> ACodecBufferChannel::makeMemoryDealer(size_t heapSize) {
297    sp<MemoryDealer> dealer;
298    if (mDealer != nullptr && mCrypto != nullptr && mHeapSeqNum >= 0) {
299        mCrypto->unsetHeap(mHeapSeqNum);
300    }
301    dealer = new MemoryDealer(heapSize, "ACodecBufferChannel");
302    if (mCrypto != nullptr) {
303        int32_t seqNum = mCrypto->setHeap(dealer->getMemoryHeap());
304        if (seqNum >= 0) {
305            mHeapSeqNum = seqNum;
306            ALOGV("setHeap returned mHeapSeqNum=%d", mHeapSeqNum);
307        } else {
308            mHeapSeqNum = -1;
309            ALOGE("setHeap failed, setting mHeapSeqNum=-1");
310        }
311    } else if (mDescrambler != nullptr) {
312        sp<IMemoryHeap> heap = dealer->getMemoryHeap();
313        mHidlMemory = fromHeap(heap);
314        if (mHidlMemory != NULL) {
315            ALOGV("created hidl_memory for descrambler");
316        } else {
317            ALOGE("failed to create hidl_memory for descrambler");
318        }
319    }
320    return dealer;
321}
322
323void ACodecBufferChannel::setInputBufferArray(const std::vector<BufferAndId> &array) {
324    if (hasCryptoOrDescrambler()) {
325        size_t totalSize = std::accumulate(
326                array.begin(), array.end(), 0u,
327                [alignment = MemoryDealer::getAllocationAlignment()]
328                (size_t sum, const BufferAndId& elem) {
329                    return sum + align(elem.mBuffer->capacity(), alignment);
330                });
331        size_t maxSize = std::accumulate(
332                array.begin(), array.end(), 0u,
333                [alignment = MemoryDealer::getAllocationAlignment()]
334                (size_t max, const BufferAndId& elem) {
335                    return std::max(max, align(elem.mBuffer->capacity(), alignment));
336                });
337        size_t destinationBufferSize = maxSize;
338        size_t heapSize = totalSize + destinationBufferSize;
339        if (heapSize > 0) {
340            mDealer = makeMemoryDealer(heapSize);
341            mDecryptDestination = mDealer->allocate(destinationBufferSize);
342        }
343    }
344    std::vector<const BufferInfo> inputBuffers;
345    for (const BufferAndId &elem : array) {
346        sp<IMemory> sharedEncryptedBuffer;
347        if (hasCryptoOrDescrambler()) {
348            sharedEncryptedBuffer = mDealer->allocate(elem.mBuffer->capacity());
349        }
350        inputBuffers.emplace_back(elem.mBuffer, elem.mBufferId, sharedEncryptedBuffer);
351    }
352    std::atomic_store(
353            &mInputBuffers,
354            std::make_shared<const std::vector<const BufferInfo>>(inputBuffers));
355}
356
357void ACodecBufferChannel::setOutputBufferArray(const std::vector<BufferAndId> &array) {
358    std::vector<const BufferInfo> outputBuffers;
359    for (const BufferAndId &elem : array) {
360        outputBuffers.emplace_back(elem.mBuffer, elem.mBufferId, nullptr);
361    }
362    std::atomic_store(
363            &mOutputBuffers,
364            std::make_shared<const std::vector<const BufferInfo>>(outputBuffers));
365}
366
367void ACodecBufferChannel::fillThisBuffer(IOMX::buffer_id bufferId) {
368    ALOGV("fillThisBuffer #%d", bufferId);
369    std::shared_ptr<const std::vector<const BufferInfo>> array(
370            std::atomic_load(&mInputBuffers));
371    BufferInfoIterator it = findBufferId(array, bufferId);
372
373    if (it == array->end()) {
374        ALOGE("fillThisBuffer: unrecognized buffer #%d", bufferId);
375        return;
376    }
377    if (it->mClientBuffer != it->mCodecBuffer) {
378        it->mClientBuffer->setFormat(it->mCodecBuffer->format());
379    }
380
381    mCallback->onInputBufferAvailable(
382            std::distance(array->begin(), it),
383            it->mClientBuffer);
384}
385
386void ACodecBufferChannel::drainThisBuffer(
387        IOMX::buffer_id bufferId,
388        OMX_U32 omxFlags) {
389    ALOGV("drainThisBuffer #%d", bufferId);
390    std::shared_ptr<const std::vector<const BufferInfo>> array(
391            std::atomic_load(&mOutputBuffers));
392    BufferInfoIterator it = findBufferId(array, bufferId);
393
394    if (it == array->end()) {
395        ALOGE("drainThisBuffer: unrecognized buffer #%d", bufferId);
396        return;
397    }
398    if (it->mClientBuffer != it->mCodecBuffer) {
399        it->mClientBuffer->setFormat(it->mCodecBuffer->format());
400    }
401
402    uint32_t flags = 0;
403    if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) {
404        flags |= MediaCodec::BUFFER_FLAG_SYNCFRAME;
405    }
406    if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
407        flags |= MediaCodec::BUFFER_FLAG_CODECCONFIG;
408    }
409    if (omxFlags & OMX_BUFFERFLAG_EOS) {
410        flags |= MediaCodec::BUFFER_FLAG_EOS;
411    }
412    it->mClientBuffer->meta()->setInt32("flags", flags);
413
414    mCallback->onOutputBufferAvailable(
415            std::distance(array->begin(), it),
416            it->mClientBuffer);
417}
418
419}  // namespace android
420