am: c1a82b91f0
Change-Id: I49c9746a6689f49ab2c6b8a9c64ab8823b8c6e17
gugelfrei
commit
7685d32a4e
@ -0,0 +1,264 @@
|
||||
/*
|
||||
* 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 "C2Encoder"
|
||||
|
||||
#include "C2Encoder.h"
|
||||
|
||||
int32_t C2Encoder::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)) {
|
||||
mIsAudioEncoder = true;
|
||||
int32_t numChannels;
|
||||
if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE, &mSampleRate)) {
|
||||
ALOGE("AMEDIAFORMAT_KEY_SAMPLE_RATE not set");
|
||||
return -1;
|
||||
}
|
||||
if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_CHANNEL_COUNT, &numChannels)) {
|
||||
ALOGE("AMEDIAFORMAT_KEY_CHANNEL_COUNT not set");
|
||||
return -1;
|
||||
}
|
||||
C2StreamSampleRateInfo::input sampleRateInfo(0u, mSampleRate);
|
||||
C2StreamChannelCountInfo::input channelCountInfo(0u, numChannels);
|
||||
configParam.push_back(&sampleRateInfo);
|
||||
configParam.push_back(&channelCountInfo);
|
||||
} else {
|
||||
mIsAudioEncoder = false;
|
||||
if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_WIDTH, &mWidth)) {
|
||||
ALOGE("AMEDIAFORMAT_KEY_WIDTH not set");
|
||||
return -1;
|
||||
}
|
||||
if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_HEIGHT, &mHeight)) {
|
||||
ALOGE("AMEDIAFORMAT_KEY_HEIGHT not set");
|
||||
return -1;
|
||||
}
|
||||
C2StreamPictureSizeInfo::input inputSize(0u, mWidth, mHeight);
|
||||
configParam.push_back(&inputSize);
|
||||
|
||||
if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_FRAME_RATE, &mFrameRate) ||
|
||||
(mFrameRate <= 0)) {
|
||||
mFrameRate = KDefaultFrameRate;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// In encoder components, fetch the size of input buffer allocated
|
||||
int32_t C2Encoder::getInputMaxBufSize() {
|
||||
int32_t bitStreamInfo[1] = {0};
|
||||
std::vector<std::unique_ptr<C2Param>> inParams;
|
||||
c2_status_t status = mComponent->query({}, {C2StreamMaxBufferSizeInfo::input::PARAM_TYPE},
|
||||
C2_DONT_BLOCK, &inParams);
|
||||
if (status != C2_OK && inParams.size() == 0) {
|
||||
ALOGE("Query MaxBufferSizeInfo failed => %d", status);
|
||||
return status;
|
||||
} else {
|
||||
size_t offset = sizeof(C2Param);
|
||||
for (size_t i = 0; i < inParams.size(); ++i) {
|
||||
C2Param *param = inParams[i].get();
|
||||
bitStreamInfo[i] = *(int32_t *)((uint8_t *)param + offset);
|
||||
}
|
||||
}
|
||||
mInputMaxBufSize = bitStreamInfo[0];
|
||||
if (mInputMaxBufSize < 0) {
|
||||
ALOGE("Invalid mInputMaxBufSize %d\n", mInputMaxBufSize);
|
||||
return -1;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
int32_t C2Encoder::encodeFrames(ifstream &eleStream, size_t inputBufferSize) {
|
||||
ALOGV("In %s", __func__);
|
||||
int32_t frameSize = 0;
|
||||
if (!mIsAudioEncoder) {
|
||||
frameSize = mWidth * mHeight * 3 / 2;
|
||||
} else {
|
||||
frameSize = DEFAULT_AUDIO_FRAME_SIZE;
|
||||
if (getInputMaxBufSize() != 0) return -1;
|
||||
if (frameSize > mInputMaxBufSize) {
|
||||
frameSize = mInputMaxBufSize;
|
||||
}
|
||||
}
|
||||
int32_t numFrames = (inputBufferSize + frameSize - 1) / frameSize;
|
||||
// Temporary buffer to read data from the input file
|
||||
char *data = (char *)malloc(frameSize);
|
||||
if (!data) {
|
||||
ALOGE("Insufficient memory to read from input file");
|
||||
return -1;
|
||||
}
|
||||
|
||||
typedef std::unique_lock<std::mutex> ULock;
|
||||
uint64_t presentationTimeUs = 0;
|
||||
size_t offset = 0;
|
||||
c2_status_t status = C2_OK;
|
||||
|
||||
mStats->setStartTime();
|
||||
while (numFrames > 0) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (mIsAudioEncoder) {
|
||||
presentationTimeUs = mNumInputFrame * frameSize * (1000000 / mSampleRate);
|
||||
} else {
|
||||
presentationTimeUs = mNumInputFrame * (1000000 / mFrameRate);
|
||||
}
|
||||
uint32_t flags = 0;
|
||||
if (numFrames == 1) flags |= C2FrameData::FLAG_END_OF_STREAM;
|
||||
|
||||
work->input.flags = (C2FrameData::flags_t)flags;
|
||||
work->input.ordinal.timestamp = presentationTimeUs;
|
||||
work->input.ordinal.frameIndex = mNumInputFrame;
|
||||
work->input.buffers.clear();
|
||||
|
||||
if (inputBufferSize - offset < frameSize) {
|
||||
frameSize = inputBufferSize - offset;
|
||||
}
|
||||
eleStream.read(data, frameSize);
|
||||
if (eleStream.gcount() != frameSize) {
|
||||
ALOGE("read() from file failed. Incorrect bytes read");
|
||||
return -1;
|
||||
}
|
||||
offset += frameSize;
|
||||
|
||||
if (frameSize) {
|
||||
if (mIsAudioEncoder) {
|
||||
std::shared_ptr<C2LinearBlock> block;
|
||||
status = mLinearPool->fetchLinearBlock(
|
||||
frameSize, {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}, &block);
|
||||
if (status != C2_OK || !block) {
|
||||
cout << "fetchLinearBlock 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(), data, frameSize);
|
||||
work->input.buffers.emplace_back(new LinearBuffer(block));
|
||||
} else {
|
||||
std::shared_ptr<C2GraphicBlock> block;
|
||||
status = mGraphicPool->fetchGraphicBlock(
|
||||
mWidth, mHeight, HAL_PIXEL_FORMAT_YV12,
|
||||
{C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}, &block);
|
||||
if (status != C2_OK || !block) {
|
||||
cout << "fetchGraphicBlock failed : " << status << endl;
|
||||
return status;
|
||||
}
|
||||
C2GraphicView view = block->map().get();
|
||||
if (view.error() != C2_OK) {
|
||||
cout << "C2GraphicBlock::map() failed : " << view.error() << endl;
|
||||
return view.error();
|
||||
}
|
||||
|
||||
uint8_t *pY = view.data()[C2PlanarLayout::PLANE_Y];
|
||||
uint8_t *pU = view.data()[C2PlanarLayout::PLANE_U];
|
||||
uint8_t *pV = view.data()[C2PlanarLayout::PLANE_V];
|
||||
memcpy(pY, data, mWidth * mHeight);
|
||||
memcpy(pU, data + mWidth * mHeight, (mWidth * mHeight >> 2));
|
||||
memcpy(pV, data + (mWidth * mHeight * 5 >> 2), mWidth * mHeight >> 2);
|
||||
work->input.buffers.emplace_back(new GraphicBuffer(block));
|
||||
}
|
||||
mStats->addFrameSize(frameSize);
|
||||
}
|
||||
|
||||
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, frameSize);
|
||||
numFrames--;
|
||||
mNumInputFrame++;
|
||||
}
|
||||
free(data);
|
||||
return status;
|
||||
}
|
||||
|
||||
void C2Encoder::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 C2Encoder::dumpStatistics(string inputReference, int64_t durationUs) {
|
||||
string operation = "c2encode";
|
||||
mStats->dumpStatistics(operation, inputReference, durationUs);
|
||||
}
|
||||
|
||||
void C2Encoder::resetEncoder() {
|
||||
mIsAudioEncoder = false;
|
||||
mNumInputFrame = 0;
|
||||
mEos = false;
|
||||
if (mStats) mStats->reset();
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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_ENCODER_H__
|
||||
#define __C2_ENCODER_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
|
||||
#include "BenchmarkC2Common.h"
|
||||
|
||||
#define DEFAULT_AUDIO_FRAME_SIZE 4096
|
||||
|
||||
constexpr int32_t KDefaultFrameRate = 25;
|
||||
|
||||
class C2Encoder : public BenchmarkC2Common {
|
||||
public:
|
||||
C2Encoder()
|
||||
: mIsAudioEncoder(false),
|
||||
mWidth(0),
|
||||
mHeight(0),
|
||||
mNumInputFrame(0),
|
||||
mComponent(nullptr) {}
|
||||
|
||||
int32_t createCodec2Component(string codecName, AMediaFormat *format);
|
||||
|
||||
int32_t encodeFrames(ifstream &eleStream, size_t inputBufferSize);
|
||||
|
||||
int32_t getInputMaxBufSize();
|
||||
|
||||
void deInitCodec();
|
||||
|
||||
void dumpStatistics(string inputReference, int64_t durationUs);
|
||||
|
||||
void resetEncoder();
|
||||
|
||||
private:
|
||||
bool mIsAudioEncoder;
|
||||
|
||||
int32_t mWidth;
|
||||
int32_t mHeight;
|
||||
int32_t mFrameRate;
|
||||
int32_t mSampleRate;
|
||||
|
||||
int32_t mNumInputFrame;
|
||||
int32_t mInputMaxBufSize;
|
||||
|
||||
std::shared_ptr<android::Codec2Client::Listener> mListener;
|
||||
std::shared_ptr<android::Codec2Client::Component> mComponent;
|
||||
};
|
||||
|
||||
#endif // __C2_ENCODER_H__
|
@ -0,0 +1,177 @@
|
||||
/*
|
||||
* 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 "C2EncoderTest"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
|
||||
#include "BenchmarkTestEnvironment.h"
|
||||
#include "C2Encoder.h"
|
||||
#include "Decoder.h"
|
||||
|
||||
static BenchmarkTestEnvironment *gEnv = nullptr;
|
||||
|
||||
class C2EncoderTest : public ::testing::TestWithParam<pair<string, string>> {
|
||||
public:
|
||||
C2EncoderTest() : mEncoder(nullptr) { setupC2EncoderTest(); }
|
||||
|
||||
void setupC2EncoderTest();
|
||||
|
||||
vector<string> mCodecList;
|
||||
C2Encoder *mEncoder;
|
||||
};
|
||||
|
||||
void C2EncoderTest::setupC2EncoderTest() {
|
||||
mEncoder = new C2Encoder();
|
||||
ASSERT_NE(mEncoder, nullptr) << "C2Encoder creation failed";
|
||||
|
||||
int32_t status = mEncoder->setupCodec2();
|
||||
ASSERT_EQ(status, 0) << "Codec2 setup failed";
|
||||
|
||||
mCodecList = mEncoder->getSupportedComponentList(true /* isEncoder*/);
|
||||
ASSERT_GT(mCodecList.size(), 0) << "Codec2 client didn't recognise any component";
|
||||
}
|
||||
|
||||
TEST_P(C2EncoderTest, Codec2Encode) {
|
||||
ALOGV("Encodes the input using codec2 framework");
|
||||
string inputFile = gEnv->getRes() + GetParam().first;
|
||||
FILE *inputFp = fopen(inputFile.c_str(), "rb");
|
||||
ASSERT_NE(inputFp, nullptr) << "Unable to open input file for reading";
|
||||
|
||||
Decoder *decoder = new Decoder();
|
||||
ASSERT_NE(decoder, nullptr) << "Decoder creation failed";
|
||||
|
||||
Extractor *extractor = decoder->getExtractor();
|
||||
ASSERT_NE(extractor, nullptr) << "Extractor creation failed";
|
||||
|
||||
// Read file properties
|
||||
struct stat buf;
|
||||
stat(inputFile.c_str(), &buf);
|
||||
size_t fileSize = buf.st_size;
|
||||
int32_t fd = fileno(inputFp);
|
||||
|
||||
ASSERT_LE(fileSize, kMaxBufferSize)
|
||||
<< "Input file size is greater than the threshold memory dedicated to the test";
|
||||
|
||||
int32_t trackCount = extractor->initExtractor(fd, fileSize);
|
||||
ASSERT_GT(trackCount, 0) << "initExtractor failed";
|
||||
|
||||
for (int curTrack = 0; curTrack < trackCount; curTrack++) {
|
||||
int32_t status = extractor->setupTrackFormat(curTrack);
|
||||
ASSERT_EQ(status, 0) << "Track Format invalid";
|
||||
|
||||
uint8_t *inputBuffer = (uint8_t *)malloc(fileSize);
|
||||
ASSERT_NE(inputBuffer, nullptr) << "Insufficient memory";
|
||||
|
||||
vector<AMediaCodecBufferInfo> frameInfo;
|
||||
AMediaCodecBufferInfo info;
|
||||
uint32_t inputBufferOffset = 0;
|
||||
|
||||
// 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
|
||||
ASSERT_LE(inputBufferOffset + info.size, fileSize) << "Memory allocated not sufficient";
|
||||
|
||||
memcpy(inputBuffer + inputBufferOffset, extractor->getFrameBuf(), info.size);
|
||||
frameInfo.push_back(info);
|
||||
inputBufferOffset += info.size;
|
||||
}
|
||||
|
||||
string decName = "";
|
||||
string outputFileName = "decode.out";
|
||||
FILE *outFp = fopen(outputFileName.c_str(), "wb");
|
||||
ASSERT_NE(outFp, nullptr) << "Unable to open output file" << outputFileName
|
||||
<< " for dumping decoder's output";
|
||||
|
||||
decoder->setupDecoder();
|
||||
status = decoder->decode(inputBuffer, frameInfo, decName, false /*asyncMode */, outFp);
|
||||
ASSERT_EQ(status, AMEDIA_OK) << "Decode returned error : " << status;
|
||||
|
||||
// Encode the given input stream for all C2 codecs supported by device
|
||||
AMediaFormat *format = extractor->getFormat();
|
||||
ifstream eleStream;
|
||||
eleStream.open(outputFileName.c_str(), ifstream::binary | ifstream::ate);
|
||||
ASSERT_EQ(eleStream.is_open(), true) << outputFileName.c_str() << " - file not found";
|
||||
size_t eleSize = eleStream.tellg();
|
||||
|
||||
for (string codecName : mCodecList) {
|
||||
if (codecName.find(GetParam().second) != string::npos) {
|
||||
status = mEncoder->createCodec2Component(codecName, format);
|
||||
ASSERT_EQ(status, 0) << "Create component failed for " << codecName;
|
||||
|
||||
// Send the inputs to C2 Encoder and wait till all buffers are returned.
|
||||
eleStream.seekg(0, ifstream::beg);
|
||||
status = mEncoder->encodeFrames(eleStream, eleSize);
|
||||
ASSERT_EQ(status, 0) << "Encoder failed for " << codecName;
|
||||
|
||||
mEncoder->waitOnInputConsumption();
|
||||
ASSERT_TRUE(mEncoder->mEos) << "Test Failed. Didn't receive EOS \n";
|
||||
|
||||
mEncoder->deInitCodec();
|
||||
int64_t durationUs = extractor->getClipDuration();
|
||||
cout << "codec: " << codecName << endl;
|
||||
mEncoder->dumpStatistics(GetParam().first, durationUs);
|
||||
mEncoder->resetEncoder();
|
||||
}
|
||||
}
|
||||
|
||||
// Destroy the decoder for the given input
|
||||
decoder->deInitCodec();
|
||||
decoder->resetDecoder();
|
||||
free(inputBuffer);
|
||||
}
|
||||
fclose(inputFp);
|
||||
extractor->deInitExtractor();
|
||||
delete decoder;
|
||||
delete mEncoder;
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
AudioEncoderTest, C2EncoderTest,
|
||||
::testing::Values(
|
||||
make_pair("bbb_44100hz_2ch_128kbps_aac_30sec.mp4", "aac"),
|
||||
make_pair("bbb_8000hz_1ch_8kbps_amrnb_30sec.3gp", "amrnb"),
|
||||
make_pair("bbb_16000hz_1ch_9kbps_amrwb_30sec.3gp", "amrwb"),
|
||||
make_pair("bbb_44100hz_2ch_600kbps_flac_30sec.mp4", "flac"),
|
||||
make_pair("bbb_48000hz_2ch_100kbps_opus_30sec.webm", "opus")));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
VideoEncoderTest, C2EncoderTest,
|
||||
::testing::Values(
|
||||
make_pair("crowd_1920x1080_25fps_4000kbps_vp9.webm", "vp9"),
|
||||
make_pair("crowd_1920x1080_25fps_4000kbps_vp8.webm", "vp8"),
|
||||
make_pair("crowd_176x144_25fps_6000kbps_mpeg4.mp4", "mpeg4"),
|
||||
make_pair("crowd_176x144_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 Encoder Test result = %d\n", status);
|
||||
}
|
||||
return status;
|
||||
}
|
Loading…
Reference in new issue