Squashed commit of the following:

commit 1efc38dc3c33fef57b759002db3965ed07a28cb0
Author: Andreas Huber <andih@google.com>
Date:   Thu Nov 19 14:36:14 2009 -0800

    Sending the SEEK-COMPLETE notification temporarily broke seeking backwards in time behaviour. This is now fixed.

    Also, get rid of the semi-random delay after posting buffers to surface flinger in favour of delaying the buffer release until the next frame is displayed.

commit 51973062eb5ee63fd64b845d72bac517cc3369cf
Author: Andreas Huber <andih@google.com>
Date:   Wed Nov 18 14:01:43 2009 -0800

    Fix one more unit test, properly send seek-complete notification only after seek actually completed.

commit cb22250b34b1fcfe1bf459723a761fd003950229
Author: Andreas Huber <andih@google.com>
Date:   Wed Nov 18 12:31:36 2009 -0800

    Fix seek-while-paused in AwesomePlayer, revert to using FileSource if MmapSource fails.

commit 25eb9241138ddf7bb27ce90657116c5f8a94d880
Author: Andreas Huber <andih@google.com>
Date:   Wed Nov 18 12:30:40 2009 -0800

    Support seeking and duration in AMRExtractor, assuming all frames are the same size.

commit 44192f2ebb7ea3bbd3ba5910025692dbc6a08faa
Author: Andreas Huber <andih@google.com>
Date:   Wed Nov 18 10:21:44 2009 -0800

    MediaPlayerImpl is dead, long live AwesomePlayer.

commit c5b52d3c0674f5dc94db506afbce52401cceddac
Author: Andreas Huber <andih@google.com>
Date:   Wed Nov 18 09:42:23 2009 -0800

    New implementation of the stagefright mediaplayer.
diff --git a/cmds/stagefright/record.cpp b/cmds/stagefright/record.cpp
index 8c25d85..a31a5c0 100644
--- a/cmds/stagefright/record.cpp
+++ b/cmds/stagefright/record.cpp
@@ -19,13 +19,13 @@
 #include <binder/ProcessState.h>
 #include <media/stagefright/AudioPlayer.h>
 #include <media/stagefright/CameraSource.h>
+#include <media/stagefright/FileSource.h>
 #include <media/stagefright/MediaBufferGroup.h>
 #include <media/stagefright/MediaDebug.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/MediaExtractor.h>
 #include <media/stagefright/MPEG4Writer.h>
-#include <media/stagefright/MmapSource.h>
 #include <media/stagefright/OMXClient.h>
 #include <media/stagefright/OMXCodec.h>
 #include <media/MediaPlayerInterface.h>
@@ -105,7 +105,7 @@
     sp<MediaSource> source;
 
     sp<MediaExtractor> extractor =
-        MediaExtractor::Create(new MmapSource(filename));
+        MediaExtractor::Create(new FileSource(filename));
 
     size_t num_tracks = extractor->countTracks();
 
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index d26e558..76ec54b 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -24,15 +24,14 @@
 #include <binder/ProcessState.h>
 #include <media/IMediaPlayerService.h>
 #include <media/stagefright/CachingDataSource.h>
+#include <media/stagefright/FileSource.h>
 #include <media/stagefright/HTTPDataSource.h>
 #include <media/stagefright/JPEGSource.h>
 #include <media/stagefright/MediaDebug.h>
 #include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MediaPlayerImpl.h>
 #include <media/stagefright/MediaExtractor.h>
 #include <media/stagefright/MediaSource.h>
 #include <media/stagefright/MetaData.h>
-#include <media/stagefright/MmapSource.h>
 #include <media/stagefright/OMXClient.h>
 #include <media/stagefright/OMXCodec.h>
 
@@ -52,9 +51,6 @@
 static void playSource(OMXClient *client, const sp<MediaSource> &source) {
     sp<MetaData> meta = source->getFormat();
 
-    int64_t durationUs;
-    CHECK(meta->findInt64(kKeyDuration, &durationUs));
-
     const char *mime;
     CHECK(meta->findCString(kKeyMIMEType, &mime));
 
@@ -74,6 +70,9 @@
     rawSource->start();
 
     if (gReproduceBug >= 3 && gReproduceBug <= 5) {
+        int64_t durationUs;
+        CHECK(meta->findInt64(kKeyDuration, &durationUs));
+
         status_t err;
         MediaBuffer *buffer;
         MediaSource::ReadOptions options;
@@ -368,7 +367,7 @@
             dataSource = new HTTPDataSource(filename);
             dataSource = new CachingDataSource(dataSource, 64 * 1024, 10);
         } else {
-            dataSource = new MmapSource(filename);
+            dataSource = new FileSource(filename);
         }
 
         bool isJPEG = false;
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index f723cfd..6575da6 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -133,9 +133,9 @@
         return INVALID_OPERATION;
     };
 
-protected:
     virtual void        sendEvent(int msg, int ext1=0, int ext2=0) { if (mNotify) mNotify(mCookie, msg, ext1, ext2); }
 
+protected:
     void*               mCookie;
     notify_callback_f   mNotify;
 };
diff --git a/include/media/stagefright/AudioPlayer.h b/include/media/stagefright/AudioPlayer.h
index 960eda3..71344e6 100644
--- a/include/media/stagefright/AudioPlayer.h
+++ b/include/media/stagefright/AudioPlayer.h
@@ -30,12 +30,20 @@
 
 class AudioPlayer : public TimeSource {
 public:
+    enum {
+        REACHED_EOS,
+        SEEK_COMPLETE
+    };
+
     AudioPlayer(const sp<MediaPlayerBase::AudioSink> &audioSink);
     virtual ~AudioPlayer();
 
     // Caller retains ownership of "source".
     void setSource(const sp<MediaSource> &source);
 
+    void setListenerCallback(
+            void (*notify)(void *cookie, int what), void *cookie);
+
     // Return time in us.
     virtual int64_t getRealTimeUs();
 
@@ -76,6 +84,9 @@
 
     bool mStarted;
 
+    void (*mListenerCallback)(void *cookie, int what);
+    void *mListenerCookie;
+
     sp<MediaPlayerBase::AudioSink> mAudioSink;
 
     static void AudioCallback(int event, void *user, void *info);
diff --git a/include/media/stagefright/MediaPlayerImpl.h b/include/media/stagefright/MediaPlayerImpl.h
deleted file mode 100644
index 53a2088..0000000
--- a/include/media/stagefright/MediaPlayerImpl.h
+++ /dev/null
@@ -1,128 +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.
- */
-
-#ifndef MEDIA_PLAYER_IMPL_H_
-
-#define MEDIA_PLAYER_IMPL_H_
-
-#include <pthread.h>
-
-#include <media/MediaPlayerInterface.h>
-#include <media/stagefright/OMXClient.h>
-#include <utils/RefBase.h>
-#include <utils/threads.h>
-
-namespace android {
-
-class AudioPlayer;
-class IOMXRenderer;
-class ISurface;
-class MediaExtractor;
-class MediaBuffer;
-class MediaSource;
-class MemoryHeapPmem;
-class MetaData;
-class Surface;
-class TimeSource;
-
-class MediaPlayerImpl {
-public:
-    MediaPlayerImpl(const char *uri);
-
-    status_t initCheck() const;
-
-    // Assumes ownership of "fd".
-    MediaPlayerImpl(int fd, int64_t offset, int64_t length);
-
-    ~MediaPlayerImpl();
-
-    void play();
-    void pause();
-    bool isPlaying() const;
-
-    void setSurface(const sp<Surface> &surface);
-    void setISurface(const sp<ISurface> &isurface);
-
-    void setAudioSink(const sp<MediaPlayerBase::AudioSink> &audioSink);
-
-    int32_t getWidth() const { return mVideoWidth; }
-    int32_t getHeight() const { return mVideoHeight; }
-
-    int64_t getDuration();
-    int64_t getPosition();
-    status_t seekTo(int64_t time);
-
-private:
-    status_t mInitCheck;
-
-    OMXClient mClient;
-
-    sp<MediaExtractor> mExtractor;
-
-    TimeSource *mTimeSource;
-
-    sp<MediaSource> mAudioSource;
-    sp<MediaSource> mAudioDecoder;
-    AudioPlayer *mAudioPlayer;
-
-    sp<MediaSource> mVideoSource;
-    sp<MediaSource> mVideoDecoder;
-    int32_t mVideoWidth, mVideoHeight;
-    int64_t mVideoPosition;
-
-    int64_t mDuration;
-
-    bool mPlaying;
-    bool mPaused;
-
-    int64_t mTimeSourceDeltaUs;
-
-    sp<Surface> mSurface;
-    sp<ISurface> mISurface;
-    sp<IOMXRenderer> mVideoRenderer;
-
-    sp<MediaPlayerBase::AudioSink> mAudioSink;
-
-    Mutex mLock;
-    pthread_t mVideoThread;
-
-    bool mSeeking;
-    int64_t mSeekTimeUs;
-
-    void init();
-
-    static void *VideoWrapper(void *me);
-    void videoEntry();
-
-    void setAudioSource(const sp<MediaSource> &source);
-    void setVideoSource(const sp<MediaSource> &source);
-
-    MediaSource *makeShoutcastSource(const char *path);
-
-    void displayOrDiscardFrame(MediaBuffer *buffer, int64_t pts_us);
-    void populateISurface();
-    void depopulateISurface();
-    void sendFrameToISurface(MediaBuffer *buffer);
-
-    void stop();
-
-    MediaPlayerImpl(const MediaPlayerImpl &);
-    MediaPlayerImpl &operator=(const MediaPlayerImpl &);
-};
-
-}  // namespace android
-
-#endif  // MEDIA_PLAYER_IMPL_H_
diff --git a/include/media/stagefright/MmapSource.h b/include/media/stagefright/MmapSource.h
deleted file mode 100644
index 1b39d53..0000000
--- a/include/media/stagefright/MmapSource.h
+++ /dev/null
@@ -1,53 +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.
- */
-
-#ifndef MMAP_SOURCE_H_
-
-#define MMAP_SOURCE_H_
-
-#include <media/stagefright/DataSource.h>
-#include <media/stagefright/MediaErrors.h>
-
-namespace android {
-
-class MmapSource : public DataSource {
-public:
-    MmapSource(const char *filename);
-
-    // Assumes ownership of "fd".
-    MmapSource(int fd, int64_t offset, int64_t length);
-
-    virtual status_t initCheck() const;
-
-    virtual ssize_t readAt(off_t offset, void *data, size_t size);
-    virtual status_t getSize(off_t *size);
-
-protected:
-    virtual ~MmapSource();
-
-private:
-    int mFd;
-    void *mBase;
-    size_t mSize;
-
-    MmapSource(const MmapSource &);
-    MmapSource &operator=(const MmapSource &);
-};
-
-}  // namespace android
-
-#endif  // MMAP_SOURCE_H_
-
diff --git a/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp b/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
index 7a3aee8..42c1877 100644
--- a/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
+++ b/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
@@ -24,11 +24,11 @@
 #include <media/stagefright/CachingDataSource.h>
 #include <media/stagefright/ColorConverter.h>
 #include <media/stagefright/DataSource.h>
+#include <media/stagefright/FileSource.h>
 #include <media/stagefright/HTTPDataSource.h>
 #include <media/stagefright/MediaDebug.h>
 #include <media/stagefright/MediaExtractor.h>
 #include <media/stagefright/MetaData.h>
-#include <media/stagefright/MmapSource.h>
 #include <media/stagefright/OMXCodec.h>
 
 namespace android {
@@ -58,7 +58,7 @@
     LOGV("setDataSource(%d, %lld, %lld)", fd, offset, length);
 
     mExtractor = MediaExtractor::Create(
-            new MmapSource(fd, offset, length));
+            new FileSource(fd, offset, length));
 
     return OK;
 }
diff --git a/media/libmediaplayerservice/StagefrightPlayer.cpp b/media/libmediaplayerservice/StagefrightPlayer.cpp
index dbee451..5915105 100644
--- a/media/libmediaplayerservice/StagefrightPlayer.cpp
+++ b/media/libmediaplayerservice/StagefrightPlayer.cpp
@@ -3,19 +3,24 @@
 #include <utils/Log.h>
 
 #include "StagefrightPlayer.h"
-#include <media/stagefright/MediaPlayerImpl.h>
+
+#include "AwesomePlayer.h"
 
 namespace android {
 
 StagefrightPlayer::StagefrightPlayer()
-    : mPlayer(NULL) {
+    : mPlayer(new AwesomePlayer) {
     LOGV("StagefrightPlayer");
+
+    mPlayer->setListener(this);
 }
 
 StagefrightPlayer::~StagefrightPlayer() {
     LOGV("~StagefrightPlayer");
     reset();
-    LOGV("~StagefrightPlayer done.");
+
+    delete mPlayer;
+    mPlayer = NULL;
 }
 
 status_t StagefrightPlayer::initCheck() {
@@ -25,62 +30,32 @@
 
 status_t StagefrightPlayer::setDataSource(const char *url) {
     LOGV("setDataSource('%s')", url);
-
-    reset();
-    mPlayer = new MediaPlayerImpl(url);
-
-    status_t err = mPlayer->initCheck();
-    if (err != OK) {
-        delete mPlayer;
-        mPlayer = NULL;
-    } else {
-        mPlayer->setAudioSink(mAudioSink);
-    }
-
-    return err;
+    return mPlayer->setDataSource(url);
 }
 
 // Warning: The filedescriptor passed into this method will only be valid until
 // the method returns, if you want to keep it, dup it!
 status_t StagefrightPlayer::setDataSource(int fd, int64_t offset, int64_t length) {
     LOGV("setDataSource(%d, %lld, %lld)", fd, offset, length);
-
-    reset();
-    mPlayer = new MediaPlayerImpl(dup(fd), offset, length);
-
-    status_t err = mPlayer->initCheck();
-    if (err != OK) {
-        delete mPlayer;
-        mPlayer = NULL;
-    } else {
-        mPlayer->setAudioSink(mAudioSink);
-    }
-
-    return err;
+    return mPlayer->setDataSource(dup(fd), offset, length);
 }
 
 status_t StagefrightPlayer::setVideoSurface(const sp<ISurface> &surface) {
     LOGV("setVideoSurface");
 
-    if (mPlayer == NULL) {
-        return NO_INIT;
-    }
-
     mPlayer->setISurface(surface);
-
     return OK;
 }
 
 status_t StagefrightPlayer::prepare() {
     LOGV("prepare");
 
-    if (mPlayer == NULL) {
-        return NO_INIT;
+    int32_t width, height;
+    if (mPlayer->getVideoDimensions(&width, &height) != OK) {
+        width = height = 0;
     }
 
-    sendEvent(
-            MEDIA_SET_VIDEO_SIZE,
-            mPlayer->getWidth(), mPlayer->getHeight());
+    sendEvent(MEDIA_SET_VIDEO_SIZE, width, height);
 
     return OK;
 }
@@ -102,92 +77,76 @@
 status_t StagefrightPlayer::start() {
     LOGV("start");
 
-    if (mPlayer == NULL) {
-        return NO_INIT;
-    }
-
-    mPlayer->play();
-
-    return OK;
+    return mPlayer->play();
 }
 
 status_t StagefrightPlayer::stop() {
     LOGV("stop");
 
-    if (mPlayer == NULL) {
-        return NO_INIT;
-    }
-
-    reset();
-
-    return OK;
+    return pause();  // what's the difference?
 }
 
 status_t StagefrightPlayer::pause() {
     LOGV("pause");
 
-    if (mPlayer == NULL) {
-        return NO_INIT;
-    }
-
-    mPlayer->pause();
-
-    return OK;
+    return mPlayer->pause();
 }
 
 bool StagefrightPlayer::isPlaying() {
     LOGV("isPlaying");
-    return mPlayer != NULL && mPlayer->isPlaying();
+    return mPlayer->isPlaying();
 }
 
 status_t StagefrightPlayer::seekTo(int msec) {
     LOGV("seekTo");
 
-    if (mPlayer == NULL) {
-        return NO_INIT;
-    }
-
     status_t err = mPlayer->seekTo((int64_t)msec * 1000);
 
-    sendEvent(MEDIA_SEEK_COMPLETE);
-
     return err;
 }
 
 status_t StagefrightPlayer::getCurrentPosition(int *msec) {
     LOGV("getCurrentPosition");
 
-    if (mPlayer == NULL) {
-        return NO_INIT;
+    int64_t positionUs;
+    status_t err = mPlayer->getPosition(&positionUs);
+
+    if (err != OK) {
+        return err;
     }
 
-    *msec = mPlayer->getPosition() / 1000;
+    *msec = (positionUs + 500) / 1000;
+
     return OK;
 }
 
 status_t StagefrightPlayer::getDuration(int *msec) {
     LOGV("getDuration");
 
-    if (mPlayer == NULL) {
-        return NO_INIT;
+    int64_t durationUs;
+    status_t err = mPlayer->getDuration(&durationUs);
+
+    if (err != OK) {
+        return err;
     }
 
-    *msec = mPlayer->getDuration() / 1000;
+    *msec = (durationUs + 500) / 1000;
+
     return OK;
 }
 
 status_t StagefrightPlayer::reset() {
     LOGV("reset");
 
-    delete mPlayer;
-    mPlayer = NULL;
+    mPlayer->reset();
 
     return OK;
 }
 
 status_t StagefrightPlayer::setLooping(int loop) {
     LOGV("setLooping");
-    return UNKNOWN_ERROR;
+
+    return mPlayer->setLooping(loop);
 }
 
 player_type StagefrightPlayer::playerType() {
@@ -202,9 +161,7 @@
 void StagefrightPlayer::setAudioSink(const sp<AudioSink> &audioSink) {
     MediaPlayerInterface::setAudioSink(audioSink);
 
-    if (mPlayer != NULL) {
-        mPlayer->setAudioSink(audioSink);
-    }
+    mPlayer->setAudioSink(audioSink);
 }
 
 }  // namespace android
diff --git a/media/libmediaplayerservice/StagefrightPlayer.h b/media/libmediaplayerservice/StagefrightPlayer.h
index f214872..9d005cb 100644
--- a/media/libmediaplayerservice/StagefrightPlayer.h
+++ b/media/libmediaplayerservice/StagefrightPlayer.h
@@ -22,7 +22,7 @@
 
 namespace android {
 
-class MediaPlayerImpl;
+struct AwesomePlayer;
 
 class StagefrightPlayer : public MediaPlayerInterface {
 public:
@@ -49,7 +49,7 @@
     virtual void setAudioSink(const sp<AudioSink> &audioSink);
 
 private:
-    MediaPlayerImpl *mPlayer;
+    AwesomePlayer *mPlayer;
 
     StagefrightPlayer(const StagefrightPlayer &);
     StagefrightPlayer &operator=(const StagefrightPlayer &);
diff --git a/media/libstagefright/AMRExtractor.cpp b/media/libstagefright/AMRExtractor.cpp
index 1e3c5a4..bdd7550 100644
--- a/media/libstagefright/AMRExtractor.cpp
+++ b/media/libstagefright/AMRExtractor.cpp
@@ -33,7 +33,10 @@
 
 class AMRSource : public MediaSource {
 public:
-    AMRSource(const sp<DataSource> &source, bool isWide);
+    AMRSource(const sp<DataSource> &source,
+              const sp<MetaData> &meta,
+              size_t frameSize,
+              bool isWide);
 
     virtual status_t start(MetaData *params = NULL);
     virtual status_t stop();
@@ -48,6 +51,8 @@
 
 private:
     sp<DataSource> mDataSource;
+    sp<MetaData> mMeta;
+    size_t mFrameSize;
     bool mIsWide;
 
     off_t mOffset;
@@ -61,15 +66,63 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
+static size_t getFrameSize(bool isWide, unsigned FT) {
+    static const size_t kFrameSizeNB[8] = {
+        95, 103, 118, 134, 148, 159, 204, 244
+    };
+    static const size_t kFrameSizeWB[9] = {
+        132, 177, 253, 285, 317, 365, 397, 461, 477
+    };
+
+    size_t frameSize = isWide ? kFrameSizeWB[FT] : kFrameSizeNB[FT];
+
+    // Round up bits to bytes and add 1 for the header byte.
+    frameSize = (frameSize + 7) / 8 + 1;
+
+    return frameSize;
+}
+
 AMRExtractor::AMRExtractor(const sp<DataSource> &source)
     : mDataSource(source),
       mInitCheck(NO_INIT) {
     String8 mimeType;
     float confidence;
-    if (SniffAMR(mDataSource, &mimeType, &confidence)) {
-        mInitCheck = OK;
-        mIsWide = (mimeType == MEDIA_MIMETYPE_AUDIO_AMR_WB);
+    if (!SniffAMR(mDataSource, &mimeType, &confidence)) {
+        return;
     }
+
+    mIsWide = (mimeType == MEDIA_MIMETYPE_AUDIO_AMR_WB);
+
+    mMeta = new MetaData;
+    mMeta->setCString(
+            kKeyMIMEType, mIsWide ? MEDIA_MIMETYPE_AUDIO_AMR_WB
+                                  : MEDIA_MIMETYPE_AUDIO_AMR_NB);
+
+    mMeta->setInt32(kKeyChannelCount, 1);
+    mMeta->setInt32(kKeySampleRate, mIsWide ? 16000 : 8000);
+
+    size_t offset = mIsWide ? 9 : 6;
+    uint8_t header;
+    if (mDataSource->readAt(offset, &header, 1) != 1) {
+        return;
+    }
+
+    unsigned FT = (header >> 3) & 0x0f;
+
+    if (FT > 8 || (!mIsWide && FT > 7)) {
+        return;
+    }
+
+    mFrameSize = getFrameSize(mIsWide, FT);
+
+    off_t streamSize;
+    if (mDataSource->getSize(&streamSize) == OK) {
+        off_t numFrames = streamSize / mFrameSize;
+
+        mMeta->setInt64(kKeyDuration, 20000ll * numFrames);
+    }
+
+    mInitCheck = OK;
 }
 
 AMRExtractor::~AMRExtractor() {
@@ -84,7 +137,7 @@
         return NULL;
     }
 
-    return new AMRSource(mDataSource, mIsWide);
+    return new AMRSource(mDataSource, mMeta, mFrameSize, mIsWide);
 }
 
 sp<MetaData> AMRExtractor::getTrackMetaData(size_t index, uint32_t flags) {
@@ -92,26 +145,17 @@
         return NULL;
     }
 
-    return makeAMRFormat(mIsWide);
-}
-
-// static
-sp<MetaData> AMRExtractor::makeAMRFormat(bool isWide) {
-    sp<MetaData> meta = new MetaData;
-    meta->setCString(
-            kKeyMIMEType, isWide ? MEDIA_MIMETYPE_AUDIO_AMR_WB
-                                 : MEDIA_MIMETYPE_AUDIO_AMR_NB);
-
-    meta->setInt32(kKeyChannelCount, 1);
-    meta->setInt32(kKeySampleRate, isWide ? 16000 : 8000);
-
-    return meta;
+    return mMeta;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 
-AMRSource::AMRSource(const sp<DataSource> &source, bool isWide)
+AMRSource::AMRSource(
+        const sp<DataSource> &source, const sp<MetaData> &meta,
+        size_t frameSize, bool isWide)
     : mDataSource(source),
+      mMeta(meta),
+      mFrameSize(frameSize),
       mIsWide(isWide),
       mOffset(mIsWide ? 9 : 6),
       mCurrentTimeUs(0),
@@ -148,13 +192,20 @@
 }
 
 sp<MetaData> AMRSource::getFormat() {
-    return AMRExtractor::makeAMRFormat(mIsWide);
+    return mMeta;
 }
 
 status_t AMRSource::read(
         MediaBuffer **out, const ReadOptions *options) {
     *out = NULL;
 
+    int64_t seekTimeUs;
+    if (options && options->getSeekTo(&seekTimeUs)) {
+        int64_t seekFrame = seekTimeUs / 20000ll;  // 20ms per frame.
+        mCurrentTimeUs = seekFrame * 20000ll;
+        mOffset = seekFrame * mFrameSize + (mIsWide ? 9 : 6);
+    }
+
     uint8_t header;
     ssize_t n = mDataSource->readAt(mOffset, &header, 1);
 
@@ -180,17 +231,8 @@
         return ERROR_MALFORMED;
     }
 
-    static const size_t kFrameSizeNB[8] = {
-        95, 103, 118, 134, 148, 159, 204, 244
-    };
-    static const size_t kFrameSizeWB[9] = {
-        132, 177, 253, 285, 317, 365, 397, 461, 477
-    };
-
-    size_t frameSize = mIsWide ? kFrameSizeWB[FT] : kFrameSizeNB[FT];
-
-    // Round up bits to bytes and add 1 for the header byte.
-    frameSize = (frameSize + 7) / 8 + 1;
+    size_t frameSize = getFrameSize(mIsWide, FT);
+    CHECK_EQ(frameSize, mFrameSize);
 
     n = mDataSource->readAt(mOffset, buffer->data(), frameSize);
 
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index c36e769..460c496 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -17,6 +17,7 @@
 LOCAL_SRC_FILES +=                \
         AMRExtractor.cpp          \
         AudioPlayer.cpp           \
+        AwesomePlayer.cpp         \
         CachingDataSource.cpp     \
         CameraSource.cpp          \
         DataSource.cpp            \
@@ -28,8 +29,6 @@
         MPEG4Extractor.cpp        \
         MPEG4Writer.cpp           \
         MediaExtractor.cpp        \
-        MediaPlayerImpl.cpp       \
-        MmapSource.cpp            \
         SampleTable.cpp           \
         ShoutcastSource.cpp       \
         TimeSource.cpp            \
diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp
index d7e3f66..4280683 100644
--- a/media/libstagefright/AudioPlayer.cpp
+++ b/media/libstagefright/AudioPlayer.cpp
@@ -47,6 +47,12 @@
     }
 }
 
+void AudioPlayer::setListenerCallback(
+        void (*notify)(void *cookie, int what), void *cookie) {
+    mListenerCallback = notify;
+    mListenerCookie = cookie;
+}
+
 void AudioPlayer::setSource(const sp<MediaSource> &source) {
     CHECK_EQ(mSource, NULL);
     mSource = source;
@@ -195,7 +201,6 @@
                     mInputBuffer->release();
                     mInputBuffer = NULL;
                 }
-                mSeeking = false;
             }
         }
 
@@ -205,7 +210,19 @@
             CHECK((err == OK && mInputBuffer != NULL)
                    || (err != OK && mInputBuffer == NULL));
 
+            if (mSeeking) {
+                mSeeking = false;
+
+                if (mListenerCallback) {
+                    (*mListenerCallback)(mListenerCookie, SEEK_COMPLETE);
+                }
+            }
+
             if (err != OK) {
+                if (mListenerCallback) {
+                    (*mListenerCallback)(mListenerCookie, REACHED_EOS);
+                }
+
                 memset((char *)data + size_done, 0, size_remaining);
                 break;
             }
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
new file mode 100644
index 0000000..ed46cea
--- /dev/null
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -0,0 +1,626 @@
+/*
+ * 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 "AwesomePlayer"
+#include <utils/Log.h>
+
+#include "include/AwesomePlayer.h"
+
+#include <media/stagefright/AudioPlayer.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/FileSource.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/OMXCodec.h>
+
+namespace android {
+
+struct AwesomeEvent : public TimedEventQueue::Event {
+    AwesomeEvent(AwesomePlayer *player, int32_t code)
+        : mPlayer(player),
+          mCode(code) {
+    }
+
+protected:
+    virtual ~AwesomeEvent() {}
+
+    virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
+        mPlayer->onEvent(mCode);
+    }
+
+private:
+    AwesomePlayer *mPlayer;
+    int32_t mCode;
+
+    AwesomeEvent(const AwesomeEvent &);
+    AwesomeEvent &operator=(const AwesomeEvent &);
+};
+
+AwesomePlayer::AwesomePlayer()
+    : mTimeSource(NULL),
+      mAudioPlayer(NULL),
+      mLastVideoBuffer(NULL),
+      mVideoBuffer(NULL) {
+    CHECK_EQ(mClient.connect(), OK);
+
+    DataSource::RegisterDefaultSniffers();
+
+    mVideoEvent = new AwesomeEvent(this, 0);
+    mVideoEventPending = false;
+    mStreamDoneEvent = new AwesomeEvent(this, 1);
+    mStreamDoneEventPending = false;
+
+    mQueue.start();
+
+    reset();
+}
+
+AwesomePlayer::~AwesomePlayer() {
+    mQueue.stop();
+
+    reset();
+
+    mClient.disconnect();
+}
+
+void AwesomePlayer::cancelPlayerEvents() {
+    mQueue.cancelEvent(mVideoEvent->eventID());
+    mVideoEventPending = false;
+    mQueue.cancelEvent(mStreamDoneEvent->eventID());
+    mStreamDoneEventPending = false;
+}
+
+void AwesomePlayer::setListener(const sp<MediaPlayerBase> &listener) {
+    Mutex::Autolock autoLock(mLock);
+    mListener = listener;
+}
+
+status_t AwesomePlayer::setDataSource(const char *uri) {
+    Mutex::Autolock autoLock(mLock);
+
+    reset_l();
+
+    sp<MediaExtractor> extractor = MediaExtractor::CreateFromURI(uri);
+
+    if (extractor == NULL) {
+        return UNKNOWN_ERROR;
+    }
+
+    return setDataSource_l(extractor);
+}
+
+status_t AwesomePlayer::setDataSource(
+        int fd, int64_t offset, int64_t length) {
+    Mutex::Autolock autoLock(mLock);
+
+    reset_l();
+
+    sp<DataSource> source = new FileSource(fd, offset, length);
+
+    status_t err = source->initCheck();
+
+    if (err != OK) {
+        return err;
+    }
+
+    sp<MediaExtractor> extractor = MediaExtractor::Create(source);
+
+    if (extractor == NULL) {
+        return UNKNOWN_ERROR;
+    }
+
+    return setDataSource_l(extractor);
+}
+
+status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
+    reset_l();
+
+    bool haveAudio = false;
+    bool haveVideo = false;
+    for (size_t i = 0; i < extractor->countTracks(); ++i) {
+        sp<MetaData> meta = extractor->getTrackMetaData(i);
+
+        const char *mime;
+        CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+        if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
+            if (setVideoSource(extractor->getTrack(i)) == OK) {
+                haveVideo = true;
+            }
+        } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
+            if (setAudioSource(extractor->getTrack(i)) == OK) {
+                haveAudio = true;
+            }
+        }
+
+        if (haveAudio && haveVideo) {
+            break;
+        }
+    }
+
+    return !haveAudio && !haveVideo ? UNKNOWN_ERROR : OK;
+}
+
+void AwesomePlayer::reset() {
+    Mutex::Autolock autoLock(mLock);
+    reset_l();
+}
+
+void AwesomePlayer::reset_l() {
+    cancelPlayerEvents();
+
+    if (mLastVideoBuffer) {
+        mLastVideoBuffer->release();
+        mLastVideoBuffer = NULL;
+    }
+
+    if (mVideoBuffer) {
+        mVideoBuffer->release();
+        mVideoBuffer = NULL;
+    }
+
+    if (mVideoSource != NULL) {
+        mVideoSource->stop();
+        mVideoSource.clear();
+    }
+
+    mAudioSource.clear();
+
+    if (mTimeSource != mAudioPlayer) {
+        delete mTimeSource;
+    }
+    mTimeSource = NULL;
+
+    delete mAudioPlayer;
+    mAudioPlayer = NULL;
+
+    mVideoRenderer.clear();
+
+    mDurationUs = -1;
+    mFlags = 0;
+    mVideoWidth = mVideoHeight = -1;
+    mTimeSourceDeltaUs = 0;
+    mVideoTimeUs = 0;
+
+    mSeeking = false;
+    mSeekTimeUs = 0;
+}
+
+// static
+void AwesomePlayer::AudioNotify(void *_me, int what) {
+    AwesomePlayer *me = (AwesomePlayer *)_me;
+
+    Mutex::Autolock autoLock(me->mLock);
+
+    switch (what) {
+        case AudioPlayer::REACHED_EOS:
+            me->postStreamDoneEvent_l();
+            break;
+
+        case AudioPlayer::SEEK_COMPLETE:
+        {
+            if (me->mListener != NULL) {
+                me->mListener->sendEvent(MEDIA_SEEK_COMPLETE);
+            }
+
+            break;
+        }
+
+        default:
+            CHECK(!"should not be here.");
+            break;
+    }
+}
+
+void AwesomePlayer::onStreamDone() {
+    // Posted whenever any stream finishes playing.
+
+    Mutex::Autolock autoLock(mLock);
+    mStreamDoneEventPending = false;
+
+    if (mFlags & LOOPING) {
+        seekTo_l(0);
+
+        if (mVideoRenderer != NULL) {
+            postVideoEvent_l();
+        }
+    } else {
+        if (mListener != NULL) {
+            mListener->sendEvent(MEDIA_PLAYBACK_COMPLETE);
+        }
+
+        pause_l();
+    }
+}
+
+status_t AwesomePlayer::play() {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mFlags & PLAYING) {
+        return OK;
+    }
+
+    mFlags |= PLAYING;
+    mFlags |= FIRST_FRAME;
+
+    if (mAudioSource != NULL) {
+        if (mAudioPlayer == NULL) {
+            if (mAudioSink != NULL) {
+                mAudioPlayer = new AudioPlayer(mAudioSink);
+
+                mAudioPlayer->setListenerCallback(
+                        &AwesomePlayer::AudioNotify, this);
+
+                mAudioPlayer->setSource(mAudioSource);
+                mAudioPlayer->start();
+
+                delete mTimeSource;
+                mTimeSource = mAudioPlayer;
+
+                // If there was a seek request while we were paused
+                // and we're just starting up again, honor the request now.
+                seekAudioIfNecessary_l();
+            }
+        } else {
+            mAudioPlayer->resume();
+        }
+    }
+
+    if (mTimeSource == NULL && mAudioPlayer == NULL) {
+        mTimeSource = new SystemTimeSource;
+    }
+
+    if (mVideoSource != NULL) {
+        if (mVideoRenderer == NULL) {
+            initRenderer_l();
+        }
+
+        if (mVideoRenderer != NULL) {
+            // Kick off video playback
+            postVideoEvent_l();
+        }
+    }
+
+    return OK;
+}
+
+void AwesomePlayer::initRenderer_l() {
+    if (mISurface != NULL) {
+        sp<MetaData> meta = mVideoSource->getFormat();
+
+        int32_t format;
+        const char *component;
+        int32_t decodedWidth, decodedHeight;
+        CHECK(meta->findInt32(kKeyColorFormat, &format));
+        CHECK(meta->findCString(kKeyDecoderComponent, &component));
+        CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
+        CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
+
+        mVideoRenderer =
+            mClient.interface()->createRenderer(
+                    mISurface, component,
+                    (OMX_COLOR_FORMATTYPE)format,
+                    decodedWidth, decodedHeight,
+                    mVideoWidth, mVideoHeight);
+    }
+}
+
+status_t AwesomePlayer::pause() {
+    Mutex::Autolock autoLock(mLock);
+    return pause_l();
+}
+
+status_t AwesomePlayer::pause_l() {
+    if (!(mFlags & PLAYING)) {
+        return OK;
+    }
+
+    cancelPlayerEvents();
+
+    if (mAudioPlayer != NULL) {
+        mAudioPlayer->pause();
+    }
+
+    mFlags &= ~PLAYING;
+
+    return OK;
+}
+
+bool AwesomePlayer::isPlaying() const {
+    Mutex::Autolock autoLock(mLock);
+
+    return mFlags & PLAYING;
+}
+
+void AwesomePlayer::setISurface(const sp<ISurface> &isurface) {
+    Mutex::Autolock autoLock(mLock);
+
+    mISurface = isurface;
+}
+
+void AwesomePlayer::setAudioSink(
+        const sp<MediaPlayerBase::AudioSink> &audioSink) {
+    Mutex::Autolock autoLock(mLock);
+
+    mAudioSink = audioSink;
+}
+
+status_t AwesomePlayer::setLooping(bool shouldLoop) {
+    Mutex::Autolock autoLock(mLock);
+
+    mFlags = mFlags & ~LOOPING;
+
+    if (shouldLoop) {
+        mFlags |= LOOPING;
+    }
+
+    return OK;
+}
+
+status_t AwesomePlayer::getDuration(int64_t *durationUs) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mDurationUs < 0) {
+        return UNKNOWN_ERROR;
+    }
+
+    *durationUs = mDurationUs;
+
+    return OK;
+}
+
+status_t AwesomePlayer::getPosition(int64_t *positionUs) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mVideoRenderer != NULL) {
+        *positionUs = mVideoTimeUs;
+    } else if (mAudioPlayer != NULL) {
+        *positionUs = mAudioPlayer->getMediaTimeUs();
+    } else {
+        *positionUs = 0;
+    }
+
+    return OK;
+}
+
+status_t AwesomePlayer::seekTo(int64_t timeUs) {
+    Mutex::Autolock autoLock(mLock);
+    return seekTo_l(timeUs);
+}
+
+status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
+    mSeeking = true;
+    mSeekTimeUs = timeUs;
+
+    seekAudioIfNecessary_l();
+
+    return OK;
+}
+
+void AwesomePlayer::seekAudioIfNecessary_l() {
+    if (mSeeking && mVideoRenderer == NULL && mAudioPlayer != NULL) {
+        mAudioPlayer->seekTo(mSeekTimeUs);
+
+        mSeeking = false;
+    }
+}
+
+status_t AwesomePlayer::getVideoDimensions(
+        int32_t *width, int32_t *height) const {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mVideoWidth < 0 || mVideoHeight < 0) {
+        return UNKNOWN_ERROR;
+    }
+
+    *width = mVideoWidth;
+    *height = mVideoHeight;
+
+    return OK;
+}
+
+status_t AwesomePlayer::setAudioSource(const sp<MediaSource> &source) {
+    if (source == NULL) {
+        return UNKNOWN_ERROR;
+    }
+
+    mAudioSource = OMXCodec::Create(
+            mClient.interface(), source->getFormat(),
+            false, // createEncoder
+            source);
+
+    if (mAudioSource != NULL) {
+        int64_t durationUs;
+        if (source->getFormat()->findInt64(kKeyDuration, &durationUs)) {
+            if (mDurationUs < 0 || durationUs > mDurationUs) {
+                mDurationUs = durationUs;
+            }
+        }
+    }
+
+    return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
+}
+
+status_t AwesomePlayer::setVideoSource(const sp<MediaSource> &source) {
+    if (source == NULL) {
+        return UNKNOWN_ERROR;
+    }
+
+    mVideoSource = OMXCodec::Create(
+            mClient.interface(), source->getFormat(),
+            false, // createEncoder
+            source);
+
+    if (mVideoSource != NULL) {
+        int64_t durationUs;
+        if (source->getFormat()->findInt64(kKeyDuration, &durationUs)) {
+            if (mDurationUs < 0 || durationUs > mDurationUs) {
+                mDurationUs = durationUs;
+            }
+        }
+
+        CHECK(source->getFormat()->findInt32(kKeyWidth, &mVideoWidth));
+        CHECK(source->getFormat()->findInt32(kKeyHeight, &mVideoHeight));
+
+        mVideoSource->start();
+    }
+
+    return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
+}
+
+void AwesomePlayer::onEvent(int32_t code) {
+    if (code == 1) {
+        onStreamDone();
+        return;
+    }
+
+    Mutex::Autolock autoLock(mLock);
+    mVideoEventPending = false;
+
+    if (mSeeking) {
+        if (mLastVideoBuffer) {
+            mLastVideoBuffer->release();
+            mLastVideoBuffer = NULL;
+        }
+
+        if (mVideoBuffer) {
+            mVideoBuffer->release();
+            mVideoBuffer = NULL;
+        }
+    }
+
+    if (!mVideoBuffer) {
+        MediaSource::ReadOptions options;
+        if (mSeeking) {
+            LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
+
+            options.setSeekTo(mSeekTimeUs);
+        }
+        for (;;) {
+            status_t err = mVideoSource->read(&mVideoBuffer, &options);
+
+            if (err != OK) {
+                CHECK_EQ(mVideoBuffer, NULL);
+
+                if (err == INFO_FORMAT_CHANGED) {
+                    LOGV("VideoSource signalled format change.");
+
+                    initRenderer_l();
+                    continue;
+                }
+
+                postStreamDoneEvent_l();
+                return;
+            }
+
+            break;
+        }
+    }
+
+    int64_t timeUs;
+    CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
+
+    mVideoTimeUs = timeUs;
+
+    if (mSeeking) {
+        if (mAudioPlayer != NULL) {
+            LOGV("seeking audio to %lld us (%.2f secs).", timeUs, timeUs / 1E6);
+
+            mAudioPlayer->seekTo(timeUs);
+        } else {
+            // If we're playing video only, report seek complete now,
+            // otherwise audio player will notify us later.
+            if (mListener != NULL) {
+                mListener->sendEvent(MEDIA_SEEK_COMPLETE);
+            }
+        }
+
+        mFlags |= FIRST_FRAME;
+        mSeeking = false;
+    }
+
+    if (mFlags & FIRST_FRAME) {
+        mFlags &= ~FIRST_FRAME;
+
+        mTimeSourceDeltaUs = mTimeSource->getRealTimeUs() - timeUs;
+    }
+
+    int64_t realTimeUs, mediaTimeUs;
+    if (mAudioPlayer != NULL
+        && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
+        mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
+    }
+
+    int64_t nowUs = mTimeSource->getRealTimeUs() - mTimeSourceDeltaUs;
+
+    int64_t latenessUs = nowUs - timeUs;
+
+    if (latenessUs > 20000) {
+        // We're more than 20ms late.
+        LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6);
+
+        mVideoBuffer->release();
+        mVideoBuffer = NULL;
+
+        postVideoEvent_l();
+        return;
+    }
+
+    if (latenessUs < -10000) {
+        // We're more than 10ms early.
+
+        postVideoEvent_l(10000);
+        return;
+    }
+
+    void *id;
+    if (mVideoBuffer->meta_data()->findPointer(kKeyBufferID, &id)) {
+        mVideoRenderer->render((IOMX::buffer_id)id);
+    }
+
+    if (mLastVideoBuffer) {
+        mLastVideoBuffer->release();
+        mLastVideoBuffer = NULL;
+    }
+    mLastVideoBuffer = mVideoBuffer;
+    mVideoBuffer = NULL;
+
+    postVideoEvent_l();
+}
+
+void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
+    if (mVideoEventPending) {
+        return;
+    }
+
+    mVideoEventPending = true;
+    mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
+}
+
+void AwesomePlayer::postStreamDoneEvent_l() {
+    if (mStreamDoneEventPending) {
+        return;
+    }
+    mStreamDoneEventPending = true;
+    mQueue.postEvent(mStreamDoneEvent);
+}
+
+}  // namespace android
+
diff --git a/media/libstagefright/MediaExtractor.cpp b/media/libstagefright/MediaExtractor.cpp
index 19a1f85..9d3deb7 100644
--- a/media/libstagefright/MediaExtractor.cpp
+++ b/media/libstagefright/MediaExtractor.cpp
@@ -25,10 +25,10 @@
 
 #include <media/stagefright/CachingDataSource.h>
 #include <media/stagefright/DataSource.h>
+#include <media/stagefright/FileSource.h>
 #include <media/stagefright/HTTPDataSource.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaExtractor.h>
-#include <media/stagefright/MmapSource.h>
 #include <utils/String8.h>
 
 namespace android {
@@ -70,13 +70,13 @@
         const char *uri, const char *mime) {
     sp<DataSource> source;
     if (!strncasecmp("file://", uri, 7)) {
-        source = new MmapSource(uri + 7);
+        source = new FileSource(uri + 7);
     } else if (!strncasecmp("http://", uri, 7)) {
         source = new HTTPDataSource(uri);
         source = new CachingDataSource(source, 64 * 1024, 10);
     } else {
         // Assume it's a filename.
-        source = new MmapSource(uri);
+        source = new FileSource(uri);
     }
 
     if (source == NULL || source->initCheck() != OK) {
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
-
diff --git a/media/libstagefright/MmapSource.cpp b/media/libstagefright/MmapSource.cpp
deleted file mode 100644
index 42749cf..0000000
--- a/media/libstagefright/MmapSource.cpp
+++ /dev/null
@@ -1,113 +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 "MmapSource"
-#include <utils/Log.h>
-
-#include <sys/mman.h>
-
-#include <fcntl.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <media/stagefright/MediaDebug.h>
-#include <media/stagefright/MmapSource.h>
-
-namespace android {
-
-MmapSource::MmapSource(const char *filename)
-    : mFd(open(filename, O_RDONLY)),
-      mBase(NULL),
-      mSize(0) {
-    LOGV("MmapSource '%s'", filename);
-
-    if (mFd < 0) {
-        return;
-    }
-
-    off_t size = lseek(mFd, 0, SEEK_END);
-    mSize = (size_t)size;
-
-    mBase = mmap(0, mSize, PROT_READ, MAP_FILE | MAP_SHARED, mFd, 0);
-
-    if (mBase == (void *)-1) {
-        mBase = NULL;
-
-        close(mFd);
-        mFd = -1;
-    }
-}
-
-MmapSource::MmapSource(int fd, int64_t offset, int64_t length)
-    : mFd(fd),
-      mBase(NULL),
-      mSize(length) {
-    LOGV("MmapSource fd:%d offset:%lld length:%lld", fd, offset, length);
-    CHECK(fd >= 0);
-
-    mBase = mmap(0, mSize, PROT_READ, MAP_FILE | MAP_SHARED, mFd, offset);
-
-    if (mBase == (void *)-1) {
-        mBase = NULL;
-
-        close(mFd);
-        mFd = -1;
-    }
-
-}
-
-MmapSource::~MmapSource() {
-    if (mFd != -1) {
-        munmap(mBase, mSize);
-        mBase = NULL;
-        mSize = 0;
-
-        close(mFd);
-        mFd = -1;
-    }
-}
-
-status_t MmapSource::initCheck() const {
-    return mFd == -1 ? NO_INIT : OK;
-}
-
-ssize_t MmapSource::readAt(off_t offset, void *data, size_t size) {
-    LOGV("readAt offset:%ld data:%p size:%d", offset, data, size);
-    CHECK(offset >= 0);
-
-    size_t avail = 0;
-    if (offset >= 0 && offset < (off_t)mSize) {
-        avail = mSize - offset;
-    }
-
-    if (size > avail) {
-        size = avail;
-    }
-
-    memcpy(data, (const uint8_t *)mBase + offset, size);
-
-    return (ssize_t)size;
-}
-
-status_t MmapSource::getSize(off_t *size) {
-    *size = mSize;
-
-    return OK;
-}
-
-}  // namespace android
-
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index d36653e..9297aff 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -30,7 +30,6 @@
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaExtractor.h>
 #include <media/stagefright/MetaData.h>
-#include <media/stagefright/MmapSource.h>
 #include <media/stagefright/OMXCodec.h>
 #include <media/stagefright/Utils.h>
 #include <utils/Vector.h>
diff --git a/media/libstagefright/TimedEventQueue.cpp b/media/libstagefright/TimedEventQueue.cpp
index fa68771..d079e70 100644
--- a/media/libstagefright/TimedEventQueue.cpp
+++ b/media/libstagefright/TimedEventQueue.cpp
@@ -135,7 +135,9 @@
 }
 
 bool TimedEventQueue::cancelEvent(event_id id) {
-    CHECK(id != 0);
+    if (id == 0) {
+        return false;
+    }
 
     cancelEvents(&MatchesEventID, &id, true /* stopAfterFirstMatch */);
 
@@ -162,6 +164,7 @@
             mQueueHeadChangedCondition.signal();
         }
 
+        (*it).event->setEventID(0);
         it = mQueue.erase(it);
 
         if (stopAfterFirstMatch) {
@@ -228,7 +231,12 @@
                 }
             }
 
+            if (mQueue.empty()) {
+                continue;
+            }
+
             event = (*it).event;
+            event->setEventID(0);
             mQueue.erase(it);
         }
 
diff --git a/media/libstagefright/include/AMRExtractor.h b/media/libstagefright/include/AMRExtractor.h
index debf006..1972a1c 100644
--- a/media/libstagefright/include/AMRExtractor.h
+++ b/media/libstagefright/include/AMRExtractor.h
@@ -32,14 +32,14 @@
     virtual sp<MediaSource> getTrack(size_t index);
     virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
 
-    static sp<MetaData> makeAMRFormat(bool isWide);
-
 protected:
     virtual ~AMRExtractor();
 
 private:
     sp<DataSource> mDataSource;
+    sp<MetaData> mMeta;
     status_t mInitCheck;
+    size_t mFrameSize;
     bool mIsWide;
 
     AMRExtractor(const AMRExtractor &);
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
new file mode 100644
index 0000000..2727c3c
--- /dev/null
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -0,0 +1,133 @@
+/*
+ * 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.
+ */
+
+#ifndef AWESOME_PLAYER_H_
+
+#define AWESOME_PLAYER_H_
+
+#include "TimedEventQueue.h"
+
+#include <media/MediaPlayerInterface.h>
+#include <media/stagefright/OMXClient.h>
+#include <utils/threads.h>
+
+namespace android {
+
+struct MediaBuffer;
+struct MediaExtractor;
+struct MediaSource;
+struct AudioPlayer;
+struct TimeSource;
+
+struct AwesomePlayer {
+    AwesomePlayer();
+    ~AwesomePlayer();
+
+    void setListener(const sp<MediaPlayerBase> &listener);
+
+    status_t setDataSource(const char *uri);
+    status_t setDataSource(int fd, int64_t offset, int64_t length);
+
+    void reset();
+
+    status_t play();
+    status_t pause();
+
+    bool isPlaying() const;
+
+    void setISurface(const sp<ISurface> &isurface);
+    void setAudioSink(const sp<MediaPlayerBase::AudioSink> &audioSink);
+    status_t setLooping(bool shouldLoop);
+
+    status_t getDuration(int64_t *durationUs);
+    status_t getPosition(int64_t *positionUs);
+
+    status_t seekTo(int64_t timeUs);
+
+    status_t getVideoDimensions(int32_t *width, int32_t *height) const;
+
+private:
+    friend struct AwesomeEvent;
+
+    enum Flags {
+        PLAYING     = 1,
+        LOOPING     = 2,
+        FIRST_FRAME = 4,
+    };
+
+    mutable Mutex mLock;
+
+    OMXClient mClient;
+    TimedEventQueue mQueue;
+    sp<MediaPlayerBase> mListener;
+
+    sp<ISurface> mISurface;
+    sp<MediaPlayerBase::AudioSink> mAudioSink;
+
+    TimeSource *mTimeSource;
+
+    sp<MediaSource> mVideoSource;
+    sp<IOMXRenderer> mVideoRenderer;
+
+    sp<MediaSource> mAudioSource;
+    AudioPlayer *mAudioPlayer;
+    int64_t mDurationUs;
+
+    uint32_t mFlags;
+
+    int32_t mVideoWidth, mVideoHeight;
+    int64_t mTimeSourceDeltaUs;
+    int64_t mVideoTimeUs;
+
+    bool mSeeking;
+    int64_t mSeekTimeUs;
+
+    sp<TimedEventQueue::Event> mVideoEvent;
+    bool mVideoEventPending;
+    sp<TimedEventQueue::Event> mStreamDoneEvent;
+    bool mStreamDoneEventPending;
+
+    void postVideoEvent_l(int64_t delayUs = -1);
+    void postStreamDoneEvent_l();
+
+    MediaBuffer *mLastVideoBuffer;
+    MediaBuffer *mVideoBuffer;
+
+    status_t setDataSource_l(const sp<MediaExtractor> &extractor);
+    void reset_l();
+    status_t seekTo_l(int64_t timeUs);
+    status_t pause_l();
+    void initRenderer_l();
+    void seekAudioIfNecessary_l();
+
+    void cancelPlayerEvents();
+
+    status_t setAudioSource(const sp<MediaSource> &source);
+    status_t setVideoSource(const sp<MediaSource> &source);
+
+    void onEvent(int32_t code);
+
+    static void AudioNotify(void *me, int what);
+    void onStreamDone();
+
+    AwesomePlayer(const AwesomePlayer &);
+    AwesomePlayer &operator=(const AwesomePlayer &);
+};
+
+}  // namespace android
+
+#endif  // AWESOME_PLAYER_H_
+