From 52b52cdfb7502d5a0fd7bba21d1daa3e36a54e42 Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Tue, 23 Nov 2010 11:41:34 -0800 Subject: Support streaming data across binder boundaries. Change-Id: Ifbac61406dcb81343765f99ccba08bd90f9274cc --- cmds/stagefright/Android.mk | 24 +++++++ cmds/stagefright/stream.cpp | 168 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 192 insertions(+) create mode 100644 cmds/stagefright/stream.cpp (limited to 'cmds/stagefright') diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk index 93baefd..f8650eb 100644 --- a/cmds/stagefright/Android.mk +++ b/cmds/stagefright/Android.mk @@ -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) diff --git a/cmds/stagefright/stream.cpp b/cmds/stagefright/stream.cpp new file mode 100644 index 0000000..f2b5638 --- /dev/null +++ b/cmds/stagefright/stream.cpp @@ -0,0 +1,168 @@ +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include + +using namespace android; + +struct MyStreamSource : public BnStreamSource { + // Caller retains ownership of fd. + MyStreamSource(int fd); + + virtual void setListener(const sp &listener); + virtual void setBuffers(const Vector > &buffers); + + virtual void onBufferAvailable(size_t index); + +protected: + virtual ~MyStreamSource(); + +private: + int mFd; + + sp mListener; + Vector > mBuffers; + + DISALLOW_EVIL_CONSTRUCTORS(MyStreamSource); +}; + +MyStreamSource::MyStreamSource(int fd) + : mFd(fd) { + CHECK_GE(fd, 0); +} + +MyStreamSource::~MyStreamSource() { +} + +void MyStreamSource::setListener(const sp &listener) { + mListener = listener; +} + +void MyStreamSource::setBuffers(const Vector > &buffers) { + mBuffers = buffers; +} + +void MyStreamSource::onBufferAvailable(size_t index) { + CHECK_LT(index, mBuffers.size()); + sp 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 composerClient = new SurfaceComposerClient; + CHECK_EQ(composerClient->initCheck(), (status_t)OK); + + sp 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 = control->getSurface(); + CHECK(surface != NULL); + + sp sm = defaultServiceManager(); + sp binder = sm->getService(String16("media.player")); + sp service = interface_cast(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 client = new MyClient; + + sp 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; +} -- cgit v1.1