AudioPlayerBase and VideoEditorAudioPlayer class design is incorrect.

o this patch removed the AudioPlayerBase class.
o verified and passed functional tests

Change-Id: I33727069ef63136979b954a9dee1c35309ef6dd4
diff --git a/libvideoeditor/lvpp/Android.mk b/libvideoeditor/lvpp/Android.mk
index db6cb48..1ea02a3 100755
--- a/libvideoeditor/lvpp/Android.mk
+++ b/libvideoeditor/lvpp/Android.mk
@@ -34,7 +34,6 @@
     DummyAudioSource.cpp \
     DummyVideoSource.cpp \
     VideoEditorBGAudioProcessing.cpp \
-    AudioPlayerBase.cpp \
     PreviewRenderer.cpp \
     I420ColorConverter.cpp \
     NativeWindowRenderer.cpp
diff --git a/libvideoeditor/lvpp/AudioPlayerBase.cpp b/libvideoeditor/lvpp/AudioPlayerBase.cpp
deleted file mode 100644
index 67ea43c..0000000
--- a/libvideoeditor/lvpp/AudioPlayerBase.cpp
+++ /dev/null
@@ -1,510 +0,0 @@
-/*
- * Copyright (C) 2011 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 "AudioPlayerBase"
-#include <utils/Log.h>
-
-#include <binder/IPCThreadState.h>
-#include <media/AudioTrack.h>
-#include <media/stagefright/MediaDebug.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MediaSource.h>
-#include <media/stagefright/MetaData.h>
-
-#include "AudioPlayerBase.h"
-#include "PreviewPlayer.h"
-
-namespace android {
-
-AudioPlayerBase::AudioPlayerBase(
-        const sp<MediaPlayerBase::AudioSink> &audioSink,
-        PreviewPlayer *observer)
-    : mAudioTrack(NULL),
-      mInputBuffer(NULL),
-      mSampleRate(0),
-      mLatencyUs(0),
-      mFrameSize(0),
-      mNumFramesPlayed(0),
-      mPositionTimeMediaUs(-1),
-      mPositionTimeRealUs(-1),
-      mSeeking(false),
-      mReachedEOS(false),
-      mFinalStatus(OK),
-      mStarted(false),
-      mIsFirstBuffer(false),
-      mFirstBufferResult(OK),
-      mFirstBuffer(NULL),
-      mAudioSink(audioSink),
-      mObserver(observer) {
-}
-
-AudioPlayerBase::~AudioPlayerBase() {
-    if (mStarted) {
-        reset();
-    }
-}
-
-void AudioPlayerBase::setSource(const sp<MediaSource> &source) {
-    CHECK_EQ(mSource, NULL);
-    mSource = source;
-}
-
-status_t AudioPlayerBase::start(bool sourceAlreadyStarted) {
-    CHECK(!mStarted);
-    CHECK(mSource != NULL);
-
-    status_t err;
-    if (!sourceAlreadyStarted) {
-        err = mSource->start();
-
-        if (err != OK) {
-            return err;
-        }
-    }
-
-    // We allow an optional INFO_FORMAT_CHANGED at the very beginning
-    // of playback, if there is one, getFormat below will retrieve the
-    // updated format, if there isn't, we'll stash away the valid buffer
-    // of data to be used on the first audio callback.
-
-    CHECK(mFirstBuffer == NULL);
-
-    mFirstBufferResult = mSource->read(&mFirstBuffer);
-    if (mFirstBufferResult == INFO_FORMAT_CHANGED) {
-        ALOGV("INFO_FORMAT_CHANGED!!!");
-
-        CHECK(mFirstBuffer == NULL);
-        mFirstBufferResult = OK;
-        mIsFirstBuffer = false;
-    } else {
-        mIsFirstBuffer = true;
-    }
-
-    sp<MetaData> format = mSource->getFormat();
-    const char *mime;
-    bool success = format->findCString(kKeyMIMEType, &mime);
-    CHECK(success);
-    CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW));
-
-    success = format->findInt32(kKeySampleRate, &mSampleRate);
-    CHECK(success);
-
-    int32_t numChannels;
-    success = format->findInt32(kKeyChannelCount, &numChannels);
-    CHECK(success);
-
-    if (mAudioSink.get() != NULL) {
-        status_t err = mAudioSink->open(
-                mSampleRate, numChannels, AUDIO_FORMAT_PCM_16_BIT,
-                DEFAULT_AUDIOSINK_BUFFERCOUNT,
-                &AudioPlayerBase::AudioSinkCallback, this);
-        if (err != OK) {
-            if (mFirstBuffer != NULL) {
-                mFirstBuffer->release();
-                mFirstBuffer = NULL;
-            }
-
-            if (!sourceAlreadyStarted) {
-                mSource->stop();
-            }
-
-            return err;
-        }
-
-        mLatencyUs = (int64_t)mAudioSink->latency() * 1000;
-        mFrameSize = mAudioSink->frameSize();
-
-        mAudioSink->start();
-    } else {
-        mAudioTrack = new AudioTrack(
-                AUDIO_STREAM_MUSIC, mSampleRate, AUDIO_FORMAT_PCM_16_BIT,
-                (numChannels == 2)
-                    ? AUDIO_CHANNEL_OUT_STEREO
-                    : AUDIO_CHANNEL_OUT_MONO,
-                0, 0, &AudioCallback, this, 0);
-
-        if ((err = mAudioTrack->initCheck()) != OK) {
-            delete mAudioTrack;
-            mAudioTrack = NULL;
-
-            if (mFirstBuffer != NULL) {
-                mFirstBuffer->release();
-                mFirstBuffer = NULL;
-            }
-
-            if (!sourceAlreadyStarted) {
-                mSource->stop();
-            }
-
-            return err;
-        }
-
-        mLatencyUs = (int64_t)mAudioTrack->latency() * 1000;
-        mFrameSize = mAudioTrack->frameSize();
-
-        mAudioTrack->start();
-    }
-
-    mStarted = true;
-
-    return OK;
-}
-
-void AudioPlayerBase::pause(bool playPendingSamples) {
-    CHECK(mStarted);
-
-    if (playPendingSamples) {
-        if (mAudioSink.get() != NULL) {
-            mAudioSink->stop();
-        } else {
-            mAudioTrack->stop();
-        }
-    } else {
-        if (mAudioSink.get() != NULL) {
-            mAudioSink->pause();
-        } else {
-            mAudioTrack->pause();
-        }
-    }
-}
-
-void AudioPlayerBase::resume() {
-    CHECK(mStarted);
-
-    if (mAudioSink.get() != NULL) {
-        mAudioSink->start();
-    } else {
-        mAudioTrack->start();
-    }
-}
-
-void AudioPlayerBase::reset() {
-    CHECK(mStarted);
-
-    if (mAudioSink.get() != NULL) {
-        mAudioSink->stop();
-        mAudioSink->close();
-    } else {
-        mAudioTrack->stop();
-
-        delete mAudioTrack;
-        mAudioTrack = NULL;
-    }
-
-    // Make sure to release any buffer we hold onto so that the
-    // source is able to stop().
-
-    if (mFirstBuffer != NULL) {
-        mFirstBuffer->release();
-        mFirstBuffer = NULL;
-    }
-
-    if (mInputBuffer != NULL) {
-        ALOGV("AudioPlayerBase releasing input buffer.");
-
-        mInputBuffer->release();
-        mInputBuffer = NULL;
-    }
-
-    mSource->stop();
-
-    // The following hack is necessary to ensure that the OMX
-    // component is completely released by the time we may try
-    // to instantiate it again.
-    wp<MediaSource> tmp = mSource;
-    mSource.clear();
-    while (tmp.promote() != NULL) {
-        usleep(1000);
-    }
-    IPCThreadState::self()->flushCommands();
-
-    mNumFramesPlayed = 0;
-    mPositionTimeMediaUs = -1;
-    mPositionTimeRealUs = -1;
-    mSeeking = false;
-    mReachedEOS = false;
-    mFinalStatus = OK;
-    mStarted = false;
-}
-
-// static
-void AudioPlayerBase::AudioCallback(int event, void *user, void *info) {
-    static_cast<AudioPlayerBase *>(user)->AudioCallback(event, info);
-}
-
-bool AudioPlayerBase::isSeeking() {
-    Mutex::Autolock autoLock(mLock);
-    return mSeeking;
-}
-
-bool AudioPlayerBase::reachedEOS(status_t *finalStatus) {
-    *finalStatus = OK;
-
-    Mutex::Autolock autoLock(mLock);
-    *finalStatus = mFinalStatus;
-    return mReachedEOS;
-}
-
-// static
-size_t AudioPlayerBase::AudioSinkCallback(
-        MediaPlayerBase::AudioSink *audioSink,
-        void *buffer, size_t size, void *cookie) {
-    AudioPlayerBase *me = (AudioPlayerBase *)cookie;
-
-    return me->fillBuffer(buffer, size);
-}
-
-void AudioPlayerBase::AudioCallback(int event, void *info) {
-    if (event != AudioTrack::EVENT_MORE_DATA) {
-        return;
-    }
-
-    AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
-    size_t numBytesWritten = fillBuffer(buffer->raw, buffer->size);
-
-    buffer->size = numBytesWritten;
-}
-
-uint32_t AudioPlayerBase::getNumFramesPendingPlayout() const {
-    uint32_t numFramesPlayedOut;
-    status_t err;
-
-    if (mAudioSink != NULL) {
-        err = mAudioSink->getPosition(&numFramesPlayedOut);
-    } else {
-        err = mAudioTrack->getPosition(&numFramesPlayedOut);
-    }
-
-    if (err != OK || mNumFramesPlayed < numFramesPlayedOut) {
-        return 0;
-    }
-
-    // mNumFramesPlayed is the number of frames submitted
-    // to the audio sink for playback, but not all of them
-    // may have played out by now.
-    return mNumFramesPlayed - numFramesPlayedOut;
-}
-
-size_t AudioPlayerBase::fillBuffer(void *data, size_t size) {
-    if (mNumFramesPlayed == 0) {
-        ALOGV("AudioCallback");
-    }
-
-    if (mReachedEOS) {
-        return 0;
-    }
-
-    bool postSeekComplete = false;
-    bool postEOS = false;
-    int64_t postEOSDelayUs = 0;
-
-    size_t size_done = 0;
-    size_t size_remaining = size;
-    while (size_remaining > 0) {
-        MediaSource::ReadOptions options;
-
-        {
-            Mutex::Autolock autoLock(mLock);
-
-            if (mSeeking) {
-                if (mIsFirstBuffer) {
-                    if (mFirstBuffer != NULL) {
-                        mFirstBuffer->release();
-                        mFirstBuffer = NULL;
-                    }
-                    mIsFirstBuffer = false;
-                }
-
-                options.setSeekTo(mSeekTimeUs);
-
-                if (mInputBuffer != NULL) {
-                    mInputBuffer->release();
-                    mInputBuffer = NULL;
-                }
-
-                mSeeking = false;
-                if (mObserver) {
-                    postSeekComplete = true;
-                }
-            }
-        }
-
-        if (mInputBuffer == NULL) {
-            status_t err;
-
-            if (mIsFirstBuffer) {
-                mInputBuffer = mFirstBuffer;
-                mFirstBuffer = NULL;
-                err = mFirstBufferResult;
-
-                mIsFirstBuffer = false;
-            } else {
-                err = mSource->read(&mInputBuffer, &options);
-            }
-
-            CHECK((err == OK && mInputBuffer != NULL)
-                   || (err != OK && mInputBuffer == NULL));
-
-            Mutex::Autolock autoLock(mLock);
-
-            if (err != OK) {
-                if (mObserver && !mReachedEOS) {
-                    // We don't want to post EOS right away but only
-                    // after all frames have actually been played out.
-
-                    // These are the number of frames submitted to the
-                    // AudioTrack that you haven't heard yet.
-                    uint32_t numFramesPendingPlayout =
-                        getNumFramesPendingPlayout();
-
-                    // These are the number of frames we're going to
-                    // submit to the AudioTrack by returning from this
-                    // callback.
-                    uint32_t numAdditionalFrames = size_done / mFrameSize;
-
-                    numFramesPendingPlayout += numAdditionalFrames;
-
-                    int64_t timeToCompletionUs =
-                        (1000000ll * numFramesPendingPlayout) / mSampleRate;
-
-                    ALOGV("total number of frames played: %lld (%lld us)",
-                            (mNumFramesPlayed + numAdditionalFrames),
-                            1000000ll * (mNumFramesPlayed + numAdditionalFrames)
-                                / mSampleRate);
-
-                    ALOGV("%d frames left to play, %lld us (%.2f secs)",
-                         numFramesPendingPlayout,
-                         timeToCompletionUs, timeToCompletionUs / 1E6);
-
-                    postEOS = true;
-                    postEOSDelayUs = timeToCompletionUs + mLatencyUs;
-                }
-
-                mReachedEOS = true;
-                mFinalStatus = err;
-                break;
-            }
-
-            CHECK(mInputBuffer->meta_data()->findInt64(
-                        kKeyTime, &mPositionTimeMediaUs));
-
-            mPositionTimeRealUs =
-                ((mNumFramesPlayed + size_done / mFrameSize) * 1000000)
-                    / mSampleRate;
-
-            ALOGV("buffer->size() = %d, "
-                 "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f",
-                 mInputBuffer->range_length(),
-                 mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6);
-        }
-
-        if (mInputBuffer->range_length() == 0) {
-            mInputBuffer->release();
-            mInputBuffer = NULL;
-
-            continue;
-        }
-
-        size_t copy = size_remaining;
-        if (copy > mInputBuffer->range_length()) {
-            copy = mInputBuffer->range_length();
-        }
-
-        memcpy((char *)data + size_done,
-               (const char *)mInputBuffer->data() + mInputBuffer->range_offset(),
-               copy);
-
-        mInputBuffer->set_range(mInputBuffer->range_offset() + copy,
-                                mInputBuffer->range_length() - copy);
-
-        size_done += copy;
-        size_remaining -= copy;
-    }
-
-    {
-        Mutex::Autolock autoLock(mLock);
-        mNumFramesPlayed += size_done / mFrameSize;
-    }
-
-    if (postEOS) {
-        mObserver->postAudioEOS(postEOSDelayUs);
-    }
-
-    if (postSeekComplete) {
-        mObserver->postAudioSeekComplete();
-    }
-
-    return size_done;
-}
-
-int64_t AudioPlayerBase::getRealTimeUs() {
-    Mutex::Autolock autoLock(mLock);
-    return getRealTimeUsLocked();
-}
-
-int64_t AudioPlayerBase::getRealTimeUsLocked() const {
-    return -mLatencyUs + (mNumFramesPlayed * 1000000) / mSampleRate;
-}
-
-int64_t AudioPlayerBase::getMediaTimeUs() {
-    Mutex::Autolock autoLock(mLock);
-
-    if (mPositionTimeMediaUs < 0 || mPositionTimeRealUs < 0) {
-        if (mSeeking) {
-            return mSeekTimeUs;
-        }
-
-        return 0;
-    }
-
-    int64_t realTimeOffset = getRealTimeUsLocked() - mPositionTimeRealUs;
-    if (realTimeOffset < 0) {
-        realTimeOffset = 0;
-    }
-
-    return mPositionTimeMediaUs + realTimeOffset;
-}
-
-bool AudioPlayerBase::getMediaTimeMapping(
-        int64_t *realtime_us, int64_t *mediatime_us) {
-    Mutex::Autolock autoLock(mLock);
-
-    *realtime_us = mPositionTimeRealUs;
-    *mediatime_us = mPositionTimeMediaUs;
-
-    return mPositionTimeRealUs != -1 && mPositionTimeMediaUs != -1;
-}
-
-status_t AudioPlayerBase::seekTo(int64_t time_us) {
-    Mutex::Autolock autoLock(mLock);
-
-    mSeeking = true;
-    mPositionTimeRealUs = mPositionTimeMediaUs = -1;
-    mReachedEOS = false;
-    mSeekTimeUs = time_us;
-
-    if (mAudioSink != NULL) {
-        mAudioSink->flush();
-    } else {
-        mAudioTrack->flush();
-    }
-
-    return OK;
-}
-
-}
diff --git a/libvideoeditor/lvpp/AudioPlayerBase.h b/libvideoeditor/lvpp/AudioPlayerBase.h
deleted file mode 100644
index b39d4a2..0000000
--- a/libvideoeditor/lvpp/AudioPlayerBase.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2011 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 AUDIO_PLAYER_BASE_H_
-
-#define AUDIO_PLAYER_BASE_H_
-
-#include <media/MediaPlayerInterface.h>
-#include <media/stagefright/MediaBuffer.h>
-#include <media/stagefright/TimeSource.h>
-#include <utils/threads.h>
-
-namespace android {
-
-class MediaSource;
-class AudioTrack;
-class PreviewPlayer;
-
-class AudioPlayerBase : public TimeSource {
-public:
-    enum {
-        REACHED_EOS,
-        SEEK_COMPLETE
-    };
-
-    AudioPlayerBase(const sp<MediaPlayerBase::AudioSink> &audioSink,
-                PreviewPlayer *audioObserver = NULL);
-
-    virtual ~AudioPlayerBase();
-
-    // Caller retains ownership of "source".
-    void setSource(const sp<MediaSource> &source);
-
-    // Return time in us.
-    virtual int64_t getRealTimeUs();
-
-    status_t start(bool sourceAlreadyStarted = false);
-
-    void pause(bool playPendingSamples = false);
-    void resume();
-
-    // Returns the timestamp of the last buffer played (in us).
-    int64_t getMediaTimeUs();
-
-    // Returns true iff a mapping is established, i.e. the AudioPlayerBase
-    // has played at least one frame of audio.
-    bool getMediaTimeMapping(int64_t *realtime_us, int64_t *mediatime_us);
-
-    status_t seekTo(int64_t time_us);
-
-    bool isSeeking();
-    bool reachedEOS(status_t *finalStatus);
-
-private:
-    friend class VideoEditorAudioPlayer;
-    sp<MediaSource> mSource;
-    AudioTrack *mAudioTrack;
-
-    MediaBuffer *mInputBuffer;
-
-    int mSampleRate;
-    int64_t mLatencyUs;
-    size_t mFrameSize;
-
-    Mutex mLock;
-    int64_t mNumFramesPlayed;
-
-    int64_t mPositionTimeMediaUs;
-    int64_t mPositionTimeRealUs;
-
-    bool mSeeking;
-    bool mReachedEOS;
-    status_t mFinalStatus;
-    int64_t mSeekTimeUs;
-
-    bool mStarted;
-
-    bool mIsFirstBuffer;
-    status_t mFirstBufferResult;
-    MediaBuffer *mFirstBuffer;
-
-    sp<MediaPlayerBase::AudioSink> mAudioSink;
-    PreviewPlayer *mObserver;
-
-    static void AudioCallback(int event, void *user, void *info);
-    void AudioCallback(int event, void *info);
-
-    static size_t AudioSinkCallback(
-            MediaPlayerBase::AudioSink *audioSink,
-            void *data, size_t size, void *me);
-
-    size_t fillBuffer(void *data, size_t size);
-
-    int64_t getRealTimeUsLocked() const;
-
-    void reset();
-
-    uint32_t getNumFramesPendingPlayout() const;
-
-    AudioPlayerBase(const AudioPlayerBase &);
-    AudioPlayerBase &operator=(const AudioPlayerBase &);
-};
-
-}  // namespace android
-
-#endif  // AUDIO_PLAYER_BASE_H_
diff --git a/libvideoeditor/lvpp/PreviewPlayer.cpp b/libvideoeditor/lvpp/PreviewPlayer.cpp
index 77c70a5..80eee4b 100755
--- a/libvideoeditor/lvpp/PreviewPlayer.cpp
+++ b/libvideoeditor/lvpp/PreviewPlayer.cpp
@@ -36,7 +36,6 @@
 #include <surfaceflinger/ISurfaceComposer.h>
 
 #include "VideoEditorPreviewController.h"
-#include "AudioPlayerBase.h"
 #include "DummyAudioSource.h"
 #include "DummyVideoSource.h"
 #include "VideoEditorSRC.h"
@@ -99,7 +98,7 @@
 
     mVideoRenderer = NULL;
     mEffectsSettings = NULL;
-    mVeAudioPlayer = NULL;
+    mAudioPlayer = NULL;
     mAudioMixStoryBoardTS = 0;
     mCurrentMediaBeginCutTime = 0;
     mCurrentMediaVolumeValue = 0;
@@ -368,7 +367,7 @@
 
         // We've already started the MediaSource in order to enable
         // the prefetcher to read its data.
-        status_t err = mVeAudioPlayer->start(
+        status_t err = mAudioPlayer->start(
                 true /* sourceAlreadyStarted */);
 
         if (err != OK) {
@@ -376,7 +375,7 @@
             return err;
         }
     } else {
-        mVeAudioPlayer->resume();
+        mAudioPlayer->resume();
     }
 
     mFlags |= AUDIO_RUNNING;
@@ -386,7 +385,7 @@
     return OK;
 }
 
-status_t PreviewPlayer::setAudioPlayer(AudioPlayerBase *audioPlayer) {
+status_t PreviewPlayer::setAudioPlayer(VideoEditorAudioPlayer *audioPlayer) {
     ALOGV("setAudioPlayer");
     Mutex::Autolock autoLock(mLock);
     CHECK(!(mFlags & PLAYING));
@@ -394,11 +393,9 @@
 
     ALOGV("SetAudioPlayer");
     mIsChangeSourceRequired = true;
-    mVeAudioPlayer =
-            (VideoEditorAudioPlayer*)mAudioPlayer;
 
     // check if the new and old source are dummy
-    sp<MediaSource> anAudioSource = mVeAudioPlayer->getSource();
+    sp<MediaSource> anAudioSource = mAudioPlayer->getSource();
     if (anAudioSource == NULL) {
         // Audio player does not have any source set.
         ALOGV("setAudioPlayer: Audio player does not have any source set");
@@ -546,25 +543,22 @@
             if (mAudioSink != NULL) {
 
                 mAudioPlayer = new VideoEditorAudioPlayer(mAudioSink, this);
-                mVeAudioPlayer =
-                          (VideoEditorAudioPlayer*)mAudioPlayer;
-
                 mAudioPlayer->setSource(mAudioSource);
 
-                mVeAudioPlayer->setAudioMixSettings(
+                mAudioPlayer->setAudioMixSettings(
                  mPreviewPlayerAudioMixSettings);
 
-                mVeAudioPlayer->setAudioMixPCMFileHandle(
+                mAudioPlayer->setAudioMixPCMFileHandle(
                  mAudioMixPCMFileHandle);
 
-                mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
+                mAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
                  mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
                  mCurrentMediaVolumeValue);
 
                  mFlags |= AUDIOPLAYER_STARTED;
                 // We've already started the MediaSource in order to enable
                 // the prefetcher to read its data.
-                status_t err = mVeAudioPlayer->start(
+                status_t err = mAudioPlayer->start(
                         true /* sourceAlreadyStarted */);
 
                 if (err != OK) {
@@ -575,41 +569,40 @@
                     return err;
                 }
 
-                mTimeSource = mVeAudioPlayer;
+                mTimeSource = mAudioPlayer;
                 mFlags |= AUDIO_RUNNING;
                 deferredAudioSeek = true;
                 mWatchForAudioSeekComplete = false;
                 mWatchForAudioEOS = true;
             }
         } else {
-            mVeAudioPlayer = (VideoEditorAudioPlayer*)mAudioPlayer;
-            bool isAudioPlayerStarted = mVeAudioPlayer->isStarted();
+            bool isAudioPlayerStarted = mAudioPlayer->isStarted();
 
             if (mIsChangeSourceRequired == true) {
                 ALOGV("play_l: Change audio source required");
 
                 if (isAudioPlayerStarted == true) {
-                    mVeAudioPlayer->pause();
+                    mAudioPlayer->pause();
                 }
 
-                mVeAudioPlayer->setSource(mAudioSource);
-                mVeAudioPlayer->setObserver(this);
+                mAudioPlayer->setSource(mAudioSource);
+                mAudioPlayer->setObserver(this);
 
-                mVeAudioPlayer->setAudioMixSettings(
+                mAudioPlayer->setAudioMixSettings(
                  mPreviewPlayerAudioMixSettings);
 
-                mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
+                mAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
                     mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
                     mCurrentMediaVolumeValue);
 
                 if (isAudioPlayerStarted == true) {
-                    mVeAudioPlayer->resume();
+                    mAudioPlayer->resume();
                 } else {
                     status_t err = OK;
-                    err = mVeAudioPlayer->start(true);
+                    err = mAudioPlayer->start(true);
                     if (err != OK) {
                         mAudioPlayer = NULL;
-                        mVeAudioPlayer = NULL;
+                        mAudioPlayer = NULL;
 
                         mFlags &= ~(PLAYING | FIRST_FRAME);
                         return err;
@@ -617,16 +610,16 @@
                 }
             } else {
                 ALOGV("play_l: No Source change required");
-                mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
+                mAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
                     mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
                     mCurrentMediaVolumeValue);
 
-                mVeAudioPlayer->resume();
+                mAudioPlayer->resume();
             }
 
             mFlags |= AUDIOPLAYER_STARTED;
             mFlags |= AUDIO_RUNNING;
-            mTimeSource = mVeAudioPlayer;
+            mTimeSource = mAudioPlayer;
             deferredAudioSeek = true;
             mWatchForAudioSeekComplete = false;
             mWatchForAudioEOS = true;
diff --git a/libvideoeditor/lvpp/PreviewPlayer.h b/libvideoeditor/lvpp/PreviewPlayer.h
index 45f3fc2..177853f 100755
--- a/libvideoeditor/lvpp/PreviewPlayer.h
+++ b/libvideoeditor/lvpp/PreviewPlayer.h
@@ -30,7 +30,6 @@
 namespace android {
 
 struct VideoEditorAudioPlayer;
-struct AudioPlayerBase;
 struct MediaExtractor;
 
 struct PreviewPlayer {
@@ -89,7 +88,7 @@
     status_t setImageClipProperties(uint32_t width, uint32_t height);
     status_t readFirstVideoFrame();
     status_t getLastRenderedTimeMs(uint32_t *lastRenderedTimeMs);
-    status_t setAudioPlayer(AudioPlayerBase *audioPlayer);
+    status_t setAudioPlayer(VideoEditorAudioPlayer *audioPlayer);
 
 private:
     enum {
@@ -143,7 +142,7 @@
 
     sp<MediaSource> mAudioTrack;
     sp<MediaSource> mAudioSource;
-    AudioPlayerBase *mAudioPlayer;
+    VideoEditorAudioPlayer *mAudioPlayer;
     int64_t mDurationUs;
 
     int32_t mDisplayWidth;
@@ -235,7 +234,6 @@
 
     M4VIFI_UInt8*  mFrameRGBBuffer;
     M4VIFI_UInt8*  mFrameYUVBuffer;
-    VideoEditorAudioPlayer  *mVeAudioPlayer;
 
     void cancelPlayerEvents_l(bool updateProgressCb = false);
     status_t setDataSource_l(const sp<MediaExtractor> &extractor);
diff --git a/libvideoeditor/lvpp/VideoEditorAudioPlayer.cpp b/libvideoeditor/lvpp/VideoEditorAudioPlayer.cpp
index 0b642ac..17ad482 100755
--- a/libvideoeditor/lvpp/VideoEditorAudioPlayer.cpp
+++ b/libvideoeditor/lvpp/VideoEditorAudioPlayer.cpp
@@ -35,9 +35,25 @@
 VideoEditorAudioPlayer::VideoEditorAudioPlayer(
         const sp<MediaPlayerBase::AudioSink> &audioSink,
         PreviewPlayer *observer)
-    : AudioPlayerBase(audioSink, observer) {
+    : mAudioTrack(NULL),
+      mInputBuffer(NULL),
+      mSampleRate(0),
+      mLatencyUs(0),
+      mFrameSize(0),
+      mNumFramesPlayed(0),
+      mPositionTimeMediaUs(-1),
+      mPositionTimeRealUs(-1),
+      mSeeking(false),
+      mReachedEOS(false),
+      mFinalStatus(OK),
+      mStarted(false),
+      mIsFirstBuffer(false),
+      mFirstBufferResult(OK),
+      mFirstBuffer(NULL),
+      mAudioSink(audioSink),
+      mObserver(observer) {
 
-    ALOGV("VideoEditorAudioPlayer");
+    ALOGV("Constructor");
     mBGAudioPCMFileHandle = NULL;
     mAudioProcess = NULL;
     mBGAudioPCMFileLength = 0;
@@ -54,7 +70,7 @@
 
 VideoEditorAudioPlayer::~VideoEditorAudioPlayer() {
 
-    ALOGV("~VideoEditorAudioPlayer");
+    ALOGV("Destructor");
     if (mStarted) {
         reset();
     }
@@ -63,6 +79,184 @@
         mAudioProcess = NULL;
     }
 }
+
+void VideoEditorAudioPlayer::pause(bool playPendingSamples) {
+    ALOGV("pause: playPendingSamples=%d", playPendingSamples);
+    CHECK(mStarted);
+
+    if (playPendingSamples) {
+        if (mAudioSink.get() != NULL) {
+            mAudioSink->stop();
+        } else {
+            mAudioTrack->stop();
+        }
+    } else {
+        if (mAudioSink.get() != NULL) {
+            mAudioSink->pause();
+        } else {
+            mAudioTrack->pause();
+        }
+    }
+}
+
+void VideoEditorAudioPlayer::clear() {
+    ALOGV("clear");
+    if (!mStarted) {
+        return;
+    }
+
+    if (mAudioSink.get() != NULL) {
+        mAudioSink->stop();
+        mAudioSink->close();
+    } else {
+        mAudioTrack->stop();
+
+        delete mAudioTrack;
+        mAudioTrack = NULL;
+    }
+
+    // Make sure to release any buffer we hold onto so that the
+    // source is able to stop().
+
+    if (mFirstBuffer != NULL) {
+        mFirstBuffer->release();
+        mFirstBuffer = NULL;
+    }
+
+    if (mInputBuffer != NULL) {
+        ALOGV("AudioPlayerBase releasing input buffer.");
+
+        mInputBuffer->release();
+        mInputBuffer = NULL;
+    }
+
+    mSource->stop();
+
+    // The following hack is necessary to ensure that the OMX
+    // component is completely released by the time we may try
+    // to instantiate it again.
+    wp<MediaSource> tmp = mSource;
+    mSource.clear();
+    while (tmp.promote() != NULL) {
+        usleep(1000);
+    }
+    IPCThreadState::self()->flushCommands();
+
+    mNumFramesPlayed = 0;
+    mPositionTimeMediaUs = -1;
+    mPositionTimeRealUs = -1;
+    mSeeking = false;
+    mReachedEOS = false;
+    mFinalStatus = OK;
+    mStarted = false;
+}
+
+void VideoEditorAudioPlayer::resume() {
+    ALOGV("resume");
+
+    veAudMixSettings audioMixSettings;
+
+    // Single audio player is used;
+    // Pass on the audio ducking parameters
+    // which might have changed with new audio source
+    audioMixSettings.lvInDucking_threshold =
+        mAudioMixSettings->uiInDucking_threshold;
+    audioMixSettings.lvInDucking_lowVolume =
+        ((M4OSA_Float)mAudioMixSettings->uiInDucking_lowVolume) / 100.0;
+    audioMixSettings.lvInDucking_enable =
+        mAudioMixSettings->bInDucking_enable;
+    audioMixSettings.lvPTVolLevel =
+        ((M4OSA_Float)mBGAudioStoryBoardCurrentMediaVolumeVal) / 100.0;
+    audioMixSettings.lvBTVolLevel =
+        ((M4OSA_Float)mAudioMixSettings->uiAddVolume) / 100.0;
+    audioMixSettings.lvBTChannelCount = mAudioMixSettings->uiBTChannelCount;
+    audioMixSettings.lvPTChannelCount = mAudioMixSettings->uiNbChannels;
+
+    // Call to Audio mix param setting
+    mAudioProcess->veSetAudioProcessingParams(audioMixSettings);
+
+    CHECK(mStarted);
+
+    if (mAudioSink.get() != NULL) {
+        mAudioSink->start();
+    } else {
+        mAudioTrack->start();
+    }
+}
+
+status_t VideoEditorAudioPlayer::seekTo(int64_t time_us) {
+    ALOGV("seekTo: %lld", time_us);
+    Mutex::Autolock autoLock(mLock);
+
+    mSeeking = true;
+    mPositionTimeRealUs = mPositionTimeMediaUs = -1;
+    mReachedEOS = false;
+    mSeekTimeUs = time_us;
+
+    if (mAudioSink != NULL) {
+        mAudioSink->flush();
+    } else {
+        mAudioTrack->flush();
+    }
+
+    return OK;
+}
+
+bool VideoEditorAudioPlayer::isSeeking() {
+    Mutex::Autolock lock(mLock);
+    ALOGV("isSeeking: mSeeking=%d", mSeeking);
+    return mSeeking;
+}
+
+bool VideoEditorAudioPlayer::reachedEOS(status_t *finalStatus) {
+    ALOGV("reachedEOS: status=%d", mFinalStatus);
+    *finalStatus = OK;
+
+    Mutex::Autolock autoLock(mLock);
+    *finalStatus = mFinalStatus;
+    return mReachedEOS;
+}
+
+int64_t VideoEditorAudioPlayer::getRealTimeUs() {
+    Mutex::Autolock autoLock(mLock);
+    return getRealTimeUs_l();
+}
+
+int64_t VideoEditorAudioPlayer::getRealTimeUs_l() {
+    return -mLatencyUs + (mNumFramesPlayed * 1000000) / mSampleRate;
+}
+
+int64_t VideoEditorAudioPlayer::getMediaTimeUs() {
+    ALOGV("getMediaTimeUs");
+    Mutex::Autolock autoLock(mLock);
+
+    if (mPositionTimeMediaUs < 0 || mPositionTimeRealUs < 0) {
+        if (mSeeking) {
+            return mSeekTimeUs;
+        }
+
+        return 0;
+    }
+
+    int64_t realTimeOffset = getRealTimeUs_l() - mPositionTimeRealUs;
+    if (realTimeOffset < 0) {
+        realTimeOffset = 0;
+    }
+
+    return mPositionTimeMediaUs + realTimeOffset;
+}
+
+bool VideoEditorAudioPlayer::getMediaTimeMapping(
+        int64_t *realtime_us, int64_t *mediatime_us) {
+    ALOGV("getMediaTimeMapping");
+    Mutex::Autolock autoLock(mLock);
+
+    *realtime_us = mPositionTimeRealUs;
+    *mediatime_us = mPositionTimeMediaUs;
+
+    return mPositionTimeRealUs != -1 && mPositionTimeMediaUs != -1;
+}
+
 void VideoEditorAudioPlayer::setSource(const sp<MediaSource> &source) {
     Mutex::Autolock autoLock(mLock);
 
@@ -106,6 +300,23 @@
     return mStarted;
 }
 
+// static
+void VideoEditorAudioPlayer::AudioCallback(int event, void *user, void *info) {
+    static_cast<VideoEditorAudioPlayer *>(user)->AudioCallback(event, info);
+}
+
+
+void VideoEditorAudioPlayer::AudioCallback(int event, void *info) {
+    if (event != AudioTrack::EVENT_MORE_DATA) {
+        return;
+    }
+
+    AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
+    size_t numBytesWritten = fillBuffer(buffer->raw, buffer->size);
+
+    buffer->size = numBytesWritten;
+}
+
 status_t VideoEditorAudioPlayer::start(bool sourceAlreadyStarted) {
     Mutex::Autolock autoLock(mLock);
     CHECK(!mStarted);
@@ -355,37 +566,11 @@
     return OK;
 }
 
-void VideoEditorAudioPlayer::resume() {
-
-    veAudMixSettings audioMixSettings;
-
-    // Single audio player is used;
-    // Pass on the audio ducking parameters
-    // which might have changed with new audio source
-    audioMixSettings.lvInDucking_threshold =
-        mAudioMixSettings->uiInDucking_threshold;
-    audioMixSettings.lvInDucking_lowVolume =
-        ((M4OSA_Float)mAudioMixSettings->uiInDucking_lowVolume) / 100.0;
-    audioMixSettings.lvInDucking_enable =
-        mAudioMixSettings->bInDucking_enable;
-    audioMixSettings.lvPTVolLevel =
-        ((M4OSA_Float)mBGAudioStoryBoardCurrentMediaVolumeVal) / 100.0;
-    audioMixSettings.lvBTVolLevel =
-        ((M4OSA_Float)mAudioMixSettings->uiAddVolume) / 100.0;
-    audioMixSettings.lvBTChannelCount = mAudioMixSettings->uiBTChannelCount;
-    audioMixSettings.lvPTChannelCount = mAudioMixSettings->uiNbChannels;
-
-    // Call to Audio mix param setting
-    mAudioProcess->veSetAudioProcessingParams(audioMixSettings);
-
-    //Call the base class
-    AudioPlayerBase::resume();
-}
 
 void VideoEditorAudioPlayer::reset() {
 
     ALOGV("reset");
-    AudioPlayerBase::reset();
+    clear();
 
     // Capture the current seek point
     mBGAudioPCMFileSeekPoint = 0;
diff --git a/libvideoeditor/lvpp/VideoEditorAudioPlayer.h b/libvideoeditor/lvpp/VideoEditorAudioPlayer.h
index 2eab4c5..626df39 100755
--- a/libvideoeditor/lvpp/VideoEditorAudioPlayer.h
+++ b/libvideoeditor/lvpp/VideoEditorAudioPlayer.h
@@ -15,19 +15,18 @@
  */
 
 #ifndef VE_AUDIO_PLAYER_H_
-
 #define VE_AUDIO_PLAYER_H_
 
 #include <media/MediaPlayerInterface.h>
 #include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/TimeSource.h>
 #include <utils/threads.h>
+
 #include "M4xVSS_API.h"
 #include "VideoEditorMain.h"
 #include "M4OSA_FileReader.h"
 #include "VideoEditorBGAudioProcessing.h"
-#include "AudioPlayerBase.h"
-#include "PreviewPlayer.h"
+
 
 namespace android {
 
@@ -35,8 +34,7 @@
 class AudioTrack;
 class PreviewPlayer;
 
-
-class VideoEditorAudioPlayer : public AudioPlayerBase {
+class VideoEditorAudioPlayer : public TimeSource {
 public:
     enum {
         REACHED_EOS,
@@ -46,10 +44,24 @@
     VideoEditorAudioPlayer(const sp<MediaPlayerBase::AudioSink> &audioSink,
         PreviewPlayer *audioObserver = NULL);
 
-    virtual ~VideoEditorAudioPlayer();
+    ~VideoEditorAudioPlayer();
+
+    // Return time in us.
+    int64_t getRealTimeUs();
+
+    // Returns the timestamp of the last buffer played (in us).
+    int64_t getMediaTimeUs();
+
+    // Returns true iff a mapping is established, i.e. the AudioPlayerBase
+    // has played at least one frame of audio.
+    bool getMediaTimeMapping(int64_t *realtime_us, int64_t *mediatime_us);
 
     status_t start(bool sourceAlreadyStarted = false);
+    void pause(bool playPendingSamples = false);
     void resume();
+    status_t seekTo(int64_t time_us);
+    bool isSeeking();
+    bool reachedEOS(status_t *finalStatus);
 
     void setAudioMixSettings(M4xVSS_AudioMixingSettings* pAudioMixSettings);
     void setAudioMixPCMFileHandle(M4OSA_Context pBGAudioPCMFileHandle);
@@ -78,15 +90,48 @@
     int64_t mBGAudioStoryBoardCurrentMediaBeginCutTS;
     int64_t mBGAudioStoryBoardCurrentMediaVolumeVal;
 
+    sp<MediaSource> mSource;
+    AudioTrack *mAudioTrack;
+
+    MediaBuffer *mInputBuffer;
+
+    int mSampleRate;
+    int64_t mLatencyUs;
+    size_t mFrameSize;
+
+    Mutex mLock;
+    int64_t mNumFramesPlayed;
+
+    int64_t mPositionTimeMediaUs;
+    int64_t mPositionTimeRealUs;
+
+    bool mSeeking;
+    bool mReachedEOS;
+    status_t mFinalStatus;
+    int64_t mSeekTimeUs;
+
+    bool mStarted;
+
+    bool mIsFirstBuffer;
+    status_t mFirstBufferResult;
+    MediaBuffer *mFirstBuffer;
+
+    sp<MediaPlayerBase::AudioSink> mAudioSink;
+    PreviewPlayer *mObserver;
+
+    static void AudioCallback(int event, void *user, void *info);
+    void AudioCallback(int event, void *info);
     size_t fillBuffer(void *data, size_t size);
-
-    void reset();
-    void setPrimaryTrackVolume(M4OSA_Int16 *data, M4OSA_UInt32 size, M4OSA_Float volLevel);
-
     static size_t AudioSinkCallback(
             MediaPlayerBase::AudioSink *audioSink,
             void *data, size_t size, void *me);
 
+    void reset();
+    void clear();
+    int64_t getRealTimeUs_l();
+    void setPrimaryTrackVolume(
+            M4OSA_Int16 *data, M4OSA_UInt32 size, M4OSA_Float volLevel);
+
     VideoEditorAudioPlayer(const VideoEditorAudioPlayer &);
     VideoEditorAudioPlayer &operator=(const VideoEditorAudioPlayer &);
 };