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

Commit e00eefe6 authored by Glenn Kasten's avatar Glenn Kasten
Browse files

Fix several test-resample BufferProvider bugs

Previously getNextBuffer always returned the same data address over
and over.  Now it correctly returns the right portion of the input buffer.

Previously getNextBuffer always returned the total number of frames in
the input, which might be larger than the size requested by the caller,
and/or larger than the number of remaining input frames.  It also always
returned successfully, even when there should be no frames available.
This violates the contract for getNextBuffer.  Now getNextBuffer will
return the maximum of the number of frames requested, and the number of
remaining frames available.  If that maximum is zero, getNextBuffer will
return an error instead.

Previously releaseBuffer would silently allow releasing more frames than
were actually gotten, which violates the contract for releaseBuffer.
Now releaseBuffer checks for this and logs a message if it happens.

Add 'v' (verbose) option to log buffer provider calls.

Bug: 12194314
Change-Id: I9b915e954b3612a07ef271da8652486b8875e0fd
parent e175e5ec
Loading
Loading
Loading
Loading
+61 −10
Original line number Original line Diff line number Diff line
@@ -29,6 +29,8 @@


using namespace android;
using namespace android;


bool gVerbose = false;

struct HeaderWav {
struct HeaderWav {
    HeaderWav(size_t size, int nc, int sr, int bits) {
    HeaderWav(size_t size, int nc, int sr, int bits) {
        strncpy(RIFF, "RIFF", 4);
        strncpy(RIFF, "RIFF", 4);
@@ -62,10 +64,11 @@ struct HeaderWav {
};
};


static int usage(const char* name) {
static int usage(const char* name) {
    fprintf(stderr,"Usage: %s [-p] [-h] [-s] [-q {dq|lq|mq|hq|vhq}] [-i input-sample-rate] "
    fprintf(stderr,"Usage: %s [-p] [-h] [-v] [-s] [-q {dq|lq|mq|hq|vhq}] [-i input-sample-rate] "
                   "[-o output-sample-rate] [<input-file>] <output-file>\n", name);
                   "[-o output-sample-rate] [<input-file>] <output-file>\n", name);
    fprintf(stderr,"    -p    enable profiling\n");
    fprintf(stderr,"    -p    enable profiling\n");
    fprintf(stderr,"    -h    create wav file\n");
    fprintf(stderr,"    -h    create wav file\n");
    fprintf(stderr,"    -v    verbose : log buffer provider calls\n");
    fprintf(stderr,"    -s    stereo\n");
    fprintf(stderr,"    -s    stereo\n");
    fprintf(stderr,"    -q    resampler quality\n");
    fprintf(stderr,"    -q    resampler quality\n");
    fprintf(stderr,"              dq  : default quality\n");
    fprintf(stderr,"              dq  : default quality\n");
@@ -89,7 +92,7 @@ int main(int argc, char* argv[]) {
    AudioResampler::src_quality quality = AudioResampler::DEFAULT_QUALITY;
    AudioResampler::src_quality quality = AudioResampler::DEFAULT_QUALITY;


    int ch;
    int ch;
    while ((ch = getopt(argc, argv, "phsq:i:o:")) != -1) {
    while ((ch = getopt(argc, argv, "phvsq:i:o:")) != -1) {
        switch (ch) {
        switch (ch) {
        case 'p':
        case 'p':
            profiling = true;
            profiling = true;
@@ -97,6 +100,9 @@ int main(int argc, char* argv[]) {
        case 'h':
        case 'h':
            writeHeader = true;
            writeHeader = true;
            break;
            break;
        case 'v':
            gVerbose = true;
            break;
        case 's':
        case 's':
            channels = 2;
            channels = 2;
            break;
            break;
@@ -186,24 +192,59 @@ int main(int argc, char* argv[]) {
    // ----------------------------------------------------------
    // ----------------------------------------------------------


    class Provider: public AudioBufferProvider {
    class Provider: public AudioBufferProvider {
        int16_t* mAddr;
        int16_t* const  mAddr;      // base address
        size_t mNumFrames;
        const size_t    mNumFrames; // total frames
        const int       mChannels;
        size_t          mNextFrame; // index of next frame to provide
        size_t          mUnrel;     // number of frames not yet released
    public:
    public:
        Provider(const void* addr, size_t size, int channels) {
        Provider(const void* addr, size_t size, int channels)
            mAddr = (int16_t*) addr;
          : mAddr((int16_t*) addr),
            mNumFrames = size / (channels*sizeof(int16_t));
            mNumFrames(size / (channels*sizeof(int16_t))),
            mChannels(channels),
            mNextFrame(0), mUnrel(0) {
        }
        }
        virtual status_t getNextBuffer(Buffer* buffer,
        virtual status_t getNextBuffer(Buffer* buffer,
                int64_t pts = kInvalidPTS) {
                int64_t pts = kInvalidPTS) {
            buffer->frameCount = mNumFrames;
            size_t requestedFrames = buffer->frameCount;
            buffer->i16 = mAddr;
            if (requestedFrames > mNumFrames - mNextFrame) {
                buffer->frameCount = mNumFrames - mNextFrame;
            }
            if (gVerbose) {
                printf("getNextBuffer() requested %u frames out of %u frames available,"
                        " and returned %u frames\n",
                        requestedFrames, mNumFrames - mNextFrame, buffer->frameCount);
            }
            mUnrel = buffer->frameCount;
            if (buffer->frameCount > 0) {
                buffer->i16 = &mAddr[mChannels * mNextFrame];
                return NO_ERROR;
                return NO_ERROR;
            } else {
                buffer->i16 = NULL;
                return NOT_ENOUGH_DATA;
            }
        }
        }
        virtual void releaseBuffer(Buffer* buffer) {
        virtual void releaseBuffer(Buffer* buffer) {
            if (buffer->frameCount > mUnrel) {
                fprintf(stderr, "ERROR releaseBuffer() released %u frames but only %u available "
                        "to release\n", buffer->frameCount, mUnrel);
                mNextFrame += mUnrel;
                mUnrel = 0;
            } else {
                if (gVerbose) {
                    printf("releaseBuffer() released %u frames out of %u frames available "
                            "to release\n", buffer->frameCount, mUnrel);
                }
                mNextFrame += buffer->frameCount;
                mUnrel -= buffer->frameCount;
            }
        }
        }
    } provider(input_vaddr, input_size, channels);
    } provider(input_vaddr, input_size, channels);


    size_t input_frames = input_size / (channels * sizeof(int16_t));
    size_t input_frames = input_size / (channels * sizeof(int16_t));
    if (gVerbose) {
        printf("%u input frames\n", input_frames);
    }
    size_t output_size = 2 * 4 * ((int64_t) input_frames * output_freq) / input_freq;
    size_t output_size = 2 * 4 * ((int64_t) input_frames * output_freq) / input_freq;
    output_size &= ~7; // always stereo, 32-bits
    output_size &= ~7; // always stereo, 32-bits


@@ -240,7 +281,17 @@ int main(int argc, char* argv[]) {
    resampler->setVolume(0x1000, 0x1000);
    resampler->setVolume(0x1000, 0x1000);


    memset(output_vaddr, 0, output_size);
    memset(output_vaddr, 0, output_size);
    if (gVerbose) {
        printf("resample() %u output frames\n", out_frames);
    }
    resampler->resample((int*) output_vaddr, out_frames, &provider);
    resampler->resample((int*) output_vaddr, out_frames, &provider);
    if (gVerbose) {
        printf("resample() complete\n");
    }
    resampler->reset();
    if (gVerbose) {
        printf("reset() complete\n");
    }


    // down-mix (we just truncate and keep the left channel)
    // down-mix (we just truncate and keep the left channel)
    int32_t* out = (int32_t*) output_vaddr;
    int32_t* out = (int32_t*) output_vaddr;