summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarco Nelissen <marcone@google.com>2012-03-29 09:31:28 -0700
committerMarco Nelissen <marcone@google.com>2012-04-02 09:19:03 -0700
commit4110c101c3d0dd8dbc44c8d2d0edd3e2e7d6652f (patch)
tree7bb39d31afac7348bb91093cc0e1c2d9aa49cba2
parenta1472d9883e35edd280201c8be3191695007dfd4 (diff)
downloadframeworks_av-4110c101c3d0dd8dbc44c8d2d0edd3e2e7d6652f.zip
frameworks_av-4110c101c3d0dd8dbc44c8d2d0edd3e2e7d6652f.tar.gz
frameworks_av-4110c101c3d0dd8dbc44c8d2d0edd3e2e7d6652f.tar.bz2
Add gapless playback support for NuPlayer
This makes NuPlayer use a SkipCutBuffer when needed, and adds a new AudioSink method to retrieve the number of frames written so far, so NuPlayerRenderer can calculate how much data it can write without blocking. Also make some more methods const. Change-Id: Id7d253ad8a7b85e9a84ca2baafbe32817b16c744
-rw-r--r--include/media/MediaPlayerInterface.h5
-rwxr-xr-xlibvideoeditor/lvpp/VideoEditorPlayer.cpp11
-rwxr-xr-xlibvideoeditor/lvpp/VideoEditorPlayer.h5
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.cpp25
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.h11
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayer.cpp36
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayer.h3
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp4
8 files changed, 85 insertions, 15 deletions
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index d4aa233..9a8f4b0 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -87,8 +87,9 @@ public:
virtual ssize_t frameSize() const = 0;
virtual uint32_t latency() const = 0;
virtual float msecsPerFrame() const = 0;
- virtual status_t getPosition(uint32_t *position) = 0;
- virtual int getSessionId() = 0;
+ virtual status_t getPosition(uint32_t *position) const = 0;
+ virtual status_t getFramesWritten(uint32_t *frameswritten) const = 0;
+ virtual int getSessionId() const = 0;
// If no callback is specified, use the "write" API below to submit
// audio data.
diff --git a/libvideoeditor/lvpp/VideoEditorPlayer.cpp b/libvideoeditor/lvpp/VideoEditorPlayer.cpp
index 57cab08..1ba1f44 100755
--- a/libvideoeditor/lvpp/VideoEditorPlayer.cpp
+++ b/libvideoeditor/lvpp/VideoEditorPlayer.cpp
@@ -376,12 +376,19 @@ float VideoEditorPlayer::VeAudioOutput::msecsPerFrame() const
return mMsecsPerFrame;
}
-status_t VideoEditorPlayer::VeAudioOutput::getPosition(uint32_t *position) {
+status_t VideoEditorPlayer::VeAudioOutput::getPosition(uint32_t *position) const {
if (mTrack == 0) return NO_INIT;
return mTrack->getPosition(position);
}
+status_t VideoEditorPlayer::VeAudioOutput::getFramesWritten(uint32_t *written) const {
+
+ if (mTrack == 0) return NO_INIT;
+ *written = mNumFramesWritten;
+ return OK;
+}
+
status_t VideoEditorPlayer::VeAudioOutput::open(
uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
audio_format_t format, int bufferCount,
@@ -569,7 +576,7 @@ status_t VideoEditorPlayer::VeAudioOutput::dump(int fd, const Vector<String16>&
return NO_ERROR;
}
-int VideoEditorPlayer::VeAudioOutput::getSessionId() {
+int VideoEditorPlayer::VeAudioOutput::getSessionId() const {
return mSessionId;
}
diff --git a/libvideoeditor/lvpp/VideoEditorPlayer.h b/libvideoeditor/lvpp/VideoEditorPlayer.h
index 6962501..350b384 100755
--- a/libvideoeditor/lvpp/VideoEditorPlayer.h
+++ b/libvideoeditor/lvpp/VideoEditorPlayer.h
@@ -45,8 +45,9 @@ class VideoEditorPlayer : public MediaPlayerInterface {
virtual ssize_t frameSize() const;
virtual uint32_t latency() const;
virtual float msecsPerFrame() const;
- virtual status_t getPosition(uint32_t *position);
- virtual int getSessionId();
+ virtual status_t getPosition(uint32_t *position) const;
+ virtual status_t getFramesWritten(uint32_t*) const;
+ virtual int getSessionId() const;
virtual status_t open(
uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index cc3138d..a977337 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -1417,6 +1417,7 @@ MediaPlayerService::AudioOutput::AudioOutput(int sessionId)
: mCallback(NULL),
mCallbackCookie(NULL),
mCallbackData(NULL),
+ mBytesWritten(0),
mSessionId(sessionId) {
ALOGV("AudioOutput(%d)", sessionId);
mTrack = 0;
@@ -1495,12 +1496,19 @@ float MediaPlayerService::AudioOutput::msecsPerFrame() const
return mMsecsPerFrame;
}
-status_t MediaPlayerService::AudioOutput::getPosition(uint32_t *position)
+status_t MediaPlayerService::AudioOutput::getPosition(uint32_t *position) const
{
if (mTrack == 0) return NO_INIT;
return mTrack->getPosition(position);
}
+status_t MediaPlayerService::AudioOutput::getFramesWritten(uint32_t *frameswritten) const
+{
+ if (mTrack == 0) return NO_INIT;
+ *frameswritten = mBytesWritten / frameSize();
+ return OK;
+}
+
status_t MediaPlayerService::AudioOutput::open(
uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
audio_format_t format, int bufferCount,
@@ -1656,6 +1664,7 @@ void MediaPlayerService::AudioOutput::switchToNextOutput() {
mTrack = NULL;
mNextOutput->mSampleRateHz = mSampleRateHz;
mNextOutput->mMsecsPerFrame = mMsecsPerFrame;
+ mNextOutput->mBytesWritten = mBytesWritten;
}
}
@@ -1666,6 +1675,7 @@ ssize_t MediaPlayerService::AudioOutput::write(const void* buffer, size_t size)
//ALOGV("write(%p, %u)", buffer, size);
if (mTrack) {
ssize_t ret = mTrack->write(buffer, size);
+ mBytesWritten += ret;
return ret;
}
return NO_INIT;
@@ -1777,7 +1787,7 @@ void MediaPlayerService::AudioOutput::CallbackWrapper(
data->unlock();
}
-int MediaPlayerService::AudioOutput::getSessionId()
+int MediaPlayerService::AudioOutput::getSessionId() const
{
return mSessionId;
}
@@ -1802,13 +1812,20 @@ float MediaPlayerService::AudioCache::msecsPerFrame() const
return mMsecsPerFrame;
}
-status_t MediaPlayerService::AudioCache::getPosition(uint32_t *position)
+status_t MediaPlayerService::AudioCache::getPosition(uint32_t *position) const
{
if (position == 0) return BAD_VALUE;
*position = mSize;
return NO_ERROR;
}
+status_t MediaPlayerService::AudioCache::getFramesWritten(uint32_t *written) const
+{
+ if (written == 0) return BAD_VALUE;
+ *written = mSize;
+ return NO_ERROR;
+}
+
////////////////////////////////////////////////////////////////////////////////
struct CallbackThread : public Thread {
@@ -1971,7 +1988,7 @@ void MediaPlayerService::AudioCache::notify(
p->mSignal.signal();
}
-int MediaPlayerService::AudioCache::getSessionId()
+int MediaPlayerService::AudioCache::getSessionId() const
{
return 0;
}
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index b08dd6c..2a8cfd2 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -84,8 +84,9 @@ class MediaPlayerService : public BnMediaPlayerService
virtual ssize_t frameSize() const;
virtual uint32_t latency() const;
virtual float msecsPerFrame() const;
- virtual status_t getPosition(uint32_t *position);
- virtual int getSessionId();
+ virtual status_t getPosition(uint32_t *position) const;
+ virtual status_t getFramesWritten(uint32_t *frameswritten) const;
+ virtual int getSessionId() const;
virtual status_t open(
uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
@@ -122,6 +123,7 @@ class MediaPlayerService : public BnMediaPlayerService
AudioCallback mCallback;
void * mCallbackCookie;
CallbackData * mCallbackData;
+ uint64_t mBytesWritten;
audio_stream_type_t mStreamType;
float mLeftVolume;
float mRightVolume;
@@ -181,8 +183,9 @@ class MediaPlayerService : public BnMediaPlayerService
virtual ssize_t frameSize() const { return ssize_t(mChannelCount * ((mFormat == AUDIO_FORMAT_PCM_16_BIT)?sizeof(int16_t):sizeof(u_int8_t))); }
virtual uint32_t latency() const;
virtual float msecsPerFrame() const;
- virtual status_t getPosition(uint32_t *position);
- virtual int getSessionId();
+ virtual status_t getPosition(uint32_t *position) const;
+ virtual status_t getFramesWritten(uint32_t *frameswritten) const;
+ virtual int getSessionId() const;
virtual status_t open(
uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 544d501..11cea3b 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -39,6 +39,7 @@
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MetaData.h>
+#include <media/stagefright/SkipCutBuffer.h>
#include <gui/ISurfaceTexture.h>
#include "avc_utils.h"
@@ -63,10 +64,13 @@ NuPlayer::NuPlayer()
mSkipRenderingVideoUntilMediaTimeUs(-1ll),
mVideoLateByUs(0ll),
mNumFramesTotal(0ll),
- mNumFramesDropped(0ll) {
+ mNumFramesDropped(0ll),
+ mSkipCutBuffer(NULL) {
}
NuPlayer::~NuPlayer() {
+ delete mSkipCutBuffer;
+ mSkipCutBuffer = NULL;
}
void NuPlayer::setUID(uid_t uid) {
@@ -234,6 +238,32 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
mSource->start();
+ sp<MetaData> meta = mSource->getFormat(true /* audio */);
+ if (meta != NULL) {
+ int32_t delay = 0;
+ if (!meta->findInt32(kKeyEncoderDelay, &delay)) {
+ delay = 0;
+ }
+ int32_t padding = 0;
+ if (!meta->findInt32(kKeyEncoderPadding, &padding)) {
+ padding = 0;
+ }
+ int32_t numchannels = 0;
+ if (delay + padding) {
+ if (meta->findInt32(kKeyChannelCount, &numchannels)) {
+ size_t frameSize = numchannels * sizeof(int16_t);
+ if (mSkipCutBuffer) {
+ size_t prevbuffersize = mSkipCutBuffer->size();
+ if (prevbuffersize != 0) {
+ ALOGW("Replacing SkipCutBuffer holding %d bytes", prevbuffersize);
+ }
+ delete mSkipCutBuffer;
+ }
+ mSkipCutBuffer = new SkipCutBuffer(delay * frameSize, padding * frameSize);
+ }
+ }
+ }
+
mRenderer = new Renderer(
mAudioSink,
new AMessage(kWhatRendererNotify, id()));
@@ -844,6 +874,10 @@ void NuPlayer::renderBuffer(bool audio, const sp<AMessage> &msg) {
skipUntilMediaTimeUs = -1;
}
+ if (audio && mSkipCutBuffer) {
+ mSkipCutBuffer->submit(buffer);
+ }
+
mRenderer->queueBuffer(audio, buffer, reply);
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index 25766e0..f917f64 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -27,6 +27,7 @@ namespace android {
struct ACodec;
struct MetaData;
struct NuPlayerDriver;
+class SkipCutBuffer;
struct NuPlayer : public AHandler {
NuPlayer();
@@ -128,6 +129,8 @@ private:
int64_t mVideoLateByUs;
int64_t mNumFramesTotal, mNumFramesDropped;
+ SkipCutBuffer *mSkipCutBuffer;
+
status_t instantiateDecoder(bool audio, sp<Decoder> *decoder);
status_t feedDecoderInputData(bool audio, const sp<AMessage> &msg);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index ecbc428..1f13955 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -591,6 +591,10 @@ bool NuPlayer::Renderer::dropBufferWhileFlushing(
void NuPlayer::Renderer::onAudioSinkChanged() {
CHECK(!mDrainAudioQueuePending);
mNumFramesWritten = 0;
+ uint32_t written;
+ if (mAudioSink->getFramesWritten(&written) == OK) {
+ mNumFramesWritten = written;
+ }
}
void NuPlayer::Renderer::notifyPosition() {