MediaExtractor.java revision a45746efadd11bb7dfab026fb3c81a25fae74ca4
1/* 2 * Copyright (C) 2012 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 17package android.media; 18 19import android.content.ContentResolver; 20import android.content.Context; 21import android.content.res.AssetFileDescriptor; 22import android.media.MediaCodec; 23import android.media.MediaFormat; 24import android.net.Uri; 25import java.io.FileDescriptor; 26import java.io.IOException; 27import java.nio.ByteBuffer; 28import java.util.Map; 29 30/** 31 * MediaExtractor facilitates extraction of demuxed, typically encoded, media data 32 * from a data source. 33 * <p>It is generally used like this: 34 * <pre> 35 * MediaExtractor extractor = new MediaExtractor(); 36 * extractor.setDataSource(...); 37 * int numTracks = extractor.getTrackCount(); 38 * for (int i = 0; i < numTracks; ++i) { 39 * MediaFormat format = extractor.getTrackFormat(i); 40 * String mime = format.getString(MediaFormat.KEY_MIME); 41 * if (weAreInterestedInThisTrack) { 42 * extractor.selectTrack(i); 43 * } 44 * } 45 * ByteBuffer inputBuffer = ByteBuffer.allocate(...) 46 * while (extractor.readSampleData(inputBuffer, ...) >= 0) { 47 * int trackIndex = extractor.getTrackIndex(); 48 * long presentationTimeUs = extractor.getSampleTime(); 49 * ... 50 * extractor.advance(); 51 * } 52 * 53 * extractor.release(); 54 * extractor = null; 55 * </pre> 56 */ 57final public class MediaExtractor { 58 public MediaExtractor() { 59 native_setup(); 60 } 61 62 /** 63 * Sets the data source as a content Uri. 64 * 65 * @param context the Context to use when resolving the Uri 66 * @param uri the Content URI of the data you want to extract from. 67 * @param headers the headers to be sent together with the request for the data 68 */ 69 public final void setDataSource( 70 Context context, Uri uri, Map<String, String> headers) 71 throws IOException { 72 String scheme = uri.getScheme(); 73 if(scheme == null || scheme.equals("file")) { 74 setDataSource(uri.getPath()); 75 return; 76 } 77 78 AssetFileDescriptor fd = null; 79 try { 80 ContentResolver resolver = context.getContentResolver(); 81 fd = resolver.openAssetFileDescriptor(uri, "r"); 82 if (fd == null) { 83 return; 84 } 85 // Note: using getDeclaredLength so that our behavior is the same 86 // as previous versions when the content provider is returning 87 // a full file. 88 if (fd.getDeclaredLength() < 0) { 89 setDataSource(fd.getFileDescriptor()); 90 } else { 91 setDataSource( 92 fd.getFileDescriptor(), 93 fd.getStartOffset(), 94 fd.getDeclaredLength()); 95 } 96 return; 97 } catch (SecurityException ex) { 98 } catch (IOException ex) { 99 } finally { 100 if (fd != null) { 101 fd.close(); 102 } 103 } 104 105 setDataSource(uri.toString(), headers); 106 } 107 108 /** 109 * Sets the data source (file-path or http URL) to use. 110 * 111 * @param path the path of the file, or the http URL 112 * @param headers the headers associated with the http request for the stream you want to play 113 */ 114 public final void setDataSource(String path, Map<String, String> headers) { 115 String[] keys = null; 116 String[] values = null; 117 118 if (headers != null) { 119 keys = new String[headers.size()]; 120 values = new String[headers.size()]; 121 122 int i = 0; 123 for (Map.Entry<String, String> entry: headers.entrySet()) { 124 keys[i] = entry.getKey(); 125 values[i] = entry.getValue(); 126 ++i; 127 } 128 } 129 setDataSource(path, keys, values); 130 } 131 132 private native final void setDataSource( 133 String path, String[] keys, String[] values); 134 135 /** 136 * Sets the data source (file-path or http URL) to use. 137 * 138 * @param path the path of the file, or the http URL of the stream 139 * 140 * <p>When <code>path</code> refers to a local file, the file may actually be opened by a 141 * process other than the calling application. This implies that the pathname 142 * should be an absolute path (as any other process runs with unspecified current working 143 * directory), and that the pathname should reference a world-readable file. 144 * As an alternative, the application could first open the file for reading, 145 * and then use the file descriptor form {@link #setDataSource(FileDescriptor)}. 146 */ 147 public final void setDataSource(String path) { 148 setDataSource(path, null, null); 149 } 150 151 /** 152 * Sets the data source (FileDescriptor) to use. It is the caller's responsibility 153 * to close the file descriptor. It is safe to do so as soon as this call returns. 154 * 155 * @param fd the FileDescriptor for the file you want to extract from. 156 */ 157 public final void setDataSource(FileDescriptor fd) { 158 setDataSource(fd, 0, 0x7ffffffffffffffL); 159 } 160 161 /** 162 * Sets the data source (FileDescriptor) to use. The FileDescriptor must be 163 * seekable (N.B. a LocalSocket is not seekable). It is the caller's responsibility 164 * to close the file descriptor. It is safe to do so as soon as this call returns. 165 * 166 * @param fd the FileDescriptor for the file you want to extract from. 167 * @param offset the offset into the file where the data to be extracted starts, in bytes 168 * @param length the length in bytes of the data to be extracted 169 */ 170 public native final void setDataSource( 171 FileDescriptor fd, long offset, long length); 172 173 @Override 174 protected void finalize() { 175 native_finalize(); 176 } 177 178 /** 179 * Make sure you call this when you're done to free up any resources 180 * instead of relying on the garbage collector to do this for you at 181 * some point in the future. 182 */ 183 public native final void release(); 184 185 /** 186 * Count the number of tracks found in the data source. 187 */ 188 public native final int getTrackCount(); 189 190 /** 191 * Get the track format at the specified index. 192 * More detail on the representation can be found at {@link android.media.MediaCodec} 193 */ 194 public MediaFormat getTrackFormat(int index) { 195 return new MediaFormat(getTrackFormatNative(index)); 196 } 197 198 private native Map<String, Object> getTrackFormatNative(int index); 199 200 /** 201 * Subsequent calls to {@link #readSampleData}, {@link #getSampleTrackIndex} and 202 * {@link #getSampleTime} only retrieve information for the subset of tracks 203 * selected. 204 * Selecting the same track multiple times has no effect, the track is 205 * only selected once. 206 */ 207 public native void selectTrack(int index); 208 209 /** 210 * Subsequent calls to {@link #readSampleData}, {@link #getSampleTrackIndex} and 211 * {@link #getSampleTime} only retrieve information for the subset of tracks 212 * selected. 213 */ 214 public native void unselectTrack(int index); 215 216 /** 217 * If possible, seek to a sync sample at or before the specified time 218 */ 219 public static final int SEEK_TO_PREVIOUS_SYNC = 0; 220 /** 221 * If possible, seek to a sync sample at or after the specified time 222 */ 223 public static final int SEEK_TO_NEXT_SYNC = 1; 224 /** 225 * If possible, seek to the sync sample closest to the specified time 226 */ 227 public static final int SEEK_TO_CLOSEST_SYNC = 2; 228 229 /** 230 * All selected tracks seek near the requested time according to the 231 * specified mode. 232 */ 233 public native void seekTo(long timeUs, int mode); 234 235 /** 236 * Advance to the next sample. Returns false if no more sample data 237 * is available (end of stream). 238 */ 239 public native boolean advance(); 240 241 /** 242 * Retrieve the current encoded sample and store it in the byte buffer 243 * starting at the given offset. Returns the sample size (or -1 if 244 * no more samples are available). 245 */ 246 public native int readSampleData(ByteBuffer byteBuf, int offset); 247 248 /** 249 * Returns the track index the current sample originates from (or -1 250 * if no more samples are available) 251 */ 252 public native int getSampleTrackIndex(); 253 254 /** 255 * Returns the current sample's presentation time in microseconds. 256 * or -1 if no more samples are available. 257 */ 258 public native long getSampleTime(); 259 260 // Keep these in sync with their equivalents in NuMediaExtractor.h 261 /** 262 * The sample is a sync sample 263 */ 264 public static final int SAMPLE_FLAG_SYNC = 1; 265 266 /** 267 * The sample is (at least partially) encrypted, see also the documentation 268 * for {@link android.media.MediaCodec#queueSecureInputBuffer} 269 */ 270 public static final int SAMPLE_FLAG_ENCRYPTED = 2; 271 272 /** 273 * Returns the current sample's flags. 274 */ 275 public native int getSampleFlags(); 276 277 /** 278 * If the sample flags indicate that the current sample is at least 279 * partially encrypted, this call returns relevant information about 280 * the structure of the sample data required for decryption. 281 * @param info The android.media.MediaCodec.CryptoInfo structure 282 * to be filled in. 283 * @return true iff the sample flags contain {@link #SAMPLE_FLAG_ENCRYPTED} 284 */ 285 public native boolean getSampleCryptoInfo(MediaCodec.CryptoInfo info); 286 287 /** 288 * Returns an estimate of how much data is presently cached in memory 289 * expressed in microseconds. Returns -1 if that information is unavailable 290 * or not applicable (no cache). 291 */ 292 public native long getCachedDuration(); 293 294 /** 295 * Returns true iff we are caching data and the cache has reached the 296 * end of the data stream (for now, a future seek may of course restart 297 * the fetching of data). 298 * This API only returns a meaningful result if {@link #getCachedDuration} 299 * indicates the presence of a cache, i.e. does NOT return -1. 300 */ 301 public native boolean hasCacheReachedEndOfStream(); 302 303 private static native final void native_init(); 304 private native final void native_setup(); 305 private native final void native_finalize(); 306 307 static { 308 System.loadLibrary("media_jni"); 309 native_init(); 310 } 311 312 private int mNativeContext; 313} 314