commit
ee90235611
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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 __AMRWBDEC_TEST_ENVIRONMENT_H__
|
||||
#define __AMRWBDEC_TEST_ENVIRONMENT_H__
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <getopt.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class AmrwbDecTestEnvironment : public ::testing::Environment {
|
||||
public:
|
||||
AmrwbDecTestEnvironment() : 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 AmrwbDecTestEnvironment::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 // __AMRWBDEC_TEST_ENVIRONMENT_H__
|
@ -0,0 +1,223 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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: "AmrwbDecoderTest",
|
||||
gtest: true,
|
||||
|
||||
srcs: [
|
||||
"AmrwbDecoderTest.cpp",
|
||||
],
|
||||
|
||||
static_libs: [
|
||||
"libstagefright_amrwbdec",
|
||||
"libsndfile",
|
||||
"libaudioutils",
|
||||
],
|
||||
|
||||
shared_libs: [
|
||||
"liblog",
|
||||
],
|
||||
|
||||
cflags: [
|
||||
"-Werror",
|
||||
"-Wall",
|
||||
],
|
||||
|
||||
sanitize: {
|
||||
cfi: true,
|
||||
misc_undefined: [
|
||||
"unsigned-integer-overflow",
|
||||
"signed-integer-overflow",
|
||||
],
|
||||
},
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
## Media Testing ##
|
||||
---
|
||||
#### AMR-WB Decoder :
|
||||
The Amr-Wb Decoder Test Suite validates the amrwb decoder available in libstagefright.
|
||||
|
||||
Run the following steps to build the test suite:
|
||||
```
|
||||
m AmrwbDecoderTest
|
||||
```
|
||||
|
||||
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/AmrwbDecoderTest/AmrwbDecoderTest /data/local/tmp/
|
||||
```
|
||||
|
||||
To test 32-bit binary push binaries from nativetest.
|
||||
```
|
||||
adb push ${OUT}/data/nativetest/AmrwbDecoderTest/AmrwbDecoderTest /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-wb folder and push all the files in this folder to /data/local/tmp/ on the device.
|
||||
```
|
||||
adb push amr-wb/. /data/local/tmp/
|
||||
```
|
||||
|
||||
usage: AmrwbDecoderTest -P \<path_to_folder\>
|
||||
```
|
||||
adb shell /data/local/tmp/AmrwbDecoderTest -P /data/local/tmp/
|
||||
```
|
Loading…
Reference in new issue