diff options
Diffstat (limited to 'media/libstagefright/MediaPlayerImpl.cpp')
-rw-r--r-- | media/libstagefright/MediaPlayerImpl.cpp | 658 |
1 files changed, 0 insertions, 658 deletions
diff --git a/media/libstagefright/MediaPlayerImpl.cpp b/media/libstagefright/MediaPlayerImpl.cpp deleted file mode 100644 index c1044a3..0000000 --- a/media/libstagefright/MediaPlayerImpl.cpp +++ /dev/null @@ -1,658 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -//#define LOG_NDEBUG 0 -#define LOG_TAG "MediaPlayerImpl" -#include "utils/Log.h" - -#include "include/stagefright_string.h" -#include "include/HTTPStream.h" - -#include <OMX_Component.h> - -#include <unistd.h> - -#include <media/stagefright/AudioPlayer.h> -// #include <media/stagefright/CameraSource.h> -#include <media/stagefright/MediaDebug.h> -#include <media/stagefright/MediaDefs.h> -#include <media/stagefright/MediaExtractor.h> -#include <media/stagefright/MediaPlayerImpl.h> -#include <media/stagefright/MetaData.h> -#include <media/stagefright/MmapSource.h> -#include <media/stagefright/OMXCodec.h> -#include <media/stagefright/ShoutcastSource.h> -#include <media/stagefright/TimeSource.h> -#include <ui/PixelFormat.h> -#include <ui/Surface.h> - -namespace android { - -MediaPlayerImpl::MediaPlayerImpl(const char *uri) - : mInitCheck(NO_INIT), - mTimeSource(NULL), - mAudioPlayer(NULL), - mVideoWidth(0), - mVideoHeight(0), - mVideoPosition(0), - mDuration(0), - mPlaying(false), - mPaused(false), - mSeeking(false) { - LOGV("MediaPlayerImpl(%s)", uri); - DataSource::RegisterDefaultSniffers(); - - status_t err = mClient.connect(); - if (err != OK) { - LOGE("Failed to connect to OMXClient."); - return; - } - - if (!strncasecmp("shoutcast://", uri, 12)) { - setAudioSource(makeShoutcastSource(uri)); -#if 0 - } else if (!strncasecmp("camera:", uri, 7)) { - mVideoWidth = 480; - mVideoHeight = 320; - mVideoDecoder = CameraSource::Create(); -#endif - } else { - mExtractor = MediaExtractor::CreateFromURI(uri); - - if (mExtractor == NULL) { - return; - } - } - - init(); - - mInitCheck = OK; -} - -MediaPlayerImpl::MediaPlayerImpl(int fd, int64_t offset, int64_t length) - : mInitCheck(NO_INIT), - mTimeSource(NULL), - mAudioPlayer(NULL), - mVideoWidth(0), - mVideoHeight(0), - mVideoPosition(0), - mDuration(0), - mPlaying(false), - mPaused(false), - mSeeking(false) { - LOGV("MediaPlayerImpl(%d, %lld, %lld)", fd, offset, length); - DataSource::RegisterDefaultSniffers(); - - status_t err = mClient.connect(); - if (err != OK) { - LOGE("Failed to connect to OMXClient."); - return; - } - - mExtractor = MediaExtractor::Create( - new MmapSource(fd, offset, length)); - - if (mExtractor == NULL) { - return; - } - - init(); - - mInitCheck = OK; -} - -status_t MediaPlayerImpl::initCheck() const { - return mInitCheck; -} - -MediaPlayerImpl::~MediaPlayerImpl() { - stop(); - setSurface(NULL); - - if (mInitCheck == OK) { - mClient.disconnect(); - } - - LOGV("~MediaPlayerImpl done."); -} - -void MediaPlayerImpl::play() { - LOGV("play"); - - if (mPlaying) { - if (mPaused) { - if (mAudioSource != NULL) { - mAudioPlayer->resume(); - } - mPaused = false; - } - return; - } - - mPlaying = true; - - if (mAudioSource != NULL) { - mAudioPlayer = new AudioPlayer(mAudioSink); - mAudioPlayer->setSource(mAudioDecoder); - - if (mVideoDecoder == NULL) { - // If there is no video, start playing right away, - // otherwise we'll start the audio player after we decode - // the first video frame, this way we won't be behind right - // away. - mAudioPlayer->start(); - } - - mTimeSource = mAudioPlayer; - } else { - mTimeSource = new SystemTimeSource; - } - - if (mVideoDecoder != NULL) { - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); - - pthread_create(&mVideoThread, &attr, VideoWrapper, this); - - pthread_attr_destroy(&attr); - } -} - -void MediaPlayerImpl::pause() { - if (!mPlaying || mPaused) { - return; - } - - if (mAudioSource != NULL) { - mAudioPlayer->pause(); - } - - mPaused = true; -} - -void MediaPlayerImpl::stop() { - if (!mPlaying) { - return; - } - - mPlaying = false; - - if (mVideoDecoder != NULL) { - void *dummy; - pthread_join(mVideoThread, &dummy); - } - - if (mAudioSource != NULL) { - mAudioPlayer->stop(); - - delete mAudioPlayer; - mAudioPlayer = NULL; - } else { - delete mTimeSource; - } - - mTimeSource = NULL; -} - -// static -void *MediaPlayerImpl::VideoWrapper(void *me) { - ((MediaPlayerImpl *)me)->videoEntry(); - - return NULL; -} - -void MediaPlayerImpl::videoEntry() { - bool firstFrame = true; - bool eof = false; - - status_t err = mVideoDecoder->start(); - CHECK_EQ(err, OK); - - while (mPlaying) { - MediaBuffer *buffer; - - MediaSource::ReadOptions options; - bool seeking = false; - - { - Mutex::Autolock autoLock(mLock); - if (mSeeking) { - LOGV("seek-options to %lld", mSeekTimeUs); - options.setSeekTo(mSeekTimeUs); - - mSeeking = false; - seeking = true; - eof = false; - } - } - - if (eof || mPaused) { - usleep(100000); - continue; - } - - status_t err = mVideoDecoder->read(&buffer, &options); - CHECK((err == OK && buffer != NULL) || (err != OK && buffer == NULL)); - - if (err == INFO_FORMAT_CHANGED) { - LOGV("format changed."); - depopulateISurface(); - populateISurface(); - continue; - } - - if (err == ERROR_END_OF_STREAM || err != OK) { - eof = true; - continue; - } - - if (buffer->range_length() == 0) { - // The final buffer is empty. - buffer->release(); - continue; - } - - int64_t pts_us; - CHECK(buffer->meta_data()->findInt64(kKeyTime, &pts_us)); - - { - Mutex::Autolock autoLock(mLock); - mVideoPosition = pts_us; - - LOGV("now_video = %.2f secs (%lld ms)", - pts_us / 1E6, (pts_us + 500) / 1000); - } - - if (seeking && mAudioPlayer != NULL) { - // Now that we know where exactly video seeked (taking sync-samples - // into account), we will seek the audio track to the same time. - mAudioPlayer->seekTo(pts_us); - } - - if (firstFrame || seeking) { - if (firstFrame && mAudioPlayer != NULL) { - // We've deferred starting the audio player until now. - mAudioPlayer->start(); - } - mTimeSourceDeltaUs = mTimeSource->getRealTimeUs() - pts_us; - firstFrame = false; - } - - displayOrDiscardFrame(buffer, pts_us); - } - - mVideoDecoder->stop(); -} - -void MediaPlayerImpl::displayOrDiscardFrame( - MediaBuffer *buffer, int64_t pts_us) { - for (;;) { - if (!mPlaying || mPaused) { - buffer->release(); - buffer = NULL; - - return; - } - - int64_t realtime_us, mediatime_us; - if (mAudioPlayer != NULL - && mAudioPlayer->getMediaTimeMapping(&realtime_us, &mediatime_us)) { - mTimeSourceDeltaUs = realtime_us - mediatime_us; - LOGV("mTimeSourceDeltaUs = %.2f secs", mTimeSourceDeltaUs / 1E6); - } - - int64_t now_us = mTimeSource->getRealTimeUs(); - now_us -= mTimeSourceDeltaUs; - - int64_t delay_us = pts_us - now_us; - - if (delay_us < -15000) { - // We're late. - - LOGV("we're late by %lld ms, dropping a frame\n", - -delay_us / 1000); - - buffer->release(); - buffer = NULL; - return; - } else if (delay_us > 100000) { - LOGV("we're much too early (by %lld ms)\n", - delay_us / 1000); - usleep(100000); - continue; - } else if (delay_us > 0) { - usleep(delay_us); - } - - break; - } - - { - Mutex::Autolock autoLock(mLock); - if (mVideoRenderer.get() != NULL) { - sendFrameToISurface(buffer); - } - } - - buffer->release(); - buffer = NULL; -} - -void MediaPlayerImpl::init() { - if (mExtractor != NULL) { - size_t num_tracks = mExtractor->countTracks(); - - mDuration = 0; - - for (size_t i = 0; i < num_tracks; ++i) { - const sp<MetaData> meta = mExtractor->getTrackMetaData(i); - CHECK(meta != NULL); - - const char *mime; - if (!meta->findCString(kKeyMIMEType, &mime)) { - continue; - } - - bool is_audio = false; - bool is_acceptable = false; - if (!strncasecmp(mime, "audio/", 6)) { - is_audio = true; - is_acceptable = (mAudioSource == NULL); - } else if (!strncasecmp(mime, "video/", 6)) { - is_acceptable = (mVideoSource == NULL); - } - - if (!is_acceptable) { - continue; - } - - sp<MediaSource> source = mExtractor->getTrack(i); - - int64_t durationUs; - if (meta->findInt64(kKeyDuration, &durationUs)) { - if (durationUs > mDuration) { - mDuration = durationUs; - } - } - - if (is_audio) { - setAudioSource(source); - } else { - setVideoSource(source); - } - } - } -} - -void MediaPlayerImpl::setAudioSource(const sp<MediaSource> &source) { - LOGV("setAudioSource"); - mAudioSource = source; - - sp<MetaData> meta = source->getFormat(); - - const char *mime; - CHECK(meta->findCString(kKeyMIMEType, &mime)); - - if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) { - mAudioDecoder = source; - } else { - mAudioDecoder = OMXCodec::Create( - mClient.interface(), meta, false /* createEncoder */, source); - } -} - -void MediaPlayerImpl::setVideoSource(const sp<MediaSource> &source) { - LOGV("setVideoSource"); - mVideoSource = source; - - sp<MetaData> meta = source->getFormat(); - - bool success = meta->findInt32(kKeyWidth, &mVideoWidth); - CHECK(success); - - success = meta->findInt32(kKeyHeight, &mVideoHeight); - CHECK(success); - - mVideoDecoder = OMXCodec::Create( - mClient.interface(), meta, false /* createEncoder */, source); - - if (mISurface.get() != NULL || mSurface.get() != NULL) { - depopulateISurface(); - populateISurface(); - } -} - -void MediaPlayerImpl::setSurface(const sp<Surface> &surface) { - LOGV("setSurface %p", surface.get()); - Mutex::Autolock autoLock(mLock); - - depopulateISurface(); - - mSurface = surface; - mISurface = NULL; - - if (mSurface.get() != NULL) { - populateISurface(); - } -} - -void MediaPlayerImpl::setISurface(const sp<ISurface> &isurface) { - LOGV("setISurface %p", isurface.get()); - Mutex::Autolock autoLock(mLock); - - depopulateISurface(); - - mSurface = NULL; - mISurface = isurface; - - if (mISurface.get() != NULL) { - populateISurface(); - } -} - -MediaSource *MediaPlayerImpl::makeShoutcastSource(const char *uri) { - if (strncasecmp(uri, "shoutcast://", 12)) { - return NULL; - } - - string host; - string path; - int port; - - char *slash = strchr(uri + 12, '/'); - if (slash == NULL) { - host = uri + 12; - path = "/"; - } else { - host = string(uri + 12, slash - (uri + 12)); - path = slash; - } - - char *colon = strchr(host.c_str(), ':'); - if (colon == NULL) { - port = 80; - } else { - char *end; - long tmp = strtol(colon + 1, &end, 10); - CHECK(end > colon + 1); - CHECK(tmp > 0 && tmp < 65536); - port = tmp; - - host = string(host, 0, colon - host.c_str()); - } - - LOGV("Connecting to host '%s', port %d, path '%s'", - host.c_str(), port, path.c_str()); - - HTTPStream *http = new HTTPStream; - int http_status; - - for (;;) { - status_t err = http->connect(host.c_str(), port); - CHECK_EQ(err, OK); - - err = http->send("GET "); - err = http->send(path.c_str()); - err = http->send(" HTTP/1.1\r\n"); - err = http->send("Host: "); - err = http->send(host.c_str()); - err = http->send("\r\n"); - err = http->send("Icy-MetaData: 1\r\n\r\n"); - - CHECK_EQ(OK, http->receive_header(&http_status)); - - if (http_status == 301 || http_status == 302) { - string location; - CHECK(http->find_header_value("Location", &location)); - - CHECK(string(location, 0, 7) == "http://"); - location.erase(0, 7); - string::size_type slashPos = location.find('/'); - if (slashPos == string::npos) { - slashPos = location.size(); - location += '/'; - } - - http->disconnect(); - - LOGV("Redirecting to %s\n", location.c_str()); - - host = string(location, 0, slashPos); - - string::size_type colonPos = host.find(':'); - if (colonPos != string::npos) { - const char *start = host.c_str() + colonPos + 1; - char *end; - long tmp = strtol(start, &end, 10); - CHECK(end > start && (*end == '\0')); - - port = (tmp >= 0 && tmp < 65536) ? (int)tmp : 80; - } else { - port = 80; - } - - path = string(location, slashPos); - - continue; - } - - break; - } - - if (http_status != 200) { - LOGE("Connection failed: http_status = %d", http_status); - return NULL; - } - - MediaSource *source = new ShoutcastSource(http); - - return source; -} - -bool MediaPlayerImpl::isPlaying() const { - return mPlaying && !mPaused; -} - -int64_t MediaPlayerImpl::getDuration() { - return mDuration; -} - -int64_t MediaPlayerImpl::getPosition() { - int64_t position = 0; - if (mVideoSource != NULL) { - Mutex::Autolock autoLock(mLock); - position = mVideoPosition; - } else if (mAudioPlayer != NULL) { - position = mAudioPlayer->getMediaTimeUs(); - } - - return position; -} - -status_t MediaPlayerImpl::seekTo(int64_t time) { - LOGV("seekTo %lld", time); - - if (mPaused) { - return UNKNOWN_ERROR; - } - - if (mVideoSource == NULL && mAudioPlayer != NULL) { - mAudioPlayer->seekTo(time); - } else { - Mutex::Autolock autoLock(mLock); - mSeekTimeUs = time; - mSeeking = true; - } - - return OK; -} - -void MediaPlayerImpl::populateISurface() { - if (mVideoSource == NULL) { - return; - } - - sp<MetaData> meta = mVideoDecoder->getFormat(); - - int32_t format; - const char *component; - int32_t decodedWidth, decodedHeight; - bool success = meta->findInt32(kKeyColorFormat, &format); - success = success && meta->findCString(kKeyDecoderComponent, &component); - success = success && meta->findInt32(kKeyWidth, &decodedWidth); - success = success && meta->findInt32(kKeyHeight, &decodedHeight); - CHECK(success); - - LOGV("mVideoWidth=%d, mVideoHeight=%d, decodedWidth=%d, decodedHeight=%d", - mVideoWidth, mVideoHeight, decodedWidth, decodedHeight); - - if (mSurface.get() != NULL) { - mVideoRenderer = - mClient.interface()->createRenderer( - mSurface, component, - (OMX_COLOR_FORMATTYPE)format, - decodedWidth, decodedHeight, - mVideoWidth, mVideoHeight); - } else { - mVideoRenderer = - mClient.interface()->createRenderer( - mISurface, component, - (OMX_COLOR_FORMATTYPE)format, - decodedWidth, decodedHeight, - mVideoWidth, mVideoHeight); - } -} - -void MediaPlayerImpl::depopulateISurface() { - mVideoRenderer.clear(); -} - -void MediaPlayerImpl::sendFrameToISurface(MediaBuffer *buffer) { - void *id; - if (buffer->meta_data()->findPointer(kKeyBufferID, &id)) { - mVideoRenderer->render((IOMX::buffer_id)id); - } -} - -void MediaPlayerImpl::setAudioSink( - const sp<MediaPlayerBase::AudioSink> &audioSink) { - LOGV("setAudioSink %p", audioSink.get()); - mAudioSink = audioSink; -} - -} // namespace android - |