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