stream.cpp revision 54e6649e4cac3475593f3acb7894837fa1dc61eb
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(-1) {  // 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