am: 71a763b475
Change-Id: Ib92f255469b657f5e2fc4e819dae04bc9226445a
gugelfrei
commit
f4021f5772
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* 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 "BenchmarkC2Common"
|
||||
|
||||
#include "BenchmarkC2Common.h"
|
||||
|
||||
int32_t BenchmarkC2Common::setupCodec2() {
|
||||
ALOGV("In %s", __func__);
|
||||
mClient = android::Codec2Client::CreateFromService("default");
|
||||
if (!mClient) return -1;
|
||||
|
||||
std::shared_ptr<C2AllocatorStore> store = android::GetCodec2PlatformAllocatorStore();
|
||||
if (!store) return -1;
|
||||
|
||||
c2_status_t status = store->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &mLinearAllocator);
|
||||
if (status != C2_OK) return status;
|
||||
|
||||
mLinearPool = std::make_shared<C2PooledBlockPool>(mLinearAllocator, mBlockPoolId++);
|
||||
if (!mLinearPool) return -1;
|
||||
|
||||
status = store->fetchAllocator(C2AllocatorStore::DEFAULT_GRAPHIC, &mGraphicAllocator);
|
||||
if (status != C2_OK) return status;
|
||||
|
||||
mGraphicPool = std::make_shared<C2PooledBlockPool>(mGraphicAllocator, mBlockPoolId++);
|
||||
if (!mGraphicPool) return -1;
|
||||
|
||||
for (int i = 0; i < MAX_INPUT_BUFFERS; ++i) {
|
||||
mWorkQueue.emplace_back(new C2Work);
|
||||
}
|
||||
if (!mStats) mStats = new Stats();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
vector<string> BenchmarkC2Common::getSupportedComponentList(bool isEncoder) {
|
||||
// Get List of components from all known services
|
||||
vector<string> codecList;
|
||||
const std::vector<C2Component::Traits> listTraits = mClient->ListComponents();
|
||||
if (listTraits.size() == 0)
|
||||
ALOGE("ComponentInfo list empty.");
|
||||
else {
|
||||
for (size_t i = 0; i < listTraits.size(); i++) {
|
||||
if (isEncoder && C2Component::KIND_ENCODER == listTraits[i].kind) {
|
||||
codecList.push_back(listTraits[i].name);
|
||||
} else if (!isEncoder && C2Component::KIND_DECODER == listTraits[i].kind) {
|
||||
codecList.push_back(listTraits[i].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
return codecList;
|
||||
}
|
||||
|
||||
void BenchmarkC2Common::waitOnInputConsumption() {
|
||||
typedef std::unique_lock<std::mutex> ULock;
|
||||
uint32_t queueSize;
|
||||
uint32_t maxRetry = 0;
|
||||
{
|
||||
ULock l(mQueueLock);
|
||||
queueSize = mWorkQueue.size();
|
||||
}
|
||||
while ((maxRetry < MAX_RETRY) && (queueSize < MAX_INPUT_BUFFERS)) {
|
||||
ULock l(mQueueLock);
|
||||
if (queueSize != mWorkQueue.size()) {
|
||||
queueSize = mWorkQueue.size();
|
||||
maxRetry = 0;
|
||||
} else {
|
||||
mQueueCondition.wait_for(l, TIME_OUT);
|
||||
maxRetry++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BenchmarkC2Common::handleWorkDone(std::list<std::unique_ptr<C2Work>> &workItems) {
|
||||
ALOGV("In %s", __func__);
|
||||
mStats->addOutputTime();
|
||||
for (std::unique_ptr<C2Work> &work : workItems) {
|
||||
if (!work->worklets.empty()) {
|
||||
if (work->worklets.front()->output.flags != C2FrameData::FLAG_INCOMPLETE) {
|
||||
mEos = (work->worklets.front()->output.flags & C2FrameData::FLAG_END_OF_STREAM) !=
|
||||
0;
|
||||
ALOGV("WorkDone: frameID received %d , mEos : %d",
|
||||
(int)work->worklets.front()->output.ordinal.frameIndex.peeku(), mEos);
|
||||
work->input.buffers.clear();
|
||||
work->worklets.clear();
|
||||
{
|
||||
typedef std::unique_lock<std::mutex> ULock;
|
||||
ULock l(mQueueLock);
|
||||
mWorkQueue.push_back(std::move(work));
|
||||
mQueueCondition.notify_all();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* 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 __BENCHMARK_C2_COMMON_H__
|
||||
#define __BENCHMARK_C2_COMMON_H__
|
||||
|
||||
#include "codec2/hidl/client.h"
|
||||
|
||||
#include <C2Component.h>
|
||||
#include <C2Config.h>
|
||||
|
||||
#include <hidl/HidlSupport.h>
|
||||
|
||||
#include <C2AllocatorIon.h>
|
||||
#include <C2Buffer.h>
|
||||
#include <C2BufferPriv.h>
|
||||
|
||||
#include "BenchmarkCommon.h"
|
||||
|
||||
#define MAX_RETRY 20
|
||||
#define TIME_OUT 400ms
|
||||
#define MAX_INPUT_BUFFERS 8
|
||||
|
||||
using android::C2AllocatorIon;
|
||||
|
||||
class LinearBuffer : public C2Buffer {
|
||||
public:
|
||||
explicit LinearBuffer(const std::shared_ptr<C2LinearBlock> &block)
|
||||
: C2Buffer({block->share(block->offset(), block->size(), ::C2Fence())}) {}
|
||||
|
||||
explicit LinearBuffer(const std::shared_ptr<C2LinearBlock> &block, size_t size)
|
||||
: C2Buffer({block->share(block->offset(), size, ::C2Fence())}) {}
|
||||
};
|
||||
|
||||
class GraphicBuffer : public C2Buffer {
|
||||
public:
|
||||
explicit GraphicBuffer(const std::shared_ptr<C2GraphicBlock> &block)
|
||||
: C2Buffer({block->share(C2Rect(block->width(), block->height()), ::C2Fence())}) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle Callback functions onWorkDone(), onTripped(),
|
||||
* onError(), onDeath(), onFramesRendered() for C2 Components
|
||||
*/
|
||||
struct CodecListener : public android::Codec2Client::Listener {
|
||||
public:
|
||||
CodecListener(
|
||||
const std::function<void(std::list<std::unique_ptr<C2Work>> &workItems)> fn = nullptr)
|
||||
: callBack(fn) {}
|
||||
virtual void onWorkDone(const std::weak_ptr<android::Codec2Client::Component> &comp,
|
||||
std::list<std::unique_ptr<C2Work>> &workItems) override {
|
||||
ALOGV("onWorkDone called");
|
||||
(void)comp;
|
||||
if (callBack) callBack(workItems);
|
||||
}
|
||||
|
||||
virtual void onTripped(
|
||||
const std::weak_ptr<android::Codec2Client::Component> &comp,
|
||||
const std::vector<std::shared_ptr<C2SettingResult>> &settingResults) override {
|
||||
(void)comp;
|
||||
(void)settingResults;
|
||||
}
|
||||
|
||||
virtual void onError(const std::weak_ptr<android::Codec2Client::Component> &comp,
|
||||
uint32_t errorCode) override {
|
||||
(void)comp;
|
||||
ALOGV("onError called");
|
||||
if (errorCode != 0) ALOGE("Error : %u", errorCode);
|
||||
}
|
||||
|
||||
virtual void onDeath(const std::weak_ptr<android::Codec2Client::Component> &comp) override {
|
||||
(void)comp;
|
||||
}
|
||||
|
||||
virtual void onInputBufferDone(uint64_t frameIndex, size_t arrayIndex) override {
|
||||
(void)frameIndex;
|
||||
(void)arrayIndex;
|
||||
}
|
||||
|
||||
virtual void onFrameRendered(uint64_t bufferQueueId, int32_t slotId,
|
||||
int64_t timestampNs) override {
|
||||
(void)bufferQueueId;
|
||||
(void)slotId;
|
||||
(void)timestampNs;
|
||||
}
|
||||
|
||||
std::function<void(std::list<std::unique_ptr<C2Work>> &workItems)> callBack;
|
||||
};
|
||||
|
||||
class BenchmarkC2Common {
|
||||
public:
|
||||
BenchmarkC2Common()
|
||||
: mEos(false),
|
||||
mStats(nullptr),
|
||||
mClient(nullptr),
|
||||
mBlockPoolId(0),
|
||||
mLinearPool(nullptr),
|
||||
mGraphicPool(nullptr),
|
||||
mLinearAllocator(nullptr),
|
||||
mGraphicAllocator(nullptr) {}
|
||||
|
||||
int32_t setupCodec2();
|
||||
|
||||
vector<string> getSupportedComponentList(bool isEncoder);
|
||||
|
||||
void waitOnInputConsumption();
|
||||
|
||||
// callback function to process onWorkDone received by Listener
|
||||
void handleWorkDone(std::list<std::unique_ptr<C2Work>> &workItems);
|
||||
|
||||
bool mEos;
|
||||
protected:
|
||||
Stats *mStats;
|
||||
|
||||
std::shared_ptr<android::Codec2Client> mClient;
|
||||
|
||||
C2BlockPool::local_id_t mBlockPoolId;
|
||||
std::shared_ptr<C2BlockPool> mLinearPool;
|
||||
std::shared_ptr<C2BlockPool> mGraphicPool;
|
||||
std::shared_ptr<C2Allocator> mLinearAllocator;
|
||||
std::shared_ptr<C2Allocator> mGraphicAllocator;
|
||||
|
||||
std::mutex mQueueLock;
|
||||
std::condition_variable mQueueCondition;
|
||||
std::list<std::unique_ptr<C2Work>> mWorkQueue;
|
||||
};
|
||||
|
||||
#endif // __BENCHMARK_C2_COMMON_H__
|
@ -0,0 +1,166 @@
|
||||
/*
|
||||
* 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 "C2Decoder"
|
||||
|
||||
#include "C2Decoder.h"
|
||||
|
||||
int32_t C2Decoder::createCodec2Component(string compName, AMediaFormat *format) {
|
||||
ALOGV("In %s", __func__);
|
||||
mListener.reset(new CodecListener(
|
||||
[this](std::list<std::unique_ptr<C2Work>> &workItems) { handleWorkDone(workItems); }));
|
||||
if (!mListener) return -1;
|
||||
|
||||
const char *mime = nullptr;
|
||||
AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime);
|
||||
if (!mime) {
|
||||
ALOGE("Error in AMediaFormat_getString");
|
||||
return -1;
|
||||
}
|
||||
// Configure the plugin with Input properties
|
||||
std::vector<C2Param *> configParam;
|
||||
if (!strncmp(mime, "audio/", 6)) {
|
||||
int32_t sampleRate, numChannels;
|
||||
AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE, &sampleRate);
|
||||
AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_CHANNEL_COUNT, &numChannels);
|
||||
C2StreamSampleRateInfo::output sampleRateInfo(0u, sampleRate);
|
||||
C2StreamChannelCountInfo::output channelCountInfo(0u, numChannels);
|
||||
configParam.push_back(&sampleRateInfo);
|
||||
configParam.push_back(&channelCountInfo);
|
||||
|
||||
} else {
|
||||
int32_t width, height;
|
||||
AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_WIDTH, &width);
|
||||
AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_HEIGHT, &height);
|
||||
C2StreamPictureSizeInfo::input inputSize(0u, width, height);
|
||||
configParam.push_back(&inputSize);
|
||||
}
|
||||
|
||||
int64_t sTime = mStats->getCurTime();
|
||||
mComponent = mClient->CreateComponentByName(compName.c_str(), mListener, &mClient);
|
||||
if (mComponent == nullptr) {
|
||||
ALOGE("Create component failed for %s", compName.c_str());
|
||||
return -1;
|
||||
}
|
||||
std::vector<std::unique_ptr<C2SettingResult>> failures;
|
||||
int32_t status = mComponent->config(configParam, C2_DONT_BLOCK, &failures);
|
||||
if (failures.size() != 0) {
|
||||
ALOGE("Invalid Configuration");
|
||||
return -1;
|
||||
}
|
||||
|
||||
status |= mComponent->start();
|
||||
int64_t eTime = mStats->getCurTime();
|
||||
int64_t timeTaken = mStats->getTimeDiff(sTime, eTime);
|
||||
mStats->setInitTime(timeTaken);
|
||||
return status;
|
||||
}
|
||||
|
||||
int32_t C2Decoder::decodeFrames(uint8_t *inputBuffer, vector<AMediaCodecBufferInfo> &frameInfo) {
|
||||
ALOGV("In %s", __func__);
|
||||
typedef std::unique_lock<std::mutex> ULock;
|
||||
c2_status_t status = C2_OK;
|
||||
mStats->setStartTime();
|
||||
while (1) {
|
||||
if (mNumInputFrame == frameInfo.size()) break;
|
||||
std::unique_ptr<C2Work> work;
|
||||
// Prepare C2Work
|
||||
{
|
||||
ULock l(mQueueLock);
|
||||
if (mWorkQueue.empty()) mQueueCondition.wait_for(l, MAX_RETRY * TIME_OUT);
|
||||
if (!mWorkQueue.empty()) {
|
||||
mStats->addInputTime();
|
||||
work.swap(mWorkQueue.front());
|
||||
mWorkQueue.pop_front();
|
||||
} else {
|
||||
cout << "Wait for generating C2Work exceeded timeout" << endl;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t flags = frameInfo[mNumInputFrame].flags;
|
||||
if (flags == AMEDIACODEC_BUFFER_FLAG_CODEC_CONFIG) {
|
||||
flags = C2FrameData::FLAG_CODEC_CONFIG;
|
||||
}
|
||||
if (mNumInputFrame == (frameInfo.size() - 1)) {
|
||||
flags |= C2FrameData::FLAG_END_OF_STREAM;
|
||||
}
|
||||
work->input.flags = (C2FrameData::flags_t)flags;
|
||||
work->input.ordinal.timestamp = frameInfo[mNumInputFrame].presentationTimeUs;
|
||||
work->input.ordinal.frameIndex = mNumInputFrame;
|
||||
work->input.buffers.clear();
|
||||
int size = frameInfo[mNumInputFrame].size;
|
||||
int alignedSize = ALIGN(size, PAGE_SIZE);
|
||||
if (size) {
|
||||
std::shared_ptr<C2LinearBlock> block;
|
||||
status = mLinearPool->fetchLinearBlock(
|
||||
alignedSize, {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}, &block);
|
||||
if (status != C2_OK || block == nullptr) {
|
||||
cout << "C2LinearBlock::map() failed : " << status << endl;
|
||||
return status;
|
||||
}
|
||||
|
||||
C2WriteView view = block->map().get();
|
||||
if (view.error() != C2_OK) {
|
||||
cout << "C2LinearBlock::map() failed : " << view.error() << endl;
|
||||
return view.error();
|
||||
}
|
||||
memcpy(view.base(), inputBuffer + mOffset, size);
|
||||
work->input.buffers.emplace_back(new LinearBuffer(block, size));
|
||||
mStats->addFrameSize(size);
|
||||
}
|
||||
work->worklets.clear();
|
||||
work->worklets.emplace_back(new C2Worklet);
|
||||
|
||||
std::list<std::unique_ptr<C2Work>> items;
|
||||
items.push_back(std::move(work));
|
||||
// queue() invokes process() function of C2 Plugin.
|
||||
status = mComponent->queue(&items);
|
||||
if (status != C2_OK) {
|
||||
ALOGE("queue failed");
|
||||
return status;
|
||||
}
|
||||
ALOGV("Frame #%d size = %d queued", mNumInputFrame, size);
|
||||
mNumInputFrame++;
|
||||
mOffset += size;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
void C2Decoder::deInitCodec() {
|
||||
ALOGV("In %s", __func__);
|
||||
if (!mComponent) return;
|
||||
|
||||
int64_t sTime = mStats->getCurTime();
|
||||
mComponent->stop();
|
||||
mComponent->release();
|
||||
mComponent = nullptr;
|
||||
int64_t eTime = mStats->getCurTime();
|
||||
int64_t timeTaken = mStats->getTimeDiff(sTime, eTime);
|
||||
mStats->setDeInitTime(timeTaken);
|
||||
}
|
||||
|
||||
void C2Decoder::dumpStatistics(string inputReference, int64_t durationUs) {
|
||||
string operation = "c2decode";
|
||||
mStats->dumpStatistics(operation, inputReference, durationUs);
|
||||
}
|
||||
|
||||
void C2Decoder::resetDecoder() {
|
||||
mOffset = 0;
|
||||
mNumInputFrame = 0;
|
||||
if (mStats) mStats->reset();
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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 __C2_DECODER_H__
|
||||
#define __C2_DECODER_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
|
||||
#include "BenchmarkC2Common.h"
|
||||
|
||||
#define ALIGN(_sz, _align) (((_sz) + ((_align) - 1)) & ~((_align) - 1))
|
||||
|
||||
class C2Decoder : public BenchmarkC2Common {
|
||||
public:
|
||||
C2Decoder() : mOffset(0), mNumInputFrame(0), mComponent(nullptr) {}
|
||||
|
||||
int32_t createCodec2Component(string codecName, AMediaFormat *format);
|
||||
|
||||
int32_t decodeFrames(uint8_t *inputBuffer, vector<AMediaCodecBufferInfo> &frameInfo);
|
||||
|
||||
void deInitCodec();
|
||||
|
||||
void dumpStatistics(string inputReference, int64_t durationUs);
|
||||
|
||||
void resetDecoder();
|
||||
|
||||
private:
|
||||
int32_t mOffset;
|
||||
int32_t mNumInputFrame;
|
||||
vector<AMediaCodecBufferInfo> mFrameMetaData;
|
||||
|
||||
std::shared_ptr<android::Codec2Client::Listener> mListener;
|
||||
std::shared_ptr<android::Codec2Client::Component> mComponent;
|
||||
};
|
||||
|
||||
#endif // __C2_DECODER_H__
|
@ -0,0 +1,213 @@
|
||||
/*
|
||||
* 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 "C2DecoderTest"
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
|
||||
#include "BenchmarkTestEnvironment.h"
|
||||
#include "C2Decoder.h"
|
||||
#include "Extractor.h"
|
||||
|
||||
static BenchmarkTestEnvironment *gEnv = nullptr;
|
||||
|
||||
class C2DecoderTest : public ::testing::TestWithParam<pair<string, string>> {
|
||||
public:
|
||||
C2DecoderTest() : mDecoder(nullptr), disableTest(false) { setupC2DecoderTest(); }
|
||||
|
||||
void setupC2DecoderTest();
|
||||
|
||||
vector<string> mCodecList;
|
||||
C2Decoder *mDecoder;
|
||||
bool disableTest;
|
||||
};
|
||||
|
||||
void C2DecoderTest::setupC2DecoderTest() {
|
||||
mDecoder = new C2Decoder();
|
||||
if (!mDecoder) {
|
||||
cout << "[ WARN ] Test Skipped. C2Decoder creation failed\n";
|
||||
disableTest = true;
|
||||
return;
|
||||
}
|
||||
int32_t status = mDecoder->setupCodec2();
|
||||
if (status != 0) {
|
||||
cout << "[ WARN ] Test Skipped. Codec2 setup failed \n";
|
||||
disableTest = true;
|
||||
return;
|
||||
}
|
||||
mCodecList = mDecoder->getSupportedComponentList(false /* isEncoder*/);
|
||||
if (!mCodecList.size()) {
|
||||
cout << "[ WARN ] Test Skipped. Codec2 client didn't recognise any component \n";
|
||||
disableTest = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(C2DecoderTest, Codec2Decode) {
|
||||
if (disableTest) return;
|
||||
|
||||
ALOGV("Decode the samples given by extractor using codec2");
|
||||
string inputFile = gEnv->getRes() + GetParam().first;
|
||||
FILE *inputFp = fopen(inputFile.c_str(), "rb");
|
||||
if (!inputFp) {
|
||||
cout << "[ WARN ] Test Skipped. Unable to open input file" << inputFile
|
||||
<< " for reading \n";
|
||||
return;
|
||||
}
|
||||
|
||||
Extractor *extractor = new Extractor();
|
||||
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);
|
||||
|
||||
if (fileSize > kMaxBufferSize) {
|
||||
cout << "[ WARN ] Test Skipped. Input file size is greater than the threshold memory "
|
||||
"dedicated to the test \n";
|
||||
}
|
||||
|
||||
int32_t trackCount = extractor->initExtractor(fd, fileSize);
|
||||
if (trackCount <= 0) {
|
||||
cout << "[ WARN ] Test Skipped. initExtractor failed\n";
|
||||
return;
|
||||
}
|
||||
for (int32_t 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(fileSize);
|
||||
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 > fileSize) {
|
||||
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 > fileSize) {
|
||||
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;
|
||||
}
|
||||
|
||||
AMediaFormat *format = extractor->getFormat();
|
||||
// Decode the given input stream for all C2 codecs supported by device
|
||||
for (string codecName : mCodecList) {
|
||||
if (codecName.find(GetParam().second) != string::npos &&
|
||||
codecName.find("secure") == string::npos) {
|
||||
status = mDecoder->createCodec2Component(codecName, format);
|
||||
if (status != 0) {
|
||||
cout << "[ WARN ] Test Skipped. Create component failed for " << codecName
|
||||
<< "\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
// Send the inputs to C2 Decoder and wait till all buffers are returned.
|
||||
mDecoder->decodeFrames(inputBuffer, frameInfo);
|
||||
mDecoder->waitOnInputConsumption();
|
||||
if (!mDecoder->mEos) {
|
||||
cout << "[ WARN ] Test Failed. Didn't receive EOS \n";
|
||||
}
|
||||
mDecoder->deInitCodec();
|
||||
int64_t durationUs = extractor->getClipDuration();
|
||||
cout << "codec: " << codecName << endl;
|
||||
mDecoder->dumpStatistics(GetParam().first, durationUs);
|
||||
mDecoder->resetDecoder();
|
||||
}
|
||||
}
|
||||
free(inputBuffer);
|
||||
fclose(inputFp);
|
||||
extractor->deInitExtractor();
|
||||
delete extractor;
|
||||
delete mDecoder;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: (b/140549596)
|
||||
// Add wav files
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
AudioDecoderTest, C2DecoderTest,
|
||||
::testing::Values(
|
||||
make_pair("bbb_44100hz_2ch_128kbps_aac_30sec.mp4", "aac"),
|
||||
make_pair("bbb_44100hz_2ch_128kbps_mp3_30sec.mp3", "mp3"),
|
||||
make_pair("bbb_8000hz_1ch_8kbps_amrnb_30sec.3gp", "amrnb"),
|
||||
make_pair("bbb_16000hz_1ch_9kbps_amrwb_30sec.3gp", "amrnb"),
|
||||
make_pair("bbb_44100hz_2ch_80kbps_vorbis_30sec.mp4", "vorbis"),
|
||||
make_pair("bbb_44100hz_2ch_600kbps_flac_30sec.mp4", "flac"),
|
||||
make_pair("bbb_48000hz_2ch_100kbps_opus_30sec.webm", "opus")));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
VideoDecoderTest, C2DecoderTest,
|
||||
::testing::Values(
|
||||
make_pair("crowd_1920x1080_25fps_4000kbps_vp9.webm", "vp9"),
|
||||
make_pair("crowd_1920x1080_25fps_4000kbps_vp8.webm", "vp8"),
|
||||
make_pair("crowd_1920x1080_25fps_4000kbps_av1.webm", "av1"),
|
||||
make_pair("crowd_1920x1080_25fps_7300kbps_mpeg2.mp4", "mpeg2"),
|
||||
make_pair("crowd_1920x1080_25fps_6000kbps_mpeg4.mp4", "mpeg4"),
|
||||
make_pair("crowd_352x288_25fps_6000kbps_h263.3gp", "h263"),
|
||||
make_pair("crowd_1920x1080_25fps_6700kbps_h264.ts", "avc"),
|
||||
make_pair("crowd_1920x1080_25fps_4000kbps_h265.mkv", "hevc")));
|
||||
|
||||
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();
|
||||
ALOGV("C2 Decoder Test result = %d\n", status);
|
||||
}
|
||||
return status;
|
||||
}
|
Loading…
Reference in new issue