mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Release the created placeholder surface in DecodeOneFrameUtil.
PiperOrigin-RevId: 511000498
This commit is contained in:
parent
57a638aa88
commit
43b8859cb7
1 changed files with 56 additions and 21 deletions
|
|
@ -30,15 +30,15 @@ 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 com.google.android.exoplayer2.Format;
|
import com.google.android.exoplayer2.Format;
|
||||||
import com.google.android.exoplayer2.util.MediaFormatUtil;
|
import com.google.android.exoplayer2.util.MediaFormatUtil;
|
||||||
import com.google.android.exoplayer2.util.MimeTypes;
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.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. */
|
||||||
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 =
|
||||||
"No MediaCodec decoders on this device support this value.";
|
"No MediaCodec decoders on this device support this value.";
|
||||||
|
|
@ -66,14 +66,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();
|
||||||
}
|
}
|
||||||
|
|
@ -87,42 +92,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…
Reference in a new issue