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

Commit daaee262 authored by Ruchika Ashtankar's avatar Ruchika Ashtankar
Browse files

MediaTesting: Add amr-nb Decoder Test

Test: AmrnbDecoderTest -P /data/local/tmp/

Bug: 145341631

Change-Id: Ifa9702af73f4fef9281c3f35be2809f82e2b2d14
parent 097f05bd
Loading
Loading
Loading
Loading
+72 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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 __AMRNBDEC_TEST_ENVIRONMENT_H__
#define __AMRNBDEC_TEST_ENVIRONMENT_H__

#include <gtest/gtest.h>

#include <getopt.h>

using namespace std;

class AmrnbDecTestEnvironment : public ::testing::Environment {
  public:
    AmrnbDecTestEnvironment() : res("/data/local/tmp/") {}

    // Parses the command line arguments
    int initFromOptions(int argc, char **argv);

    void setRes(const char *_res) { res = _res; }

    const string getRes() const { return res; }

  private:
    string res;
};

int AmrnbDecTestEnvironment::initFromOptions(int argc, char **argv) {
    static struct option options[] = {{"res", required_argument, 0, 'P'}, {0, 0, 0, 0}};

    while (true) {
        int index = 0;
        int c = getopt_long(argc, argv, "P:", options, &index);
        if (c == -1) {
            break;
        }

        switch (c) {
            case 'P':
                setRes(optarg);
                break;
            default:
                break;
        }
    }

    if (optind < argc) {
        fprintf(stderr,
                "unrecognized option: %s\n\n"
                "usage: %s <gtest options> <test options>\n\n"
                "test options are:\n\n"
                "-P, --path: Resource files directory location\n",
                argv[optind ?: 1], argv[0]);
        return 2;
    }
    return 0;
}

#endif  // __AMRNBDEC_TEST_ENVIRONMENT_H__
+175 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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 "AmrnbDecoderTest"
#define OUTPUT_FILE "/data/local/tmp/amrnbDecode.out"

#include <utils/Log.h>

#include <audio_utils/sndfile.h>
#include <stdio.h>

#include "gsmamr_dec.h"

#include "AmrnbDecTestEnvironment.h"

// Constants for AMR-NB
constexpr int32_t kInputBufferSize = 64;
constexpr int32_t kSamplesPerFrame = L_FRAME;
constexpr int32_t kBitsPerSample = 16;
constexpr int32_t kSampleRate = 8000;
constexpr int32_t kChannels = 1;
constexpr int32_t kOutputBufferSize = kSamplesPerFrame * kBitsPerSample / 8;
const int32_t kFrameSizes[] = {12, 13, 15, 17, 19, 20, 26, 31, -1, -1, -1, -1, -1, -1, -1, -1};

constexpr int32_t kNumFrameReset = 150;

static AmrnbDecTestEnvironment *gEnv = nullptr;

class AmrnbDecoderTest : public ::testing::TestWithParam<string> {
  public:
    AmrnbDecoderTest() : mFpInput(nullptr) {}

    ~AmrnbDecoderTest() {
        if (mFpInput) {
            fclose(mFpInput);
            mFpInput = nullptr;
        }
    }

    FILE *mFpInput;
    SNDFILE *openOutputFile(SF_INFO *sfInfo);
    int32_t DecodeFrames(void *amrHandle, SNDFILE *outFileHandle, int32_t frameCount = INT32_MAX);
};

SNDFILE *AmrnbDecoderTest::openOutputFile(SF_INFO *sfInfo) {
    memset(sfInfo, 0, sizeof(SF_INFO));
    sfInfo->channels = kChannels;
    sfInfo->format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
    sfInfo->samplerate = kSampleRate;
    SNDFILE *outFileHandle = sf_open(OUTPUT_FILE, SFM_WRITE, sfInfo);
    return outFileHandle;
}

int32_t AmrnbDecoderTest::DecodeFrames(void *amrHandle, SNDFILE *outFileHandle,
                                       int32_t frameCount) {
    uint8_t inputBuf[kInputBufferSize];
    int16_t outputBuf[kOutputBufferSize];

    while (frameCount > 0) {
        uint8_t mode;
        int32_t bytesRead = fread(&mode, 1, 1, mFpInput);
        if (bytesRead != 1) break;

        // Find frame type
        Frame_Type_3GPP frameType = (Frame_Type_3GPP)((mode >> 3) & 0x0f);
        int32_t frameSize = kFrameSizes[frameType];
        if (frameSize < 0) {
            ALOGE("Illegal frame type");
            return -1;
        }
        bytesRead = fread(inputBuf, 1, frameSize, mFpInput);
        if (bytesRead != frameSize) break;

        int32_t bytesDecoded = AMRDecode(amrHandle, frameType, inputBuf, outputBuf, MIME_IETF);
        if (bytesDecoded == -1) {
            ALOGE("Failed to decode the input file");
            return -1;
        }

        sf_writef_short(outFileHandle, outputBuf, kSamplesPerFrame);
        frameCount--;
    }
    return 0;
}

TEST_F(AmrnbDecoderTest, CreateAmrnbDecoderTest) {
    void *amrHandle;
    int32_t status = GSMInitDecode(&amrHandle, (Word8 *)"AMRNBDecoder");
    ASSERT_EQ(status, 0) << "Error creating AMR-NB decoder";
    GSMDecodeFrameExit(&amrHandle);
    ASSERT_EQ(amrHandle, nullptr) << "Error deleting AMR-NB decoder";
}

TEST_P(AmrnbDecoderTest, DecodeTest) {
    string inputFile = gEnv->getRes() + GetParam();
    mFpInput = fopen(inputFile.c_str(), "rb");
    ASSERT_NE(mFpInput, nullptr) << "Error opening input file " << inputFile;

    // Open the output file.
    SF_INFO sfInfo;
    SNDFILE *outFileHandle = openOutputFile(&sfInfo);
    ASSERT_NE(outFileHandle, nullptr) << "Error opening output file for writing decoded output";

    void *amrHandle;
    int32_t status = GSMInitDecode(&amrHandle, (Word8 *)"AMRNBDecoder");
    ASSERT_EQ(status, 0) << "Error creating AMR-NB decoder";

    // Decode
    int32_t decoderErr = DecodeFrames(amrHandle, outFileHandle);
    ASSERT_EQ(decoderErr, 0) << "DecodeFrames returned error";

    sf_close(outFileHandle);
    GSMDecodeFrameExit(&amrHandle);
    ASSERT_EQ(amrHandle, nullptr) << "Error deleting AMR-NB decoder";
}

TEST_P(AmrnbDecoderTest, ResetDecodeTest) {
    string inputFile = gEnv->getRes() + GetParam();
    mFpInput = fopen(inputFile.c_str(), "rb");
    ASSERT_NE(mFpInput, nullptr) << "Error opening input file " << inputFile;

    // Open the output file.
    SF_INFO sfInfo;
    SNDFILE *outFileHandle = openOutputFile(&sfInfo);
    ASSERT_NE(outFileHandle, nullptr) << "Error opening output file for writing decoded output";

    void *amrHandle;
    int32_t status = GSMInitDecode(&amrHandle, (Word8 *)"AMRNBDecoder");
    ASSERT_EQ(status, 0) << "Error creating AMR-NB decoder";

    // Decode kNumFrameReset first
    int32_t decoderErr = DecodeFrames(amrHandle, outFileHandle, kNumFrameReset);
    ASSERT_EQ(decoderErr, 0) << "DecodeFrames returned error";

    status = Speech_Decode_Frame_reset(amrHandle);
    ASSERT_EQ(status, 0) << "Error resting AMR-NB decoder";

    // Start decoding again
    decoderErr = DecodeFrames(amrHandle, outFileHandle);
    ASSERT_EQ(decoderErr, 0) << "DecodeFrames returned error";

    sf_close(outFileHandle);
    GSMDecodeFrameExit(&amrHandle);
    ASSERT_EQ(amrHandle, nullptr) << "Error deleting AMR-NB decoder";
}

INSTANTIATE_TEST_SUITE_P(AmrnbDecoderTestAll, AmrnbDecoderTest,
                         ::testing::Values(("bbb_8000hz_1ch_8kbps_amrnb_30sec.amrnb"),
                                           ("sine_amrnb_1ch_12kbps_8000hz.amrnb")));

int main(int argc, char **argv) {
    gEnv = new AmrnbDecTestEnvironment();
    ::testing::AddGlobalTestEnvironment(gEnv);
    ::testing::InitGoogleTest(&argc, argv);
    int status = gEnv->initFromOptions(argc, argv);
    if (status == 0) {
        status = RUN_ALL_TESTS();
        ALOGV("Test result = %d\n", status);
    }
    return status;
}
+48 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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.
 */

cc_test {
    name: "AmrnbDecoderTest",
    gtest: true,

    srcs: [
        "AmrnbDecoderTest.cpp",
    ],

    static_libs: [
        "libstagefright_amrnb_common",
        "libstagefright_amrnbdec",
        "libaudioutils",
        "libsndfile",
    ],

    shared_libs: [
        "liblog",
    ],

    cflags: [
        "-Werror",
        "-Wall",
    ],

    sanitize: {
        cfi: true,
        misc_undefined: [
            "unsigned-integer-overflow",
            "signed-integer-overflow",
        ],
    },
}
+34 −0
Original line number Diff line number Diff line
## Media Testing ##
---
#### AMR-NB Decoder :
The Amr-Nb Decoder Test Suite validates the amrnb decoder available in libstagefright.

Run the following steps to build the test suite:
```
m AmrnbDecoderTest
```

The 32-bit binaries will be created in the following path : ${OUT}/data/nativetest/

The 64-bit binaries will be created in the following path : ${OUT}/data/nativetest64/

To test 64-bit binary push binaries from nativetest64.
```
adb push ${OUT}/data/nativetest64/AmrnbDecoderTest/AmrnbDecoderTest /data/local/tmp/
```

To test 32-bit binary push binaries from nativetest.
```
adb push ${OUT}/data/nativetest/AmrnbDecoderTest/AmrnbDecoderTest /data/local/tmp/
```

The resource file for the tests is taken from [here](https://drive.google.com/drive/folders/13cM4tAaVFrmr-zGFqaAzFBbKs75pnm9b). Push these files into device for testing.
Download amr-nb folder and push all the files in this folder to /data/local/tmp/ on the device.
```
adb push amr-nb/. /data/local/tmp/
```

usage: AmrnbDecoderTest -P \<path_to_folder\>
```
adb shell /data/local/tmp/AmrnbDecoderTest -P /data/local/tmp/
```