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