blob: 33bdcac04a65dfe65a19dcce86e48bf9b6f5ae89 [file] [log] [blame]
/*
* 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 "ESDSTest"
#include <utils/Log.h>
#include <stdio.h>
#include <string.h>
#include <fstream>
#include <memory>
#include <media/esds/ESDS.h>
#include <binder/ProcessState.h>
#include <datasource/FileSource.h>
#include <media/stagefright/MediaExtractorFactory.h>
#include <media/stagefright/MetaData.h>
#include "ESDSTestEnvironment.h"
using namespace android;
static ESDSTestEnvironment *gEnv = nullptr;
struct ESDSParams {
const char *inputFile;
int32_t objectTypeIndication;
const char *codecSpecificInfoData;
int32_t codecSpecificInfoDataSize;
int32_t bitrateMax;
int32_t bitrateAvg;
};
class ESDSUnitTest : public ::testing::TestWithParam<tuple<
/* InputFile */ const char *,
/* ObjectTypeIndication */ int32_t,
/* CodecSpecificInfoData */ const char *,
/* CodecSpecificInfoDataSize */ int32_t,
/* BitrateMax */ int32_t,
/* BitrateAvg */ int32_t>> {
public:
ESDSUnitTest() : mESDSData(nullptr) {
mESDSParams.inputFile = get<0>(GetParam());
mESDSParams.objectTypeIndication = get<1>(GetParam());
mESDSParams.codecSpecificInfoData = get<2>(GetParam());
mESDSParams.codecSpecificInfoDataSize = get<3>(GetParam());
mESDSParams.bitrateMax = get<4>(GetParam());
mESDSParams.bitrateAvg = get<5>(GetParam());
};
virtual void TearDown() override {
if (mDataSource) mDataSource.clear();
if (mInputFp) {
fclose(mInputFp);
mInputFp = nullptr;
}
}
virtual void SetUp() override { ASSERT_NO_FATAL_FAILURE(readESDSData()); }
const void *mESDSData;
size_t mESDSSize;
ESDSParams mESDSParams;
private:
void readESDSData() {
string inputFile = gEnv->getRes() + mESDSParams.inputFile;
mInputFp = fopen(inputFile.c_str(), "rb");
ASSERT_NE(mInputFp, nullptr) << "File open failed for file: " << inputFile;
int32_t fd = fileno(mInputFp);
ASSERT_GE(fd, 0) << "File descriptor invalid for file: " << inputFile;
struct stat buf;
status_t status = stat(inputFile.c_str(), &buf);
ASSERT_EQ(status, 0) << "Failed to get properties of input file: " << mESDSParams.inputFile;
size_t fileSize = buf.st_size;
mDataSource = new FileSource(dup(fd), 0, fileSize);
ASSERT_NE(mDataSource, nullptr) << "Unable to create data source for file: " << inputFile;
sp<IMediaExtractor> extractor = MediaExtractorFactory::Create(mDataSource);
if (extractor == nullptr) {
mDataSource.clear();
ASSERT_TRUE(false) << "Unable to create extractor for file: " << inputFile;
}
size_t numTracks = extractor->countTracks();
ASSERT_GT(numTracks, 0) << "No tracks in file: " << inputFile;
ASSERT_TRUE(esdsDataPresent(numTracks, extractor))
<< "Unable to find esds in any track in file: " << inputFile;
}
bool esdsDataPresent(size_t numTracks, sp<IMediaExtractor> extractor) {
bool foundESDS = false;
uint32_t type;
for (size_t i = 0; i < numTracks; ++i) {
sp<MetaData> trackMeta = extractor->getTrackMetaData(i);
if (trackMeta != nullptr &&
trackMeta->findData(kKeyESDS, &type, &mESDSData, &mESDSSize)) {
trackMeta->clear();
foundESDS = true;
break;
}
}
return foundESDS;
}
FILE *mInputFp;
sp<DataSource> mDataSource;
};
TEST_P(ESDSUnitTest, InvalidDataTest) {
std::unique_ptr<char[]> invalidData(new char[mESDSSize]());
ASSERT_NE(invalidData, nullptr) << "Unable to allocate memory";
ESDS esds((void*)invalidData.get(), mESDSSize);
ASSERT_NE(esds.InitCheck(), OK) << "invalid ESDS data accepted";
}
TEST(ESDSSanityUnitTest, ConstructorSanityTest) {
std::unique_ptr<char[]> invalidData(new char[1]());
ASSERT_NE(invalidData, nullptr) << "Unable to allocate memory";
ESDS esds_zero((void*)invalidData.get(), 0);
ASSERT_NE(esds_zero.InitCheck(), OK) << "invalid ESDS data accepted";
ESDS esds_null(NULL, 0);
ASSERT_NE(esds_null.InitCheck(), OK) << "invalid ESDS data accepted";
}
TEST_P(ESDSUnitTest, CreateAndDestroyTest) {
ESDS esds(mESDSData, mESDSSize);
ASSERT_EQ(esds.InitCheck(), OK) << "ESDS data invalid";
}
TEST_P(ESDSUnitTest, ObjectTypeIndicationTest) {
ESDS esds(mESDSData, mESDSSize);
ASSERT_EQ(esds.InitCheck(), OK) << "ESDS data invalid";
uint8_t objectTypeIndication;
status_t status = esds.getObjectTypeIndication(&objectTypeIndication);
ASSERT_EQ(status, OK) << "ESDS objectTypeIndication data invalid";
ASSERT_EQ(objectTypeIndication, mESDSParams.objectTypeIndication)
<< "ESDS objectTypeIndication data doesn't match";
}
TEST_P(ESDSUnitTest, CodecSpecificInfoTest) {
ESDS esds(mESDSData, mESDSSize);
ASSERT_EQ(esds.InitCheck(), OK) << "ESDS data invalid";
status_t status;
const void *codecSpecificInfo;
size_t codecSpecificInfoSize;
status = esds.getCodecSpecificInfo(&codecSpecificInfo, &codecSpecificInfoSize);
ASSERT_EQ(status, OK) << "ESDS getCodecSpecificInfo data invalid";
ASSERT_EQ(mESDSParams.codecSpecificInfoDataSize, codecSpecificInfoSize)
<< "CodecSpecificInfo data doesn't match";
status = memcmp(codecSpecificInfo, mESDSParams.codecSpecificInfoData, codecSpecificInfoSize);
ASSERT_EQ(status, 0) << "CodecSpecificInfo data doesn't match";
}
TEST_P(ESDSUnitTest, GetBitrateTest) {
ESDS esds(mESDSData, mESDSSize);
ASSERT_EQ(esds.InitCheck(), OK) << "ESDS data invalid";
uint32_t bitrateMax;
uint32_t bitrateAvg;
status_t status = esds.getBitRate(&bitrateMax, &bitrateAvg);
ASSERT_EQ(status, OK) << "ESDS bitRate data invalid";
ASSERT_EQ(bitrateMax, mESDSParams.bitrateMax) << "ESDS bitrateMax doesn't match";
ASSERT_EQ(bitrateAvg, mESDSParams.bitrateAvg) << "ESDS bitrateAvg doesn't match";
ASSERT_LE(bitrateAvg, bitrateMax) << "ESDS bitrateMax is less than bitrateAvg";
}
INSTANTIATE_TEST_SUITE_P(
ESDSUnitTestAll, ESDSUnitTest,
::testing::Values(
// InputFile, ObjectTypeIndication, CodecSpecificInfoData,
// CodecSpecificInfoDataSize, BitrateMax, BitrateAvg
make_tuple("video_176x144_3gp_h263_56kbps_12fps_aac_stereo_128kbps_22050hz.3gp", 64,
"\x13\x90", 2, 131072, 0),
make_tuple("video_1280x720_mp4_mpeg2_3000kbps_30fps_aac_stereo_128kbps_48000hz.mp4",
97,
"\x00\x00\x01\xB3\x50\x02\xD0\x35\xFF\xFF\xE1\xA0\x00\x00\x01\xB5\x15"
"\x6A\x00\x01\x00\x00",
22, 3415452, 3415452),
make_tuple("video_176x144_3gp_h263_56kbps_25fps_aac_mono_24kbps_11025hz.3gp", 64,
"\x15\x08", 2, 24576, 0)));
int main(int argc, char **argv) {
// MediaExtractor needs binder thread pool
ProcessState::self()->startThreadPool();
gEnv = new ESDSTestEnvironment();
::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;
}