[go: nahoru, domu]

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 &lt; 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, ...) &gt;= 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&hellip;: for listed containers<br>
41743a2398258964e438c2dcdb4638fe9a24edfb208Lajos Molnar     *      MPEG4, AAC&hellip;: 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