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