Add APIs to set data source using AssetFileDescriptor & FileDescriptor
Introduced three `setDataSource` APIs in `MediaExtractorCompat`, enabling the use of `AssetFileDescriptor` and `FileDescriptor` to set the data source. PiperOrigin-RevId: 653957035
This commit is contained in:
parent
1e28755b4a
commit
0def3b215c
@ -22,6 +22,7 @@ import static androidx.media3.exoplayer.source.SampleStream.FLAG_PEEK;
|
||||
import static androidx.media3.exoplayer.source.SampleStream.FLAG_REQUIRE_FORMAT;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.AssetFileDescriptor;
|
||||
import android.media.MediaExtractor;
|
||||
import android.media.MediaFormat;
|
||||
import android.net.Uri;
|
||||
@ -41,6 +42,7 @@ import androidx.media3.datasource.DataSource;
|
||||
import androidx.media3.datasource.DataSourceUtil;
|
||||
import androidx.media3.datasource.DataSpec;
|
||||
import androidx.media3.datasource.DefaultDataSource;
|
||||
import androidx.media3.datasource.FileDescriptorDataSource;
|
||||
import androidx.media3.decoder.DecoderInputBuffer;
|
||||
import androidx.media3.exoplayer.mediacodec.MediaCodecUtil;
|
||||
import androidx.media3.exoplayer.source.SampleQueue;
|
||||
@ -67,6 +69,7 @@ import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Lists;
|
||||
import java.io.EOFException;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
@ -136,9 +139,18 @@ public final class MediaExtractorCompat {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance using the given {@link ExtractorsFactory extractorsFactory} to create
|
||||
* the {@link Extractor extractors} to use for obtaining media samples from a DataSource generated
|
||||
* by the given {@link DataSource.Factory dataSourceFactory}.
|
||||
* Creates a new instance using the given {@link ExtractorsFactory} to create the {@linkplain
|
||||
* Extractor extractors} to use for obtaining media samples from a {@link DataSource} generated by
|
||||
* the given {@link DataSource.Factory}.
|
||||
*
|
||||
* <p>Note: The {@link DataSource.Factory} provided will not be used to generate {@link
|
||||
* DataSource} when setting data source using methods:
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@link #setDataSource(AssetFileDescriptor)}
|
||||
* <li>{@link #setDataSource(FileDescriptor)}
|
||||
* <li>{@link #setDataSource(FileDescriptor, long, long)}
|
||||
* </ul>
|
||||
*/
|
||||
public MediaExtractorCompat(
|
||||
ExtractorsFactory extractorsFactory, DataSource.Factory dataSourceFactory) {
|
||||
@ -156,8 +168,8 @@ public final class MediaExtractorCompat {
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the internal state with the media stream obtained from the given {@code uri} at the
|
||||
* given {@code offset}.
|
||||
* Sets the data source using the media stream obtained from the given {@link Uri} at the given
|
||||
* {@code offset}.
|
||||
*
|
||||
* @param uri The content {@link Uri} to extract from.
|
||||
* @param offset The offset into the file where the data to be extracted starts, in bytes.
|
||||
@ -167,13 +179,75 @@ public final class MediaExtractorCompat {
|
||||
* @throws IllegalStateException If this method is called twice on the same instance.
|
||||
*/
|
||||
public void setDataSource(Uri uri, long offset) throws IOException {
|
||||
prepareDataSource(
|
||||
dataSourceFactory.createDataSource(), buildDataSpec(uri, /* position= */ offset));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the data source using the media stream obtained from the provided {@link
|
||||
* AssetFileDescriptor}.
|
||||
*
|
||||
* <p>Note: The caller is responsible for closing the {@link AssetFileDescriptor}. It is safe to
|
||||
* do so immediately after this method returns.
|
||||
*
|
||||
* @param assetFileDescriptor The {@link AssetFileDescriptor} for the file to extract from.
|
||||
* @throws IOException If an error occurs while extracting the media.
|
||||
* @throws UnrecognizedInputFormatException If none of the available extractors successfully
|
||||
* sniffs the input.
|
||||
* @throws IllegalStateException If this method is called twice on the same instance.
|
||||
*/
|
||||
public void setDataSource(AssetFileDescriptor assetFileDescriptor) throws IOException {
|
||||
if (assetFileDescriptor.getLength() == AssetFileDescriptor.UNKNOWN_LENGTH) {
|
||||
setDataSource(assetFileDescriptor.getFileDescriptor());
|
||||
} else {
|
||||
setDataSource(
|
||||
assetFileDescriptor.getFileDescriptor(),
|
||||
assetFileDescriptor.getStartOffset(),
|
||||
assetFileDescriptor.getLength());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the data source using the media stream obtained from the provided {@link FileDescriptor}.
|
||||
*
|
||||
* @param fileDescriptor The {@link FileDescriptor} for the file to extract from.
|
||||
* @throws IOException If an error occurs while extracting the media.
|
||||
* @throws UnrecognizedInputFormatException If none of the available extractors successfully
|
||||
* sniffs the input.
|
||||
* @throws IllegalStateException If this method is called twice on the same instance.
|
||||
*/
|
||||
public void setDataSource(FileDescriptor fileDescriptor) throws IOException {
|
||||
setDataSource(fileDescriptor, /* offset= */ 0, /* length= */ C.LENGTH_UNSET);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the data source using the media stream obtained from the provided {@link FileDescriptor},
|
||||
* with a specified {@code offset} and {@code length}.
|
||||
*
|
||||
* @param fileDescriptor The {@link FileDescriptor} for the file to extract from.
|
||||
* @param offset The offset into the file where the data to be extracted starts, in bytes.
|
||||
* @param length The length of the data to be extracted, in bytes, or {@link C#LENGTH_UNSET} if it
|
||||
* is unknown.
|
||||
* @throws IOException If an error occurs while extracting the media.
|
||||
* @throws UnrecognizedInputFormatException If none of the available extractors successfully
|
||||
* sniffs the input.
|
||||
* @throws IllegalStateException If this method is called twice on the same instance.
|
||||
*/
|
||||
public void setDataSource(FileDescriptor fileDescriptor, long offset, long length)
|
||||
throws IOException {
|
||||
FileDescriptorDataSource fileDescriptorDataSource =
|
||||
new FileDescriptorDataSource(fileDescriptor, offset, length);
|
||||
DataSpec dataSpec = new DataSpec(Uri.EMPTY);
|
||||
prepareDataSource(fileDescriptorDataSource, dataSpec);
|
||||
}
|
||||
|
||||
private void prepareDataSource(DataSource dataSource, DataSpec dataSpec) throws IOException {
|
||||
// Assert that this instance is not being re-prepared, which is not currently supported.
|
||||
Assertions.checkState(!hasBeenPrepared);
|
||||
hasBeenPrepared = true;
|
||||
offsetInCurrentFile = offset;
|
||||
DataSpec dataSpec = buildDataSpec(uri, /* position= */ offsetInCurrentFile);
|
||||
offsetInCurrentFile = dataSpec.position;
|
||||
currentDataSource = dataSource;
|
||||
|
||||
currentDataSource = dataSourceFactory.createDataSource();
|
||||
long length = currentDataSource.open(dataSpec);
|
||||
ExtractorInput currentExtractorInput =
|
||||
new DefaultExtractorInput(currentDataSource, /* position= */ 0, length);
|
||||
|
Loading…
x
Reference in New Issue
Block a user