• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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