stream.cpp revision a15874665fa785c82afa9f2e8cb3512470c297cb
1#include <binder/ProcessState.h> 2 3#include <media/IStreamSource.h> 4#include <media/mediaplayer.h> 5#include <media/stagefright/foundation/ADebug.h> 6#include <media/stagefright/foundation/AMessage.h> 7 8#include <binder/IServiceManager.h> 9#include <media/IMediaPlayerService.h> 10#include <surfaceflinger/ISurfaceComposer.h> 11#include <surfaceflinger/SurfaceComposerClient.h> 12 13#include <fcntl.h> 14 15using namespace android; 16 17struct MyStreamSource : public BnStreamSource { 18 // Caller retains ownership of fd. 19 MyStreamSource(int fd); 20 21 virtual void setListener(const sp<IStreamListener> &listener); 22 virtual void setBuffers(const Vector<sp<IMemory> > &buffers); 23 24 virtual void onBufferAvailable(size_t index); 25 26protected: 27 virtual ~MyStreamSource(); 28 29private: 30 int mFd; 31 off64_t mFileSize; 32 int64_t mNextSeekTimeUs; 33 34 sp<IStreamListener> mListener; 35 Vector<sp<IMemory> > mBuffers; 36 37 DISALLOW_EVIL_CONSTRUCTORS(MyStreamSource); 38}; 39 40MyStreamSource::MyStreamSource(int fd) 41 : mFd(fd), 42 mFileSize(0), 43 mNextSeekTimeUs(ALooper::GetNowUs() + 5000000ll) { 44 CHECK_GE(fd, 0); 45 46 mFileSize = lseek64(fd, 0, SEEK_END); 47 lseek64(fd, 0, SEEK_SET); 48} 49 50MyStreamSource::~MyStreamSource() { 51} 52 53void MyStreamSource::setListener(const sp<IStreamListener> &listener) { 54 mListener = listener; 55} 56 57void MyStreamSource::setBuffers(const Vector<sp<IMemory> > &buffers) { 58 mBuffers = buffers; 59} 60 61void MyStreamSource::onBufferAvailable(size_t index) { 62 CHECK_LT(index, mBuffers.size()); 63 64 if (mNextSeekTimeUs >= 0 && mNextSeekTimeUs <= ALooper::GetNowUs()) { 65 off64_t offset = (off64_t)(((float)rand() / RAND_MAX) * mFileSize * 0.8); 66 offset = (offset / 188) * 188; 67 68 lseek(mFd, offset, SEEK_SET); 69 70 mListener->issueCommand( 71 IStreamListener::DISCONTINUITY, false /* synchronous */); 72 73 mNextSeekTimeUs = -1; 74 mNextSeekTimeUs = ALooper::GetNowUs() + 5000000ll; 75 } 76 77 sp<IMemory> mem = mBuffers.itemAt(index); 78 79 ssize_t n = read(mFd, mem->pointer(), mem->size()); 80 if (n <= 0) { 81 mListener->issueCommand(IStreamListener::EOS, false /* synchronous */); 82 } else { 83 mListener->queueBuffer(index, n); 84 } 85} 86 87//////////////////////////////////////////////////////////////////////////////// 88 89struct MyClient : public BnMediaPlayerClient { 90 MyClient() 91 : mEOS(false) { 92 } 93 94 virtual void notify(int msg, int ext1, int ext2) { 95 Mutex::Autolock autoLock(mLock); 96 97 if (msg == MEDIA_ERROR || msg == MEDIA_PLAYBACK_COMPLETE) { 98 mEOS = true; 99 mCondition.signal(); 100 } 101 } 102 103 void waitForEOS() { 104 Mutex::Autolock autoLock(mLock); 105 while (!mEOS) { 106 mCondition.wait(mLock); 107 } 108 } 109 110protected: 111 virtual ~MyClient() { 112 } 113 114private: 115 Mutex mLock; 116 Condition mCondition; 117 118 bool mEOS; 119 120 DISALLOW_EVIL_CONSTRUCTORS(MyClient); 121}; 122 123int main(int argc, char **argv) { 124 android::ProcessState::self()->startThreadPool(); 125 126 if (argc != 2) { 127 fprintf(stderr, "Usage: %s filename\n", argv[0]); 128 return 1; 129 } 130 131 sp<SurfaceComposerClient> composerClient = new SurfaceComposerClient; 132 CHECK_EQ(composerClient->initCheck(), (status_t)OK); 133 134 sp<SurfaceControl> control = 135 composerClient->createSurface( 136 getpid(), 137 String8("A Surface"), 138 0, 139 1280, 140 800, 141 PIXEL_FORMAT_RGB_565, 142 0); 143 144 CHECK(control != NULL); 145 CHECK(control->isValid()); 146 147 CHECK_EQ(composerClient->openTransaction(), (status_t)OK); 148 CHECK_EQ(control->setLayer(30000), (status_t)OK); 149 CHECK_EQ(control->show(), (status_t)OK); 150 CHECK_EQ(composerClient->closeTransaction(), (status_t)OK); 151 152 sp<Surface> surface = control->getSurface(); 153 CHECK(surface != NULL); 154 155 sp<IServiceManager> sm = defaultServiceManager(); 156 sp<IBinder> binder = sm->getService(String16("media.player")); 157 sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder); 158 159 CHECK(service.get() != NULL); 160 161 int fd = open(argv[1], O_RDONLY); 162 163 if (fd < 0) { 164 fprintf(stderr, "Failed to open file '%s'.", argv[1]); 165 return 1; 166 } 167 168 sp<MyClient> client = new MyClient; 169 170 sp<IMediaPlayer> player = 171 service->create(getpid(), client, new MyStreamSource(fd), 0); 172 173 if (player != NULL) { 174 player->setVideoSurface(surface); 175 player->start(); 176 177 client->waitForEOS(); 178 179 player->stop(); 180 } else { 181 fprintf(stderr, "failed to instantiate player.\n"); 182 } 183 184 close(fd); 185 fd = -1; 186 187 composerClient->dispose(); 188 189 return 0; 190} 191