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