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 
36 namespace android {
37 using binder::Status;
38 using MediaDescrambler::DescrambleInfo;
39 using BufferInfo = ACodecBufferChannel::BufferInfo;
40 using BufferInfoIterator = std::vector<const BufferInfo>::const_iterator;
41 
~ACodecBufferChannel()42 ACodecBufferChannel::~ACodecBufferChannel() {
43     if (mCrypto != nullptr && mDealer != nullptr && mHeapSeqNum >= 0) {
44         mCrypto->unsetHeap(mHeapSeqNum);
45     }
46 }
47 
findClientBuffer(const std::shared_ptr<const std::vector<const BufferInfo>> & array,const sp<MediaCodecBuffer> & buffer)48 static 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 
findBufferId(const std::shared_ptr<const std::vector<const BufferInfo>> & array,IOMX::buffer_id bufferId)56 static 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 
BufferInfo(const sp<MediaCodecBuffer> & buffer,IOMX::buffer_id bufferId,const sp<IMemory> & sharedEncryptedBuffer)64 ACodecBufferChannel::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 
ACodecBufferChannel(const sp<AMessage> & inputBufferFilled,const sp<AMessage> & outputBufferDrained)77 ACodecBufferChannel::ACodecBufferChannel(
78         const sp<AMessage> &inputBufferFilled, const sp<AMessage> &outputBufferDrained)
79     : mInputBufferFilled(inputBufferFilled),
80       mOutputBufferDrained(outputBufferDrained),
81       mHeapSeqNum(-1) {
82 }
83 
queueInputBuffer(const sp<MediaCodecBuffer> & buffer)84 status_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 
queueSecureInputBuffer(const sp<MediaCodecBuffer> & buffer,bool secure,const uint8_t * key,const uint8_t * iv,CryptoPlugin::Mode mode,CryptoPlugin::Pattern pattern,const CryptoPlugin::SubSample * subSamples,size_t numSubSamples,AString * errorDetailMsg)102 status_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 
renderOutputBuffer(const sp<MediaCodecBuffer> & buffer,int64_t timestampNs)209 status_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 
discardBuffer(const sp<MediaCodecBuffer> & buffer)228 status_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 
getInputBufferArray(Vector<sp<MediaCodecBuffer>> * array)250 void 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 
getOutputBufferArray(Vector<sp<MediaCodecBuffer>> * array)259 void 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 
makeMemoryDealer(size_t heapSize)268 sp<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 
setInputBufferArray(const std::vector<BufferAndId> & array)287 void 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 
setOutputBufferArray(const std::vector<BufferAndId> & array)321 void 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 
fillThisBuffer(IOMX::buffer_id bufferId)331 void 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 
drainThisBuffer(IOMX::buffer_id bufferId,OMX_U32 omxFlags)350 void 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