xref: /aosp_15_r20/cts/tests/media/jni/NativeMuxerTest.cpp (revision b7c941bb3fa97aba169d73cee0bed2de8ac964bf)
1*b7c941bbSAndroid Build Coastguard Worker /*
2*b7c941bbSAndroid Build Coastguard Worker  * Copyright (C) 2019 The Android Open Source Project
3*b7c941bbSAndroid Build Coastguard Worker  *
4*b7c941bbSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*b7c941bbSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*b7c941bbSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*b7c941bbSAndroid Build Coastguard Worker  *
8*b7c941bbSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*b7c941bbSAndroid Build Coastguard Worker  *
10*b7c941bbSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*b7c941bbSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*b7c941bbSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*b7c941bbSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*b7c941bbSAndroid Build Coastguard Worker  * limitations under the License.
15*b7c941bbSAndroid Build Coastguard Worker  */
16*b7c941bbSAndroid Build Coastguard Worker 
17*b7c941bbSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
18*b7c941bbSAndroid Build Coastguard Worker #define LOG_TAG "NativeMuxerTest"
19*b7c941bbSAndroid Build Coastguard Worker #include <log/log.h>
20*b7c941bbSAndroid Build Coastguard Worker 
21*b7c941bbSAndroid Build Coastguard Worker #include <dlfcn.h>
22*b7c941bbSAndroid Build Coastguard Worker #include <fcntl.h>
23*b7c941bbSAndroid Build Coastguard Worker #include <jni.h>
24*b7c941bbSAndroid Build Coastguard Worker #include <media/NdkMediaExtractor.h>
25*b7c941bbSAndroid Build Coastguard Worker #include <media/NdkMediaFormat.h>
26*b7c941bbSAndroid Build Coastguard Worker #include <media/NdkMediaMuxer.h>
27*b7c941bbSAndroid Build Coastguard Worker #include <sys/stat.h>
28*b7c941bbSAndroid Build Coastguard Worker #include <unistd.h>
29*b7c941bbSAndroid Build Coastguard Worker 
30*b7c941bbSAndroid Build Coastguard Worker #include <cmath>
31*b7c941bbSAndroid Build Coastguard Worker #include <cstring>
32*b7c941bbSAndroid Build Coastguard Worker #include <fstream>
33*b7c941bbSAndroid Build Coastguard Worker #include <map>
34*b7c941bbSAndroid Build Coastguard Worker #include <vector>
35*b7c941bbSAndroid Build Coastguard Worker 
36*b7c941bbSAndroid Build Coastguard Worker #include "NativeMediaCommon.h"
37*b7c941bbSAndroid Build Coastguard Worker 
38*b7c941bbSAndroid Build Coastguard Worker // Transcoding arrived in Android 12/S, which is api 31.
39*b7c941bbSAndroid Build Coastguard Worker #define __TRANSCODING_MIN_API__ 31
40*b7c941bbSAndroid Build Coastguard Worker 
41*b7c941bbSAndroid Build Coastguard Worker /**
42*b7c941bbSAndroid Build Coastguard Worker  * MuxerNativeTestHelper breaks a media file to elements that a muxer can use to rebuild its clone.
43*b7c941bbSAndroid Build Coastguard Worker  * While testing muxer, if the test doesn't use MediaCodecs class to generate elementary stream,
44*b7c941bbSAndroid Build Coastguard Worker  * but uses MediaExtractor, this class will be handy
45*b7c941bbSAndroid Build Coastguard Worker  */
46*b7c941bbSAndroid Build Coastguard Worker class MuxerNativeTestHelper {
47*b7c941bbSAndroid Build Coastguard Worker   public:
MuxerNativeTestHelper(const char * srcPath,const char * mediaType=nullptr,int frameLimit=-1)48*b7c941bbSAndroid Build Coastguard Worker     explicit MuxerNativeTestHelper(const char* srcPath, const char* mediaType = nullptr,
49*b7c941bbSAndroid Build Coastguard Worker                                    int frameLimit = -1)
50*b7c941bbSAndroid Build Coastguard Worker         : mSrcPath(srcPath), mMediaType(mediaType), mTrackCount(0), mBuffer(nullptr) {
51*b7c941bbSAndroid Build Coastguard Worker         mFrameLimit = frameLimit < 0 ? INT_MAX : frameLimit;
52*b7c941bbSAndroid Build Coastguard Worker         splitMediaToMuxerParameters();
53*b7c941bbSAndroid Build Coastguard Worker     }
54*b7c941bbSAndroid Build Coastguard Worker 
~MuxerNativeTestHelper()55*b7c941bbSAndroid Build Coastguard Worker     ~MuxerNativeTestHelper() {
56*b7c941bbSAndroid Build Coastguard Worker         for (auto format : mFormat) AMediaFormat_delete(format);
57*b7c941bbSAndroid Build Coastguard Worker         delete[] mBuffer;
58*b7c941bbSAndroid Build Coastguard Worker         for (const auto& buffInfoTrack : mBufferInfo) {
59*b7c941bbSAndroid Build Coastguard Worker             for (auto info : buffInfoTrack) delete info;
60*b7c941bbSAndroid Build Coastguard Worker         }
61*b7c941bbSAndroid Build Coastguard Worker     }
62*b7c941bbSAndroid Build Coastguard Worker 
getTrackCount()63*b7c941bbSAndroid Build Coastguard Worker     int getTrackCount() { return mTrackCount; }
64*b7c941bbSAndroid Build Coastguard Worker 
getSampleCount(size_t trackId)65*b7c941bbSAndroid Build Coastguard Worker     size_t getSampleCount(size_t trackId) {
66*b7c941bbSAndroid Build Coastguard Worker         if (trackId >= mTrackCount) {
67*b7c941bbSAndroid Build Coastguard Worker             return 0;
68*b7c941bbSAndroid Build Coastguard Worker         }
69*b7c941bbSAndroid Build Coastguard Worker         return mBufferInfo[(mInpIndexMap.at(trackId))].size();
70*b7c941bbSAndroid Build Coastguard Worker     }
71*b7c941bbSAndroid Build Coastguard Worker 
getTrackFormat(size_t trackId)72*b7c941bbSAndroid Build Coastguard Worker     AMediaFormat* getTrackFormat(size_t trackId) {
73*b7c941bbSAndroid Build Coastguard Worker         if (trackId >= mTrackCount) {
74*b7c941bbSAndroid Build Coastguard Worker             return nullptr;
75*b7c941bbSAndroid Build Coastguard Worker         }
76*b7c941bbSAndroid Build Coastguard Worker         return mFormat[trackId];
77*b7c941bbSAndroid Build Coastguard Worker     }
78*b7c941bbSAndroid Build Coastguard Worker 
79*b7c941bbSAndroid Build Coastguard Worker     bool registerTrack(AMediaMuxer* muxer);
80*b7c941bbSAndroid Build Coastguard Worker 
81*b7c941bbSAndroid Build Coastguard Worker     bool insertSampleData(AMediaMuxer* muxer);
82*b7c941bbSAndroid Build Coastguard Worker 
83*b7c941bbSAndroid Build Coastguard Worker     bool writeAFewSamplesData(AMediaMuxer* muxer, uint32_t fromIndex, uint32_t toIndex);
84*b7c941bbSAndroid Build Coastguard Worker 
85*b7c941bbSAndroid Build Coastguard Worker     bool writeAFewSamplesDataFromTime(AMediaMuxer* muxer, int64_t* fromTime, uint32_t numSamples,
86*b7c941bbSAndroid Build Coastguard Worker                                       bool lastSplit);
87*b7c941bbSAndroid Build Coastguard Worker 
88*b7c941bbSAndroid Build Coastguard Worker     bool muxMedia(AMediaMuxer* muxer);
89*b7c941bbSAndroid Build Coastguard Worker 
90*b7c941bbSAndroid Build Coastguard Worker     bool appendMedia(AMediaMuxer *muxer, uint32_t fromIndex, uint32_t toIndex);
91*b7c941bbSAndroid Build Coastguard Worker 
92*b7c941bbSAndroid Build Coastguard Worker     bool appendMediaFromTime(AMediaMuxer *muxer, int64_t *appendFromTime,
93*b7c941bbSAndroid Build Coastguard Worker                                     uint32_t numSamples, bool lastSplit);
94*b7c941bbSAndroid Build Coastguard Worker 
95*b7c941bbSAndroid Build Coastguard Worker     bool combineMedias(AMediaMuxer* muxer, MuxerNativeTestHelper* that, const int* repeater);
96*b7c941bbSAndroid Build Coastguard Worker 
97*b7c941bbSAndroid Build Coastguard Worker     bool isSubsetOf(MuxerNativeTestHelper* that);
98*b7c941bbSAndroid Build Coastguard Worker 
99*b7c941bbSAndroid Build Coastguard Worker     void offsetTimeStamp(int64_t tsAudioOffsetUs, int64_t tsVideoOffsetUs, int sampleOffset);
100*b7c941bbSAndroid Build Coastguard Worker 
101*b7c941bbSAndroid Build Coastguard Worker   private:
102*b7c941bbSAndroid Build Coastguard Worker     void splitMediaToMuxerParameters();
103*b7c941bbSAndroid Build Coastguard Worker 
104*b7c941bbSAndroid Build Coastguard Worker     static const int STTS_TOLERANCE_US = 100;
105*b7c941bbSAndroid Build Coastguard Worker     const char* mSrcPath;
106*b7c941bbSAndroid Build Coastguard Worker     const char* mMediaType;
107*b7c941bbSAndroid Build Coastguard Worker     int mTrackCount;
108*b7c941bbSAndroid Build Coastguard Worker     std::vector<AMediaFormat*> mFormat;
109*b7c941bbSAndroid Build Coastguard Worker     uint8_t* mBuffer;
110*b7c941bbSAndroid Build Coastguard Worker     std::vector<std::vector<AMediaCodecBufferInfo*>> mBufferInfo;
111*b7c941bbSAndroid Build Coastguard Worker     std::map<int, int> mInpIndexMap;
112*b7c941bbSAndroid Build Coastguard Worker     std::vector<int> mTrackIdxOrder;
113*b7c941bbSAndroid Build Coastguard Worker     int mFrameLimit;
114*b7c941bbSAndroid Build Coastguard Worker     // combineMedias() uses local version of this variable
115*b7c941bbSAndroid Build Coastguard Worker     std::map<int, int> mOutIndexMap;
116*b7c941bbSAndroid Build Coastguard Worker };
117*b7c941bbSAndroid Build Coastguard Worker 
splitMediaToMuxerParameters()118*b7c941bbSAndroid Build Coastguard Worker void MuxerNativeTestHelper::splitMediaToMuxerParameters() {
119*b7c941bbSAndroid Build Coastguard Worker     FILE* ifp = fopen(mSrcPath, "rbe");
120*b7c941bbSAndroid Build Coastguard Worker     int fd;
121*b7c941bbSAndroid Build Coastguard Worker     int fileSize;
122*b7c941bbSAndroid Build Coastguard Worker     if (ifp) {
123*b7c941bbSAndroid Build Coastguard Worker         struct stat buf {};
124*b7c941bbSAndroid Build Coastguard Worker         stat(mSrcPath, &buf);
125*b7c941bbSAndroid Build Coastguard Worker         fileSize = buf.st_size;
126*b7c941bbSAndroid Build Coastguard Worker         fd = fileno(ifp);
127*b7c941bbSAndroid Build Coastguard Worker     } else {
128*b7c941bbSAndroid Build Coastguard Worker         return;
129*b7c941bbSAndroid Build Coastguard Worker     }
130*b7c941bbSAndroid Build Coastguard Worker     AMediaExtractor* extractor = AMediaExtractor_new();
131*b7c941bbSAndroid Build Coastguard Worker     if (extractor == nullptr) {
132*b7c941bbSAndroid Build Coastguard Worker         fclose(ifp);
133*b7c941bbSAndroid Build Coastguard Worker         return;
134*b7c941bbSAndroid Build Coastguard Worker     }
135*b7c941bbSAndroid Build Coastguard Worker     // Set up MediaExtractor to read from the source.
136*b7c941bbSAndroid Build Coastguard Worker     media_status_t status = AMediaExtractor_setDataSourceFd(extractor, fd, 0, fileSize);
137*b7c941bbSAndroid Build Coastguard Worker     if (AMEDIA_OK != status) {
138*b7c941bbSAndroid Build Coastguard Worker         AMediaExtractor_delete(extractor);
139*b7c941bbSAndroid Build Coastguard Worker         fclose(ifp);
140*b7c941bbSAndroid Build Coastguard Worker         return;
141*b7c941bbSAndroid Build Coastguard Worker     }
142*b7c941bbSAndroid Build Coastguard Worker 
143*b7c941bbSAndroid Build Coastguard Worker     // Set up MediaFormat
144*b7c941bbSAndroid Build Coastguard Worker     int index = 0;
145*b7c941bbSAndroid Build Coastguard Worker     for (size_t trackID = 0; trackID < AMediaExtractor_getTrackCount(extractor); trackID++) {
146*b7c941bbSAndroid Build Coastguard Worker         AMediaExtractor_selectTrack(extractor, trackID);
147*b7c941bbSAndroid Build Coastguard Worker         AMediaFormat* format = AMediaExtractor_getTrackFormat(extractor, trackID);
148*b7c941bbSAndroid Build Coastguard Worker         if (mMediaType == nullptr) {
149*b7c941bbSAndroid Build Coastguard Worker             mTrackCount++;
150*b7c941bbSAndroid Build Coastguard Worker             mFormat.push_back(format);
151*b7c941bbSAndroid Build Coastguard Worker             mInpIndexMap[trackID] = index++;
152*b7c941bbSAndroid Build Coastguard Worker         } else {
153*b7c941bbSAndroid Build Coastguard Worker             const char* mediaType;
154*b7c941bbSAndroid Build Coastguard Worker             bool hasKey = AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mediaType);
155*b7c941bbSAndroid Build Coastguard Worker             if (hasKey && !strcmp(mediaType, mMediaType)) {
156*b7c941bbSAndroid Build Coastguard Worker                 mTrackCount++;
157*b7c941bbSAndroid Build Coastguard Worker                 mFormat.push_back(format);
158*b7c941bbSAndroid Build Coastguard Worker                 mInpIndexMap[trackID] = index;
159*b7c941bbSAndroid Build Coastguard Worker                 break;
160*b7c941bbSAndroid Build Coastguard Worker             } else {
161*b7c941bbSAndroid Build Coastguard Worker                 AMediaFormat_delete(format);
162*b7c941bbSAndroid Build Coastguard Worker                 AMediaExtractor_unselectTrack(extractor, trackID);
163*b7c941bbSAndroid Build Coastguard Worker             }
164*b7c941bbSAndroid Build Coastguard Worker         }
165*b7c941bbSAndroid Build Coastguard Worker     }
166*b7c941bbSAndroid Build Coastguard Worker 
167*b7c941bbSAndroid Build Coastguard Worker     if (mTrackCount <= 0) {
168*b7c941bbSAndroid Build Coastguard Worker         AMediaExtractor_delete(extractor);
169*b7c941bbSAndroid Build Coastguard Worker         fclose(ifp);
170*b7c941bbSAndroid Build Coastguard Worker         return;
171*b7c941bbSAndroid Build Coastguard Worker     }
172*b7c941bbSAndroid Build Coastguard Worker 
173*b7c941bbSAndroid Build Coastguard Worker     // Set up location for elementary stream
174*b7c941bbSAndroid Build Coastguard Worker     int bufferSize = ((fileSize + 127) >> 7) << 7;
175*b7c941bbSAndroid Build Coastguard Worker     // Ideally, Sum of return values of extractor.readSampleData(...) should not exceed
176*b7c941bbSAndroid Build Coastguard Worker     // source file size. But in case of Vorbis, aosp extractor appends an additional 4 bytes to
177*b7c941bbSAndroid Build Coastguard Worker     // the data at every readSampleData() call. bufferSize <<= 1 empirically large enough to
178*b7c941bbSAndroid Build Coastguard Worker     // hold the excess 4 bytes per read call
179*b7c941bbSAndroid Build Coastguard Worker     bufferSize <<= 1;
180*b7c941bbSAndroid Build Coastguard Worker     mBuffer = new uint8_t[bufferSize];
181*b7c941bbSAndroid Build Coastguard Worker     if (mBuffer == nullptr) {
182*b7c941bbSAndroid Build Coastguard Worker         mTrackCount = 0;
183*b7c941bbSAndroid Build Coastguard Worker         AMediaExtractor_delete(extractor);
184*b7c941bbSAndroid Build Coastguard Worker         fclose(ifp);
185*b7c941bbSAndroid Build Coastguard Worker         return;
186*b7c941bbSAndroid Build Coastguard Worker     }
187*b7c941bbSAndroid Build Coastguard Worker 
188*b7c941bbSAndroid Build Coastguard Worker     // Let MediaExtractor do its thing
189*b7c941bbSAndroid Build Coastguard Worker     bool sawEOS = false;
190*b7c941bbSAndroid Build Coastguard Worker     int frameCount = 0;
191*b7c941bbSAndroid Build Coastguard Worker     int offset = 0;
192*b7c941bbSAndroid Build Coastguard Worker     mBufferInfo.resize(mTrackCount);
193*b7c941bbSAndroid Build Coastguard Worker     while (!sawEOS && frameCount < mFrameLimit) {
194*b7c941bbSAndroid Build Coastguard Worker         auto* bufferInfo = new AMediaCodecBufferInfo();
195*b7c941bbSAndroid Build Coastguard Worker         bufferInfo->offset = offset;
196*b7c941bbSAndroid Build Coastguard Worker         bufferInfo->size =
197*b7c941bbSAndroid Build Coastguard Worker                 AMediaExtractor_readSampleData(extractor, mBuffer + offset, (bufferSize - offset));
198*b7c941bbSAndroid Build Coastguard Worker         if (bufferInfo->size < 0) {
199*b7c941bbSAndroid Build Coastguard Worker             sawEOS = true;
200*b7c941bbSAndroid Build Coastguard Worker         } else {
201*b7c941bbSAndroid Build Coastguard Worker             bufferInfo->presentationTimeUs = AMediaExtractor_getSampleTime(extractor);
202*b7c941bbSAndroid Build Coastguard Worker             bufferInfo->flags = AMediaExtractor_getSampleFlags(extractor);
203*b7c941bbSAndroid Build Coastguard Worker             int trackID = AMediaExtractor_getSampleTrackIndex(extractor);
204*b7c941bbSAndroid Build Coastguard Worker             mTrackIdxOrder.push_back(trackID);
205*b7c941bbSAndroid Build Coastguard Worker             mBufferInfo[(mInpIndexMap.at(trackID))].push_back(bufferInfo);
206*b7c941bbSAndroid Build Coastguard Worker             AMediaExtractor_advance(extractor);
207*b7c941bbSAndroid Build Coastguard Worker             frameCount++;
208*b7c941bbSAndroid Build Coastguard Worker         }
209*b7c941bbSAndroid Build Coastguard Worker         offset += bufferInfo->size;
210*b7c941bbSAndroid Build Coastguard Worker     }
211*b7c941bbSAndroid Build Coastguard Worker     ALOGV("frameCount:%d", frameCount);
212*b7c941bbSAndroid Build Coastguard Worker     AMediaExtractor_delete(extractor);
213*b7c941bbSAndroid Build Coastguard Worker     fclose(ifp);
214*b7c941bbSAndroid Build Coastguard Worker }
215*b7c941bbSAndroid Build Coastguard Worker 
registerTrack(AMediaMuxer * muxer)216*b7c941bbSAndroid Build Coastguard Worker bool MuxerNativeTestHelper::registerTrack(AMediaMuxer* muxer) {
217*b7c941bbSAndroid Build Coastguard Worker     for (int trackID = 0; trackID < mTrackCount; trackID++) {
218*b7c941bbSAndroid Build Coastguard Worker         int dstIndex = AMediaMuxer_addTrack(muxer, mFormat[trackID]);
219*b7c941bbSAndroid Build Coastguard Worker         if (dstIndex < 0) return false;
220*b7c941bbSAndroid Build Coastguard Worker         mOutIndexMap[trackID] = dstIndex;
221*b7c941bbSAndroid Build Coastguard Worker     }
222*b7c941bbSAndroid Build Coastguard Worker     return true;
223*b7c941bbSAndroid Build Coastguard Worker }
224*b7c941bbSAndroid Build Coastguard Worker 
insertSampleData(AMediaMuxer * muxer)225*b7c941bbSAndroid Build Coastguard Worker bool MuxerNativeTestHelper::insertSampleData(AMediaMuxer* muxer) {
226*b7c941bbSAndroid Build Coastguard Worker     // write all registered tracks in interleaved order
227*b7c941bbSAndroid Build Coastguard Worker     int* frameCount = new int[mTrackCount]{0};
228*b7c941bbSAndroid Build Coastguard Worker     for (int trackID : mTrackIdxOrder) {
229*b7c941bbSAndroid Build Coastguard Worker         int index = mInpIndexMap.at(trackID);
230*b7c941bbSAndroid Build Coastguard Worker         AMediaCodecBufferInfo* info = mBufferInfo[index][frameCount[index]];
231*b7c941bbSAndroid Build Coastguard Worker         if (AMediaMuxer_writeSampleData(muxer, mOutIndexMap.at(index), mBuffer, info) !=
232*b7c941bbSAndroid Build Coastguard Worker             AMEDIA_OK) {
233*b7c941bbSAndroid Build Coastguard Worker             delete[] frameCount;
234*b7c941bbSAndroid Build Coastguard Worker             return false;
235*b7c941bbSAndroid Build Coastguard Worker         }
236*b7c941bbSAndroid Build Coastguard Worker         ALOGV("Track: %d Timestamp: %" PRId64 "", trackID, info->presentationTimeUs);
237*b7c941bbSAndroid Build Coastguard Worker         frameCount[index]++;
238*b7c941bbSAndroid Build Coastguard Worker     }
239*b7c941bbSAndroid Build Coastguard Worker     delete[] frameCount;
240*b7c941bbSAndroid Build Coastguard Worker     ALOGV("Total track samples %zu", mTrackIdxOrder.size());
241*b7c941bbSAndroid Build Coastguard Worker     return true;
242*b7c941bbSAndroid Build Coastguard Worker }
243*b7c941bbSAndroid Build Coastguard Worker 
writeAFewSamplesData(AMediaMuxer * muxer,uint32_t fromIndex,uint32_t toIndex)244*b7c941bbSAndroid Build Coastguard Worker bool MuxerNativeTestHelper::writeAFewSamplesData(AMediaMuxer* muxer, uint32_t fromIndex,
245*b7c941bbSAndroid Build Coastguard Worker                                                  uint32_t toIndex) {
246*b7c941bbSAndroid Build Coastguard Worker     ALOGV("fromIndex:%u, toIndex:%u", fromIndex, toIndex);
247*b7c941bbSAndroid Build Coastguard Worker     // write all registered tracks in interleaved order
248*b7c941bbSAndroid Build Coastguard Worker     ALOGV("mTrackIdxOrder.size:%zu", mTrackIdxOrder.size());
249*b7c941bbSAndroid Build Coastguard Worker     if (fromIndex > toIndex || toIndex >= mTrackIdxOrder.size()) {
250*b7c941bbSAndroid Build Coastguard Worker         ALOGE("wrong index");
251*b7c941bbSAndroid Build Coastguard Worker         return false;
252*b7c941bbSAndroid Build Coastguard Worker     }
253*b7c941bbSAndroid Build Coastguard Worker     int* frameCount = new int[mTrackCount]{0};
254*b7c941bbSAndroid Build Coastguard Worker     for (int i = 0; i < fromIndex; ++i) {
255*b7c941bbSAndroid Build Coastguard Worker         ++frameCount[mInpIndexMap.at(mTrackIdxOrder[i])];
256*b7c941bbSAndroid Build Coastguard Worker     }
257*b7c941bbSAndroid Build Coastguard Worker     ALOGV("Initial samples skipped:");
258*b7c941bbSAndroid Build Coastguard Worker     for (int i = 0; i < mTrackCount; ++i) {
259*b7c941bbSAndroid Build Coastguard Worker         ALOGV("i:%d:%d", i, frameCount[i]);
260*b7c941bbSAndroid Build Coastguard Worker     }
261*b7c941bbSAndroid Build Coastguard Worker     for (int i = fromIndex; i <= toIndex; ++i) {
262*b7c941bbSAndroid Build Coastguard Worker         int trackID = mTrackIdxOrder[i];
263*b7c941bbSAndroid Build Coastguard Worker         int trackIndex = mInpIndexMap.at(trackID);
264*b7c941bbSAndroid Build Coastguard Worker         ALOGV("trackID:%d, trackIndex:%d, frameCount:%d", trackID, trackIndex,
265*b7c941bbSAndroid Build Coastguard Worker               frameCount[trackIndex]);
266*b7c941bbSAndroid Build Coastguard Worker         AMediaCodecBufferInfo* info = mBufferInfo[trackIndex][frameCount[trackIndex]];
267*b7c941bbSAndroid Build Coastguard Worker         ALOGV("Got info offset:%d, size:%d", info->offset, info->size);
268*b7c941bbSAndroid Build Coastguard Worker         if (AMediaMuxer_writeSampleData(muxer, mOutIndexMap.at(trackIndex), mBuffer, info) !=
269*b7c941bbSAndroid Build Coastguard Worker             AMEDIA_OK) {
270*b7c941bbSAndroid Build Coastguard Worker             delete[] frameCount;
271*b7c941bbSAndroid Build Coastguard Worker             return false;
272*b7c941bbSAndroid Build Coastguard Worker         }
273*b7c941bbSAndroid Build Coastguard Worker         ALOGV("Track: %d Timestamp: %" PRId64 "", trackID, info->presentationTimeUs);
274*b7c941bbSAndroid Build Coastguard Worker         ++frameCount[trackIndex];
275*b7c941bbSAndroid Build Coastguard Worker     }
276*b7c941bbSAndroid Build Coastguard Worker     ALOGV("Last sample counts:");
277*b7c941bbSAndroid Build Coastguard Worker     for (int i = 0; i < mTrackCount; ++i) {
278*b7c941bbSAndroid Build Coastguard Worker         ALOGV("i:%d", frameCount[i]);
279*b7c941bbSAndroid Build Coastguard Worker     }
280*b7c941bbSAndroid Build Coastguard Worker     delete[] frameCount;
281*b7c941bbSAndroid Build Coastguard Worker     return true;
282*b7c941bbSAndroid Build Coastguard Worker }
283*b7c941bbSAndroid Build Coastguard Worker 
writeAFewSamplesDataFromTime(AMediaMuxer * muxer,int64_t * fromTime,uint32_t numSamples,bool lastSplit)284*b7c941bbSAndroid Build Coastguard Worker bool MuxerNativeTestHelper::writeAFewSamplesDataFromTime(AMediaMuxer* muxer, int64_t* fromTime,
285*b7c941bbSAndroid Build Coastguard Worker                                                          uint32_t numSamples, bool lastSplit) {
286*b7c941bbSAndroid Build Coastguard Worker     for (int tc = 0; tc < mTrackCount; ++tc) {
287*b7c941bbSAndroid Build Coastguard Worker         ALOGV("fromTime[%d]:%lld", tc, (long long)fromTime[tc]);
288*b7c941bbSAndroid Build Coastguard Worker     }
289*b7c941bbSAndroid Build Coastguard Worker     ALOGV("numSamples:%u", numSamples);
290*b7c941bbSAndroid Build Coastguard Worker     uint32_t samplesWritten = 0;
291*b7c941bbSAndroid Build Coastguard Worker     uint32_t i = 0;
292*b7c941bbSAndroid Build Coastguard Worker     int* frameCount = new int[mTrackCount]{0};
293*b7c941bbSAndroid Build Coastguard Worker     do {
294*b7c941bbSAndroid Build Coastguard Worker         int trackID = mTrackIdxOrder[i++];
295*b7c941bbSAndroid Build Coastguard Worker         int trackIndex = mInpIndexMap.at(trackID);
296*b7c941bbSAndroid Build Coastguard Worker         ALOGV("trackID:%d, trackIndex:%d, frameCount:%d", trackID, trackIndex,
297*b7c941bbSAndroid Build Coastguard Worker               frameCount[trackIndex]);
298*b7c941bbSAndroid Build Coastguard Worker         AMediaCodecBufferInfo* info = mBufferInfo[trackIndex][frameCount[trackIndex]];
299*b7c941bbSAndroid Build Coastguard Worker         ++frameCount[trackIndex];
300*b7c941bbSAndroid Build Coastguard Worker         ALOGV("Got info offset:%d, size:%d, PTS:%" PRId64 "", info->offset, info->size,
301*b7c941bbSAndroid Build Coastguard Worker               info->presentationTimeUs);
302*b7c941bbSAndroid Build Coastguard Worker         if (info->presentationTimeUs < fromTime[trackID]) {
303*b7c941bbSAndroid Build Coastguard Worker             ALOGV("skipped");
304*b7c941bbSAndroid Build Coastguard Worker             continue;
305*b7c941bbSAndroid Build Coastguard Worker         }
306*b7c941bbSAndroid Build Coastguard Worker         if (AMediaMuxer_writeSampleData(muxer, mOutIndexMap.at(trackIndex), mBuffer, info) !=
307*b7c941bbSAndroid Build Coastguard Worker             AMEDIA_OK) {
308*b7c941bbSAndroid Build Coastguard Worker             delete[] frameCount;
309*b7c941bbSAndroid Build Coastguard Worker             return false;
310*b7c941bbSAndroid Build Coastguard Worker         } else {
311*b7c941bbSAndroid Build Coastguard Worker             ++samplesWritten;
312*b7c941bbSAndroid Build Coastguard Worker         }
313*b7c941bbSAndroid Build Coastguard Worker     } while ((lastSplit) ? (i < mTrackIdxOrder.size())
314*b7c941bbSAndroid Build Coastguard Worker                          : ((samplesWritten < numSamples) && (i < mTrackIdxOrder.size())));
315*b7c941bbSAndroid Build Coastguard Worker     ALOGV("samplesWritten:%u", samplesWritten);
316*b7c941bbSAndroid Build Coastguard Worker 
317*b7c941bbSAndroid Build Coastguard Worker     delete[] frameCount;
318*b7c941bbSAndroid Build Coastguard Worker     return true;
319*b7c941bbSAndroid Build Coastguard Worker }
320*b7c941bbSAndroid Build Coastguard Worker 
muxMedia(AMediaMuxer * muxer)321*b7c941bbSAndroid Build Coastguard Worker bool MuxerNativeTestHelper::muxMedia(AMediaMuxer* muxer) {
322*b7c941bbSAndroid Build Coastguard Worker     return (registerTrack(muxer) && (AMediaMuxer_start(muxer) == AMEDIA_OK) &&
323*b7c941bbSAndroid Build Coastguard Worker             insertSampleData(muxer) && (AMediaMuxer_stop(muxer) == AMEDIA_OK));
324*b7c941bbSAndroid Build Coastguard Worker }
325*b7c941bbSAndroid Build Coastguard Worker 
appendMedia(AMediaMuxer * muxer,uint32_t fromIndex,uint32_t toIndex)326*b7c941bbSAndroid Build Coastguard Worker bool MuxerNativeTestHelper::appendMedia(AMediaMuxer *muxer, uint32_t fromIndex, uint32_t toIndex) {
327*b7c941bbSAndroid Build Coastguard Worker     if (__builtin_available(android __TRANSCODING_MIN_API__, *)) {
328*b7c941bbSAndroid Build Coastguard Worker         ALOGV("fromIndex:%u, toIndex:%u", fromIndex, toIndex);
329*b7c941bbSAndroid Build Coastguard Worker         if (fromIndex == 0) {
330*b7c941bbSAndroid Build Coastguard Worker             registerTrack(muxer);
331*b7c941bbSAndroid Build Coastguard Worker         } else {
332*b7c941bbSAndroid Build Coastguard Worker             size_t trackCount = AMediaMuxer_getTrackCount(muxer);
333*b7c941bbSAndroid Build Coastguard Worker             ALOGV("appendMedia:trackCount:%zu", trackCount);
334*b7c941bbSAndroid Build Coastguard Worker             for(size_t i = 0; i < trackCount; ++i) {
335*b7c941bbSAndroid Build Coastguard Worker                 ALOGV("track i:%zu", i);
336*b7c941bbSAndroid Build Coastguard Worker                 ALOGV("%s", AMediaFormat_toString(AMediaMuxer_getTrackFormat(muxer, i)));
337*b7c941bbSAndroid Build Coastguard Worker                 ALOGV("%s", AMediaFormat_toString(mFormat[i]));
338*b7c941bbSAndroid Build Coastguard Worker                 for(size_t j = 0; j < mFormat.size(); ++j) {
339*b7c941bbSAndroid Build Coastguard Worker                     const char* thatMediaType = nullptr;
340*b7c941bbSAndroid Build Coastguard Worker                     AMediaFormat_getString(AMediaMuxer_getTrackFormat(muxer, i),
341*b7c941bbSAndroid Build Coastguard Worker                                                 AMEDIAFORMAT_KEY_MIME, &thatMediaType);
342*b7c941bbSAndroid Build Coastguard Worker                     const char* thisMediaType = nullptr;
343*b7c941bbSAndroid Build Coastguard Worker                     AMediaFormat_getString(mFormat[j], AMEDIAFORMAT_KEY_MIME, &thisMediaType);
344*b7c941bbSAndroid Build Coastguard Worker                     ALOGV("strlen(thisMediaType)%zu", strlen(thisMediaType));
345*b7c941bbSAndroid Build Coastguard Worker                     if (strcmp(thatMediaType, thisMediaType) == 0) {
346*b7c941bbSAndroid Build Coastguard Worker                         ALOGV("appendMedia:i:%zu, j:%zu", i, j);
347*b7c941bbSAndroid Build Coastguard Worker                         mOutIndexMap[j]=i;
348*b7c941bbSAndroid Build Coastguard Worker                     }
349*b7c941bbSAndroid Build Coastguard Worker                 }
350*b7c941bbSAndroid Build Coastguard Worker             }
351*b7c941bbSAndroid Build Coastguard Worker         }
352*b7c941bbSAndroid Build Coastguard Worker         AMediaMuxer_start(muxer);
353*b7c941bbSAndroid Build Coastguard Worker         bool res = writeAFewSamplesData(muxer, fromIndex, toIndex);
354*b7c941bbSAndroid Build Coastguard Worker         AMediaMuxer_stop(muxer);
355*b7c941bbSAndroid Build Coastguard Worker         return res;
356*b7c941bbSAndroid Build Coastguard Worker     } else {
357*b7c941bbSAndroid Build Coastguard Worker         return false;
358*b7c941bbSAndroid Build Coastguard Worker     }
359*b7c941bbSAndroid Build Coastguard Worker }
360*b7c941bbSAndroid Build Coastguard Worker 
appendMediaFromTime(AMediaMuxer * muxer,int64_t * appendFromTime,uint32_t numSamples,bool lastSplit)361*b7c941bbSAndroid Build Coastguard Worker bool MuxerNativeTestHelper::appendMediaFromTime(AMediaMuxer *muxer, int64_t *appendFromTime,
362*b7c941bbSAndroid Build Coastguard Worker                                                         uint32_t numSamples, bool lastSplit) {
363*b7c941bbSAndroid Build Coastguard Worker     if (__builtin_available(android __TRANSCODING_MIN_API__, *)) {
364*b7c941bbSAndroid Build Coastguard Worker         size_t trackCount = AMediaMuxer_getTrackCount(muxer);
365*b7c941bbSAndroid Build Coastguard Worker         ALOGV("appendMediaFromTime:trackCount:%zu", trackCount);
366*b7c941bbSAndroid Build Coastguard Worker         for(size_t i = 0; i < trackCount; ++i) {
367*b7c941bbSAndroid Build Coastguard Worker             ALOGV("track i:%zu", i);
368*b7c941bbSAndroid Build Coastguard Worker             ALOGV("%s", AMediaFormat_toString(AMediaMuxer_getTrackFormat(muxer, i)));
369*b7c941bbSAndroid Build Coastguard Worker             ALOGV("%s", AMediaFormat_toString(mFormat[i]));
370*b7c941bbSAndroid Build Coastguard Worker             for(size_t j = 0; j < mFormat.size(); ++j) {
371*b7c941bbSAndroid Build Coastguard Worker                 const char* thatMediaType = nullptr;
372*b7c941bbSAndroid Build Coastguard Worker                 AMediaFormat_getString(AMediaMuxer_getTrackFormat(muxer, i),
373*b7c941bbSAndroid Build Coastguard Worker                                        AMEDIAFORMAT_KEY_MIME, &thatMediaType);
374*b7c941bbSAndroid Build Coastguard Worker                 const char* thisMediaType = nullptr;
375*b7c941bbSAndroid Build Coastguard Worker                 AMediaFormat_getString(mFormat[j], AMEDIAFORMAT_KEY_MIME, &thisMediaType);
376*b7c941bbSAndroid Build Coastguard Worker                 ALOGV("strlen(thisMediaType)%zu", strlen(thisMediaType));
377*b7c941bbSAndroid Build Coastguard Worker                 if (strcmp(thatMediaType, thisMediaType) == 0) {
378*b7c941bbSAndroid Build Coastguard Worker                     ALOGV("appendMediaFromTime:i:%zu, j:%zu", i, j);
379*b7c941bbSAndroid Build Coastguard Worker                     mOutIndexMap[j]=i;
380*b7c941bbSAndroid Build Coastguard Worker                 }
381*b7c941bbSAndroid Build Coastguard Worker             }
382*b7c941bbSAndroid Build Coastguard Worker         }
383*b7c941bbSAndroid Build Coastguard Worker         AMediaMuxer_start(muxer);
384*b7c941bbSAndroid Build Coastguard Worker         bool res = writeAFewSamplesDataFromTime(muxer, appendFromTime, numSamples, lastSplit);
385*b7c941bbSAndroid Build Coastguard Worker         AMediaMuxer_stop(muxer);
386*b7c941bbSAndroid Build Coastguard Worker         return res;
387*b7c941bbSAndroid Build Coastguard Worker     } else {
388*b7c941bbSAndroid Build Coastguard Worker         return false;
389*b7c941bbSAndroid Build Coastguard Worker     }
390*b7c941bbSAndroid Build Coastguard Worker }
combineMedias(AMediaMuxer * muxer,MuxerNativeTestHelper * that,const int * repeater)391*b7c941bbSAndroid Build Coastguard Worker bool MuxerNativeTestHelper::combineMedias(AMediaMuxer* muxer, MuxerNativeTestHelper* that,
392*b7c941bbSAndroid Build Coastguard Worker                                           const int* repeater) {
393*b7c941bbSAndroid Build Coastguard Worker     if (that == nullptr) return false;
394*b7c941bbSAndroid Build Coastguard Worker     if (repeater == nullptr) return false;
395*b7c941bbSAndroid Build Coastguard Worker 
396*b7c941bbSAndroid Build Coastguard Worker     // register tracks
397*b7c941bbSAndroid Build Coastguard Worker     int totalTracksToAdd = repeater[0] * this->mTrackCount + repeater[1] * that->mTrackCount;
398*b7c941bbSAndroid Build Coastguard Worker     int outIndexMap[totalTracksToAdd];
399*b7c941bbSAndroid Build Coastguard Worker     MuxerNativeTestHelper* group[2]{this, that};
400*b7c941bbSAndroid Build Coastguard Worker     for (int k = 0, idx = 0; k < 2; k++) {
401*b7c941bbSAndroid Build Coastguard Worker         for (int j = 0; j < repeater[k]; j++) {
402*b7c941bbSAndroid Build Coastguard Worker             for (AMediaFormat* format : group[k]->mFormat) {
403*b7c941bbSAndroid Build Coastguard Worker                 int dstIndex = AMediaMuxer_addTrack(muxer, format);
404*b7c941bbSAndroid Build Coastguard Worker                 if (dstIndex < 0) return false;
405*b7c941bbSAndroid Build Coastguard Worker                 outIndexMap[idx++] = dstIndex;
406*b7c941bbSAndroid Build Coastguard Worker             }
407*b7c941bbSAndroid Build Coastguard Worker         }
408*b7c941bbSAndroid Build Coastguard Worker     }
409*b7c941bbSAndroid Build Coastguard Worker     // start
410*b7c941bbSAndroid Build Coastguard Worker     if (AMediaMuxer_start(muxer) != AMEDIA_OK) return false;
411*b7c941bbSAndroid Build Coastguard Worker     // write sample data
412*b7c941bbSAndroid Build Coastguard Worker     // write all registered tracks in planar order viz all samples of a track A then all
413*b7c941bbSAndroid Build Coastguard Worker     // samples of track B, ...
414*b7c941bbSAndroid Build Coastguard Worker     for (int k = 0, idx = 0; k < 2; k++) {
415*b7c941bbSAndroid Build Coastguard Worker         for (int j = 0; j < repeater[k]; j++) {
416*b7c941bbSAndroid Build Coastguard Worker             for (int i = 0; i < group[k]->mTrackCount; i++) {
417*b7c941bbSAndroid Build Coastguard Worker                 for (int p = 0; p < group[k]->mBufferInfo[i].size(); p++) {
418*b7c941bbSAndroid Build Coastguard Worker                     AMediaCodecBufferInfo* info = group[k]->mBufferInfo[i][p];
419*b7c941bbSAndroid Build Coastguard Worker                     if (AMediaMuxer_writeSampleData(muxer, outIndexMap[idx], group[k]->mBuffer,
420*b7c941bbSAndroid Build Coastguard Worker                                                     info) != AMEDIA_OK) {
421*b7c941bbSAndroid Build Coastguard Worker                         return false;
422*b7c941bbSAndroid Build Coastguard Worker                     }
423*b7c941bbSAndroid Build Coastguard Worker                     ALOGV("Track: %d Timestamp: %" PRId64 "", outIndexMap[idx],
424*b7c941bbSAndroid Build Coastguard Worker                           info->presentationTimeUs);
425*b7c941bbSAndroid Build Coastguard Worker                 }
426*b7c941bbSAndroid Build Coastguard Worker                 idx++;
427*b7c941bbSAndroid Build Coastguard Worker             }
428*b7c941bbSAndroid Build Coastguard Worker         }
429*b7c941bbSAndroid Build Coastguard Worker     }
430*b7c941bbSAndroid Build Coastguard Worker     // stop
431*b7c941bbSAndroid Build Coastguard Worker     return (AMediaMuxer_stop(muxer) == AMEDIA_OK);
432*b7c941bbSAndroid Build Coastguard Worker }
433*b7c941bbSAndroid Build Coastguard Worker 
434*b7c941bbSAndroid Build Coastguard Worker // returns true if 'this' stream is a subset of 'that'. That is all tracks in current media
435*b7c941bbSAndroid Build Coastguard Worker // stream are present in ref media stream
isSubsetOf(MuxerNativeTestHelper * that)436*b7c941bbSAndroid Build Coastguard Worker bool MuxerNativeTestHelper::isSubsetOf(MuxerNativeTestHelper* that) {
437*b7c941bbSAndroid Build Coastguard Worker     if (this == that) return true;
438*b7c941bbSAndroid Build Coastguard Worker     if (that == nullptr) return false;
439*b7c941bbSAndroid Build Coastguard Worker 
440*b7c941bbSAndroid Build Coastguard Worker     for (int i = 0; i < mTrackCount; i++) {
441*b7c941bbSAndroid Build Coastguard Worker         AMediaFormat* thisFormat = mFormat[i];
442*b7c941bbSAndroid Build Coastguard Worker         const char* thisMediaType = nullptr;
443*b7c941bbSAndroid Build Coastguard Worker         AMediaFormat_getString(thisFormat, AMEDIAFORMAT_KEY_MIME, &thisMediaType);
444*b7c941bbSAndroid Build Coastguard Worker         int tolerance = !strncmp(thisMediaType, "video/", strlen("video/")) ? STTS_TOLERANCE_US : 0;
445*b7c941bbSAndroid Build Coastguard Worker         tolerance += 1;  // rounding error
446*b7c941bbSAndroid Build Coastguard Worker         int j = 0;
447*b7c941bbSAndroid Build Coastguard Worker         for (; j < that->mTrackCount; j++) {
448*b7c941bbSAndroid Build Coastguard Worker             AMediaFormat* thatFormat = that->mFormat[j];
449*b7c941bbSAndroid Build Coastguard Worker             const char* thatMediaType = nullptr;
450*b7c941bbSAndroid Build Coastguard Worker             AMediaFormat_getString(thatFormat, AMEDIAFORMAT_KEY_MIME, &thatMediaType);
451*b7c941bbSAndroid Build Coastguard Worker             if (thisMediaType != nullptr && thatMediaType != nullptr &&
452*b7c941bbSAndroid Build Coastguard Worker                 !strcmp(thisMediaType, thatMediaType)) {
453*b7c941bbSAndroid Build Coastguard Worker                 if (!isFormatSimilar(thisFormat, thatFormat)) continue;
454*b7c941bbSAndroid Build Coastguard Worker                 if (mBufferInfo[i].size() <= that->mBufferInfo[j].size()) {
455*b7c941bbSAndroid Build Coastguard Worker                     int tolerance = !strncmp(thisMediaType, "video/", strlen("video/"))
456*b7c941bbSAndroid Build Coastguard Worker                                             ? STTS_TOLERANCE_US
457*b7c941bbSAndroid Build Coastguard Worker                                             : 0;
458*b7c941bbSAndroid Build Coastguard Worker                     tolerance += 1;  // rounding error
459*b7c941bbSAndroid Build Coastguard Worker                     int k = 0;
460*b7c941bbSAndroid Build Coastguard Worker                     for (; k < mBufferInfo[i].size(); k++) {
461*b7c941bbSAndroid Build Coastguard Worker                         ALOGV("k:%d", k);
462*b7c941bbSAndroid Build Coastguard Worker                         AMediaCodecBufferInfo* thisInfo = mBufferInfo[i][k];
463*b7c941bbSAndroid Build Coastguard Worker                         AMediaCodecBufferInfo* thatInfo = that->mBufferInfo[j][k];
464*b7c941bbSAndroid Build Coastguard Worker                         if (thisInfo->flags != thatInfo->flags) {
465*b7c941bbSAndroid Build Coastguard Worker                             ALOGD("flags this:%u, that:%u", thisInfo->flags, thatInfo->flags);
466*b7c941bbSAndroid Build Coastguard Worker                             break;
467*b7c941bbSAndroid Build Coastguard Worker                         }
468*b7c941bbSAndroid Build Coastguard Worker                         if (thisInfo->size != thatInfo->size) {
469*b7c941bbSAndroid Build Coastguard Worker                             ALOGD("size  this:%d, that:%d", thisInfo->size, thatInfo->size);
470*b7c941bbSAndroid Build Coastguard Worker                             break;
471*b7c941bbSAndroid Build Coastguard Worker                         } else if (memcmp(mBuffer + thisInfo->offset,
472*b7c941bbSAndroid Build Coastguard Worker                                           that->mBuffer + thatInfo->offset, thisInfo->size)) {
473*b7c941bbSAndroid Build Coastguard Worker                             ALOGD("memcmp failed");
474*b7c941bbSAndroid Build Coastguard Worker                             break;
475*b7c941bbSAndroid Build Coastguard Worker                         }
476*b7c941bbSAndroid Build Coastguard Worker                         if (abs(thisInfo->presentationTimeUs - thatInfo->presentationTimeUs) >
477*b7c941bbSAndroid Build Coastguard Worker                             tolerance) {
478*b7c941bbSAndroid Build Coastguard Worker                             ALOGD("time this:%lld, that:%lld",
479*b7c941bbSAndroid Build Coastguard Worker                                   (long long)thisInfo->presentationTimeUs,
480*b7c941bbSAndroid Build Coastguard Worker                                   (long long)thatInfo->presentationTimeUs);
481*b7c941bbSAndroid Build Coastguard Worker                             break;
482*b7c941bbSAndroid Build Coastguard Worker                         }
483*b7c941bbSAndroid Build Coastguard Worker                     }
484*b7c941bbSAndroid Build Coastguard Worker                     if (k == mBufferInfo[i].size()) break;
485*b7c941bbSAndroid Build Coastguard Worker                 }
486*b7c941bbSAndroid Build Coastguard Worker             }
487*b7c941bbSAndroid Build Coastguard Worker         }
488*b7c941bbSAndroid Build Coastguard Worker         if (j == that->mTrackCount) {
489*b7c941bbSAndroid Build Coastguard Worker             AMediaFormat_getString(thisFormat, AMEDIAFORMAT_KEY_MIME, &thisMediaType);
490*b7c941bbSAndroid Build Coastguard Worker             ALOGV("For media type %s, Couldn't find a match", thisMediaType);
491*b7c941bbSAndroid Build Coastguard Worker             return false;
492*b7c941bbSAndroid Build Coastguard Worker         }
493*b7c941bbSAndroid Build Coastguard Worker     }
494*b7c941bbSAndroid Build Coastguard Worker     return true;
495*b7c941bbSAndroid Build Coastguard Worker }
496*b7c941bbSAndroid Build Coastguard Worker 
offsetTimeStamp(int64_t tsAudioOffsetUs,int64_t tsVideoOffsetUs,int sampleOffset)497*b7c941bbSAndroid Build Coastguard Worker void MuxerNativeTestHelper::offsetTimeStamp(int64_t tsAudioOffsetUs, int64_t tsVideoOffsetUs,
498*b7c941bbSAndroid Build Coastguard Worker                                             int sampleOffset) {
499*b7c941bbSAndroid Build Coastguard Worker     // offset pts of samples from index sampleOffset till the end by tsOffset for each audio and
500*b7c941bbSAndroid Build Coastguard Worker     // video track
501*b7c941bbSAndroid Build Coastguard Worker     for (int trackID = 0; trackID < mTrackCount; trackID++) {
502*b7c941bbSAndroid Build Coastguard Worker         int64_t tsOffsetUs = 0;
503*b7c941bbSAndroid Build Coastguard Worker         const char* thisMediaType = nullptr;
504*b7c941bbSAndroid Build Coastguard Worker         AMediaFormat_getString(mFormat[trackID], AMEDIAFORMAT_KEY_MIME, &thisMediaType);
505*b7c941bbSAndroid Build Coastguard Worker         if (thisMediaType != nullptr) {
506*b7c941bbSAndroid Build Coastguard Worker             if (strncmp(thisMediaType, "video/", strlen("video/")) == 0) {
507*b7c941bbSAndroid Build Coastguard Worker                 tsOffsetUs = tsVideoOffsetUs;
508*b7c941bbSAndroid Build Coastguard Worker             } else if (strncmp(thisMediaType, "audio/", strlen("audio/")) == 0) {
509*b7c941bbSAndroid Build Coastguard Worker                 tsOffsetUs = tsAudioOffsetUs;
510*b7c941bbSAndroid Build Coastguard Worker             }
511*b7c941bbSAndroid Build Coastguard Worker             for (int i = sampleOffset; i < mBufferInfo[trackID].size(); i++) {
512*b7c941bbSAndroid Build Coastguard Worker                 AMediaCodecBufferInfo* info = mBufferInfo[trackID][i];
513*b7c941bbSAndroid Build Coastguard Worker                 info->presentationTimeUs += tsOffsetUs;
514*b7c941bbSAndroid Build Coastguard Worker             }
515*b7c941bbSAndroid Build Coastguard Worker         }
516*b7c941bbSAndroid Build Coastguard Worker     }
517*b7c941bbSAndroid Build Coastguard Worker }
518*b7c941bbSAndroid Build Coastguard Worker 
isCodecContainerPairValid(OutputFormat format,const char * mediaType)519*b7c941bbSAndroid Build Coastguard Worker static bool isCodecContainerPairValid(OutputFormat format, const char* mediaType) {
520*b7c941bbSAndroid Build Coastguard Worker     static const std::map<OutputFormat, std::vector<const char*>> codecListforType = {
521*b7c941bbSAndroid Build Coastguard Worker             {AMEDIAMUXER_OUTPUT_FORMAT_MPEG_4,
522*b7c941bbSAndroid Build Coastguard Worker              {AMEDIA_MIMETYPE_VIDEO_MPEG4, AMEDIA_MIMETYPE_VIDEO_H263, AMEDIA_MIMETYPE_VIDEO_AVC,
523*b7c941bbSAndroid Build Coastguard Worker               AMEDIA_MIMETYPE_VIDEO_HEVC, AMEDIA_MIMETYPE_AUDIO_AAC}},
524*b7c941bbSAndroid Build Coastguard Worker             {AMEDIAMUXER_OUTPUT_FORMAT_WEBM,
525*b7c941bbSAndroid Build Coastguard Worker              {AMEDIA_MIMETYPE_VIDEO_VP8, AMEDIA_MIMETYPE_VIDEO_VP9, AMEDIA_MIMETYPE_AUDIO_VORBIS,
526*b7c941bbSAndroid Build Coastguard Worker               AMEDIA_MIMETYPE_AUDIO_OPUS}},
527*b7c941bbSAndroid Build Coastguard Worker             {AMEDIAMUXER_OUTPUT_FORMAT_THREE_GPP,
528*b7c941bbSAndroid Build Coastguard Worker              {AMEDIA_MIMETYPE_VIDEO_MPEG4, AMEDIA_MIMETYPE_VIDEO_H263, AMEDIA_MIMETYPE_VIDEO_AVC,
529*b7c941bbSAndroid Build Coastguard Worker               AMEDIA_MIMETYPE_AUDIO_AAC, AMEDIA_MIMETYPE_AUDIO_AMR_NB,
530*b7c941bbSAndroid Build Coastguard Worker               AMEDIA_MIMETYPE_AUDIO_AMR_WB}},
531*b7c941bbSAndroid Build Coastguard Worker             {AMEDIAMUXER_OUTPUT_FORMAT_OGG, {AMEDIA_MIMETYPE_AUDIO_OPUS}},
532*b7c941bbSAndroid Build Coastguard Worker     };
533*b7c941bbSAndroid Build Coastguard Worker 
534*b7c941bbSAndroid Build Coastguard Worker     if (format == AMEDIAMUXER_OUTPUT_FORMAT_MPEG_4 &&
535*b7c941bbSAndroid Build Coastguard Worker         strncmp(mediaType, "application/", strlen("application/")) == 0)
536*b7c941bbSAndroid Build Coastguard Worker         return true;
537*b7c941bbSAndroid Build Coastguard Worker 
538*b7c941bbSAndroid Build Coastguard Worker     auto it = codecListforType.find(format);
539*b7c941bbSAndroid Build Coastguard Worker     if (it != codecListforType.end())
540*b7c941bbSAndroid Build Coastguard Worker         for (auto it2 : it->second)
541*b7c941bbSAndroid Build Coastguard Worker             if (strcmp(it2, mediaType) == 0) return true;
542*b7c941bbSAndroid Build Coastguard Worker 
543*b7c941bbSAndroid Build Coastguard Worker     return false;
544*b7c941bbSAndroid Build Coastguard Worker }
545*b7c941bbSAndroid Build Coastguard Worker 
nativeTestSetLocation(JNIEnv * env,jobject,jint jformat,jstring jsrcPath,jstring jdstPath)546*b7c941bbSAndroid Build Coastguard Worker static jboolean nativeTestSetLocation(JNIEnv* env, jobject, jint jformat, jstring jsrcPath,
547*b7c941bbSAndroid Build Coastguard Worker                                       jstring jdstPath) {
548*b7c941bbSAndroid Build Coastguard Worker     bool isPass = true;
549*b7c941bbSAndroid Build Coastguard Worker     bool isGeoDataSupported;
550*b7c941bbSAndroid Build Coastguard Worker     const float atlanticLat = 14.59f;
551*b7c941bbSAndroid Build Coastguard Worker     const float atlanticLong = 28.67f;
552*b7c941bbSAndroid Build Coastguard Worker     const float tooFarNorth = 90.5f;
553*b7c941bbSAndroid Build Coastguard Worker     const float tooFarWest = -180.5f;
554*b7c941bbSAndroid Build Coastguard Worker     const float tooFarSouth = -90.5f;
555*b7c941bbSAndroid Build Coastguard Worker     const float tooFarEast = 180.5f;
556*b7c941bbSAndroid Build Coastguard Worker     const float annapurnaLat = 28.59f;
557*b7c941bbSAndroid Build Coastguard Worker     const float annapurnaLong = 83.82f;
558*b7c941bbSAndroid Build Coastguard Worker     const char* cdstPath = env->GetStringUTFChars(jdstPath, nullptr);
559*b7c941bbSAndroid Build Coastguard Worker     FILE* ofp = fopen(cdstPath, "wbe+");
560*b7c941bbSAndroid Build Coastguard Worker     if (ofp) {
561*b7c941bbSAndroid Build Coastguard Worker         AMediaMuxer* muxer = AMediaMuxer_new(fileno(ofp), (OutputFormat)jformat);
562*b7c941bbSAndroid Build Coastguard Worker         media_status_t status = AMediaMuxer_setLocation(muxer, tooFarNorth, atlanticLong);
563*b7c941bbSAndroid Build Coastguard Worker         if (status == AMEDIA_OK) {
564*b7c941bbSAndroid Build Coastguard Worker             isPass = false;
565*b7c941bbSAndroid Build Coastguard Worker             ALOGE("setLocation succeeds on bad args: (%f, %f)", tooFarNorth, atlanticLong);
566*b7c941bbSAndroid Build Coastguard Worker         }
567*b7c941bbSAndroid Build Coastguard Worker         status = AMediaMuxer_setLocation(muxer, tooFarSouth, atlanticLong);
568*b7c941bbSAndroid Build Coastguard Worker         if (status == AMEDIA_OK) {
569*b7c941bbSAndroid Build Coastguard Worker             isPass = false;
570*b7c941bbSAndroid Build Coastguard Worker             ALOGE("setLocation succeeds on bad args: (%f, %f)", tooFarSouth, atlanticLong);
571*b7c941bbSAndroid Build Coastguard Worker         }
572*b7c941bbSAndroid Build Coastguard Worker         status = AMediaMuxer_setLocation(muxer, atlanticLat, tooFarWest);
573*b7c941bbSAndroid Build Coastguard Worker         if (status == AMEDIA_OK) {
574*b7c941bbSAndroid Build Coastguard Worker             isPass = false;
575*b7c941bbSAndroid Build Coastguard Worker             ALOGE("setLocation succeeds on bad args: (%f, %f)", atlanticLat, tooFarWest);
576*b7c941bbSAndroid Build Coastguard Worker         }
577*b7c941bbSAndroid Build Coastguard Worker         status = AMediaMuxer_setLocation(muxer, atlanticLat, tooFarEast);
578*b7c941bbSAndroid Build Coastguard Worker         if (status == AMEDIA_OK) {
579*b7c941bbSAndroid Build Coastguard Worker             isPass = false;
580*b7c941bbSAndroid Build Coastguard Worker             ALOGE("setLocation succeeds on bad args: (%f, %f)", atlanticLat, tooFarEast);
581*b7c941bbSAndroid Build Coastguard Worker         }
582*b7c941bbSAndroid Build Coastguard Worker         status = AMediaMuxer_setLocation(muxer, tooFarNorth, tooFarWest);
583*b7c941bbSAndroid Build Coastguard Worker         if (status == AMEDIA_OK) {
584*b7c941bbSAndroid Build Coastguard Worker             isPass = false;
585*b7c941bbSAndroid Build Coastguard Worker             ALOGE("setLocation succeeds on bad args: (%f, %f)", tooFarNorth, tooFarWest);
586*b7c941bbSAndroid Build Coastguard Worker         }
587*b7c941bbSAndroid Build Coastguard Worker         status = AMediaMuxer_setLocation(muxer, atlanticLat, atlanticLong);
588*b7c941bbSAndroid Build Coastguard Worker         isGeoDataSupported = (status == AMEDIA_OK);
589*b7c941bbSAndroid Build Coastguard Worker         if (isGeoDataSupported) {
590*b7c941bbSAndroid Build Coastguard Worker             status = AMediaMuxer_setLocation(muxer, annapurnaLat, annapurnaLong);
591*b7c941bbSAndroid Build Coastguard Worker             if (status != AMEDIA_OK) {
592*b7c941bbSAndroid Build Coastguard Worker                 isPass = false;
593*b7c941bbSAndroid Build Coastguard Worker                 ALOGE("setLocation fails on args: (%f, %f)", annapurnaLat, annapurnaLong);
594*b7c941bbSAndroid Build Coastguard Worker             }
595*b7c941bbSAndroid Build Coastguard Worker         } else {
596*b7c941bbSAndroid Build Coastguard Worker             isPass &= ((OutputFormat)jformat != AMEDIAMUXER_OUTPUT_FORMAT_MPEG_4 &&
597*b7c941bbSAndroid Build Coastguard Worker                        (OutputFormat)jformat != AMEDIAMUXER_OUTPUT_FORMAT_THREE_GPP);
598*b7c941bbSAndroid Build Coastguard Worker         }
599*b7c941bbSAndroid Build Coastguard Worker         const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
600*b7c941bbSAndroid Build Coastguard Worker         auto* mediaInfo = new MuxerNativeTestHelper(csrcPath);
601*b7c941bbSAndroid Build Coastguard Worker         if (mediaInfo->registerTrack(muxer) && AMediaMuxer_start(muxer) == AMEDIA_OK) {
602*b7c941bbSAndroid Build Coastguard Worker             status = AMediaMuxer_setLocation(muxer, atlanticLat, atlanticLong);
603*b7c941bbSAndroid Build Coastguard Worker             if (status == AMEDIA_OK) {
604*b7c941bbSAndroid Build Coastguard Worker                 isPass = false;
605*b7c941bbSAndroid Build Coastguard Worker                 ALOGE("setLocation succeeds after starting the muxer");
606*b7c941bbSAndroid Build Coastguard Worker             }
607*b7c941bbSAndroid Build Coastguard Worker             if (mediaInfo->insertSampleData(muxer) && AMediaMuxer_stop(muxer) == AMEDIA_OK) {
608*b7c941bbSAndroid Build Coastguard Worker                 status = AMediaMuxer_setLocation(muxer, atlanticLat, atlanticLong);
609*b7c941bbSAndroid Build Coastguard Worker                 if (status == AMEDIA_OK) {
610*b7c941bbSAndroid Build Coastguard Worker                     isPass = false;
611*b7c941bbSAndroid Build Coastguard Worker                     ALOGE("setLocation succeeds after stopping the muxer");
612*b7c941bbSAndroid Build Coastguard Worker                 }
613*b7c941bbSAndroid Build Coastguard Worker             } else {
614*b7c941bbSAndroid Build Coastguard Worker                 isPass = false;
615*b7c941bbSAndroid Build Coastguard Worker                 ALOGE("failed to writeSampleData or stop muxer");
616*b7c941bbSAndroid Build Coastguard Worker             }
617*b7c941bbSAndroid Build Coastguard Worker         } else {
618*b7c941bbSAndroid Build Coastguard Worker             isPass = false;
619*b7c941bbSAndroid Build Coastguard Worker             ALOGE("failed to addTrack or start muxer");
620*b7c941bbSAndroid Build Coastguard Worker         }
621*b7c941bbSAndroid Build Coastguard Worker         delete mediaInfo;
622*b7c941bbSAndroid Build Coastguard Worker         env->ReleaseStringUTFChars(jsrcPath, csrcPath);
623*b7c941bbSAndroid Build Coastguard Worker         AMediaMuxer_delete(muxer);
624*b7c941bbSAndroid Build Coastguard Worker         fclose(ofp);
625*b7c941bbSAndroid Build Coastguard Worker     } else {
626*b7c941bbSAndroid Build Coastguard Worker         isPass = false;
627*b7c941bbSAndroid Build Coastguard Worker         ALOGE("failed to open output file %s", cdstPath);
628*b7c941bbSAndroid Build Coastguard Worker     }
629*b7c941bbSAndroid Build Coastguard Worker     env->ReleaseStringUTFChars(jdstPath, cdstPath);
630*b7c941bbSAndroid Build Coastguard Worker     return static_cast<jboolean>(isPass);
631*b7c941bbSAndroid Build Coastguard Worker }
632*b7c941bbSAndroid Build Coastguard Worker 
633*b7c941bbSAndroid Build Coastguard Worker // @ApiTest = AMEDIAMUXER_OUTPUT_FORMAT_MPEG_4
634*b7c941bbSAndroid Build Coastguard Worker // @ApiTest = AMEDIAMUXER_OUTPUT_FORMAT_THREE_GPP
635*b7c941bbSAndroid Build Coastguard Worker //
nativeTestSetOrientationHint(JNIEnv * env,jobject,jint jformat,jstring jsrcPath,jstring jdstPath)636*b7c941bbSAndroid Build Coastguard Worker static jboolean nativeTestSetOrientationHint(JNIEnv* env, jobject, jint jformat, jstring jsrcPath,
637*b7c941bbSAndroid Build Coastguard Worker                                              jstring jdstPath) {
638*b7c941bbSAndroid Build Coastguard Worker     bool isPass = true;
639*b7c941bbSAndroid Build Coastguard Worker     bool isOrientationSupported;
640*b7c941bbSAndroid Build Coastguard Worker     const int badRotation[] = {360, 45, -90};
641*b7c941bbSAndroid Build Coastguard Worker     const int oldRotation = 90;
642*b7c941bbSAndroid Build Coastguard Worker     const int currRotation = 180;
643*b7c941bbSAndroid Build Coastguard Worker     const char* cdstPath = env->GetStringUTFChars(jdstPath, nullptr);
644*b7c941bbSAndroid Build Coastguard Worker     FILE* ofp = fopen(cdstPath, "wbe+");
645*b7c941bbSAndroid Build Coastguard Worker     if (ofp) {
646*b7c941bbSAndroid Build Coastguard Worker         AMediaMuxer* muxer = AMediaMuxer_new(fileno(ofp), (OutputFormat)jformat);
647*b7c941bbSAndroid Build Coastguard Worker         media_status_t status;
648*b7c941bbSAndroid Build Coastguard Worker         for (int degrees : badRotation) {
649*b7c941bbSAndroid Build Coastguard Worker             status = AMediaMuxer_setOrientationHint(muxer, degrees);
650*b7c941bbSAndroid Build Coastguard Worker             if (status == AMEDIA_OK) {
651*b7c941bbSAndroid Build Coastguard Worker                 isPass = false;
652*b7c941bbSAndroid Build Coastguard Worker                 ALOGE("setOrientationHint succeeds on bad args: %d", degrees);
653*b7c941bbSAndroid Build Coastguard Worker             }
654*b7c941bbSAndroid Build Coastguard Worker         }
655*b7c941bbSAndroid Build Coastguard Worker         status = AMediaMuxer_setOrientationHint(muxer, oldRotation);
656*b7c941bbSAndroid Build Coastguard Worker         isOrientationSupported = (status == AMEDIA_OK);
657*b7c941bbSAndroid Build Coastguard Worker         if (isOrientationSupported) {
658*b7c941bbSAndroid Build Coastguard Worker             status = AMediaMuxer_setOrientationHint(muxer, currRotation);
659*b7c941bbSAndroid Build Coastguard Worker             if (status != AMEDIA_OK) {
660*b7c941bbSAndroid Build Coastguard Worker                 isPass = false;
661*b7c941bbSAndroid Build Coastguard Worker                 ALOGE("setOrientationHint fails on args: %d", currRotation);
662*b7c941bbSAndroid Build Coastguard Worker             }
663*b7c941bbSAndroid Build Coastguard Worker         } else {
664*b7c941bbSAndroid Build Coastguard Worker             isPass &= ((OutputFormat)jformat != AMEDIAMUXER_OUTPUT_FORMAT_MPEG_4 &&
665*b7c941bbSAndroid Build Coastguard Worker                        (OutputFormat)jformat != AMEDIAMUXER_OUTPUT_FORMAT_THREE_GPP);
666*b7c941bbSAndroid Build Coastguard Worker         }
667*b7c941bbSAndroid Build Coastguard Worker         const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
668*b7c941bbSAndroid Build Coastguard Worker         auto* mediaInfo = new MuxerNativeTestHelper(csrcPath);
669*b7c941bbSAndroid Build Coastguard Worker         if (mediaInfo->registerTrack(muxer) && AMediaMuxer_start(muxer) == AMEDIA_OK) {
670*b7c941bbSAndroid Build Coastguard Worker             status = AMediaMuxer_setOrientationHint(muxer, currRotation);
671*b7c941bbSAndroid Build Coastguard Worker             if (status == AMEDIA_OK) {
672*b7c941bbSAndroid Build Coastguard Worker                 isPass = false;
673*b7c941bbSAndroid Build Coastguard Worker                 ALOGE("setOrientationHint succeeds after starting the muxer");
674*b7c941bbSAndroid Build Coastguard Worker             }
675*b7c941bbSAndroid Build Coastguard Worker             if (mediaInfo->insertSampleData(muxer) && AMediaMuxer_stop(muxer) == AMEDIA_OK) {
676*b7c941bbSAndroid Build Coastguard Worker                 status = AMediaMuxer_setOrientationHint(muxer, currRotation);
677*b7c941bbSAndroid Build Coastguard Worker                 if (status == AMEDIA_OK) {
678*b7c941bbSAndroid Build Coastguard Worker                     isPass = false;
679*b7c941bbSAndroid Build Coastguard Worker                     ALOGE("setOrientationHint succeeds after stopping the muxer");
680*b7c941bbSAndroid Build Coastguard Worker                 }
681*b7c941bbSAndroid Build Coastguard Worker             } else {
682*b7c941bbSAndroid Build Coastguard Worker                 isPass = false;
683*b7c941bbSAndroid Build Coastguard Worker                 ALOGE("failed to writeSampleData or stop muxer");
684*b7c941bbSAndroid Build Coastguard Worker             }
685*b7c941bbSAndroid Build Coastguard Worker         } else {
686*b7c941bbSAndroid Build Coastguard Worker             isPass = false;
687*b7c941bbSAndroid Build Coastguard Worker             ALOGE("failed to addTrack or start muxer");
688*b7c941bbSAndroid Build Coastguard Worker         }
689*b7c941bbSAndroid Build Coastguard Worker         delete mediaInfo;
690*b7c941bbSAndroid Build Coastguard Worker         env->ReleaseStringUTFChars(jsrcPath, csrcPath);
691*b7c941bbSAndroid Build Coastguard Worker         AMediaMuxer_delete(muxer);
692*b7c941bbSAndroid Build Coastguard Worker         fclose(ofp);
693*b7c941bbSAndroid Build Coastguard Worker     } else {
694*b7c941bbSAndroid Build Coastguard Worker         isPass = false;
695*b7c941bbSAndroid Build Coastguard Worker         ALOGE("failed to open output file %s", cdstPath);
696*b7c941bbSAndroid Build Coastguard Worker     }
697*b7c941bbSAndroid Build Coastguard Worker     env->ReleaseStringUTFChars(jdstPath, cdstPath);
698*b7c941bbSAndroid Build Coastguard Worker     return static_cast<jboolean>(isPass);
699*b7c941bbSAndroid Build Coastguard Worker }
700*b7c941bbSAndroid Build Coastguard Worker 
nativeTestMultiTrack(JNIEnv * env,jobject,jint jformat,jstring jsrcPathA,jstring jsrcPathB,jstring jrefPath,jstring jdstPath)701*b7c941bbSAndroid Build Coastguard Worker static jboolean nativeTestMultiTrack(JNIEnv* env, jobject, jint jformat, jstring jsrcPathA,
702*b7c941bbSAndroid Build Coastguard Worker                                      jstring jsrcPathB, jstring jrefPath, jstring jdstPath) {
703*b7c941bbSAndroid Build Coastguard Worker     bool isPass = true;
704*b7c941bbSAndroid Build Coastguard Worker     const char* csrcPathA = env->GetStringUTFChars(jsrcPathA, nullptr);
705*b7c941bbSAndroid Build Coastguard Worker     const char* csrcPathB = env->GetStringUTFChars(jsrcPathB, nullptr);
706*b7c941bbSAndroid Build Coastguard Worker     auto* mediaInfoA = new MuxerNativeTestHelper(csrcPathA);
707*b7c941bbSAndroid Build Coastguard Worker     auto* mediaInfoB = new MuxerNativeTestHelper(csrcPathB);
708*b7c941bbSAndroid Build Coastguard Worker     if (mediaInfoA->getTrackCount() == 1 && mediaInfoB->getTrackCount() == 1) {
709*b7c941bbSAndroid Build Coastguard Worker         const char* crefPath = env->GetStringUTFChars(jrefPath, nullptr);
710*b7c941bbSAndroid Build Coastguard Worker         // number of times to repeat {mSrcFileA, mSrcFileB} in Output
711*b7c941bbSAndroid Build Coastguard Worker         // values should be in sync with testMultiTrack
712*b7c941bbSAndroid Build Coastguard Worker         static const int numTracks[][2] = {{1, 1}, {2, 0}, {0, 2}, {1, 2}, {2, 1}, {2, 2}};
713*b7c941bbSAndroid Build Coastguard Worker         // prepare reference
714*b7c941bbSAndroid Build Coastguard Worker         FILE* rfp = fopen(crefPath, "wbe+");
715*b7c941bbSAndroid Build Coastguard Worker         if (rfp) {
716*b7c941bbSAndroid Build Coastguard Worker             AMediaMuxer* muxer = AMediaMuxer_new(fileno(rfp), (OutputFormat)jformat);
717*b7c941bbSAndroid Build Coastguard Worker             bool muxStatus = mediaInfoA->combineMedias(muxer, mediaInfoB, numTracks[0]);
718*b7c941bbSAndroid Build Coastguard Worker             AMediaMuxer_delete(muxer);
719*b7c941bbSAndroid Build Coastguard Worker             fclose(rfp);
720*b7c941bbSAndroid Build Coastguard Worker             if (muxStatus) {
721*b7c941bbSAndroid Build Coastguard Worker                 auto* refInfo = new MuxerNativeTestHelper(crefPath);
722*b7c941bbSAndroid Build Coastguard Worker                 if (!mediaInfoA->isSubsetOf(refInfo) || !mediaInfoB->isSubsetOf(refInfo)) {
723*b7c941bbSAndroid Build Coastguard Worker                     isPass = false;
724*b7c941bbSAndroid Build Coastguard Worker                     ALOGE("testMultiTrack: inputs: %s %s, fmt: %d, error ! muxing src A and src B "
725*b7c941bbSAndroid Build Coastguard Worker                           "failed", csrcPathA, csrcPathB, jformat);
726*b7c941bbSAndroid Build Coastguard Worker                 } else {
727*b7c941bbSAndroid Build Coastguard Worker                     const char* cdstPath = env->GetStringUTFChars(jdstPath, nullptr);
728*b7c941bbSAndroid Build Coastguard Worker                     for (int i = 1; i < sizeof(numTracks) / sizeof(numTracks[0]) && isPass; i++) {
729*b7c941bbSAndroid Build Coastguard Worker                         FILE* ofp = fopen(cdstPath, "wbe+");
730*b7c941bbSAndroid Build Coastguard Worker                         if (ofp) {
731*b7c941bbSAndroid Build Coastguard Worker                             muxer = AMediaMuxer_new(fileno(ofp), (OutputFormat)jformat);
732*b7c941bbSAndroid Build Coastguard Worker                             bool status =
733*b7c941bbSAndroid Build Coastguard Worker                                     mediaInfoA->combineMedias(muxer, mediaInfoB, numTracks[i]);
734*b7c941bbSAndroid Build Coastguard Worker                             AMediaMuxer_delete(muxer);
735*b7c941bbSAndroid Build Coastguard Worker                             fclose(ofp);
736*b7c941bbSAndroid Build Coastguard Worker                             if (status) {
737*b7c941bbSAndroid Build Coastguard Worker                                 auto* dstInfo = new MuxerNativeTestHelper(cdstPath);
738*b7c941bbSAndroid Build Coastguard Worker                                 if (!dstInfo->isSubsetOf(refInfo)) {
739*b7c941bbSAndroid Build Coastguard Worker                                     isPass = false;
740*b7c941bbSAndroid Build Coastguard Worker                                     ALOGE("testMultiTrack: inputs: %s %s, fmt: %d, error ! muxing "
741*b7c941bbSAndroid Build Coastguard Worker                                           "src A: %d, src B: %d failed", csrcPathA, csrcPathB,
742*b7c941bbSAndroid Build Coastguard Worker                                           jformat, numTracks[i][0], numTracks[i][1]);
743*b7c941bbSAndroid Build Coastguard Worker                                 }
744*b7c941bbSAndroid Build Coastguard Worker                                 delete dstInfo;
745*b7c941bbSAndroid Build Coastguard Worker                             } else {
746*b7c941bbSAndroid Build Coastguard Worker                                 if ((OutputFormat)jformat != AMEDIAMUXER_OUTPUT_FORMAT_MPEG_4) {
747*b7c941bbSAndroid Build Coastguard Worker                                     isPass = false;
748*b7c941bbSAndroid Build Coastguard Worker                                     ALOGE("testMultiTrack: inputs: %s %s, fmt: %d, error ! muxing "
749*b7c941bbSAndroid Build Coastguard Worker                                           "src A: %d, src B: %d failed", csrcPathA, csrcPathB,
750*b7c941bbSAndroid Build Coastguard Worker                                           jformat, numTracks[i][0], numTracks[i][1]);
751*b7c941bbSAndroid Build Coastguard Worker                                 }
752*b7c941bbSAndroid Build Coastguard Worker                             }
753*b7c941bbSAndroid Build Coastguard Worker                         } else {
754*b7c941bbSAndroid Build Coastguard Worker                             isPass = false;
755*b7c941bbSAndroid Build Coastguard Worker                             ALOGE("failed to open output file %s", cdstPath);
756*b7c941bbSAndroid Build Coastguard Worker                         }
757*b7c941bbSAndroid Build Coastguard Worker                     }
758*b7c941bbSAndroid Build Coastguard Worker                     env->ReleaseStringUTFChars(jdstPath, cdstPath);
759*b7c941bbSAndroid Build Coastguard Worker                 }
760*b7c941bbSAndroid Build Coastguard Worker                 delete refInfo;
761*b7c941bbSAndroid Build Coastguard Worker             } else {
762*b7c941bbSAndroid Build Coastguard Worker                 if ((OutputFormat)jformat != AMEDIAMUXER_OUTPUT_FORMAT_OGG) {
763*b7c941bbSAndroid Build Coastguard Worker                     isPass = false;
764*b7c941bbSAndroid Build Coastguard Worker                     ALOGE("testMultiTrack: inputs: %s %s, fmt: %d, error ! muxing src A and src B "
765*b7c941bbSAndroid Build Coastguard Worker                           "failed", csrcPathA, csrcPathB, jformat);
766*b7c941bbSAndroid Build Coastguard Worker                 }
767*b7c941bbSAndroid Build Coastguard Worker             }
768*b7c941bbSAndroid Build Coastguard Worker         } else {
769*b7c941bbSAndroid Build Coastguard Worker             isPass = false;
770*b7c941bbSAndroid Build Coastguard Worker             ALOGE("failed to open reference output file %s", crefPath);
771*b7c941bbSAndroid Build Coastguard Worker         }
772*b7c941bbSAndroid Build Coastguard Worker         env->ReleaseStringUTFChars(jrefPath, crefPath);
773*b7c941bbSAndroid Build Coastguard Worker     } else {
774*b7c941bbSAndroid Build Coastguard Worker         isPass = false;
775*b7c941bbSAndroid Build Coastguard Worker         if (mediaInfoA->getTrackCount() != 1) {
776*b7c941bbSAndroid Build Coastguard Worker             ALOGE("error: file %s, track count exp/rec - %d/%d", csrcPathA, 1,
777*b7c941bbSAndroid Build Coastguard Worker                   mediaInfoA->getTrackCount());
778*b7c941bbSAndroid Build Coastguard Worker         }
779*b7c941bbSAndroid Build Coastguard Worker         if (mediaInfoB->getTrackCount() != 1) {
780*b7c941bbSAndroid Build Coastguard Worker             ALOGE("error: file %s, track count exp/rec - %d/%d", csrcPathB, 1,
781*b7c941bbSAndroid Build Coastguard Worker                   mediaInfoB->getTrackCount());
782*b7c941bbSAndroid Build Coastguard Worker         }
783*b7c941bbSAndroid Build Coastguard Worker     }
784*b7c941bbSAndroid Build Coastguard Worker     env->ReleaseStringUTFChars(jsrcPathA, csrcPathA);
785*b7c941bbSAndroid Build Coastguard Worker     env->ReleaseStringUTFChars(jsrcPathB, csrcPathB);
786*b7c941bbSAndroid Build Coastguard Worker     delete mediaInfoA;
787*b7c941bbSAndroid Build Coastguard Worker     delete mediaInfoB;
788*b7c941bbSAndroid Build Coastguard Worker     return static_cast<jboolean>(isPass);
789*b7c941bbSAndroid Build Coastguard Worker }
790*b7c941bbSAndroid Build Coastguard Worker 
nativeTestOffsetPts(JNIEnv * env,jobject,jint format,jstring jsrcPath,jstring jdstPath,jintArray joffsetIndices)791*b7c941bbSAndroid Build Coastguard Worker static jboolean nativeTestOffsetPts(JNIEnv* env, jobject, jint format, jstring jsrcPath,
792*b7c941bbSAndroid Build Coastguard Worker                                     jstring jdstPath, jintArray joffsetIndices) {
793*b7c941bbSAndroid Build Coastguard Worker     bool isPass = true;
794*b7c941bbSAndroid Build Coastguard Worker     // values should be in sync with testOffsetPresentationTime
795*b7c941bbSAndroid Build Coastguard Worker     static const int64_t OFFSET_TS_AUDIO_US[4] = {-23220LL, 0LL, 200000LL, 400000LL};
796*b7c941bbSAndroid Build Coastguard Worker     static const int64_t OFFSET_TS_VIDEO_US[3] = {0LL, 200000LL, 400000LL};
797*b7c941bbSAndroid Build Coastguard Worker     jsize len = env->GetArrayLength(joffsetIndices);
798*b7c941bbSAndroid Build Coastguard Worker     jint* coffsetIndices = env->GetIntArrayElements(joffsetIndices, nullptr);
799*b7c941bbSAndroid Build Coastguard Worker     const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
800*b7c941bbSAndroid Build Coastguard Worker     const char* cdstPath = env->GetStringUTFChars(jdstPath, nullptr);
801*b7c941bbSAndroid Build Coastguard Worker     auto* mediaInfo = new MuxerNativeTestHelper(csrcPath);
802*b7c941bbSAndroid Build Coastguard Worker     if (mediaInfo->getTrackCount() != 0) {
803*b7c941bbSAndroid Build Coastguard Worker         for (int64_t audioOffsetUs : OFFSET_TS_AUDIO_US) {
804*b7c941bbSAndroid Build Coastguard Worker             for (int64_t videoOffsetUs : OFFSET_TS_VIDEO_US) {
805*b7c941bbSAndroid Build Coastguard Worker                 for (int i = 0; i < len; i++) {
806*b7c941bbSAndroid Build Coastguard Worker                     mediaInfo->offsetTimeStamp(audioOffsetUs, videoOffsetUs, coffsetIndices[i]);
807*b7c941bbSAndroid Build Coastguard Worker                 }
808*b7c941bbSAndroid Build Coastguard Worker                 FILE* ofp = fopen(cdstPath, "wbe+");
809*b7c941bbSAndroid Build Coastguard Worker                 if (ofp) {
810*b7c941bbSAndroid Build Coastguard Worker                     AMediaMuxer* muxer = AMediaMuxer_new(fileno(ofp), (OutputFormat)format);
811*b7c941bbSAndroid Build Coastguard Worker                     mediaInfo->muxMedia(muxer);
812*b7c941bbSAndroid Build Coastguard Worker                     AMediaMuxer_delete(muxer);
813*b7c941bbSAndroid Build Coastguard Worker                     fclose(ofp);
814*b7c941bbSAndroid Build Coastguard Worker                     auto* outInfo = new MuxerNativeTestHelper(cdstPath);
815*b7c941bbSAndroid Build Coastguard Worker                     isPass = mediaInfo->isSubsetOf(outInfo);
816*b7c941bbSAndroid Build Coastguard Worker                     if (!isPass) {
817*b7c941bbSAndroid Build Coastguard Worker                         ALOGE("Validation failed after adding timestamp offsets audio: %lld,"
818*b7c941bbSAndroid Build Coastguard Worker                               " video: %lld", (long long) audioOffsetUs, (long long) videoOffsetUs);
819*b7c941bbSAndroid Build Coastguard Worker                     }
820*b7c941bbSAndroid Build Coastguard Worker                     delete outInfo;
821*b7c941bbSAndroid Build Coastguard Worker                 } else {
822*b7c941bbSAndroid Build Coastguard Worker                     isPass = false;
823*b7c941bbSAndroid Build Coastguard Worker                     ALOGE("failed to open output file %s", cdstPath);
824*b7c941bbSAndroid Build Coastguard Worker                 }
825*b7c941bbSAndroid Build Coastguard Worker                 for (int i = len - 1; i >= 0; i--) {
826*b7c941bbSAndroid Build Coastguard Worker                     mediaInfo->offsetTimeStamp(-audioOffsetUs, -videoOffsetUs, coffsetIndices[i]);
827*b7c941bbSAndroid Build Coastguard Worker                 }
828*b7c941bbSAndroid Build Coastguard Worker             }
829*b7c941bbSAndroid Build Coastguard Worker         }
830*b7c941bbSAndroid Build Coastguard Worker     } else {
831*b7c941bbSAndroid Build Coastguard Worker         isPass = false;
832*b7c941bbSAndroid Build Coastguard Worker         ALOGE("no valid track found in input file %s", csrcPath);
833*b7c941bbSAndroid Build Coastguard Worker     }
834*b7c941bbSAndroid Build Coastguard Worker     env->ReleaseStringUTFChars(jdstPath, cdstPath);
835*b7c941bbSAndroid Build Coastguard Worker     env->ReleaseStringUTFChars(jsrcPath, csrcPath);
836*b7c941bbSAndroid Build Coastguard Worker     env->ReleaseIntArrayElements(joffsetIndices, coffsetIndices, 0);
837*b7c941bbSAndroid Build Coastguard Worker     delete mediaInfo;
838*b7c941bbSAndroid Build Coastguard Worker     return static_cast<jboolean>(isPass);
839*b7c941bbSAndroid Build Coastguard Worker }
840*b7c941bbSAndroid Build Coastguard Worker 
841*b7c941bbSAndroid Build Coastguard Worker // simple muxer tests, including varying the output container format.
842*b7c941bbSAndroid Build Coastguard Worker //
843*b7c941bbSAndroid Build Coastguard Worker // @ApiTest = AMEDIAMUXER_OUTPUT_FORMAT_HEIF
844*b7c941bbSAndroid Build Coastguard Worker // @ApiTest = AMEDIAMUXER_OUTPUT_FORMAT_MPEG_4
845*b7c941bbSAndroid Build Coastguard Worker // @ApiTest = AMEDIAMUXER_OUTPUT_FORMAT_OGG
846*b7c941bbSAndroid Build Coastguard Worker // @ApiTest = AMEDIAMUXER_OUTPUT_FORMAT_THREE_GPP
847*b7c941bbSAndroid Build Coastguard Worker // @ApiTest = AMEDIAMUXER_OUTPUT_FORMAT_WEBM
848*b7c941bbSAndroid Build Coastguard Worker //
nativeTestSimpleMux(JNIEnv * env,jobject,jstring jsrcPath,jstring jdstPath,jstring jMediaType,jstring jselector)849*b7c941bbSAndroid Build Coastguard Worker static jboolean nativeTestSimpleMux(JNIEnv* env, jobject, jstring jsrcPath, jstring jdstPath,
850*b7c941bbSAndroid Build Coastguard Worker                                     jstring jMediaType, jstring jselector) {
851*b7c941bbSAndroid Build Coastguard Worker     bool isPass = true;
852*b7c941bbSAndroid Build Coastguard Worker     const char* cMediaType = env->GetStringUTFChars(jMediaType, nullptr);
853*b7c941bbSAndroid Build Coastguard Worker     const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
854*b7c941bbSAndroid Build Coastguard Worker     const char* cselector = env->GetStringUTFChars(jselector, nullptr);
855*b7c941bbSAndroid Build Coastguard Worker     auto* mediaInfo = new MuxerNativeTestHelper(csrcPath, cMediaType);
856*b7c941bbSAndroid Build Coastguard Worker     static const std::map<OutputFormat, const char*> formatStringPair = {
857*b7c941bbSAndroid Build Coastguard Worker             {AMEDIAMUXER_OUTPUT_FORMAT_MPEG_4, "mp4"},
858*b7c941bbSAndroid Build Coastguard Worker             {AMEDIAMUXER_OUTPUT_FORMAT_WEBM, "webm"},
859*b7c941bbSAndroid Build Coastguard Worker             {AMEDIAMUXER_OUTPUT_FORMAT_THREE_GPP, "3gp"},
860*b7c941bbSAndroid Build Coastguard Worker             {AMEDIAMUXER_OUTPUT_FORMAT_HEIF, "heif"},
861*b7c941bbSAndroid Build Coastguard Worker             {AMEDIAMUXER_OUTPUT_FORMAT_OGG, "ogg"}};
862*b7c941bbSAndroid Build Coastguard Worker     if (mediaInfo->getTrackCount() == 1) {
863*b7c941bbSAndroid Build Coastguard Worker         const char* cdstPath = env->GetStringUTFChars(jdstPath, nullptr);
864*b7c941bbSAndroid Build Coastguard Worker         for (int fmt = LOCAL_AMEDIAMUXER_OUTPUT_FORMAT_FIRST;
865*b7c941bbSAndroid Build Coastguard Worker              fmt <= LOCAL_AMEDIAMUXER_OUTPUT_FORMAT_LAST && isPass; fmt++) {
866*b7c941bbSAndroid Build Coastguard Worker             auto it = formatStringPair.find((OutputFormat)fmt);
867*b7c941bbSAndroid Build Coastguard Worker             if (it == formatStringPair.end() || strstr(cselector, it->second) == nullptr) {
868*b7c941bbSAndroid Build Coastguard Worker                 continue;
869*b7c941bbSAndroid Build Coastguard Worker             }
870*b7c941bbSAndroid Build Coastguard Worker             if (fmt == AMEDIAMUXER_OUTPUT_FORMAT_WEBM) continue;  // TODO(b/146923551)
871*b7c941bbSAndroid Build Coastguard Worker             FILE* ofp = fopen(cdstPath, "wbe+");
872*b7c941bbSAndroid Build Coastguard Worker             if (ofp) {
873*b7c941bbSAndroid Build Coastguard Worker                 AMediaMuxer* muxer = AMediaMuxer_new(fileno(ofp), (OutputFormat)fmt);
874*b7c941bbSAndroid Build Coastguard Worker                 bool muxStatus = mediaInfo->muxMedia(muxer);
875*b7c941bbSAndroid Build Coastguard Worker                 bool result = true;
876*b7c941bbSAndroid Build Coastguard Worker                 AMediaMuxer_delete(muxer);
877*b7c941bbSAndroid Build Coastguard Worker                 fclose(ofp);
878*b7c941bbSAndroid Build Coastguard Worker                 if (muxStatus) {
879*b7c941bbSAndroid Build Coastguard Worker                     auto* outInfo = new MuxerNativeTestHelper(cdstPath, cMediaType);
880*b7c941bbSAndroid Build Coastguard Worker                     result = mediaInfo->isSubsetOf(outInfo);
881*b7c941bbSAndroid Build Coastguard Worker                     delete outInfo;
882*b7c941bbSAndroid Build Coastguard Worker                 }
883*b7c941bbSAndroid Build Coastguard Worker                 if ((muxStatus && !result) ||
884*b7c941bbSAndroid Build Coastguard Worker                     (!muxStatus && isCodecContainerPairValid((OutputFormat)fmt, cMediaType))) {
885*b7c941bbSAndroid Build Coastguard Worker                     isPass = false;
886*b7c941bbSAndroid Build Coastguard Worker                     ALOGE("error: file %s, mediaType %s, output != clone(input) for format %d",
887*b7c941bbSAndroid Build Coastguard Worker                           csrcPath, cMediaType, fmt);
888*b7c941bbSAndroid Build Coastguard Worker                 }
889*b7c941bbSAndroid Build Coastguard Worker             } else {
890*b7c941bbSAndroid Build Coastguard Worker                 isPass = false;
891*b7c941bbSAndroid Build Coastguard Worker                 ALOGE("error: file %s, mediaType %s, failed to open output file %s", csrcPath,
892*b7c941bbSAndroid Build Coastguard Worker                       cMediaType, cdstPath);
893*b7c941bbSAndroid Build Coastguard Worker             }
894*b7c941bbSAndroid Build Coastguard Worker         }
895*b7c941bbSAndroid Build Coastguard Worker         env->ReleaseStringUTFChars(jdstPath, cdstPath);
896*b7c941bbSAndroid Build Coastguard Worker     } else {
897*b7c941bbSAndroid Build Coastguard Worker         isPass = false;
898*b7c941bbSAndroid Build Coastguard Worker         ALOGE("error: file %s, mediaType %s, track count exp/rec - %d/%d", csrcPath, cMediaType, 1,
899*b7c941bbSAndroid Build Coastguard Worker               mediaInfo->getTrackCount());
900*b7c941bbSAndroid Build Coastguard Worker     }
901*b7c941bbSAndroid Build Coastguard Worker     env->ReleaseStringUTFChars(jselector, cselector);
902*b7c941bbSAndroid Build Coastguard Worker     env->ReleaseStringUTFChars(jsrcPath, csrcPath);
903*b7c941bbSAndroid Build Coastguard Worker     env->ReleaseStringUTFChars(jMediaType, cMediaType);
904*b7c941bbSAndroid Build Coastguard Worker     delete mediaInfo;
905*b7c941bbSAndroid Build Coastguard Worker     return static_cast<jboolean>(isPass);
906*b7c941bbSAndroid Build Coastguard Worker }
907*b7c941bbSAndroid Build Coastguard Worker 
908*b7c941bbSAndroid Build Coastguard Worker /* Check whether AMediaMuxer_getTrackCount works as expected.
909*b7c941bbSAndroid Build Coastguard Worker  */
nativeTestGetTrackCount(JNIEnv * env,jobject,jstring jsrcPath,jstring jdstPath,jint jformat,jint jtrackCount)910*b7c941bbSAndroid Build Coastguard Worker static jboolean nativeTestGetTrackCount(JNIEnv* env, jobject, jstring jsrcPath, jstring jdstPath,
911*b7c941bbSAndroid Build Coastguard Worker                                             jint jformat, jint jtrackCount) {
912*b7c941bbSAndroid Build Coastguard Worker     bool isPass = true;
913*b7c941bbSAndroid Build Coastguard Worker     if (__builtin_available(android __TRANSCODING_MIN_API__, *)) {
914*b7c941bbSAndroid Build Coastguard Worker         const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
915*b7c941bbSAndroid Build Coastguard Worker         const char* cdstPath = env->GetStringUTFChars(jdstPath, nullptr);
916*b7c941bbSAndroid Build Coastguard Worker         FILE* ofp = fopen(cdstPath, "w+");
917*b7c941bbSAndroid Build Coastguard Worker         if (ofp) {
918*b7c941bbSAndroid Build Coastguard Worker             AMediaMuxer *muxer = AMediaMuxer_new(fileno(ofp), (OutputFormat)jformat);
919*b7c941bbSAndroid Build Coastguard Worker             if (muxer) {
920*b7c941bbSAndroid Build Coastguard Worker                 auto* mediaInfo = new MuxerNativeTestHelper(csrcPath);
921*b7c941bbSAndroid Build Coastguard Worker                 if (!mediaInfo->registerTrack(muxer)) {
922*b7c941bbSAndroid Build Coastguard Worker                     isPass = false;
923*b7c941bbSAndroid Build Coastguard Worker                     ALOGE("register track failed");
924*b7c941bbSAndroid Build Coastguard Worker                 }
925*b7c941bbSAndroid Build Coastguard Worker                 if (AMediaMuxer_getTrackCount(muxer) != jtrackCount) {
926*b7c941bbSAndroid Build Coastguard Worker                     isPass = false;
927*b7c941bbSAndroid Build Coastguard Worker                     ALOGE("track counts are not equal");
928*b7c941bbSAndroid Build Coastguard Worker                 }
929*b7c941bbSAndroid Build Coastguard Worker                 delete mediaInfo;
930*b7c941bbSAndroid Build Coastguard Worker                 AMediaMuxer_delete(muxer);
931*b7c941bbSAndroid Build Coastguard Worker             } else {
932*b7c941bbSAndroid Build Coastguard Worker                 isPass = false;
933*b7c941bbSAndroid Build Coastguard Worker                 ALOGE("Failed to create muxer");
934*b7c941bbSAndroid Build Coastguard Worker             }
935*b7c941bbSAndroid Build Coastguard Worker             fclose(ofp);
936*b7c941bbSAndroid Build Coastguard Worker         } else {
937*b7c941bbSAndroid Build Coastguard Worker             isPass = false;
938*b7c941bbSAndroid Build Coastguard Worker             ALOGE("file open error: file  %s", csrcPath);
939*b7c941bbSAndroid Build Coastguard Worker         }
940*b7c941bbSAndroid Build Coastguard Worker         env->ReleaseStringUTFChars(jsrcPath, csrcPath);
941*b7c941bbSAndroid Build Coastguard Worker         env->ReleaseStringUTFChars(jdstPath, cdstPath);
942*b7c941bbSAndroid Build Coastguard Worker     } else {
943*b7c941bbSAndroid Build Coastguard Worker         isPass = false;
944*b7c941bbSAndroid Build Coastguard Worker     }
945*b7c941bbSAndroid Build Coastguard Worker     return static_cast<jboolean>(isPass);
946*b7c941bbSAndroid Build Coastguard Worker }
947*b7c941bbSAndroid Build Coastguard Worker 
948*b7c941bbSAndroid Build Coastguard Worker /* Check whether AMediaMuxer_getTrackCount works as expected when the file is opened in
949*b7c941bbSAndroid Build Coastguard Worker  * append mode.
950*b7c941bbSAndroid Build Coastguard Worker  */
nativeTestAppendGetTrackCount(JNIEnv * env,jobject,jstring jsrcPath,jint jtrackCount)951*b7c941bbSAndroid Build Coastguard Worker static jboolean nativeTestAppendGetTrackCount(JNIEnv* env, jobject, jstring jsrcPath,
952*b7c941bbSAndroid Build Coastguard Worker                                                         jint jtrackCount) {
953*b7c941bbSAndroid Build Coastguard Worker     bool isPass = true;
954*b7c941bbSAndroid Build Coastguard Worker     if (__builtin_available(android __TRANSCODING_MIN_API__, *)) {
955*b7c941bbSAndroid Build Coastguard Worker         const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
956*b7c941bbSAndroid Build Coastguard Worker         for (unsigned int mode = AMEDIAMUXER_APPEND_IGNORE_LAST_VIDEO_GOP;
957*b7c941bbSAndroid Build Coastguard Worker                     mode <= AMEDIAMUXER_APPEND_TO_EXISTING_DATA; ++mode) {
958*b7c941bbSAndroid Build Coastguard Worker             ALOGV("mode:%u", mode);
959*b7c941bbSAndroid Build Coastguard Worker             FILE* ofp = fopen(csrcPath, "r");
960*b7c941bbSAndroid Build Coastguard Worker             if (ofp) {
961*b7c941bbSAndroid Build Coastguard Worker                 AMediaMuxer *muxer = AMediaMuxer_append(fileno(ofp), (AppendMode)mode);
962*b7c941bbSAndroid Build Coastguard Worker                 if (muxer) {
963*b7c941bbSAndroid Build Coastguard Worker                     ssize_t trackCount = AMediaMuxer_getTrackCount(muxer);
964*b7c941bbSAndroid Build Coastguard Worker                     if ( trackCount != jtrackCount) {
965*b7c941bbSAndroid Build Coastguard Worker                         isPass = false;
966*b7c941bbSAndroid Build Coastguard Worker                         ALOGE("trackcounts are not equal, trackCount:%ld vs jtrackCount:%d",
967*b7c941bbSAndroid Build Coastguard Worker                                     (long)trackCount, jtrackCount);
968*b7c941bbSAndroid Build Coastguard Worker                     }
969*b7c941bbSAndroid Build Coastguard Worker                     AMediaMuxer_delete(muxer);
970*b7c941bbSAndroid Build Coastguard Worker                 } else {
971*b7c941bbSAndroid Build Coastguard Worker                     isPass = false;
972*b7c941bbSAndroid Build Coastguard Worker                     ALOGE("Failed to create muxer");
973*b7c941bbSAndroid Build Coastguard Worker                 }
974*b7c941bbSAndroid Build Coastguard Worker                 fclose(ofp);
975*b7c941bbSAndroid Build Coastguard Worker                 ofp = nullptr;
976*b7c941bbSAndroid Build Coastguard Worker             } else {
977*b7c941bbSAndroid Build Coastguard Worker                 isPass = false;
978*b7c941bbSAndroid Build Coastguard Worker                 ALOGE("file open error: file  %s", csrcPath);
979*b7c941bbSAndroid Build Coastguard Worker             }
980*b7c941bbSAndroid Build Coastguard Worker         }
981*b7c941bbSAndroid Build Coastguard Worker         env->ReleaseStringUTFChars(jsrcPath, csrcPath);
982*b7c941bbSAndroid Build Coastguard Worker     } else {
983*b7c941bbSAndroid Build Coastguard Worker         isPass = false;
984*b7c941bbSAndroid Build Coastguard Worker     }
985*b7c941bbSAndroid Build Coastguard Worker     return static_cast<jboolean>(isPass);
986*b7c941bbSAndroid Build Coastguard Worker }
987*b7c941bbSAndroid Build Coastguard Worker 
988*b7c941bbSAndroid Build Coastguard Worker /* Checks whether AMediaMuxer_getTrackFormat works as expected in muxer mode.
989*b7c941bbSAndroid Build Coastguard Worker  */
nativeTestGetTrackFormat(JNIEnv * env,jobject,jstring jsrcPath,jstring jdstPath,jint joutFormat)990*b7c941bbSAndroid Build Coastguard Worker static jboolean nativeTestGetTrackFormat(JNIEnv* env, jobject, jstring jsrcPath, jstring jdstPath,
991*b7c941bbSAndroid Build Coastguard Worker                                                     jint joutFormat) {
992*b7c941bbSAndroid Build Coastguard Worker     bool isPass = true;
993*b7c941bbSAndroid Build Coastguard Worker     if (__builtin_available(android __TRANSCODING_MIN_API__, *)) {
994*b7c941bbSAndroid Build Coastguard Worker         const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
995*b7c941bbSAndroid Build Coastguard Worker         const char* cdstPath = env->GetStringUTFChars(jdstPath, nullptr);
996*b7c941bbSAndroid Build Coastguard Worker         FILE* ofp = fopen(cdstPath, "w+");
997*b7c941bbSAndroid Build Coastguard Worker         if (ofp) {
998*b7c941bbSAndroid Build Coastguard Worker             AMediaMuxer *muxer = AMediaMuxer_new(fileno(ofp), (OutputFormat)joutFormat);
999*b7c941bbSAndroid Build Coastguard Worker             if (muxer) {
1000*b7c941bbSAndroid Build Coastguard Worker                 auto* mediaInfo = new MuxerNativeTestHelper(csrcPath);
1001*b7c941bbSAndroid Build Coastguard Worker                 if (!mediaInfo->registerTrack(muxer)) {
1002*b7c941bbSAndroid Build Coastguard Worker                     isPass = false;
1003*b7c941bbSAndroid Build Coastguard Worker                     ALOGE("register track failed");
1004*b7c941bbSAndroid Build Coastguard Worker                 }
1005*b7c941bbSAndroid Build Coastguard Worker                 for(int i = 0 ; i < mediaInfo->getTrackCount(); ++i ) {
1006*b7c941bbSAndroid Build Coastguard Worker                     if (!isFormatSimilar(mediaInfo->getTrackFormat(i),
1007*b7c941bbSAndroid Build Coastguard Worker                             AMediaMuxer_getTrackFormat(muxer, i))) {
1008*b7c941bbSAndroid Build Coastguard Worker                         isPass = false;
1009*b7c941bbSAndroid Build Coastguard Worker                         ALOGE("track formats are not similar");
1010*b7c941bbSAndroid Build Coastguard Worker                     }
1011*b7c941bbSAndroid Build Coastguard Worker                 }
1012*b7c941bbSAndroid Build Coastguard Worker                 delete mediaInfo;
1013*b7c941bbSAndroid Build Coastguard Worker                 AMediaMuxer_delete(muxer);
1014*b7c941bbSAndroid Build Coastguard Worker             } else {
1015*b7c941bbSAndroid Build Coastguard Worker                 isPass = false;
1016*b7c941bbSAndroid Build Coastguard Worker                 ALOGE("Failed to create muxer");
1017*b7c941bbSAndroid Build Coastguard Worker             }
1018*b7c941bbSAndroid Build Coastguard Worker             fclose(ofp);
1019*b7c941bbSAndroid Build Coastguard Worker         } else {
1020*b7c941bbSAndroid Build Coastguard Worker             isPass = false;
1021*b7c941bbSAndroid Build Coastguard Worker             ALOGE("file open error: file  %s", csrcPath);
1022*b7c941bbSAndroid Build Coastguard Worker         }
1023*b7c941bbSAndroid Build Coastguard Worker         env->ReleaseStringUTFChars(jsrcPath, csrcPath);
1024*b7c941bbSAndroid Build Coastguard Worker         env->ReleaseStringUTFChars(jdstPath, cdstPath);
1025*b7c941bbSAndroid Build Coastguard Worker     } else {
1026*b7c941bbSAndroid Build Coastguard Worker         isPass = false;
1027*b7c941bbSAndroid Build Coastguard Worker     }
1028*b7c941bbSAndroid Build Coastguard Worker     return static_cast<jboolean>(isPass);
1029*b7c941bbSAndroid Build Coastguard Worker }
1030*b7c941bbSAndroid Build Coastguard Worker 
1031*b7c941bbSAndroid Build Coastguard Worker /* Checks whether AMediaMuxer_getTrackFormat works as expected when the file is opened in
1032*b7c941bbSAndroid Build Coastguard Worker  * append mode.
1033*b7c941bbSAndroid Build Coastguard Worker  */
nativeTestAppendGetTrackFormat(JNIEnv * env,jobject,jstring jsrcPath)1034*b7c941bbSAndroid Build Coastguard Worker static jboolean nativeTestAppendGetTrackFormat(JNIEnv* env, jobject, jstring jsrcPath) {
1035*b7c941bbSAndroid Build Coastguard Worker     bool isPass = true;
1036*b7c941bbSAndroid Build Coastguard Worker     if (__builtin_available(android __TRANSCODING_MIN_API__, *)) {
1037*b7c941bbSAndroid Build Coastguard Worker         const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
1038*b7c941bbSAndroid Build Coastguard Worker         for (unsigned int mode = AMEDIAMUXER_APPEND_IGNORE_LAST_VIDEO_GOP;
1039*b7c941bbSAndroid Build Coastguard Worker                     mode <= AMEDIAMUXER_APPEND_TO_EXISTING_DATA; ++mode) {
1040*b7c941bbSAndroid Build Coastguard Worker             ALOGV("mode:%u", mode);
1041*b7c941bbSAndroid Build Coastguard Worker             FILE* ofp = fopen(csrcPath, "r");
1042*b7c941bbSAndroid Build Coastguard Worker             if (ofp) {
1043*b7c941bbSAndroid Build Coastguard Worker                 AMediaMuxer *muxer = AMediaMuxer_append(fileno(ofp), (AppendMode)mode);
1044*b7c941bbSAndroid Build Coastguard Worker                 if (muxer) {
1045*b7c941bbSAndroid Build Coastguard Worker                     auto* mediaInfo = new MuxerNativeTestHelper(csrcPath);
1046*b7c941bbSAndroid Build Coastguard Worker                     for(int i = 0 ; i < mediaInfo->getTrackCount(); ++i ) {
1047*b7c941bbSAndroid Build Coastguard Worker                         if (!isFormatSimilar(mediaInfo->getTrackFormat(i),
1048*b7c941bbSAndroid Build Coastguard Worker                                 AMediaMuxer_getTrackFormat(muxer, i))) {
1049*b7c941bbSAndroid Build Coastguard Worker                             isPass = false;
1050*b7c941bbSAndroid Build Coastguard Worker                             ALOGE("track formats are not similar");
1051*b7c941bbSAndroid Build Coastguard Worker                         }
1052*b7c941bbSAndroid Build Coastguard Worker                     }
1053*b7c941bbSAndroid Build Coastguard Worker                     delete mediaInfo;
1054*b7c941bbSAndroid Build Coastguard Worker                     AMediaMuxer_delete(muxer);
1055*b7c941bbSAndroid Build Coastguard Worker                 } else {
1056*b7c941bbSAndroid Build Coastguard Worker                     isPass = false;
1057*b7c941bbSAndroid Build Coastguard Worker                     ALOGE("Failed to create muxer");
1058*b7c941bbSAndroid Build Coastguard Worker                 }
1059*b7c941bbSAndroid Build Coastguard Worker                 fclose(ofp);
1060*b7c941bbSAndroid Build Coastguard Worker             } else {
1061*b7c941bbSAndroid Build Coastguard Worker                 isPass = false;
1062*b7c941bbSAndroid Build Coastguard Worker                 ALOGE("file open error: file  %s", csrcPath);
1063*b7c941bbSAndroid Build Coastguard Worker             }
1064*b7c941bbSAndroid Build Coastguard Worker         }
1065*b7c941bbSAndroid Build Coastguard Worker         env->ReleaseStringUTFChars(jsrcPath, csrcPath);
1066*b7c941bbSAndroid Build Coastguard Worker     }
1067*b7c941bbSAndroid Build Coastguard Worker     else {
1068*b7c941bbSAndroid Build Coastguard Worker         isPass = false;
1069*b7c941bbSAndroid Build Coastguard Worker     }
1070*b7c941bbSAndroid Build Coastguard Worker     return static_cast<jboolean>(isPass);
1071*b7c941bbSAndroid Build Coastguard Worker }
1072*b7c941bbSAndroid Build Coastguard Worker 
1073*b7c941bbSAndroid Build Coastguard Worker /*
1074*b7c941bbSAndroid Build Coastguard Worker  * Checks if appending media data to the end of existing media data in a file works good.
1075*b7c941bbSAndroid Build Coastguard Worker  * Mode : AMEDIAMUXER_APPEND_TO_EXISTING_DATA.  Splits the contents of source file equally
1076*b7c941bbSAndroid Build Coastguard Worker  * starting from one and increasing the number of splits by one for every iteration.  Starts
1077*b7c941bbSAndroid Build Coastguard Worker  * with writing first split into a new file and appends the rest of the contents split by split.
1078*b7c941bbSAndroid Build Coastguard Worker  */
nativeTestSimpleAppend(JNIEnv * env,jobject,jint joutFormat,jstring jsrcPath,jstring jdstPath)1079*b7c941bbSAndroid Build Coastguard Worker static jboolean nativeTestSimpleAppend(JNIEnv* env, jobject, jint joutFormat, jstring jsrcPath,
1080*b7c941bbSAndroid Build Coastguard Worker                         jstring jdstPath) {
1081*b7c941bbSAndroid Build Coastguard Worker     bool isPass = true;
1082*b7c941bbSAndroid Build Coastguard Worker     if (__builtin_available(android __TRANSCODING_MIN_API__, *)) {
1083*b7c941bbSAndroid Build Coastguard Worker         const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
1084*b7c941bbSAndroid Build Coastguard Worker         const char* cdstPath = env->GetStringUTFChars(jdstPath, nullptr);
1085*b7c941bbSAndroid Build Coastguard Worker         ALOGV("csrcPath:%s", csrcPath);
1086*b7c941bbSAndroid Build Coastguard Worker         ALOGV("cdstPath:%s", cdstPath);
1087*b7c941bbSAndroid Build Coastguard Worker         auto* mediaInfo = new MuxerNativeTestHelper(csrcPath);
1088*b7c941bbSAndroid Build Coastguard Worker         for (int numSplits = 1; numSplits <= 5; ++numSplits) {
1089*b7c941bbSAndroid Build Coastguard Worker             ALOGV("numSplits:%d", numSplits);
1090*b7c941bbSAndroid Build Coastguard Worker             size_t totalSampleCount = 0;
1091*b7c941bbSAndroid Build Coastguard Worker             AMediaMuxer *muxer = nullptr;
1092*b7c941bbSAndroid Build Coastguard Worker             // Start by writing first split into a new file.
1093*b7c941bbSAndroid Build Coastguard Worker             FILE* ofp = fopen(cdstPath, "w+");
1094*b7c941bbSAndroid Build Coastguard Worker             if (ofp) {
1095*b7c941bbSAndroid Build Coastguard Worker                 muxer = AMediaMuxer_new(fileno(ofp), (OutputFormat)joutFormat);
1096*b7c941bbSAndroid Build Coastguard Worker                 if (muxer) {
1097*b7c941bbSAndroid Build Coastguard Worker                     for(int i = 0 ; i < mediaInfo->getTrackCount(); ++i ) {
1098*b7c941bbSAndroid Build Coastguard Worker                         ALOGV("getSampleCount:%d:%zu", i, mediaInfo->getSampleCount(i));
1099*b7c941bbSAndroid Build Coastguard Worker                         totalSampleCount += mediaInfo->getSampleCount(i);
1100*b7c941bbSAndroid Build Coastguard Worker                     }
1101*b7c941bbSAndroid Build Coastguard Worker                     mediaInfo->appendMedia(muxer, 0, (totalSampleCount/numSplits)-1);
1102*b7c941bbSAndroid Build Coastguard Worker                     AMediaMuxer_delete(muxer);
1103*b7c941bbSAndroid Build Coastguard Worker                 } else {
1104*b7c941bbSAndroid Build Coastguard Worker                     isPass = false;
1105*b7c941bbSAndroid Build Coastguard Worker                     ALOGE("Failed to create muxer");
1106*b7c941bbSAndroid Build Coastguard Worker                 }
1107*b7c941bbSAndroid Build Coastguard Worker                 fclose(ofp);
1108*b7c941bbSAndroid Build Coastguard Worker                 ofp = nullptr;
1109*b7c941bbSAndroid Build Coastguard Worker                 // Check if the contents in the new file is as same as in the source file.
1110*b7c941bbSAndroid Build Coastguard Worker                 if (isPass) {
1111*b7c941bbSAndroid Build Coastguard Worker                     auto* mediaInfoDest = new MuxerNativeTestHelper(cdstPath, nullptr);
1112*b7c941bbSAndroid Build Coastguard Worker                     isPass = mediaInfoDest->isSubsetOf(mediaInfo);
1113*b7c941bbSAndroid Build Coastguard Worker                     delete mediaInfoDest;
1114*b7c941bbSAndroid Build Coastguard Worker                 }
1115*b7c941bbSAndroid Build Coastguard Worker             } else {
1116*b7c941bbSAndroid Build Coastguard Worker                 isPass = false;
1117*b7c941bbSAndroid Build Coastguard Worker                 ALOGE("failed to open output file %s", cdstPath);
1118*b7c941bbSAndroid Build Coastguard Worker             }
1119*b7c941bbSAndroid Build Coastguard Worker 
1120*b7c941bbSAndroid Build Coastguard Worker             // Append rest of the contents from the source file to the new file split by split.
1121*b7c941bbSAndroid Build Coastguard Worker             int curSplit = 1;
1122*b7c941bbSAndroid Build Coastguard Worker             while (curSplit < numSplits && isPass) {
1123*b7c941bbSAndroid Build Coastguard Worker                 ofp = fopen(cdstPath, "r+");
1124*b7c941bbSAndroid Build Coastguard Worker                 if (ofp) {
1125*b7c941bbSAndroid Build Coastguard Worker                     muxer = AMediaMuxer_append(fileno(ofp), AMEDIAMUXER_APPEND_TO_EXISTING_DATA);
1126*b7c941bbSAndroid Build Coastguard Worker                     if (muxer) {
1127*b7c941bbSAndroid Build Coastguard Worker                         ssize_t trackCount = AMediaMuxer_getTrackCount(muxer);
1128*b7c941bbSAndroid Build Coastguard Worker                         if (trackCount > 0) {
1129*b7c941bbSAndroid Build Coastguard Worker                             decltype(trackCount) tc = 0;
1130*b7c941bbSAndroid Build Coastguard Worker                             while(tc < trackCount) {
1131*b7c941bbSAndroid Build Coastguard Worker                                 AMediaFormat* format = AMediaMuxer_getTrackFormat(muxer, tc);
1132*b7c941bbSAndroid Build Coastguard Worker                                 int64_t val = 0;
1133*b7c941bbSAndroid Build Coastguard Worker                                 if (AMediaFormat_getInt64(format,
1134*b7c941bbSAndroid Build Coastguard Worker                                             AMEDIAFORMAT_KEY_SAMPLE_TIME_BEFORE_APPEND, &val)) {
1135*b7c941bbSAndroid Build Coastguard Worker                                     ALOGV("sample-time-before-append:%lld", (long long)val);
1136*b7c941bbSAndroid Build Coastguard Worker                                 }
1137*b7c941bbSAndroid Build Coastguard Worker                                 ++tc;
1138*b7c941bbSAndroid Build Coastguard Worker                             }
1139*b7c941bbSAndroid Build Coastguard Worker                             mediaInfo->appendMedia(muxer, totalSampleCount*curSplit/numSplits,
1140*b7c941bbSAndroid Build Coastguard Worker                                                         totalSampleCount*(curSplit+1)/numSplits-1);
1141*b7c941bbSAndroid Build Coastguard Worker                         } else {
1142*b7c941bbSAndroid Build Coastguard Worker                             isPass = false;
1143*b7c941bbSAndroid Build Coastguard Worker                             ALOGE("no tracks in the file");
1144*b7c941bbSAndroid Build Coastguard Worker                         }
1145*b7c941bbSAndroid Build Coastguard Worker                         AMediaMuxer_delete(muxer);
1146*b7c941bbSAndroid Build Coastguard Worker                     } else {
1147*b7c941bbSAndroid Build Coastguard Worker                         isPass = false;
1148*b7c941bbSAndroid Build Coastguard Worker                         ALOGE("failed to create muxer");
1149*b7c941bbSAndroid Build Coastguard Worker                     }
1150*b7c941bbSAndroid Build Coastguard Worker                     fclose(ofp);
1151*b7c941bbSAndroid Build Coastguard Worker                     ofp = nullptr;
1152*b7c941bbSAndroid Build Coastguard Worker                     if (isPass) {
1153*b7c941bbSAndroid Build Coastguard Worker                         auto* mediaInfoDest = new MuxerNativeTestHelper(cdstPath, nullptr);
1154*b7c941bbSAndroid Build Coastguard Worker                         isPass = mediaInfoDest->isSubsetOf(mediaInfo);
1155*b7c941bbSAndroid Build Coastguard Worker                         delete mediaInfoDest;
1156*b7c941bbSAndroid Build Coastguard Worker                     }
1157*b7c941bbSAndroid Build Coastguard Worker                 } else {
1158*b7c941bbSAndroid Build Coastguard Worker                     isPass = false;
1159*b7c941bbSAndroid Build Coastguard Worker                     ALOGE("failed to open output file %s", cdstPath);
1160*b7c941bbSAndroid Build Coastguard Worker                 }
1161*b7c941bbSAndroid Build Coastguard Worker                 ++curSplit;
1162*b7c941bbSAndroid Build Coastguard Worker             }
1163*b7c941bbSAndroid Build Coastguard Worker         }
1164*b7c941bbSAndroid Build Coastguard Worker         delete mediaInfo;
1165*b7c941bbSAndroid Build Coastguard Worker         env->ReleaseStringUTFChars(jdstPath, cdstPath);
1166*b7c941bbSAndroid Build Coastguard Worker         env->ReleaseStringUTFChars(jsrcPath, csrcPath);
1167*b7c941bbSAndroid Build Coastguard Worker     } else {
1168*b7c941bbSAndroid Build Coastguard Worker         isPass = false;
1169*b7c941bbSAndroid Build Coastguard Worker     }
1170*b7c941bbSAndroid Build Coastguard Worker     return static_cast<jboolean>(isPass);
1171*b7c941bbSAndroid Build Coastguard Worker }
1172*b7c941bbSAndroid Build Coastguard Worker 
1173*b7c941bbSAndroid Build Coastguard Worker /* Checks if opening a file to append data and closing it without actually appending data
1174*b7c941bbSAndroid Build Coastguard Worker  * works good in all append modes.
1175*b7c941bbSAndroid Build Coastguard Worker  */
nativeTestNoSamples(JNIEnv * env,jobject,jint joutFormat,jstring jinPath,jstring joutPath)1176*b7c941bbSAndroid Build Coastguard Worker static jboolean nativeTestNoSamples(JNIEnv* env, jobject, jint joutFormat, jstring jinPath,
1177*b7c941bbSAndroid Build Coastguard Worker                                         jstring joutPath) {
1178*b7c941bbSAndroid Build Coastguard Worker     bool isPass = true;
1179*b7c941bbSAndroid Build Coastguard Worker     if (__builtin_available(android __TRANSCODING_MIN_API__, *)) {
1180*b7c941bbSAndroid Build Coastguard Worker         const char* cinPath = env->GetStringUTFChars(jinPath, nullptr);
1181*b7c941bbSAndroid Build Coastguard Worker         const char* coutPath = env->GetStringUTFChars(joutPath, nullptr);
1182*b7c941bbSAndroid Build Coastguard Worker         ALOGV("cinPath:%s", cinPath);
1183*b7c941bbSAndroid Build Coastguard Worker         ALOGV("coutPath:%s", coutPath);
1184*b7c941bbSAndroid Build Coastguard Worker         auto* mediaInfo = new MuxerNativeTestHelper(cinPath);
1185*b7c941bbSAndroid Build Coastguard Worker         for (unsigned int mode = AMEDIAMUXER_APPEND_IGNORE_LAST_VIDEO_GOP;
1186*b7c941bbSAndroid Build Coastguard Worker                     mode <= AMEDIAMUXER_APPEND_TO_EXISTING_DATA; ++mode) {
1187*b7c941bbSAndroid Build Coastguard Worker             if (mediaInfo->getTrackCount() != 0) {
1188*b7c941bbSAndroid Build Coastguard Worker                 // Create a new file and write media data to it.
1189*b7c941bbSAndroid Build Coastguard Worker                 FILE *ofp = fopen(coutPath, "wbe+");
1190*b7c941bbSAndroid Build Coastguard Worker                 if (ofp) {
1191*b7c941bbSAndroid Build Coastguard Worker                     AMediaMuxer *muxer = AMediaMuxer_new(fileno(ofp), (OutputFormat) joutFormat);
1192*b7c941bbSAndroid Build Coastguard Worker                     mediaInfo->muxMedia(muxer);
1193*b7c941bbSAndroid Build Coastguard Worker                     AMediaMuxer_delete(muxer);
1194*b7c941bbSAndroid Build Coastguard Worker                     fclose(ofp);
1195*b7c941bbSAndroid Build Coastguard Worker                 } else {
1196*b7c941bbSAndroid Build Coastguard Worker                     isPass = false;
1197*b7c941bbSAndroid Build Coastguard Worker                     ALOGE("failed to open output file %s", coutPath);
1198*b7c941bbSAndroid Build Coastguard Worker                 }
1199*b7c941bbSAndroid Build Coastguard Worker             } else {
1200*b7c941bbSAndroid Build Coastguard Worker                 isPass = false;
1201*b7c941bbSAndroid Build Coastguard Worker                 ALOGE("no tracks in input file");
1202*b7c941bbSAndroid Build Coastguard Worker             }
1203*b7c941bbSAndroid Build Coastguard Worker             ALOGV("after file close");
1204*b7c941bbSAndroid Build Coastguard Worker             FILE* ofp = fopen(coutPath, "r+");
1205*b7c941bbSAndroid Build Coastguard Worker             if (ofp) {
1206*b7c941bbSAndroid Build Coastguard Worker                 ALOGV("create append muxer");
1207*b7c941bbSAndroid Build Coastguard Worker                 // Open the new file in one of the append modes and close it without writing data.
1208*b7c941bbSAndroid Build Coastguard Worker                 AMediaMuxer *muxer = AMediaMuxer_append(fileno(ofp), (AppendMode)mode);
1209*b7c941bbSAndroid Build Coastguard Worker                 if (muxer) {
1210*b7c941bbSAndroid Build Coastguard Worker                     AMediaMuxer_start(muxer);
1211*b7c941bbSAndroid Build Coastguard Worker                     AMediaMuxer_stop(muxer);
1212*b7c941bbSAndroid Build Coastguard Worker                     ALOGV("delete append muxer");
1213*b7c941bbSAndroid Build Coastguard Worker                     AMediaMuxer_delete(muxer);
1214*b7c941bbSAndroid Build Coastguard Worker                 } else {
1215*b7c941bbSAndroid Build Coastguard Worker                     isPass = false;
1216*b7c941bbSAndroid Build Coastguard Worker                     ALOGE("failed to create muxer");
1217*b7c941bbSAndroid Build Coastguard Worker                 }
1218*b7c941bbSAndroid Build Coastguard Worker                 fclose(ofp);
1219*b7c941bbSAndroid Build Coastguard Worker                 ofp = nullptr;
1220*b7c941bbSAndroid Build Coastguard Worker             } else {
1221*b7c941bbSAndroid Build Coastguard Worker                 isPass = false;
1222*b7c941bbSAndroid Build Coastguard Worker                 ALOGE("failed to open output file to append %s", coutPath);
1223*b7c941bbSAndroid Build Coastguard Worker             }
1224*b7c941bbSAndroid Build Coastguard Worker             // Check if contents written in the new file match with contents in the original file.
1225*b7c941bbSAndroid Build Coastguard Worker             auto* mediaInfoOut = new MuxerNativeTestHelper(coutPath, nullptr);
1226*b7c941bbSAndroid Build Coastguard Worker             isPass = mediaInfoOut->isSubsetOf(mediaInfo);
1227*b7c941bbSAndroid Build Coastguard Worker             delete mediaInfoOut;
1228*b7c941bbSAndroid Build Coastguard Worker         }
1229*b7c941bbSAndroid Build Coastguard Worker         delete mediaInfo;
1230*b7c941bbSAndroid Build Coastguard Worker         env->ReleaseStringUTFChars(jinPath, cinPath);
1231*b7c941bbSAndroid Build Coastguard Worker         env->ReleaseStringUTFChars(joutPath, coutPath);
1232*b7c941bbSAndroid Build Coastguard Worker     } else {
1233*b7c941bbSAndroid Build Coastguard Worker         isPass = false;
1234*b7c941bbSAndroid Build Coastguard Worker     }
1235*b7c941bbSAndroid Build Coastguard Worker     return static_cast<jboolean>(isPass);
1236*b7c941bbSAndroid Build Coastguard Worker }
1237*b7c941bbSAndroid Build Coastguard Worker 
1238*b7c941bbSAndroid Build Coastguard Worker /*
1239*b7c941bbSAndroid Build Coastguard Worker  * Checks if appending media data in AMEDIAMUXER_APPEND_IGNORE_LAST_VIDEO_GOP mode works good.
1240*b7c941bbSAndroid Build Coastguard Worker  * Splits the contents of source file equally starting from one and increasing the number of
1241*b7c941bbSAndroid Build Coastguard Worker  * splits by one for every iteration.  Starts with writing first split into a new file and
1242*b7c941bbSAndroid Build Coastguard Worker  * appends the rest of the contents split by split.
1243*b7c941bbSAndroid Build Coastguard Worker  */
nativeTestIgnoreLastGOPAppend(JNIEnv * env,jobject,jint joutFormat,jstring jsrcPath,jstring jdstPath)1244*b7c941bbSAndroid Build Coastguard Worker static jboolean nativeTestIgnoreLastGOPAppend(JNIEnv* env, jobject, jint joutFormat,
1245*b7c941bbSAndroid Build Coastguard Worker                                     jstring jsrcPath, jstring jdstPath) {
1246*b7c941bbSAndroid Build Coastguard Worker     bool isPass = true;
1247*b7c941bbSAndroid Build Coastguard Worker     if (__builtin_available(android __TRANSCODING_MIN_API__, *)) {
1248*b7c941bbSAndroid Build Coastguard Worker         const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
1249*b7c941bbSAndroid Build Coastguard Worker         const char* cdstPath = env->GetStringUTFChars(jdstPath, nullptr);
1250*b7c941bbSAndroid Build Coastguard Worker         ALOGV("csrcPath:%s", csrcPath);
1251*b7c941bbSAndroid Build Coastguard Worker         ALOGV("cdstPath:%s", cdstPath);
1252*b7c941bbSAndroid Build Coastguard Worker         auto* mediaInfo = new MuxerNativeTestHelper(csrcPath);
1253*b7c941bbSAndroid Build Coastguard Worker         for (int numSplits = 1; numSplits <= 5 && isPass; ++numSplits) {
1254*b7c941bbSAndroid Build Coastguard Worker             ALOGV("numSplits:%d", numSplits);
1255*b7c941bbSAndroid Build Coastguard Worker             size_t totalSampleCount = 0;
1256*b7c941bbSAndroid Build Coastguard Worker             size_t totalSamplesWritten = 0;
1257*b7c941bbSAndroid Build Coastguard Worker             AMediaMuxer *muxer = nullptr;
1258*b7c941bbSAndroid Build Coastguard Worker             FILE* ofp = fopen(cdstPath, "w+");
1259*b7c941bbSAndroid Build Coastguard Worker             if (ofp) {
1260*b7c941bbSAndroid Build Coastguard Worker                 // Start by writing first split into a new file.
1261*b7c941bbSAndroid Build Coastguard Worker                 muxer = AMediaMuxer_new(fileno(ofp), (OutputFormat)joutFormat);
1262*b7c941bbSAndroid Build Coastguard Worker                 if (muxer) {
1263*b7c941bbSAndroid Build Coastguard Worker                     for(int i = 0 ; i < mediaInfo->getTrackCount(); ++i ) {
1264*b7c941bbSAndroid Build Coastguard Worker                         ALOGV("getSampleCount:%d:%zu", i, mediaInfo->getSampleCount(i));
1265*b7c941bbSAndroid Build Coastguard Worker                         totalSampleCount += mediaInfo->getSampleCount(i);
1266*b7c941bbSAndroid Build Coastguard Worker                     }
1267*b7c941bbSAndroid Build Coastguard Worker                     mediaInfo->appendMedia(muxer, 0, (totalSampleCount/numSplits)-1);
1268*b7c941bbSAndroid Build Coastguard Worker                     totalSamplesWritten += (totalSampleCount/numSplits);
1269*b7c941bbSAndroid Build Coastguard Worker                     AMediaMuxer_delete(muxer);
1270*b7c941bbSAndroid Build Coastguard Worker                 } else {
1271*b7c941bbSAndroid Build Coastguard Worker                     isPass = false;
1272*b7c941bbSAndroid Build Coastguard Worker                     ALOGE("Failed to create muxer");
1273*b7c941bbSAndroid Build Coastguard Worker                 }
1274*b7c941bbSAndroid Build Coastguard Worker                 fclose(ofp);
1275*b7c941bbSAndroid Build Coastguard Worker                 ofp = nullptr;
1276*b7c941bbSAndroid Build Coastguard Worker                 if (isPass) {
1277*b7c941bbSAndroid Build Coastguard Worker                     // Check if the contents in the new file is as same as in the source file.
1278*b7c941bbSAndroid Build Coastguard Worker                     auto* mediaInfoDest = new MuxerNativeTestHelper(cdstPath, nullptr);
1279*b7c941bbSAndroid Build Coastguard Worker                     isPass = mediaInfoDest->isSubsetOf(mediaInfo);
1280*b7c941bbSAndroid Build Coastguard Worker                     delete mediaInfoDest;
1281*b7c941bbSAndroid Build Coastguard Worker                 }
1282*b7c941bbSAndroid Build Coastguard Worker             } else {
1283*b7c941bbSAndroid Build Coastguard Worker                 isPass = false;
1284*b7c941bbSAndroid Build Coastguard Worker                 ALOGE("failed to open output file %s", cdstPath);
1285*b7c941bbSAndroid Build Coastguard Worker             }
1286*b7c941bbSAndroid Build Coastguard Worker 
1287*b7c941bbSAndroid Build Coastguard Worker             // Append rest of the contents from the source file to the new file split by split.
1288*b7c941bbSAndroid Build Coastguard Worker             int curSplit = 1;
1289*b7c941bbSAndroid Build Coastguard Worker             while (curSplit < numSplits && isPass) {
1290*b7c941bbSAndroid Build Coastguard Worker                 ofp = fopen(cdstPath, "r+");
1291*b7c941bbSAndroid Build Coastguard Worker                 if (ofp) {
1292*b7c941bbSAndroid Build Coastguard Worker                     muxer = AMediaMuxer_append(fileno(ofp),
1293*b7c941bbSAndroid Build Coastguard Worker                                 AMEDIAMUXER_APPEND_IGNORE_LAST_VIDEO_GOP);
1294*b7c941bbSAndroid Build Coastguard Worker                     if (muxer) {
1295*b7c941bbSAndroid Build Coastguard Worker                         auto trackCount = AMediaMuxer_getTrackCount(muxer);
1296*b7c941bbSAndroid Build Coastguard Worker                         if (trackCount > 0) {
1297*b7c941bbSAndroid Build Coastguard Worker                             decltype(trackCount) tc = 0;
1298*b7c941bbSAndroid Build Coastguard Worker                             int64_t* appendFromTime = new int64_t[trackCount]{0};
1299*b7c941bbSAndroid Build Coastguard Worker                             while(tc < trackCount) {
1300*b7c941bbSAndroid Build Coastguard Worker                                 AMediaFormat* format = AMediaMuxer_getTrackFormat(muxer, tc);
1301*b7c941bbSAndroid Build Coastguard Worker                                 int64_t val = 0;
1302*b7c941bbSAndroid Build Coastguard Worker                                 if (AMediaFormat_getInt64(format,
1303*b7c941bbSAndroid Build Coastguard Worker                                             AMEDIAFORMAT_KEY_SAMPLE_TIME_BEFORE_APPEND, &val)) {
1304*b7c941bbSAndroid Build Coastguard Worker                                     ALOGV("sample-time-before-append:%lld", (long long)val);
1305*b7c941bbSAndroid Build Coastguard Worker                                     appendFromTime[tc] = val;
1306*b7c941bbSAndroid Build Coastguard Worker                                 }
1307*b7c941bbSAndroid Build Coastguard Worker                                 ++tc;
1308*b7c941bbSAndroid Build Coastguard Worker                             }
1309*b7c941bbSAndroid Build Coastguard Worker                             bool lastSplit = (curSplit == numSplits-1) ? true : false;
1310*b7c941bbSAndroid Build Coastguard Worker                             mediaInfo->appendMediaFromTime(muxer, appendFromTime,
1311*b7c941bbSAndroid Build Coastguard Worker                                 totalSampleCount/numSplits + ((curSplit-1) * 30), lastSplit);
1312*b7c941bbSAndroid Build Coastguard Worker                             delete[] appendFromTime;
1313*b7c941bbSAndroid Build Coastguard Worker                         } else {
1314*b7c941bbSAndroid Build Coastguard Worker                             isPass = false;
1315*b7c941bbSAndroid Build Coastguard Worker                             ALOGE("no tracks in the file");
1316*b7c941bbSAndroid Build Coastguard Worker                         }
1317*b7c941bbSAndroid Build Coastguard Worker                         AMediaMuxer_delete(muxer);
1318*b7c941bbSAndroid Build Coastguard Worker                     } else {
1319*b7c941bbSAndroid Build Coastguard Worker                         isPass = false;
1320*b7c941bbSAndroid Build Coastguard Worker                         ALOGE("failed to create muxer");
1321*b7c941bbSAndroid Build Coastguard Worker                     }
1322*b7c941bbSAndroid Build Coastguard Worker                     fclose(ofp);
1323*b7c941bbSAndroid Build Coastguard Worker                     ofp = nullptr;
1324*b7c941bbSAndroid Build Coastguard Worker                     if (isPass) {
1325*b7c941bbSAndroid Build Coastguard Worker                         auto* mediaInfoDest = new MuxerNativeTestHelper(cdstPath, nullptr);
1326*b7c941bbSAndroid Build Coastguard Worker                         isPass = mediaInfoDest->isSubsetOf(mediaInfo);
1327*b7c941bbSAndroid Build Coastguard Worker                         delete mediaInfoDest;
1328*b7c941bbSAndroid Build Coastguard Worker                     }
1329*b7c941bbSAndroid Build Coastguard Worker                 } else {
1330*b7c941bbSAndroid Build Coastguard Worker                     isPass = false;
1331*b7c941bbSAndroid Build Coastguard Worker                     ALOGE("failed to open output file %s", cdstPath);
1332*b7c941bbSAndroid Build Coastguard Worker                 }
1333*b7c941bbSAndroid Build Coastguard Worker                 ++curSplit;
1334*b7c941bbSAndroid Build Coastguard Worker             }
1335*b7c941bbSAndroid Build Coastguard Worker         }
1336*b7c941bbSAndroid Build Coastguard Worker         delete mediaInfo;
1337*b7c941bbSAndroid Build Coastguard Worker         env->ReleaseStringUTFChars(jdstPath, cdstPath);
1338*b7c941bbSAndroid Build Coastguard Worker         env->ReleaseStringUTFChars(jsrcPath, csrcPath);
1339*b7c941bbSAndroid Build Coastguard Worker     } else {
1340*b7c941bbSAndroid Build Coastguard Worker         isPass = false;
1341*b7c941bbSAndroid Build Coastguard Worker     }
1342*b7c941bbSAndroid Build Coastguard Worker     return static_cast<jboolean>(isPass);
1343*b7c941bbSAndroid Build Coastguard Worker }
1344*b7c941bbSAndroid Build Coastguard Worker 
registerAndroidMediaV2CtsMuxerTestApi(JNIEnv * env)1345*b7c941bbSAndroid Build Coastguard Worker int registerAndroidMediaV2CtsMuxerTestApi(JNIEnv* env) {
1346*b7c941bbSAndroid Build Coastguard Worker     const JNINativeMethod methodTable[] = {
1347*b7c941bbSAndroid Build Coastguard Worker             {"nativeTestSetOrientationHint", "(ILjava/lang/String;Ljava/lang/String;)Z",
1348*b7c941bbSAndroid Build Coastguard Worker              (void*)nativeTestSetOrientationHint},
1349*b7c941bbSAndroid Build Coastguard Worker             {"nativeTestSetLocation", "(ILjava/lang/String;Ljava/lang/String;)Z",
1350*b7c941bbSAndroid Build Coastguard Worker              (void*)nativeTestSetLocation},
1351*b7c941bbSAndroid Build Coastguard Worker             {"nativeTestGetTrackCount", "(Ljava/lang/String;Ljava/lang/String;II)Z",
1352*b7c941bbSAndroid Build Coastguard Worker              (void*)nativeTestGetTrackCount},
1353*b7c941bbSAndroid Build Coastguard Worker             {"nativeTestGetTrackFormat", "(Ljava/lang/String;Ljava/lang/String;I)Z",
1354*b7c941bbSAndroid Build Coastguard Worker              (void*)nativeTestGetTrackFormat},
1355*b7c941bbSAndroid Build Coastguard Worker     };
1356*b7c941bbSAndroid Build Coastguard Worker     jclass c = env->FindClass("android/mediav2/cts/MuxerTest$TestApi");
1357*b7c941bbSAndroid Build Coastguard Worker     return env->RegisterNatives(c, methodTable, sizeof(methodTable) / sizeof(JNINativeMethod));
1358*b7c941bbSAndroid Build Coastguard Worker }
1359*b7c941bbSAndroid Build Coastguard Worker 
registerAndroidMediaV2CtsMuxerTestMultiTrack(JNIEnv * env)1360*b7c941bbSAndroid Build Coastguard Worker int registerAndroidMediaV2CtsMuxerTestMultiTrack(JNIEnv* env) {
1361*b7c941bbSAndroid Build Coastguard Worker     const JNINativeMethod methodTable[] = {
1362*b7c941bbSAndroid Build Coastguard Worker             {"nativeTestMultiTrack",
1363*b7c941bbSAndroid Build Coastguard Worker              "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z",
1364*b7c941bbSAndroid Build Coastguard Worker              (void*)nativeTestMultiTrack},
1365*b7c941bbSAndroid Build Coastguard Worker     };
1366*b7c941bbSAndroid Build Coastguard Worker     jclass c = env->FindClass("android/mediav2/cts/MuxerTest$TestMultiTrack");
1367*b7c941bbSAndroid Build Coastguard Worker     return env->RegisterNatives(c, methodTable, sizeof(methodTable) / sizeof(JNINativeMethod));
1368*b7c941bbSAndroid Build Coastguard Worker }
1369*b7c941bbSAndroid Build Coastguard Worker 
registerAndroidMediaV2CtsMuxerTestOffsetPts(JNIEnv * env)1370*b7c941bbSAndroid Build Coastguard Worker int registerAndroidMediaV2CtsMuxerTestOffsetPts(JNIEnv* env) {
1371*b7c941bbSAndroid Build Coastguard Worker     const JNINativeMethod methodTable[] = {
1372*b7c941bbSAndroid Build Coastguard Worker             {"nativeTestOffsetPts", "(ILjava/lang/String;Ljava/lang/String;[I)Z",
1373*b7c941bbSAndroid Build Coastguard Worker              (void*)nativeTestOffsetPts},
1374*b7c941bbSAndroid Build Coastguard Worker     };
1375*b7c941bbSAndroid Build Coastguard Worker     jclass c = env->FindClass("android/mediav2/cts/MuxerTest$TestOffsetPts");
1376*b7c941bbSAndroid Build Coastguard Worker     return env->RegisterNatives(c, methodTable, sizeof(methodTable) / sizeof(JNINativeMethod));
1377*b7c941bbSAndroid Build Coastguard Worker }
1378*b7c941bbSAndroid Build Coastguard Worker 
registerAndroidMediaV2CtsMuxerTestSimpleMux(JNIEnv * env)1379*b7c941bbSAndroid Build Coastguard Worker int registerAndroidMediaV2CtsMuxerTestSimpleMux(JNIEnv* env) {
1380*b7c941bbSAndroid Build Coastguard Worker     const JNINativeMethod methodTable[] = {
1381*b7c941bbSAndroid Build Coastguard Worker             {"nativeTestSimpleMux",
1382*b7c941bbSAndroid Build Coastguard Worker              "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z",
1383*b7c941bbSAndroid Build Coastguard Worker              (void*)nativeTestSimpleMux},
1384*b7c941bbSAndroid Build Coastguard Worker     };
1385*b7c941bbSAndroid Build Coastguard Worker     jclass c = env->FindClass("android/mediav2/cts/MuxerTest$TestSimpleMux");
1386*b7c941bbSAndroid Build Coastguard Worker     return env->RegisterNatives(c, methodTable, sizeof(methodTable) / sizeof(JNINativeMethod));
1387*b7c941bbSAndroid Build Coastguard Worker }
1388*b7c941bbSAndroid Build Coastguard Worker 
registerAndroidMediaV2CtsMuxerTestSimpleAppend(JNIEnv * env)1389*b7c941bbSAndroid Build Coastguard Worker int registerAndroidMediaV2CtsMuxerTestSimpleAppend(JNIEnv* env) {
1390*b7c941bbSAndroid Build Coastguard Worker     const JNINativeMethod methodTable[] = {
1391*b7c941bbSAndroid Build Coastguard Worker             {"nativeTestSimpleAppend",
1392*b7c941bbSAndroid Build Coastguard Worker              "(ILjava/lang/String;Ljava/lang/String;)Z",
1393*b7c941bbSAndroid Build Coastguard Worker              (void*)nativeTestSimpleAppend},
1394*b7c941bbSAndroid Build Coastguard Worker             {"nativeTestAppendGetTrackCount",
1395*b7c941bbSAndroid Build Coastguard Worker              "(Ljava/lang/String;I)Z",
1396*b7c941bbSAndroid Build Coastguard Worker              (void*)nativeTestAppendGetTrackCount},
1397*b7c941bbSAndroid Build Coastguard Worker             {"nativeTestAppendGetTrackFormat", "(Ljava/lang/String;)Z",
1398*b7c941bbSAndroid Build Coastguard Worker              (void*)nativeTestAppendGetTrackFormat},
1399*b7c941bbSAndroid Build Coastguard Worker              {"nativeTestNoSamples",
1400*b7c941bbSAndroid Build Coastguard Worker               "(ILjava/lang/String;Ljava/lang/String;)Z",
1401*b7c941bbSAndroid Build Coastguard Worker               (void*)nativeTestNoSamples},
1402*b7c941bbSAndroid Build Coastguard Worker             {"nativeTestIgnoreLastGOPAppend",
1403*b7c941bbSAndroid Build Coastguard Worker              "(ILjava/lang/String;Ljava/lang/String;)Z",
1404*b7c941bbSAndroid Build Coastguard Worker              (void*)nativeTestIgnoreLastGOPAppend},
1405*b7c941bbSAndroid Build Coastguard Worker     };
1406*b7c941bbSAndroid Build Coastguard Worker     jclass c = env->FindClass("android/mediav2/cts/MuxerTest$TestSimpleAppend");
1407*b7c941bbSAndroid Build Coastguard Worker     return env->RegisterNatives(c, methodTable, sizeof(methodTable) / sizeof(JNINativeMethod));
1408*b7c941bbSAndroid Build Coastguard Worker }
1409*b7c941bbSAndroid Build Coastguard Worker 
1410*b7c941bbSAndroid Build Coastguard Worker extern int registerAndroidMediaV2CtsMuxerUnitTestApi(JNIEnv* env);
1411*b7c941bbSAndroid Build Coastguard Worker 
JNI_OnLoad(JavaVM * vm,void *)1412*b7c941bbSAndroid Build Coastguard Worker extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) {
1413*b7c941bbSAndroid Build Coastguard Worker     JNIEnv* env;
1414*b7c941bbSAndroid Build Coastguard Worker     if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) return JNI_ERR;
1415*b7c941bbSAndroid Build Coastguard Worker     if (registerAndroidMediaV2CtsMuxerTestApi(env) != JNI_OK) return JNI_ERR;
1416*b7c941bbSAndroid Build Coastguard Worker     if (registerAndroidMediaV2CtsMuxerTestMultiTrack(env) != JNI_OK) return JNI_ERR;
1417*b7c941bbSAndroid Build Coastguard Worker     if (registerAndroidMediaV2CtsMuxerTestOffsetPts(env) != JNI_OK) return JNI_ERR;
1418*b7c941bbSAndroid Build Coastguard Worker     if (registerAndroidMediaV2CtsMuxerTestSimpleMux(env) != JNI_OK) return JNI_ERR;
1419*b7c941bbSAndroid Build Coastguard Worker     if (registerAndroidMediaV2CtsMuxerTestSimpleAppend(env) != JNI_OK) return JNI_ERR;
1420*b7c941bbSAndroid Build Coastguard Worker     if (registerAndroidMediaV2CtsMuxerUnitTestApi(env) != JNI_OK) return JNI_ERR;
1421*b7c941bbSAndroid Build Coastguard Worker     return JNI_VERSION_1_6;
1422*b7c941bbSAndroid Build Coastguard Worker }
1423