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