1 /*
2 * Copyright (C) 2009 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 //#define LOG_NDEBUG 0
18 #define LOG_TAG "MediaPlayerImpl"
19 #include "utils/Log.h"
20
21 #include <OMX_Component.h>
22
23 #include <unistd.h>
24
25 #include <media/stagefright/AudioPlayer.h>
26 #include <media/stagefright/CachingDataSource.h>
27 // #include <media/stagefright/CameraSource.h>
28 #include <media/stagefright/HTTPDataSource.h>
29 #include <media/stagefright/HTTPStream.h>
30 #include <media/stagefright/MediaDebug.h>
31 #include <media/stagefright/MediaExtractor.h>
32 #include <media/stagefright/MediaPlayerImpl.h>
33 #include <media/stagefright/MetaData.h>
34 #include <media/stagefright/MmapSource.h>
35 #include <media/stagefright/OMXCodec.h>
36 #include <media/stagefright/ShoutcastSource.h>
37 #include <media/stagefright/TimeSource.h>
38 #include <ui/PixelFormat.h>
39 #include <ui/Surface.h>
40
41 namespace android {
42
MediaPlayerImpl(const char * uri)43 MediaPlayerImpl::MediaPlayerImpl(const char *uri)
44 : mInitCheck(NO_INIT),
45 mTimeSource(NULL),
46 mAudioPlayer(NULL),
47 mVideoWidth(0),
48 mVideoHeight(0),
49 mVideoPosition(0),
50 mDuration(0),
51 mPlaying(false),
52 mPaused(false),
53 mSeeking(false) {
54 LOGI("MediaPlayerImpl(%s)", uri);
55 DataSource::RegisterDefaultSniffers();
56
57 status_t err = mClient.connect();
58 if (err != OK) {
59 LOGE("Failed to connect to OMXClient.");
60 return;
61 }
62
63 if (!strncasecmp("shoutcast://", uri, 12)) {
64 setAudioSource(makeShoutcastSource(uri));
65 #if 0
66 } else if (!strncasecmp("camera:", uri, 7)) {
67 mVideoWidth = 480;
68 mVideoHeight = 320;
69 mVideoDecoder = CameraSource::Create();
70 #endif
71 } else {
72 sp<DataSource> source;
73 if (!strncasecmp("file://", uri, 7)) {
74 source = new MmapSource(uri + 7);
75 } else if (!strncasecmp("http://", uri, 7)) {
76 source = new HTTPDataSource(uri);
77 source = new CachingDataSource(source, 64 * 1024, 10);
78 } else {
79 // Assume it's a filename.
80 source = new MmapSource(uri);
81 }
82
83 mExtractor = MediaExtractor::Create(source);
84
85 if (mExtractor == NULL) {
86 return;
87 }
88 }
89
90 init();
91
92 mInitCheck = OK;
93 }
94
MediaPlayerImpl(int fd,int64_t offset,int64_t length)95 MediaPlayerImpl::MediaPlayerImpl(int fd, int64_t offset, int64_t length)
96 : mInitCheck(NO_INIT),
97 mTimeSource(NULL),
98 mAudioPlayer(NULL),
99 mVideoWidth(0),
100 mVideoHeight(0),
101 mVideoPosition(0),
102 mDuration(0),
103 mPlaying(false),
104 mPaused(false),
105 mSeeking(false) {
106 LOGI("MediaPlayerImpl(%d, %lld, %lld)", fd, offset, length);
107 DataSource::RegisterDefaultSniffers();
108
109 status_t err = mClient.connect();
110 if (err != OK) {
111 LOGE("Failed to connect to OMXClient.");
112 return;
113 }
114
115 mExtractor = MediaExtractor::Create(
116 new MmapSource(fd, offset, length));
117
118 if (mExtractor == NULL) {
119 return;
120 }
121
122 init();
123
124 mInitCheck = OK;
125 }
126
initCheck() const127 status_t MediaPlayerImpl::initCheck() const {
128 return mInitCheck;
129 }
130
~MediaPlayerImpl()131 MediaPlayerImpl::~MediaPlayerImpl() {
132 stop();
133 setSurface(NULL);
134
135 if (mInitCheck == OK) {
136 mClient.disconnect();
137 }
138
139 LOGV("~MediaPlayerImpl done.");
140 }
141
play()142 void MediaPlayerImpl::play() {
143 LOGI("play");
144
145 if (mPlaying) {
146 if (mPaused) {
147 if (mAudioSource != NULL) {
148 mAudioPlayer->resume();
149 }
150 mPaused = false;
151 }
152 return;
153 }
154
155 mPlaying = true;
156
157 if (mAudioSource != NULL) {
158 mAudioPlayer = new AudioPlayer(mAudioSink);
159 mAudioPlayer->setSource(mAudioDecoder);
160
161 if (mVideoDecoder == NULL) {
162 // If there is no video, start playing right away,
163 // otherwise we'll start the audio player after we decode
164 // the first video frame, this way we won't be behind right
165 // away.
166 mAudioPlayer->start();
167 }
168
169 mTimeSource = mAudioPlayer;
170 } else {
171 mTimeSource = new SystemTimeSource;
172 }
173
174 if (mVideoDecoder != NULL) {
175 pthread_attr_t attr;
176 pthread_attr_init(&attr);
177 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
178
179 pthread_create(&mVideoThread, &attr, VideoWrapper, this);
180
181 pthread_attr_destroy(&attr);
182 }
183 }
184
pause()185 void MediaPlayerImpl::pause() {
186 if (!mPlaying || mPaused) {
187 return;
188 }
189
190 if (mAudioSource != NULL) {
191 mAudioPlayer->pause();
192 }
193
194 mPaused = true;
195 }
196
stop()197 void MediaPlayerImpl::stop() {
198 if (!mPlaying) {
199 return;
200 }
201
202 mPlaying = false;
203
204 if (mVideoDecoder != NULL) {
205 void *dummy;
206 pthread_join(mVideoThread, &dummy);
207 }
208
209 if (mAudioSource != NULL) {
210 mAudioPlayer->stop();
211
212 delete mAudioPlayer;
213 mAudioPlayer = NULL;
214 } else {
215 delete mTimeSource;
216 }
217
218 mTimeSource = NULL;
219 }
220
221 // static
VideoWrapper(void * me)222 void *MediaPlayerImpl::VideoWrapper(void *me) {
223 ((MediaPlayerImpl *)me)->videoEntry();
224
225 return NULL;
226 }
227
videoEntry()228 void MediaPlayerImpl::videoEntry() {
229 bool firstFrame = true;
230 bool eof = false;
231
232 status_t err = mVideoDecoder->start();
233 CHECK_EQ(err, OK);
234
235 while (mPlaying) {
236 MediaBuffer *buffer;
237
238 MediaSource::ReadOptions options;
239 bool seeking = false;
240
241 {
242 Mutex::Autolock autoLock(mLock);
243 if (mSeeking) {
244 LOGI("seek-options to %lld", mSeekTimeUs);
245 options.setSeekTo(mSeekTimeUs);
246
247 mSeeking = false;
248 seeking = true;
249 eof = false;
250 }
251 }
252
253 if (eof || mPaused) {
254 usleep(100000);
255 continue;
256 }
257
258 status_t err = mVideoDecoder->read(&buffer, &options);
259 CHECK((err == OK && buffer != NULL) || (err != OK && buffer == NULL));
260
261 if (err == ERROR_END_OF_STREAM || err != OK) {
262 eof = true;
263 continue;
264 }
265
266 if (buffer->range_length() == 0) {
267 // The final buffer is empty.
268 buffer->release();
269 continue;
270 }
271
272 int32_t units, scale;
273 bool success =
274 buffer->meta_data()->findInt32(kKeyTimeUnits, &units);
275 CHECK(success);
276 success =
277 buffer->meta_data()->findInt32(kKeyTimeScale, &scale);
278 CHECK(success);
279
280 int64_t pts_us = (int64_t)units * 1000000 / scale;
281 {
282 Mutex::Autolock autoLock(mLock);
283 mVideoPosition = pts_us;
284
285 LOGV("now_video = %.2f secs (%lld ms)",
286 pts_us / 1E6, (pts_us + 500) / 1000);
287 }
288
289 if (seeking && mAudioPlayer != NULL) {
290 // Now that we know where exactly video seeked (taking sync-samples
291 // into account), we will seek the audio track to the same time.
292 mAudioPlayer->seekTo(pts_us);
293 }
294
295 if (firstFrame || seeking) {
296 if (firstFrame && mAudioPlayer != NULL) {
297 // We've deferred starting the audio player until now.
298 mAudioPlayer->start();
299 }
300 mTimeSourceDeltaUs = mTimeSource->getRealTimeUs() - pts_us;
301 firstFrame = false;
302 }
303
304 displayOrDiscardFrame(buffer, pts_us);
305 }
306
307 mVideoDecoder->stop();
308 }
309
displayOrDiscardFrame(MediaBuffer * buffer,int64_t pts_us)310 void MediaPlayerImpl::displayOrDiscardFrame(
311 MediaBuffer *buffer, int64_t pts_us) {
312 for (;;) {
313 if (!mPlaying || mPaused) {
314 buffer->release();
315 buffer = NULL;
316
317 return;
318 }
319
320 int64_t realtime_us, mediatime_us;
321 if (mAudioPlayer != NULL
322 && mAudioPlayer->getMediaTimeMapping(&realtime_us, &mediatime_us)) {
323 mTimeSourceDeltaUs = realtime_us - mediatime_us;
324 LOGV("mTimeSourceDeltaUs = %.2f secs", mTimeSourceDeltaUs / 1E6);
325 }
326
327 int64_t now_us = mTimeSource->getRealTimeUs();
328 now_us -= mTimeSourceDeltaUs;
329
330 int64_t delay_us = pts_us - now_us;
331
332 if (delay_us < -15000) {
333 // We're late.
334
335 LOGI("we're late by %lld ms, dropping a frame\n",
336 -delay_us / 1000);
337
338 buffer->release();
339 buffer = NULL;
340 return;
341 } else if (delay_us > 100000) {
342 LOGI("we're much too early (by %lld ms)\n",
343 delay_us / 1000);
344 usleep(100000);
345 continue;
346 } else if (delay_us > 0) {
347 usleep(delay_us);
348 }
349
350 break;
351 }
352
353 {
354 Mutex::Autolock autoLock(mLock);
355 if (mVideoRenderer.get() != NULL) {
356 sendFrameToISurface(buffer);
357 }
358 }
359
360 buffer->release();
361 buffer = NULL;
362 }
363
init()364 void MediaPlayerImpl::init() {
365 if (mExtractor != NULL) {
366 size_t num_tracks = mExtractor->countTracks();
367
368 mDuration = 0;
369
370 for (size_t i = 0; i < num_tracks; ++i) {
371 const sp<MetaData> meta = mExtractor->getTrackMetaData(i);
372 CHECK(meta != NULL);
373
374 const char *mime;
375 if (!meta->findCString(kKeyMIMEType, &mime)) {
376 continue;
377 }
378
379 bool is_audio = false;
380 bool is_acceptable = false;
381 if (!strncasecmp(mime, "audio/", 6)) {
382 is_audio = true;
383 is_acceptable = (mAudioSource == NULL);
384 } else if (!strncasecmp(mime, "video/", 6)) {
385 is_acceptable = (mVideoSource == NULL);
386 }
387
388 if (!is_acceptable) {
389 continue;
390 }
391
392 sp<MediaSource> source = mExtractor->getTrack(i);
393
394 int32_t units, scale;
395 if (meta->findInt32(kKeyDuration, &units)
396 && meta->findInt32(kKeyTimeScale, &scale)) {
397 int64_t duration_us = (int64_t)units * 1000000 / scale;
398 if (duration_us > mDuration) {
399 mDuration = duration_us;
400 }
401 }
402
403 if (is_audio) {
404 setAudioSource(source);
405 } else {
406 setVideoSource(source);
407 }
408 }
409 }
410 }
411
setAudioSource(const sp<MediaSource> & source)412 void MediaPlayerImpl::setAudioSource(const sp<MediaSource> &source) {
413 LOGI("setAudioSource");
414 mAudioSource = source;
415
416 sp<MetaData> meta = source->getFormat();
417
418 mAudioDecoder = OMXCodec::Create(
419 mClient.interface(), meta, false /* createEncoder */, source);
420 }
421
setVideoSource(const sp<MediaSource> & source)422 void MediaPlayerImpl::setVideoSource(const sp<MediaSource> &source) {
423 LOGI("setVideoSource");
424 mVideoSource = source;
425
426 sp<MetaData> meta = source->getFormat();
427
428 bool success = meta->findInt32(kKeyWidth, &mVideoWidth);
429 CHECK(success);
430
431 success = meta->findInt32(kKeyHeight, &mVideoHeight);
432 CHECK(success);
433
434 mVideoDecoder = OMXCodec::Create(
435 mClient.interface(), meta, false /* createEncoder */, source);
436
437 if (mISurface.get() != NULL || mSurface.get() != NULL) {
438 depopulateISurface();
439 populateISurface();
440 }
441 }
442
setSurface(const sp<Surface> & surface)443 void MediaPlayerImpl::setSurface(const sp<Surface> &surface) {
444 LOGI("setSurface %p", surface.get());
445 Mutex::Autolock autoLock(mLock);
446
447 depopulateISurface();
448
449 mSurface = surface;
450 mISurface = NULL;
451
452 if (mSurface.get() != NULL) {
453 populateISurface();
454 }
455 }
456
setISurface(const sp<ISurface> & isurface)457 void MediaPlayerImpl::setISurface(const sp<ISurface> &isurface) {
458 LOGI("setISurface %p", isurface.get());
459 Mutex::Autolock autoLock(mLock);
460
461 depopulateISurface();
462
463 mSurface = NULL;
464 mISurface = isurface;
465
466 if (mISurface.get() != NULL) {
467 populateISurface();
468 }
469 }
470
makeShoutcastSource(const char * uri)471 MediaSource *MediaPlayerImpl::makeShoutcastSource(const char *uri) {
472 if (strncasecmp(uri, "shoutcast://", 12)) {
473 return NULL;
474 }
475
476 string host;
477 string path;
478 int port;
479
480 char *slash = strchr(uri + 12, '/');
481 if (slash == NULL) {
482 host = uri + 12;
483 path = "/";
484 } else {
485 host = string(uri + 12, slash - (uri + 12));
486 path = slash;
487 }
488
489 char *colon = strchr(host.c_str(), ':');
490 if (colon == NULL) {
491 port = 80;
492 } else {
493 char *end;
494 long tmp = strtol(colon + 1, &end, 10);
495 CHECK(end > colon + 1);
496 CHECK(tmp > 0 && tmp < 65536);
497 port = tmp;
498
499 host = string(host, 0, colon - host.c_str());
500 }
501
502 LOGI("Connecting to host '%s', port %d, path '%s'",
503 host.c_str(), port, path.c_str());
504
505 HTTPStream *http = new HTTPStream;
506 int http_status;
507
508 for (;;) {
509 status_t err = http->connect(host.c_str(), port);
510 CHECK_EQ(err, OK);
511
512 err = http->send("GET ");
513 err = http->send(path.c_str());
514 err = http->send(" HTTP/1.1\r\n");
515 err = http->send("Host: ");
516 err = http->send(host.c_str());
517 err = http->send("\r\n");
518 err = http->send("Icy-MetaData: 1\r\n\r\n");
519
520 CHECK_EQ(OK, http->receive_header(&http_status));
521
522 if (http_status == 301 || http_status == 302) {
523 string location;
524 CHECK(http->find_header_value("Location", &location));
525
526 CHECK(string(location, 0, 7) == "http://");
527 location.erase(0, 7);
528 string::size_type slashPos = location.find('/');
529 if (slashPos == string::npos) {
530 slashPos = location.size();
531 location += '/';
532 }
533
534 http->disconnect();
535
536 LOGI("Redirecting to %s\n", location.c_str());
537
538 host = string(location, 0, slashPos);
539
540 string::size_type colonPos = host.find(':');
541 if (colonPos != string::npos) {
542 const char *start = host.c_str() + colonPos + 1;
543 char *end;
544 long tmp = strtol(start, &end, 10);
545 CHECK(end > start && (*end == '\0'));
546
547 port = (tmp >= 0 && tmp < 65536) ? (int)tmp : 80;
548 } else {
549 port = 80;
550 }
551
552 path = string(location, slashPos);
553
554 continue;
555 }
556
557 break;
558 }
559
560 if (http_status != 200) {
561 LOGE("Connection failed: http_status = %d", http_status);
562 return NULL;
563 }
564
565 MediaSource *source = new ShoutcastSource(http);
566
567 return source;
568 }
569
isPlaying() const570 bool MediaPlayerImpl::isPlaying() const {
571 return mPlaying && !mPaused;
572 }
573
getDuration()574 int64_t MediaPlayerImpl::getDuration() {
575 return mDuration;
576 }
577
getPosition()578 int64_t MediaPlayerImpl::getPosition() {
579 int64_t position = 0;
580 if (mVideoSource != NULL) {
581 Mutex::Autolock autoLock(mLock);
582 position = mVideoPosition;
583 } else if (mAudioPlayer != NULL) {
584 position = mAudioPlayer->getMediaTimeUs();
585 }
586
587 return position;
588 }
589
seekTo(int64_t time)590 status_t MediaPlayerImpl::seekTo(int64_t time) {
591 LOGI("seekTo %lld", time);
592
593 if (mPaused) {
594 return UNKNOWN_ERROR;
595 }
596
597 if (mVideoSource == NULL && mAudioPlayer != NULL) {
598 mAudioPlayer->seekTo(time);
599 } else {
600 Mutex::Autolock autoLock(mLock);
601 mSeekTimeUs = time;
602 mSeeking = true;
603 }
604
605 return OK;
606 }
607
populateISurface()608 void MediaPlayerImpl::populateISurface() {
609 if (mVideoSource == NULL) {
610 return;
611 }
612
613 sp<MetaData> meta = mVideoDecoder->getFormat();
614
615 int32_t format;
616 const char *component;
617 int32_t decodedWidth, decodedHeight;
618 bool success = meta->findInt32(kKeyColorFormat, &format);
619 success = success && meta->findCString(kKeyDecoderComponent, &component);
620 success = success && meta->findInt32(kKeyWidth, &decodedWidth);
621 success = success && meta->findInt32(kKeyHeight, &decodedHeight);
622 CHECK(success);
623
624 if (mSurface.get() != NULL) {
625 mVideoRenderer =
626 mClient.interface()->createRenderer(
627 mSurface, component,
628 (OMX_COLOR_FORMATTYPE)format,
629 decodedWidth, decodedHeight,
630 mVideoWidth, mVideoHeight);
631 } else {
632 mVideoRenderer =
633 mClient.interface()->createRenderer(
634 mISurface, component,
635 (OMX_COLOR_FORMATTYPE)format,
636 decodedWidth, decodedHeight,
637 mVideoWidth, mVideoHeight);
638 }
639 }
640
depopulateISurface()641 void MediaPlayerImpl::depopulateISurface() {
642 mVideoRenderer.clear();
643 }
644
sendFrameToISurface(MediaBuffer * buffer)645 void MediaPlayerImpl::sendFrameToISurface(MediaBuffer *buffer) {
646 void *id;
647 if (buffer->meta_data()->findPointer(kKeyBufferID, &id)) {
648 mVideoRenderer->render((IOMX::buffer_id)id);
649 }
650 }
651
setAudioSink(const sp<MediaPlayerBase::AudioSink> & audioSink)652 void MediaPlayerImpl::setAudioSink(
653 const sp<MediaPlayerBase::AudioSink> &audioSink) {
654 LOGI("setAudioSink %p", audioSink.get());
655 mAudioSink = audioSink;
656 }
657
658 } // namespace android
659
660