• 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 #include "BenchmarkCommon.h"
43 using namespace android;
44 
ReadMediaSamples(benchmark::State & state,const std::string & srcFileName,bool readAudio,bool sequentialAccess=false)45 static void ReadMediaSamples(benchmark::State& state, const std::string& srcFileName,
46                              bool readAudio, bool sequentialAccess = false) {
47     int srcFd = 0;
48     std::string srcPath = kAssetDirectory + srcFileName;
49 
50     if ((srcFd = open(srcPath.c_str(), O_RDONLY)) < 0) {
51         state.SkipWithError("Unable to open source file: " + srcPath);
52         return;
53     }
54 
55     const size_t fileSize = lseek(srcFd, 0, SEEK_END);
56     lseek(srcFd, 0, SEEK_SET);
57 
58     for (auto _ : state) {
59         auto sampleReader = MediaSampleReaderNDK::createFromFd(srcFd, 0, fileSize);
60         if (sampleReader->setEnforceSequentialAccess(sequentialAccess) != AMEDIA_OK) {
61             state.SkipWithError("setEnforceSequentialAccess failed");
62             return;
63         }
64 
65         // Select tracks.
66         std::vector<int> trackIndices;
67         for (int trackIndex = 0; trackIndex < sampleReader->getTrackCount(); ++trackIndex) {
68             const char* mime = nullptr;
69 
70             AMediaFormat* trackFormat = sampleReader->getTrackFormat(trackIndex);
71             AMediaFormat_getString(trackFormat, AMEDIAFORMAT_KEY_MIME, &mime);
72 
73             if (strncmp(mime, "video/", 6) == 0) {
74                 int32_t frameCount;
75                 if (AMediaFormat_getInt32(trackFormat, AMEDIAFORMAT_KEY_FRAME_COUNT, &frameCount)) {
76                     state.counters["VideoFrameRate"] =
77                             benchmark::Counter(frameCount, benchmark::Counter::kIsRate);
78                 }
79             } else if (!readAudio && strncmp(mime, "audio/", 6) == 0) {
80                 continue;
81             }
82 
83             trackIndices.push_back(trackIndex);
84             sampleReader->selectTrack(trackIndex);
85         }
86 
87         // Start threads.
88         std::vector<std::thread> trackThreads;
89         for (auto trackIndex : trackIndices) {
90             trackThreads.emplace_back([trackIndex, sampleReader, &state] {
91                 LOG(INFO) << "Track " << trackIndex << " started";
92                 MediaSampleInfo info;
93 
94                 size_t bufferSize = 0;
95                 std::unique_ptr<uint8_t[]> buffer;
96 
97                 while (true) {
98                     media_status_t status = sampleReader->getSampleInfoForTrack(trackIndex, &info);
99                     if (status == AMEDIA_ERROR_END_OF_STREAM) {
100                         break;
101                     }
102 
103                     if (info.size > bufferSize) {
104                         bufferSize = info.size;
105                         buffer.reset(new uint8_t[bufferSize]);
106                     }
107 
108                     status = sampleReader->readSampleDataForTrack(trackIndex, buffer.get(),
109                                                                   bufferSize);
110                     if (status != AMEDIA_OK) {
111                         state.SkipWithError("Error reading sample data");
112                         break;
113                     }
114                 }
115 
116                 LOG(INFO) << "Track " << trackIndex << " finished";
117             });
118         }
119 
120         // Join threads.
121         for (auto& thread : trackThreads) {
122             thread.join();
123         }
124     }
125 
126     close(srcFd);
127 }
128 
129 // Benchmark registration wrapper for transcoding.
130 #define TRANSCODER_BENCHMARK(func) \
131     BENCHMARK(func)->UseRealTime()->MeasureProcessCPUTime()->Unit(benchmark::kMillisecond)
132 
BM_MediaSampleReader_AudioVideo_Parallel(benchmark::State & state)133 static void BM_MediaSampleReader_AudioVideo_Parallel(benchmark::State& state) {
134     ReadMediaSamples(state, "video_1920x1080_3648frame_h264_22Mbps_30fps_aac.mp4",
135                      true /* readAudio */);
136 }
137 
BM_MediaSampleReader_AudioVideo_Sequential(benchmark::State & state)138 static void BM_MediaSampleReader_AudioVideo_Sequential(benchmark::State& state) {
139     ReadMediaSamples(state, "video_1920x1080_3648frame_h264_22Mbps_30fps_aac.mp4",
140                      true /* readAudio */, true /* sequentialAccess */);
141 }
142 
BM_MediaSampleReader_Video(benchmark::State & state)143 static void BM_MediaSampleReader_Video(benchmark::State& state) {
144     ReadMediaSamples(state, "video_1920x1080_3648frame_h264_22Mbps_30fps_aac.mp4",
145                      false /* readAudio */);
146 }
147 
148 TRANSCODER_BENCHMARK(BM_MediaSampleReader_AudioVideo_Parallel);
149 TRANSCODER_BENCHMARK(BM_MediaSampleReader_AudioVideo_Sequential);
150 TRANSCODER_BENCHMARK(BM_MediaSampleReader_Video);
151 
152 BENCHMARK_MAIN();
153