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