1 /*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "WriterTest"
19 #include <utils/Log.h>
20
21 #include <binder/ProcessState.h>
22
23 #include <inttypes.h>
24 #include <fstream>
25 #include <iostream>
26
27 #include <media/NdkMediaExtractor.h>
28 #include <media/stagefright/MediaDefs.h>
29 #include <media/stagefright/MetaData.h>
30 #include <media/stagefright/Utils.h>
31
32 #include <media/mediarecorder.h>
33
34 #include <media/stagefright/AACWriter.h>
35 #include <media/stagefright/AMRWriter.h>
36 #include <media/stagefright/MPEG2TSWriter.h>
37 #include <media/stagefright/MPEG4Writer.h>
38 #include <media/stagefright/OggWriter.h>
39 #include <webm/WebmWriter.h>
40
41 #include "WriterTestEnvironment.h"
42 #include "WriterUtility.h"
43
44 #define OUTPUT_FILE_NAME "/data/local/tmp/writer.out"
45
46 // Stts values within 0.1ms(100us) difference are fudged to save too
47 // many stts entries in MPEG4Writer.
48 constexpr int32_t kMpeg4MuxToleranceTimeUs = 100;
49 // Tolerance value for other writers
50 constexpr int32_t kMuxToleranceTimeUs = 1;
51
52 static WriterTestEnvironment *gEnv = nullptr;
53
54 enum inputId {
55 // audio streams
56 AAC_1,
57 AAC_ADTS_1,
58 AMR_NB_1,
59 AMR_WB_1,
60 FLAC_1,
61 OPUS_1,
62 VORBIS_1,
63 // video streams
64 AV1_1,
65 AVC_1,
66 H263_1,
67 HEVC_1,
68 MPEG4_1,
69 VP8_1,
70 VP9_1,
71 // heif stream
72 HEIC_1,
73 UNUSED_ID,
74 UNKNOWN_ID,
75 };
76
77 // LookUpTable of clips and metadata for component testing
78 static const struct InputData {
79 inputId inpId;
80 const char *mime;
81 string inputFile;
82 string info;
83 int32_t firstParam;
84 int32_t secondParam;
85 bool isAudio;
86 } kInputData[] = {
87 {AAC_1, MEDIA_MIMETYPE_AUDIO_AAC, "audio_aac_stereo_8kbps_11025hz.aac",
88 "audio_aac_stereo_8kbps_11025hz.info", 11025, 2, true},
89 {AAC_ADTS_1, MEDIA_MIMETYPE_AUDIO_AAC_ADTS, "Mps_2_c2_fr1_Sc1_Dc2_0x03_raw.adts",
90 "Mps_2_c2_fr1_Sc1_Dc2_0x03_raw.info", 48000, 2, true},
91 {AMR_NB_1, MEDIA_MIMETYPE_AUDIO_AMR_NB, "sine_amrnb_1ch_12kbps_8000hz.amrnb",
92 "sine_amrnb_1ch_12kbps_8000hz.info", 8000, 1, true},
93 {AMR_WB_1, MEDIA_MIMETYPE_AUDIO_AMR_WB, "bbb_amrwb_1ch_14kbps_16000hz.amrwb",
94 "bbb_amrwb_1ch_14kbps_16000hz.info", 16000, 1, true},
95 {FLAC_1, MEDIA_MIMETYPE_AUDIO_FLAC, "bbb_flac_stereo_680kbps_48000hz.flac",
96 "bbb_flac_stereo_680kbps_48000hz.info", 48000, 2, true},
97 {OPUS_1, MEDIA_MIMETYPE_AUDIO_OPUS, "bbb_opus_stereo_128kbps_48000hz.opus",
98 "bbb_opus_stereo_128kbps_48000hz.info", 48000, 2, true},
99 {VORBIS_1, MEDIA_MIMETYPE_AUDIO_VORBIS, "bbb_vorbis_1ch_64kbps_16kHz.vorbis",
100 "bbb_vorbis_1ch_64kbps_16kHz.info", 16000, 1, true},
101
102 {AV1_1, MEDIA_MIMETYPE_VIDEO_AV1, "bbb_av1_176_144.av1", "bbb_av1_176_144.info", 176, 144,
103 false},
104 {AVC_1, MEDIA_MIMETYPE_VIDEO_AVC, "bbb_avc_352x288_768kbps_30fps.avc",
105 "bbb_avc_352x288_768kbps_30fps.info", 352, 288, false},
106 {H263_1, MEDIA_MIMETYPE_VIDEO_H263, "bbb_h263_352x288_300kbps_12fps.h263",
107 "bbb_h263_352x288_300kbps_12fps.info", 352, 288, false},
108 {HEVC_1, MEDIA_MIMETYPE_VIDEO_HEVC, "bbb_hevc_340x280_768kbps_30fps.hevc",
109 "bbb_hevc_340x280_768kbps_30fps.info", 340, 280, false},
110 {MPEG4_1, MEDIA_MIMETYPE_VIDEO_MPEG4, "bbb_mpeg4_352x288_512kbps_30fps.m4v",
111 "bbb_mpeg4_352x288_512kbps_30fps.info", 352, 288, false},
112 {VP8_1, MEDIA_MIMETYPE_VIDEO_VP8, "bbb_vp8_176x144_240kbps_60fps.vp8",
113 "bbb_vp8_176x144_240kbps_60fps.info", 176, 144, false},
114 {VP9_1, MEDIA_MIMETYPE_VIDEO_VP9, "bbb_vp9_176x144_285kbps_60fps.vp9",
115 "bbb_vp9_176x144_285kbps_60fps.info", 176, 144, false},
116
117 {HEIC_1, MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC, "bbb_hevc_176x144_176kbps_60fps.hevc",
118 "bbb_heic_176x144_176kbps_60fps.info", 176, 144, false},
119 };
120
121 class WriterTest {
122 public:
WriterTest()123 WriterTest() : mWriter(nullptr), mFileMeta(nullptr) {}
124
~WriterTest()125 ~WriterTest() {
126 if (mFileMeta) {
127 mFileMeta.clear();
128 mFileMeta = nullptr;
129 }
130 if (mWriter) {
131 mWriter.clear();
132 mWriter = nullptr;
133 }
134 if (gEnv->cleanUp()) remove(OUTPUT_FILE_NAME);
135
136 for (int32_t idx = 0; idx < kMaxTrackCount; idx++) {
137 mBufferInfo[idx].clear();
138 if (mCurrentTrack[idx]) {
139 mCurrentTrack[idx]->stop();
140 mCurrentTrack[idx].clear();
141 mCurrentTrack[idx] = nullptr;
142 }
143 if (mInputStream[idx].is_open()) mInputStream[idx].close();
144 }
145 }
146
setupWriterType(string writerFormat)147 void setupWriterType(string writerFormat) {
148 mWriterName = unknown_comp;
149 mDisableTest = false;
150 static const std::map<std::string, standardWriters> mapWriter = {
151 {"ogg", OGG}, {"aac", AAC}, {"aac_adts", AAC_ADTS}, {"webm", WEBM},
152 {"mpeg4", MPEG4}, {"amrnb", AMR_NB}, {"amrwb", AMR_WB}, {"mpeg2Ts", MPEG2TS}};
153 // Find the component type
154 if (mapWriter.find(writerFormat) != mapWriter.end()) {
155 mWriterName = mapWriter.at(writerFormat);
156 }
157 if (mWriterName == standardWriters::unknown_comp) {
158 cout << "[ WARN ] Test Skipped. No specific writer mentioned\n";
159 mDisableTest = true;
160 }
161 }
162
163 void getInputBufferInfo(string inputFileName, string inputInfo, int32_t idx = 0);
164
165 int32_t createWriter(int32_t fd);
166
167 int32_t addWriterSource(bool isAudio, configFormat params, int32_t idx = 0);
168
169 void setupExtractor(AMediaExtractor *extractor, string inputFileName, int32_t &trackCount);
170
171 void extract(AMediaExtractor *extractor, configFormat ¶ms, vector<BufferInfo> &bufferInfo,
172 uint8_t *buffer, size_t bufSize, size_t *bytesExtracted, int32_t idx);
173
174 void compareParams(configFormat srcParam, configFormat dstParam, vector<BufferInfo> dstBufInfo,
175 int32_t index);
176
177 enum standardWriters {
178 OGG,
179 AAC,
180 AAC_ADTS,
181 WEBM,
182 MPEG4,
183 AMR_NB,
184 AMR_WB,
185 MPEG2TS,
186 unknown_comp,
187 };
188
189 standardWriters mWriterName;
190 sp<MediaWriter> mWriter;
191 sp<MetaData> mFileMeta;
192 sp<MediaAdapter> mCurrentTrack[kMaxTrackCount]{};
193
194 bool mDisableTest;
195 int32_t mNumCsds[kMaxTrackCount]{};
196 int32_t mInputFrameId[kMaxTrackCount]{};
197 ifstream mInputStream[kMaxTrackCount]{};
198 vector<BufferInfo> mBufferInfo[kMaxTrackCount];
199 };
200
201 class WriteFunctionalityTest
202 : public WriterTest,
203 public ::testing::TestWithParam<tuple<string /* writerFormat*/, inputId /* inputId0*/,
204 inputId /* inputId1*/, float /* BufferInterval*/>> {
205 public:
SetUp()206 virtual void SetUp() override { setupWriterType(get<0>(GetParam())); }
207 };
208
getInputBufferInfo(string inputFileName,string inputInfo,int32_t idx)209 void WriterTest::getInputBufferInfo(string inputFileName, string inputInfo, int32_t idx) {
210 std::ifstream eleInfo;
211 eleInfo.open(inputInfo.c_str());
212 ASSERT_EQ(eleInfo.is_open(), true);
213 int32_t bytesCount = 0;
214 uint32_t flags = 0;
215 int64_t timestamp = 0;
216 int32_t numCsds = 0;
217 while (1) {
218 if (!(eleInfo >> bytesCount)) break;
219 eleInfo >> flags;
220 eleInfo >> timestamp;
221 mBufferInfo[idx].push_back({bytesCount, flags, timestamp});
222 if (flags == CODEC_CONFIG_FLAG) numCsds++;
223 }
224 eleInfo.close();
225 mNumCsds[idx] = numCsds;
226 mInputStream[idx].open(inputFileName.c_str(), std::ifstream::binary);
227 ASSERT_EQ(mInputStream[idx].is_open(), true);
228 }
229
createWriter(int32_t fd)230 int32_t WriterTest::createWriter(int32_t fd) {
231 mFileMeta = new MetaData;
232 switch (mWriterName) {
233 case OGG:
234 mWriter = new OggWriter(fd);
235 mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_OGG);
236 break;
237 case AAC:
238 mWriter = new AACWriter(fd);
239 mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AAC_ADIF);
240 break;
241 case AAC_ADTS:
242 mWriter = new AACWriter(fd);
243 mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AAC_ADTS);
244 break;
245 case WEBM:
246 mWriter = new WebmWriter(fd);
247 mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_WEBM);
248 break;
249 case MPEG4:
250 mWriter = new MPEG4Writer(fd);
251 mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_MPEG_4);
252 break;
253 case AMR_NB:
254 mWriter = new AMRWriter(fd);
255 mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AMR_NB);
256 break;
257 case AMR_WB:
258 mWriter = new AMRWriter(fd);
259 mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AMR_WB);
260 break;
261 case MPEG2TS:
262 mWriter = new MPEG2TSWriter(fd);
263 mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_MPEG2TS);
264 break;
265 default:
266 return -1;
267 }
268 if (mWriter == nullptr) return -1;
269 mFileMeta->setInt32(kKeyRealTimeRecording, false);
270 return 0;
271 }
272
addWriterSource(bool isAudio,configFormat params,int32_t idx)273 int32_t WriterTest::addWriterSource(bool isAudio, configFormat params, int32_t idx) {
274 if (mInputFrameId[idx]) return -1;
275 sp<AMessage> format = new AMessage;
276 if (mInputStream[idx].is_open()) {
277 format->setString("mime", params.mime);
278 if (isAudio) {
279 format->setInt32("channel-count", params.channelCount);
280 format->setInt32("sample-rate", params.sampleRate);
281 } else {
282 format->setInt32("width", params.width);
283 format->setInt32("height", params.height);
284 }
285 if (mNumCsds[idx]) {
286 int32_t status = writeHeaderBuffers(mInputStream[idx], mBufferInfo[idx],
287 mInputFrameId[idx], format, mNumCsds[idx]);
288 if (status != 0) return -1;
289 }
290 }
291
292 sp<MetaData> trackMeta = new MetaData;
293 convertMessageToMetaData(format, trackMeta);
294 mCurrentTrack[idx] = new MediaAdapter(trackMeta);
295 if (mCurrentTrack[idx] == nullptr) {
296 ALOGE("MediaAdapter returned nullptr");
297 return -1;
298 }
299 status_t result = mWriter->addSource(mCurrentTrack[idx]);
300 return result;
301 }
302
getFileDetails(string & inputFilePath,string & info,configFormat & params,bool & isAudio,inputId inpId)303 void getFileDetails(string &inputFilePath, string &info, configFormat ¶ms, bool &isAudio,
304 inputId inpId) {
305 int32_t inputDataSize = sizeof(kInputData) / sizeof(kInputData[0]);
306 int32_t streamIndex = 0;
307 for (; streamIndex < inputDataSize; streamIndex++) {
308 if (inpId == kInputData[streamIndex].inpId) {
309 break;
310 }
311 }
312 if (streamIndex == inputDataSize) {
313 return;
314 }
315 inputFilePath += kInputData[streamIndex].inputFile;
316 info += kInputData[streamIndex].info;
317 strcpy(params.mime, kInputData[streamIndex].mime);
318 isAudio = kInputData[streamIndex].isAudio;
319 if (isAudio) {
320 params.sampleRate = kInputData[streamIndex].firstParam;
321 params.channelCount = kInputData[streamIndex].secondParam;
322 } else {
323 params.width = kInputData[streamIndex].firstParam;
324 params.height = kInputData[streamIndex].secondParam;
325 }
326 return;
327 }
328
setupExtractor(AMediaExtractor * extractor,string inputFileName,int32_t & trackCount)329 void WriterTest::setupExtractor(AMediaExtractor *extractor, string inputFileName,
330 int32_t &trackCount) {
331 ALOGV("Input file for extractor: %s", inputFileName.c_str());
332
333 int32_t fd = open(inputFileName.c_str(), O_RDONLY);
334 ASSERT_GE(fd, 0) << "Failed to open writer's output file to validate";
335
336 struct stat buf;
337 int32_t status = fstat(fd, &buf);
338 ASSERT_EQ(status, 0) << "Failed to get properties of input file for extractor";
339
340 size_t fileSize = buf.st_size;
341 ALOGV("Size of input file to extractor: %zu", fileSize);
342
343 status = AMediaExtractor_setDataSourceFd(extractor, fd, 0, fileSize);
344 ASSERT_EQ(status, AMEDIA_OK) << "Failed to set data source for extractor";
345
346 trackCount = AMediaExtractor_getTrackCount(extractor);
347 ASSERT_GT(trackCount, 0) << "No tracks reported by extractor";
348 ALOGV("Number of tracks reported by extractor : %d", trackCount);
349 return;
350 }
351
extract(AMediaExtractor * extractor,configFormat & params,vector<BufferInfo> & bufferInfo,uint8_t * buffer,size_t bufSize,size_t * bytesExtracted,int32_t idx)352 void WriterTest::extract(AMediaExtractor *extractor, configFormat ¶ms,
353 vector<BufferInfo> &bufferInfo, uint8_t *buffer, size_t bufSize,
354 size_t *bytesExtracted, int32_t idx) {
355 AMediaExtractor_selectTrack(extractor, idx);
356 AMediaFormat *format = AMediaExtractor_getTrackFormat(extractor, idx);
357 ASSERT_NE(format, nullptr) << "Track format is NULL";
358 ALOGI("Track format = %s", AMediaFormat_toString(format));
359
360 const char *mime = nullptr;
361 AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime);
362 ASSERT_NE(mime, nullptr) << "Track mime is NULL";
363 ALOGI("Track mime = %s", mime);
364 strlcpy(params.mime, mime, kMimeSize);
365
366 if (!strncmp(mime, "audio/", 6)) {
367 ASSERT_TRUE(
368 AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_CHANNEL_COUNT, ¶ms.channelCount))
369 << "Extractor did not report channel count";
370 ASSERT_TRUE(AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE, ¶ms.sampleRate))
371 << "Extractor did not report sample rate";
372 } else if (!strncmp(mime, "video/", 6) || !strncmp(mime, "image/", 6)) {
373 ASSERT_TRUE(AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_WIDTH, ¶ms.width))
374 << "Extractor did not report width";
375 ASSERT_TRUE(AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_HEIGHT, ¶ms.height))
376 << "Extractor did not report height";
377 } else {
378 ASSERT_TRUE(false) << "Invalid mime " << mime;
379 }
380
381 int32_t bufferOffset = 0;
382 // Get CSD data
383 int index = 0;
384 void *csdBuf;
385 while (1) {
386 csdBuf = nullptr;
387 char csdName[16];
388 snprintf(csdName, 16, "csd-%d", index);
389 size_t csdSize = 0;
390 bool csdFound = AMediaFormat_getBuffer(format, csdName, &csdBuf, &csdSize);
391 if (!csdFound || !csdBuf || !csdSize) break;
392
393 bufferInfo.push_back({static_cast<int32_t>(csdSize), CODEC_CONFIG_FLAG, 0});
394 memcpy(buffer + bufferOffset, csdBuf, csdSize);
395 bufferOffset += csdSize;
396 index++;
397 }
398
399 // Get frame data
400 while (1) {
401 ssize_t sampleSize = AMediaExtractor_getSampleSize(extractor);
402 if (sampleSize < 0) break;
403
404 uint8_t *sampleBuffer = (uint8_t *)malloc(sampleSize);
405 ASSERT_NE(sampleBuffer, nullptr) << "Failed to allocate the buffer of size " << sampleSize;
406
407 int bytesRead = AMediaExtractor_readSampleData(extractor, sampleBuffer, sampleSize);
408 ASSERT_EQ(bytesRead, sampleSize)
409 << "Number of bytes extracted does not match with sample size";
410 int64_t pts = AMediaExtractor_getSampleTime(extractor);
411 uint32_t flag = AMediaExtractor_getSampleFlags(extractor);
412
413 if (mime == MEDIA_MIMETYPE_AUDIO_VORBIS) {
414 // Removing 4 bytes of AMEDIAFORMAT_KEY_VALID_SAMPLES from sample size
415 bytesRead = bytesRead - 4;
416 }
417
418 ASSERT_LE(bufferOffset + bytesRead, bufSize)
419 << "Size of the buffer is insufficient to store the extracted data";
420 bufferInfo.push_back({bytesRead, flag, pts});
421 memcpy(buffer + bufferOffset, sampleBuffer, bytesRead);
422 bufferOffset += bytesRead;
423
424 AMediaExtractor_advance(extractor);
425 free(sampleBuffer);
426 }
427 *bytesExtracted = bufferOffset;
428 return;
429 }
430
compareParams(configFormat srcParam,configFormat dstParam,vector<BufferInfo> dstBufInfo,int32_t index)431 void WriterTest::compareParams(configFormat srcParam, configFormat dstParam,
432 vector<BufferInfo> dstBufInfo, int32_t index) {
433 ASSERT_STREQ(srcParam.mime, dstParam.mime)
434 << "Extracted mime type does not match with input mime type";
435
436 if (!strncmp(srcParam.mime, "audio/", 6)) {
437 ASSERT_EQ(srcParam.channelCount, dstParam.channelCount)
438 << "Extracted channel count does not match with input channel count";
439 ASSERT_EQ(srcParam.sampleRate, dstParam.sampleRate)
440 << "Extracted sample rate does not match with input sample rate";
441 } else if (!strncmp(srcParam.mime, "video/", 6) || !strncmp(srcParam.mime, "image/", 6)) {
442 ASSERT_EQ(srcParam.width, dstParam.width)
443 << "Extracted width does not match with input width";
444 ASSERT_EQ(srcParam.height, dstParam.height)
445 << "Extracted height does not match with input height";
446 } else {
447 ASSERT_TRUE(false) << "Invalid mime type" << srcParam.mime;
448 }
449
450 int32_t toleranceValueUs = kMuxToleranceTimeUs;
451 if (mWriterName == MPEG4) {
452 toleranceValueUs = kMpeg4MuxToleranceTimeUs;
453 }
454 for (int32_t i = 0; i < dstBufInfo.size(); i++) {
455 ASSERT_EQ(mBufferInfo[index][i].size, dstBufInfo[i].size)
456 << "Input size " << mBufferInfo[index][i].size << " mismatched with extracted size "
457 << dstBufInfo[i].size;
458 ASSERT_EQ(mBufferInfo[index][i].flags, dstBufInfo[i].flags)
459 << "Input flag " << mBufferInfo[index][i].flags
460 << " mismatched with extracted size " << dstBufInfo[i].flags;
461 ASSERT_LE(abs(mBufferInfo[index][i].timeUs - dstBufInfo[i].timeUs), toleranceValueUs)
462 << "Difference between original timestamp " << mBufferInfo[index][i].timeUs
463 << " and extracted timestamp " << dstBufInfo[i].timeUs
464 << "is greater than tolerance value = " << toleranceValueUs << " micro seconds";
465 }
466 return;
467 }
468
TEST_P(WriteFunctionalityTest,CreateWriterTest)469 TEST_P(WriteFunctionalityTest, CreateWriterTest) {
470 if (mDisableTest) return;
471 ALOGV("Tests the creation of writers");
472
473 string outputFile = OUTPUT_FILE_NAME;
474 int32_t fd =
475 open(outputFile.c_str(), O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
476 ASSERT_GE(fd, 0) << "Failed to open output file to dump writer's data";
477
478 // Creating writer within a test scope. Destructor should be called when the test ends
479 ASSERT_EQ((status_t)OK, createWriter(fd))
480 << "Failed to create writer for output format:" << get<0>(GetParam());
481 }
482
TEST_P(WriteFunctionalityTest,WriterTest)483 TEST_P(WriteFunctionalityTest, WriterTest) {
484 if (mDisableTest) return;
485 ALOGV("Checks if for a given input, a valid muxed file has been created or not");
486
487 string writerFormat = get<0>(GetParam());
488 string outputFile = OUTPUT_FILE_NAME;
489 int32_t fd =
490 open(outputFile.c_str(), O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
491 ASSERT_GE(fd, 0) << "Failed to open output file to dump writer's data";
492
493 int32_t status = createWriter(fd);
494 ASSERT_EQ((status_t)OK, status) << "Failed to create writer for output format:" << writerFormat;
495
496 inputId inpId[] = {get<1>(GetParam()), get<2>(GetParam())};
497 ASSERT_NE(inpId[0], UNUSED_ID) << "Test expects first inputId to be a valid id";
498
499 int32_t numTracks = 1;
500 if (inpId[1] != UNUSED_ID) {
501 numTracks++;
502 }
503
504 size_t fileSize[numTracks];
505 configFormat param[numTracks];
506 for (int32_t idx = 0; idx < numTracks; idx++) {
507 string inputFile = gEnv->getRes();
508 string inputInfo = gEnv->getRes();
509 bool isAudio;
510 getFileDetails(inputFile, inputInfo, param[idx], isAudio, inpId[idx]);
511 ASSERT_NE(inputFile.compare(gEnv->getRes()), 0) << "No input file specified";
512
513 struct stat buf;
514 status = stat(inputFile.c_str(), &buf);
515 ASSERT_EQ(status, 0) << "Failed to get properties of input file:" << inputFile;
516 fileSize[idx] = buf.st_size;
517
518 ASSERT_NO_FATAL_FAILURE(getInputBufferInfo(inputFile, inputInfo, idx));
519 status = addWriterSource(isAudio, param[idx], idx);
520 ASSERT_EQ((status_t)OK, status) << "Failed to add source for " << writerFormat << "Writer";
521 }
522
523 status = mWriter->start(mFileMeta.get());
524 ASSERT_EQ((status_t)OK, status);
525 float interval = get<3>(GetParam());
526 ASSERT_LE(interval, 1.0f) << "Buffer interval invalid. Should be less than or equal to 1.0";
527
528 size_t range = 0;
529 int32_t loopCount = 0;
530 int32_t offset[kMaxTrackCount]{};
531 while (loopCount < ceil(1.0 / interval)) {
532 for (int32_t idx = 0; idx < numTracks; idx++) {
533 range = mBufferInfo[idx].size() * interval;
534 status = sendBuffersToWriter(mInputStream[idx], mBufferInfo[idx], mInputFrameId[idx],
535 mCurrentTrack[idx], offset[idx], range);
536 ASSERT_EQ((status_t)OK, status) << writerFormat << " writer failed";
537 offset[idx] += range;
538 }
539 loopCount++;
540 }
541 for (int32_t idx = 0; idx < kMaxTrackCount; idx++) {
542 if (mCurrentTrack[idx]) {
543 mCurrentTrack[idx]->stop();
544 }
545 }
546 status = mWriter->stop();
547 ASSERT_EQ((status_t)OK, status) << "Failed to stop the writer";
548 close(fd);
549
550 // Validate the output muxed file created by writer
551 // TODO(b/146423022): Skip validating output for webm writer
552 // TODO(b/146421018): Skip validating output for ogg writer
553 if (mWriterName != OGG && mWriterName != WEBM) {
554 configFormat extractorParams[numTracks];
555 vector<BufferInfo> extractorBufferInfo[numTracks];
556 int32_t trackCount = -1;
557
558 AMediaExtractor *extractor = AMediaExtractor_new();
559 ASSERT_NE(extractor, nullptr) << "Failed to create extractor";
560 ASSERT_NO_FATAL_FAILURE(setupExtractor(extractor, outputFile, trackCount));
561 ASSERT_EQ(trackCount, numTracks)
562 << "Tracks reported by extractor does not match with input number of tracks";
563
564 for (int32_t idx = 0; idx < numTracks; idx++) {
565 char *inputBuffer = (char *)malloc(fileSize[idx]);
566 ASSERT_NE(inputBuffer, nullptr)
567 << "Failed to allocate the buffer of size " << fileSize[idx];
568 mInputStream[idx].seekg(0, mInputStream[idx].beg);
569 mInputStream[idx].read(inputBuffer, fileSize[idx]);
570 ASSERT_EQ(mInputStream[idx].gcount(), fileSize[idx]);
571
572 uint8_t *extractedBuffer = (uint8_t *)malloc(fileSize[idx]);
573 ASSERT_NE(extractedBuffer, nullptr)
574 << "Failed to allocate the buffer of size " << fileSize[idx];
575 size_t bytesExtracted = 0;
576
577 ASSERT_NO_FATAL_FAILURE(extract(extractor, extractorParams[idx],
578 extractorBufferInfo[idx], extractedBuffer,
579 fileSize[idx], &bytesExtracted, idx));
580 ASSERT_GT(bytesExtracted, 0) << "Total bytes extracted by extractor cannot be zero";
581
582 ASSERT_NO_FATAL_FAILURE(
583 compareParams(param[idx], extractorParams[idx], extractorBufferInfo[idx], idx));
584
585 ASSERT_EQ(memcmp(extractedBuffer, (uint8_t *)inputBuffer, bytesExtracted), 0)
586 << "Extracted bit stream does not match with input bit stream";
587
588 free(inputBuffer);
589 free(extractedBuffer);
590 }
591 AMediaExtractor_delete(extractor);
592 }
593 }
594
TEST_P(WriteFunctionalityTest,PauseWriterTest)595 TEST_P(WriteFunctionalityTest, PauseWriterTest) {
596 if (mDisableTest) return;
597 ALOGV("Validates the pause() api of writers");
598
599 string writerFormat = get<0>(GetParam());
600 string outputFile = OUTPUT_FILE_NAME;
601 int32_t fd =
602 open(outputFile.c_str(), O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
603 ASSERT_GE(fd, 0) << "Failed to open output file to dump writer's data";
604
605 int32_t status = createWriter(fd);
606 ASSERT_EQ((status_t)OK, status) << "Failed to create writer for output format:" << writerFormat;
607
608 string inputFile = gEnv->getRes();
609 string inputInfo = gEnv->getRes();
610 configFormat param;
611 bool isAudio;
612 inputId inpId = get<1>(GetParam());
613 ASSERT_NE(inpId, UNUSED_ID) << "Test expects first inputId to be a valid id";
614
615 getFileDetails(inputFile, inputInfo, param, isAudio, inpId);
616 ASSERT_NE(inputFile.compare(gEnv->getRes()), 0) << "No input file specified";
617
618 ASSERT_NO_FATAL_FAILURE(getInputBufferInfo(inputFile, inputInfo));
619 status = addWriterSource(isAudio, param);
620 ASSERT_EQ((status_t)OK, status) << "Failed to add source for " << writerFormat << "Writer";
621
622 status = mWriter->start(mFileMeta.get());
623 ASSERT_EQ((status_t)OK, status);
624 status = sendBuffersToWriter(mInputStream[0], mBufferInfo[0], mInputFrameId[0],
625 mCurrentTrack[0], 0, mBufferInfo[0].size() / 4);
626 ASSERT_EQ((status_t)OK, status) << writerFormat << " writer failed";
627
628 bool isPaused = false;
629 if ((mWriterName != standardWriters::MPEG2TS) && (mWriterName != standardWriters::MPEG4)) {
630 status = mWriter->pause();
631 ASSERT_EQ((status_t)OK, status);
632 isPaused = true;
633 }
634 // In the pause state, writers shouldn't write anything. Testing the writers for the same
635 int32_t numFramesPaused = mBufferInfo[0].size() / 4;
636 status = sendBuffersToWriter(mInputStream[0], mBufferInfo[0], mInputFrameId[0],
637 mCurrentTrack[0], mInputFrameId[0], numFramesPaused, isPaused);
638 ASSERT_EQ((status_t)OK, status) << writerFormat << " writer failed";
639
640 if (isPaused) {
641 status = mWriter->start(mFileMeta.get());
642 ASSERT_EQ((status_t)OK, status);
643 }
644 status = sendBuffersToWriter(mInputStream[0], mBufferInfo[0], mInputFrameId[0],
645 mCurrentTrack[0], mInputFrameId[0], mBufferInfo[0].size());
646 ASSERT_EQ((status_t)OK, status) << writerFormat << " writer failed";
647 mCurrentTrack[0]->stop();
648
649 status = mWriter->stop();
650 ASSERT_EQ((status_t)OK, status) << "Failed to stop the writer";
651 close(fd);
652 }
653
TEST_P(WriteFunctionalityTest,MultiStartStopPauseTest)654 TEST_P(WriteFunctionalityTest, MultiStartStopPauseTest) {
655 // TODO: (b/144821804)
656 // Enable the test for MPE2TS writer
657 if (mDisableTest || mWriterName == standardWriters::MPEG2TS) return;
658 ALOGV("Test writers for multiple start, stop and pause calls");
659
660 string outputFile = OUTPUT_FILE_NAME;
661 int32_t fd =
662 open(outputFile.c_str(), O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
663 ASSERT_GE(fd, 0) << "Failed to open output file to dump writer's data";
664
665 string writerFormat = get<0>(GetParam());
666 int32_t status = createWriter(fd);
667 ASSERT_EQ(status, (status_t)OK) << "Failed to create writer for output format:" << writerFormat;
668
669 string inputFile = gEnv->getRes();
670 string inputInfo = gEnv->getRes();
671 configFormat param;
672 bool isAudio;
673 inputId inpId = get<1>(GetParam());
674 ASSERT_NE(inpId, UNUSED_ID) << "Test expects first inputId to be a valid id";
675
676 getFileDetails(inputFile, inputInfo, param, isAudio, inpId);
677 ASSERT_NE(inputFile.compare(gEnv->getRes()), 0) << "No input file specified";
678
679 ASSERT_NO_FATAL_FAILURE(getInputBufferInfo(inputFile, inputInfo));
680 status = addWriterSource(isAudio, param);
681 ASSERT_EQ((status_t)OK, status) << "Failed to add source for " << writerFormat << "Writer";
682
683 // first start should succeed.
684 status = mWriter->start(mFileMeta.get());
685 ASSERT_EQ((status_t)OK, status) << "Could not start the writer";
686
687 // Multiple start() may/may not succeed.
688 // Writers are expected to not crash on multiple start() calls.
689 for (int32_t count = 0; count < kMaxCount; count++) {
690 mWriter->start(mFileMeta.get());
691 }
692
693 status = sendBuffersToWriter(mInputStream[0], mBufferInfo[0], mInputFrameId[0],
694 mCurrentTrack[0], 0, mBufferInfo[0].size() / 4);
695 ASSERT_EQ((status_t)OK, status) << writerFormat << " writer failed";
696
697 for (int32_t count = 0; count < kMaxCount; count++) {
698 mWriter->pause();
699 mWriter->start(mFileMeta.get());
700 }
701
702 mWriter->pause();
703 int32_t numFramesPaused = mBufferInfo[0].size() / 4;
704 status = sendBuffersToWriter(mInputStream[0], mBufferInfo[0], mInputFrameId[0],
705 mCurrentTrack[0], mInputFrameId[0], numFramesPaused, true);
706 ASSERT_EQ((status_t)OK, status) << writerFormat << " writer failed";
707
708 for (int32_t count = 0; count < kMaxCount; count++) {
709 mWriter->start(mFileMeta.get());
710 }
711
712 status = sendBuffersToWriter(mInputStream[0], mBufferInfo[0], mInputFrameId[0],
713 mCurrentTrack[0], mInputFrameId[0], mBufferInfo[0].size());
714 ASSERT_EQ((status_t)OK, status) << writerFormat << " writer failed";
715
716 mCurrentTrack[0]->stop();
717
718 // first stop should succeed.
719 status = mWriter->stop();
720 ASSERT_EQ((status_t)OK, status) << "Failed to stop the writer";
721 // Multiple stop() may/may not succeed.
722 // Writers are expected to not crash on multiple stop() calls.
723 for (int32_t count = 0; count < kMaxCount; count++) {
724 mWriter->stop();
725 }
726 close(fd);
727 }
728
729 class WriterValidityTest
730 : public WriterTest,
731 public ::testing::TestWithParam<
732 tuple<string /* writerFormat*/, inputId /* inputId0*/, bool /* addSourceFail*/>> {
733 public:
SetUp()734 virtual void SetUp() override { setupWriterType(get<0>(GetParam())); }
735 };
736
TEST_P(WriterValidityTest,InvalidInputTest)737 TEST_P(WriterValidityTest, InvalidInputTest) {
738 if (mDisableTest) return;
739 ALOGV("Validates writer's behavior for invalid inputs");
740
741 string writerFormat = get<0>(GetParam());
742 inputId inpId = get<1>(GetParam());
743 bool addSourceFailExpected = get<2>(GetParam());
744
745 // Test writers for invalid FD value
746 int32_t fd = -1;
747 int32_t status = createWriter(fd);
748 if (status != OK) {
749 ALOGV("createWriter failed for invalid FD, this is expected behavior");
750 return;
751 }
752
753 // If writer was created for invalid fd, test it further.
754 string inputFile = gEnv->getRes();
755 string inputInfo = gEnv->getRes();
756 configFormat param;
757 bool isAudio;
758 ASSERT_NE(inpId, UNUSED_ID) << "Test expects first inputId to be a valid id";
759
760 getFileDetails(inputFile, inputInfo, param, isAudio, inpId);
761 ASSERT_NE(inputFile.compare(gEnv->getRes()), 0) << "No input file specified";
762
763 ASSERT_NO_FATAL_FAILURE(getInputBufferInfo(inputFile, inputInfo));
764 status = addWriterSource(isAudio, param);
765 if (status != OK) {
766 ASSERT_TRUE(addSourceFailExpected)
767 << "Failed to add source for " << writerFormat << " writer";
768 ALOGV("addWriterSource failed for invalid FD, this is expected behavior");
769 return;
770 }
771
772 // start the writer with valid argument but invalid FD
773 status = mWriter->start(mFileMeta.get());
774 ASSERT_NE((status_t)OK, status) << "Writer did not fail for invalid FD";
775
776 status = sendBuffersToWriter(mInputStream[0], mBufferInfo[0], mInputFrameId[0],
777 mCurrentTrack[0], 0, mBufferInfo[0].size());
778 ASSERT_NE((status_t)OK, status) << "Writer did not report error for invalid FD";
779
780 status = mCurrentTrack[0]->stop();
781 ASSERT_EQ((status_t)OK, status) << "Failed to stop the track";
782
783 status = mWriter->stop();
784 ASSERT_EQ((status_t)OK, status) << "Failed to stop " << writerFormat << " writer";
785 }
786
TEST_P(WriterValidityTest,MalFormedDataTest)787 TEST_P(WriterValidityTest, MalFormedDataTest) {
788 if (mDisableTest) return;
789 // Enable test for Ogg writer
790 ASSERT_NE(mWriterName, OGG) << "TODO(b/160105646)";
791 ALOGV("Test writer for malformed inputs");
792
793 string writerFormat = get<0>(GetParam());
794 inputId inpId = get<1>(GetParam());
795 bool addSourceFailExpected = get<2>(GetParam());
796 int32_t fd =
797 open(OUTPUT_FILE_NAME, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
798 ASSERT_GE(fd, 0) << "Failed to open output file to dump writer's data";
799
800 int32_t status = createWriter(fd);
801 ASSERT_EQ(status, (status_t)OK)
802 << "Failed to create writer for " << writerFormat << " output format";
803
804 string inputFile = gEnv->getRes();
805 string inputInfo = gEnv->getRes();
806 configFormat param;
807 bool isAudio;
808 ASSERT_NE(inpId, UNUSED_ID) << "Test expects first inputId to be a valid id";
809
810 getFileDetails(inputFile, inputInfo, param, isAudio, inpId);
811 ASSERT_NE(inputFile.compare(gEnv->getRes()), 0) << "No input file specified";
812
813 ASSERT_NO_FATAL_FAILURE(getInputBufferInfo(inputFile, inputInfo));
814 // Remove CSD data from input
815 mNumCsds[0] = 0;
816 status = addWriterSource(isAudio, param);
817 if (status != OK) {
818 ASSERT_TRUE(addSourceFailExpected)
819 << "Failed to add source for " << writerFormat << " writer";
820 ALOGV("%s writer failed to addSource after removing CSD from input", writerFormat.c_str());
821 return;
822 }
823
824 status = mWriter->start(mFileMeta.get());
825 ASSERT_EQ((status_t)OK, status) << "Could not start " << writerFormat << "writer";
826
827 // Skip first few frames. These may contain sync frames also.
828 int32_t frameID = mInputFrameId[0] + mBufferInfo[0].size() / 4;
829 status = sendBuffersToWriter(mInputStream[0], mBufferInfo[0], frameID, mCurrentTrack[0], 0,
830 mBufferInfo[0].size());
831 ASSERT_EQ((status_t)OK, status) << writerFormat << " writer failed";
832
833 status = mCurrentTrack[0]->stop();
834 ASSERT_EQ((status_t)OK, status) << "Failed to stop the track";
835
836 Vector<String16> args;
837 status = mWriter->dump(fd, args);
838 ASSERT_EQ((status_t)OK, status) << "Failed to dump statistics from writer";
839
840 status = mWriter->stop();
841 ASSERT_EQ((status_t)OK, status) << "Failed to stop " << writerFormat << " writer";
842 close(fd);
843 }
844
845 // This test is specific to MPEG4Writer to test more APIs
TEST_P(WriteFunctionalityTest,Mpeg4WriterTest)846 TEST_P(WriteFunctionalityTest, Mpeg4WriterTest) {
847 if (mDisableTest) return;
848 if (mWriterName != standardWriters::MPEG4) return;
849 ALOGV("Test MPEG4 writer specific APIs");
850
851 inputId inpId = get<1>(GetParam());
852 int32_t fd =
853 open(OUTPUT_FILE_NAME, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
854 ASSERT_GE(fd, 0) << "Failed to open output file to dump writer's data";
855
856 int32_t status = createWriter(fd);
857 ASSERT_EQ(status, (status_t)OK) << "Failed to create writer for mpeg4 output format";
858
859 string inputFile = gEnv->getRes();
860 string inputInfo = gEnv->getRes();
861 configFormat param;
862 bool isAudio;
863 ASSERT_NE(inpId, UNUSED_ID) << "Test expects first inputId to be a valid id";
864
865 getFileDetails(inputFile, inputInfo, param, isAudio, inpId);
866 ASSERT_NE(inputFile.compare(gEnv->getRes()), 0) << "No input file specified";
867
868 ASSERT_NO_FATAL_FAILURE(getInputBufferInfo(inputFile, inputInfo));
869 status = addWriterSource(isAudio, param);
870 ASSERT_EQ((status_t)OK, status) << "Failed to add source for mpeg4 Writer";
871
872 // signal meta data for the writer
873 sp<MPEG4Writer> mp4writer = static_cast<MPEG4Writer *>(mWriter.get());
874 status = mp4writer->setInterleaveDuration(kDefaultInterleaveDuration);
875 ASSERT_EQ((status_t)OK, status) << "setInterleaveDuration failed";
876
877 status = mp4writer->setGeoData(kDefaultLatitudex10000, kDefaultLongitudex10000);
878 ASSERT_EQ((status_t)OK, status) << "setGeoData failed";
879
880 status = mp4writer->setCaptureRate(kDefaultFPS);
881 ASSERT_EQ((status_t)OK, status) << "setCaptureRate failed";
882
883 status = mWriter->start(mFileMeta.get());
884 ASSERT_EQ((status_t)OK, status) << "Could not start the writer";
885
886 status = sendBuffersToWriter(mInputStream[0], mBufferInfo[0], mInputFrameId[0],
887 mCurrentTrack[0], 0, mBufferInfo[0].size());
888 ASSERT_EQ((status_t)OK, status) << "mpeg4 writer failed";
889
890 status = mCurrentTrack[0]->stop();
891 ASSERT_EQ((status_t)OK, status) << "Failed to stop the track";
892
893 status = mWriter->stop();
894 ASSERT_EQ((status_t)OK, status) << "Failed to stop the writer";
895 mp4writer.clear();
896 close(fd);
897 }
898
899 class ListenerTest
900 : public WriterTest,
901 public ::testing::TestWithParam<tuple<
902 string /* writerFormat*/, inputId /* inputId0*/, inputId /* inputId1*/,
903 float /* FileSizeLimit*/, float /* FileDurationLimit*/, float /* BufferInterval*/>> {
904 public:
SetUp()905 virtual void SetUp() override { setupWriterType(get<0>(GetParam())); }
906 };
907
TEST_P(ListenerTest,SetMaxFileLimitsTest)908 TEST_P(ListenerTest, SetMaxFileLimitsTest) {
909 // TODO(b/151892414): Enable test for other writers
910 if (mDisableTest || mWriterName != MPEG4) return;
911 ALOGV("Validates writer when max file limits are set");
912
913 string writerFormat = get<0>(GetParam());
914 string outputFile = OUTPUT_FILE_NAME;
915 int32_t fd =
916 open(outputFile.c_str(), O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
917 ASSERT_GE(fd, 0) << "Failed to open output file to dump writer's data";
918
919 int32_t status = createWriter(fd);
920 ASSERT_EQ((status_t)OK, status) << "Failed to create writer for output format:" << writerFormat;
921
922 inputId inpId[] = {get<1>(GetParam()), get<2>(GetParam())};
923 ASSERT_NE(inpId[0], UNUSED_ID) << "Test expects first inputId to be a valid id";
924
925 size_t inputFileSize = 0;
926 int64_t lastFrameTimeStampUs = INT_MAX;
927 int32_t numTracks = 1;
928 if (inpId[1] != UNUSED_ID) {
929 numTracks++;
930 }
931 for (int32_t idx = 0; idx < numTracks; idx++) {
932 string inputFile = gEnv->getRes();
933 string inputInfo = gEnv->getRes();
934 configFormat param;
935 bool isAudio;
936 getFileDetails(inputFile, inputInfo, param, isAudio, inpId[idx]);
937 ASSERT_NE(inputFile.compare(gEnv->getRes()), 0) << "No input file specified";
938
939 ASSERT_NO_FATAL_FAILURE(getInputBufferInfo(inputFile, inputInfo, idx));
940 status = addWriterSource(isAudio, param, idx);
941 ASSERT_EQ((status_t)OK, status) << "Failed to add source for " << writerFormat << "Writer";
942
943 // Read file properties
944 struct stat buf;
945 status = stat(inputFile.c_str(), &buf);
946 ASSERT_EQ(0, status);
947
948 inputFileSize += buf.st_size;
949 if (lastFrameTimeStampUs > mBufferInfo[idx][mBufferInfo[idx].size() - 1].timeUs) {
950 lastFrameTimeStampUs = mBufferInfo[idx][mBufferInfo[idx].size() - 1].timeUs;
951 }
952 }
953
954 float fileSizeLimit = get<3>(GetParam());
955 float fileDurationLimit = get<4>(GetParam());
956 int64_t maxFileSize = 0;
957 int64_t maxFileDuration = 0;
958 if (fileSizeLimit > 0) {
959 maxFileSize = (int64_t)(fileSizeLimit * inputFileSize);
960 mWriter->setMaxFileSize(maxFileSize);
961 }
962 if (fileDurationLimit > 0) {
963 maxFileDuration = (int64_t)(fileDurationLimit * lastFrameTimeStampUs);
964 mWriter->setMaxFileDuration(maxFileDuration);
965 }
966
967 sp<WriterListener> listener = new WriterListener();
968 ASSERT_NE(listener, nullptr) << "unable to allocate listener";
969
970 mWriter->setListener(listener);
971 status = mWriter->start(mFileMeta.get());
972 ASSERT_EQ((status_t)OK, status);
973
974 float interval = get<5>(GetParam());
975 ASSERT_LE(interval, 1.0f) << "Buffer interval invalid. Should be less than or equal to 1.0";
976
977 size_t range = 0;
978 int32_t loopCount = 0;
979 int32_t offset[kMaxTrackCount]{};
980 while (loopCount < ceil(1.0 / interval)) {
981 for (int32_t idx = 0; idx < numTracks; idx++) {
982 range = mBufferInfo[idx].size() * interval;
983 status = sendBuffersToWriter(mInputStream[idx], mBufferInfo[idx], mInputFrameId[idx],
984 mCurrentTrack[idx], offset[idx], range, false, listener);
985 ASSERT_EQ((status_t)OK, status) << writerFormat << " writer failed";
986 offset[idx] += range;
987 }
988 loopCount++;
989 }
990
991 ASSERT_TRUE(mWriter->reachedEOS()) << "EOS not signalled.";
992
993 for (int32_t idx = 0; idx < kMaxTrackCount; idx++) {
994 if (mCurrentTrack[idx]) {
995 mCurrentTrack[idx]->stop();
996 }
997 }
998
999 status = mWriter->stop();
1000 ASSERT_EQ((status_t)OK, status) << "Failed to stop the writer";
1001 close(fd);
1002
1003 if (maxFileSize <= 0) {
1004 ASSERT_FALSE(listener->mSignaledSize);
1005 } else if (maxFileDuration <= 0) {
1006 ASSERT_FALSE(listener->mSignaledDuration);
1007 } else if (maxFileSize > 0 && maxFileDuration <= 0) {
1008 ASSERT_TRUE(listener->mSignaledSize);
1009 } else if (maxFileDuration > 0 && maxFileSize <= 0) {
1010 ASSERT_TRUE(listener->mSignaledDuration);
1011 } else {
1012 ASSERT_TRUE(listener->mSignaledSize || listener->mSignaledDuration);
1013 }
1014
1015 if (maxFileSize > 0) {
1016 struct stat buf;
1017 status = stat(outputFile.c_str(), &buf);
1018 ASSERT_EQ(0, status);
1019 ASSERT_LE(buf.st_size, maxFileSize);
1020 }
1021 }
1022
1023 // TODO: (b/150923387)
1024 // Add WEBM input
1025 INSTANTIATE_TEST_SUITE_P(ListenerTestAll, ListenerTest,
1026 ::testing::Values(make_tuple("aac", AAC_1, UNUSED_ID, 0.6, 0.7, 1),
1027 make_tuple("amrnb", AMR_NB_1, UNUSED_ID, 0.2, 0.6, 1),
1028 make_tuple("amrwb", AMR_WB_1, UNUSED_ID, 0.5, 0.5, 1),
1029 make_tuple("mpeg2Ts", AAC_1, UNUSED_ID, 0.2, 1, 1),
1030 make_tuple("mpeg4", AAC_1, UNUSED_ID, 0.4, 0.3, 0.25),
1031 make_tuple("mpeg4", AAC_1, UNUSED_ID, 0.3, 1, 0.5),
1032 make_tuple("ogg", OPUS_1, UNUSED_ID, 0.7, 0.3, 1)));
1033
1034 // TODO: (b/144476164)
1035 // Add AAC_ADTS, FLAC, AV1 input
1036 INSTANTIATE_TEST_SUITE_P(
1037 WriterTestAll, WriteFunctionalityTest,
1038 ::testing::Values(
1039 make_tuple("aac", AAC_1, UNUSED_ID, 1),
1040
1041 make_tuple("amrnb", AMR_NB_1, UNUSED_ID, 1),
1042 make_tuple("amrwb", AMR_WB_1, UNUSED_ID, 1),
1043
1044 // TODO(b/144902018): Enable test for mpeg2ts
1045 // make_tuple("mpeg2Ts", AAC_1, UNUSED_ID, 1),
1046 // make_tuple("mpeg2Ts", AVC_1, UNUSED_ID, 1),
1047 // TODO(b/156355857): Add multitrack for mpeg2ts
1048 // make_tuple("mpeg2Ts", AAC_1, AVC_1, 0.50),
1049 // make_tuple("mpeg2Ts", AVC_1, AAC_1, 0.25),
1050
1051 make_tuple("mpeg4", AAC_1, UNUSED_ID, 1),
1052 make_tuple("mpeg4", AMR_NB_1, UNUSED_ID, 1),
1053 make_tuple("mpeg4", AMR_WB_1, UNUSED_ID, 1),
1054 make_tuple("mpeg4", AVC_1, UNUSED_ID, 1),
1055 make_tuple("mpeg4", H263_1, UNUSED_ID, 1),
1056 make_tuple("mpeg4", HEIC_1, UNUSED_ID, 1),
1057 make_tuple("mpeg4", HEVC_1, UNUSED_ID, 1),
1058 make_tuple("mpeg4", MPEG4_1, UNUSED_ID, 1),
1059 make_tuple("mpeg4", AAC_1, AVC_1, 0.25),
1060 make_tuple("mpeg4", AVC_1, AAC_1, 0.75),
1061 make_tuple("mpeg4", AMR_WB_1, AAC_1, 0.75),
1062 make_tuple("mpeg4", HEVC_1, AMR_WB_1, 0.25),
1063 make_tuple("mpeg4", H263_1, AMR_NB_1, 0.50),
1064 make_tuple("mpeg4", MPEG4_1, AAC_1, 0.75),
1065 make_tuple("mpeg4", AMR_NB_1, AMR_WB_1, 0.25),
1066 make_tuple("mpeg4", H263_1, AMR_NB_1, 0.50),
1067 make_tuple("mpeg4", MPEG4_1, HEVC_1, 0.75),
1068
1069 make_tuple("ogg", OPUS_1, UNUSED_ID, 1),
1070
1071 make_tuple("webm", OPUS_1, UNUSED_ID, 1),
1072 make_tuple("webm", VORBIS_1, UNUSED_ID, 1),
1073 make_tuple("webm", VP8_1, UNUSED_ID, 1),
1074 make_tuple("webm", VP9_1, UNUSED_ID, 1),
1075 make_tuple("webm", VP8_1, OPUS_1, 0.50),
1076 make_tuple("webm", VORBIS_1, VP8_1, 0.25)));
1077
1078 INSTANTIATE_TEST_SUITE_P(
1079 WriterValidityTest, WriterValidityTest,
1080 ::testing::Values(
1081 make_tuple("aac", AAC_1, true),
1082
1083 make_tuple("amrnb", AMR_NB_1, true),
1084 make_tuple("amrwb", AMR_WB_1, true),
1085
1086 make_tuple("mpeg4", AAC_1, false),
1087 make_tuple("mpeg4", AMR_NB_1, false),
1088 make_tuple("mpeg4", AVC_1, false),
1089 make_tuple("mpeg4", H263_1, false),
1090 make_tuple("mpeg4", HEIC_1, false),
1091 make_tuple("mpeg4", HEVC_1, false),
1092 make_tuple("mpeg4", MPEG4_1, false),
1093
1094 make_tuple("ogg", OPUS_1, true),
1095
1096 make_tuple("webm", OPUS_1, false),
1097 make_tuple("webm", VORBIS_1, true),
1098 make_tuple("webm", VP8_1, false),
1099 make_tuple("webm", VP9_1, false)));
1100
main(int argc,char ** argv)1101 int main(int argc, char **argv) {
1102 ProcessState::self()->startThreadPool();
1103 gEnv = new WriterTestEnvironment();
1104 ::testing::AddGlobalTestEnvironment(gEnv);
1105 ::testing::InitGoogleTest(&argc, argv);
1106 int status = gEnv->initFromOptions(argc, argv);
1107 if (status == 0) {
1108 status = RUN_ALL_TESTS();
1109 ALOGV("Test result = %d\n", status);
1110 }
1111 return status;
1112 }
1113