1 /* 2 * Copyright (C) 2009 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 "BpMediaSource" 19 #include <utils/Log.h> 20 21 #include <inttypes.h> 22 #include <stdint.h> 23 #include <sys/types.h> 24 25 #include <binder/Parcel.h> 26 #include <media/IMediaSource.h> 27 #include <media/stagefright/MediaBuffer.h> 28 #include <media/stagefright/MediaBufferGroup.h> 29 #include <media/MediaSource.h> 30 #include <media/stagefright/MetaData.h> 31 32 namespace android { 33 34 enum { 35 START = IBinder::FIRST_CALL_TRANSACTION, 36 STOP, 37 PAUSE, 38 GETFORMAT, 39 // READ, deprecated 40 READMULTIPLE, 41 RELEASE_BUFFER, 42 SUPPORT_NONBLOCKING_READ, 43 }; 44 45 enum { 46 NULL_BUFFER, 47 SHARED_BUFFER, 48 INLINE_BUFFER, 49 SHARED_BUFFER_INDEX, 50 }; 51 52 class RemoteMediaBufferWrapper : public MediaBuffer { 53 public: 54 RemoteMediaBufferWrapper(const sp<IMemory> &mem) 55 : MediaBuffer(mem) { 56 ALOGV("RemoteMediaBufferWrapper: creating %p", this); 57 } 58 59 protected: 60 virtual ~RemoteMediaBufferWrapper() { 61 // Release our interest in the MediaBuffer's shared memory. 62 int32_t old = addRemoteRefcount(-1); 63 ALOGV("RemoteMediaBufferWrapper: releasing %p, refcount %d", this, old - 1); 64 mMemory.clear(); // don't set the dead object flag. 65 } 66 }; 67 68 class BpMediaSource : public BpInterface<IMediaSource> { 69 public: 70 explicit BpMediaSource(const sp<IBinder>& impl) 71 : BpInterface<IMediaSource>(impl), mBuffersSinceStop(0) 72 { 73 } 74 75 virtual status_t start(MetaData *params) { 76 ALOGV("start"); 77 Parcel data, reply; 78 data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor()); 79 if (params) { 80 params->writeToParcel(data); 81 } 82 status_t ret = remote()->transact(START, data, &reply); 83 if (ret == NO_ERROR && params) { 84 ALOGW("ignoring potentially modified MetaData from start"); 85 ALOGW("input:"); 86 params->dumpToLog(); 87 sp<MetaData> meta = MetaData::createFromParcel(reply); 88 ALOGW("output:"); 89 meta->dumpToLog(); 90 } 91 return ret; 92 } 93 94 virtual status_t stop() { 95 ALOGV("stop"); 96 Parcel data, reply; 97 data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor()); 98 status_t status = remote()->transact(STOP, data, &reply); 99 mMemoryCache.reset(); 100 mBuffersSinceStop = 0; 101 return status; 102 } 103 104 virtual sp<MetaData> getFormat() { 105 ALOGV("getFormat"); 106 Parcel data, reply; 107 data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor()); 108 status_t ret = remote()->transact(GETFORMAT, data, &reply); 109 if (ret == NO_ERROR) { 110 AutoMutex _l(mLock); 111 mMetaData = MetaData::createFromParcel(reply); 112 return mMetaData; 113 } 114 return NULL; 115 } 116 117 virtual status_t read(MediaBufferBase **buffer, 118 const MediaSource::ReadOptions *options) { 119 Vector<MediaBufferBase *> buffers; 120 status_t ret = readMultiple(&buffers, 1 /* maxNumBuffers */, options); 121 *buffer = buffers.size() == 0 ? nullptr : buffers[0]; 122 ALOGV("read status %d, bufferCount %u, sinceStop %u", 123 ret, *buffer != nullptr, mBuffersSinceStop); 124 return ret; 125 } 126 127 virtual status_t readMultiple( 128 Vector<MediaBufferBase *> *buffers, uint32_t maxNumBuffers, 129 const MediaSource::ReadOptions *options) { 130 ALOGV("readMultiple"); 131 if (buffers == NULL || !buffers->isEmpty()) { 132 return BAD_VALUE; 133 } 134 Parcel data, reply; 135 data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor()); 136 data.writeUint32(maxNumBuffers); 137 if (options != nullptr) { 138 data.writeByteArray(sizeof(*options), (uint8_t*) options); 139 } 140 status_t ret = remote()->transact(READMULTIPLE, data, &reply); 141 mMemoryCache.gc(); 142 if (ret != NO_ERROR) { 143 return ret; 144 } 145 // wrap the returned data in a vector of MediaBuffers 146 int32_t buftype; 147 uint32_t bufferCount = 0; 148 while ((buftype = reply.readInt32()) != NULL_BUFFER) { 149 LOG_ALWAYS_FATAL_IF(bufferCount >= maxNumBuffers, 150 "Received %u+ buffers and requested %u buffers", 151 bufferCount + 1, maxNumBuffers); 152 MediaBuffer *buf; 153 if (buftype == SHARED_BUFFER || buftype == SHARED_BUFFER_INDEX) { 154 uint64_t index = reply.readUint64(); 155 ALOGV("Received %s index %llu", 156 buftype == SHARED_BUFFER ? "SHARED_BUFFER" : "SHARED_BUFFER_INDEX", 157 (unsigned long long) index); 158 sp<IMemory> mem; 159 if (buftype == SHARED_BUFFER) { 160 sp<IBinder> binder = reply.readStrongBinder(); 161 mem = interface_cast<IMemory>(binder); 162 LOG_ALWAYS_FATAL_IF(mem.get() == nullptr, 163 "Received NULL IMemory for shared buffer"); 164 mMemoryCache.insert(index, mem); 165 } else { 166 mem = mMemoryCache.lookup(index); 167 LOG_ALWAYS_FATAL_IF(mem.get() == nullptr, 168 "Received invalid IMemory index for shared buffer: %llu", 169 (unsigned long long)index); 170 } 171 size_t offset = reply.readInt32(); 172 size_t length = reply.readInt32(); 173 buf = new RemoteMediaBufferWrapper(mem); 174 buf->set_range(offset, length); 175 buf->meta_data().updateFromParcel(reply); 176 } else { // INLINE_BUFFER 177 int32_t len = reply.readInt32(); 178 ALOGV("INLINE_BUFFER status %d and len %d", ret, len); 179 buf = new MediaBuffer(len); 180 reply.read(buf->data(), len); 181 buf->meta_data().updateFromParcel(reply); 182 } 183 buffers->push_back(buf); 184 ++bufferCount; 185 ++mBuffersSinceStop; 186 } 187 ret = reply.readInt32(); 188 ALOGV("readMultiple status %d, bufferCount %u, sinceStop %u", 189 ret, bufferCount, mBuffersSinceStop); 190 if (bufferCount && ret == WOULD_BLOCK) { 191 ret = OK; 192 } 193 return ret; 194 } 195 196 // Binder proxy adds readMultiple support. 197 virtual bool supportReadMultiple() { 198 return true; 199 } 200 201 virtual bool supportNonblockingRead() { 202 ALOGV("supportNonblockingRead"); 203 Parcel data, reply; 204 data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor()); 205 status_t ret = remote()->transact(SUPPORT_NONBLOCKING_READ, data, &reply); 206 if (ret == NO_ERROR) { 207 return reply.readInt32() != 0; 208 } 209 return false; 210 } 211 212 virtual status_t pause() { 213 ALOGV("pause"); 214 Parcel data, reply; 215 data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor()); 216 return remote()->transact(PAUSE, data, &reply); 217 } 218 219 private: 220 221 uint32_t mBuffersSinceStop; // Buffer tracking variable 222 223 // NuPlayer passes pointers-to-metadata around, so we use this to keep the metadata alive 224 // XXX: could we use this for caching, or does metadata change on the fly? 225 sp<MetaData> mMetaData; 226 // ensure synchronize access to mMetaData 227 Mutex mLock; 228 229 // Cache all IMemory objects received from MediaExtractor. 230 // We gc IMemory objects that are no longer active (referenced by a MediaBuffer). 231 232 struct MemoryCache { 233 sp<IMemory> lookup(uint64_t index) { 234 auto p = mIndexToMemory.find(index); 235 if (p == mIndexToMemory.end()) { 236 ALOGE("cannot find index!"); 237 return nullptr; 238 } 239 return p->second; 240 } 241 242 void insert(uint64_t index, const sp<IMemory> &mem) { 243 if (mIndexToMemory.find(index) != mIndexToMemory.end()) { 244 ALOGE("index %llu already present", (unsigned long long)index); 245 return; 246 } 247 (void)mIndexToMemory.emplace(index, mem); 248 } 249 250 void reset() { 251 mIndexToMemory.clear(); 252 } 253 254 void gc() { 255 for (auto it = mIndexToMemory.begin(); it != mIndexToMemory.end(); ) { 256 if (MediaBuffer::isDeadObject(it->second)) { 257 it = mIndexToMemory.erase(it); 258 } else { 259 ++it; 260 } 261 } 262 } 263 private: 264 // C++14 unordered_map erase on iterator is stable; C++11 has no guarantee. 265 std::map<uint64_t, sp<IMemory>> mIndexToMemory; 266 } mMemoryCache; 267 }; 268 269 IMPLEMENT_META_INTERFACE(MediaSource, "android.media.IMediaSource"); 270 271 #undef LOG_TAG 272 #define LOG_TAG "BnMediaSource" 273 274 BnMediaSource::BnMediaSource() 275 : mBuffersSinceStop(0) 276 , mGroup(new MediaBufferGroup(kBinderMediaBuffers /* growthLimit */)) { 277 } 278 279 BnMediaSource::~BnMediaSource() { 280 } 281 282 status_t BnMediaSource::onTransact( 283 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) 284 { 285 switch (code) { 286 case START: { 287 ALOGV("start"); 288 CHECK_INTERFACE(IMediaSource, data, reply); 289 sp<MetaData> meta; 290 if (data.dataAvail()) { 291 meta = MetaData::createFromParcel(data); 292 } 293 status_t ret = start(meta.get()); 294 if (ret == NO_ERROR && meta != NULL) { 295 meta->writeToParcel(*reply); 296 } 297 return ret; 298 } 299 case STOP: { 300 ALOGV("stop"); 301 CHECK_INTERFACE(IMediaSource, data, reply); 302 mGroup->signalBufferReturned(nullptr); 303 status_t status = stop(); 304 mIndexCache.reset(); 305 mBuffersSinceStop = 0; 306 return status; 307 } 308 case PAUSE: { 309 ALOGV("pause"); 310 CHECK_INTERFACE(IMediaSource, data, reply); 311 mGroup->signalBufferReturned(nullptr); 312 return pause(); 313 } 314 case GETFORMAT: { 315 ALOGV("getFormat"); 316 CHECK_INTERFACE(IMediaSource, data, reply); 317 sp<MetaData> meta = getFormat(); 318 if (meta != NULL) { 319 meta->writeToParcel(*reply); 320 return NO_ERROR; 321 } 322 return UNKNOWN_ERROR; 323 } 324 case READMULTIPLE: { 325 ALOGV("readMultiple"); 326 CHECK_INTERFACE(IMediaSource, data, reply); 327 328 // Get max number of buffers to read. 329 uint32_t maxNumBuffers; 330 data.readUint32(&maxNumBuffers); 331 if (maxNumBuffers > kMaxNumReadMultiple) { 332 maxNumBuffers = kMaxNumReadMultiple; 333 } 334 335 // Get read options, if any. 336 MediaSource::ReadOptions opts; 337 uint32_t len; 338 const bool useOptions = 339 data.readUint32(&len) == NO_ERROR 340 && len == sizeof(opts) 341 && data.read((void *)&opts, len) == NO_ERROR; 342 343 mGroup->signalBufferReturned(nullptr); 344 mIndexCache.gc(); 345 size_t inlineTransferSize = 0; 346 status_t ret = NO_ERROR; 347 uint32_t bufferCount = 0; 348 for (; bufferCount < maxNumBuffers; ++bufferCount, ++mBuffersSinceStop) { 349 MediaBuffer *buf = nullptr; 350 ret = read((MediaBufferBase **)&buf, useOptions ? &opts : nullptr); 351 opts.clearNonPersistent(); // Remove options that only apply to first buffer. 352 if (ret != NO_ERROR || buf == nullptr) { 353 break; 354 } 355 356 // Even if we're using shared memory, we might not want to use it, since for small 357 // sizes it's faster to copy data through the Binder transaction 358 // On the other hand, if the data size is large enough, it's better to use shared 359 // memory. When data is too large, binder can't handle it. 360 // 361 // TODO: reduce MediaBuffer::kSharedMemThreshold 362 MediaBuffer *transferBuf = nullptr; 363 const size_t length = buf->range_length(); 364 size_t offset = buf->range_offset(); 365 if (length >= (supportNonblockingRead() && buf->mMemory != nullptr ? 366 kTransferSharedAsSharedThreshold : kTransferInlineAsSharedThreshold)) { 367 if (buf->mMemory != nullptr) { 368 ALOGV("Use shared memory: %zu", length); 369 transferBuf = buf; 370 } else { 371 ALOGV("Large buffer %zu without IMemory!", length); 372 ret = mGroup->acquire_buffer( 373 (MediaBufferBase **)&transferBuf, false /* nonBlocking */, length); 374 if (ret != OK 375 || transferBuf == nullptr 376 || transferBuf->mMemory == nullptr) { 377 ALOGV("Failed to acquire shared memory, size %zu, ret %d", 378 length, ret); 379 if (transferBuf != nullptr) { 380 transferBuf->release(); 381 transferBuf = nullptr; 382 } 383 // Current buffer transmit inline; no more additional buffers. 384 maxNumBuffers = 0; 385 } else { 386 memcpy(transferBuf->data(), (uint8_t*)buf->data() + offset, length); 387 offset = 0; 388 if (!mGroup->has_buffers()) { 389 maxNumBuffers = 0; // No more MediaBuffers, stop readMultiple. 390 } 391 } 392 } 393 } 394 if (transferBuf != nullptr) { // Using shared buffers. 395 if (!transferBuf->isObserved() && transferBuf != buf) { 396 // Transfer buffer must be part of a MediaBufferGroup. 397 ALOGV("adding shared memory buffer %p to local group", transferBuf); 398 mGroup->add_buffer(transferBuf); 399 transferBuf->add_ref(); // We have already acquired buffer. 400 } 401 uint64_t index = mIndexCache.lookup(transferBuf->mMemory); 402 if (index == 0) { 403 index = mIndexCache.insert(transferBuf->mMemory); 404 reply->writeInt32(SHARED_BUFFER); 405 reply->writeUint64(index); 406 reply->writeStrongBinder(IInterface::asBinder(transferBuf->mMemory)); 407 ALOGV("SHARED_BUFFER(%p) %llu", 408 transferBuf, (unsigned long long)index); 409 } else { 410 reply->writeInt32(SHARED_BUFFER_INDEX); 411 reply->writeUint64(index); 412 ALOGV("SHARED_BUFFER_INDEX(%p) %llu", 413 transferBuf, (unsigned long long)index); 414 } 415 reply->writeInt32(offset); 416 reply->writeInt32(length); 417 buf->meta_data().writeToParcel(*reply); 418 transferBuf->addRemoteRefcount(1); 419 if (transferBuf != buf) { 420 transferBuf->release(); // release local ref 421 } else if (!supportNonblockingRead()) { 422 maxNumBuffers = 0; // stop readMultiple with one shared buffer. 423 } 424 } else { 425 ALOGV_IF(buf->mMemory != nullptr, 426 "INLINE(%p) %zu shared mem available, but only %zu used", 427 buf, buf->mMemory->size(), length); 428 reply->writeInt32(INLINE_BUFFER); 429 reply->writeByteArray(length, (uint8_t*)buf->data() + offset); 430 buf->meta_data().writeToParcel(*reply); 431 inlineTransferSize += length; 432 if (inlineTransferSize > kInlineMaxTransfer) { 433 maxNumBuffers = 0; // stop readMultiple if inline transfer is too large. 434 } 435 } 436 buf->release(); 437 } 438 reply->writeInt32(NULL_BUFFER); // Indicate no more MediaBuffers. 439 reply->writeInt32(ret); 440 ALOGV("readMultiple status %d, bufferCount %u, sinceStop %u", 441 ret, bufferCount, mBuffersSinceStop); 442 return NO_ERROR; 443 } 444 case SUPPORT_NONBLOCKING_READ: { 445 ALOGV("supportNonblockingRead"); 446 CHECK_INTERFACE(IMediaSource, data, reply); 447 reply->writeInt32((int32_t)supportNonblockingRead()); 448 return NO_ERROR; 449 } 450 default: 451 return BBinder::onTransact(code, data, reply, flags); 452 } 453 } 454 455 } // namespace android 456 457