ACodecBufferChannel.cpp revision aaa5e6400d7654ca1a7dcebeba36214ed060e3cb
1572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams/*
2572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams * Copyright 2016, The Android Open Source Project
3572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams *
4572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams * Licensed under the Apache License, Version 2.0 (the "License");
5572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams * you may not use this file except in compliance with the License.
6572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams * You may obtain a copy of the License at
7572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams *
8572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams *     http://www.apache.org/licenses/LICENSE-2.0
9572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams *
10572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams * Unless required by applicable law or agreed to in writing, software
11572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams * distributed under the License is distributed on an "AS IS" BASIS,
12572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams * See the License for the specific language governing permissions and
14572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams * limitations under the License.
15572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams */
16572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
17572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams//#define LOG_NDEBUG 0
18572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#define LOG_TAG "ACodecBufferChannel"
19572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#include <utils/Log.h>
20572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
21572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#include <numeric>
22572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
23572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#include <android/media/IDescrambler.h>
24572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#include <binder/MemoryDealer.h>
25572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#include <media/openmax/OMX_Core.h>
26572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#include <media/stagefright/foundation/AMessage.h>
27572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#include <media/stagefright/foundation/AUtils.h>
28572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#include <media/stagefright/MediaCodec.h>
29572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#include <media/MediaCodecBuffer.h>
30572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#include <system/window.h>
31572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
32572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#include "include/ACodecBufferChannel.h"
33f1d97e536561b4731997c85873dde3b3fb721cb2Stephen Hines#include "include/SecureBuffer.h"
34572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#include "include/SharedMemoryBuffer.h"
35572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
36572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsnamespace android {
37572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsusing binder::Status;
38572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsusing MediaDescrambler::DescrambleInfo;
39572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsusing BufferInfo = ACodecBufferChannel::BufferInfo;
40572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsusing 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
287status_t 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        if (elem.mBuffer->data() == NULL && sharedEncryptedBuffer == NULL) {
315            return BAD_VALUE;
316        }
317        inputBuffers.emplace_back(elem.mBuffer, elem.mBufferId, sharedEncryptedBuffer);
318    }
319    std::atomic_store(
320            &mInputBuffers,
321            std::make_shared<const std::vector<const BufferInfo>>(inputBuffers));
322    return OK;
323}
324
325void ACodecBufferChannel::setOutputBufferArray(const std::vector<BufferAndId> &array) {
326    std::vector<const BufferInfo> outputBuffers;
327    for (const BufferAndId &elem : array) {
328        outputBuffers.emplace_back(elem.mBuffer, elem.mBufferId, nullptr);
329    }
330    std::atomic_store(
331            &mOutputBuffers,
332            std::make_shared<const std::vector<const BufferInfo>>(outputBuffers));
333}
334
335void ACodecBufferChannel::fillThisBuffer(IOMX::buffer_id bufferId) {
336    ALOGV("fillThisBuffer #%d", bufferId);
337    std::shared_ptr<const std::vector<const BufferInfo>> array(
338            std::atomic_load(&mInputBuffers));
339    BufferInfoIterator it = findBufferId(array, bufferId);
340
341    if (it == array->end()) {
342        ALOGE("fillThisBuffer: unrecognized buffer #%d", bufferId);
343        return;
344    }
345    if (it->mClientBuffer != it->mCodecBuffer) {
346        it->mClientBuffer->setFormat(it->mCodecBuffer->format());
347    }
348
349    mCallback->onInputBufferAvailable(
350            std::distance(array->begin(), it),
351            it->mClientBuffer);
352}
353
354void ACodecBufferChannel::drainThisBuffer(
355        IOMX::buffer_id bufferId,
356        OMX_U32 omxFlags) {
357    ALOGV("drainThisBuffer #%d", bufferId);
358    std::shared_ptr<const std::vector<const BufferInfo>> array(
359            std::atomic_load(&mOutputBuffers));
360    BufferInfoIterator it = findBufferId(array, bufferId);
361
362    if (it == array->end()) {
363        ALOGE("drainThisBuffer: unrecognized buffer #%d", bufferId);
364        return;
365    }
366    if (it->mClientBuffer != it->mCodecBuffer) {
367        it->mClientBuffer->setFormat(it->mCodecBuffer->format());
368    }
369
370    uint32_t flags = 0;
371    if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) {
372        flags |= MediaCodec::BUFFER_FLAG_SYNCFRAME;
373    }
374    if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
375        flags |= MediaCodec::BUFFER_FLAG_CODECCONFIG;
376    }
377    if (omxFlags & OMX_BUFFERFLAG_EOS) {
378        flags |= MediaCodec::BUFFER_FLAG_EOS;
379    }
380    it->mClientBuffer->meta()->setInt32("flags", flags);
381
382    mCallback->onOutputBufferAvailable(
383            std::distance(array->begin(), it),
384            it->mClientBuffer);
385}
386
387}  // namespace android
388