summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarco Nelissen <marcone@google.com>2012-04-27 09:33:24 -0700
committerMarco Nelissen <marcone@google.com>2012-04-30 09:40:47 -0700
commit8b71241ce7353731ab75322c46e090ee35014a33 (patch)
treeafc21859dae503e57aa5a3cc777512800d1fd64e
parent83faee053cfd4251dbb591b62039f563ffdac399 (diff)
downloadframeworks_av-8b71241ce7353731ab75322c46e090ee35014a33.zip
frameworks_av-8b71241ce7353731ab75322c46e090ee35014a33.tar.gz
frameworks_av-8b71241ce7353731ab75322c46e090ee35014a33.tar.bz2
Fix mono gapless playback for decoders that output stereo
The old AAC decoder always outputs stereo, even for mono source material, so we need to use the number of channels of the output when calculating the number of bytes to skip, not the number of channels in the source. This makes OMXCodec skip the right amount of data, and prevents NuPlayer from writing half a frame and then asserting when the AudioSink doesn't accept it. Also move use of the SkipCutBuffer from NuPlayer to ACodec, so that it also works when using the new Java APIs, and make SkipCutBuffer derive from RefBase. b/774846 Change-Id: I34df9fea3e6730617eae559afaa556f4085ef0a0
-rw-r--r--include/media/stagefright/ACodec.h4
-rw-r--r--include/media/stagefright/OMXCodec.h2
-rw-r--r--include/media/stagefright/SkipCutBuffer.h6
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayer.cpp36
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayer.h3
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp9
-rw-r--r--media/libstagefright/ACodec.cpp21
-rw-r--r--media/libstagefright/NuMediaExtractor.cpp9
-rwxr-xr-xmedia/libstagefright/OMXCodec.cpp12
9 files changed, 53 insertions, 49 deletions
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index b8d925e..72827c1 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -22,6 +22,7 @@
#include <android/native_window.h>
#include <media/IOMX.h>
#include <media/stagefright/foundation/AHierarchicalStateMachine.h>
+#include <media/stagefright/SkipCutBuffer.h>
#include <OMX_Audio.h>
namespace android {
@@ -120,6 +121,9 @@ private:
sp<ExecutingToIdleState> mExecutingToIdleState;
sp<IdleToLoadedState> mIdleToLoadedState;
sp<FlushingState> mFlushingState;
+ int32_t mEncoderDelay;
+ int32_t mEncoderPadding;
+ sp<SkipCutBuffer> mSkipCutBuffer;
AString mComponentName;
uint32_t mFlags;
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index 887ce5d..81350ca 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -204,7 +204,7 @@ private:
ReadOptions::SeekMode mSeekMode;
int64_t mTargetTimeUs;
bool mOutputPortSettingsChangedPending;
- SkipCutBuffer *mSkipCutBuffer;
+ sp<SkipCutBuffer> mSkipCutBuffer;
MediaBuffer *mLeftOverBuffer;
diff --git a/include/media/stagefright/SkipCutBuffer.h b/include/media/stagefright/SkipCutBuffer.h
index 27851ca..2653b53 100644
--- a/include/media/stagefright/SkipCutBuffer.h
+++ b/include/media/stagefright/SkipCutBuffer.h
@@ -27,12 +27,11 @@ namespace android {
* utility class to cut the start and end off a stream of data in MediaBuffers
*
*/
-class SkipCutBuffer {
+class SkipCutBuffer: public RefBase {
public:
// 'skip' is the number of bytes to skip from the beginning
// 'cut' is the number of bytes to cut from the end
SkipCutBuffer(int32_t skip, int32_t cut);
- virtual ~SkipCutBuffer();
// Submit one MediaBuffer for skipping and cutting. This may consume all or
// some of the data in the buffer, or it may add data to it.
@@ -42,6 +41,9 @@ class SkipCutBuffer {
void clear();
size_t size(); // how many bytes are currently stored in the buffer
+ protected:
+ virtual ~SkipCutBuffer();
+
private:
void write(const char *src, size_t num);
size_t read(char *dst, size_t num);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index f1467c4..2a770cd 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -39,7 +39,6 @@
#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"
@@ -64,13 +63,10 @@ NuPlayer::NuPlayer()
mSkipRenderingVideoUntilMediaTimeUs(-1ll),
mVideoLateByUs(0ll),
mNumFramesTotal(0ll),
- mNumFramesDropped(0ll),
- mSkipCutBuffer(NULL) {
+ mNumFramesDropped(0ll) {
}
NuPlayer::~NuPlayer() {
- delete mSkipCutBuffer;
- mSkipCutBuffer = NULL;
}
void NuPlayer::setUID(uid_t uid) {
@@ -238,32 +234,6 @@ 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()));
@@ -892,10 +862,6 @@ 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 f917f64..25766e0 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -27,7 +27,6 @@ namespace android {
struct ACodec;
struct MetaData;
struct NuPlayerDriver;
-class SkipCutBuffer;
struct NuPlayer : public AHandler {
NuPlayer();
@@ -129,8 +128,6 @@ 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/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index 25974b6..d18d146 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -124,6 +124,15 @@ sp<AMessage> NuPlayer::Decoder::makeFormat(const sp<MetaData> &meta) {
msg->setInt32("channel-count", numChannels);
msg->setInt32("sample-rate", sampleRate);
+ int32_t delay = 0;
+ if (meta->findInt32(kKeyEncoderDelay, &delay)) {
+ msg->setInt32("encoder-delay", delay);
+ }
+ int32_t padding = 0;
+ if (meta->findInt32(kKeyEncoderPadding, &padding)) {
+ msg->setInt32("encoder-padding", padding);
+ }
+
int32_t isADTS;
if (meta->findInt32(kKeyIsADTS, &isADTS) && isADTS != 0) {
msg->setInt32("is-adts", true);
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index c303146..0de2d0a 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -889,6 +889,13 @@ status_t ACodec::configureCodec(
}
}
+ if (!msg->findInt32("encoder-delay", &mEncoderDelay)) {
+ mEncoderDelay = 0;
+ }
+ if (!msg->findInt32("encoder-padding", &mEncoderPadding)) {
+ mEncoderPadding = 0;
+ }
+
int32_t maxInputSize;
if (msg->findInt32("max-input-size", &maxInputSize)) {
err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize);
@@ -2003,6 +2010,17 @@ void ACodec::sendFormatChange() {
notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
notify->setInt32("channel-count", params.nChannels);
notify->setInt32("sample-rate", params.nSamplingRate);
+ if (mEncoderDelay + mEncoderPadding) {
+ size_t frameSize = params.nChannels * sizeof(int16_t);
+ if (mSkipCutBuffer != NULL) {
+ size_t prevbufsize = mSkipCutBuffer->size();
+ if (prevbufsize != 0) {
+ ALOGW("Replacing SkipCutBuffer holding %d bytes", prevbufsize);
+ }
+ }
+ mSkipCutBuffer = new SkipCutBuffer(mEncoderDelay * frameSize,
+ mEncoderPadding * frameSize);
+ }
break;
}
@@ -2417,6 +2435,9 @@ bool ACodec::BaseState::onOMXFillBufferDone(
info->mData->setRange(rangeOffset, rangeLength);
}
+ if (mCodec->mSkipCutBuffer != NULL) {
+ mCodec->mSkipCutBuffer->submit(info->mData);
+ }
info->mData->meta()->setInt64("timeUs", timeUs);
sp<AMessage> notify = mCodec->mNotify->dup();
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index 78b2469..d6075cd 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -220,6 +220,15 @@ status_t NuMediaExtractor::getTrackFormat(
msg->setInt32("channel-count", numChannels);
msg->setInt32("sample-rate", sampleRate);
+ int32_t delay = 0;
+ if (meta->findInt32(kKeyEncoderDelay, &delay)) {
+ msg->setInt32("encoder-delay", delay);
+ }
+ int32_t padding = 0;
+ if (meta->findInt32(kKeyEncoderPadding, &padding)) {
+ msg->setInt32("encoder-padding", padding);
+ }
+
int32_t isADTS;
if (meta->findInt32(kKeyIsADTS, &isADTS)) {
msg->setInt32("is-adts", true);
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 245d941..fb6491b 100755
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1434,9 +1434,6 @@ OMXCodec::~OMXCodec() {
free(mMIME);
mMIME = NULL;
-
- delete mSkipCutBuffer;
- mSkipCutBuffer = NULL;
}
status_t OMXCodec::init() {
@@ -1610,14 +1607,13 @@ status_t OMXCodec::allocateBuffersOnPort(OMX_U32 portIndex) {
}
int32_t numchannels = 0;
if (delay + padding) {
- if (meta->findInt32(kKeyChannelCount, &numchannels)) {
+ if (mOutputFormat->findInt32(kKeyChannelCount, &numchannels)) {
size_t frameSize = numchannels * sizeof(int16_t);
- if (mSkipCutBuffer) {
+ if (mSkipCutBuffer != NULL) {
size_t prevbuffersize = mSkipCutBuffer->size();
if (prevbuffersize != 0) {
ALOGW("Replacing SkipCutBuffer holding %d bytes", prevbuffersize);
}
- delete mSkipCutBuffer;
}
mSkipCutBuffer = new SkipCutBuffer(delay * frameSize, padding * frameSize);
}
@@ -2541,7 +2537,7 @@ void OMXCodec::onCmdComplete(OMX_COMMANDTYPE cmd, OMX_U32 data) {
CHECK_EQ(countBuffersWeOwn(mPortBuffers[portIndex]),
mPortBuffers[portIndex].size());
- if (mSkipCutBuffer && mPortStatus[kPortIndexOutput] == ENABLED) {
+ if (mSkipCutBuffer != NULL && mPortStatus[kPortIndexOutput] == ENABLED) {
mSkipCutBuffer->clear();
}
@@ -3863,7 +3859,7 @@ status_t OMXCodec::read(
info->mStatus = OWNED_BY_CLIENT;
info->mMediaBuffer->add_ref();
- if (mSkipCutBuffer) {
+ if (mSkipCutBuffer != NULL) {
mSkipCutBuffer->submit(info->mMediaBuffer);
}
*buffer = info->mMediaBuffer;