MediaCodec Clase
Definición
Importante
Parte de la información hace referencia a la versión preliminar del producto, que puede haberse modificado sustancialmente antes de lanzar la versión definitiva. Microsoft no otorga ninguna garantía, explícita o implícita, con respecto a la información proporcionada aquí.
La clase MediaCodec se puede usar para acceder a los códecs multimedia de bajo nivel, i.
[Android.Runtime.Register("android/media/MediaCodec", DoNotGenerateAcw=true)]
public sealed class MediaCodec : Java.Lang.Object
[<Android.Runtime.Register("android/media/MediaCodec", DoNotGenerateAcw=true)>]
type MediaCodec = class
inherit Object
- Herencia
- Atributos
Comentarios
La clase MediaCodec se puede usar para acceder a los códecs multimedia de bajo nivel, es decir, componentes de codificador o descodificador. Forma parte de la infraestructura de soporte multimedia de bajo nivel de Android (normalmente se usa junto con , , MediaCrypto
, , , Image
, y Surface
AudioTrack
). MediaDrm
MediaMuxer
MediaSync
MediaExtractor
<center><img src=".. /.. /.. /images/media/mediacodec_buffers.svg" style="width: 540px; height: 205px" alt="MediaCodec buffer flow diagram"></center>
En términos generales, un códec procesa los datos de entrada para generar datos de salida. Procesa los datos de forma asincrónica y usa un conjunto de búferes de entrada y salida. En un nivel simplista, se solicita (o recibe) un búfer de entrada vacío, se rellena con datos y se envía al códec para su procesamiento. El códec usa los datos y lo transforma en uno de sus búferes de salida vacíos. Por último, solicita (o recibe) un búfer de salida rellenado, consume su contenido y lo vuelve a liberar al códec.
<h3 id=quality Floor>"quality Floor">Minimum Quality Floor for Video Encoding</h3>
android.os.Build.VERSION_CODES#S
A partir de , Video MediaCodecs de Android exige un piso de calidad mínimo. La intención es eliminar las codificaciones de vídeo de mala calidad. Este piso de calidad se aplica cuando el códec está en modo velocidad de bits variable (VBR); no se aplica cuando el códec está en modo velocidad de bits constante (CBR). El cumplimiento del suelo de calidad también está restringido a un rango de tamaño determinado; este intervalo de tamaño está actualmente para resoluciones de vídeo mayores de 320x240 hasta 1920x1080.
Cuando esta planta de calidad está en vigor, el códec y el código de marco auxiliar funcionarán para asegurarse de que el vídeo generado sea de al menos una calidad "justa" o "buena". La métrica que se usa para elegir estos destinos es vmAF (función de evaluación de varios métodos de vídeo) con una puntuación de destino de 70 para las secuencias de prueba seleccionadas.
El efecto típico es que algunos vídeos generarán una velocidad de bits superior a la configurada originalmente. Esto será más notable para los vídeos que se configuraron con velocidades de bits muy bajas; El códec usará una velocidad de bits que se determina que es más probable que genere un vídeo de calidad "justo" o "bueno". Otra situación es donde un vídeo incluye contenido muy complicado (mucho movimiento y detalle); en estas configuraciones, el códec usará una velocidad de bits adicional según sea necesario para evitar perder todos los detalles más finos del contenido.
Este piso de calidad no afectará al contenido capturado en altas velocidades de bits (una velocidad de bits alta ya debe proporcionar el códec con capacidad suficiente para codificar todos los detalles). El piso de calidad no funciona en codificaciones CBR. El piso de calidad actualmente no funciona en resoluciones de 320x240 o inferiores, ni en vídeos con resolución superior a 1920x1080.
<h3>Tipos de< datos/h3>
Los códecs funcionan en tres tipos de datos: datos comprimidos, datos de audio sin procesar y datos de vídeo sin procesar. Los tres tipos de datos se pueden procesar mediante ByteBuffer ByteBuffers
, pero debe usar un Surface
para los datos de vídeo sin procesar para mejorar el rendimiento del códec. Surface usa búferes de vídeo nativos sin asignarlos ni copiarlos en ByteBuffers; por lo tanto, es mucho más eficaz. Normalmente no puedes acceder a los datos de vídeo sin procesar cuando usas surface, pero puedes usar la ImageReader
clase para acceder a fotogramas de vídeo sin proteger (sin procesar). Esto puede ser más eficaz que usar ByteBuffers, ya que algunos búferes nativos se pueden asignar a ByteBuffer#isDirect direct ByteBuffers. Al usar el modo ByteBuffer, puede acceder a fotogramas de vídeo sin procesar mediante la Image
clase y/#getInputImage getInput
#getOutputImage OutputImage(int)
.
<h4>Búferes comprimidos</h4>
Los búferes de entrada (para descodificadores) y los búferes de salida (para codificadores) contienen datos comprimidos según el tipo de formato MediaFormat#KEY_MIME. En el caso de los tipos de vídeo, normalmente se trata de un único fotograma de vídeo comprimido. Para los datos de audio, normalmente es una sola unidad de acceso (un segmento de audio codificado normalmente que contiene unos pocos milisegundos de audio según lo dicta el tipo de formato), pero este requisito se relaja ligeramente en que un búfer puede contener varias unidades de acceso codificadas de audio. En cualquier caso, los búferes no se inician ni terminan en límites arbitrarios de bytes, sino en límites de unidad de acceso o marco a menos que estén marcados con #BUFFER_FLAG_PARTIAL_FRAME
.
<h4>Búferes de audio sin formato/<h4>
Los búferes de audio sin procesar contienen fotogramas completos de datos de audio PCM, que es una muestra para cada canal en orden de canal. Cada muestra de audio PCM es un entero de 16 bits con signo o un valor float, en orden de bytes nativo. Los búferes de audio sin procesar de la codificación PCM flotante solo son posibles si mediaFormat#KEY_PCM_ENCODING de MediaFormat#KEY_PCM_ENCODING está establecido en AudioFormat#ENCODING_PCM_FLOAT durante MediaCodec #configure configure(…)
y confirmado por #getOutputFormat
para descodificadores o #getInputFormat
para codificadores. Un método de ejemplo para comprobar el PCM flotante en MediaFormat es el siguiente:
static boolean isPcmFloat(MediaFormat format) {
return format.getInteger(MediaFormat.KEY_PCM_ENCODING, AudioFormat.ENCODING_PCM_16BIT)
== AudioFormat.ENCODING_PCM_FLOAT;
}
Para extraer, en una matriz corta, un canal de un búfer que contiene datos de audio entero con signo de 16 bits, se puede usar el código siguiente:
// Assumes the buffer PCM encoding is 16 bit.
short[] getSamplesForChannel(MediaCodec codec, int bufferId, int channelIx) {
ByteBuffer outputBuffer = codec.getOutputBuffer(bufferId);
MediaFormat format = codec.getOutputFormat(bufferId);
ShortBuffer samples = outputBuffer.order(ByteOrder.nativeOrder()).asShortBuffer();
int numChannels = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
if (channelIx < 0 || channelIx >= numChannels) {
return null;
}
short[] res = new short[samples.remaining() / numChannels];
for (int i = 0; i < res.length; ++i) {
res[i] = samples.get(i * numChannels + channelIx);
}
return res;
}
<h4>Búferes de vídeo sin formato/<h4>
En los búferes de vídeo del modo ByteBuffer se diseñan según su formato de color MediaFormat#KEY_COLOR_FORMAT. Puede obtener los formatos de color admitidos como una matriz de #getCodecInfo
CodecCapabilities#colorFormats colorFormats
.
MediaCodecInfo#getCapabilitiesForType getCapabilitiesForType(…)
.
. Los códecs de vídeo pueden admitir tres tipos de formatos de color: ul>li strong native raw video format:</strong> Esto está marcado por CodecCapabilities#COLOR_FormatSurface
y se puede usar con una superficie de entrada o salida.<>><<</li><><fuerte búferes< YUV flexibles>/fuerte> (por CodecCapabilities#COLOR_FormatYUV420Flexible
ejemplo): Se pueden usar con una superficie de entrada y salida, así como en el modo ByteBuffer, mediante/ .#getInputImage getInput
<#getOutputImage OutputImage(int)
/li><li><fuerte>otros formatos específicos:</strong> Estos normalmente solo se admiten en el modo ByteBuffer. Algunos formatos de color son específicos del proveedor. Otros se definen en CodecCapabilities
. Para los formatos de color equivalentes a un formato flexible, todavía puede usar #getInputImage getInput
/#getOutputImage OutputImage(int)
.</li></ul>
Todos los códecs de vídeo admiten búferes YUV 4:2:0 flexibles desde android.os.Build.VERSION_CODES#LOLLIPOP_MR1
.
<h4>Acceso a byteBuffers de vídeo sin procesar en dispositivos< anteriores/h4>
android.os.Build.VERSION_CODES#LOLLIPOP
Antes y Image
compatibilidad, debe usar los valores de formato de MediaFormat#KEY_STRIDE
salida y MediaFormat#KEY_SLICE_HEIGHT
para comprender el diseño de los búferes de salida sin procesar. <p class=note> que en algunos dispositivos el alto de segmento se anuncia como 0. Esto podría significar que el alto del segmento es el mismo que el alto del marco o que el alto del segmento es el alto del marco alineado con algún valor (normalmente una potencia de 2). Desafortunadamente, no hay ninguna manera estándar y sencilla de indicar el alto real del segmento en este caso. Además, el paso vertical del U
plano en formatos planar tampoco se especifica ni se define, aunque normalmente es la mitad del alto del segmento.
Las MediaFormat#KEY_WIDTH
teclas y MediaFormat#KEY_HEIGHT
especifican el tamaño de los fotogramas de vídeo; sin embargo, para la mayoría de las codificaciones, el vídeo (imagen) solo ocupa una parte del fotograma de vídeo. Esto se representa mediante el "rectángulo de recorte".
Debe usar las siguientes claves para obtener el rectángulo de recorte de imágenes de salida sin procesar del formato de salida #getOutputFormat. Si estas teclas no están presentes, el vídeo ocupa todo el fotograma de vídeo. El rectángulo de recorte se entiende en el contexto del marco <de salida em>antes</em> aplicando cualquier rotación de MediaFormat#KEY_ROTATION. <table style="width: 0%">thead<>tr<>th>Format Key</th><>Type</th><>Description</th/th<>/tr></thead><><td<MediaFormat#KEY_CROP_LEFT
> td<>><>integer/td td td<>>The left-coordinate (x) of the crop rectangle</td<>/tr tr><><td<>MediaFormat#KEY_CROP_TOP
/td<>td>integer/<<< td>><td><td>La coordenada superior (y) del rectángulo< de recorte/td></tr<>><tr tdMediaFormat#KEY_CROP_RIGHT
>< Integer</td><td>La coordenada derecha (x) <fuerte>MENOS 1/fuerte> del rectángulo< de recorte/td<>/tr tr><<>td tdMediaFormat#KEY_CROP_BOTTOM
<><>> integer</td td td><>La coordenada inferior (y) <fuerte>MENOS 1<</fuerte> del rectángulo< de recorte/td<>/tr tr td>><<colspan=3> Las coordenadas derecha e inferior se pueden entender como las coordenadas de la columna o la fila más válida de la parte inferior derecha de la imagen de salida recortada. </td></tr></tbody></table>
El tamaño del fotograma de vídeo (antes de la rotación) se puede calcular como tal:
MediaFormat format = decoder.getOutputFormat(…);
int width = format.getInteger(MediaFormat.KEY_WIDTH);
if (format.containsKey(MediaFormat.KEY_CROP_LEFT)
&& format.containsKey(MediaFormat.KEY_CROP_RIGHT)) {
width = format.getInteger(MediaFormat.KEY_CROP_RIGHT) + 1
- format.getInteger(MediaFormat.KEY_CROP_LEFT);
}
int height = format.getInteger(MediaFormat.KEY_HEIGHT);
if (format.containsKey(MediaFormat.KEY_CROP_TOP)
&& format.containsKey(MediaFormat.KEY_CROP_BOTTOM)) {
height = format.getInteger(MediaFormat.KEY_CROP_BOTTOM) + 1
- format.getInteger(MediaFormat.KEY_CROP_TOP);
}
<p class=note Tenga en cuenta> también que el significado de BufferInfo#offset BufferInfo.offset
no era coherente en todos los dispositivos. En algunos dispositivos, el desplazamiento apuntaba al píxel superior izquierdo del rectángulo de recorte, mientras que en la mayoría de los dispositivos apuntaba al píxel superior izquierdo de todo el fotograma.
<h3>States</h3>
Durante su vida existe un códec conceptualmente en uno de los tres estados: Detenido, Ejecutándose o Liberado. El estado colectivo Detenido es realmente el agrupamiento de tres estados: Sin inicializar, Configurado y Error, mientras que el estado En ejecución avanza conceptualmente a través de tres subes estados: Flushed, Running y End-of-Stream.
<center><img src=".. /.. /.. /images/media/mediacodec_states.svg" style="width: 519px; height: 356px" alt="MediaCodec state diagram"></center>
Al crear un códec mediante uno de los métodos de fábrica, el códec está en estado Sin inicializar. En primer lugar, debe configurarlo a través #configure configure(…)
de , que lo lleva al estado Configurado y, a continuación, llamar #start
a para moverlo al estado En ejecución. En este estado, puede procesar los datos a través de la manipulación de la cola de búfer descrita anteriormente.
El estado Executing tiene tres subestados: Flushed, Running y End-of-Stream. Inmediatamente después #start
de que el códec esté en estado vaciado, donde contiene todos los búferes. Tan pronto como se desquee el primer búfer de entrada, el códec se mueve al sub-estado En ejecución, donde pasa la mayor parte de su vida. Al poner en cola un búfer de entrada con el marcador de fin de flujo de #BUFFER_FLAG_END_OF_STREAM, el códec pasa al subeste de fin de flujo. En este estado, el códec ya no acepta más búferes de entrada, pero sigue generando búferes de salida hasta que se alcanza el final del flujo en la salida. En el caso de los descodificadores, puede volver al subes state Flushed en cualquier momento mientras se encuentra en el estado Executing mediante #flush
. <p class=note><strong>Note:</strong> Going back to Flushed state is only supported for decoders, and may not work for encoders (the behavior is undefined).
Llame #stop
a para devolver el códec al estado Sin inicializar, donde puede que se vuelva a configurar. Cuando haya terminado de usar un códec, debe liberarlo llamando a #release
.
En raras ocasiones, el códec puede encontrar un error y pasar al estado Error. Esto se comunica mediante un valor devuelto no válido de una operación de puesta en cola o a veces a través de una excepción. Llame #reset
a para que el códec se pueda volver a usar. Puede llamarlo desde cualquier estado para volver al códec al estado Sin inicializar. De lo contrario, llame #release
a para pasar al estado Liberado del terminal.
<h3>Creation</h3>
Use MediaCodecList
para crear un objeto MediaCodec para un elemento específico MediaFormat
. Al descodificar un archivo o una secuencia, puede obtener el formato deseado de MediaExtractor#getTrackFormat MediaExtractor.getTrackFormat
. Inserte las características específicas que quiera agregar mediante MediaFormat#setFeatureEnabled MediaFormat.setFeatureEnabled
y, a continuación, llame MediaCodecList#findDecoderForFormat MediaCodecList.findDecoderForFormat
a para obtener el nombre de un códec que pueda controlar ese formato multimedia específico. Por último, cree el códec mediante #createByCodecName
. <p class=note><strong>Note:</strong> On android.os.Build.VERSION_CODES#LOLLIPOP
, el formato para MediaCodecList.findDecoder
/EncoderForFormat
no debe contener una velocidad de fotogramas MediaFormat#KEY_FRAME_RATE. Use format.setString(MediaFormat.KEY_FRAME_RATE, null)
para borrar cualquier configuración de velocidad de fotogramas existente en el formato .
También puede crear el códec preferido para un tipo MIME específico mediante #createDecoderByType createDecoder
/#createEncoderByType EncoderByType(String)
. Sin embargo, esto no se puede usar para insertar características y puede crear un códec que no pueda controlar el formato multimedia deseado específico.
<h4>Crear descodificadores< seguros/h4>
En las versiones android.os.Build.VERSION_CODES#KITKAT_WATCH
y versiones anteriores, es posible que los códecs seguros no aparezcan en MediaCodecList
, pero todavía pueden estar disponibles en el sistema. Los códecs seguros que existen solo se pueden crear instancias por nombre; al anexar ".secure"
al nombre de un códec normal (el nombre de todos los códecs seguros debe terminar en ".secure"
. ) #createByCodecName
producirá un IOException
si el códec no está presente en el sistema.
Desde android.os.Build.VERSION_CODES#LOLLIPOP
adelante, debe usar la CodecCapabilities#FEATURE_SecurePlayback
característica en formato multimedia para crear un descodificador seguro.
<h3>Initialization</h3>
Después de crear el códec, puede establecer una devolución de llamada mediante #setCallback setCallback
si desea procesar datos de forma asincrónica. A continuación, #configure configurar el códec mediante el formato multimedia específico. Esto es cuando se puede especificar la salida Surface
de los productores de vídeo – códecs que generan datos de vídeo sin procesar (por ejemplo, descodificadores de vídeo). Esto también se puede establecer cuando se pueden establecer los parámetros de descifrado para códecs seguros (consulte MediaCrypto
). Por último, dado que algunos códecs pueden funcionar en varios modos, debe especificar si desea que funcione como descodificador o como codificador.
Como android.os.Build.VERSION_CODES#LOLLIPOP
, puede consultar el formato de entrada y salida resultantes en el estado Configurado. Puede usarlo para comprobar la configuración resultante, por ejemplo, formatos de color, antes de iniciar el códec.
Si desea procesar búferes de vídeo de entrada sin procesar de forma nativa con un consumidor de vídeo – un códec que procesa la entrada de vídeo sin procesar, como un codificador de vídeo – crea un Surface de destino para los datos de entrada mediante #createInputSurface
después de la configuración. Como alternativa, configure el códec para usar una superficie de entrada persistente creada anteriormente #createPersistentInputSurface llamando a #setInputSurface
.
<h4 id=CSD>"CSD">Data</h4 específico del códec>
Algunos formatos, en particular los formatos de audio AAC y MPEG4, H.264 y H.265 requieren que los datos reales sean prefijos por varios búferes que contienen datos de configuración o datos específicos del códec. Al procesar estos formatos comprimidos, estos datos deben enviarse al códec después #start
y antes de cualquier dato de fotograma. Estos datos deben marcarse con la marca #BUFFER_FLAG_CODEC_CONFIG
en una llamada a #queueInputBuffer queueInputBuffer
.
Los datos específicos del códec también se pueden incluir en el formato pasado a #configure configure
en entradas de ByteBuffer con claves "csd-0", "csd-1", etc. Estas claves siempre se incluyen en la pista MediaFormat
obtenida de .MediaExtractor#getTrackFormat MediaExtractor
Los datos específicos del códec en el formato se envían automáticamente al códec sobre #start
; no debe<<>> enviar estos datos explícitamente. Si el formato no contenía datos específicos del códec, puede optar por enviarlo mediante el número especificado de búferes en el orden correcto, según los requisitos de formato. En el caso de H.264 AVC, también puede concatenar todos los datos específicos del códec y enviarlos como un único búfer de configuración de códecs.
Android usa los siguientes búferes de datos específicos del códec. También se deben establecer en el formato de pista para una configuración de seguimiento adecuada MediaMuxer
. Cada conjunto de parámetros y las secciones de datos específicos del códec marcadas con (sup*/sup>) deben comenzar con un código de inicio de "\x00\x00\x00\x01"
.<><
<style>td. NA { background: #ccc; } .mid > tr td > { vertical-align: middle; }</style><table><thead><th>Format</th>><CSD buffer #0</th th>><CSD buffer #1</th><>CSD buffer #2</th></thead<>tbody class=mid><tr<>td>AAC</td td<>>información específica del codificador de ESDS<sup>*</sup></td td><class=NA>Not Used</td td><class=NA>Not Used</Td></tr tr><><td>VORBIS</td td>><Identification header</td td><>setup header</td td><class=NA>Not Used</td></tr tr><><td>OPUS</td td><td>Identification header</td td>><pre-skip in nanosecs<br> (unsigned ByteOrder#nativeOrder native-order integer).)<br> Esto invalida el valor de pre-skip en el encabezado de identificación.</td td>><Seek Pre-roll in nanosecs<br> (unsigned 64-bit ByteOrder#nativeOrder native-order integer).)</td/tr tr<>td><>FLAC</td td><>"fLaC", el marcador de secuencia FLAC en ASCII,br>< seguido del bloque STREAMINFO (el bloque de metadatos obligatorios),<br> opcionalmente seguido de cualquier número de otros bloques< de metadatos/td td<>class=NA>Not Used/td td><class=NA>Not Used<</td/td<> tr td<>><>MPEG-4</td>><<Td>Información específica del descodificador de ESDS sup*/sup></td><td class=NA>Not Used/td<>td class=NA>Not Used<</td<>/tr tr><td><>H.264 AVC</td>><SPS (Conjuntos<de parámetros de secuencia sup>*/sup>)</td td>><PPS (Conjuntos<de parámetros de imagen sup>*<</sup>)</td td><<>< class=NA>Not Used</td></tr tr td><>><H.265 HEVC</td td><>VPS (Video Parameter Sets<sup>*</sup>) +<br> SPS (Sequence Parameter Sets<sup>*</sup>) +<br> PPS (Picture Parameter Sets<sup>*</sup>)</td td><class=NA>Not Used/td td><class=NA>Not Used/<< td></tr tr><><td>VP9</td><td>VP9 CodecPrivate Data (optional)</td><td class=NA>Not Used</td td<>class=NA>Not Used</td></tr tr td><>><AV1</td avd><>AV1 AV1 Av1CodecConfigurationRecord Data (opcional) </td td<>td class=NA>Not Used/< td><td class=NA>Not Used</td></tr></tbody></table>
<p class=note><strong>Note:</strong> care must be taken if the codec is flushed inmediatamente or shortly after start, before any output buffer or output format change has been returned, as the codec specific data may be lost during the flush. Debe volver a enviar los datos mediante búferes marcados con #BUFFER_FLAG_CODEC_CONFIG
después de dicho vaciado para garantizar una operación correcta del códec.
Los codificadores (o códecs que generan datos comprimidos) crearán y devolverán los datos específicos del códec antes de cualquier búfer de salida válido en los búferes de salida marcados con la marca #BUFFER_FLAG_CODEC_CONFIG códec-config. Los búferes que contienen datos específicos del códec no tienen marcas de tiempo significativas.
<h3>Procesamiento de< datos/h3>
Cada códec mantiene un conjunto de búferes de entrada y salida a los que hace referencia un identificador de búfer en las llamadas API. Después de una llamada correcta al #start
cliente "propietaria", ni los búferes de entrada ni salida. En modo sincrónico, llame #dequeueInputBuffer dequeueInput
/#dequeueOutputBuffer OutputBuffer(…)
a para obtener (obtener la propiedad de) un búfer de entrada o salida del códec. En el modo asincrónico, recibirá automáticamente búferes disponibles a través de las Callback#onInputBufferAvailable MediaCodec.Callback.onInput
/Callback#onOutputBufferAvailable OutputBufferAvailable(…)
devoluciones de llamada.
Tras obtener un búfer de entrada, llene con datos y envíelo al códec mediante #queueInputBuffer queueInputBuffer
– o #queueSecureInputBuffer queueSecureInputBuffer
si usa descifrado. No envíe varios búferes de entrada con la misma marca de tiempo (a menos que sea datos específicos del códec marcados como tales).
El códec a su vez devolverá un búfer de salida de solo lectura a través de la Callback#onOutputBufferAvailable onOutputBufferAvailable
devolución de llamada en modo asincrónico o en respuesta a una #dequeueOutputBuffer dequeueOutputBuffer
llamada en modo sincrónico. Una vez procesado el búfer de salida, llame a uno de los #releaseOutputBuffer releaseOutputBuffer
métodos para devolver el búfer al códec.
Aunque no es necesario volver a enviar o liberar búferes inmediatamente al códec, mantener presionados en los búferes de entrada o salida puede detener el códec y este comportamiento depende del dispositivo. <en>concreto, es posible que un códec se mantenga presionado al generar búferes de salida hasta <que se>>< hayan liberado o reenviado los búferes pendientes em.</strong> Por lo tanto, intente mantener en los búferes disponibles lo menos posible.
En función de la versión de la API, puede procesar datos de tres maneras: table>thead><tr<>th>Processing Mode</th><>API version <= 20<br>Jelly Bean/KitKat</th th<>>API version >= 21<br>Lollipop and later</th></tr/thead<>tbody<>tr<> td<>>Synchronous API using buffer arrays</td td><Supported</td td><<><td>Deprecated</td></tr tr>><<td td>Synchronous API using buffers</td td><class=NA>Not Available</td td><>Supported</td<> tr td>><<>Asincrónico API using buffers</td td><class=NA>Not Available</td td><td>Supported</td<>/tr<>/tbody></table>
<h4>Procesamiento asincrónico mediante búferes</h4>
Como android.os.Build.VERSION_CODES#LOLLIPOP
, el método preferido es procesar datos de forma asincrónica estableciendo una devolución de llamada antes de llamar a #configure configure
. El modo asincrónico cambia ligeramente las transiciones de estado, ya que debe llamar #start
a después #flush
de realizar la transición del códec al subeste en ejecución y empezar a recibir búferes de entrada. Del mismo modo, tras una llamada inicial al start
códec se moverá directamente al subeste en ejecución y comenzará a pasar los búferes de entrada disponibles a través de la devolución de llamada.
<center><img src=".. /.. /.. /images/media/mediacodec_async_states.svg" style="width: 516px; height: 353px" alt="MediaCodec state diagram for asinc operation"></center>
MediaCodec se usa normalmente como este en modo asincrónico:
MediaCodec codec = MediaCodec.createByCodecName(name);
MediaFormat mOutputFormat; // member variable
codec.setCallback(new MediaCodec.Callback() {
{@literal @Override}
void onInputBufferAvailable(MediaCodec mc, int inputBufferId) {
ByteBuffer inputBuffer = codec.getInputBuffer(inputBufferId);
// fill inputBuffer with valid data
…
codec.queueInputBuffer(inputBufferId, …);
}
{@literal @Override}
void onOutputBufferAvailable(MediaCodec mc, int outputBufferId, …) {
ByteBuffer outputBuffer = codec.getOutputBuffer(outputBufferId);
MediaFormat bufferFormat = codec.getOutputFormat(outputBufferId); // option A
// bufferFormat is equivalent to mOutputFormat
// outputBuffer is ready to be processed or rendered.
…
codec.releaseOutputBuffer(outputBufferId, …);
}
{@literal @Override}
void onOutputFormatChanged(MediaCodec mc, MediaFormat format) {
// Subsequent data will conform to new format.
// Can ignore if using getOutputFormat(outputBufferId)
mOutputFormat = format; // option B
}
{@literal @Override}
void onError(…) {
…
}
{@literal @Override}
void onCryptoError(…) {
…
}
});
codec.configure(format, …);
mOutputFormat = codec.getOutputFormat(); // option B
codec.start();
// wait for processing to complete
codec.stop();
codec.release();
<h4>Procesamiento sincrónico mediante búferes</h4>
Como android.os.Build.VERSION_CODES#LOLLIPOP
, debe recuperar búferes de entrada y salida mediante/#getOutputBuffer OutputBuffer(int)
#getInputBuffer getInput
o #getInputImage getInput
/#getOutputImage OutputImage(int)
incluso cuando se usa el códec en modo sincrónico. Esto permite ciertas optimizaciones por parte del marco, por ejemplo, al procesar contenido dinámico. Esta optimización está deshabilitada si llama a #getInputBuffers getInput
/#getOutputBuffers OutputBuffers()
.
<p class=note><strong>Note:</strong> no mezcla los métodos de usar búferes y matrices de búfer al mismo tiempo. En concreto, solo llame directamente getInput
/OutputBuffers
después #start
o después de haber quitado de la cola un identificador de búfer de salida con el valor de .#INFO_OUTPUT_FORMAT_CHANGED
MediaCodec se usa normalmente como este en modo sincrónico:
MediaCodec codec = MediaCodec.createByCodecName(name);
codec.configure(format, …);
MediaFormat outputFormat = codec.getOutputFormat(); // option B
codec.start();
for (;;) {
int inputBufferId = codec.dequeueInputBuffer(timeoutUs);
if (inputBufferId >= 0) {
ByteBuffer inputBuffer = codec.getInputBuffer(…);
// fill inputBuffer with valid data
…
codec.queueInputBuffer(inputBufferId, …);
}
int outputBufferId = codec.dequeueOutputBuffer(…);
if (outputBufferId >= 0) {
ByteBuffer outputBuffer = codec.getOutputBuffer(outputBufferId);
MediaFormat bufferFormat = codec.getOutputFormat(outputBufferId); // option A
// bufferFormat is identical to outputFormat
// outputBuffer is ready to be processed or rendered.
…
codec.releaseOutputBuffer(outputBufferId, …);
} else if (outputBufferId == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
// Subsequent data will conform to new format.
// Can ignore if using getOutputFormat(outputBufferId)
outputFormat = codec.getOutputFormat(); // option B
}
}
codec.stop();
codec.release();
<h4>Procesamiento sincrónico mediante matrices de búfer (en desuso)</h4>
En las versiones android.os.Build.VERSION_CODES#KITKAT_WATCH
y anteriores, el conjunto de búferes de entrada y salida se representa mediante las ByteBuffer[]
matrices. Después de una llamada correcta a #start
, recupere las matrices de búfer mediante/#getInputBuffers getInput
#getOutputBuffers OutputBuffers()
. Use los identificadores de búfer como índices en estas matrices (cuando no son negativos), como se muestra en el ejemplo siguiente. Tenga en cuenta que no hay ninguna correlación inherente entre el tamaño de las matrices y el número de búferes de entrada y salida utilizados por el sistema, aunque el tamaño de la matriz proporciona un límite superior.
MediaCodec codec = MediaCodec.createByCodecName(name);
codec.configure(format, …);
codec.start();
ByteBuffer[] inputBuffers = codec.getInputBuffers();
ByteBuffer[] outputBuffers = codec.getOutputBuffers();
for (;;) {
int inputBufferId = codec.dequeueInputBuffer(…);
if (inputBufferId >= 0) {
// fill inputBuffers[inputBufferId] with valid data
…
codec.queueInputBuffer(inputBufferId, …);
}
int outputBufferId = codec.dequeueOutputBuffer(…);
if (outputBufferId >= 0) {
// outputBuffers[outputBufferId] is ready to be processed or rendered.
…
codec.releaseOutputBuffer(outputBufferId, …);
} else if (outputBufferId == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
outputBuffers = codec.getOutputBuffers();
} else if (outputBufferId == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
// Subsequent data will conform to new format.
MediaFormat format = codec.getOutputFormat();
}
}
codec.stop();
codec.release();
<h4>Control de fin de flujo</h4>
Cuando llegue al final de los datos de entrada, debe indicarlo al códec especificando la #BUFFER_FLAG_END_OF_STREAM
marca en la llamada a #queueInputBuffer queueInputBuffer
. Puede hacerlo en el último búfer de entrada válido o enviando un búfer de entrada vacío adicional con el conjunto de marcas de fin de flujo. Si usa un búfer vacío, se omitirá la marca de tiempo.
El códec seguirá devolviendo búferes de salida hasta que finalmente señale el final del flujo de salida especificando la misma marca de fin de flujo en el BufferInfo
conjunto en #dequeueOutputBuffer dequeueOutputBuffer
o devuelto a través Callback#onOutputBufferAvailable onOutputBufferAvailable
de . Esto se puede establecer en el último búfer de salida válido o en un búfer vacío después del último búfer de salida válido. Se debe omitir la marca de tiempo de dicho búfer vacío.
No envíe búferes de entrada adicionales después de indicar el final de la secuencia de entrada, a menos que el códec se haya vaciado o detenido y reiniciado.
<h4>Usar una superficie< de salida/h4>
El procesamiento de datos es casi idéntico al modo ByteBuffer cuando se usa una salida Surface
; sin embargo, los búferes de salida no serán accesibles y se representan como null
valores. Por ejemplo, #getOutputBuffer getOutputBuffer
/#getOutputImage Image(int)
devolverá null
y #getOutputBuffers
devolverá una matriz que contenga solo null
-s.
Al usar una superficie de salida, puedes seleccionar si quieres representar o no cada búfer de salida en la superficie. Tiene tres opciones: <ul><li><strong>Do not render the buffer:</strong> Call #releaseOutputBuffer(int, boolean) releaseOutputBuffer(bufferId, false)
.</li><><strong>Representa el búfer con la marca de tiempo predeterminada:</strong> Call #releaseOutputBuffer(int, boolean) releaseOutputBuffer(bufferId, true)
.</li><><fuerte>Representa el búfer con una marca de tiempo específica:</strong> Call #releaseOutputBuffer(int, long) releaseOutputBuffer(bufferId, timestamp)
.</li></ul>
Dado android.os.Build.VERSION_CODES#M
que , la marca de tiempo predeterminada es la marca de tiempo de presentación BufferInfo#presentationTimeUs del búfer (convertida en nanosegundos). No se definió antes de eso.
Además, ya android.os.Build.VERSION_CODES#M
que , puedes cambiar la salida Surface dinámicamente mediante #setOutputSurface setOutputSurface
.
Al representar la salida en un Surface, surface puede configurarse para quitar fotogramas excesivos (que surface no consume de forma oportuna). O bien, puede configurarse para no quitar fotogramas excesivos. En el último modo si Surface no consume fotogramas de salida lo suficientemente rápidos, finalmente bloqueará el descodificador. android.os.Build.VERSION_CODES#Q
Antes del comportamiento exacto no estaba definido, con la excepción de que las superficies De vista (SurfaceView o TextureView) siempre quitaron marcos excesivos. Dado android.os.Build.VERSION_CODES#Q
que el comportamiento predeterminado es quitar fotogramas excesivos. Las aplicaciones pueden no participar en este comportamiento para superficies que no son de vista (como ImageReader o SurfaceTexture) estableciendo el SDK android.os.Build.VERSION_CODES#Q
y estableciendo la clave MediaFormat#KEY_ALLOW_FRAME_DROP
0
en en su formato de configuración.
<Transformaciones h4>al representar en Surface</h4>
Si el códec está configurado en modo Surface, cualquier rectángulo de recorte, MediaFormat#KEY_ROTATION rotación y #setVideoScalingMode modo de escalado de vídeo se aplicará automáticamente con una excepción: <p class=note> Antes de la android.os.Build.VERSION_CODES#M
versión, es posible que los descodificadores de software no hayan aplicado la rotación cuando se representen en surface. Desafortunadamente, no hay ninguna manera estándar y sencilla de identificar descodificadores de software, o si aplican la rotación que no sea probarla.
También hay algunas advertencias. <p class=note Ten en cuenta> que la relación de aspecto de píxel no se tiene en cuenta al mostrar la salida en surface. Esto significa que si usas #VIDEO_SCALING_MODE_SCALE_TO_FIT
el modo , debes colocar la superficie de salida para que tenga la relación de aspecto de pantalla final adecuada. Por el contrario, solo puede usar #VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING
el modo para el contenido con píxeles cuadrados (relación de aspecto de píxel o 1:1). <p class=note Tenga en cuenta> que, a partir de la android.os.Build.VERSION_CODES#N
versión, #VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING
el modo puede no funcionar correctamente para los vídeos girados por 90 o 270 grados. <p class=note> Al establecer el modo de escalado de vídeo, tenga en cuenta que debe restablecerse después de cada vez que cambien los búferes de salida. Dado que el #INFO_OUTPUT_BUFFERS_CHANGED
evento está en desuso, puede hacerlo después de cada vez que cambie el formato de salida.
<h4>Usar una superficie< de entrada/h4>
Cuando se usa una superficie de entrada, no hay búferes de entrada accesibles, ya que los búferes se pasan automáticamente de la superficie de entrada al códec. Al llamar #dequeueInputBuffer dequeueInputBuffer
a se producirá un IllegalStateException
, y #getInputBuffers
se devuelve una matriz falsa ByteBuffer[]
en la que <debe escribirse una matriz fuerte>no< fuerte> .
Llame #signalEndOfInputStream
a para indicar el final del flujo. La superficie de entrada dejará de enviar datos al códec inmediatamente después de esta llamada.
<h3>Buscando y Compatibilidad con< la reproducción adaptable/h3>
Los descodificadores de vídeo (y en general códecs que consumen datos de vídeo comprimidos) se comportan de forma diferente con respecto a la búsqueda y el formato cambian si admiten o no y están configurados para la reproducción adaptable. Puede comprobar si un descodificador admite CodecCapabilities#FEATURE_AdaptivePlayback reproducción adaptable a través de CodecCapabilities#isFeatureSupported CodecCapabilities.isFeatureSupported(String)
. La compatibilidad con la reproducción adaptable para descodificadores de vídeo solo se activa si configura el códec para descodificar en un Surface
.
<h4 id=KeyFrames"KeyFrames>">Stream Boundary and Key Frames</h4>
Es importante que los datos de entrada después #start
o #flush
comiencen en un límite de flujo adecuado: el primer fotograma debe ser un fotograma clave. Un <fotograma<> clave em>se puede descodificar completamente por sí mismo (para la mayoría de los códecs esto significa un fotograma I) y no se mostrarán fotogramas después de que un fotograma clave haga referencia a fotogramas antes del fotograma clave.
En la tabla siguiente se resumen los fotogramas clave adecuados para varios formatos de vídeo. <table>thead><tr><th>Format</th th><>Suitable key frame</th<>/tr<>/thead<>tbody class=mid<>tr td><>VP9/VP8</td td><>un intraframe adecuado donde ningún fotograma posterior hace referencia a fotogramas anteriores a este fotograma.<<br>(No hay ningún nombre específico para este fotograma clave).</td></tr tr><td>><H.265 HEVC</td td><>idR o CRA</td<>/tr><tr<>td>H.264 AVC</td td><>idR</td>< tr tr><td<>>MPEG-4<br>H.263<br>MPEG-2</td<>>un fotograma I adecuado donde ningún fotograma posterior haga referencia a fotogramas anteriores a este fotograma.<br>(No hay ningún nombre específico para este fotograma clave).</td></tr></tbody></table>
<h4>Para los descodificadores que no admiten la reproducción adaptable (incluido cuando no se descodificación en surface)</h4>
Para empezar a descodificar los datos que no son adyacentes a los datos enviados previamente (es decir, después de una búsqueda), es <>necesario</vaciar> fuertemente el descodificador. Dado que todos los búferes de salida se revocan inmediatamente en el punto del vaciado, es posible que desee primero indicar que espere al final de la secuencia antes de llamar a flush
. Es importante que los datos de entrada después de que un vaciado se inicie en un límite o fotograma clave de flujo adecuado. <p class=note>strong Note:</strong> the format of the data submitted after a flush must not change; #flush
does not support format discontinuities; for that, a full #stop
- #start
#configure configure(…)
- cycle is necessary.><
<p class=note><strong>Also note:</strong> if you flush the codec too soon after #start
– generally, before the first output buffer or output format change is received – you will need to resubmit the codec-specific-data to the codec-specific-data to the codec. Consulte la sección datos específicos del códec para obtener más información.
<h4>Para los descodificadores que admiten y están configurados para la reproducción< adaptable/h4>
Para empezar a descodificar los datos que no son adyacentes a los datos enviados previamente (es decir, después de una búsqueda), no es <>necesario</em> para vaciar el descodificador; sin embargo, los datos de entrada después de la discontinuidad deben iniciarse en un límite de flujo o fotograma clave adecuado.
Para algunos formatos de vídeo ( a saber, H.264, H.265, VP8 y VP9), también es posible cambiar el tamaño de imagen o la configuración de la secuencia media. Para ello, debe empaquetar los nuevos datos de configuración específicos del códec junto con el marco clave en un solo búfer (incluidos los códigos de inicio) y enviarlos como un <búfer de entrada regular< o fuerte fuerte>>.
Recibirá un #INFO_OUTPUT_FORMAT_CHANGED
valor devuelto de o una Callback#onOutputBufferAvailable onOutputFormatChanged
devolución de #dequeueOutputBuffer dequeueOutputBuffer
llamada justo después de que se produzca el cambio de tamaño de imagen y antes de que se devuelvan los fotogramas con el nuevo tamaño. <p class=note><strong>Note:</strong> igual que en el caso de los datos específicos del códec, tenga cuidado al llamar #flush
poco después de haber cambiado el tamaño de imagen. Si no ha recibido confirmación del cambio de tamaño de imagen, deberá repetir la solicitud para el nuevo tamaño de imagen.
<h3>Control de errores</h3>
Los métodos #createByCodecName createByCodecName
de fábrica y#createEncoderByType EncoderByType
#createDecoderByType createDecoder
/producen IOException
un error que debe detectar o declarar para pasar. Los métodos MediaCodec inician IllegalStateException
cuando se llama al método desde un estado de códec que no lo permite; esto suele deberse a un uso incorrecto de la API de la aplicación. Los métodos que implican búferes seguros pueden producir CryptoException
, que tiene más información de error que se puede obtener de CryptoException#getErrorCode
.
Los errores internos de códec producen un CodecException
, que puede deberse a daños en el contenido multimedia, errores de hardware, agotamiento de recursos, etc., incluso cuando la aplicación usa correctamente la API. La acción recomendada al recibir un CodecException
objeto se puede determinar mediante una llamada a CodecException#isRecoverable
y CodecException#isTransient
: <ul><li><strong>recoverable errors:</strong> If isRecoverable()
devuelve true, llame #stop
a , #configure configure(…)
y #start
para recuperar.</li li><><errores transitorios seguros>:</strong> Si isTransient()
devuelve true, los recursos no están disponibles temporalmente y el método se puede reintentar más adelante.</li li><><: errores irrecuperables fuertes>:</strong> Si ambos isRecoverable()
y isTransient()
devuelven false, el CodecException
códec es irrecuperable y el códec debe ser #reset restablecer o #release liberar.</li></ul>
Tanto como isRecoverable()
isTransient()
no devuelven true al mismo tiempo.
<h2 id=History"History>">Valid API Calls and API History</h2>
En esta sección se resumen las llamadas API válidas en cada estado y el historial de API de la clase MediaCodec. Para ver los números de versión de la API, consulte android.os.Build.VERSION_CODES
.
<style> .api > tr > th, .api > tr > td { text-align: center; padding: 4px 4px; } .api > tr > th { vertical-align: bottom; } .api > tr > td { vertical-align: middle; } .sml > tr > th, .sml > tr > td { text-align: center; padding: 2px 4px; } .fn { text-align: left; } .fn > code > a { font: 14px/19px Roboto Condensed, sans-serif; } .deg45 { white-space: nowrap; background: none; border: none; vertical-align: bottom; width: 30px; altura: 83 píxeles; } .deg45 > div { transform: skew(-45deg, 0deg) translate(1px, -67px); transform-origin: bottom left 0; width: 30px; height: 20px; } .deg45 > div div > { border: 1px solid #ddd; background: #999; height: 90px; width: 42px; } .deg45 > div > div > { transform: skew(45deg, 0deg) translate(-55px, 55px) rotate(-45deg); }</estilo>
<table align="right" style="width: 0%"><thead><tr><th>Symbol</th>><Meaning</th/th></tr></thead<>tbody class=sml><tr><td>●</td td><>Supported</td></tr tr><<>td>⁕</td td>><Semantics changed</td></tr tr><<>td>○</td td Experimental support</td></tr tr<>td>><[ ]</td td>><deprecated</td></tr tr><<>td>⎋<><>/td td><>restringido al modo< de entrada de superficie/td></tr tr>><<td>⎆</td td><>restringido al modo< de salida de superficie/td></tr tr>><<td>▧</td td>><restringido al modo< de entrada ByteBuffer/td></tr tr><<>td>↩</td td>><restringido al modo< sincrónico/td></tr tr>><<td>⇄</td td>><restringido al modo< asincrónico/td></tr tr<>><td>( )</td td><>se puede llamar, pero no< debe/td></tr<>/tbody></table>
<table style="width: 100%;"><thead class=api><tr><th class=deg45 div><div style="background:#4285f4"><div>Uninitialized</div></div><></th><class=deg45><><div div><style="background:#f4b400"><div>Configured</div/div></div><></th<>class=deg45><div div><style="background:#e67c73"><div>Flushed</div/div></div><></th><class=deg45><div><style="background:#0f9d58"><div>Running</div></div/div><></th<>class=deg45><div><div style="background:#f7cb4d"><div>End of Stream</div></div/div><></th><class=deg45><div div><style="background:#db4437"><div>Error</div/div/div><></><th<>class=deg45><div><div style="background:#666"div><>Released</div/div><></div></th th><></<>th colspan="8">SDK Version</th<>/tr tr<>tr<>th colspan="7">State</th th>><Method</th><>th 16</th><>th 17</th<>th>18</th<>>th 19</><>th th 20</>><th th 21</><th th>22</º º>><23</th></tr<>/thead<>tbody class=api<>tr<>td></td<>td></td>><< td/td<>>< td/td><td></td<>>< td/td td>><</td td td><class=fn><#createByCodecName createByCodecName
/td td<>>●</td><td>●</td><td>●</td><td>●</td><td>●</td><td>●</td><td>●</td><td>●</td></tr tr><><td></td><td></td td><<>/td td><<>/td td><></td><>< td></td>< td/td td td><class=fn><#createDecoderByType createDecoderByType
/td td<>td>●</td><td>●</td><td>●</td><td>●</td><td>●</td><td>●</td><td>●</td><td>●</td></tr tr><><td></td><td></td td><<>/td td><<>/td td><></td><>< td></td>< td/td td td><class=fn><#createEncoderByType createEncoderByType
/td td<>td>●</td><td>●</td><td>●</td><td>●</td><td>●</td><td>●</td><td>●</td><td>●</td></tr><tr><td></td><td></td>><< td/td td><></><<>td td/td><>< td/<><>td td/td><td td clase=fn<>#createPersistentInputSurface createPersistentInputSurface
/td td<>></td<>td></td td><></td><><<><>>><<<><> td td/td td><td>●</td></tr tr<>td><>16+</td td<>>-</td><td>-</td>>< td-</td<>td>-</td><>-</td><td>-</td td td><class=fn><#configure configure
/td td td<>>●</td><td>●</td><td>●</td><td>●</td><td>●</td><td>⁕</td><td>●</td><td>●</td></tr><tr><td>-</td><td>18+</td<>td>-/td<>>-<</td>>< td-/td-</td><>-</td><td>-</td td td<>class=fn#createInputSurface createInputSurface
<>/td td>><</td><td></td<>td>⎋</td><td>⎋</td><td>⎋</td><td>⎋</td><td>⎋</td><td>⎋</td></tr tr><<>td>-</td><td>-</td td>><16+</td<>td>16+</td td>><(16+)</td td><>-</td><td>-</td td td><class=fn><#dequeueInputBuffer dequeueInputBuffer
/td<>td>●</td><td>●</td><td>▧</td><td>▧</td><td>▧</td><td>⁕ ▧ ↩</td><td>▧ ↩</td><td>▧ ↩</td></tr tr>><<td>-</td><td>-</td td><>16+</td><td>16+</td td><>16+</td><td>-</td<>td>-</td td><class=fn><#dequeueOutputBuffer dequeueOutputBuffer
/td<>td td>●</td><td>●</td><td>●</td><td>●</td><td>●</td><td>⁕ ↩</td><td>↩</td><td>↩</td></tr tr>><<td>-</td><td>-</td td><>16+</td><td>16+</td td><>16+</td><td>-</td<>td>-</td td><class=fn><#flush flush
/td<>td td>●</td><td>●</td><td>●</td><td>●</td><td>●</td><td>●</td><td>●</td><td>●</td></tr tr><><td>18+</td td><>18+</td<>td>18+</td td><>18+</td td><>18+</td>><18+</td td<>td>-</td td><clase=fn>#getCodecInfo getCodecInfo
</td><td></td<>><>< td>●</td><td>●</td><td>●</td><td>●</td><td>●</td><td>●</td></tr tr><<>td>-</td><td>-</td td>><(21+)</td td><>21+</td td>><(21+)</td td><>-</td><> td-</td td td><clase=fn<>#getInputBuffer getInputBuffer
/td<>td></td td><><>><>><<< td/td><td></td><td>●</td><td>●</td><td>●</td></tr><tr><td>-</td><td>-</td><td>16+</td<>td>(16+)</td td><>(16+)</td td<>>-</td><td>-</td td td><class=fn><#getInputBuffers getInputBuffers
/td td<>>●</td><td>●</td><td>●</td><td>●</td><td>●</td td><>[⁕ ↩]</td td><>[↩]</td td><>[↩]</td></tr tr><<>td>-</td td>><21+</td><td>(21+)</td<>td>(21+)</td td<>>(21+)</td>>< td-</td td><>-</td td<>clase=fn<#getInputFormat getInputFormat
>/td<>td>< td/><><<>><><><td><td></td><td>●</td><td>●</td><td>●</td/tr><tr><td>-</td><td>-</td td><>(21+)</td td<>>21+</td td>><(21+)</td><> td-</td><td>-</td td td<>clase=fn><#getInputImage getInputImage
/td td<>td></td><>><< td><<>><td></td><td></td><td>○</td><td>●</td><td>●</td></tr tr>><<td>18+</td td>><18+</td td><>18+</td td><>18+</td><td td>18+</td><td>18+</td td td><>-</td td><clase=fn>#getName getName
</td><>< td td></><td><td>●</td><td>●</td><td>●</td><td>●</td><td>●</td><td>●</td></tr tr><><td>-</td><td>-</td td><>(21+)</td td><>21+</td td>><21+</td td<>>-</td td-</td><> td td<>clase=fn><#getOutputBuffer getOutputBuffer
/td<>td td></><td><>< td></Td><td></td><td></td><td>●</td><td>●</td><td>●</td></tr tr>><<td>-</td><td>-</td td><>16+</td><td>16+</td td><>16+</td><td>-</td<>td>-</td td><class=fn><#getOutputBuffers getOutputBuffers
/td<>td td>●</td><td>●</td><td>●</td><td>●</td><td>●</td td><>[⁕ ↩]</td td><>[↩]</td td><>[↩]</td></tr tr><><td>-</td><td>21+</td td><>16+</td td>><16+</td td><td>16+</td td>><-</td>>< td-</td td><class=fn><#getOutputFormat()
/td<>td>●</td><td>●</td><td>●</td><td>●</td><td>●</td><td>●</td><td>●</td><td>●</td></tr tr><><td>-</td><td>-</td td><>(21+)</td td><>21+</td td>><21+</td td<>>-</td td-</td><> td td<>clase=fn><#getOutputFormat(int)
/td<>td td></><td><>< td></Td><td></td><td></td><td>●</td><td>●</td><td>●</td></tr tr><><td>-</td><td>-</td td><>(21+)</td td><>21+</td td>><21+</td td<>>-</td td-</td><> td td<>clase=fn><#getOutputImage getOutputImage
/td<>td td></><td><>< td></Td><td></td><td></td><td>○</td><td>●</td><td>●</td></tr tr><<>td>-</td><td>-</td><td>-</td td><>16+</td><td>(16+)</td<>td>-</td>>< td-</td td><class=fn><#queueInputBuffer queueInputBuffer
/td<>td td>●</td><td>●</td><td>●</td><td>●</td><td>●</td><td>⁕</td><td>●</td><td>●</td></tr tr><<>td>-</td><td>-</td><td>-</td td><>16+</td><td>(16+)</td<>td>-</td>>< td-</td td><class=fn><#queueSecureInputBuffer queueSecureInputBuffer
/td<>td td>●</td><td>●</td><td>●</td><td>●</td><td>●</td><td>⁕</td><td>●</td><td>●</td></tr tr<>td><>16+/td td><>16+</td><td>16+</td td<>>16+</td><td td>16+<</td<>td>16+</td td td><>16+</td><td class=fn><#release release
/td<>td>●</td><td>●</td><td>●</td><td>●</td><td>●</td><td>●</td><td>●</td><td>●</td></tr><tr><td>-</td><td>-</td><td>-</td td>><16+</td><td>16+</td><td>-</td td>><-</td td><class=fn#releaseOutputBuffer(int, boolean)
></td td><td>●</td><td>●</td><td>●</td><td>●</td><td>●</td><td>⁕</td><td>●</td><td>⁕</td/tr><tr><td>-</td><td>-</td><td>-</td td><>21+</td td><>21+</td<>td>-</td td><>-</td td td<>clase=fn>#releaseOutputBuffer(int, long)
</td><td td></><td td>><< td/td><><><td></td><td></td><td>⎆</td><td>⎆</td><td>⎆</td></tr tr>><<td>21+</td td<>>21+</td<>td>21+</td td><>21+</td><td>21+</td td<>td>21+</td td td>><-</td td><td>#reset reset
<><><><><><></Td><td></td><td></td><td>●</td><td>●</td><td>●</td></tr><tr><td>21+</td td>><-</td><td>-/td><>-<</td>>< td-/td<>> td<-</td-</td>>< td<>=fn>#setCallback(Callback) setCallback
</td td td><<>/td td>><><< td/td><><td></td><td></td><td>●</td><td>●</td><td><#setCallback(Callback, Handler) ⁕
/td></tr tr>><<td>-</td td>><23+</td td><>-</td>>< td-</td><>-/td-</td><td>-</td><> td-</td td><class=fn><#setInputSurface setInputSurface
/td<>td td/td><><td></td><td></td><td></td td><<>/td><td></td td><<>/td><td>⎋</td></tr tr>><<td>23+</td td<>>23+</td<>td>23+</td td><>23+</td td<>>23+</td td><>(23+)</td td>><(23+)</td td td<>class=fn><#setOnFrameRenderedListener setOnFrameRenderedListener
/td<>td td></td><><> td<td></td><td></td><td></td td><<>/td><td></td td>><○ ⎆</td></tr tr><><td>-</td><td>23+</td<>td>23+</td td><>23+</td td><td>23+</td td>><-</td<>td>-</td td><clase=fn><#setOutputSurface setOutputSurface
/td<>td td></td>><< td td><></Td><td></td><td></td><td></td td><></td><td>⎆</td></tr tr>><<td>19+</td td<>>19+</td<>td>19+</td td><>19+</td><>19+</td><td>(19+)</td><td>-</td td><clase=fn#setParameters setParameters
></td td<<>>>< td/td><>< td td></Td><td>●</td><td>●</td><td>●</td><td>●</td><td>●</td></tr tr><><td>-</td><td>(16+)</td td>><(16+)</td td><td>16+</td><td>(16+)</td<>td>(16+)</td<>td>-</td td><clase=fn><#setVideoScalingMode setVideoScalingMode
/td<>td>⎆</td><td>⎆</td><td>⎆</td><td>⎆</td><td>⎆</td><td>⎆</td><td>⎆</td><td>⎆</td></tr tr>><<td>(29+)/td td><>29+/td><td>29+</td><td>29+</td<>td>(29+)<</td td><>(29+<)</td<>td td>-</td td td><=fn><#setAudioPresentation setAudioPresentation
/td><td></td<>td></td><td></td><>< td/td td><<>/td td><></td td><></td td><<>/td></tr tr><><td>-</td>><-</td td><td>18+</td><td>18+</td td><td>-/td td<>-<</td>><td>-</td td<>class=fn>#signalEndOfInputStream signalEndOfInputStream
</td td><></td><td></td><td>⎋</td><td>⎋</td><td>⎋</td><td>⎋</td><td>⎋</td><td>⎋</td></tr tr><<>td>-</td td>><16+</td td<>>21+(⇄)</td td><>-</td><td>-</td td><>-</td><td>-</td td><class=fn>#start start
</td><td>●</td><td>●</td><td>●</td><td>●</td><td>●</td><td>⁕</td><td>●</td><td>●</td></tr tr>><<td>-</td><td>-</td td><>16+</td><td>16+</td td><>16+</td><td>-</td<>td>-</td td><class=fn><#stop stop
/td<>td td>●</td><td>●</td><td>●</td><td>●</td><td>●</td><td>●</td><td>●</td><td>●</td></tr></tbody></table>
Documentación de Java para android.media.MediaCodec
.
Las partes de esta página son modificaciones basadas en el trabajo creado y compartido por el proyecto de código abierto de Android y se usan según los términos descritos en la licencia de atribución de Creative Commons 2.5.
Campos
BufferFlagCodecConfig |
Obsoletos.
Esto indica que el búfer marcado como tal contiene datos específicos de códec o inicialización de códecs en lugar de datos multimedia. |
BufferFlagDecodeOnly |
Obsoletos.
Esto indica que el búfer se descodifica y actualiza el estado interno del descodificador, pero no genera ningún búfer de salida. |
BufferFlagEndOfStream |
Obsoletos.
Esto indica el final de la secuencia, i. |
BufferFlagKeyFrame |
Obsoletos.
Esto indica que el búfer (codificado) marcado como tal contiene los datos de un fotograma clave. |
BufferFlagPartialFrame |
Obsoletos.
Esto indica que el búfer solo contiene parte de un marco y el descodificador debe procesar por lotes los datos hasta que aparezca un búfer sin esta marca antes de descodificar el marco. |
BufferFlagSyncFrame |
Obsoletos.
Esto indica que el búfer (codificado) marcado como tal contiene los datos de un fotograma clave. |
ConfigureFlagEncode |
Obsoletos.
Si este códec se va a usar como codificador, pase esta marca. |
ConfigureFlagUseBlockModel |
Obsoletos.
Si se va a usar este códec con |
ConfigureFlagUseCryptoAsync |
Obsoletos.
Esta marca solo debe usarse en un descodificador seguro. |
CryptoModeAesCbc |
Obsoletos.
La clase MediaCodec se puede usar para acceder a los códecs multimedia de bajo nivel, i. |
CryptoModeAesCtr | |
CryptoModeUnencrypted | |
InfoOutputBuffersChanged |
Obsoletos.
Los búferes de salida han cambiado, el cliente debe hacer referencia al nuevo conjunto de búferes de salida devueltos por |
InfoOutputFormatChanged |
Obsoletos.
El formato de salida ha cambiado; los datos posteriores seguirán el nuevo formato. |
InfoTryAgainLater |
Obsoletos.
Si se ha especificado un tiempo de espera no negativo en la llamada a |
ParameterKeyHdr10PlusInfo |
Establezca los metadatos HDR10+ en el siguiente marco de entrada en cola. |
ParameterKeyLowLatency |
Habilite o deshabilite el modo de descodificación de baja latencia. |
ParameterKeyOffsetTime |
Especifique un desplazamiento (en micro-segundo) que se agregará encima de las marcas de tiempo en adelante. |
ParameterKeyRequestSyncFrame |
Solicite que el codificador genere un marco de sincronización "pronto". |
ParameterKeySuspend |
Suspende o reanude temporalmente la codificación de los datos de entrada. |
ParameterKeySuspendTime |
Cuando |
ParameterKeyTunnelPeek |
Controle la inspección de vídeo del primer fotograma cuando se configura un códec para el modo de túnel con |
ParameterKeyVideoBitrate |
Cambie la velocidad de bits de destino de un codificador de vídeo sobre la marcha. |
VideoScalingModeScaleToFit |
Obsoletos.
El contenido se escala a las dimensiones de la superficie. |
VideoScalingModeScaleToFitWithCropping |
Obsoletos.
El contenido se escala, manteniendo su relación de aspecto, se usa toda la superficie, se puede recortar el contenido. |
Propiedades
CanonicalName |
Recupere el nombre del códec subyacente. |
Class |
Devuelve la clase en tiempo de ejecución de este |
CodecInfo |
Obtenga la información del códec. |
Handle |
Identificador de la instancia de Android subyacente. (Heredado de Object) |
InputFormat |
Llame a esto después de |
JniIdentityHashCode |
La clase MediaCodec se puede usar para acceder a los códecs multimedia de bajo nivel, i. (Heredado de Object) |
JniPeerMembers |
La clase MediaCodec se puede usar para acceder a los códecs multimedia de bajo nivel, i. |
Metrics |
Devuelve datos de métricas sobre la instancia de códec actual. |
Name |
Recupere el nombre del códec. |
OutputFormat |
Llame a esto después de dequeueOutputBuffer indica un cambio de formato devolviendo |
PeerReference |
La clase MediaCodec se puede usar para acceder a los códecs multimedia de bajo nivel, i. (Heredado de Object) |
SupportedVendorParameters |
Devuelve una lista de nombres de parámetros de proveedor. |
ThresholdClass |
Esta API admite la infraestructura mono para Android y no está pensada para usarse directamente desde el código. (Heredado de Object) |
ThresholdType |
Esta API admite la infraestructura mono para Android y no está pensada para usarse directamente desde el código. (Heredado de Object) |
Métodos
Clone() |
Crea y devuelve una copia de este objeto. (Heredado de Object) |
Configure(MediaFormat, Surface, MediaCodecConfigFlags, MediaDescrambler) |
Configure un componente que se usará con un descrambler. |
Configure(MediaFormat, Surface, MediaCrypto, MediaCodecConfigFlags) |
Configura un componente. |
CreateByCodecName(String) |
Si conoce el nombre exacto del componente al que desea crear una instancia, use este método para crear una instancia de él. |
CreateDecoderByType(String) |
Cree una instancia del descodificador preferido que admite los datos de entrada del tipo mime especificado. |
CreateEncoderByType(String) |
Cree una instancia del codificador preferido que admite los datos de salida del tipo mime especificado. |
CreateInputSurface() |
Solicita a Surface que use como entrada para un codificador, en lugar de búferes de entrada. |
CreatePersistentInputSurface() |
Cree una superficie de entrada persistente que se pueda usar con códecs que normalmente tienen una superficie de entrada, como codificadores de vídeo. |
DequeueInputBuffer(Int64) |
Devuelve el índice de un búfer de entrada que se va a rellenar con datos válidos o -1 si no hay ningún búfer disponible actualmente. |
DequeueOutputBuffer(MediaCodec+BufferInfo, Int64) |
Desquee un búfer de salida, bloquee como máximo microsegundos "timeoutUs". |
Dispose() |
La clase MediaCodec se puede usar para acceder a los códecs multimedia de bajo nivel, i. (Heredado de Object) |
Dispose(Boolean) |
La clase MediaCodec se puede usar para acceder a los códecs multimedia de bajo nivel, i. (Heredado de Object) |
Equals(Object) |
Indica si algún otro objeto es "igual a" este. (Heredado de Object) |
Flush() |
Vaciar los puertos de entrada y salida del componente. |
GetHashCode() |
Devuelve un valor de código hash del objeto. (Heredado de Object) |
GetInputBuffer(Int32) |
Devuelve un |
GetInputBuffers() |
Obsoletos.
Recupere el conjunto de búferes de entrada. |
GetInputImage(Int32) |
Devuelve un objeto Image grabable para un índice de búfer de entrada desqueued para contener el marco de vídeo de entrada sin procesar. |
GetOutputBuffer(Int32) |
Devuelve un byteBuffer de solo lectura para un índice de búfer de salida en cola. |
GetOutputBuffers() |
Obsoletos.
Recupere el conjunto de búferes de salida. |
GetOutputFormat(Int32) |
Devuelve el formato de salida de un búfer de salida específico. |
GetOutputFrame(Int32) |
Devuelve un objeto |
GetOutputImage(Int32) |
Devuelve un objeto Image de solo lectura para un índice de búfer de salida desqueuado que contiene el marco de vídeo sin procesar. |
GetParameterDescriptor(String) |
Describir un parámetro con el nombre. |
GetQueueRequest(Int32) |
Devuelve un |
JavaFinalize() |
Lo llama el recolector de elementos no utilizados en un objeto cuando la recolección de elementos no utilizados determina que no hay más referencias al objeto . (Heredado de Object) |
MapHardwareBuffer(HardwareBuffer) |
Asigne un |
Notify() |
Activa un único subproceso que está esperando en el monitor de este objeto. (Heredado de Object) |
NotifyAll() |
Activa todos los subprocesos que están esperando en el monitor de este objeto. (Heredado de Object) |
QueueInputBuffer(Int32, Int32, Int32, Int64, MediaCodecBufferFlags) |
Después de rellenar un intervalo del búfer de entrada en el índice especificado, envíelo al componente. |
QueueSecureInputBuffer(Int32, Int32, MediaCodec+CryptoInfo, Int64, MediaCodecBufferFlags) |
Similar a |
Release() |
Libere los recursos usados por la instancia del códec. |
ReleaseOutputBuffer(Int32, Boolean) |
Si ha terminado con un búfer, use esta llamada para devolver el búfer al códec o para representarlo en la superficie de salida. |
ReleaseOutputBuffer(Int32, Int64) |
Si ha terminado con un búfer, use esta llamada para actualizar su marca de tiempo de superficie y devolverla al códec para representarla en la superficie de salida. |
Reset() |
Devuelve el códec a su estado inicial (sin inicializar). |
SetAudioPresentation(AudioPresentation) |
Establece la presentación de audio. |
SetCallback(MediaCodec+Callback) |
Establece una devolución de llamada asincrónica para eventos MediaCodec accionables en el bucle predeterminado. |
SetCallback(MediaCodec+Callback, Handler) |
Establece una devolución de llamada asincrónica para eventos MediaCodec accionables en el bucle predeterminado. |
SetHandle(IntPtr, JniHandleOwnership) |
Establece la propiedad Handle. (Heredado de Object) |
SetInputSurface(Surface) |
Configura el códec (e. |
SetOnFirstTunnelFrameReadyListener(Handler, MediaCodec+IOnFirstTunnelFrameReadyListener) |
Registra una devolución de llamada que se va a invocar cuando se ha descodificado el primer marco de salida y está listo para representarse en un códec configurado para el modo de túnel con |
SetOnFrameRenderedListener(MediaCodec+IOnFrameRenderedListener, Handler) |
Registra una devolución de llamada que se va a invocar cuando se representa un marco de salida en la superficie de salida. |
SetOutputSurface(Surface) |
Establece dinámicamente la superficie de salida de un códec. |
SetParameters(Bundle) |
Comunique los cambios de parámetro adicionales a la instancia del componente. |
SetVideoScalingMode(VideoScalingMode) |
Si se ha especificado una superficie en una llamada anterior para especificar el modo de escalado que se va a |
SignalEndOfInputStream() |
Indica el final del flujo en la entrada. |
Start() |
Después de configurar correctamente el componente, llame a |
Stop() |
Finalice la sesión de descodificación o codificación, tenga en cuenta que la instancia del códec permanece activa y lista para volver a usarse |
SubscribeToVendorParameters(IList<String>) |
Suscríbase a los parámetros del proveedor para que estos parámetros estén presentes y |
ToArray<T>() |
La clase MediaCodec se puede usar para acceder a los códecs multimedia de bajo nivel, i. (Heredado de Object) |
ToString() |
Devuelve una representación de cadena del objeto. (Heredado de Object) |
UnregisterFromRuntime() |
La clase MediaCodec se puede usar para acceder a los códecs multimedia de bajo nivel, i. (Heredado de Object) |
UnsubscribeFromVendorParameters(IList<String>) |
Cancele la suscripción a los parámetros del proveedor para que estos parámetros no estén presentes y los cambios en |
Wait() |
Hace que el subproceso actual espere hasta que se despierta, normalmente por ser em notificado/em> o <em>interrumpido</em>.<>< (Heredado de Object) |
Wait(Int64) |
Hace que el subproceso actual espere hasta que se despierte, normalmente por ser <em>notificado</em> o <em>interrumpido</em>, o hasta que haya transcurrido una cierta cantidad de tiempo real. (Heredado de Object) |
Wait(Int64, Int32) |
Hace que el subproceso actual espere hasta que se despierte, normalmente por ser <em>notificado</em> o <em>interrumpido</em>, o hasta que haya transcurrido una cierta cantidad de tiempo real. (Heredado de Object) |
Implementaciones de interfaz explícitas
IJavaPeerable.Disposed() |
La clase MediaCodec se puede usar para acceder a los códecs multimedia de bajo nivel, i. (Heredado de Object) |
IJavaPeerable.DisposeUnlessReferenced() |
La clase MediaCodec se puede usar para acceder a los códecs multimedia de bajo nivel, i. (Heredado de Object) |
IJavaPeerable.Finalized() |
La clase MediaCodec se puede usar para acceder a los códecs multimedia de bajo nivel, i. (Heredado de Object) |
IJavaPeerable.JniManagedPeerState |
La clase MediaCodec se puede usar para acceder a los códecs multimedia de bajo nivel, i. (Heredado de Object) |
IJavaPeerable.SetJniIdentityHashCode(Int32) |
La clase MediaCodec se puede usar para acceder a los códecs multimedia de bajo nivel, i. (Heredado de Object) |
IJavaPeerable.SetJniManagedPeerState(JniManagedPeerStates) |
La clase MediaCodec se puede usar para acceder a los códecs multimedia de bajo nivel, i. (Heredado de Object) |
IJavaPeerable.SetPeerReference(JniObjectReference) |
La clase MediaCodec se puede usar para acceder a los códecs multimedia de bajo nivel, i. (Heredado de Object) |
Métodos de extensión
JavaCast<TResult>(IJavaObject) |
Realiza una conversión de tipos comprobados en tiempo de ejecución de Android. |
JavaCast<TResult>(IJavaObject) |
La clase MediaCodec se puede usar para acceder a los códecs multimedia de bajo nivel, i. |
GetJniTypeName(IJavaPeerable) |
La clase MediaCodec se puede usar para acceder a los códecs multimedia de bajo nivel, i. |