blob: bb84bd1ab995f2f13c73be9ec1afad5c6c3a4993 [file] [log] [blame]
James Dong199d1c12011-03-17 11:48:13 -07001/*
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
Andreas Huber52b52cd2010-11-23 11:41:34 -080017#include <binder/ProcessState.h>
18
19#include <media/IStreamSource.h>
20#include <media/mediaplayer.h>
21#include <media/stagefright/foundation/ADebug.h>
Andreas Huberae9d5072010-12-06 10:36:06 -080022#include <media/stagefright/foundation/AMessage.h>
Andreas Huber52b52cd2010-11-23 11:41:34 -080023
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;
Andreas Hubera1587462010-12-15 15:17:42 -080047 off64_t mFileSize;
48 int64_t mNextSeekTimeUs;
Andreas Huber52b52cd2010-11-23 11:41:34 -080049
50 sp<IStreamListener> mListener;
51 Vector<sp<IMemory> > mBuffers;
52
53 DISALLOW_EVIL_CONSTRUCTORS(MyStreamSource);
54};
55
56MyStreamSource::MyStreamSource(int fd)
Andreas Hubera1587462010-12-15 15:17:42 -080057 : mFd(fd),
58 mFileSize(0),
Andreas Huber54e66492010-12-23 10:27:40 -080059 mNextSeekTimeUs(-1) { // ALooper::GetNowUs() + 5000000ll) {
Andreas Huber52b52cd2010-11-23 11:41:34 -080060 CHECK_GE(fd, 0);
Andreas Hubera1587462010-12-15 15:17:42 -080061
62 mFileSize = lseek64(fd, 0, SEEK_END);
63 lseek64(fd, 0, SEEK_SET);
Andreas Huber52b52cd2010-11-23 11:41:34 -080064}
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());
Andreas Hubera1587462010-12-15 15:17:42 -080079
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
Andreas Huber52b52cd2010-11-23 11:41:34 -080093 sp<IMemory> mem = mBuffers.itemAt(index);
94
95 ssize_t n = read(mFd, mem->pointer(), mem->size());
96 if (n <= 0) {
Andreas Huberae9d5072010-12-06 10:36:06 -080097 mListener->issueCommand(IStreamListener::EOS, false /* synchronous */);
Andreas Huber52b52cd2010-11-23 11:41:34 -080098 } 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) {
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}