MediaTesting: Add Extractor Factory Unit Test

Test: atest ExtractorFactoryTest -- --enable-module-dynamic-download=true

Bug: 149541234

Change-Id: I17b9d6dd5585c186929d149681748a79b16e5b20
gugelfrei
Manisha Jajoo 4 years ago committed by Ray Essick
parent 06675ff30f
commit a7f72b47bf

@ -0,0 +1,61 @@
/*
* Copyright (C) 2020 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: "ExtractorFactoryTest",
gtest: true,
srcs: [
"ExtractorFactoryTest.cpp",
],
shared_libs: [
"liblog",
"libbase",
"libutils",
"libmedia",
"libbinder",
"libcutils",
"libdl_android",
"libdatasource",
"libmediametrics",
],
static_libs: [
"libstagefright",
"libstagefright_foundation",
],
include_dirs: [
"frameworks/av/media/libstagefright",
],
// TODO: (b/150181583)
compile_multilib: "first",
cflags: [
"-Werror",
"-Wall",
],
sanitize: {
cfi: true,
misc_undefined: [
"unsigned-integer-overflow",
"signed-integer-overflow",
],
},
}

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2020 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.
-->
<configuration description="Test module config for extractor factory unit tests">
<option name="test-suite-tag" value="ExtractorFactoryTest" />
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="ExtractorFactoryTest->/data/local/tmp/ExtractorFactoryTest" />
<option name="push-file"
key="https://storage.googleapis.com/android_media/frameworks/av/media/extractors/tests/extractor.zip?unzip=true"
value="/data/local/tmp/ExtractorFactoryTestRes/" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="ExtractorFactoryTest" />
<option name="native-test-flag" value="-P /data/local/tmp/ExtractorFactoryTestRes/" />
</test>
</configuration>

@ -0,0 +1,167 @@
/*
* Copyright (C) 2020 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 "ExtractorFactoryTest"
#include <utils/Log.h>
#include <binder/ProcessState.h>
#include <datasource/FileSource.h>
#include <media/stagefright/MediaExtractorFactory.h>
#include <media/stagefright/foundation/MediaDefs.h>
#include "ExtractorFactoryTestEnvironment.h"
#define OUTPUT_FILE_NAME "/data/local/tmp/exFactoryLogs"
using namespace android;
static ExtractorFactoryTestEnvironment *gEnv = nullptr;
class ExtractorFactoryTest : public ::testing::TestWithParam<pair<string, string>> {
public:
ExtractorFactoryTest() : mDataSource(nullptr), mExtractor(nullptr) {}
~ExtractorFactoryTest() {
if (mDataSource) {
mDataSource.clear();
mDataSource = nullptr;
}
if (mExtractor) {
mExtractor.clear();
mExtractor = nullptr;
}
}
int32_t createDataSource(string inputFileName);
int32_t createExtractor(bool createFromService, string inputMime);
sp<DataSource> mDataSource;
sp<IMediaExtractor> mExtractor;
};
int32_t ExtractorFactoryTest::createDataSource(string inputFileName) {
FILE *mInputFp = fopen(inputFileName.c_str(), "rb");
if (!mInputFp) {
ALOGE("Unable to open input file : %s for reading", inputFileName.c_str());
return -1;
}
struct stat buf;
int32_t status = stat(inputFileName.c_str(), &buf);
if (status != 0) {
ALOGE("Failed to read file properties for input file : %s", inputFileName.c_str());
return -1;
}
int32_t fd = fileno(mInputFp);
if (fd < 0) {
ALOGE("Invalid file descriptor for input file : %s", inputFileName.c_str());
return -1;
}
mDataSource = new FileSource(dup(fd), 0, buf.st_size);
if (!mDataSource) return -1;
return 0;
}
int32_t ExtractorFactoryTest::createExtractor(bool createFromService, string inputMime) {
ALOGV("Creating extractor for mime : %s", inputMime.c_str());
if (createFromService) {
mExtractor = MediaExtractorFactory::CreateFromService(mDataSource, inputMime.c_str());
} else {
mExtractor = MediaExtractorFactory::Create(mDataSource);
}
if (mExtractor == nullptr) return -1;
return 0;
}
TEST_F(ExtractorFactoryTest, ListExtractorsTest) {
MediaExtractorFactory::LoadExtractors();
vector<std::string> supportedTypes = MediaExtractorFactory::getSupportedTypes();
ASSERT_GT(supportedTypes.size(), 0) << " MediaExtractorFactory doesn't suuport any extractor";
FILE *outputLog = fopen(OUTPUT_FILE_NAME, "wb");
ASSERT_NE(outputLog, nullptr) << "Unable to open output file - " << OUTPUT_FILE_NAME
<< " for writing";
int32_t fd = fileno(outputLog);
ASSERT_GE(fd, 0);
Vector<String16> args;
int32_t status = MediaExtractorFactory::dump(fd, args);
ASSERT_EQ(status, OK) << "MediaExtractorFactory dump failed";
fclose(outputLog);
}
TEST_P(ExtractorFactoryTest, ExtractorFactoryApiTest) {
string inputMime = GetParam().second;
string inputFileName = gEnv->getRes() + GetParam().first;
MediaExtractorFactory::LoadExtractors();
bool createMode[] = {true, false};
for (bool createFromService : createMode) {
int32_t status = createDataSource(inputFileName);
ASSERT_EQ(status, 0) << "create data source failed";
status = createExtractor(createFromService, inputMime);
ASSERT_EQ(status, 0) << "Extractor creation failed for input: " << inputFileName;
int32_t numTracks = mExtractor->countTracks();
ASSERT_GT(numTracks, 0) << "Extractor didn't find any track for the given clip";
sp<MetaData> meta = mExtractor->getMetaData();
ASSERT_NE(meta, nullptr) << "getMetaData returned null";
const char *mime;
bool valueFound = meta->findCString(kKeyMIMEType, &mime);
ASSERT_TRUE(valueFound) << "Extractor did not provide MIME type";
ASSERT_EQ(mime, inputMime) << "Extractor factory returned invalid mime type";
mExtractor.clear();
mDataSource.clear();
}
}
// TODO: (b/150111966)
// Replace mime strings with appropriate definitions
INSTANTIATE_TEST_SUITE_P(
ExtractorFactoryTestAll, ExtractorFactoryTest,
::testing::Values(make_pair("loudsoftaac.aac", MEDIA_MIMETYPE_AUDIO_AAC_ADTS),
make_pair("testamr.amr", "audio/amr"),
make_pair("amrwb.wav", MEDIA_MIMETYPE_AUDIO_AMR_WB),
make_pair("john_cage.ogg", MEDIA_MIMETYPE_CONTAINER_OGG),
make_pair("monotestgsm.wav", MEDIA_MIMETYPE_CONTAINER_WAV),
make_pair("segment000001.ts", MEDIA_MIMETYPE_CONTAINER_MPEG2TS),
make_pair("sinesweepflac.flac", MEDIA_MIMETYPE_AUDIO_FLAC),
make_pair("testopus.opus", MEDIA_MIMETYPE_CONTAINER_OGG),
make_pair("midi_a.mid", MEDIA_MIMETYPE_AUDIO_MIDI),
make_pair("sinesweepvorbis.mkv", MEDIA_MIMETYPE_CONTAINER_MATROSKA),
make_pair("sinesweepoggmp4.mp4", "audio/mp4"),
make_pair("sinesweepmp3lame.mp3", MEDIA_MIMETYPE_AUDIO_MPEG),
make_pair("swirl_144x136_vp9.webm", "video/webm"),
make_pair("swirl_144x136_vp8.webm", "video/webm"),
make_pair("swirl_132x130_mpeg4.mp4", MEDIA_MIMETYPE_CONTAINER_MPEG4)));
int main(int argc, char **argv) {
ProcessState::self()->startThreadPool();
gEnv = new ExtractorFactoryTestEnvironment();
::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,72 @@
/*
* Copyright (C) 2020 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 __EXTRACTOR_FACTORY_TEST_ENVIRONMENT_H__
#define __EXTRACTOR_FACTORY_TEST_ENVIRONMENT_H__
#include <gtest/gtest.h>
#include <getopt.h>
using namespace std;
class ExtractorFactoryTestEnvironment : public ::testing::Environment {
public:
ExtractorFactoryTestEnvironment() : 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 ExtractorFactoryTestEnvironment::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 // __EXTRACTOR_FACTORY_TEST_ENVIRONMENT_H__

@ -0,0 +1,37 @@
## Media Testing ##
---
#### Writer :
The Writer Test Suite validates the writers available in libstagefright.
Run the following steps to build the test suite:
```
mmm frameworks/av/media/libstagefright/tests/writer/
```
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/ExtractorFactoryTest/ExtractorFactoryTest /data/local/tmp/
To test 32-bit binary push binaries from nativetest.
adb push ${OUT}/data/nativetest/ExtractorFactoryTest/ExtractorFactoryTest /data/local/tmp/
The resource file for the tests is taken from [here](https://storage.googleapis.com/android_media/frameworks/av/media/extractors/tests/extractor.zip).
Download, unzip and push these files into device for testing.
```
adb push extractor /data/local/tmp/
```
usage: ExtractorFactoryTest -P \<path_to_res_folder\>
```
adb shell /data/local/tmp/ExtractorFactoryTest -P /data/local/tmp/extractor/
```
Alternatively, the test can also be run using atest command.
```
atest ExtractorFactoryTest -- --enable-module-dynamic-download=true
```
Loading…
Cancel
Save