Release the created placeholder surface in DecodeOneFrameUtil.
PiperOrigin-RevId: 511000498
This commit is contained in:
parent
a33b0d64c1
commit
0ce1fcc4ad
@ -30,6 +30,7 @@ import android.media.MediaCodecList;
|
|||||||
import android.media.MediaExtractor;
|
import android.media.MediaExtractor;
|
||||||
import android.media.MediaFormat;
|
import android.media.MediaFormat;
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.media3.common.Format;
|
import androidx.media3.common.Format;
|
||||||
import androidx.media3.common.MimeTypes;
|
import androidx.media3.common.MimeTypes;
|
||||||
import androidx.media3.common.util.MediaFormatUtil;
|
import androidx.media3.common.util.MediaFormatUtil;
|
||||||
@ -37,9 +38,8 @@ import androidx.media3.common.util.UnstableApi;
|
|||||||
import androidx.media3.common.util.Util;
|
import androidx.media3.common.util.Util;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
|
||||||
|
|
||||||
/** Utilities for decoding a frame for tests. */
|
/** Utilities for decoding a video frame for tests. */
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
public final class DecodeOneFrameUtil {
|
public final class DecodeOneFrameUtil {
|
||||||
public static final String NO_DECODER_SUPPORT_ERROR_STRING =
|
public static final String NO_DECODER_SUPPORT_ERROR_STRING =
|
||||||
@ -68,14 +68,19 @@ public final class DecodeOneFrameUtil {
|
|||||||
* @param listener A {@link Listener} implementation.
|
* @param listener A {@link Listener} implementation.
|
||||||
* @param surface The {@link Surface} to render the decoded frame to, {@code null} if the decoded
|
* @param surface The {@link Surface} to render the decoded frame to, {@code null} if the decoded
|
||||||
* frame is not needed.
|
* frame is not needed.
|
||||||
* @throws IOException If extractor or codec creation fails.
|
* @throws IOException If the {@link MediaExtractor} or {@link MediaCodec} cannot be created.
|
||||||
*/
|
*/
|
||||||
public static void decodeOneCacheFileFrame(
|
public static void decodeOneCacheFileFrame(
|
||||||
String cacheFilePath, Listener listener, @Nullable Surface surface) throws IOException {
|
String cacheFilePath, Listener listener, @Nullable Surface surface) throws IOException {
|
||||||
MediaExtractor mediaExtractor = new MediaExtractor();
|
MediaExtractor mediaExtractor = new MediaExtractor();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mediaExtractor.setDataSource(cacheFilePath);
|
mediaExtractor.setDataSource(cacheFilePath);
|
||||||
decodeOneFrame(mediaExtractor, listener, surface);
|
if (surface == null) {
|
||||||
|
decodeOneVideoFrame(mediaExtractor, listener);
|
||||||
|
} else {
|
||||||
|
decodeOneVideoFrame(mediaExtractor, listener, surface);
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
mediaExtractor.release();
|
mediaExtractor.release();
|
||||||
}
|
}
|
||||||
@ -89,42 +94,72 @@ public final class DecodeOneFrameUtil {
|
|||||||
* @param listener A {@link Listener} implementation.
|
* @param listener A {@link Listener} implementation.
|
||||||
* @param surface The {@link Surface} to render the decoded frame to, {@code null} if the decoded
|
* @param surface The {@link Surface} to render the decoded frame to, {@code null} if the decoded
|
||||||
* frame is not needed.
|
* frame is not needed.
|
||||||
|
* @throws IOException If the {@link MediaExtractor} or {@link MediaCodec} cannot be created.
|
||||||
*/
|
*/
|
||||||
public static void decodeOneAssetFileFrame(
|
public static void decodeOneAssetFileFrame(
|
||||||
String assetFilePath, Listener listener, @Nullable Surface surface) throws Exception {
|
String assetFilePath, Listener listener, @Nullable Surface surface) throws IOException {
|
||||||
MediaExtractor mediaExtractor = new MediaExtractor();
|
MediaExtractor mediaExtractor = new MediaExtractor();
|
||||||
Context context = getApplicationContext();
|
Context context = getApplicationContext();
|
||||||
|
|
||||||
try (AssetFileDescriptor afd = context.getAssets().openFd(assetFilePath)) {
|
try (AssetFileDescriptor afd = context.getAssets().openFd(assetFilePath)) {
|
||||||
mediaExtractor.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
|
mediaExtractor.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
|
||||||
decodeOneFrame(mediaExtractor, listener, surface);
|
if (surface == null) {
|
||||||
|
decodeOneVideoFrame(mediaExtractor, listener);
|
||||||
|
} else {
|
||||||
|
decodeOneVideoFrame(mediaExtractor, listener, surface);
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
mediaExtractor.release();
|
mediaExtractor.release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads and decodes one frame from the {@code mediaExtractor} and renders it to the {@code
|
* Reads and decodes one video frame from the {@code mediaExtractor} and renders it to the {@code
|
||||||
|
* surface}.
|
||||||
|
*
|
||||||
|
* <p>A placeholder surface is used.
|
||||||
|
*
|
||||||
|
* @param mediaExtractor The {@link MediaExtractor} with a {@link
|
||||||
|
* MediaExtractor#setDataSource(String) data source set}.
|
||||||
|
* @param listener A {@link Listener} implementation.
|
||||||
|
* @throws UnsupportedOperationException If there is no supported {@linkplain MediaCodec decoders}
|
||||||
|
* available.
|
||||||
|
* @throws IOException If the {@link MediaExtractor} or {@link MediaCodec} cannot be created.
|
||||||
|
*/
|
||||||
|
private static void decodeOneVideoFrame(MediaExtractor mediaExtractor, Listener listener)
|
||||||
|
throws IOException {
|
||||||
|
@Nullable SurfaceTexture placeholderSurfaceTexture = null;
|
||||||
|
@Nullable Surface placeholderSurface = null;
|
||||||
|
try {
|
||||||
|
placeholderSurfaceTexture = new SurfaceTexture(/* texName= */ 0);
|
||||||
|
placeholderSurface = new Surface(placeholderSurfaceTexture);
|
||||||
|
decodeOneVideoFrame(mediaExtractor, listener, placeholderSurface);
|
||||||
|
} finally {
|
||||||
|
if (placeholderSurfaceTexture != null) {
|
||||||
|
placeholderSurfaceTexture.release();
|
||||||
|
}
|
||||||
|
if (placeholderSurface != null) {
|
||||||
|
placeholderSurface.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads and decodes one video frame from the {@code mediaExtractor} and renders it to the {@code
|
||||||
* surface}.
|
* surface}.
|
||||||
*
|
*
|
||||||
* @param mediaExtractor The {@link MediaExtractor} with a {@link
|
* @param mediaExtractor The {@link MediaExtractor} with a {@link
|
||||||
* MediaExtractor#setDataSource(String) data source set}.
|
* MediaExtractor#setDataSource(String) data source set}.
|
||||||
* @param listener A {@link Listener} implementation.
|
* @param listener A {@link Listener} implementation.
|
||||||
* @param surface The {@link Surface} to render the decoded frame to, {@code null} if the decoded
|
* @param surface The {@link Surface} to render the decoded frame to.
|
||||||
* frame is not needed.
|
* @throws IOException If the {@link MediaCodec} cannot be created.
|
||||||
* @throws IOException If codec creation fails.
|
* @throws UnsupportedOperationException If there is no supported {@linkplain MediaCodec decoders}
|
||||||
* @throws UnsupportedOperationException If no decoder supports this file's MediaFormat.
|
* available.
|
||||||
*/
|
*/
|
||||||
private static void decodeOneFrame(
|
private static void decodeOneVideoFrame(
|
||||||
MediaExtractor mediaExtractor, Listener listener, @Nullable Surface surface)
|
MediaExtractor mediaExtractor, Listener listener, Surface surface) throws IOException {
|
||||||
throws IOException {
|
|
||||||
// Set up the extractor to read the first video frame and get its format.
|
|
||||||
if (surface == null) {
|
|
||||||
// Creates a placeholder surface.
|
|
||||||
surface = new Surface(new SurfaceTexture(/* texName= */ 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable MediaCodec mediaCodec = null;
|
|
||||||
@Nullable MediaFormat mediaFormat = null;
|
@Nullable MediaFormat mediaFormat = null;
|
||||||
|
@Nullable MediaCodec mediaCodec = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (int i = 0; i < mediaExtractor.getTrackCount(); i++) {
|
for (int i = 0; i < mediaExtractor.getTrackCount(); i++) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user