Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8b71241c authored by Marco Nelissen's avatar Marco Nelissen
Browse files

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
parent 83faee05
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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;
+1 −1
Original line number Diff line number Diff line
@@ -204,7 +204,7 @@ private:
    ReadOptions::SeekMode mSeekMode;
    int64_t mTargetTimeUs;
    bool mOutputPortSettingsChangedPending;
    SkipCutBuffer *mSkipCutBuffer;
    sp<SkipCutBuffer> mSkipCutBuffer;

    MediaBuffer *mLeftOverBuffer;

+4 −2
Original line number Diff line number Diff line
@@ -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);
+1 −35
Original line number Diff line number Diff line
@@ -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);
}

+0 −3
Original line number Diff line number Diff line
@@ -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);
Loading