188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber/* 288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * Copyright (C) 2012 The Android Open Source Project 388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * 488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * you may not use this file except in compliance with the License. 688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * You may obtain a copy of the License at 788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * 888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * 1088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * Unless required by applicable law or agreed to in writing, software 1188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 1288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * See the License for the specific language governing permissions and 1488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * limitations under the License. 1588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber */ 1688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 1788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberpackage android.media; 1888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 1999f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnarimport android.annotation.IntDef; 2099f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnarimport android.annotation.NonNull; 2199f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnarimport android.annotation.Nullable; 2207ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huberimport android.content.ContentResolver; 2307ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huberimport android.content.Context; 2407ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huberimport android.content.res.AssetFileDescriptor; 2591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huberimport android.media.MediaCodec; 2660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huberimport android.media.MediaFormat; 27d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huberimport android.media.MediaHTTPService; 2807ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huberimport android.net.Uri; 29d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huberimport android.os.IBinder; 30c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen 31a3c1c2297d97c2c442290848e97f1f53162d4b68Jeff Sharkeyimport com.android.internal.util.Preconditions; 32a3c1c2297d97c2c442290848e97f1f53162d4b68Jeff Sharkey 3307ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huberimport java.io.FileDescriptor; 3407ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huberimport java.io.IOException; 3599f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnarimport java.lang.annotation.Retention; 3699f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnarimport java.lang.annotation.RetentionPolicy; 3788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberimport java.nio.ByteBuffer; 38e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissenimport java.nio.ByteOrder; 3921b0008db6443cc4c7188254491c8dce2da8758aRobert Shihimport java.util.Collections; 40e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissenimport java.util.HashMap; 4121b0008db6443cc4c7188254491c8dce2da8758aRobert Shihimport java.util.List; 4288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberimport java.util.Map; 43e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissenimport java.util.UUID; 4488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 4588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber/** 4607ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * MediaExtractor facilitates extraction of demuxed, typically encoded, media data 4707ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * from a data source. 4807ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * <p>It is generally used like this: 4907ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * <pre> 5007ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * MediaExtractor extractor = new MediaExtractor(); 5107ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * extractor.setDataSource(...); 5260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * int numTracks = extractor.getTrackCount(); 5307ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * for (int i = 0; i < numTracks; ++i) { 542ac3f2e285159300c62c797bb2123604773ccac7Andreas Huber * MediaFormat format = extractor.getTrackFormat(i); 552ac3f2e285159300c62c797bb2123604773ccac7Andreas Huber * String mime = format.getString(MediaFormat.KEY_MIME); 5607ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * if (weAreInterestedInThisTrack) { 5707ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * extractor.selectTrack(i); 5807ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * } 5907ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * } 6007ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * ByteBuffer inputBuffer = ByteBuffer.allocate(...) 6107ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * while (extractor.readSampleData(inputBuffer, ...) >= 0) { 62a242deb1de365f0ed0032a87565df1971cb6bbe2Teng-Hui Zhu * int trackIndex = extractor.getSampleTrackIndex(); 6307ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * long presentationTimeUs = extractor.getSampleTime(); 6407ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * ... 6507ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * extractor.advance(); 6607ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * } 6707ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * 6807ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * extractor.release(); 6907ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * extractor = null; 7007ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * </pre> 7160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber */ 728240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huberfinal public class MediaExtractor { 7307ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber public MediaExtractor() { 7407ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber native_setup(); 7507ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber } 7607ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber 7707ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber /** 784eaa2938084353a54dc259466172909329a048ccChris Watkins * Sets the data source (MediaDataSource) to use. 794eaa2938084353a54dc259466172909329a048ccChris Watkins * 804eaa2938084353a54dc259466172909329a048ccChris Watkins * @param dataSource the MediaDataSource for the media you want to extract from 8199f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar * 8299f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar * @throws IllegalArgumentException if dataSource is invalid. 83c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen */ 8499f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar public native final void setDataSource(@NonNull MediaDataSource dataSource) 8599f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar throws IOException; 86c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen 87c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen /** 8807ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * Sets the data source as a content Uri. 8907ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * 9007ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * @param context the Context to use when resolving the Uri 9107ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * @param uri the Content URI of the data you want to extract from. 9299f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar * @param headers the headers to be sent together with the request for the data. 9399f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar * This can be {@code null} if no specific headers are to be sent with the 9499f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar * request. 9507ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber */ 9607ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber public final void setDataSource( 9799f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar @NonNull Context context, @NonNull Uri uri, @Nullable Map<String, String> headers) 9807ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber throws IOException { 9907ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber String scheme = uri.getScheme(); 10099f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar if (scheme == null || scheme.equals("file")) { 10107ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber setDataSource(uri.getPath()); 10207ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber return; 10307ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber } 10407ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber 10507ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber AssetFileDescriptor fd = null; 10607ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber try { 10707ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber ContentResolver resolver = context.getContentResolver(); 10807ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber fd = resolver.openAssetFileDescriptor(uri, "r"); 10907ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber if (fd == null) { 11007ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber return; 11107ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber } 11207ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber // Note: using getDeclaredLength so that our behavior is the same 11307ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber // as previous versions when the content provider is returning 11407ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber // a full file. 11507ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber if (fd.getDeclaredLength() < 0) { 11607ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber setDataSource(fd.getFileDescriptor()); 11707ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber } else { 11807ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber setDataSource( 11907ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber fd.getFileDescriptor(), 12007ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber fd.getStartOffset(), 12107ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber fd.getDeclaredLength()); 12207ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber } 12307ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber return; 12407ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber } catch (SecurityException ex) { 12507ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber } catch (IOException ex) { 12607ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber } finally { 12707ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber if (fd != null) { 12807ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber fd.close(); 12907ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber } 13007ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber } 13107ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber 13207ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber setDataSource(uri.toString(), headers); 13307ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber } 13407ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber 13507ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber /** 13607ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * Sets the data source (file-path or http URL) to use. 13707ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * 13807ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * @param path the path of the file, or the http URL 13999f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar * @param headers the headers associated with the http request for the stream you want to play. 14099f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar * This can be {@code null} if no specific headers are to be sent with the 14199f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar * request. 14207ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber */ 14399f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar public final void setDataSource(@NonNull String path, @Nullable Map<String, String> headers) 144a57da0dc5a5b863cdb12287699ba58f34529bd62Andreas Huber throws IOException { 14507ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber String[] keys = null; 14607ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber String[] values = null; 14707ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber 14807ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber if (headers != null) { 14907ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber keys = new String[headers.size()]; 15007ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber values = new String[headers.size()]; 15107ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber 15207ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber int i = 0; 15307ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber for (Map.Entry<String, String> entry: headers.entrySet()) { 15407ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber keys[i] = entry.getKey(); 15507ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber values[i] = entry.getValue(); 15607ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber ++i; 15707ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber } 15807ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber } 159d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber 160d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber nativeSetDataSource( 161d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber MediaHTTPService.createHttpServiceBinderIfNecessary(path), 162d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber path, 163d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber keys, 164d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber values); 16507ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber } 16607ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber 167d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber private native final void nativeSetDataSource( 16899f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar @NonNull IBinder httpServiceBinder, 16999f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar @NonNull String path, 17099f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar @Nullable String[] keys, 17199f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar @Nullable String[] values) throws IOException; 17207ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber 17307ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber /** 17407ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * Sets the data source (file-path or http URL) to use. 17507ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * 17607ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * @param path the path of the file, or the http URL of the stream 17707ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * 17807ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * <p>When <code>path</code> refers to a local file, the file may actually be opened by a 17907ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * process other than the calling application. This implies that the pathname 18007ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * should be an absolute path (as any other process runs with unspecified current working 18107ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * directory), and that the pathname should reference a world-readable file. 18207ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * As an alternative, the application could first open the file for reading, 18307ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * and then use the file descriptor form {@link #setDataSource(FileDescriptor)}. 18407ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber */ 18599f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar public final void setDataSource(@NonNull String path) throws IOException { 186d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber nativeSetDataSource( 187d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber MediaHTTPService.createHttpServiceBinderIfNecessary(path), 188d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber path, 189d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber null, 190d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber null); 19107ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber } 19207ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber 19307ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber /** 194a3c1c2297d97c2c442290848e97f1f53162d4b68Jeff Sharkey * Sets the data source (AssetFileDescriptor) to use. It is the caller's 195a3c1c2297d97c2c442290848e97f1f53162d4b68Jeff Sharkey * responsibility to close the file descriptor. It is safe to do so as soon 196a3c1c2297d97c2c442290848e97f1f53162d4b68Jeff Sharkey * as this call returns. 197a3c1c2297d97c2c442290848e97f1f53162d4b68Jeff Sharkey * 198a3c1c2297d97c2c442290848e97f1f53162d4b68Jeff Sharkey * @param afd the AssetFileDescriptor for the file you want to extract from. 199a3c1c2297d97c2c442290848e97f1f53162d4b68Jeff Sharkey */ 200a3c1c2297d97c2c442290848e97f1f53162d4b68Jeff Sharkey public final void setDataSource(@NonNull AssetFileDescriptor afd) 201a3c1c2297d97c2c442290848e97f1f53162d4b68Jeff Sharkey throws IOException, IllegalArgumentException, IllegalStateException { 202a3c1c2297d97c2c442290848e97f1f53162d4b68Jeff Sharkey Preconditions.checkNotNull(afd); 203a3c1c2297d97c2c442290848e97f1f53162d4b68Jeff Sharkey // Note: using getDeclaredLength so that our behavior is the same 204a3c1c2297d97c2c442290848e97f1f53162d4b68Jeff Sharkey // as previous versions when the content provider is returning 205a3c1c2297d97c2c442290848e97f1f53162d4b68Jeff Sharkey // a full file. 206a3c1c2297d97c2c442290848e97f1f53162d4b68Jeff Sharkey if (afd.getDeclaredLength() < 0) { 207a3c1c2297d97c2c442290848e97f1f53162d4b68Jeff Sharkey setDataSource(afd.getFileDescriptor()); 208a3c1c2297d97c2c442290848e97f1f53162d4b68Jeff Sharkey } else { 209a3c1c2297d97c2c442290848e97f1f53162d4b68Jeff Sharkey setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getDeclaredLength()); 210a3c1c2297d97c2c442290848e97f1f53162d4b68Jeff Sharkey } 211a3c1c2297d97c2c442290848e97f1f53162d4b68Jeff Sharkey } 212a3c1c2297d97c2c442290848e97f1f53162d4b68Jeff Sharkey 213a3c1c2297d97c2c442290848e97f1f53162d4b68Jeff Sharkey /** 21407ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * Sets the data source (FileDescriptor) to use. It is the caller's responsibility 21507ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * to close the file descriptor. It is safe to do so as soon as this call returns. 21607ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * 21707ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * @param fd the FileDescriptor for the file you want to extract from. 21807ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber */ 21999f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar public final void setDataSource(@NonNull FileDescriptor fd) throws IOException { 22007ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber setDataSource(fd, 0, 0x7ffffffffffffffL); 22188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber } 22288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 22307ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber /** 22407ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * Sets the data source (FileDescriptor) to use. The FileDescriptor must be 22507ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * seekable (N.B. a LocalSocket is not seekable). It is the caller's responsibility 22607ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * to close the file descriptor. It is safe to do so as soon as this call returns. 22707ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * 22807ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * @param fd the FileDescriptor for the file you want to extract from. 22907ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * @param offset the offset into the file where the data to be extracted starts, in bytes 23007ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber * @param length the length in bytes of the data to be extracted 23107ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber */ 23207ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber public native final void setDataSource( 23399f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar @NonNull FileDescriptor fd, long offset, long length) throws IOException; 23407ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber 23588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber @Override 23688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber protected void finalize() { 23788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber native_finalize(); 23888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber } 23988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 24060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber /** 24160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * Make sure you call this when you're done to free up any resources 24260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * instead of relying on the garbage collector to do this for you at 24360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * some point in the future. 24460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber */ 24588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber public native final void release(); 24688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 24760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber /** 24860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * Count the number of tracks found in the data source. 24960d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber */ 25060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber public native final int getTrackCount(); 25160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber 25260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber /** 25321b0008db6443cc4c7188254491c8dce2da8758aRobert Shih * Extract DRM initialization data if it exists 25421b0008db6443cc4c7188254491c8dce2da8758aRobert Shih * 25521b0008db6443cc4c7188254491c8dce2da8758aRobert Shih * @return DRM initialization data in the content, or {@code null} 25621b0008db6443cc4c7188254491c8dce2da8758aRobert Shih * if no recognizable DRM format is found; 25721b0008db6443cc4c7188254491c8dce2da8758aRobert Shih * @see DrmInitData 25821b0008db6443cc4c7188254491c8dce2da8758aRobert Shih */ 25921b0008db6443cc4c7188254491c8dce2da8758aRobert Shih public DrmInitData getDrmInitData() { 26021b0008db6443cc4c7188254491c8dce2da8758aRobert Shih Map<String, Object> formatMap = getFileFormatNative(); 26121b0008db6443cc4c7188254491c8dce2da8758aRobert Shih if (formatMap == null) { 26221b0008db6443cc4c7188254491c8dce2da8758aRobert Shih return null; 26321b0008db6443cc4c7188254491c8dce2da8758aRobert Shih } 26421b0008db6443cc4c7188254491c8dce2da8758aRobert Shih if (formatMap.containsKey("pssh")) { 26521b0008db6443cc4c7188254491c8dce2da8758aRobert Shih Map<UUID, byte[]> psshMap = getPsshInfo(); 26621b0008db6443cc4c7188254491c8dce2da8758aRobert Shih final Map<UUID, DrmInitData.SchemeInitData> initDataMap = 26721b0008db6443cc4c7188254491c8dce2da8758aRobert Shih new HashMap<UUID, DrmInitData.SchemeInitData>(); 26821b0008db6443cc4c7188254491c8dce2da8758aRobert Shih for (Map.Entry<UUID, byte[]> e: psshMap.entrySet()) { 26921b0008db6443cc4c7188254491c8dce2da8758aRobert Shih UUID uuid = e.getKey(); 27021b0008db6443cc4c7188254491c8dce2da8758aRobert Shih byte[] data = e.getValue(); 27121b0008db6443cc4c7188254491c8dce2da8758aRobert Shih initDataMap.put(uuid, new DrmInitData.SchemeInitData("cenc", data)); 27221b0008db6443cc4c7188254491c8dce2da8758aRobert Shih } 27321b0008db6443cc4c7188254491c8dce2da8758aRobert Shih return new DrmInitData() { 27421b0008db6443cc4c7188254491c8dce2da8758aRobert Shih public SchemeInitData get(UUID schemeUuid) { 27521b0008db6443cc4c7188254491c8dce2da8758aRobert Shih return initDataMap.get(schemeUuid); 27621b0008db6443cc4c7188254491c8dce2da8758aRobert Shih } 27721b0008db6443cc4c7188254491c8dce2da8758aRobert Shih }; 278c67abec674ca4817c12d46653b7a87d8e9c5e512Robert Shih } else { 279c67abec674ca4817c12d46653b7a87d8e9c5e512Robert Shih int numTracks = getTrackCount(); 280c67abec674ca4817c12d46653b7a87d8e9c5e512Robert Shih for (int i = 0; i < numTracks; ++i) { 281c67abec674ca4817c12d46653b7a87d8e9c5e512Robert Shih Map<String, Object> trackFormatMap = getTrackFormatNative(i); 282c67abec674ca4817c12d46653b7a87d8e9c5e512Robert Shih if (!trackFormatMap.containsKey("crypto-key")) { 283c67abec674ca4817c12d46653b7a87d8e9c5e512Robert Shih continue; 28421b0008db6443cc4c7188254491c8dce2da8758aRobert Shih } 285c67abec674ca4817c12d46653b7a87d8e9c5e512Robert Shih ByteBuffer buf = (ByteBuffer) trackFormatMap.get("crypto-key"); 286c67abec674ca4817c12d46653b7a87d8e9c5e512Robert Shih buf.rewind(); 287c67abec674ca4817c12d46653b7a87d8e9c5e512Robert Shih final byte[] data = new byte[buf.remaining()]; 288c67abec674ca4817c12d46653b7a87d8e9c5e512Robert Shih buf.get(data); 289c67abec674ca4817c12d46653b7a87d8e9c5e512Robert Shih return new DrmInitData() { 290c67abec674ca4817c12d46653b7a87d8e9c5e512Robert Shih public SchemeInitData get(UUID schemeUuid) { 291c67abec674ca4817c12d46653b7a87d8e9c5e512Robert Shih return new DrmInitData.SchemeInitData("webm", data); 292c67abec674ca4817c12d46653b7a87d8e9c5e512Robert Shih } 293c67abec674ca4817c12d46653b7a87d8e9c5e512Robert Shih }; 294c67abec674ca4817c12d46653b7a87d8e9c5e512Robert Shih } 29521b0008db6443cc4c7188254491c8dce2da8758aRobert Shih } 29621b0008db6443cc4c7188254491c8dce2da8758aRobert Shih return null; 29721b0008db6443cc4c7188254491c8dce2da8758aRobert Shih } 29821b0008db6443cc4c7188254491c8dce2da8758aRobert Shih 29921b0008db6443cc4c7188254491c8dce2da8758aRobert Shih /** 300ecba2e4b953e9480b5084c04ec0cb5a8ba574b03Marco Nelissen * Get the PSSH info if present. 301ecba2e4b953e9480b5084c04ec0cb5a8ba574b03Marco Nelissen * @return a map of uuid-to-bytes, with the uuid specifying 302e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen * the crypto scheme, and the bytes being the data specific to that scheme. 30399f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar * This can be {@code null} if the source does not contain PSSH info. 304e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen */ 30599f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar @Nullable 306e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen public Map<UUID, byte[]> getPsshInfo() { 307e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen Map<UUID, byte[]> psshMap = null; 308e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen Map<String, Object> formatMap = getFileFormatNative(); 309e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen if (formatMap != null && formatMap.containsKey("pssh")) { 310e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen ByteBuffer rawpssh = (ByteBuffer) formatMap.get("pssh"); 311e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen rawpssh.order(ByteOrder.nativeOrder()); 312e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen rawpssh.rewind(); 313e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen formatMap.remove("pssh"); 314e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen // parse the flat pssh bytebuffer into something more manageable 315e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen psshMap = new HashMap<UUID, byte[]>(); 316e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen while (rawpssh.remaining() > 0) { 317e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen rawpssh.order(ByteOrder.BIG_ENDIAN); 318e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen long msb = rawpssh.getLong(); 319e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen long lsb = rawpssh.getLong(); 320e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen UUID uuid = new UUID(msb, lsb); 321e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen rawpssh.order(ByteOrder.nativeOrder()); 322e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen int datalen = rawpssh.getInt(); 323e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen byte [] psshdata = new byte[datalen]; 324e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen rawpssh.get(psshdata); 325e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen psshMap.put(uuid, psshdata); 326e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen } 327e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen } 328e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen return psshMap; 329e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen } 330e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen 33199f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar @NonNull 332e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen private native Map<String, Object> getFileFormatNative(); 333e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen 334e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen /** 33560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * Get the track format at the specified index. 33643a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * 33760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * More detail on the representation can be found at {@link android.media.MediaCodec} 33843a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <p> 33943a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * The following table summarizes support for format keys across android releases: 34043a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * 34143a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <table style="width: 0%"> 34243a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <thead> 34343a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <tr> 34443a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <th rowspan=2>OS Version(s)</th> 34543a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <td colspan=3>{@code MediaFormat} keys used for</th> 34643a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * </tr><tr> 34743a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <th>All Tracks</th> 34843a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <th>Audio Tracks</th> 34943a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <th>Video Tracks</th> 35043a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * </tr> 35143a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * </thead> 35243a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <tbody> 35343a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <tr> 35443a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <td>{@link android.os.Build.VERSION_CODES#JELLY_BEAN}</td> 35543a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <td rowspan=8>{@link MediaFormat#KEY_MIME},<br> 35643a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * {@link MediaFormat#KEY_DURATION},<br> 35743a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * {@link MediaFormat#KEY_MAX_INPUT_SIZE}</td> 35843a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <td rowspan=5>{@link MediaFormat#KEY_SAMPLE_RATE},<br> 35943a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * {@link MediaFormat#KEY_CHANNEL_COUNT},<br> 36043a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * {@link MediaFormat#KEY_CHANNEL_MASK},<br> 36143a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * gapless playback information<sup>.mp3, .mp4</sup>,<br> 36243a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * {@link MediaFormat#KEY_IS_ADTS}<sup>AAC if streaming</sup>,<br> 36343a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * codec-specific data<sup>AAC, Vorbis</sup></td> 36443a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <td rowspan=2>{@link MediaFormat#KEY_WIDTH},<br> 36543a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * {@link MediaFormat#KEY_HEIGHT},<br> 36643a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * codec-specific data<sup>AVC, MPEG4</sup></td> 36743a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * </tr><tr> 36843a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <td>{@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}</td> 36943a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * </tr><tr> 37043a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <td>{@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}</td> 37143a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <td rowspan=3>as above, plus<br> 37243a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * Pixel aspect ratio information<sup>AVC, *</sup></td> 37343a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * </tr><tr> 37443a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <td>{@link android.os.Build.VERSION_CODES#KITKAT}</td> 37543a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * </tr><tr> 37643a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <td>{@link android.os.Build.VERSION_CODES#KITKAT_WATCH}</td> 37743a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * </tr><tr> 37843a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <td>{@link android.os.Build.VERSION_CODES#LOLLIPOP}</td> 37943a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <td rowspan=2>as above, plus<br> 38043a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * {@link MediaFormat#KEY_BIT_RATE}<sup>AAC</sup>,<br> 38143a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * codec-specific data<sup>Opus</sup></td> 38243a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <td rowspan=2>as above, plus<br> 38343a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * {@link MediaFormat#KEY_ROTATION}<sup>.mp4</sup>,<br> 38443a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * {@link MediaFormat#KEY_BIT_RATE}<sup>MPEG4</sup>,<br> 38543a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * codec-specific data<sup>HEVC</sup></td> 38643a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * </tr><tr> 38743a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <td>{@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1}</td> 38843a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * </tr><tr> 38943a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <td>{@link android.os.Build.VERSION_CODES#M}</td> 39043a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <td>as above, plus<br> 39143a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * gapless playback information<sup>Opus</sup></td> 39243a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <td>as above, plus<br> 39343a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * {@link MediaFormat#KEY_FRAME_RATE} (integer)</td> 39443a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * </tr><tr> 39543a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <td>{@link android.os.Build.VERSION_CODES#N}</td> 39643a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <td>as above, plus<br> 39743a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * {@link MediaFormat#KEY_TRACK_ID},<br> 39843a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <!-- {link MediaFormat#KEY_MAX_BIT_RATE}<sup>#, .mp4</sup>,<br> --> 39943a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * {@link MediaFormat#KEY_BIT_RATE}<sup>#, .mp4</sup></td> 40043a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <td>as above, plus<br> 40143a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * {@link MediaFormat#KEY_PCM_ENCODING},<br> 40243a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * {@link MediaFormat#KEY_PROFILE}<sup>AAC</sup></td> 40343a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <td>as above, plus<br> 40443a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * {@link MediaFormat#KEY_HDR_STATIC_INFO}<sup>#, .webm</sup>,<br> 40543a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * {@link MediaFormat#KEY_COLOR_STANDARD}<sup>#</sup>,<br> 40643a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * {@link MediaFormat#KEY_COLOR_TRANSFER}<sup>#</sup>,<br> 40743a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * {@link MediaFormat#KEY_COLOR_RANGE}<sup>#</sup>,<br> 40843a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * {@link MediaFormat#KEY_PROFILE}<sup>MPEG2, H.263, MPEG4, AVC, HEVC, VP9</sup>,<br> 40943a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * {@link MediaFormat#KEY_LEVEL}<sup>H.263, MPEG4, AVC, HEVC, VP9</sup>,<br> 41043a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * codec-specific data<sup>VP9</sup></td> 41143a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * </tr> 41243a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <tr> 41343a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <td colspan=4> 41443a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <p class=note><strong>Notes:</strong><br> 41543a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * #: container-specified value only.<br> 41643a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * .mp4, .webm…: for listed containers<br> 41743a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * MPEG4, AAC…: for listed codecs 41843a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * </td> 41943a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * </tr><tr> 42043a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <td colspan=4> 42143a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <p class=note>Note that that level information contained in the container many times 42243a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * does not match the level of the actual bitstream. You may want to clear the level using 42343a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * {@code MediaFormat.setString(KEY_LEVEL, null)} before using the track format to find a 42443a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * decoder that can play back a particular track. 42543a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * </td> 42643a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * </tr><tr> 42743a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <td colspan=4> 42843a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <p class=note><strong>*Pixel (sample) aspect ratio</strong> is returned in the following 42943a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * keys. The display width can be calculated for example as: 43043a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <p align=center> 43143a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * display-width = display-height * crop-width / crop-height * sar-width / sar-height 43243a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * </td> 43343a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * </tr><tr> 43443a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <th>Format Key</th><th>Value Type</th><th colspan=2>Description</th> 43543a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * </tr><tr> 43643a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <td>{@code "sar-width"}</td><td>Integer</td><td colspan=2>Pixel aspect ratio width</td> 43743a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * </tr><tr> 43843a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * <td>{@code "sar-height"}</td><td>Integer</td><td colspan=2>Pixel aspect ratio height</td> 43943a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * </tr> 44043a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * </tbody> 44143a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * </table> 44243a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar * 44360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber */ 44499f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar @NonNull 44560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber public MediaFormat getTrackFormat(int index) { 44660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber return new MediaFormat(getTrackFormatNative(index)); 44760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber } 44860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber 44999f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar @NonNull 45060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber private native Map<String, Object> getTrackFormatNative(int index); 45160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber 45260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber /** 45360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * Subsequent calls to {@link #readSampleData}, {@link #getSampleTrackIndex} and 45460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * {@link #getSampleTime} only retrieve information for the subset of tracks 45560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * selected. 45660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * Selecting the same track multiple times has no effect, the track is 45760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * only selected once. 45807ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber */ 45988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber public native void selectTrack(int index); 46088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 46160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber /** 46260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * Subsequent calls to {@link #readSampleData}, {@link #getSampleTrackIndex} and 46360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * {@link #getSampleTime} only retrieve information for the subset of tracks 46460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * selected. 46560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber */ 466f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber public native void unselectTrack(int index); 467f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber 46860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber /** 46960d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * If possible, seek to a sync sample at or before the specified time 47060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber */ 471f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber public static final int SEEK_TO_PREVIOUS_SYNC = 0; 47260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber /** 47360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * If possible, seek to a sync sample at or after the specified time 47460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber */ 475f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber public static final int SEEK_TO_NEXT_SYNC = 1; 47660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber /** 47760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * If possible, seek to the sync sample closest to the specified time 47860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber */ 479f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber public static final int SEEK_TO_CLOSEST_SYNC = 2; 480f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber 48199f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar /** @hide */ 48299f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar @IntDef({ 48399f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar SEEK_TO_PREVIOUS_SYNC, 48499f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar SEEK_TO_NEXT_SYNC, 48599f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar SEEK_TO_CLOSEST_SYNC, 48699f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar }) 48799f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar @Retention(RetentionPolicy.SOURCE) 48899f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar public @interface SeekMode {} 48999f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar 49060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber /** 49160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * All selected tracks seek near the requested time according to the 49260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * specified mode. 49360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber */ 49499f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar public native void seekTo(long timeUs, @SeekMode int mode); 49588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 49660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber /** 49760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * Advance to the next sample. Returns false if no more sample data 49860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * is available (end of stream). 49907ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber */ 50088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber public native boolean advance(); 50188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 50260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber /** 50360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * Retrieve the current encoded sample and store it in the byte buffer 5047be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar * starting at the given offset. 5057be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar * <p> 5067be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar * <b>Note:</b>As of API 21, on success the position and limit of 5077be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar * {@code byteBuf} is updated to point to the data just read. 5087be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar * @param byteBuf the destination byte buffer 5097be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar * @return the sample size (or -1 if no more samples are available). 51060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber */ 51199f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar public native int readSampleData(@NonNull ByteBuffer byteBuf, int offset); 51288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 51360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber /** 51460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * Returns the track index the current sample originates from (or -1 51560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * if no more samples are available) 51660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber */ 51788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber public native int getSampleTrackIndex(); 51888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 51960d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber /** 52060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * Returns the current sample's presentation time in microseconds. 52160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * or -1 if no more samples are available. 52260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber */ 52388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber public native long getSampleTime(); 52488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 5259b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber // Keep these in sync with their equivalents in NuMediaExtractor.h 52660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber /** 5277be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar * The sample is a sync sample (or in {@link MediaCodec}'s terminology 5287be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar * it is a key frame.) 5297be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar * 5307be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar * @see MediaCodec#BUFFER_FLAG_KEY_FRAME 53160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber */ 5329b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber public static final int SAMPLE_FLAG_SYNC = 1; 53307ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber 53460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber /** 53560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * The sample is (at least partially) encrypted, see also the documentation 53660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * for {@link android.media.MediaCodec#queueSecureInputBuffer} 53760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber */ 5389b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber public static final int SAMPLE_FLAG_ENCRYPTED = 2; 5399b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber 54099f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar /** @hide */ 54199f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar @IntDef( 54299f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar flag = true, 54399f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar value = { 54499f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar SAMPLE_FLAG_SYNC, 54599f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar SAMPLE_FLAG_ENCRYPTED, 54699f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar }) 54799f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar @Retention(RetentionPolicy.SOURCE) 54899f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar public @interface SampleFlag {} 54999f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar 55060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber /** 55160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * Returns the current sample's flags. 55260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber */ 55399f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar @SampleFlag 5549b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber public native int getSampleFlags(); 5559b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber 55660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber /** 55760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * If the sample flags indicate that the current sample is at least 55860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * partially encrypted, this call returns relevant information about 55960d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * the structure of the sample data required for decryption. 56060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * @param info The android.media.MediaCodec.CryptoInfo structure 56160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * to be filled in. 56260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * @return true iff the sample flags contain {@link #SAMPLE_FLAG_ENCRYPTED} 56360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber */ 56499f8072386ce9891a5973d591dc1a30e45b50bc6Lajos Molnar public native boolean getSampleCryptoInfo(@NonNull MediaCodec.CryptoInfo info); 56591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber 56660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber /** 56760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * Returns an estimate of how much data is presently cached in memory 56860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * expressed in microseconds. Returns -1 if that information is unavailable 56960d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * or not applicable (no cache). 57074a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber */ 57174a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber public native long getCachedDuration(); 57274a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber 57360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber /** 57460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * Returns true iff we are caching data and the cache has reached the 57560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * end of the data stream (for now, a future seek may of course restart 57660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * the fetching of data). 577a45746efadd11bb7dfab026fb3c81a25fae74ca4Jeff Smith * This API only returns a meaningful result if {@link #getCachedDuration} 57860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * indicates the presence of a cache, i.e. does NOT return -1. 57960d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber */ 58074a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber public native boolean hasCacheReachedEndOfStream(); 58174a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber 58288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber private static native final void native_init(); 58307ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber private native final void native_setup(); 58488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber private native final void native_finalize(); 58588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 58688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber static { 58788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber System.loadLibrary("media_jni"); 58888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber native_init(); 58988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber } 59088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 591075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat private long mNativeContext; 59288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber} 593