236 lines
8.8 KiB
C++
236 lines
8.8 KiB
C++
/*
|
|
* 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 "Mpeg2tsUnitTest"
|
|
|
|
#include <utils/Log.h>
|
|
|
|
#include <stdint.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include <datasource/FileSource.h>
|
|
#include <media/stagefright/MediaDefs.h>
|
|
#include <media/stagefright/MetaDataBase.h>
|
|
#include <media/stagefright/foundation/AUtils.h>
|
|
#include <mpeg2ts/AnotherPacketSource.h>
|
|
#include <mpeg2ts/ATSParser.h>
|
|
|
|
#include "Mpeg2tsUnitTestEnvironment.h"
|
|
|
|
constexpr size_t kTSPacketSize = 188;
|
|
constexpr uint16_t kPIDMask = 0x1FFF;
|
|
// Max value of PID which is also used for Null packets
|
|
constexpr uint16_t kPIDMaxValue = 8191;
|
|
constexpr uint8_t kTSSyncByte = 0x47;
|
|
constexpr uint8_t kVideoPresent = 0x01;
|
|
constexpr uint8_t kAudioPresent = 0x02;
|
|
constexpr uint8_t kMetaDataPresent = 0x04;
|
|
|
|
static Mpeg2tsUnitTestEnvironment *gEnv = nullptr;
|
|
|
|
using namespace android;
|
|
|
|
class Mpeg2tsUnitTest
|
|
: public ::testing ::TestWithParam<
|
|
tuple</*fileName*/ string, /*sourceType*/ char, /*numSource*/ uint16_t>> {
|
|
public:
|
|
Mpeg2tsUnitTest()
|
|
: mInputBuffer(nullptr), mSource(nullptr), mFpInput(nullptr), mParser(nullptr) {}
|
|
|
|
~Mpeg2tsUnitTest() {
|
|
if (mInputBuffer) free(mInputBuffer);
|
|
if (mFpInput) fclose(mFpInput);
|
|
mSource.clear();
|
|
}
|
|
|
|
void SetUp() override {
|
|
mOffset = 0;
|
|
mNumDataSource = 0;
|
|
tuple<string, char, uint16_t> params = GetParam();
|
|
char sourceType = get<1>(params);
|
|
/* mSourceType = 0b x x x x x M A V
|
|
/ | \
|
|
metaData audio video */
|
|
mMediaType = (sourceType & 0x07);
|
|
mNumDataSource = get<2>(params);
|
|
string inputFile = gEnv->getRes() + get<0>(params);
|
|
mFpInput = fopen(inputFile.c_str(), "rb");
|
|
ASSERT_NE(mFpInput, nullptr) << "Failed to open file: " << inputFile;
|
|
|
|
struct stat buf;
|
|
int8_t err = stat(inputFile.c_str(), &buf);
|
|
ASSERT_EQ(err, 0) << "Failed to get information for file: " << inputFile;
|
|
|
|
long fileSize = buf.st_size;
|
|
mTotalPackets = fileSize / kTSPacketSize;
|
|
int32_t fd = fileno(mFpInput);
|
|
ASSERT_GE(fd, 0) << "Failed to get the integer file descriptor";
|
|
|
|
mSource = new FileSource(dup(fd), 0, buf.st_size);
|
|
ASSERT_NE(mSource, nullptr) << "Failed to get the data source!";
|
|
|
|
mParser = new ATSParser();
|
|
ASSERT_NE(mParser, nullptr) << "Unable to create ATS parser!";
|
|
mInputBuffer = (uint8_t *)malloc(kTSPacketSize);
|
|
ASSERT_NE(mInputBuffer, nullptr) << "Failed to allocate memory for TS packet!";
|
|
}
|
|
|
|
uint64_t mOffset;
|
|
uint64_t mTotalPackets;
|
|
uint16_t mNumDataSource;
|
|
|
|
int8_t mMediaType;
|
|
|
|
uint8_t *mInputBuffer;
|
|
string mInputFile;
|
|
sp<DataSource> mSource;
|
|
FILE *mFpInput;
|
|
ATSParser *mParser;
|
|
};
|
|
|
|
TEST_P(Mpeg2tsUnitTest, MediaInfoTest) {
|
|
bool videoFound = false;
|
|
bool audioFound = false;
|
|
bool metaDataFound = false;
|
|
bool syncPointPresent = false;
|
|
|
|
int16_t totalDataSource = 0;
|
|
int32_t val32 = 0;
|
|
uint8_t numDataSource = 0;
|
|
uint8_t packet[kTSPacketSize];
|
|
ssize_t numBytesRead = -1;
|
|
|
|
ATSParser::SyncEvent event(mOffset);
|
|
static const ATSParser::SourceType mediaType[] = {ATSParser::VIDEO, ATSParser::AUDIO,
|
|
ATSParser::META, ATSParser::NUM_SOURCE_TYPES};
|
|
const uint32_t nMediaTypes = sizeof(mediaType) / sizeof(mediaType[0]);
|
|
|
|
while ((numBytesRead = mSource->readAt(mOffset, packet, kTSPacketSize)) == kTSPacketSize) {
|
|
ASSERT_TRUE(packet[0] == kTSSyncByte) << "Sync byte error!";
|
|
|
|
// pid is 13 bits
|
|
uint16_t pid = (packet[1] + (packet[2] << 8)) & kPIDMask;
|
|
ASSERT_TRUE(pid <= kPIDMaxValue) << "Invalid PID: " << pid;
|
|
|
|
status_t err = mParser->feedTSPacket(packet, kTSPacketSize, &event);
|
|
ASSERT_EQ(err, (status_t)OK) << "Unable to feed TS packet!";
|
|
|
|
mOffset += numBytesRead;
|
|
for (int i = 0; i < nMediaTypes; i++) {
|
|
if (mParser->hasSource(mediaType[i])) {
|
|
switch (mediaType[i]) {
|
|
case ATSParser::VIDEO:
|
|
videoFound = true;
|
|
break;
|
|
case ATSParser::AUDIO:
|
|
audioFound = true;
|
|
break;
|
|
case ATSParser::META:
|
|
metaDataFound = true;
|
|
break;
|
|
case ATSParser::NUM_SOURCE_TYPES:
|
|
numDataSource = 3;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (videoFound && audioFound && metaDataFound && (numDataSource == 3)) break;
|
|
}
|
|
|
|
for (int i = 0; i < nMediaTypes; i++) {
|
|
ATSParser::SourceType currentMediaType = mediaType[i];
|
|
if (mParser->hasSource(currentMediaType)) {
|
|
if (event.hasReturnedData()) {
|
|
syncPointPresent = true;
|
|
sp<AnotherPacketSource> syncPacketSource = event.getMediaSource();
|
|
ASSERT_NE(syncPacketSource, nullptr)
|
|
<< "Cannot get sync source for media type: " << currentMediaType;
|
|
|
|
status_t err = syncPacketSource->start();
|
|
ASSERT_EQ(err, (status_t)OK) << "Error returned while starting!";
|
|
|
|
sp<MetaData> format = syncPacketSource->getFormat();
|
|
ASSERT_NE(format, nullptr) << "Unable to get the format of the source packet!";
|
|
|
|
MediaBufferBase *buf;
|
|
syncPacketSource->read(&buf, nullptr);
|
|
ASSERT_NE(buf, nullptr) << "Failed to read sync packet source data";
|
|
|
|
MetaDataBase &inMeta = buf->meta_data();
|
|
bool status = inMeta.findInt32(kKeyIsSyncFrame, &val32);
|
|
ASSERT_EQ(status, true) << "Sync frame key is not set";
|
|
|
|
status = inMeta.findInt32(kKeyCryptoMode, &val32);
|
|
ASSERT_EQ(status, false) << "Invalid packet, found scrambled packets!";
|
|
|
|
err = syncPacketSource->stop();
|
|
ASSERT_EQ(err, (status_t)OK) << "Error returned while stopping!";
|
|
}
|
|
sp<AnotherPacketSource> packetSource = mParser->getSource(currentMediaType);
|
|
ASSERT_NE(packetSource, nullptr)
|
|
<< "Cannot get source for media type: " << currentMediaType;
|
|
|
|
status_t err = packetSource->start();
|
|
ASSERT_EQ(err, (status_t)OK) << "Error returned while starting!";
|
|
sp<MetaData> format = packetSource->getFormat();
|
|
ASSERT_NE(format, nullptr) << "Unable to get the format of the packet!";
|
|
|
|
err = packetSource->stop();
|
|
ASSERT_EQ(err, (status_t)OK) << "Error returned while stopping!";
|
|
}
|
|
}
|
|
|
|
ASSERT_EQ(videoFound, bool(mMediaType & kVideoPresent)) << "No Video packets found!";
|
|
ASSERT_EQ(audioFound, bool(mMediaType & kAudioPresent)) << "No Audio packets found!";
|
|
ASSERT_EQ(metaDataFound, bool(mMediaType & kMetaDataPresent)) << "No meta data found!";
|
|
|
|
if (videoFound || audioFound) {
|
|
ASSERT_TRUE(syncPointPresent) << "No sync points found for audio/video";
|
|
}
|
|
|
|
if (videoFound) totalDataSource += 1;
|
|
if (audioFound) totalDataSource += 1;
|
|
if (metaDataFound) totalDataSource += 1;
|
|
|
|
ASSERT_TRUE(totalDataSource == mNumDataSource)
|
|
<< "Expected " << mNumDataSource << " data sources, found " << totalDataSource;
|
|
if (numDataSource == 3) {
|
|
ASSERT_EQ(numDataSource, mNumDataSource)
|
|
<< "Expected " << mNumDataSource << " data sources, found " << totalDataSource;
|
|
}
|
|
}
|
|
|
|
INSTANTIATE_TEST_SUITE_P(
|
|
infoTest, Mpeg2tsUnitTest,
|
|
::testing::Values(make_tuple("crowd_1920x1080_25fps_6700kbps_h264.ts", 0x01, 1),
|
|
make_tuple("segment000001.ts", 0x03, 2),
|
|
make_tuple("bbb_44100hz_2ch_128kbps_mp3_5mins.ts", 0x02, 1)));
|
|
|
|
int32_t main(int argc, char **argv) {
|
|
gEnv = new Mpeg2tsUnitTestEnvironment();
|
|
::testing::AddGlobalTestEnvironment(gEnv);
|
|
::testing::InitGoogleTest(&argc, argv);
|
|
uint8_t status = gEnv->initFromOptions(argc, argv);
|
|
if (status == 0) {
|
|
status = RUN_ALL_TESTS();
|
|
ALOGV("Mpeg2tsUnit Test Result = %d\n", status);
|
|
}
|
|
return status;
|
|
}
|