Loading media/libstagefright/tests/writer/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ cc_test { "libcutils", "liblog", "libutils", "libmedia", ], static_libs: [ Loading media/libstagefright/tests/writer/WriterListener.h 0 → 100644 +45 −0 Original line number Diff line number Diff line /* * 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 WRITER_LISTENER_H_ #define WRITER_LISTENER_H_ #include <mutex> #include <media/IMediaRecorderClient.h> #include <media/mediarecorder.h> using namespace android; using namespace std; class WriterListener : public BnMediaRecorderClient { public: WriterListener() : mSignaledSize(false), mSignaledDuration(false) {} virtual void notify(int32_t msg, int32_t ext1, int32_t ext2) { ALOGV("msg : %d, ext1 : %d, ext2 : %d", msg, ext1, ext2); if (ext1 == MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED) { mSignaledSize = true; } else if (ext1 == MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) { mSignaledDuration = true; } } volatile bool mSignaledSize; volatile bool mSignaledDuration; }; #endif // WRITER_LISTENER_H_ media/libstagefright/tests/writer/WriterTest.cpp +123 −18 Original line number Diff line number Diff line Loading @@ -87,36 +87,37 @@ static const struct InputData { "bbb_mpeg4_352x288_512kbps_30fps.info", 352, 288, false}, }; class WriterTest : public ::testing::TestWithParam<pair<string, int32_t>> { class WriterTest { public: WriterTest() : mWriter(nullptr), mFileMeta(nullptr), mCurrentTrack(nullptr) {} ~WriterTest() { if (mWriter) { mWriter.clear(); mWriter = nullptr; } if (mFileMeta) { mFileMeta.clear(); mFileMeta = nullptr; } if (mCurrentTrack) { mCurrentTrack->stop(); mCurrentTrack.clear(); mCurrentTrack = nullptr; } if (mWriter) { mWriter.clear(); mWriter = nullptr; } mBufferInfo.clear(); if (mInputStream.is_open()) mInputStream.close(); } virtual void SetUp() override { void setupWriterType(string writerFormat) { mNumCsds = 0; mInputFrameId = 0; mWriterName = unknown_comp; mDisableTest = false; static const std::map<std::string, standardWriters> mapWriter = { {"ogg", OGG}, {"aac", AAC}, {"aac_adts", AAC_ADTS}, {"webm", WEBM}, {"mpeg4", MPEG4}, {"amrnb", AMR_NB}, {"amrwb", AMR_WB}, {"mpeg2Ts", MPEG2TS}}; // Find the component type string writerFormat = GetParam().first; if (mapWriter.find(writerFormat) != mapWriter.end()) { mWriterName = mapWriter.at(writerFormat); } Loading @@ -126,11 +127,6 @@ class WriterTest : public ::testing::TestWithParam<pair<string, int32_t>> { } } virtual void TearDown() override { mBufferInfo.clear(); if (mInputStream.is_open()) mInputStream.close(); } void getInputBufferInfo(string inputFileName, string inputInfo); int32_t createWriter(int32_t fd); Loading Loading @@ -161,6 +157,12 @@ class WriterTest : public ::testing::TestWithParam<pair<string, int32_t>> { vector<BufferInfo> mBufferInfo; }; class WriteFunctionalityTest : public WriterTest, public ::testing::TestWithParam<pair<string, int32_t>> { public: virtual void SetUp() override { setupWriterType(GetParam().first); } }; void WriterTest::getInputBufferInfo(string inputFileName, string inputInfo) { std::ifstream eleInfo; eleInfo.open(inputInfo.c_str()); Loading Loading @@ -270,7 +272,7 @@ void getFileDetails(string &inputFilePath, string &info, configFormat ¶ms, b return; } TEST_P(WriterTest, CreateWriterTest) { TEST_P(WriteFunctionalityTest, CreateWriterTest) { if (mDisableTest) return; ALOGV("Tests the creation of writers"); Loading @@ -284,7 +286,7 @@ TEST_P(WriterTest, CreateWriterTest) { << "Failed to create writer for output format:" << GetParam().first; } TEST_P(WriterTest, WriterTest) { TEST_P(WriteFunctionalityTest, WriterTest) { if (mDisableTest) return; ALOGV("Checks if for a given input, a valid muxed file has been created or not"); Loading Loading @@ -321,7 +323,7 @@ TEST_P(WriterTest, WriterTest) { close(fd); } TEST_P(WriterTest, PauseWriterTest) { TEST_P(WriteFunctionalityTest, PauseWriterTest) { if (mDisableTest) return; ALOGV("Validates the pause() api of writers"); Loading Loading @@ -378,7 +380,7 @@ TEST_P(WriterTest, PauseWriterTest) { close(fd); } TEST_P(WriterTest, MultiStartStopPauseTest) { TEST_P(WriteFunctionalityTest, MultiStartStopPauseTest) { // TODO: (b/144821804) // Enable the test for MPE2TS writer if (mDisableTest || mWriterName == standardWriters::MPEG2TS) return; Loading Loading @@ -451,9 +453,112 @@ TEST_P(WriterTest, MultiStartStopPauseTest) { close(fd); } class ListenerTest : public WriterTest, public ::testing::TestWithParam< tuple<string /* writerFormat*/, int32_t /* inputFileIdx*/, float /* FileSizeLimit*/, float /* FileDurationLimit*/>> { public: virtual void SetUp() override { tuple<string, int32_t, float, float> params = GetParam(); setupWriterType(get<0>(params)); } }; TEST_P(ListenerTest, SetMaxFileLimitsTest) { if (mDisableTest) return; ALOGV("Validates writer when max file limits are set"); tuple<string, int32_t, float, float> params = GetParam(); string writerFormat = get<0>(params); string outputFile = OUTPUT_FILE_NAME; int32_t fd = open(outputFile.c_str(), O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR); ASSERT_GE(fd, 0) << "Failed to open output file to dump writer's data"; int32_t status = createWriter(fd); ASSERT_EQ((status_t)OK, status) << "Failed to create writer for output format:" << writerFormat; string inputFile = gEnv->getRes(); string inputInfo = gEnv->getRes(); configFormat param; bool isAudio; int32_t inputFileIdx = get<1>(params); getFileDetails(inputFile, inputInfo, param, isAudio, inputFileIdx); ASSERT_NE(inputFile.compare(gEnv->getRes()), 0) << "No input file specified"; ASSERT_NO_FATAL_FAILURE(getInputBufferInfo(inputFile, inputInfo)); status = addWriterSource(isAudio, param); ASSERT_EQ((status_t)OK, status) << "Failed to add source for " << writerFormat << "Writer"; // Read file properties struct stat buf; status = stat(inputFile.c_str(), &buf); ASSERT_EQ(0, status); float fileSizeLimit = get<2>(params); float fileDurationLimit = get<3>(params); int64_t maxFileSize = 0; int64_t maxFileDuration = 0; size_t inputFileSize = buf.st_size; int64_t lastFrameTimeStampUs = mBufferInfo[mBufferInfo.size() - 1].timeUs; if (fileSizeLimit > 0) { maxFileSize = (int64_t)(fileSizeLimit * inputFileSize); mWriter->setMaxFileSize(maxFileSize); } if (fileDurationLimit > 0) { maxFileDuration = (int64_t)(fileDurationLimit * lastFrameTimeStampUs); mWriter->setMaxFileDuration(maxFileDuration); } sp<WriterListener> listener = new WriterListener(); ASSERT_NE(listener, nullptr) << "unable to allocate listener"; mWriter->setListener(listener); status = mWriter->start(mFileMeta.get()); ASSERT_EQ((status_t)OK, status); status = sendBuffersToWriter(mInputStream, mBufferInfo, mInputFrameId, mCurrentTrack, 0, mBufferInfo.size(), false, listener); ASSERT_EQ((status_t)OK, status) << writerFormat << " writer failed"; ASSERT_TRUE(mWriter->reachedEOS()) << "EOS not signalled."; mCurrentTrack->stop(); status = mWriter->stop(); ASSERT_EQ((status_t)OK, status) << "Failed to stop the writer"; close(fd); if (maxFileSize <= 0) { ASSERT_FALSE(listener->mSignaledSize); } else if (maxFileDuration <= 0) { ASSERT_FALSE(listener->mSignaledDuration); } else if (maxFileSize > 0 && maxFileDuration <= 0) { ASSERT_TRUE(listener->mSignaledSize); } else if (maxFileDuration > 0 && maxFileSize <= 0) { ASSERT_TRUE(listener->mSignaledDuration); } else { ASSERT_TRUE(listener->mSignaledSize || listener->mSignaledDuration); } if (maxFileSize > 0) { struct stat buf; status = stat(outputFile.c_str(), &buf); ASSERT_EQ(0, status); ASSERT_LE(buf.st_size, maxFileSize); } } // TODO: (b/150923387) // Add WEBM input INSTANTIATE_TEST_SUITE_P( ListenerTestAll, ListenerTest, ::testing::Values(make_tuple("ogg", 0, 0.7, 0.3), make_tuple("aac", 1, 0.6, 0.7), make_tuple("mpeg4", 1, 0.4, 0.3), make_tuple("amrnb", 3, 0.2, 0.6), make_tuple("amrwb", 4, 0.5, 0.5), make_tuple("mpeg2Ts", 1, 0.2, 1))); // TODO: (b/144476164) // Add AAC_ADTS, FLAC, AV1 input INSTANTIATE_TEST_SUITE_P(WriterTestAll, WriterTest, INSTANTIATE_TEST_SUITE_P(WriterTestAll, WriteFunctionalityTest, ::testing::Values(make_pair("ogg", 0), make_pair("webm", 0), make_pair("aac", 1), make_pair("mpeg4", 1), make_pair("amrnb", 3), make_pair("amrwb", 4), Loading media/libstagefright/tests/writer/WriterUtility.cpp +8 −1 Original line number Diff line number Diff line Loading @@ -24,9 +24,16 @@ int32_t sendBuffersToWriter(ifstream &inputStream, vector<BufferInfo> &bufferInfo, int32_t &inputFrameId, sp<MediaAdapter> ¤tTrack, int32_t offset, int32_t range, bool isPaused) { int32_t range, bool isPaused, sp<WriterListener> listener) { while (1) { if (inputFrameId >= (int)bufferInfo.size() || inputFrameId >= (offset + range)) break; if (listener != nullptr) { if (listener->mSignaledDuration || listener->mSignaledSize) { ALOGV("Max File limit reached. No more buffers will be sent to the writer"); break; } } int32_t size = bufferInfo[inputFrameId].size; char *data = (char *)malloc(size); if (!data) { Loading media/libstagefright/tests/writer/WriterUtility.h +3 −3 Original line number Diff line number Diff line Loading @@ -27,8 +27,7 @@ #include <media/stagefright/MediaAdapter.h> using namespace android; using namespace std; #include "WriterListener.h" #define CODEC_CONFIG_FLAG 32 Loading @@ -43,7 +42,8 @@ struct BufferInfo { int32_t sendBuffersToWriter(ifstream &inputStream, vector<BufferInfo> &bufferInfo, int32_t &inputFrameId, sp<MediaAdapter> ¤tTrack, int32_t offset, int32_t range, bool isPaused = false); int32_t range, bool isPaused = false, sp<WriterListener> listener = nullptr); int32_t writeHeaderBuffers(ifstream &inputStream, vector<BufferInfo> &bufferInfo, int32_t &inputFrameId, sp<AMessage> &format, int32_t numCsds); Loading Loading
media/libstagefright/tests/writer/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ cc_test { "libcutils", "liblog", "libutils", "libmedia", ], static_libs: [ Loading
media/libstagefright/tests/writer/WriterListener.h 0 → 100644 +45 −0 Original line number Diff line number Diff line /* * 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 WRITER_LISTENER_H_ #define WRITER_LISTENER_H_ #include <mutex> #include <media/IMediaRecorderClient.h> #include <media/mediarecorder.h> using namespace android; using namespace std; class WriterListener : public BnMediaRecorderClient { public: WriterListener() : mSignaledSize(false), mSignaledDuration(false) {} virtual void notify(int32_t msg, int32_t ext1, int32_t ext2) { ALOGV("msg : %d, ext1 : %d, ext2 : %d", msg, ext1, ext2); if (ext1 == MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED) { mSignaledSize = true; } else if (ext1 == MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) { mSignaledDuration = true; } } volatile bool mSignaledSize; volatile bool mSignaledDuration; }; #endif // WRITER_LISTENER_H_
media/libstagefright/tests/writer/WriterTest.cpp +123 −18 Original line number Diff line number Diff line Loading @@ -87,36 +87,37 @@ static const struct InputData { "bbb_mpeg4_352x288_512kbps_30fps.info", 352, 288, false}, }; class WriterTest : public ::testing::TestWithParam<pair<string, int32_t>> { class WriterTest { public: WriterTest() : mWriter(nullptr), mFileMeta(nullptr), mCurrentTrack(nullptr) {} ~WriterTest() { if (mWriter) { mWriter.clear(); mWriter = nullptr; } if (mFileMeta) { mFileMeta.clear(); mFileMeta = nullptr; } if (mCurrentTrack) { mCurrentTrack->stop(); mCurrentTrack.clear(); mCurrentTrack = nullptr; } if (mWriter) { mWriter.clear(); mWriter = nullptr; } mBufferInfo.clear(); if (mInputStream.is_open()) mInputStream.close(); } virtual void SetUp() override { void setupWriterType(string writerFormat) { mNumCsds = 0; mInputFrameId = 0; mWriterName = unknown_comp; mDisableTest = false; static const std::map<std::string, standardWriters> mapWriter = { {"ogg", OGG}, {"aac", AAC}, {"aac_adts", AAC_ADTS}, {"webm", WEBM}, {"mpeg4", MPEG4}, {"amrnb", AMR_NB}, {"amrwb", AMR_WB}, {"mpeg2Ts", MPEG2TS}}; // Find the component type string writerFormat = GetParam().first; if (mapWriter.find(writerFormat) != mapWriter.end()) { mWriterName = mapWriter.at(writerFormat); } Loading @@ -126,11 +127,6 @@ class WriterTest : public ::testing::TestWithParam<pair<string, int32_t>> { } } virtual void TearDown() override { mBufferInfo.clear(); if (mInputStream.is_open()) mInputStream.close(); } void getInputBufferInfo(string inputFileName, string inputInfo); int32_t createWriter(int32_t fd); Loading Loading @@ -161,6 +157,12 @@ class WriterTest : public ::testing::TestWithParam<pair<string, int32_t>> { vector<BufferInfo> mBufferInfo; }; class WriteFunctionalityTest : public WriterTest, public ::testing::TestWithParam<pair<string, int32_t>> { public: virtual void SetUp() override { setupWriterType(GetParam().first); } }; void WriterTest::getInputBufferInfo(string inputFileName, string inputInfo) { std::ifstream eleInfo; eleInfo.open(inputInfo.c_str()); Loading Loading @@ -270,7 +272,7 @@ void getFileDetails(string &inputFilePath, string &info, configFormat ¶ms, b return; } TEST_P(WriterTest, CreateWriterTest) { TEST_P(WriteFunctionalityTest, CreateWriterTest) { if (mDisableTest) return; ALOGV("Tests the creation of writers"); Loading @@ -284,7 +286,7 @@ TEST_P(WriterTest, CreateWriterTest) { << "Failed to create writer for output format:" << GetParam().first; } TEST_P(WriterTest, WriterTest) { TEST_P(WriteFunctionalityTest, WriterTest) { if (mDisableTest) return; ALOGV("Checks if for a given input, a valid muxed file has been created or not"); Loading Loading @@ -321,7 +323,7 @@ TEST_P(WriterTest, WriterTest) { close(fd); } TEST_P(WriterTest, PauseWriterTest) { TEST_P(WriteFunctionalityTest, PauseWriterTest) { if (mDisableTest) return; ALOGV("Validates the pause() api of writers"); Loading Loading @@ -378,7 +380,7 @@ TEST_P(WriterTest, PauseWriterTest) { close(fd); } TEST_P(WriterTest, MultiStartStopPauseTest) { TEST_P(WriteFunctionalityTest, MultiStartStopPauseTest) { // TODO: (b/144821804) // Enable the test for MPE2TS writer if (mDisableTest || mWriterName == standardWriters::MPEG2TS) return; Loading Loading @@ -451,9 +453,112 @@ TEST_P(WriterTest, MultiStartStopPauseTest) { close(fd); } class ListenerTest : public WriterTest, public ::testing::TestWithParam< tuple<string /* writerFormat*/, int32_t /* inputFileIdx*/, float /* FileSizeLimit*/, float /* FileDurationLimit*/>> { public: virtual void SetUp() override { tuple<string, int32_t, float, float> params = GetParam(); setupWriterType(get<0>(params)); } }; TEST_P(ListenerTest, SetMaxFileLimitsTest) { if (mDisableTest) return; ALOGV("Validates writer when max file limits are set"); tuple<string, int32_t, float, float> params = GetParam(); string writerFormat = get<0>(params); string outputFile = OUTPUT_FILE_NAME; int32_t fd = open(outputFile.c_str(), O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR); ASSERT_GE(fd, 0) << "Failed to open output file to dump writer's data"; int32_t status = createWriter(fd); ASSERT_EQ((status_t)OK, status) << "Failed to create writer for output format:" << writerFormat; string inputFile = gEnv->getRes(); string inputInfo = gEnv->getRes(); configFormat param; bool isAudio; int32_t inputFileIdx = get<1>(params); getFileDetails(inputFile, inputInfo, param, isAudio, inputFileIdx); ASSERT_NE(inputFile.compare(gEnv->getRes()), 0) << "No input file specified"; ASSERT_NO_FATAL_FAILURE(getInputBufferInfo(inputFile, inputInfo)); status = addWriterSource(isAudio, param); ASSERT_EQ((status_t)OK, status) << "Failed to add source for " << writerFormat << "Writer"; // Read file properties struct stat buf; status = stat(inputFile.c_str(), &buf); ASSERT_EQ(0, status); float fileSizeLimit = get<2>(params); float fileDurationLimit = get<3>(params); int64_t maxFileSize = 0; int64_t maxFileDuration = 0; size_t inputFileSize = buf.st_size; int64_t lastFrameTimeStampUs = mBufferInfo[mBufferInfo.size() - 1].timeUs; if (fileSizeLimit > 0) { maxFileSize = (int64_t)(fileSizeLimit * inputFileSize); mWriter->setMaxFileSize(maxFileSize); } if (fileDurationLimit > 0) { maxFileDuration = (int64_t)(fileDurationLimit * lastFrameTimeStampUs); mWriter->setMaxFileDuration(maxFileDuration); } sp<WriterListener> listener = new WriterListener(); ASSERT_NE(listener, nullptr) << "unable to allocate listener"; mWriter->setListener(listener); status = mWriter->start(mFileMeta.get()); ASSERT_EQ((status_t)OK, status); status = sendBuffersToWriter(mInputStream, mBufferInfo, mInputFrameId, mCurrentTrack, 0, mBufferInfo.size(), false, listener); ASSERT_EQ((status_t)OK, status) << writerFormat << " writer failed"; ASSERT_TRUE(mWriter->reachedEOS()) << "EOS not signalled."; mCurrentTrack->stop(); status = mWriter->stop(); ASSERT_EQ((status_t)OK, status) << "Failed to stop the writer"; close(fd); if (maxFileSize <= 0) { ASSERT_FALSE(listener->mSignaledSize); } else if (maxFileDuration <= 0) { ASSERT_FALSE(listener->mSignaledDuration); } else if (maxFileSize > 0 && maxFileDuration <= 0) { ASSERT_TRUE(listener->mSignaledSize); } else if (maxFileDuration > 0 && maxFileSize <= 0) { ASSERT_TRUE(listener->mSignaledDuration); } else { ASSERT_TRUE(listener->mSignaledSize || listener->mSignaledDuration); } if (maxFileSize > 0) { struct stat buf; status = stat(outputFile.c_str(), &buf); ASSERT_EQ(0, status); ASSERT_LE(buf.st_size, maxFileSize); } } // TODO: (b/150923387) // Add WEBM input INSTANTIATE_TEST_SUITE_P( ListenerTestAll, ListenerTest, ::testing::Values(make_tuple("ogg", 0, 0.7, 0.3), make_tuple("aac", 1, 0.6, 0.7), make_tuple("mpeg4", 1, 0.4, 0.3), make_tuple("amrnb", 3, 0.2, 0.6), make_tuple("amrwb", 4, 0.5, 0.5), make_tuple("mpeg2Ts", 1, 0.2, 1))); // TODO: (b/144476164) // Add AAC_ADTS, FLAC, AV1 input INSTANTIATE_TEST_SUITE_P(WriterTestAll, WriterTest, INSTANTIATE_TEST_SUITE_P(WriterTestAll, WriteFunctionalityTest, ::testing::Values(make_pair("ogg", 0), make_pair("webm", 0), make_pair("aac", 1), make_pair("mpeg4", 1), make_pair("amrnb", 3), make_pair("amrwb", 4), Loading
media/libstagefright/tests/writer/WriterUtility.cpp +8 −1 Original line number Diff line number Diff line Loading @@ -24,9 +24,16 @@ int32_t sendBuffersToWriter(ifstream &inputStream, vector<BufferInfo> &bufferInfo, int32_t &inputFrameId, sp<MediaAdapter> ¤tTrack, int32_t offset, int32_t range, bool isPaused) { int32_t range, bool isPaused, sp<WriterListener> listener) { while (1) { if (inputFrameId >= (int)bufferInfo.size() || inputFrameId >= (offset + range)) break; if (listener != nullptr) { if (listener->mSignaledDuration || listener->mSignaledSize) { ALOGV("Max File limit reached. No more buffers will be sent to the writer"); break; } } int32_t size = bufferInfo[inputFrameId].size; char *data = (char *)malloc(size); if (!data) { Loading
media/libstagefright/tests/writer/WriterUtility.h +3 −3 Original line number Diff line number Diff line Loading @@ -27,8 +27,7 @@ #include <media/stagefright/MediaAdapter.h> using namespace android; using namespace std; #include "WriterListener.h" #define CODEC_CONFIG_FLAG 32 Loading @@ -43,7 +42,8 @@ struct BufferInfo { int32_t sendBuffersToWriter(ifstream &inputStream, vector<BufferInfo> &bufferInfo, int32_t &inputFrameId, sp<MediaAdapter> ¤tTrack, int32_t offset, int32_t range, bool isPaused = false); int32_t range, bool isPaused = false, sp<WriterListener> listener = nullptr); int32_t writeHeaderBuffers(ifstream &inputStream, vector<BufferInfo> &bufferInfo, int32_t &inputFrameId, sp<AMessage> &format, int32_t numCsds); Loading