status_t MediaHTTP::connect( const char *uri, const KeyedVector<String8, String8> *headers, off64_t /* offset */) { if (mInitCheck != OK) { return mInitCheck; } KeyedVector<String8, String8> extHeaders; if (headers != NULL) { extHeaders = *headers; } if (extHeaders.indexOfKey(String8("User-Agent")) < 0) { extHeaders.add(String8("User-Agent"), String8(MakeUserAgent().c_str())); } bool success = mHTTPConnection->connect(uri, &extHeaders); mLastHeaders = extHeaders; mLastURI = uri; mCachedSizeValid = false; return success ? OK : UNKNOWN_ERROR; }
void GPUHardware::binderDied(const wp<IBinder>& who) { Mutex::Autolock _l(mLock); pid_t pid = mRegisteredClients.valueFor(who); if (pid != 0) { ssize_t index = mClients.indexOfKey(pid); if (index >= 0) { //LOGD("*** removing client at %d", index); Client& client(mClients.editValueAt(index)); client.revokeAllHeaps(); // not really needed in theory mClients.removeItemsAt(index); if (mClients.size() == 0) { //LOGD("*** was last client closing everything"); mCallback.clear(); mAllocator.clear(); mCurrentAllocator.clear(); mSMIHeap.clear(); mREGHeap.clear(); // NOTE: we cannot clear the EBI heap because surfaceflinger // itself may be using it, since this is where surfaces // are allocated. if we're in the middle of compositing // a surface (even if its process just died), we cannot // rip the heap under our feet. mOwner = NO_OWNER; } } } }
sp<IMemoryHeap> HeapCache::get_heap(const sp<IBinder>& binder) { sp<IMemoryHeap> realHeap; Mutex::Autolock _l(mHeapCacheLock); ssize_t i = mHeapCache.indexOfKey(binder); if (i>=0) realHeap = mHeapCache.valueAt(i).heap; else realHeap = interface_cast<IMemoryHeap>(binder); return realHeap; }
static bool findParam(uint32_t key, T *param, KeyedVector<uint32_t, uint64_t> ¶ms) { CHECK(param); if (params.indexOfKey(key) < 0) { return false; } *param = (T) params[key]; return true; }
status_t NativeInputEventSender::receiveFinishedSignals(JNIEnv* env) { if (kDebugDispatchCycle) { ALOGD("channel '%s' ~ Receiving finished signals.", getInputChannelName()); } ScopedLocalRef<jobject> senderObj(env, NULL); bool skipCallbacks = false; for (;;) { uint32_t publishedSeq; bool handled; status_t status = mInputPublisher.receiveFinishedSignal(&publishedSeq, &handled); if (status) { if (status == WOULD_BLOCK) { return OK; } ALOGE("channel '%s' ~ Failed to consume finished signals. status=%d", getInputChannelName(), status); return status; } ssize_t index = mPublishedSeqMap.indexOfKey(publishedSeq); if (index >= 0) { uint32_t seq = mPublishedSeqMap.valueAt(index); mPublishedSeqMap.removeItemsAt(index); if (kDebugDispatchCycle) { ALOGD("channel '%s' ~ Received finished signal, seq=%u, handled=%s, " "pendingEvents=%zu.", getInputChannelName(), seq, handled ? "true" : "false", mPublishedSeqMap.size()); } if (!skipCallbacks) { if (!senderObj.get()) { senderObj.reset(jniGetReferent(env, mSenderWeakGlobal)); if (!senderObj.get()) { ALOGW("channel '%s' ~ Sender object was finalized " "without being disposed.", getInputChannelName()); return DEAD_OBJECT; } } env->CallVoidMethod(senderObj.get(), gInputEventSenderClassInfo.dispatchInputEventFinished, jint(seq), jboolean(handled)); if (env->ExceptionCheck()) { ALOGE("Exception dispatching finished signal."); skipCallbacks = true; } } } } }
void HeapCache::pin_heap(const sp<IBinder>& binder) { Mutex::Autolock _l(mHeapCacheLock); ssize_t i = mHeapCache.indexOfKey(binder); if (i>=0) { heap_info_t& info(mHeapCache.editValueAt(i)); android_atomic_inc(&info.count); binder->linkToDeath(this); } else { LOGE("pin_heap binder=%p not found!!!", binder.get()); } }
GPUHardware::Client& GPUHardware::getClientLocked(pid_t pid) { ssize_t index = mClients.indexOfKey(pid); if (index < 0) { Client client; client.pid = pid; client.smi.heap = mSMIHeap; client.ebi.heap = mEBIHeap; client.reg.heap = mREGHeap; index = mClients.add(pid, client); } Client& client(mClients.editValueAt(index)); client.createClientHeaps(); return client; }
void GPUHardware::releaseLocked() { //LOGD("revoking gpu from pid %d", mOwner); if (mOwner != NO_OWNER) { // this may fail because the client might have died, and have // been removed from the list. ssize_t index = mClients.indexOfKey(mOwner); if (index >= 0) { Client& client(mClients.editValueAt(index)); client.revokeAllHeaps(); } mOwner = NO_OWNER; mCurrentAllocator.clear(); mCallback.clear(); } }
void HeapCache::free_heap(const wp<IBinder>& binder) { sp<IMemoryHeap> rel; { Mutex::Autolock _l(mHeapCacheLock); ssize_t i = mHeapCache.indexOfKey(binder); if (i>=0) { heap_info_t& info(mHeapCache.editValueAt(i)); int32_t c = android_atomic_dec(&info.count); if (c == 1) { ALOGD_IF(VERBOSE, "removing binder=%p, heap=%p, size=%d, fd=%d, count=%d", binder.unsafe_get(), info.heap.get(), static_cast<BpMemoryHeap*>(info.heap.get())->mSize, static_cast<BpMemoryHeap*>(info.heap.get())->mHeapId, info.count); rel = mHeapCache.valueAt(i).heap; mHeapCache.removeItemsAt(i); } } else { ALOGE("free_heap binder=%p not found!!!", binder.unsafe_get()); } } }
sp<IMemoryHeap> HeapCache::find_heap(const sp<IBinder>& binder) { Mutex::Autolock _l(mHeapCacheLock); ssize_t i = mHeapCache.indexOfKey(binder); if (i>=0) { heap_info_t& info = mHeapCache.editValueAt(i); ALOGD_IF(VERBOSE, "found binder=%p, heap=%p, size=%d, fd=%d, count=%d", binder.get(), info.heap.get(), static_cast<BpMemoryHeap*>(info.heap.get())->mSize, static_cast<BpMemoryHeap*>(info.heap.get())->mHeapId, info.count); android_atomic_inc(&info.count); return info.heap; } else { heap_info_t info; info.heap = interface_cast<IMemoryHeap>(binder); info.count = 1; //ALOGD("adding binder=%p, heap=%p, count=%d", // binder.get(), info.heap.get(), info.count); mHeapCache.add(binder, info); return info.heap; } }
bool MuxOMX::isLocalNode_l(node_id node) const { return mIsLocalNode.indexOfKey(node) >= 0; }
bool isWVM(const char* url, const KeyedVector<String8, String8> *headers) { sp<DataSource> dataSource; String8 mUri; KeyedVector<String8, String8> mUriHeaders; sp<HTTPBase> mConnectingDataSource; sp<NuCachedSource2> mCachedSource; uint32_t mFlags; mUri = url; void *VendorLibHandle = NULL; if (VendorLibHandle == NULL) { VendorLibHandle = dlopen("libwvm.so", RTLD_NOW); } if (!VendorLibHandle) { return false; } if (headers) { mUriHeaders = *headers; ssize_t index = mUriHeaders.indexOfKey(String8("x-hide-urls-from-log")); if (index >= 0) { // Browser is in "incognito" mode, suppress logging URLs. // This isn't something that should be passed to the server. mUriHeaders.removeItemsAt(index); mFlags |= INCOGNITO; } } if (!strncasecmp("http://", mUri.string(), 7) || !strncasecmp("https://", mUri.string(), 8)) { mConnectingDataSource = HTTPBase::Create( (mFlags & INCOGNITO) ? HTTPBase::kFlagIncognito : 0); String8 cacheConfig; bool disconnectAtHighwatermark; NuCachedSource2::RemoveCacheSpecificHeaders( &mUriHeaders, &cacheConfig, &disconnectAtHighwatermark); status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders); if (err != OK) { mConnectingDataSource.clear(); ALOGI("mConnectingDataSource->connect() returned %d", err); return false; } // The widevine extractor does its own caching. mCachedSource = new NuCachedSource2( mConnectingDataSource, cacheConfig.isEmpty() ? NULL : cacheConfig.string(), disconnectAtHighwatermark); dataSource = mCachedSource; mConnectingDataSource.clear(); // Removed prefill as we can't abort it. // // We're going to prefill the cache before trying to instantiate // the extractor below, as the latter is an operation that otherwise // could block on the datasource for a significant amount of time. // During that time we'd be unable to abort the preparation phase // without this prefill. } else { dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders); } if (dataSource == NULL) { return false; } typedef WVMLoadableExtractor *(*SnifferFunc)(const sp<DataSource>&); SnifferFunc snifferFunc = (SnifferFunc) dlsym(VendorLibHandle, "_ZN7android15IsWidevineMediaERKNS_2spINS_10DataSourceEEE"); if (snifferFunc) { if ((*snifferFunc)(dataSource)) { return true; } } return false; }
static int muxing( const char *path, bool useAudio, bool useVideo, const char *outputFileName, bool enableTrim, int trimStartTimeMs, int trimEndTimeMs, int rotationDegrees, MediaMuxer::OutputFormat container = MediaMuxer::OUTPUT_FORMAT_MPEG_4) { sp<NuMediaExtractor> extractor = new NuMediaExtractor; if (extractor->setDataSource(NULL /* httpService */, path) != OK) { fprintf(stderr, "unable to instantiate extractor. %s\n", path); return 1; } if (outputFileName == NULL) { outputFileName = "/sdcard/muxeroutput.mp4"; } ALOGV("input file %s, output file %s", path, outputFileName); ALOGV("useAudio %d, useVideo %d", useAudio, useVideo); int fd = open(outputFileName, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR); if (fd < 0) { ALOGE("couldn't open file"); return fd; } sp<MediaMuxer> muxer = new MediaMuxer(fd, container); close(fd); size_t trackCount = extractor->countTracks(); // Map the extractor's track index to the muxer's track index. KeyedVector<size_t, ssize_t> trackIndexMap; size_t bufferSize = 1 * 1024 * 1024; // default buffer size is 1MB. bool haveAudio = false; bool haveVideo = false; int64_t trimStartTimeUs = trimStartTimeMs * 1000; int64_t trimEndTimeUs = trimEndTimeMs * 1000; bool trimStarted = false; int64_t trimOffsetTimeUs = 0; for (size_t i = 0; i < trackCount; ++i) { sp<AMessage> format; status_t err = extractor->getTrackFormat(i, &format); CHECK_EQ(err, (status_t)OK); ALOGV("extractor getTrackFormat: %s", format->debugString().c_str()); AString mime; CHECK(format->findString("mime", &mime)); bool isAudio = !strncasecmp(mime.c_str(), "audio/", 6); bool isVideo = !strncasecmp(mime.c_str(), "video/", 6); if (useAudio && !haveAudio && isAudio) { haveAudio = true; } else if (useVideo && !haveVideo && isVideo) { haveVideo = true; } else { continue; } if (isVideo) { int width , height; CHECK(format->findInt32("width", &width)); CHECK(format->findInt32("height", &height)); bufferSize = width * height * 4; // Assuming it is maximally 4BPP } int64_t duration; CHECK(format->findInt64("durationUs", &duration)); // Since we got the duration now, correct the start time. if (enableTrim) { if (trimStartTimeUs > duration) { fprintf(stderr, "Warning: trimStartTimeUs > duration," " reset to 0\n"); trimStartTimeUs = 0; } } ALOGV("selecting track %zu", i); err = extractor->selectTrack(i); CHECK_EQ(err, (status_t)OK); ssize_t newTrackIndex = muxer->addTrack(format); if (newTrackIndex < 0) { fprintf(stderr, "%s track (%zu) unsupported by muxer\n", isAudio ? "audio" : "video", i); } else { trackIndexMap.add(i, newTrackIndex); } } int64_t muxerStartTimeUs = ALooper::GetNowUs(); bool sawInputEOS = false; size_t trackIndex = -1; sp<ABuffer> newBuffer = new ABuffer(bufferSize); muxer->setOrientationHint(rotationDegrees); muxer->start(); while (!sawInputEOS) { status_t err = extractor->getSampleTrackIndex(&trackIndex); if (err != OK) { ALOGV("saw input eos, err %d", err); sawInputEOS = true; break; } else if (trackIndexMap.indexOfKey(trackIndex) < 0) { // ALOGV("skipping input from unsupported track %zu", trackIndex); extractor->advance(); continue; } else { // ALOGV("reading sample from track index %zu\n", trackIndex); err = extractor->readSampleData(newBuffer); CHECK_EQ(err, (status_t)OK); int64_t timeUs; err = extractor->getSampleTime(&timeUs); CHECK_EQ(err, (status_t)OK); sp<MetaData> meta; err = extractor->getSampleMeta(&meta); CHECK_EQ(err, (status_t)OK); uint32_t sampleFlags = 0; int32_t val; if (meta->findInt32(kKeyIsSyncFrame, &val) && val != 0) { // We only support BUFFER_FLAG_SYNCFRAME in the flag for now. sampleFlags |= MediaCodec::BUFFER_FLAG_SYNCFRAME; // We turn on trimming at the sync frame. if (enableTrim && timeUs > trimStartTimeUs && timeUs <= trimEndTimeUs) { if (trimStarted == false) { trimOffsetTimeUs = timeUs; } trimStarted = true; } } // Trim can end at any non-sync frame. if (enableTrim && timeUs > trimEndTimeUs) { trimStarted = false; } if (!enableTrim || (enableTrim && trimStarted)) { err = muxer->writeSampleData(newBuffer, trackIndexMap.valueFor(trackIndex), timeUs - trimOffsetTimeUs, sampleFlags); } extractor->advance(); } } muxer->stop(); newBuffer.clear(); trackIndexMap.clear(); int64_t elapsedTimeUs = ALooper::GetNowUs() - muxerStartTimeUs; fprintf(stderr, "SUCCESS: muxer generate the video in %" PRId64 " ms\n", elapsedTimeUs / 1000); return 0; }