summaryrefslogtreecommitdiffstats
path: root/libvideoeditor
diff options
context:
space:
mode:
Diffstat (limited to 'libvideoeditor')
-rwxr-xr-xlibvideoeditor/lvpp/Android.mk1
-rw-r--r--libvideoeditor/lvpp/AudioPlayerBase.cpp510
-rw-r--r--libvideoeditor/lvpp/AudioPlayerBase.h119
-rwxr-xr-xlibvideoeditor/lvpp/PreviewPlayer.cpp51
-rwxr-xr-xlibvideoeditor/lvpp/PreviewPlayer.h6
-rwxr-xr-xlibvideoeditor/lvpp/VideoEditorAudioPlayer.cpp247
-rwxr-xr-xlibvideoeditor/lvpp/VideoEditorAudioPlayer.h63
7 files changed, 294 insertions, 703 deletions
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 @@ LOCAL_SRC_FILES:= \
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 @@ PreviewPlayer::PreviewPlayer(NativeWindowRenderer* renderer)
mVideoRenderer = NULL;
mEffectsSettings = NULL;
- mVeAudioPlayer = NULL;
+ mAudioPlayer = NULL;
mAudioMixStoryBoardTS = 0;
mCurrentMediaBeginCutTime = 0;
mCurrentMediaVolumeValue = 0;
@@ -368,7 +367,7 @@ status_t PreviewPlayer::startAudioPlayer_l() {
// 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 @@ status_t PreviewPlayer::startAudioPlayer_l() {
return err;
}
} else {
- mVeAudioPlayer->resume();
+ mAudioPlayer->resume();
}
mFlags |= AUDIO_RUNNING;
@@ -386,7 +385,7 @@ status_t PreviewPlayer::startAudioPlayer_l() {
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 @@ status_t PreviewPlayer::setAudioPlayer(AudioPlayerBase *audioPlayer) {
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 @@ status_t PreviewPlayer::play_l() {
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 @@ status_t PreviewPlayer::play_l() {
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 @@ status_t PreviewPlayer::play_l() {
}
} 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 @@ struct PreviewPlayer {
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 @@ private:
sp<MediaSource> mAudioTrack;
sp<MediaSource> mAudioSource;
- AudioPlayerBase *mAudioPlayer;
+ VideoEditorAudioPlayer *mAudioPlayer;
int64_t mDurationUs;
int32_t mDisplayWidth;
@@ -235,7 +234,6 @@ private:
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 @@ namespace android {
VideoEditorAudioPlayer::VideoEditorAudioPlayer(
const sp<MediaPlayerBase::AudioSink> &audioSink,
PreviewPlayer *observer)
- : AudioPlayerBase(audioSink, observer) {
-
- ALOGV("VideoEditorAudioPlayer");
+ : 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("Constructor");
mBGAudioPCMFileHandle = NULL;
mAudioProcess = NULL;
mBGAudioPCMFileLength = 0;
@@ -54,7 +70,7 @@ VideoEditorAudioPlayer::VideoEditorAudioPlayer(
VideoEditorAudioPlayer::~VideoEditorAudioPlayer() {
- ALOGV("~VideoEditorAudioPlayer");
+ ALOGV("Destructor");
if (mStarted) {
reset();
}
@@ -63,6 +79,184 @@ VideoEditorAudioPlayer::~VideoEditorAudioPlayer() {
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 @@ bool VideoEditorAudioPlayer::isStarted() {
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 @@ status_t VideoEditorAudioPlayer::start(bool sourceAlreadyStarted) {
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 MediaSource;
class AudioTrack;
class PreviewPlayer;
-
-class VideoEditorAudioPlayer : public AudioPlayerBase {
+class VideoEditorAudioPlayer : public TimeSource {
public:
enum {
REACHED_EOS,
@@ -46,10 +44,24 @@ public:
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 @@ private:
int64_t mBGAudioStoryBoardCurrentMediaBeginCutTS;
int64_t mBGAudioStoryBoardCurrentMediaVolumeVal;
- size_t fillBuffer(void *data, size_t size);
+ sp<MediaSource> mSource;
+ AudioTrack *mAudioTrack;
- void reset();
- void setPrimaryTrackVolume(M4OSA_Int16 *data, M4OSA_UInt32 size, M4OSA_Float volLevel);
+ 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);
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 &);
};