#include #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; off64_t mFileSize; int64_t mNextSeekTimeUs; sp mListener; Vector > mBuffers; DISALLOW_EVIL_CONSTRUCTORS(MyStreamSource); }; MyStreamSource::MyStreamSource(int fd) : mFd(fd), mFileSize(0), mNextSeekTimeUs(-1) { // ALooper::GetNowUs() + 5000000ll) { CHECK_GE(fd, 0); mFileSize = lseek64(fd, 0, SEEK_END); lseek64(fd, 0, SEEK_SET); } 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()); if (mNextSeekTimeUs >= 0 && mNextSeekTimeUs <= ALooper::GetNowUs()) { off64_t offset = (off64_t)(((float)rand() / RAND_MAX) * mFileSize * 0.8); offset = (offset / 188) * 188; lseek(mFd, offset, SEEK_SET); mListener->issueCommand( IStreamListener::DISCONTINUITY, false /* synchronous */); mNextSeekTimeUs = -1; mNextSeekTimeUs = ALooper::GetNowUs() + 5000000ll; } sp mem = mBuffers.itemAt(index); ssize_t n = read(mFd, mem->pointer(), mem->size()); if (n <= 0) { mListener->issueCommand(IStreamListener::EOS, false /* synchronous */); } 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; }