mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Add factory methods to create MediaCodecAdapter.Configuration
#exofixit PiperOrigin-RevId: 396793873
This commit is contained in:
parent
7947d27819
commit
416ec75b94
5 changed files with 120 additions and 58 deletions
|
|
@ -367,8 +367,8 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
||||||
MimeTypes.AUDIO_RAW.equals(codecInfo.mimeType)
|
MimeTypes.AUDIO_RAW.equals(codecInfo.mimeType)
|
||||||
&& !MimeTypes.AUDIO_RAW.equals(format.sampleMimeType);
|
&& !MimeTypes.AUDIO_RAW.equals(format.sampleMimeType);
|
||||||
decryptOnlyCodecFormat = decryptOnlyCodecEnabled ? format : null;
|
decryptOnlyCodecFormat = decryptOnlyCodecEnabled ? format : null;
|
||||||
return new MediaCodecAdapter.Configuration(
|
return MediaCodecAdapter.Configuration.createForAudioDecoding(
|
||||||
codecInfo, mediaFormat, format, /* surface= */ null, crypto, /* flags= */ 0);
|
codecInfo, mediaFormat, format, crypto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -39,13 +39,109 @@ import java.nio.ByteBuffer;
|
||||||
public interface MediaCodecAdapter {
|
public interface MediaCodecAdapter {
|
||||||
/** Configuration parameters for a {@link MediaCodecAdapter}. */
|
/** Configuration parameters for a {@link MediaCodecAdapter}. */
|
||||||
final class Configuration {
|
final class Configuration {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a configuration for audio decoding.
|
||||||
|
*
|
||||||
|
* @param codecInfo See {@link #codecInfo}.
|
||||||
|
* @param mediaFormat See {@link #mediaFormat}.
|
||||||
|
* @param format See {@link #format}.
|
||||||
|
* @param crypto See {@link #crypto}.
|
||||||
|
* @return The created instance.
|
||||||
|
*/
|
||||||
|
public static Configuration createForAudioDecoding(
|
||||||
|
MediaCodecInfo codecInfo,
|
||||||
|
MediaFormat mediaFormat,
|
||||||
|
Format format,
|
||||||
|
@Nullable MediaCrypto crypto) {
|
||||||
|
return new Configuration(
|
||||||
|
codecInfo,
|
||||||
|
mediaFormat,
|
||||||
|
format,
|
||||||
|
/* surface= */ null,
|
||||||
|
crypto,
|
||||||
|
/* flags= */ 0,
|
||||||
|
/* createInputSurface= */ false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a configuration for video decoding.
|
||||||
|
*
|
||||||
|
* @param codecInfo See {@link #codecInfo}.
|
||||||
|
* @param mediaFormat See {@link #mediaFormat}.
|
||||||
|
* @param format See {@link #format}.
|
||||||
|
* @param surface See {@link #surface}.
|
||||||
|
* @param crypto See {@link #crypto}.
|
||||||
|
* @return The created instance.
|
||||||
|
*/
|
||||||
|
public static Configuration createForVideoDecoding(
|
||||||
|
MediaCodecInfo codecInfo,
|
||||||
|
MediaFormat mediaFormat,
|
||||||
|
Format format,
|
||||||
|
@Nullable Surface surface,
|
||||||
|
@Nullable MediaCrypto crypto) {
|
||||||
|
return new Configuration(
|
||||||
|
codecInfo,
|
||||||
|
mediaFormat,
|
||||||
|
format,
|
||||||
|
surface,
|
||||||
|
crypto,
|
||||||
|
/* flags= */ 0,
|
||||||
|
/* createInputSurface= */ false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a configuration for audio encoding.
|
||||||
|
*
|
||||||
|
* @param codecInfo See {@link #codecInfo}.
|
||||||
|
* @param mediaFormat See {@link #mediaFormat}.
|
||||||
|
* @param format See {@link #format}.
|
||||||
|
* @return The created instance.
|
||||||
|
*/
|
||||||
|
public static Configuration createForAudioEncoding(
|
||||||
|
MediaCodecInfo codecInfo, MediaFormat mediaFormat, Format format) {
|
||||||
|
return new Configuration(
|
||||||
|
codecInfo,
|
||||||
|
mediaFormat,
|
||||||
|
format,
|
||||||
|
/* surface= */ null,
|
||||||
|
/* crypto= */ null,
|
||||||
|
MediaCodec.CONFIGURE_FLAG_ENCODE,
|
||||||
|
/* createInputSurface= */ false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a configuration for video encoding.
|
||||||
|
*
|
||||||
|
* @param codecInfo See {@link #codecInfo}.
|
||||||
|
* @param mediaFormat See {@link #mediaFormat}.
|
||||||
|
* @param format See {@link #format}.
|
||||||
|
* @return The created instance.
|
||||||
|
*/
|
||||||
|
@RequiresApi(18)
|
||||||
|
public static Configuration createForVideoEncoding(
|
||||||
|
MediaCodecInfo codecInfo, MediaFormat mediaFormat, Format format) {
|
||||||
|
return new Configuration(
|
||||||
|
codecInfo,
|
||||||
|
mediaFormat,
|
||||||
|
format,
|
||||||
|
/* surface= */ null,
|
||||||
|
/* crypto= */ null,
|
||||||
|
MediaCodec.CONFIGURE_FLAG_ENCODE,
|
||||||
|
/* createInputSurface= */ true);
|
||||||
|
}
|
||||||
|
|
||||||
/** Information about the {@link MediaCodec} being configured. */
|
/** Information about the {@link MediaCodec} being configured. */
|
||||||
public final MediaCodecInfo codecInfo;
|
public final MediaCodecInfo codecInfo;
|
||||||
/** The {@link MediaFormat} for which the codec is being configured. */
|
/** The {@link MediaFormat} for which the codec is being configured. */
|
||||||
public final MediaFormat mediaFormat;
|
public final MediaFormat mediaFormat;
|
||||||
/** The {@link Format} for which the codec is being configured. */
|
/** The {@link Format} for which the codec is being configured. */
|
||||||
public final Format format;
|
public final Format format;
|
||||||
/** For video decoding, the output where the object will render the decoded frames. */
|
/**
|
||||||
|
* For video decoding, the output where the object will render the decoded frames. This must be
|
||||||
|
* null if the codec is not a video decoder, or if it is configured for {@link ByteBuffer}
|
||||||
|
* output.
|
||||||
|
*/
|
||||||
@Nullable public final Surface surface;
|
@Nullable public final Surface surface;
|
||||||
/** For DRM protected playbacks, a {@link MediaCrypto} to use for decryption. */
|
/** For DRM protected playbacks, a {@link MediaCrypto} to use for decryption. */
|
||||||
@Nullable public final MediaCrypto crypto;
|
@Nullable public final MediaCrypto crypto;
|
||||||
|
|
@ -61,17 +157,7 @@ public interface MediaCodecAdapter {
|
||||||
*/
|
*/
|
||||||
public final boolean createInputSurface;
|
public final boolean createInputSurface;
|
||||||
|
|
||||||
public Configuration(
|
private Configuration(
|
||||||
MediaCodecInfo codecInfo,
|
|
||||||
MediaFormat mediaFormat,
|
|
||||||
Format format,
|
|
||||||
@Nullable Surface surface,
|
|
||||||
@Nullable MediaCrypto crypto,
|
|
||||||
int flags) {
|
|
||||||
this(codecInfo, mediaFormat, format, surface, crypto, flags, /* createInputSurface= */ false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Configuration(
|
|
||||||
MediaCodecInfo codecInfo,
|
MediaCodecInfo codecInfo,
|
||||||
MediaFormat mediaFormat,
|
MediaFormat mediaFormat,
|
||||||
Format format,
|
Format format,
|
||||||
|
|
|
||||||
|
|
@ -640,8 +640,8 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
||||||
}
|
}
|
||||||
surface = dummySurface;
|
surface = dummySurface;
|
||||||
}
|
}
|
||||||
return new MediaCodecAdapter.Configuration(
|
return MediaCodecAdapter.Configuration.createForVideoDecoding(
|
||||||
codecInfo, mediaFormat, format, surface, crypto, /* flags= */ 0);
|
codecInfo, mediaFormat, format, surface, crypto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -41,15 +41,13 @@ public class AsynchronousMediaCodecAdapterTest {
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
MediaCodecInfo codecInfo = createMediaCodecInfo("h264", "video/mp4");
|
MediaCodecInfo codecInfo = createMediaCodecInfo("aac", "audio/aac");
|
||||||
MediaCodecAdapter.Configuration configuration =
|
MediaCodecAdapter.Configuration configuration =
|
||||||
new MediaCodecAdapter.Configuration(
|
MediaCodecAdapter.Configuration.createForAudioDecoding(
|
||||||
codecInfo,
|
codecInfo,
|
||||||
createMediaFormat("format"),
|
createMediaFormat("format"),
|
||||||
/* format= */ new Format.Builder().build(),
|
new Format.Builder().build(),
|
||||||
/* surface= */ null,
|
/* crypto= */ null);
|
||||||
/* crypto= */ null,
|
|
||||||
/* flags= */ 0);
|
|
||||||
callbackThread = new HandlerThread("TestCallbackThread");
|
callbackThread = new HandlerThread("TestCallbackThread");
|
||||||
queueingThread = new HandlerThread("TestQueueingThread");
|
queueingThread = new HandlerThread("TestQueueingThread");
|
||||||
adapter =
|
adapter =
|
||||||
|
|
|
||||||
|
|
@ -67,17 +67,12 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||||
private boolean outputStreamEnded;
|
private boolean outputStreamEnded;
|
||||||
|
|
||||||
private static class Factory extends SynchronousMediaCodecAdapter.Factory {
|
private static class Factory extends SynchronousMediaCodecAdapter.Factory {
|
||||||
private final boolean decoder;
|
|
||||||
|
|
||||||
public Factory(boolean decoder) {
|
|
||||||
this.decoder = decoder;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected MediaCodec createCodec(Configuration configuration) throws IOException {
|
protected MediaCodec createCodec(Configuration configuration) throws IOException {
|
||||||
String sampleMimeType =
|
String sampleMimeType =
|
||||||
checkNotNull(configuration.mediaFormat.getString(MediaFormat.KEY_MIME));
|
checkNotNull(configuration.mediaFormat.getString(MediaFormat.KEY_MIME));
|
||||||
return decoder
|
boolean isDecoder = (configuration.flags & MediaCodec.CONFIGURE_FLAG_ENCODE) == 0;
|
||||||
|
return isDecoder
|
||||||
? MediaCodec.createDecoderByType(checkNotNull(sampleMimeType))
|
? MediaCodec.createDecoderByType(checkNotNull(sampleMimeType))
|
||||||
: MediaCodec.createEncoderByType(checkNotNull(sampleMimeType));
|
: MediaCodec.createEncoderByType(checkNotNull(sampleMimeType));
|
||||||
}
|
}
|
||||||
|
|
@ -115,15 +110,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||||
mediaFormat, MediaFormat.KEY_MAX_INPUT_SIZE, format.maxInputSize);
|
mediaFormat, MediaFormat.KEY_MAX_INPUT_SIZE, format.maxInputSize);
|
||||||
MediaFormatUtil.setCsdBuffers(mediaFormat, format.initializationData);
|
MediaFormatUtil.setCsdBuffers(mediaFormat, format.initializationData);
|
||||||
adapter =
|
adapter =
|
||||||
new Factory(/* decoder= */ true)
|
new Factory()
|
||||||
.createAdapter(
|
.createAdapter(
|
||||||
new MediaCodecAdapter.Configuration(
|
MediaCodecAdapter.Configuration.createForAudioDecoding(
|
||||||
createPlaceholderMediaCodecInfo(),
|
createPlaceholderMediaCodecInfo(), mediaFormat, format, /* crypto= */ null));
|
||||||
mediaFormat,
|
|
||||||
format,
|
|
||||||
/* surface= */ null,
|
|
||||||
/* crypto= */ null,
|
|
||||||
/* flags= */ 0));
|
|
||||||
return new MediaCodecAdapterWrapper(adapter);
|
return new MediaCodecAdapterWrapper(adapter);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (adapter != null) {
|
if (adapter != null) {
|
||||||
|
|
@ -154,15 +144,14 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||||
mediaFormat, MediaFormat.KEY_MAX_INPUT_SIZE, format.maxInputSize);
|
mediaFormat, MediaFormat.KEY_MAX_INPUT_SIZE, format.maxInputSize);
|
||||||
MediaFormatUtil.setCsdBuffers(mediaFormat, format.initializationData);
|
MediaFormatUtil.setCsdBuffers(mediaFormat, format.initializationData);
|
||||||
adapter =
|
adapter =
|
||||||
new Factory(/* decoder= */ true)
|
new Factory()
|
||||||
.createAdapter(
|
.createAdapter(
|
||||||
new MediaCodecAdapter.Configuration(
|
MediaCodecAdapter.Configuration.createForVideoDecoding(
|
||||||
createPlaceholderMediaCodecInfo(),
|
createPlaceholderMediaCodecInfo(),
|
||||||
mediaFormat,
|
mediaFormat,
|
||||||
format,
|
format,
|
||||||
surface,
|
surface,
|
||||||
/* crypto= */ null,
|
/* crypto= */ null));
|
||||||
/* flags= */ 0));
|
|
||||||
return new MediaCodecAdapterWrapper(adapter);
|
return new MediaCodecAdapterWrapper(adapter);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (adapter != null) {
|
if (adapter != null) {
|
||||||
|
|
@ -190,15 +179,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||||
checkNotNull(format.sampleMimeType), format.sampleRate, format.channelCount);
|
checkNotNull(format.sampleMimeType), format.sampleRate, format.channelCount);
|
||||||
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, format.bitrate);
|
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, format.bitrate);
|
||||||
adapter =
|
adapter =
|
||||||
new Factory(/* decoder= */ false)
|
new Factory()
|
||||||
.createAdapter(
|
.createAdapter(
|
||||||
new MediaCodecAdapter.Configuration(
|
MediaCodecAdapter.Configuration.createForAudioEncoding(
|
||||||
createPlaceholderMediaCodecInfo(),
|
createPlaceholderMediaCodecInfo(), mediaFormat, format));
|
||||||
mediaFormat,
|
|
||||||
format,
|
|
||||||
/* surface= */ null,
|
|
||||||
/* crypto= */ null,
|
|
||||||
/* flags= */ MediaCodec.CONFIGURE_FLAG_ENCODE));
|
|
||||||
return new MediaCodecAdapterWrapper(adapter);
|
return new MediaCodecAdapterWrapper(adapter);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (adapter != null) {
|
if (adapter != null) {
|
||||||
|
|
@ -232,16 +216,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||||
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 5_000_000);
|
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 5_000_000);
|
||||||
|
|
||||||
adapter =
|
adapter =
|
||||||
new Factory(/* decoder= */ false)
|
new Factory()
|
||||||
.createAdapter(
|
.createAdapter(
|
||||||
new MediaCodecAdapter.Configuration(
|
MediaCodecAdapter.Configuration.createForVideoEncoding(
|
||||||
createPlaceholderMediaCodecInfo(),
|
createPlaceholderMediaCodecInfo(), mediaFormat, format));
|
||||||
mediaFormat,
|
|
||||||
format,
|
|
||||||
/* surface= */ null,
|
|
||||||
/* crypto= */ null,
|
|
||||||
MediaCodec.CONFIGURE_FLAG_ENCODE,
|
|
||||||
/* createInputSurface= */ true));
|
|
||||||
return new MediaCodecAdapterWrapper(adapter);
|
return new MediaCodecAdapterWrapper(adapter);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (adapter != null) {
|
if (adapter != null) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue