1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.media.benchmark.library; 18 19 import android.media.MediaCodec; 20 import android.media.MediaExtractor; 21 import android.media.MediaFormat; 22 import android.util.Log; 23 24 import java.io.FileDescriptor; 25 import java.io.IOException; 26 import java.nio.ByteBuffer; 27 28 public class Extractor { 29 private static final String TAG = "Extractor"; 30 private static final int kMaxBufSize = 1024 * 1024 * 16; 31 private MediaExtractor mExtractor; 32 private ByteBuffer mFrameBuffer; 33 private MediaCodec.BufferInfo mBufferInfo; 34 private Stats mStats; 35 private long mDurationUs; 36 Extractor()37 public Extractor() { 38 mFrameBuffer = ByteBuffer.allocate(kMaxBufSize); 39 mBufferInfo = new MediaCodec.BufferInfo(); 40 mStats = new Stats(); 41 } 42 43 /** 44 * Creates a Media Extractor and sets data source(FileDescriptor)to use 45 * 46 * @param fileDescriptor FileDescriptor for the file which is to be extracted 47 * @return TrackCount of the sample 48 * @throws IOException If FileDescriptor is null 49 */ setUpExtractor(FileDescriptor fileDescriptor)50 public int setUpExtractor(FileDescriptor fileDescriptor) throws IOException { 51 long sTime = mStats.getCurTime(); 52 mExtractor = new MediaExtractor(); 53 mExtractor.setDataSource(fileDescriptor); 54 long eTime = mStats.getCurTime(); 55 long timeTaken = mStats.getTimeDiff(sTime, eTime); 56 mStats.setInitTime(timeTaken); 57 return mExtractor.getTrackCount(); 58 } 59 60 /** 61 * Returns the track format of the specified index 62 * 63 * @param trackID Index of the track 64 * @return Format of the track 65 */ getFormat(int trackID)66 public MediaFormat getFormat(int trackID) { return mExtractor.getTrackFormat(trackID); } 67 68 /** 69 * Returns the extracted buffer for the input clip 70 */ getFrameBuffer()71 public ByteBuffer getFrameBuffer() { return this.mFrameBuffer; } 72 73 /** 74 * Returns the information of buffer related to sample 75 */ getBufferInfo()76 public MediaCodec.BufferInfo getBufferInfo() { return this.mBufferInfo; } 77 78 /** 79 * Returns the duration of the sample 80 */ getClipDuration()81 public long getClipDuration() { return this.mDurationUs; } 82 83 /** 84 * Retrieve the current sample and store it in the byte buffer 85 * Also, sets the information related to extracted sample and store it in buffer info 86 * 87 * @return Sample size of the extracted sample 88 */ getFrameSample()89 public int getFrameSample() { 90 int sampleSize = mExtractor.readSampleData(mFrameBuffer, 0); 91 if (sampleSize < 0) { 92 mBufferInfo.flags = MediaCodec.BUFFER_FLAG_END_OF_STREAM; 93 mBufferInfo.size = 0; 94 } else { 95 mBufferInfo.size = sampleSize; 96 mBufferInfo.offset = 0; 97 mBufferInfo.flags = mExtractor.getSampleFlags(); 98 mBufferInfo.presentationTimeUs = mExtractor.getSampleTime(); 99 mExtractor.advance(); 100 } 101 return sampleSize; 102 } 103 104 /** 105 * Setup the track format and get the duration of the sample 106 * Track is selected here for extraction 107 * 108 * @param trackId Track index to be selected 109 * @return 0 for valid track, otherwise -1 110 */ selectExtractorTrack(int trackId)111 public int selectExtractorTrack(int trackId) { 112 MediaFormat trackFormat = mExtractor.getTrackFormat(trackId); 113 mDurationUs = trackFormat.getLong(MediaFormat.KEY_DURATION); 114 if (mDurationUs < 0) { 115 Log.e(TAG, "Invalid Clip"); 116 return -1; 117 } 118 mExtractor.selectTrack(trackId); 119 return 0; 120 } 121 122 /** 123 * Unselect the track 124 * 125 * @param trackId Track Index to be unselected 126 */ unselectExtractorTrack(int trackId)127 public void unselectExtractorTrack(int trackId) { mExtractor.unselectTrack(trackId); } 128 129 /** 130 * Free up the resources 131 */ deinitExtractor()132 public void deinitExtractor() { 133 long sTime = mStats.getCurTime(); 134 mExtractor.release(); 135 long eTime = mStats.getCurTime(); 136 long timeTaken = mStats.getTimeDiff(sTime, eTime); 137 mStats.setDeInitTime(timeTaken); 138 } 139 140 /** 141 * Performs extract operation 142 * 143 * @param currentTrack Track index to be extracted 144 * @return Status as 0 if extraction is successful, -1 otherwise 145 */ extractSample(int currentTrack)146 public int extractSample(int currentTrack) { 147 int status; 148 status = selectExtractorTrack(currentTrack); 149 if (status == -1) { 150 Log.e(TAG, "Failed to select track"); 151 return -1; 152 } 153 mStats.setStartTime(); 154 while (true) { 155 int readSampleSize = getFrameSample(); 156 if (readSampleSize <= 0) { 157 break; 158 } 159 mStats.addOutputTime(); 160 mStats.addFrameSize(readSampleSize); 161 } 162 unselectExtractorTrack(currentTrack); 163 return 0; 164 } 165 166 /** 167 * Write the benchmark logs for the given input file 168 * 169 * @param inputReference Name of the input file 170 * @param mimeType Mime type of the muxed file 171 * @param statsFile The output file where the stats data is written 172 */ dumpStatistics(String inputReference, String mimeType, String statsFile)173 public void dumpStatistics(String inputReference, String mimeType, String statsFile) 174 throws IOException { 175 String operation = "extract"; 176 mStats.dumpStatistics(inputReference, operation, mimeType, "", mDurationUs, statsFile); 177 } 178 } 179