Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6bdbcd74 authored by Andreas Huber's avatar Andreas Huber Committed by Android (Google) Code Review
Browse files

Merge "Support streaming data across binder boundaries."

parents a111187a 52b52cdf
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -98,3 +98,27 @@ LOCAL_MODULE_TAGS := debug
LOCAL_MODULE:= audioloop

include $(BUILD_EXECUTABLE)

################################################################################

include $(CLEAR_VARS)

LOCAL_SRC_FILES:=         \
        stream.cpp    \

LOCAL_SHARED_LIBRARIES := \
	libstagefright liblog libutils libbinder libsurfaceflinger_client \
        libstagefright_foundation libmedia

LOCAL_C_INCLUDES:= \
	$(JNI_H_INCLUDE) \
	frameworks/base/media/libstagefright \
	$(TOP)/frameworks/base/include/media/stagefright/openmax

LOCAL_CFLAGS += -Wno-multichar

LOCAL_MODULE_TAGS := debug

LOCAL_MODULE:= stream

include $(BUILD_EXECUTABLE)
+168 −0
Original line number Diff line number Diff line
#include <binder/ProcessState.h>

#include <media/IStreamSource.h>
#include <media/mediaplayer.h>
#include <media/stagefright/foundation/ADebug.h>

#include <binder/IServiceManager.h>
#include <media/IMediaPlayerService.h>
#include <surfaceflinger/ISurfaceComposer.h>
#include <surfaceflinger/SurfaceComposerClient.h>

#include <fcntl.h>

using namespace android;

struct MyStreamSource : public BnStreamSource {
    // Caller retains ownership of fd.
    MyStreamSource(int fd);

    virtual void setListener(const sp<IStreamListener> &listener);
    virtual void setBuffers(const Vector<sp<IMemory> > &buffers);

    virtual void onBufferAvailable(size_t index);

protected:
    virtual ~MyStreamSource();

private:
    int mFd;

    sp<IStreamListener> mListener;
    Vector<sp<IMemory> > mBuffers;

    DISALLOW_EVIL_CONSTRUCTORS(MyStreamSource);
};

MyStreamSource::MyStreamSource(int fd)
    : mFd(fd) {
    CHECK_GE(fd, 0);
}

MyStreamSource::~MyStreamSource() {
}

void MyStreamSource::setListener(const sp<IStreamListener> &listener) {
    mListener = listener;
}

void MyStreamSource::setBuffers(const Vector<sp<IMemory> > &buffers) {
    mBuffers = buffers;
}

void MyStreamSource::onBufferAvailable(size_t index) {
    CHECK_LT(index, mBuffers.size());
    sp<IMemory> mem = mBuffers.itemAt(index);

    ssize_t n = read(mFd, mem->pointer(), mem->size());
    if (n <= 0) {
        mListener->queueCommand(IStreamListener::EOS);
    } else {
        mListener->queueBuffer(index, n);
    }
}

////////////////////////////////////////////////////////////////////////////////

struct MyClient : public BnMediaPlayerClient {
    MyClient()
        : mEOS(false) {
    }

    virtual void notify(int msg, int ext1, int ext2) {
        Mutex::Autolock autoLock(mLock);

        if (msg == MEDIA_ERROR || msg == MEDIA_PLAYBACK_COMPLETE) {
            mEOS = true;
            mCondition.signal();
        }
    }

    void waitForEOS() {
        Mutex::Autolock autoLock(mLock);
        while (!mEOS) {
            mCondition.wait(mLock);
        }
    }

protected:
    virtual ~MyClient() {
    }

private:
    Mutex mLock;
    Condition mCondition;

    bool mEOS;

    DISALLOW_EVIL_CONSTRUCTORS(MyClient);
};

int main(int argc, char **argv) {
    android::ProcessState::self()->startThreadPool();

    if (argc != 2) {
        fprintf(stderr, "Usage: %s filename\n", argv[0]);
        return 1;
    }

    sp<SurfaceComposerClient> composerClient = new SurfaceComposerClient;
    CHECK_EQ(composerClient->initCheck(), (status_t)OK);

    sp<SurfaceControl> control =
        composerClient->createSurface(
                getpid(),
                String8("A Surface"),
                0,
                1280,
                800,
                PIXEL_FORMAT_RGB_565,
                0);

    CHECK(control != NULL);
    CHECK(control->isValid());

    CHECK_EQ(composerClient->openTransaction(), (status_t)OK);
    CHECK_EQ(control->setLayer(30000), (status_t)OK);
    CHECK_EQ(control->show(), (status_t)OK);
    CHECK_EQ(composerClient->closeTransaction(), (status_t)OK);

    sp<Surface> surface = control->getSurface();
    CHECK(surface != NULL);

    sp<IServiceManager> sm = defaultServiceManager();
    sp<IBinder> binder = sm->getService(String16("media.player"));
    sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);

    CHECK(service.get() != NULL);

    int fd = open(argv[1], O_RDONLY);

    if (fd < 0) {
        fprintf(stderr, "Failed to open file '%s'.", argv[1]);
        return 1;
    }

    sp<MyClient> client = new MyClient;

    sp<IMediaPlayer> player =
        service->create(getpid(), client, new MyStreamSource(fd), 0);

    if (player != NULL) {
        player->setVideoSurface(surface);
        player->start();

        client->waitForEOS();

        player->stop();
    } else {
        fprintf(stderr, "failed to instantiate player.\n");
    }

    close(fd);
    fd = -1;

    composerClient->dispose();

    return 0;
}
+6 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ namespace android {

class IMediaRecorder;
class IOMX;
struct IStreamSource;

class IMediaPlayerService: public IInterface
{
@@ -45,6 +46,11 @@ public:
            int audioSessionId = 0) = 0;
    virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client,
            int fd, int64_t offset, int64_t length, int audioSessionId) = 0;

    virtual sp<IMediaPlayer> create(
            pid_t pid, const sp<IMediaPlayerClient> &client,
            const sp<IStreamSource> &source, int audioSessionId) = 0;

    virtual sp<IMemory>         decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
    virtual sp<IMemory>         decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
    virtual sp<IOMX>            getOMX() = 0;
+66 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ANDROID_ISTREAMSOURCE_H_

#define ANDROID_ISTREAMSOURCE_H_

#include <binder/IInterface.h>

namespace android {

struct IMemory;
struct IStreamListener;

struct IStreamSource : public IInterface {
    DECLARE_META_INTERFACE(StreamSource);

    virtual void setListener(const sp<IStreamListener> &listener) = 0;
    virtual void setBuffers(const Vector<sp<IMemory> > &buffers) = 0;

    virtual void onBufferAvailable(size_t index) = 0;
};

struct IStreamListener : public IInterface {
    DECLARE_META_INTERFACE(StreamListener);

    enum Command {
        FLUSH,
        DISCONTINUITY,
        EOS
    };

    virtual void queueBuffer(size_t index, size_t size) = 0;
    virtual void queueCommand(Command cmd) = 0;
};

////////////////////////////////////////////////////////////////////////////////

struct BnStreamSource : public BnInterface<IStreamSource> {
    virtual status_t onTransact(
            uint32_t code, const Parcel &data, Parcel *reply,
            uint32_t flags = 0);
};

struct BnStreamListener : public BnInterface<IStreamListener> {
    virtual status_t onTransact(
            uint32_t code, const Parcel &data, Parcel *reply,
            uint32_t flags = 0);
};

}  // namespace android

#endif  // ANDROID_ISTREAMSOURCE_H_
+5 −0
Original line number Diff line number Diff line
@@ -106,6 +106,11 @@ public:
            const KeyedVector<String8, String8> *headers = NULL) = 0;

    virtual status_t    setDataSource(int fd, int64_t offset, int64_t length) = 0;

    virtual status_t    setDataSource(const sp<IStreamSource> &source) {
        return INVALID_OPERATION;
    }

    virtual status_t    setVideoSurface(const sp<Surface>& surface) = 0;
    virtual status_t    prepare() = 0;
    virtual status_t    prepareAsync() = 0;
Loading