• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /**
18  * MediaSampleReader benchmark tests.
19  *
20  * How to run the benchmark:
21  *
22  * 1. Download the media assets from http://go/transcodingbenchmark and push the directory
23  *    ("TranscodingBenchmark") to /data/local/tmp.
24  *
25  * 2. Compile the benchmark and sync to device:
26  *      $ mm -j72 && adb sync
27  *
28  * 3. Run:
29  *      $ adb shell /data/nativetest64/MediaSampleReaderBenchmark/MediaSampleReaderBenchmark
30  */
31 
32 #define LOG_TAG "MediaSampleReaderBenchmark"
33 
34 #include <android-base/logging.h>
35 #include <benchmark/benchmark.h>
36 #include <fcntl.h>
37 #include <media/MediaSampleReaderNDK.h>
38 #include <unistd.h>
39 
40 #include <thread>
41 
42 using namespace android;
43 
ReadMediaSamples(benchmark::State & state,const std::string & srcFileName,bool readAudio,bool sequentialAccess=false)44 static void ReadMediaSamples(benchmark::State& state, const std::string& srcFileName,
45                              bool readAudio, bool sequentialAccess = false) {
46     // Asset directory.
47     static const std::string kAssetDirectory = "/data/local/tmp/TranscodingBenchmark/";
48 
49     int srcFd = 0;
50     std::string srcPath = kAssetDirectory + srcFileName;
51 
52     if ((srcFd = open(srcPath.c_str(), O_RDONLY)) < 0) {
53         state.SkipWithError("Unable to open source file");
54         return;
55     }
56 
57     const size_t fileSize = lseek(srcFd, 0, SEEK_END);
58     lseek(srcFd, 0, SEEK_SET);
59 
60     for (auto _ : state) {
61         auto sampleReader = MediaSampleReaderNDK::createFromFd(srcFd, 0, fileSize);
62         if (sampleReader->setEnforceSequentialAccess(sequentialAccess) != AMEDIA_OK) {
63             state.SkipWithError("setEnforceSequentialAccess failed");
64             return;
65         }
66 
67         // Select tracks.
68         std::vector<int> trackIndices;
69         for (int trackIndex = 0; trackIndex < sampleReader->getTrackCount(); ++trackIndex) {
70             const char* mime = nullptr;
71 
72             AMediaFormat* trackFormat = sampleReader->getTrackFormat(trackIndex);
73             AMediaFormat_getString(trackFormat, AMEDIAFORMAT_KEY_MIME, &mime);
74 
75             if (strncmp(mime, "video/", 6) == 0) {
76                 int32_t frameCount;
77                 if (AMediaFormat_getInt32(trackFormat, AMEDIAFORMAT_KEY_FRAME_COUNT, &frameCount)) {
78                     state.counters["VideoFrameRate"] =
79                             benchmark::Counter(frameCount, benchmark::Counter::kIsRate);
80                 }
81             } else if (!readAudio && strncmp(mime, "audio/", 6) == 0) {
82                 continue;
83             }
84 
85             trackIndices.push_back(trackIndex);
86             sampleReader->selectTrack(trackIndex);
87         }
88 
89         // Start threads.
90         std::vector<std::thread> trackThreads;
91         for (auto trackIndex : trackIndices) {
92             trackThreads.emplace_back([trackIndex, sampleReader, &state] {
93                 LOG(INFO) << "Track " << trackIndex << " started";
94                 MediaSampleInfo info;
95 
96                 size_t bufferSize = 0;
97                 std::unique_ptr<uint8_t[]> buffer;
98 
99                 while (true) {
100                     media_status_t status = sampleReader->getSampleInfoForTrack(trackIndex, &info);
101                     if (status == AMEDIA_ERROR_END_OF_STREAM) {
102                         break;
103                     }
104 
105                     if (info.size > bufferSize) {
106                         bufferSize = info.size;
107                         buffer.reset(new uint8_t[bufferSize]);
108                     }
109 
110                     status = sampleReader->readSampleDataForTrack(trackIndex, buffer.get(),
111                                                                   bufferSize);
112                     if (status != AMEDIA_OK) {
113                         state.SkipWithError("Error reading sample data");
114                         break;
115                     }
116                 }
117 
118                 LOG(INFO) << "Track " << trackIndex << " finished";
119             });
120         }
121 
122         // Join threads.
123         for (auto& thread : trackThreads) {
124             thread.join();
125         }
126     }
127 
128     close(srcFd);
129 }
130 
131 // Benchmark registration wrapper for transcoding.
132 #define TRANSCODER_BENCHMARK(func) \
133     BENCHMARK(func)->UseRealTime()->MeasureProcessCPUTime()->Unit(benchmark::kMillisecond)
134 
BM_MediaSampleReader_AudioVideo_Parallel(benchmark::State & state)135 static void BM_MediaSampleReader_AudioVideo_Parallel(benchmark::State& state) {
136     ReadMediaSamples(state, "video_1920x1080_3648frame_h264_22Mbps_30fps_aac.mp4",
137                      true /* readAudio */);
138 }
139 
BM_MediaSampleReader_AudioVideo_Sequential(benchmark::State & state)140 static void BM_MediaSampleReader_AudioVideo_Sequential(benchmark::State& state) {
141     ReadMediaSamples(state, "video_1920x1080_3648frame_h264_22Mbps_30fps_aac.mp4",
142                      true /* readAudio */, true /* sequentialAccess */);
143 }
144 
BM_MediaSampleReader_Video(benchmark::State & state)145 static void BM_MediaSampleReader_Video(benchmark::State& state) {
146     ReadMediaSamples(state, "video_1920x1080_3648frame_h264_22Mbps_30fps_aac.mp4",
147                      false /* readAudio */);
148 }
149 
150 TRANSCODER_BENCHMARK(BM_MediaSampleReader_AudioVideo_Parallel);
151 TRANSCODER_BENCHMARK(BM_MediaSampleReader_AudioVideo_Sequential);
152 TRANSCODER_BENCHMARK(BM_MediaSampleReader_Video);
153 
154 BENCHMARK_MAIN();
155