Test: muxerTest --gtest_repeat=10 -P /sdcard/res/ Bug: 140051680 Change-Id: Ia67df1f05c10798439ca1b4910f27dcc5593c594gugelfrei
parent
789fb735a6
commit
cde255126c
@ -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_muxer",
|
||||
defaults: [
|
||||
"libbenchmark_common-defaults",
|
||||
"libbenchmark_soft_sanitize_all-defaults",
|
||||
],
|
||||
|
||||
srcs: ["Muxer.cpp"],
|
||||
|
||||
static_libs: ["libbenchmark_extractor"],
|
||||
|
||||
export_include_dirs: ["."],
|
||||
|
||||
ldflags: ["-Wl,-Bsymbolic"]
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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 "muxer"
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
#include "Muxer.h"
|
||||
|
||||
int32_t Muxer::initMuxer(int32_t fd, MUXER_OUTPUT_T outputFormat) {
|
||||
if (!mFormat) mFormat = mExtractor->getFormat();
|
||||
if (!mTimer) mTimer = new Timer();
|
||||
|
||||
int64_t sTime = mTimer->getCurTime();
|
||||
mMuxer = AMediaMuxer_new(fd, (OutputFormat)outputFormat);
|
||||
if (!mMuxer) {
|
||||
cout << "[ WARN ] Test Skipped. Unable to create muxer \n";
|
||||
return AMEDIA_ERROR_INVALID_OBJECT;
|
||||
}
|
||||
/*
|
||||
* AMediaMuxer_addTrack returns the index of the new track or a negative value
|
||||
* in case of failure, which can be interpreted as a media_status_t.
|
||||
*/
|
||||
ssize_t index = AMediaMuxer_addTrack(mMuxer, mFormat);
|
||||
if (index < 0) {
|
||||
cout << "[ WARN ] Test Skipped. Format not supported \n";
|
||||
return index;
|
||||
}
|
||||
AMediaMuxer_start(mMuxer);
|
||||
int64_t eTime = mTimer->getCurTime();
|
||||
int64_t timeTaken = mTimer->getTimeDiff(sTime, eTime);
|
||||
mTimer->setInitTime(timeTaken);
|
||||
return AMEDIA_OK;
|
||||
}
|
||||
|
||||
void Muxer::deInitMuxer() {
|
||||
int64_t sTime = mTimer->getCurTime();
|
||||
if (mFormat) {
|
||||
AMediaFormat_delete(mFormat);
|
||||
mFormat = nullptr;
|
||||
}
|
||||
if (!mMuxer) return;
|
||||
AMediaMuxer_stop(mMuxer);
|
||||
AMediaMuxer_delete(mMuxer);
|
||||
int64_t eTime = mTimer->getCurTime();
|
||||
int64_t timeTaken = mTimer->getTimeDiff(sTime, eTime);
|
||||
mTimer->setDeInitTime(timeTaken);
|
||||
}
|
||||
|
||||
void Muxer::resetMuxer() {
|
||||
if (mTimer) mTimer->resetTimers();
|
||||
}
|
||||
|
||||
void Muxer::dumpStatistics(string inputReference) {
|
||||
string operation = "mux";
|
||||
mTimer->dumpStatistics(operation, inputReference, mExtractor->getClipDuration());
|
||||
}
|
||||
|
||||
int32_t Muxer::mux(uint8_t *inputBuffer, vector<AMediaCodecBufferInfo> &frameInfos) {
|
||||
// Mux frame data
|
||||
size_t frameIdx = 0;
|
||||
mTimer->setStartTime();
|
||||
while (frameIdx < frameInfos.size()) {
|
||||
AMediaCodecBufferInfo info = frameInfos.at(frameIdx);
|
||||
media_status_t status = AMediaMuxer_writeSampleData(mMuxer, 0, inputBuffer, &info);
|
||||
if (status != 0) {
|
||||
ALOGE("Error in AMediaMuxer_writeSampleData");
|
||||
return status;
|
||||
}
|
||||
mTimer->addOutputTime();
|
||||
frameIdx++;
|
||||
}
|
||||
return AMEDIA_OK;
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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 __MUXER_H__
|
||||
#define __MUXER_H__
|
||||
|
||||
#include <media/NdkMediaMuxer.h>
|
||||
|
||||
#include "BenchmarkCommon.h"
|
||||
#include "Timer.h"
|
||||
#include "Extractor.h"
|
||||
|
||||
typedef enum {
|
||||
MUXER_OUTPUT_FORMAT_MPEG_4 = 0,
|
||||
MUXER_OUTPUT_FORMAT_WEBM = 1,
|
||||
MUXER_OUTPUT_FORMAT_3GPP = 2,
|
||||
MUXER_OUTPUT_FORMAT_OGG = 4,
|
||||
MUXER_OUTPUT_FORMAT_INVALID = 5,
|
||||
} MUXER_OUTPUT_T;
|
||||
|
||||
class Muxer {
|
||||
public:
|
||||
Muxer() : mFormat(nullptr), mMuxer(nullptr), mTimer(nullptr) { mExtractor = new Extractor(); }
|
||||
|
||||
virtual ~Muxer() {
|
||||
if (mTimer) delete mTimer;
|
||||
if (mExtractor) delete mExtractor;
|
||||
}
|
||||
|
||||
Timer *getTimer() { return mTimer; }
|
||||
Extractor *getExtractor() { return mExtractor; }
|
||||
|
||||
/* Muxer related utilities */
|
||||
int32_t initMuxer(int32_t fd, MUXER_OUTPUT_T outputFormat);
|
||||
void deInitMuxer();
|
||||
void resetMuxer();
|
||||
|
||||
/* Process the frames and give Muxed output */
|
||||
int32_t mux(uint8_t *inputBuffer, vector<AMediaCodecBufferInfo> &frameSizes);
|
||||
|
||||
void dumpStatistics(string inputReference);
|
||||
|
||||
private:
|
||||
AMediaFormat *mFormat;
|
||||
AMediaMuxer *mMuxer;
|
||||
Extractor *mExtractor;
|
||||
Timer *mTimer;
|
||||
};
|
||||
|
||||
#endif // __MUXER_H__
|
@ -0,0 +1,181 @@
|
||||
|
||||
/*
|
||||
* 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 "muxerTest"
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
#include "Muxer.h"
|
||||
#include "BenchmarkTestEnvironment.h"
|
||||
|
||||
#define OUTPUT_FILE_NAME "/data/local/tmp/mux.out"
|
||||
|
||||
static BenchmarkTestEnvironment *gEnv = nullptr;
|
||||
|
||||
class MuxerTest : public ::testing::TestWithParam<pair<string, string>> {};
|
||||
|
||||
static MUXER_OUTPUT_T getMuxerOutFormat(string fmt) {
|
||||
static const struct {
|
||||
string name;
|
||||
MUXER_OUTPUT_T value;
|
||||
} kFormatMaps[] = {{"mp4", MUXER_OUTPUT_FORMAT_MPEG_4},
|
||||
{"webm", MUXER_OUTPUT_FORMAT_WEBM},
|
||||
{"3gpp", MUXER_OUTPUT_FORMAT_3GPP},
|
||||
{"ogg", MUXER_OUTPUT_FORMAT_OGG}};
|
||||
|
||||
MUXER_OUTPUT_T format = MUXER_OUTPUT_FORMAT_INVALID;
|
||||
for (size_t i = 0; i < sizeof(kFormatMaps) / sizeof(kFormatMaps[0]); ++i) {
|
||||
if (!fmt.compare(kFormatMaps[i].name)) {
|
||||
format = kFormatMaps[i].value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return format;
|
||||
}
|
||||
|
||||
TEST_P(MuxerTest, Mux) {
|
||||
ALOGV("Mux the samples given by extractor");
|
||||
string inputFile = gEnv->getRes() + GetParam().first;
|
||||
FILE *inputFp = fopen(inputFile.c_str(), "rb");
|
||||
if (!inputFp) {
|
||||
cout << "[ WARN ] Test Skipped. Unable to open input file for reading \n";
|
||||
return;
|
||||
}
|
||||
string fmt = GetParam().second;
|
||||
MUXER_OUTPUT_T outputFormat = getMuxerOutFormat(fmt);
|
||||
if (outputFormat == MUXER_OUTPUT_FORMAT_INVALID) {
|
||||
ALOGE("output format is MUXER_OUTPUT_FORMAT_INVALID");
|
||||
return;
|
||||
}
|
||||
|
||||
Muxer *muxerObj = new Muxer();
|
||||
Extractor *extractor = muxerObj->getExtractor();
|
||||
if (!extractor) {
|
||||
cout << "[ WARN ] Test Skipped. Extractor creation failed \n";
|
||||
return;
|
||||
}
|
||||
|
||||
// Read file properties
|
||||
size_t fileSize = 0;
|
||||
fseek(inputFp, 0, SEEK_END);
|
||||
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) {
|
||||
std::cout << "[ WARN ] Test Skipped. Insufficient memory \n";
|
||||
return;
|
||||
}
|
||||
// AMediaCodecBufferInfo : <size of frame> <flags> <presentationTimeUs> <offset>
|
||||
vector<AMediaCodecBufferInfo> frameInfos;
|
||||
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 muxer
|
||||
if (inputBufferOffset + info.size > kMaxBufferSize) {
|
||||
cout << "[ WARN ] Test Skipped. Memory allocated not sufficient\n";
|
||||
free(inputBuffer);
|
||||
return;
|
||||
}
|
||||
memcpy(inputBuffer + inputBufferOffset, extractor->getFrameBuf(), info.size);
|
||||
info.offset = inputBufferOffset;
|
||||
frameInfos.push_back(info);
|
||||
inputBufferOffset += info.size;
|
||||
}
|
||||
|
||||
string outputFileName = OUTPUT_FILE_NAME;
|
||||
FILE *outputFp = fopen(outputFileName.c_str(), "w+b");
|
||||
if (!outputFp) {
|
||||
cout << "[ WARN ] Test Skipped. Unable to open output file for writing \n";
|
||||
return;
|
||||
}
|
||||
int32_t fd = fileno(outputFp);
|
||||
status = muxerObj->initMuxer(fd, outputFormat);
|
||||
if (status != 0) {
|
||||
cout << "[ WARN ] Test Skipped. initMuxer failed\n";
|
||||
return;
|
||||
}
|
||||
|
||||
status = muxerObj->mux(inputBuffer, frameInfos);
|
||||
if (status != 0) {
|
||||
cout << "[ WARN ] Test Skipped. Mux failed \n";
|
||||
return;
|
||||
}
|
||||
muxerObj->deInitMuxer();
|
||||
muxerObj->dumpStatistics(GetParam().first + "." + fmt.c_str());
|
||||
free(inputBuffer);
|
||||
fclose(outputFp);
|
||||
muxerObj->resetMuxer();
|
||||
}
|
||||
fclose(inputFp);
|
||||
extractor->deInitExtractor();
|
||||
delete muxerObj;
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
MuxerTestAll, MuxerTest,
|
||||
::testing::Values(make_pair("crowd_1920x1080_25fps_4000kbps_vp8.webm", "webm"),
|
||||
make_pair("crowd_1920x1080_25fps_4000kbps_vp9.webm", "webm"),
|
||||
make_pair("crowd_1920x1080_25fps_6000kbps_mpeg4.mp4", "mp4"),
|
||||
make_pair("crowd_352x288_25fps_6000kbps_h263.3gp", "mp4"),
|
||||
make_pair("crowd_1920x1080_25fps_6700kbps_h264.ts", "mp4"),
|
||||
make_pair("crowd_1920x1080_25fps_4000kbps_h265.mkv", "mp4"),
|
||||
make_pair("crowd_1920x1080_25fps_6000kbps_mpeg4.mp4", "3gpp"),
|
||||
make_pair("crowd_352x288_25fps_6000kbps_h263.3gp", "3gpp"),
|
||||
make_pair("crowd_1920x1080_25fps_6700kbps_h264.ts", "3gpp"),
|
||||
make_pair("crowd_1920x1080_25fps_4000kbps_h265.mkv", "3gpp"),
|
||||
make_pair("bbb_48000hz_2ch_100kbps_opus_5mins.webm", "ogg"),
|
||||
make_pair("bbb_44100hz_2ch_80kbps_vorbis_5mins.mp4", "webm"),
|
||||
make_pair("bbb_48000hz_2ch_100kbps_opus_5mins.webm", "webm"),
|
||||
make_pair("bbb_44100hz_2ch_128kbps_aac_5mins.mp4", "mp4"),
|
||||
make_pair("bbb_8000hz_1ch_8kbps_amrnb_5mins.3gp", "mp4"),
|
||||
make_pair("bbb_16000hz_1ch_9kbps_amrwb_5mins.3gp", "mp4"),
|
||||
make_pair("bbb_44100hz_2ch_128kbps_aac_5mins.mp4", "3gpp"),
|
||||
make_pair("bbb_8000hz_1ch_8kbps_amrnb_5mins.3gp", "3gpp"),
|
||||
make_pair("bbb_16000hz_1ch_9kbps_amrwb_5mins.3gp", "3gpp")));
|
||||
|
||||
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("Test result = %d\n", status);
|
||||
}
|
||||
return status;
|
||||
}
|
Loading…
Reference in new issue