Beispiel #1
0
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;
            }
        }
    }
}
Beispiel #3
0
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> &params) {
    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();
    }
}
Beispiel #9
0
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());
        }
    }
}
Beispiel #10
0
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;
    }
}
Beispiel #11
0
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;
}