Benchmark: add Decoder

Test: decoderTest --gtest_repeat=10 -P /sdcard/res/

Bug: 140051680
Change-Id: I853ab5b08a3dfc866470ef727dfdf4763322e598
gugelfrei
Manisha Jajoo 5 years ago
parent bac928872a
commit 90f569ac48

@ -28,3 +28,13 @@ The path to these files on the device is required to be given for the test.
```
adb shell /data/local/tmp/extractorTest -P /sdcard/res/
```
## Decoder
The test decodes input stream and benchmarks the decoders available in NDK.
Setup steps are same as extractor.
```
adb shell /data/local/tmp/decoderTest -P /sdcard/res/
```

@ -22,6 +22,7 @@ cc_library_static {
],
srcs: [
"BenchmarkCommon.cpp",
"Timer.cpp",
],

@ -0,0 +1,102 @@
/*
* 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 "BenchmarkCommon"
#include "BenchmarkCommon.h"
#include <iostream>
void CallBackHandle::ioThread() {
ALOGV("In %s mIsDone : %d, mSawError : %d ", __func__, mIsDone, mSawError);
while (!mIsDone && !mSawError) {
auto task = mIOQueue.pop();
task();
}
}
void OnInputAvailableCB(AMediaCodec *codec, void *userdata, int32_t index) {
ALOGV("OnInputAvailableCB: index(%d)", index);
CallBackHandle *self = (CallBackHandle *)userdata;
self->getTimer()->addInputTime();
self->mIOQueue.push([self, codec, index]() { self->onInputAvailable(codec, index); });
}
void OnOutputAvailableCB(AMediaCodec *codec, void *userdata, int32_t index,
AMediaCodecBufferInfo *bufferInfo) {
ALOGV("OnOutputAvailableCB: index(%d), (%d, %d, %lld, 0x%x)", index, bufferInfo->offset,
bufferInfo->size, (long long)bufferInfo->presentationTimeUs, bufferInfo->flags);
CallBackHandle *self = (CallBackHandle *)userdata;
self->getTimer()->addOutputTime();
AMediaCodecBufferInfo bufferInfoCopy = *bufferInfo;
self->mIOQueue.push([self, codec, index, bufferInfoCopy]() {
AMediaCodecBufferInfo bc = bufferInfoCopy;
self->onOutputAvailable(codec, index, &bc);
});
}
void OnFormatChangedCB(AMediaCodec *codec, void *userdata, AMediaFormat *format) {
ALOGV("OnFormatChangedCB: format(%s)", AMediaFormat_toString(format));
CallBackHandle *self = (CallBackHandle *)userdata;
self->mIOQueue.push([self, codec, format]() { self->onFormatChanged(codec, format); });
}
void OnErrorCB(AMediaCodec *codec, void *userdata, media_status_t err, int32_t actionCode,
const char *detail) {
(void)codec;
ALOGV("OnErrorCB: err(%d), actionCode(%d), detail(%s)", err, actionCode, detail);
CallBackHandle *self = (CallBackHandle *)userdata;
self->mSawError = true;
}
AMediaCodec *createMediaCodec(AMediaFormat *format, const char *mime, string codecName,
bool isEncoder) {
ALOGV("In %s", __func__);
if (!mime) {
ALOGE("Please specify a mime type to create codec");
return nullptr;
}
AMediaCodec *codec;
if (!codecName.empty()) {
codec = AMediaCodec_createCodecByName(codecName.c_str());
if (!codec) {
ALOGE("Unable to create codec by name: %s", codecName.c_str());
return nullptr;
}
} else {
if (isEncoder) {
codec = AMediaCodec_createEncoderByType(mime);
} else {
codec = AMediaCodec_createDecoderByType(mime);
}
if (!codec) {
ALOGE("Unable to create codec by mime: %s", mime);
return nullptr;
}
}
/* Configure codec with the given format*/
const char *s = AMediaFormat_toString(format);
ALOGV("Input format: %s\n", s);
media_status_t status = AMediaCodec_configure(codec, format, nullptr, nullptr, isEncoder);
if (status != AMEDIA_OK) {
ALOGE("AMediaCodec_configure failed %d", status);
return nullptr;
}
return codec;
}

@ -19,11 +19,107 @@
#include <utils/Log.h>
#include <inttypes.h>
#include <mutex>
#include <queue>
#include <thread>
#include <media/NdkMediaCodec.h>
#include <media/NdkMediaError.h>
#include "Timer.h"
using namespace std;
constexpr uint32_t kQueueDequeueTimeoutUs = 1000;
constexpr uint32_t kMaxCSDStrlen = 16;
constexpr uint32_t kMaxBufferSize = 1024 * 1024 * 16;
template <typename T>
class CallBackQueue {
public:
CallBackQueue() {}
~CallBackQueue() {}
void push(T elem) {
bool needsNotify = false;
{
lock_guard<mutex> lock(mMutex);
needsNotify = mQueue.empty();
mQueue.push(move(elem));
}
if (needsNotify) mQueueNotEmptyCondition.notify_one();
}
T pop() {
unique_lock<mutex> lock(mMutex);
if (mQueue.empty()) {
mQueueNotEmptyCondition.wait(lock, [this]() { return !mQueue.empty(); });
}
auto result = mQueue.front();
mQueue.pop();
return result;
}
private:
mutex mMutex;
queue<T> mQueue;
condition_variable mQueueNotEmptyCondition;
};
class CallBackHandle {
public:
CallBackHandle() : mSawError(false), mIsDone(false), mTimer(nullptr) {}
virtual ~CallBackHandle() {
if (mIOThread.joinable()) mIOThread.join();
if (mTimer) delete mTimer;
}
void ioThread();
// Implementation in child class (Decoder/Encoder)
virtual void onInputAvailable(AMediaCodec *codec, int32_t index) {
(void)codec;
(void)index;
}
virtual void onFormatChanged(AMediaCodec *codec, AMediaFormat *format) {
(void)codec;
(void)format;
}
virtual void onOutputAvailable(AMediaCodec *codec, int32_t index,
AMediaCodecBufferInfo *bufferInfo) {
(void)codec;
(void)index;
(void)bufferInfo;
}
virtual Timer *getTimer() { return mTimer; }
// Keep a queue of all function callbacks.
typedef function<void()> IOTask;
CallBackQueue<IOTask> mIOQueue;
thread mIOThread;
bool mSawError;
bool mIsDone;
private:
Timer *mTimer;
};
// Async API's callback
void OnInputAvailableCB(AMediaCodec *codec, void *userdata, int32_t index);
void OnOutputAvailableCB(AMediaCodec *codec, void *userdata, int32_t index,
AMediaCodecBufferInfo *bufferInfo);
void OnFormatChangedCB(AMediaCodec *codec, void *userdata, AMediaFormat *format);
void OnErrorCB(AMediaCodec *codec, void * /* userdata */, media_status_t err, int32_t actionCode,
const char *detail);
// Utility to create and configure AMediaCodec
AMediaCodec *createMediaCodec(AMediaFormat *format, const char *mime, string codecName,
bool isEncoder);
#endif // __BENCHMARK_COMMON_H__

@ -0,0 +1,31 @@
/*
* 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_library_static {
name: "libbenchmark_decoder",
defaults: [
"libbenchmark_common-defaults",
"libbenchmark_soft_sanitize_all-defaults",
],
srcs: ["Decoder.cpp"],
static_libs: ["libbenchmark_extractor"],
export_include_dirs: ["."],
ldflags: ["-Wl,-Bsymbolic"]
}

@ -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 "decoder"
#include <iostream>
#include "Decoder.h"
tuple<ssize_t, uint32_t, int64_t> readSampleData(uint8_t *inputBuffer, int32_t &offset,
vector<AMediaCodecBufferInfo> &frameInfo,
uint8_t *buf, int32_t frameID, size_t bufSize) {
ALOGV("In %s", __func__);
if (frameID == (int32_t)frameInfo.size()) {
return make_tuple(0, AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM, 0);
}
uint32_t flags = frameInfo[frameID].flags;
int64_t timestamp = frameInfo[frameID].presentationTimeUs;
ssize_t bytesCount = frameInfo[frameID].size;
if (bufSize < bytesCount) {
ALOGE("Error : insufficient resource");
return make_tuple(0, AMEDIACODEC_ERROR_INSUFFICIENT_RESOURCE, 0);
}
memcpy(buf, inputBuffer + offset, bytesCount);
offset += bytesCount;
return make_tuple(bytesCount, flags, timestamp);
}
void Decoder::onInputAvailable(AMediaCodec *mediaCodec, int32_t bufIdx) {
ALOGV("In %s", __func__);
if (mediaCodec == mCodec && mediaCodec) {
if (mSawInputEOS || bufIdx < 0) return;
if (mSignalledError) {
CallBackHandle::mSawError = true;
mDecoderDoneCondition.notify_one();
return;
}
size_t bufSize;
uint8_t *buf = AMediaCodec_getInputBuffer(mCodec, bufIdx, &bufSize);
if (!buf) {
mSignalledError = true;
mDecoderDoneCondition.notify_one();
return;
}
ssize_t bytesRead = 0;
uint32_t flag = 0;
int64_t presentationTimeUs = 0;
tie(bytesRead, flag, presentationTimeUs) = readSampleData(
mInputBuffer, mOffset, mFrameMetaData, buf, mNumInputFrame, bufSize);
if (flag == AMEDIACODEC_ERROR_INSUFFICIENT_RESOURCE) {
mSignalledError = true;
mDecoderDoneCondition.notify_one();
return;
}
if (flag == AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) mSawInputEOS = true;
ALOGV("%s bytesRead : %zd presentationTimeUs : %" PRId64 " mSawInputEOS : %s", __FUNCTION__,
bytesRead, presentationTimeUs, mSawInputEOS ? "TRUE" : "FALSE");
int status = AMediaCodec_queueInputBuffer(mCodec, bufIdx, 0 /* offset */, bytesRead,
presentationTimeUs, flag);
if (AMEDIA_OK != status) {
mSignalledError = true;
mDecoderDoneCondition.notify_one();
return;
}
mNumInputFrame++;
}
}
void Decoder::onOutputAvailable(AMediaCodec *mediaCodec, int32_t bufIdx,
AMediaCodecBufferInfo *bufferInfo) {
ALOGV("In %s", __func__);
if (mediaCodec == mCodec && mediaCodec) {
if (mSawOutputEOS || bufIdx < 0) return;
if (mSignalledError) {
CallBackHandle::mSawError = true;
mDecoderDoneCondition.notify_one();
return;
}
AMediaCodec_releaseOutputBuffer(mCodec, bufIdx, false);
mSawOutputEOS = (0 != (bufferInfo->flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM));
mNumOutputFrame++;
ALOGV("%s index : %d mSawOutputEOS : %s count : %u", __FUNCTION__, bufIdx,
mSawOutputEOS ? "TRUE" : "FALSE", mNumOutputFrame);
if (mSawOutputEOS) {
CallBackHandle::mIsDone = true;
mDecoderDoneCondition.notify_one();
}
}
}
void Decoder::onFormatChanged(AMediaCodec *mediaCodec, AMediaFormat *format) {
ALOGV("In %s", __func__);
if (mediaCodec == mCodec && mediaCodec) {
ALOGV("%s { %s }", __FUNCTION__, AMediaFormat_toString(format));
mFormat = format;
}
}
void Decoder::setupDecoder() {
if (!mFormat) mFormat = mExtractor->getFormat();
if (!mTimer) mTimer = new Timer();
}
int32_t Decoder::decode(uint8_t *inputBuffer, vector<AMediaCodecBufferInfo> &frameInfo,
string &codecName, bool asyncMode) {
ALOGV("In %s", __func__);
mInputBuffer = inputBuffer;
mFrameMetaData = frameInfo;
mOffset = 0;
const char *mime = nullptr;
AMediaFormat_getString(mFormat, AMEDIAFORMAT_KEY_MIME, &mime);
if (!mime) return AMEDIA_ERROR_INVALID_OBJECT;
int64_t sTime = mTimer->getCurTime();
mCodec = createMediaCodec(mFormat, mime, codecName, false /*isEncoder*/);
if (!mCodec) return AMEDIA_ERROR_INVALID_OBJECT;
if (asyncMode) {
AMediaCodecOnAsyncNotifyCallback aCB = {OnInputAvailableCB, OnOutputAvailableCB,
OnFormatChangedCB, OnErrorCB};
AMediaCodec_setAsyncNotifyCallback(mCodec, aCB, this);
CallBackHandle *callbackHandle = new CallBackHandle();
callbackHandle->mIOThread = thread(&CallBackHandle::ioThread, this);
}
AMediaCodec_start(mCodec);
int64_t eTime = mTimer->getCurTime();
int64_t timeTaken = mTimer->getTimeDiff(sTime, eTime);
mTimer->setInitTime(timeTaken);
mTimer->setStartTime();
if (!asyncMode) {
while (!mSawOutputEOS && !mSignalledError) {
/* Queue input data */
if (!mSawInputEOS) {
ssize_t inIdx = AMediaCodec_dequeueInputBuffer(mCodec, kQueueDequeueTimeoutUs);
if (inIdx < 0 && inIdx != AMEDIACODEC_INFO_TRY_AGAIN_LATER) {
ALOGE("AMediaCodec_dequeueInputBuffer returned invalid index %zd\n", inIdx);
return AMEDIA_ERROR_IO;
} else if (inIdx >= 0) {
mTimer->addInputTime();
onInputAvailable(mCodec, inIdx);
}
}
/* Dequeue output data */
AMediaCodecBufferInfo info;
ssize_t outIdx = AMediaCodec_dequeueOutputBuffer(mCodec, &info, kQueueDequeueTimeoutUs);
if (outIdx == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED) {
mFormat = AMediaCodec_getOutputFormat(mCodec);
const char *s = AMediaFormat_toString(mFormat);
ALOGI("Output format: %s\n", s);
} else if (outIdx >= 0) {
mTimer->addOutputTime();
onOutputAvailable(mCodec, outIdx, &info);
} else if (!(outIdx == AMEDIACODEC_INFO_TRY_AGAIN_LATER ||
outIdx == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED)) {
ALOGE("AMediaCodec_dequeueOutputBuffer returned invalid index %zd\n", outIdx);
return AMEDIA_ERROR_IO;
}
}
} else {
unique_lock<mutex> lock(mMutex);
mDecoderDoneCondition.wait(lock, [this]() { return (mSawOutputEOS || mSignalledError); });
}
if (codecName.empty()) {
char *decName;
AMediaCodec_getName(mCodec, &decName);
codecName.assign(decName);
AMediaCodec_releaseName(mCodec, decName);
}
return AMEDIA_OK;
}
void Decoder::deInitCodec() {
int64_t sTime = mTimer->getCurTime();
if (mFormat) {
AMediaFormat_delete(mFormat);
mFormat = nullptr;
}
if (!mCodec) return;
AMediaCodec_stop(mCodec);
AMediaCodec_delete(mCodec);
int64_t eTime = mTimer->getCurTime();
int64_t timeTaken = mTimer->getTimeDiff(sTime, eTime);
mTimer->setDeInitTime(timeTaken);
}
void Decoder::dumpStatistics(string inputReference) {
int64_t durationUs = mExtractor->getClipDuration();
string operation = "decode";
mTimer->dumpStatistics(operation, inputReference, durationUs);
}
void Decoder::resetDecoder() {
if (mTimer) mTimer->resetTimers();
if (mInputBuffer) mInputBuffer = nullptr;
if (!mFrameMetaData.empty()) mFrameMetaData.clear();
}

@ -0,0 +1,105 @@
/*
* 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 __DECODER_H__
#define __DECODER_H__
#include <chrono>
#include <condition_variable>
#include <mutex>
#include <queue>
#include <thread>
#include "BenchmarkCommon.h"
#include "Extractor.h"
#include "Timer.h"
class Decoder : public CallBackHandle {
public:
Decoder()
: mCodec(nullptr),
mFormat(nullptr),
mExtractor(nullptr),
mTimer(nullptr),
mNumInputFrame(0),
mNumOutputFrame(0),
mSawInputEOS(false),
mSawOutputEOS(false),
mSignalledError(false),
mInputBuffer(nullptr) {
mExtractor = new Extractor();
}
virtual ~Decoder() {
if (mTimer) delete mTimer;
if (mExtractor) delete mExtractor;
}
Timer *getTimer() override { return mTimer; }
Extractor *getExtractor() { return mExtractor; }
// Decoder related utilities
void setupDecoder();
void deInitCodec();
void resetDecoder();
// Async callback APIs
void onInputAvailable(AMediaCodec *codec, int32_t index) override;
void onFormatChanged(AMediaCodec *codec, AMediaFormat *format) override;
void onOutputAvailable(AMediaCodec *codec, int32_t index,
AMediaCodecBufferInfo *bufferInfo) override;
// Process the frames and give decoded output
int32_t decode(uint8_t *inputBuffer, vector<AMediaCodecBufferInfo> &frameInfo,
string &codecName, bool asyncMode);
void dumpStatistics(string inputReference);
private:
AMediaCodec *mCodec;
AMediaFormat *mFormat;
Extractor *mExtractor;
Timer *mTimer;
int32_t mNumInputFrame;
int32_t mNumOutputFrame;
bool mSawInputEOS;
bool mSawOutputEOS;
bool mSignalledError;
int32_t mOffset;
uint8_t *mInputBuffer;
vector<AMediaCodecBufferInfo> mFrameMetaData;
/* Asynchronous locks */
mutex mMutex;
condition_variable mDecoderDoneCondition;
};
// Read input samples
tuple<ssize_t, uint32_t, int64_t> readSampleData(uint8_t *inputBuffer, int32_t &offset,
vector<AMediaCodecBufferInfo> &frameSizes,
uint8_t *buf, int32_t frameID, size_t bufSize);
#endif // __DECODER_H__

@ -26,3 +26,19 @@ cc_test {
static_libs: ["libbenchmark_extractor"]
}
cc_test {
name: "decoderTest",
gtest: true,
defaults: [
"libbenchmark_common-defaults",
"libbenchmark_soft_sanitize_all-defaults",
],
srcs: ["DecoderTest.cpp"],
static_libs: [
"libbenchmark_extractor",
"libbenchmark_decoder",
],
}

@ -0,0 +1,217 @@
/*
* 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 "decoderTest"
#include <fstream>
#include <iostream>
#include <limits>
#include "Decoder.h"
#include "BenchmarkTestEnvironment.h"
static BenchmarkTestEnvironment *gEnv = nullptr;
class DecoderTest : public ::testing::TestWithParam<tuple<string, string, bool>> {};
TEST_P(DecoderTest, Decode) {
ALOGV("Decode the samples given by extractor");
tuple<string /* InputFile */, string /* CodecName */, bool /* asyncMode */> params = GetParam();
string inputFile = gEnv->getRes() + get<0>(params);
FILE *inputFp = fopen(inputFile.c_str(), "rb");
if (!inputFp) {
cout << "[ WARN ] Test Skipped. Unable to open input file for reading \n";
return;
}
Decoder *decoder = new Decoder();
Extractor *extractor = decoder->getExtractor();
if (!extractor) {
cout << "[ WARN ] Test Skipped. Extractor creation failed \n";
return;
}
// Read file properties
fseek(inputFp, 0, SEEK_END);
size_t fileSize = ftell(inputFp);
fseek(inputFp, 0, SEEK_SET);
int32_t fd = fileno(inputFp);
int32_t trackCount = extractor->initExtractor(fd, fileSize);
if (trackCount <= 0) {
cout << "[ WARN ] Test Skipped. initExtractor failed\n";
return;
}
for (int curTrack = 0; curTrack < trackCount; curTrack++) {
int32_t status = extractor->setupTrackFormat(curTrack);
if (status != 0) {
cout << "[ WARN ] Test Skipped. Track Format invalid \n";
return;
}
uint8_t *inputBuffer = (uint8_t *)malloc(kMaxBufferSize);
if (!inputBuffer) {
cout << "[ WARN ] Test Skipped. Insufficient memory \n";
return;
}
vector<AMediaCodecBufferInfo> frameInfo;
AMediaCodecBufferInfo info;
uint32_t inputBufferOffset = 0;
int32_t idx = 0;
// Get CSD data
while (1) {
void *csdBuffer = extractor->getCSDSample(info, idx);
if (!csdBuffer || !info.size) break;
// copy the meta data and buffer to be passed to decoder
if (inputBufferOffset + info.size > kMaxBufferSize) {
cout << "[ WARN ] Test Skipped. Memory allocated not sufficient\n";
free(inputBuffer);
return;
}
memcpy(inputBuffer + inputBufferOffset, csdBuffer, info.size);
frameInfo.push_back(info);
inputBufferOffset += info.size;
idx++;
}
// Get frame data
while (1) {
status = extractor->getFrameSample(info);
if (status || !info.size) break;
// copy the meta data and buffer to be passed to decoder
if (inputBufferOffset + info.size > kMaxBufferSize) {
cout << "[ WARN ] Test Skipped. Memory allocated not sufficient\n";
free(inputBuffer);
return;
}
memcpy(inputBuffer + inputBufferOffset, extractor->getFrameBuf(), info.size);
frameInfo.push_back(info);
inputBufferOffset += info.size;
}
string codecName = get<1>(params);
bool asyncMode = get<2>(params);
decoder->setupDecoder();
status = decoder->decode(inputBuffer, frameInfo, codecName, asyncMode);
if (status != AMEDIA_OK) {
cout << "[ WARN ] Test Skipped. Decode returned error \n";
free(inputBuffer);
return;
}
decoder->deInitCodec();
cout << "codec : " << codecName << endl;
string inputReference = get<0>(params);
decoder->dumpStatistics(inputReference);
free(inputBuffer);
decoder->resetDecoder();
}
fclose(inputFp);
extractor->deInitExtractor();
delete decoder;
}
// TODO: (b/140549596)
// Add wav files
INSTANTIATE_TEST_SUITE_P(
AudioDecoderSyncTest, DecoderTest,
::testing::Values(make_tuple("bbb_44100hz_2ch_128kbps_aac_30sec.mp4", "", false),
make_tuple("bbb_44100hz_2ch_128kbps_mp3_30sec.mp3", "", false),
make_tuple("bbb_8000hz_1ch_8kbps_amrnb_30sec.3gp", "", false),
make_tuple("bbb_16000hz_1ch_9kbps_amrwb_30sec.3gp", "", false),
make_tuple("bbb_44100hz_2ch_80kbps_vorbis_30sec.mp4", "", false),
make_tuple("bbb_48000hz_2ch_100kbps_opus_30sec.webm", "", false)));
INSTANTIATE_TEST_SUITE_P(
AudioDecoderAsyncTest, DecoderTest,
::testing::Values(make_tuple("bbb_44100hz_2ch_128kbps_aac_30sec.mp4", "", true),
make_tuple("bbb_44100hz_2ch_128kbps_mp3_30sec.mp3", "", true),
make_tuple("bbb_8000hz_1ch_8kbps_amrnb_30sec.3gp", "", true),
make_tuple("bbb_16000hz_1ch_9kbps_amrwb_30sec.3gp", "", true),
make_tuple("bbb_44100hz_2ch_80kbps_vorbis_30sec.mp4", "", true),
make_tuple("bbb_48000hz_2ch_100kbps_opus_30sec.webm", "", true)));
INSTANTIATE_TEST_SUITE_P(VideDecoderSyncTest, DecoderTest,
::testing::Values(
// Hardware codecs
make_tuple("crowd_1920x1080_25fps_4000kbps_vp9.webm", "", false),
make_tuple("crowd_1920x1080_25fps_4000kbps_vp8.webm", "", false),
make_tuple("crowd_1920x1080_25fps_4000kbps_av1.webm", "", false),
make_tuple("crowd_1920x1080_25fps_7300kbps_mpeg2.mp4", "", false),
make_tuple("crowd_1920x1080_25fps_6000kbps_mpeg4.mp4", "", false),
make_tuple("crowd_352x288_25fps_6000kbps_h263.3gp", "", false),
make_tuple("crowd_1920x1080_25fps_6700kbps_h264.ts", "", false),
make_tuple("crowd_1920x1080_25fps_4000kbps_h265.mkv", "", false),
// Software codecs
make_tuple("crowd_1920x1080_25fps_4000kbps_vp9.webm",
"c2.android.vp9.decoder", false),
make_tuple("crowd_1920x1080_25fps_4000kbps_vp8.webm",
"c2.android.vp8.decoder", false),
make_tuple("crowd_1920x1080_25fps_4000kbps_av1.webm",
"c2.android.av1.decoder", false),
make_tuple("crowd_1920x1080_25fps_7300kbps_mpeg2.mp4",
"c2.android.mpeg2.decoder", false),
make_tuple("crowd_1920x1080_25fps_6000kbps_mpeg4.mp4",
"c2.android.mpeg4.decoder", false),
make_tuple("crowd_352x288_25fps_6000kbps_h263.3gp",
"c2.android.h263.decoder", false),
make_tuple("crowd_1920x1080_25fps_6700kbps_h264.ts",
"c2.android.avc.decoder", false),
make_tuple("crowd_1920x1080_25fps_4000kbps_h265.mkv",
"c2.android.hevc.decoder", false)));
INSTANTIATE_TEST_SUITE_P(VideoDecoderAsyncTest, DecoderTest,
::testing::Values(
// Hardware codecs
make_tuple("crowd_1920x1080_25fps_4000kbps_vp9.webm", "", true),
make_tuple("crowd_1920x1080_25fps_4000kbps_vp8.webm", "", true),
make_tuple("crowd_1920x1080_25fps_4000kbps_av1.webm", "", true),
make_tuple("crowd_1920x1080_25fps_7300kbps_mpeg2.mp4", "", true),
make_tuple("crowd_1920x1080_25fps_6000kbps_mpeg4.mp4", "", true),
make_tuple("crowd_352x288_25fps_6000kbps_h263.3gp", "", true),
make_tuple("crowd_1920x1080_25fps_6700kbps_h264.ts", "", true),
make_tuple("crowd_1920x1080_25fps_4000kbps_h265.mkv", "", true),
// Software codecs
make_tuple("crowd_1920x1080_25fps_4000kbps_vp9.webm",
"c2.android.vp9.decoder", true),
make_tuple("crowd_1920x1080_25fps_4000kbps_vp8.webm",
"c2.android.vp8.decoder", true),
make_tuple("crowd_1920x1080_25fps_4000kbps_av1.webm",
"c2.android.av1.decoder", true),
make_tuple("crowd_1920x1080_25fps_7300kbps_mpeg2.mp4",
"c2.android.mpeg2.decoder", true),
make_tuple("crowd_1920x1080_25fps_6000kbps_mpeg4.mp4",
"c2.android.mpeg4.decoder", true),
make_tuple("crowd_352x288_25fps_6000kbps_h263.3gp",
"c2.android.h263.decoder", true),
make_tuple("crowd_1920x1080_25fps_6700kbps_h264.ts",
"c2.android.avc.decoder", true),
make_tuple("crowd_1920x1080_25fps_4000kbps_h265.mkv",
"c2.android.hevc.decoder", true)));
int main(int argc, char **argv) {
gEnv = new BenchmarkTestEnvironment();
::testing::AddGlobalTestEnvironment(gEnv);
::testing::InitGoogleTest(&argc, argv);
int status = gEnv->initFromOptions(argc, argv);
if (status == 0) {
status = RUN_ALL_TESTS();
ALOGD("Decoder Test result = %d\n", status);
}
return status;
}
Loading…
Cancel
Save