MediaExtractor.java revision 07ea426e3ae8915ca6bf67135f523f42cd920af0
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.net.Uri; 23import java.io.FileDescriptor; 24import java.io.IOException; 25import java.nio.ByteBuffer; 26import java.util.Map; 27 28/** 29 * MediaExtractor facilitates extraction of demuxed, typically encoded, media data 30 * from a data source. 31 * <p>It is generally used like this: 32 * <pre> 33 * MediaExtractor extractor = new MediaExtractor(); 34 * extractor.setDataSource(...); 35 * int numTracks = extractor.countTracks(); 36 * for (int i = 0; i < numTracks; ++i) { 37 * Map%lt;String, Object> format = extractor.getTrackFormat(i); 38 * String mime = (String)format.get("mime"); 39 * if (weAreInterestedInThisTrack) { 40 * extractor.selectTrack(i); 41 * } 42 * } 43 * ByteBuffer inputBuffer = ByteBuffer.allocate(...) 44 * while (extractor.readSampleData(inputBuffer, ...) >= 0) { 45 * int trackIndex = extractor.getTrackIndex(); 46 * long presentationTimeUs = extractor.getSampleTime(); 47 * ... 48 * extractor.advance(); 49 * } 50 * 51 * extractor.release(); 52 * extractor = null; 53 * </pre> 54*/ 55final public class MediaExtractor { 56 public MediaExtractor() { 57 native_setup(); 58 } 59 60 /** 61 * Sets the data source as a content Uri. 62 * 63 * @param context the Context to use when resolving the Uri 64 * @param uri the Content URI of the data you want to extract from. 65 * @param headers the headers to be sent together with the request for the data 66 */ 67 public final void setDataSource( 68 Context context, Uri uri, Map<String, String> headers) 69 throws IOException { 70 String scheme = uri.getScheme(); 71 if(scheme == null || scheme.equals("file")) { 72 setDataSource(uri.getPath()); 73 return; 74 } 75 76 AssetFileDescriptor fd = null; 77 try { 78 ContentResolver resolver = context.getContentResolver(); 79 fd = resolver.openAssetFileDescriptor(uri, "r"); 80 if (fd == null) { 81 return; 82 } 83 // Note: using getDeclaredLength so that our behavior is the same 84 // as previous versions when the content provider is returning 85 // a full file. 86 if (fd.getDeclaredLength() < 0) { 87 setDataSource(fd.getFileDescriptor()); 88 } else { 89 setDataSource( 90 fd.getFileDescriptor(), 91 fd.getStartOffset(), 92 fd.getDeclaredLength()); 93 } 94 return; 95 } catch (SecurityException ex) { 96 } catch (IOException ex) { 97 } finally { 98 if (fd != null) { 99 fd.close(); 100 } 101 } 102 103 setDataSource(uri.toString(), headers); 104 } 105 106 /** 107 * Sets the data source (file-path or http URL) to use. 108 * 109 * @param path the path of the file, or the http URL 110 * @param headers the headers associated with the http request for the stream you want to play 111 */ 112 public final void setDataSource(String path, Map<String, String> headers) { 113 String[] keys = null; 114 String[] values = null; 115 116 if (headers != null) { 117 keys = new String[headers.size()]; 118 values = new String[headers.size()]; 119 120 int i = 0; 121 for (Map.Entry<String, String> entry: headers.entrySet()) { 122 keys[i] = entry.getKey(); 123 values[i] = entry.getValue(); 124 ++i; 125 } 126 } 127 setDataSource(path, keys, values); 128 } 129 130 private native final void setDataSource( 131 String path, String[] keys, String[] values); 132 133 /** 134 * Sets the data source (file-path or http URL) to use. 135 * 136 * @param path the path of the file, or the http URL of the stream 137 * 138 * <p>When <code>path</code> refers to a local file, the file may actually be opened by a 139 * process other than the calling application. This implies that the pathname 140 * should be an absolute path (as any other process runs with unspecified current working 141 * directory), and that the pathname should reference a world-readable file. 142 * As an alternative, the application could first open the file for reading, 143 * and then use the file descriptor form {@link #setDataSource(FileDescriptor)}. 144 */ 145 public final void setDataSource(String path) { 146 setDataSource(path, null, null); 147 } 148 149 /** 150 * Sets the data source (FileDescriptor) to use. It is the caller's responsibility 151 * to close the file descriptor. It is safe to do so as soon as this call returns. 152 * 153 * @param fd the FileDescriptor for the file you want to extract from. 154 */ 155 public final void setDataSource(FileDescriptor fd) { 156 setDataSource(fd, 0, 0x7ffffffffffffffL); 157 } 158 159 /** 160 * Sets the data source (FileDescriptor) to use. The FileDescriptor must be 161 * seekable (N.B. a LocalSocket is not seekable). It is the caller's responsibility 162 * to close the file descriptor. It is safe to do so as soon as this call returns. 163 * 164 * @param fd the FileDescriptor for the file you want to extract from. 165 * @param offset the offset into the file where the data to be extracted starts, in bytes 166 * @param length the length in bytes of the data to be extracted 167 */ 168 public native final void setDataSource( 169 FileDescriptor fd, long offset, long length); 170 171 @Override 172 protected void finalize() { 173 native_finalize(); 174 } 175 176 /** Make sure you call this when you're done to free up any resources 177 * instead of relying on the garbage collector to do this for you at 178 * some point in the future. 179 */ 180 public native final void release(); 181 182 /** Count the number of tracks found in the data source. 183 */ 184 public native int countTracks(); 185 186 /** Get the track format at the specified index. 187 * More detail on the representation can be found at {@link android.media.MediaCodec} 188 */ 189 public native Map<String, Object> getTrackFormat(int index); 190 191 /** Subsequent calls to {@link #readSampleData}, {@link #getSampleTrackIndex} and 192 * {@link #getSampleTime} only retrieve information for the subset of tracks 193 * selected by the call below. 194 * Selecting the same track multiple times has no effect, the track 195 * only selected once. 196 * Media data will be returned in the order of their timestamps. 197 */ 198 public native void selectTrack(int index); 199 200 /** All selected tracks seek near the requested time. The next sample 201 * returned for each selected track will be a sync sample. 202 */ 203 public native void seekTo(long timeUs); 204 205 /** Advance to the next sample. Returns false if no more sample data 206 * is available (end of stream). 207 */ 208 public native boolean advance(); 209 210 /** Retrieve the current encoded sample and store it in the byte buffer 211 * starting at the given offset. Returns the sample size (or -1 if 212 * no more samples are available). 213 */ 214 public native int readSampleData(ByteBuffer byteBuf, int offset); 215 216 /** Returns the track index the current sample originates from (or -1 217 * if no more samples are available) 218 */ 219 public native int getSampleTrackIndex(); 220 221 /** Returns the current sample's presentation time in microseconds. 222 * or -1 if no more samples are available. 223 */ 224 public native long getSampleTime(); 225 226 // Keep these in sync with their equivalents in NuMediaExtractor.h 227 /** The sample is a sync sample */ 228 public static final int SAMPLE_FLAG_SYNC = 1; 229 230 /** The sample is (at least partially) encrypted, see also the documentation 231 * for {@link android.media.MediaCodec#queueSecureInputBuffer} 232 */ 233 public static final int SAMPLE_FLAG_ENCRYPTED = 2; 234 235 /** Returns the current sample's flags. */ 236 public native int getSampleFlags(); 237 238 private static native final void native_init(); 239 private native final void native_setup(); 240 private native final void native_finalize(); 241 242 static { 243 System.loadLibrary("media_jni"); 244 native_init(); 245 } 246 247 private int mNativeContext; 248} 249