blob: 2aad81bd1c6210d6520304fd6bde8fc3dc0a964a [file] [log] [blame]
/*
* 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 "AmrwbDecoderTest"
#define OUTPUT_FILE "/data/local/tmp/amrwbDecode.out"
#include <utils/Log.h>
#include <audio_utils/sndfile.h>
#include <stdio.h>
#include "pvamrwbdecoder.h"
#include "pvamrwbdecoder_api.h"
#include "AmrwbDecTestEnvironment.h"
// Constants for AMR-WB.
constexpr int32_t kInputBufferSize = 64;
constexpr int32_t kSamplesPerFrame = 320;
constexpr int32_t kBitsPerSample = 16;
constexpr int32_t kSampleRate = 16000;
constexpr int32_t kChannels = 1;
constexpr int32_t kMaxSourceDataUnitSize = KAMRWB_NB_BITS_MAX * sizeof(int16_t);
constexpr int32_t kOutputBufferSize = kSamplesPerFrame * kBitsPerSample / 8;
const int32_t kFrameSizes[16] = {17, 23, 32, 36, 40, 46, 50, 58, 60, -1, -1, -1, -1, -1, -1, -1};
constexpr int32_t kNumFrameReset = 150;
constexpr int32_t kMaxCount = 10;
static AmrwbDecTestEnvironment *gEnv = nullptr;
class AmrwbDecoderTest : public ::testing::TestWithParam<string> {
public:
AmrwbDecoderTest() : mFpInput(nullptr) {}
~AmrwbDecoderTest() {
if (mFpInput) {
fclose(mFpInput);
mFpInput = nullptr;
}
}
FILE *mFpInput;
int32_t DecodeFrames(int16_t *decoderCookie, void *decoderBuf, SNDFILE *outFileHandle,
int32_t frameCount = INT32_MAX);
SNDFILE *openOutputFile(SF_INFO *sfInfo);
};
SNDFILE *AmrwbDecoderTest::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 AmrwbDecoderTest::DecodeFrames(int16_t *decoderCookie, void *decoderBuf,
SNDFILE *outFileHandle, int32_t frameCount) {
uint8_t inputBuf[kInputBufferSize];
int16_t inputSampleBuf[kMaxSourceDataUnitSize];
int16_t outputBuf[kOutputBufferSize];
while (frameCount > 0) {
uint8_t modeByte;
int32_t bytesRead = fread(&modeByte, 1, 1, mFpInput);
if (bytesRead != 1) break;
int16 mode = ((modeByte >> 3) & 0x0f);
if (mode >= 9) {
// Produce silence for comfort noise, speech lost and no data.
int32_t outputBufferSize = kSamplesPerFrame * kBitsPerSample / 8;
memset(outputBuf, 0, outputBufferSize);
} else {
// Read rest of the frame.
int32_t frameSize = kFrameSizes[mode];
// AMR-WB file format cannot have mode 10, 11, 12 and 13.
if (frameSize < 0) {
ALOGE("Illegal frame mode");
return -1;
}
bytesRead = fread(inputBuf, 1, frameSize, mFpInput);
if (bytesRead != frameSize) break;
int16 frameMode = mode;
int16 frameType;
RX_State_wb rx_state;
mime_unsorting(inputBuf, inputSampleBuf, &frameType, &frameMode, 1, &rx_state);
int16_t numSamplesOutput;
pvDecoder_AmrWb(frameMode, inputSampleBuf, outputBuf, &numSamplesOutput, decoderBuf,
frameType, decoderCookie);
if (numSamplesOutput != kSamplesPerFrame) {
ALOGE("Failed to decode the input file");
return -1;
}
for (int count = 0; count < kSamplesPerFrame; ++count) {
/* Delete the 2 LSBs (14-bit output) */
outputBuf[count] &= 0xfffc;
}
}
sf_writef_short(outFileHandle, outputBuf, kSamplesPerFrame / kChannels);
frameCount--;
}
return 0;
}
TEST_F(AmrwbDecoderTest, MultiCreateAmrwbDecoderTest) {
uint32_t memRequirements = pvDecoder_AmrWbMemRequirements();
void *decoderBuf = malloc(memRequirements);
ASSERT_NE(decoderBuf, nullptr)
<< "Failed to allocate decoder memory of size " << memRequirements;
// Create AMR-WB decoder instance.
void *amrHandle = nullptr;
int16_t *decoderCookie;
for (int count = 0; count < kMaxCount; count++) {
pvDecoder_AmrWb_Init(&amrHandle, decoderBuf, &decoderCookie);
ASSERT_NE(amrHandle, nullptr) << "Failed to initialize decoder";
ALOGV("Decoder created successfully");
}
if (decoderBuf) {
free(decoderBuf);
decoderBuf = nullptr;
}
}
TEST_P(AmrwbDecoderTest, DecodeTest) {
uint32_t memRequirements = pvDecoder_AmrWbMemRequirements();
void *decoderBuf = malloc(memRequirements);
ASSERT_NE(decoderBuf, nullptr)
<< "Failed to allocate decoder memory of size " << memRequirements;
void *amrHandle = nullptr;
int16_t *decoderCookie;
pvDecoder_AmrWb_Init(&amrHandle, decoderBuf, &decoderCookie);
ASSERT_NE(amrHandle, nullptr) << "Failed to initialize decoder";
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";
int32_t decoderErr = DecodeFrames(decoderCookie, decoderBuf, outFileHandle);
ASSERT_EQ(decoderErr, 0) << "DecodeFrames returned error";
sf_close(outFileHandle);
if (decoderBuf) {
free(decoderBuf);
decoderBuf = nullptr;
}
}
TEST_P(AmrwbDecoderTest, ResetDecoderTest) {
uint32_t memRequirements = pvDecoder_AmrWbMemRequirements();
void *decoderBuf = malloc(memRequirements);
ASSERT_NE(decoderBuf, nullptr)
<< "Failed to allocate decoder memory of size " << memRequirements;
void *amrHandle = nullptr;
int16_t *decoderCookie;
pvDecoder_AmrWb_Init(&amrHandle, decoderBuf, &decoderCookie);
ASSERT_NE(amrHandle, nullptr) << "Failed to initialize decoder";
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";
// Decode 150 frames first
int32_t decoderErr = DecodeFrames(decoderCookie, decoderBuf, outFileHandle, kNumFrameReset);
ASSERT_EQ(decoderErr, 0) << "DecodeFrames returned error";
// Reset Decoder
pvDecoder_AmrWb_Reset(decoderBuf, 1);
// Start decoding again
decoderErr = DecodeFrames(decoderCookie, decoderBuf, outFileHandle);
ASSERT_EQ(decoderErr, 0) << "DecodeFrames returned error";
sf_close(outFileHandle);
if (decoderBuf) {
free(decoderBuf);
}
}
INSTANTIATE_TEST_SUITE_P(AmrwbDecoderTestAll, AmrwbDecoderTest,
::testing::Values(("bbb_amrwb_1ch_14kbps_16000hz.amrwb"),
("bbb_16000hz_1ch_9kbps_amrwb_30sec.amrwb")));
int main(int argc, char **argv) {
gEnv = new AmrwbDecTestEnvironment();
::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;
}