Condividi tramite


MediaCodec Classe

Definizione

La classe MediaCodec può essere usata per accedere ai codec multimediali di basso livello, 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
Ereditarietà
MediaCodec
Attributi

Commenti

La classe MediaCodec può essere usata per accedere ai codec multimediali di basso livello, ad esempio i componenti codificatore/decodificatore. Fa parte dell'infrastruttura di supporto multimediale di basso livello di Android (normalmente usata insieme a MediaExtractor, MediaSync, MediaMuxer, MediaDrmMediaCrypto, Image, Surfacee AudioTrack.)

<center><img src=".. /.. /.. /images/media/mediacodec_buffers.svg" style="width: 540px; altezza: 205px" alt="Diagramma di flusso del buffer MediaCodec"></center>

In termini generali, un codec elabora i dati di input per generare dati di output. Elabora i dati in modo asincrono e usa un set di buffer di input e output. A livello semplicistico, si richiede (o si riceve) un buffer di input vuoto, lo si riempie di dati e lo si invia al codec per l'elaborazione. Il codec usa i dati e lo trasforma in uno dei buffer di output vuoti. Infine, si richiede (o si riceve) un buffer di output riempito, si utilizza il relativo contenuto e lo si rilascia nuovamente al codec.

<h3 id=quality Floor"quality Floor>">Minimum Quality Floor for Video Encoding</h3>

android.os.Build.VERSION_CODES#SA partire da , i MediaCodecs video di Android applicano un piano di qualità minimo. Lo scopo è eliminare le codifiche video di scarsa qualità. Questo piano di qualità viene applicato quando il codec è in modalità Bitrate variabile (VBR); non viene applicato quando il codec è in modalità CBR (Constant Bitrate). L'applicazione del pavimento di qualità è limitata anche a un intervallo di dimensioni particolare; questo intervallo di dimensioni è attualmente destinato alle risoluzioni video superiori a 320x240 fino a 1920x1080.

Quando questo livello di qualità è attivo, il codec e il codice del framework di supporto funzioneranno per garantire che il video generato sia di almeno una qualità "equa" o "buona". La metrica usata per scegliere queste destinazioni è la funzione VMAF (Video Multi-method Assessment Function) con un punteggio di destinazione pari a 70 per le sequenze di test selezionate.

L'effetto tipico è che alcuni video genereranno una velocità in bit superiore a quella originariamente configurata. Questo sarà più importante per i video che sono stati configurati con velocità in bit molto bassa; il codec userà una velocità in bit determinata per generare un video di qualità "fair" o "good". Un'altra situazione è dove un video include contenuti molto complicati (un sacco di movimento e dettagli); in tali configurazioni, il codec userà una velocità in bit aggiuntiva in base alle esigenze per evitare di perdere tutti i dettagli più dettagliati del contenuto.

Questo livello di qualità non influirà sul contenuto acquisito a velocità in bit elevata (una velocità in bit elevata dovrebbe già fornire al codec una capacità sufficiente per codificare tutti i dettagli). Il piano di qualità non opera sulle codifiche CBR. Il pavimento di qualità attualmente non funziona su risoluzioni di 320x240 o inferiore, né su video con risoluzione superiore a 1920x1080.

<h3>Tipi di< dati/h3>

I codec operano su tre tipi di dati: dati compressi, dati audio non elaborati e dati video non elaborati. Tutti e tre i tipi di dati possono essere elaborati usando ByteBuffer ByteBuffers, ma è consigliabile usare per Surface i dati video non elaborati per migliorare le prestazioni del codec. Surface usa buffer video nativi senza mapping o copiarli in ByteBuffers; così, è molto più efficiente. Normalmente non è possibile accedere ai dati video non elaborati quando si usa un dispositivo Surface, ma è possibile usare la ImageReader classe per accedere ai fotogrammi video non protetti (non elaborati). Questa operazione può essere ancora più efficiente rispetto all'uso di ByteBuffers, perché è possibile eseguire il mapping di alcuni buffer nativi in ByteBuffer#isDirect direct ByteBuffers. Quando si usa la modalità ByteBuffer, è possibile accedere ai fotogrammi video non elaborati usando la Image classe e/#getInputImage getInput#getOutputImage OutputImage(int) .

<h4>Compressed Buffers</h4>

I buffer di input (per decodificatori) e i buffer di output (per i codificatori) contengono dati compressi in base al tipo di formato MediaFormat#KEY_MIME. Per i tipi di video si tratta in genere di un singolo fotogramma video compresso. Per i dati audio si tratta in genere di una singola unità di accesso (un segmento audio codificato che in genere contiene alcuni millisecondi di audio come determinato dal tipo di formato), ma questo requisito è leggermente rilassato in quanto un buffer può contenere più unità di accesso codificate dell'audio. In entrambi i casi, i buffer non iniziano o terminano su limiti di byte arbitrari, ma piuttosto sui limiti dell'unità di frame/accesso, a meno che non siano contrassegnati con #BUFFER_FLAG_PARTIAL_FRAME.

<h4>buffer< audio non elaborati/h4>

I buffer audio non elaborati contengono interi fotogrammi di dati audio PCM, un esempio per ogni canale nell'ordine del canale. Ogni esempio audio PCM è un intero con segno a 16 bit o float, in ordine di byte nativo. I buffer audio non elaborati nella codifica PCM float sono possibili solo se MediaFormat#KEY_PCM_ENCODING mediaformat è impostato su AudioFormat#ENCODING_PCM_FLOAT durante MediaCodec #configure configure(&hellip;) e confermato da #getOutputFormat per decodificatori o #getInputFormat codificatori. Un metodo di esempio per verificare la presenza di PCM float in MediaFormat è il seguente:

static boolean isPcmFloat(MediaFormat format) {
               return format.getInteger(MediaFormat.KEY_PCM_ENCODING, AudioFormat.ENCODING_PCM_16BIT)
                   == AudioFormat.ENCODING_PCM_FLOAT;
             }

Per estrarre, in una matrice breve, un canale di un buffer contenente dati audio con segno a 16 bit, è possibile usare il codice seguente:

// 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 &lt; 0 || channelIx &gt;= numChannels) {
                 return null;
               }
               short[] res = new short[samples.remaining() / numChannels];
               for (int i = 0; i &lt; res.length; ++i) {
                 res[i] = samples.get(i * numChannels + channelIx);
               }
               return res;
             }

<h4>buffer< video non elaborati/h4>

I buffer video in modalità ByteBuffer vengono disposti in base al formato di colore MediaFormat#KEY_COLOR_FORMAT. È possibile ottenere i formati di colore supportati come matrice da #getCodecInfo..MediaCodecInfo#getCapabilitiesForType getCapabilitiesForType(&hellip;)CodecCapabilities#colorFormats colorFormats. I codec video possono supportare tre tipi di formati di colore: ul>li strong native raw video format:</strong> Questo è contrassegnato da CodecCapabilities#COLOR_FormatSurface e può essere usato con un oggetto Surface di input o output.<>><<</li><strong><>buffer YUV< flessibili/strong> (ad esempioCodecCapabilities#COLOR_FormatYUV420Flexible): possono essere usati con un surface di input/output, nonché in modalità ByteBuffer, usando #getInputImage getInput.</#getOutputImage OutputImage(int)/li><strong><>other, specific formats:</strong> Questi sono in genere supportati solo in modalità ByteBuffer. Alcuni formati di colore sono specifici del fornitore. Altre sono definite in CodecCapabilities. Per i formati di colore equivalenti a un formato flessibile, è comunque possibile usare #getInputImage getInput/#getOutputImage OutputImage(int).</li></ul>

Tutti i codec video supportano buffer YUV 4:2:0 flessibili a partire da android.os.Build.VERSION_CODES#LOLLIPOP_MR1.

<h4>Accesso ai bytebuffer video non elaborati nei dispositivi< meno recenti/h4>

Prima di android.os.Build.VERSION_CODES#LOLLIPOP e Image il supporto, è necessario usare i valori del MediaFormat#KEY_STRIDE formato di output e MediaFormat#KEY_SLICE_HEIGHT per comprendere il layout dei buffer di output non elaborati. <p class=nota: in> alcuni dispositivi l'altezza della sezione viene pubblicizzata come 0. Ciò potrebbe significare che l'altezza della sezione corrisponde all'altezza del fotogramma o che l'altezza del fotogramma è l'altezza del fotogramma allineata a un valore (in genere una potenza di 2). Sfortunatamente, non esiste un modo standard e semplice per indicare l'altezza effettiva della sezione in questo caso. Inoltre, lo stride verticale del U piano in formati planari non è specificato o definito, anche se in genere è metà dell'altezza della sezione.

I MediaFormat#KEY_WIDTH tasti e MediaFormat#KEY_HEIGHT specificano le dimensioni dei fotogrammi video. Tuttavia, per la maggior parte dei casi il video (immagine) occupa solo una parte del fotogramma video. Questo è rappresentato dal "rettangolo di ritaglio".

È necessario usare le chiavi seguenti per ottenere il rettangolo di ritaglio delle immagini di output non elaborate dal formato di output #getOutputFormat. Se queste chiavi non sono presenti, il video occupa l'intero fotogramma video. Il rettangolo di ritaglio viene compreso nel contesto del frame <di output em>prima</em> applicando qualsiasi rotazione MediaFormat#KEY_ROTATION. <table style="width: 0%">thead><tr<>th>Format Key</th th>><Type</th th<>>Description</th/th></tr<>/thead<>tbody><tr><td><MediaFormat#KEY_CROP_LEFT/td><td>Integer</td td Td>><La coordinata sinistra (x) del rettangolo di ritaglio</td<>/tr><tr<>td<MediaFormat#KEY_CROP_TOP>/td><td>Integer/<< td td><>La coordinata superiore (y) del rettangolo di ritaglio/td<>/tr><tr><tdMediaFormat#KEY_CROP_RIGHT></td<>td>Integer</td td td><td>La coordinata destra (x) forte meno 1/forte del rettangolo< di ritaglio</td></tr tr><><td><MediaFormat#KEY_CROP_BOTTOM/td><td>Integer</td<>td>La coordinata inferiore (y) <<>forte>MENO 1<</forte>> del rettangolo di ritaglio</td></tr tr<><>td colspan=3> Le coordinate destra e inferiore possono essere considerate come le coordinate della riga più valida della colonna più valida/inferiore dell'immagine di output ritagliata. </td></tr></tbody></table>

Le dimensioni del fotogramma video (prima della rotazione) possono essere calcolate in questo modo:

MediaFormat format = decoder.getOutputFormat(&hellip;);
             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=nota Si noti> anche che il significato di BufferInfo#offset BufferInfo.offset non era coerente tra i dispositivi. In alcuni dispositivi l'offset puntato al pixel superiore sinistro del rettangolo di ritaglio, mentre nella maggior parte dei dispositivi puntava al pixel superiore sinistro dell'intero frame.

<h3>States</h3>

Durante la sua vita esiste un codec concettualmente in uno dei tre stati: Arrestato, Esecuzione o Rilasciato. Lo stato collettivo Arrestato è in realtà il conglomerato di tre stati: Non inizializzato, Configurato ed Errore, mentre lo stato In esecuzione avanza concettualmente attraverso tre sotto-stati: Flushed, Running e End-of-Stream.

<center><img src=".. /.. /.. /images/media/mediacodec_states.svg" style="width: 519px; altezza: 356px" alt="Diagramma dello stato MediaCodec"></center>

Quando si crea un codec usando uno dei metodi factory, il codec si trova nello stato Uninitialized. Prima di tutto, è necessario configurarlo tramite #configure configure(&hellip;), che lo porta allo stato Configurato, quindi chiamare #start per spostarlo nello stato In esecuzione. In questo stato è possibile elaborare i dati tramite la manipolazione della coda del buffer descritta in precedenza.

Lo stato In esecuzione ha tre stati secondari: Flushed, Running e End-of-Stream. Immediatamente dopo #start che il codec è nello stato secondario Flushed, in cui contiene tutti i buffer. Non appena viene dequeuato il primo buffer di input, il codec passa allo stato secondario In esecuzione, dove trascorre la maggior parte della sua vita. Quando si accoda un buffer di input con il marcatore di fine flusso #BUFFER_FLAG_END_OF_STREAM, il codec passa allo stato secondario End-of-Stream. In questo stato il codec non accetta più altri buffer di input, ma genera comunque buffer di output fino a quando non viene raggiunta la fine del flusso nell'output. Per i decodificatori, è possibile tornare allo stato secondario Flushed in qualsiasi momento durante lo stato In esecuzione usando #flush. <p class=nota><>complessa:</strong> Tornare allo stato scaricato è supportato solo per i decodificatori e potrebbe non funzionare per i codificatori (il comportamento non è definito).

Chiamare #stop per restituire il codec allo stato Non inizializzato, in cui può essere nuovamente configurato. Al termine dell'uso di un codec, è necessario rilasciarlo chiamando #release.

In rari casi il codec può riscontrare un errore e passare allo stato Errore. Questa operazione viene comunicata usando un valore restituito non valido da un'operazione di accodamento o talvolta tramite un'eccezione. Chiamare #reset per rendere nuovamente utilizzabile il codec. È possibile chiamarlo da qualsiasi stato per riportare il codec allo stato Non inizializzato. In caso contrario, chiamare #release per passare allo stato rilasciato del terminale.

<h3>Creazione</h3>

Usare MediaCodecList per creare un oggetto MediaCodec per un oggetto specifico MediaFormat. Quando si decodifica un file o un flusso, è possibile ottenere il formato desiderato da MediaExtractor#getTrackFormat MediaExtractor.getTrackFormat. Inserire tutte le funzionalità specifiche che si desidera aggiungere usando MediaFormat#setFeatureEnabled MediaFormat.setFeatureEnabled, quindi chiamare MediaCodecList#findDecoderForFormat MediaCodecList.findDecoderForFormat per ottenere il nome di un codec in grado di gestire tale formato multimediale specifico. Infine, creare il codec usando #createByCodecName. <p class=note><strong>Note:</strong> On android.os.Build.VERSION_CODES#LOLLIPOP, il formato per MediaCodecList.findDecoder/EncoderForFormat non deve contenere una frequenza di fotogrammi MediaFormat#KEY_FRAME_RATE. Usare format.setString(MediaFormat.KEY_FRAME_RATE, null) per cancellare qualsiasi impostazione di frequenza dei fotogrammi esistente nel formato .

È anche possibile creare il codec preferito per un tipo MIME specifico usando #createDecoderByType createDecoder/#createEncoderByType EncoderByType(String). Ciò, tuttavia, non può essere usato per inserire funzionalità e può creare un codec che non può gestire il formato multimediale desiderato specifico.

<h4>Creazione di decodificatori< sicuri/h4>

Nelle versioni android.os.Build.VERSION_CODES#KITKAT_WATCH e versioni precedenti, i codec sicuri potrebbero non essere elencati in MediaCodecList, ma potrebbero essere ancora disponibili nel sistema. È possibile creare un'istanza di codec sicuri solo per nome, aggiungendo ".secure" al nome di un codec normale (il nome di tutti i codec sicuri deve terminare in ".secure". ) #createByCodecName genererà un'eccezione IOException se il codec non è presente nel sistema.

A partire da android.os.Build.VERSION_CODES#LOLLIPOP questo momento, è consigliabile usare la CodecCapabilities#FEATURE_SecurePlayback funzionalità nel formato multimediale per creare un decodificatore sicuro.

<inizializzazione< h3>/h3>

Dopo aver creato il codec, è possibile impostare un callback usando #setCallback setCallback se si desidera elaborare i dati in modo asincrono. Quindi, #configure configurare il codec usando il formato multimediale specifico. Questo è quando è possibile specificare l'output Surface per i producer video – codec che generano dati video non elaborati (ad esempio decodificatori video). Questo è anche quando è possibile impostare i parametri di decrittografia per i codec sicuri (vedere MediaCrypto). Infine, poiché alcuni codec possono funzionare in più modalità, è necessario specificare se si vuole che funzioni come decodificatore o codificatore.

Poiché android.os.Build.VERSION_CODES#LOLLIPOP, è possibile eseguire una query sul formato di input e output risultante nello stato Configurato. È possibile usarlo per verificare la configurazione risultante, ad esempio i formati di colore, prima di avviare il codec.

Se vuoi elaborare buffer video di input non elaborati in modo nativo con un consumer video – un codec che elabora l'input video non elaborato, ad esempio un codificatore video – creare una superficie di destinazione per i dati di input usando #createInputSurface dopo la configurazione. In alternativa, configurare il codec per usare un #createPersistentInputSurface superficie di input persistente creata in precedenza chiamando #setInputSurface.

<h4 id=CSD>"CSD">Codec-specific Data</h4>

Alcuni formati, in particolare audio AAC e MPEG4, H.264 e H.265, richiedono che i dati effettivi siano preceduti da un certo numero di buffer contenenti dati di configurazione o dati specifici del codec. Durante l'elaborazione di tali formati compressi, questi dati devono essere inviati al codec dopo #start e prima di tutti i dati dei frame. Tali dati devono essere contrassegnati usando il flag #BUFFER_FLAG_CODEC_CONFIG in una chiamata a #queueInputBuffer queueInputBuffer.

I dati specifici del codec possono essere inclusi anche nel formato passato a #configure configure nelle voci ByteBuffer con chiavi "csd-0", "csd-1" e così via. Queste chiavi sono sempre incluse nella traccia MediaFormat ottenuta da MediaExtractor#getTrackFormat MediaExtractor. I dati specifici del codec nel formato vengono inviati automaticamente al codec su #start. È necessario <<non inviare in modo esplicito questi dati in modo sicuro>>. Se il formato non contiene dati specifici del codec, è possibile scegliere di inviarlo usando il numero specificato di buffer nell'ordine corretto, in base ai requisiti di formato. Nel caso di H.264 AVC, è anche possibile concatenare tutti i dati specifici del codec e inviarli come singolo buffer di configurazione codec.

Android usa i buffer di dati specifici del codec seguenti. Queste impostazioni devono essere impostate anche nel formato di traccia per una corretta MediaMuxer configurazione della traccia. Ogni set di parametri e le sezioni di dati specifiche del codec contrassegnate con (sup*/sup>) devono iniziare con un codice iniziale di "\x00\x00\x00\x01".<><

<stile>td. NA { background: #ccc; } .mid > tr > td { vertical-align: middle; }</style><table><thead><th>Format</th th>><CSD buffer #0</th th>><CSD buffer #1</th th>><CSD buffer #2</th<>/thead><tbody class=mid><tr<>td>AAC</td td Td>><Decoder-specific information from ESDS<sup>*</sup></td 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 64-bit ByteOrder#nativeOrder native-order integer).)<br> Esegue l'override del valore di pre-skip nell'intestazione di identificazione.</td td>><Seek Pre-roll in nanosecs<br> (unsigned byteOrder#nativeOrder integer a 64 bit).</td></tr tr>><<td>FLAC</td td><>"fLaC", marcatore di flusso FLAC in ASCII,br>< seguito dal blocco STREAMINFO (blocco di metadati obbligatorio),<br> facoltativamente seguito da un numero qualsiasi di altri blocchi< di metadati/td td<>class=NA>Not Used</td td td><class=NA>Not Used</td<>/tr tr<>><td>MPEG-4</td><Td>Informazioni specifiche del decodificatore da ESDS sup*/sup></td td><class=NA>Not Used</td><td td class=NA>Not Used</td<>/tr tr><<>td>H.264 AVC</td td>><SPS (Sequence Parameter Sets<sup>*</sup>)</td td>><PPS (Picture Parameter Sets<sup>*</sup>)</td 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 td<>class=NA>Not Used/< td></tr tr>><<td>VP9</td td>><VP9 CodecPrivate Data (facoltativo)</td><td class=NA>Not Used</td<>td td class=NA>Not Used/td<>/tr tr>><<td AV1/td >><>av1< AV1CodecConfigurationRecord Data (facoltativo) </td><td class=NA>Not Used<</td><td class=NA>Not Used</td></tr></tbody></table>

<p class=nota nota forte><>Nota:</attenzione forte> deve essere preso se il codec viene scaricato immediatamente o poco dopo l'avvio, prima che venga restituita una modifica del formato di output o del buffer di output, in quanto i dati specifici del codec potrebbero andare persi durante lo scaricamento. È necessario inviare di nuovo i dati usando buffer contrassegnati con #BUFFER_FLAG_CODEC_CONFIG dopo tale scaricamento per garantire un'operazione codec appropriata.

I codificatori (o codec che generano dati compressi) creeranno e restituiranno i dati specifici del codec prima di qualsiasi buffer di output valido nei buffer di output contrassegnati con il flag codec-config #BUFFER_FLAG_CODEC_CONFIG. I buffer contenenti dati specifici del codec non hanno timestamp significativi.

<h3>Elaborazione< dati/h3>

Ogni codec gestisce un set di buffer di input e output a cui fa riferimento un ID buffer nelle chiamate API. Dopo la corretta chiamata al #start client "è proprietaria" né dei buffer di input né di output. In modalità sincrona chiamare #dequeueInputBuffer dequeueInput/#dequeueOutputBuffer OutputBuffer(&hellip;) per ottenere (ottenere la proprietà di) un buffer di input o output dal codec. In modalità asincrona si riceveranno automaticamente i buffer disponibili tramite i Callback#onInputBufferAvailable MediaCodec.Callback.onInput/Callback#onOutputBufferAvailable OutputBufferAvailable(&hellip;) callback.

Dopo aver ottenuto un buffer di input, compilarli con i dati e inviarli al codec usando #queueInputBuffer queueInputBuffer &ndash oppure #queueSecureInputBuffer queueSecureInputBuffer se si usa la decrittografia. Non inviare più buffer di input con lo stesso timestamp (a meno che non siano dati specifici del codec contrassegnati come tali).

Il codec a sua volta restituirà un buffer di output di sola lettura tramite il Callback#onOutputBufferAvailable onOutputBufferAvailable callback in modalità asincrona o in risposta a una #dequeueOutputBuffer dequeueOutputBuffer chiamata in modalità sincrona. Dopo l'elaborazione del buffer di output, chiamare uno dei #releaseOutputBuffer releaseOutputBuffer metodi per restituire il buffer al codec.

Anche se non è necessario inviare di nuovo/rilasciare buffer immediatamente al codec, tenere premuto i buffer di input e/o output potrebbe bloccare il codec e questo comportamento dipende dal dispositivo. <forte>In particolare, è possibile che un codec possa contenere la generazione di buffer di output fino a quando <i buffer in sospeso em></em> non sono stati rilasciati/restituiti.</strong> Pertanto, provare a mantenere i buffer disponibili il minor possibile.

A seconda della versione dell'API, è possibile elaborare i dati in tre modi: table>thead><tr<>th>Processing Mode</th 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>Deprecated</td></tr tr>><<td>Synchronous API using buffers</td td td><class=NA>Not Available</td<>td td>Supported/td<>/tr tr<>><td>Asynchronous API using buffers</td td<>class=NA>Not Available</td td td><>Supported<</td></tr></tbody></table ><>

<elaborazione asincrona h4>tramite buffer</h4>

Poiché android.os.Build.VERSION_CODES#LOLLIPOP, il metodo preferito consiste nell'elaborare i dati in modo asincrono impostando un callback prima di chiamare #configure configure. La modalità asincrona modifica leggermente le transizioni di stato, perché è necessario chiamare #start dopo #flush per eseguire la transizione del codec allo stato secondario In esecuzione e avviare la ricezione dei buffer di input. Analogamente, quando una chiamata iniziale al start codec passerà direttamente allo stato secondario In esecuzione e inizierà a passare i buffer di input disponibili tramite il callback.

<center><img src=".. /.. /.. /images/media/mediacodec_async_states.svg" style="width: 516px; altezza: 353px" alt="Diagramma di stato MediaCodec per l'operazione asincrona"></center>

MediaCodec viene in genere usato come segue in modalità asincrona:

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
                 &hellip;
                 codec.queueInputBuffer(inputBufferId, &hellip;);
               }

               {@literal @Override}
               void onOutputBufferAvailable(MediaCodec mc, int outputBufferId, &hellip;) {
                 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.
                 &hellip;
                 codec.releaseOutputBuffer(outputBufferId, &hellip;);
               }

               {@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(&hellip;) {
                 &hellip;
               }
               {@literal @Override}
               void onCryptoError(&hellip;) {
                 &hellip;
               }
             });
             codec.configure(format, &hellip;);
             mOutputFormat = codec.getOutputFormat(); // option B
             codec.start();
             // wait for processing to complete
             codec.stop();
             codec.release();

<h4>Elaborazione sincrona con buffer</h4>

Poiché android.os.Build.VERSION_CODES#LOLLIPOP, è necessario recuperare i buffer di input e di output usando #getInputBuffer getInput/#getOutputBuffer OutputBuffer(int) e/o #getInputImage getInput/#getOutputImage OutputImage(int) anche quando si usa il codec in modalità sincrona. Ciò consente alcune ottimizzazioni dal framework, ad esempio durante l'elaborazione di contenuto dinamico. Questa ottimizzazione è disabilitata se si chiama #getInputBuffers getInput/#getOutputBuffers OutputBuffers().

<p class=nota nota complessa><>Nota:</strong> non combinare contemporaneamente i metodi di utilizzo di buffer e matrici di buffer. In particolare, chiamare getInput/OutputBuffers direttamente dopo #start o dopo aver dequeuato un ID buffer di output con il valore di #INFO_OUTPUT_FORMAT_CHANGED.

MediaCodec viene in genere usato come segue in modalità sincrona:

MediaCodec codec = MediaCodec.createByCodecName(name);
             codec.configure(format, &hellip;);
             MediaFormat outputFormat = codec.getOutputFormat(); // option B
             codec.start();
             for (;;) {
               int inputBufferId = codec.dequeueInputBuffer(timeoutUs);
               if (inputBufferId &gt;= 0) {
                 ByteBuffer inputBuffer = codec.getInputBuffer(&hellip;);
                 // fill inputBuffer with valid data
                 &hellip;
                 codec.queueInputBuffer(inputBufferId, &hellip;);
               }
               int outputBufferId = codec.dequeueOutputBuffer(&hellip;);
               if (outputBufferId &gt;= 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.
                 &hellip;
                 codec.releaseOutputBuffer(outputBufferId, &hellip;);
               } 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();

<elaborazione sincrona h4>con matrici di buffer (deprecate)</h4>

Nelle versioni android.os.Build.VERSION_CODES#KITKAT_WATCH e precedenti, il set di buffer di input e output è rappresentato dalle ByteBuffer[] matrici. Dopo una chiamata a #start, recuperare le matrici di buffer usando #getInputBuffers getInput/#getOutputBuffers OutputBuffers(). Usare l'ID buffer come indici in queste matrici (quando non negativo), come illustrato nell'esempio seguente. Si noti che non esiste alcuna correlazione intrinseca tra le dimensioni delle matrici e il numero di buffer di input e output usati dal sistema, anche se le dimensioni della matrice forniscono un limite superiore.

MediaCodec codec = MediaCodec.createByCodecName(name);
             codec.configure(format, &hellip;);
             codec.start();
             ByteBuffer[] inputBuffers = codec.getInputBuffers();
             ByteBuffer[] outputBuffers = codec.getOutputBuffers();
             for (;;) {
               int inputBufferId = codec.dequeueInputBuffer(&hellip;);
               if (inputBufferId &gt;= 0) {
                 // fill inputBuffers[inputBufferId] with valid data
                 &hellip;
                 codec.queueInputBuffer(inputBufferId, &hellip;);
               }
               int outputBufferId = codec.dequeueOutputBuffer(&hellip;);
               if (outputBufferId &gt;= 0) {
                 // outputBuffers[outputBufferId] is ready to be processed or rendered.
                 &hellip;
                 codec.releaseOutputBuffer(outputBufferId, &hellip;);
               } 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>Gestione end-of-stream</h4>

Quando si raggiunge la fine dei dati di input, è necessario segnalarlo al codec specificando il #BUFFER_FLAG_END_OF_STREAM flag nella chiamata a #queueInputBuffer queueInputBuffer. È possibile eseguire questa operazione nell'ultimo buffer di input valido oppure inviando un buffer di input vuoto aggiuntivo con il flag end-of-stream impostato. Se si usa un buffer vuoto, il timestamp verrà ignorato.

Il codec continuerà a restituire i buffer di output fino a quando alla fine segnala la fine del flusso di output specificando lo stesso flag end-of-stream nel BufferInfo set in #dequeueOutputBuffer dequeueOutputBuffer o restituito tramite Callback#onOutputBufferAvailable onOutputBufferAvailable. Può essere impostato sull'ultimo buffer di output valido o su un buffer vuoto dopo l'ultimo buffer di output valido. Il timestamp di tale buffer vuoto deve essere ignorato.

Non inviare buffer di input aggiuntivi dopo aver segnalato la fine del flusso di input, a meno che il codec non sia stato scaricato o arrestato e riavviato.

<h4>Uso di una superficie< di output/h4>

L'elaborazione dei dati è quasi identica alla modalità ByteBuffer quando si usa un output Surface. Tuttavia, i buffer di output non saranno accessibili e sono rappresentati come null valori. Ad esempio #getOutputBuffer getOutputBuffer/#getOutputImage Image(int) , restituirà null e #getOutputBuffers restituirà una matrice contenente solo null-s.

Quando si usa un dispositivo Surface di output, è possibile scegliere se eseguire o meno il rendering di ogni buffer di output sulla superficie. Sono disponibili tre opzioni: <ul><li><strong>Non eseguire il rendering del buffer:</strong> Call #releaseOutputBuffer(int, boolean) releaseOutputBuffer(bufferId, false).</li><><strong>Eseguire il rendering del buffer con il timestamp predefinito:</strong> Call #releaseOutputBuffer(int, boolean) releaseOutputBuffer(bufferId, true).</li><><strong>Eseguire il rendering del buffer con un timestamp specifico:</strong> Call #releaseOutputBuffer(int, long) releaseOutputBuffer(bufferId, timestamp).</li></ul>

Poiché android.os.Build.VERSION_CODES#M, il timestamp predefinito è il timestamp di presentazione BufferInfo#presentationTimeUs del buffer (convertito in nanosecondi). Non è stato definito prima di questo.

Inoltre, android.os.Build.VERSION_CODES#Mpuoi modificare dinamicamente Surface di output usando #setOutputSurface setOutputSurface.

Quando si esegue il rendering dell'output in un dispositivo Surface, è possibile configurare Surface per eliminare fotogrammi eccessivi (che non vengono utilizzati in modo tempestivo da Surface). Oppure può essere configurato per non eliminare frame eccessivi. In quest'ultima modalità se Surface non utilizza fotogrammi di output abbastanza velocemente, alla fine bloccherà il decodificatore. android.os.Build.VERSION_CODES#Q Prima del comportamento esatto non è stato definito, con l'eccezione che le superfici di visualizzazione (SurfaceView o TextureView) hanno sempre eliminato fotogrammi eccessivi. Poiché android.os.Build.VERSION_CODES#Q il comportamento predefinito consiste nell'eliminare frame eccessivi. Le applicazioni possono rifiutare esplicitamente questo comportamento per le superfici non di visualizzazione (ad esempio ImageReader o SurfaceTexture) impostando l'SDK android.os.Build.VERSION_CODES#Q come destinazione e impostando la chiave MediaFormat#KEY_ALLOW_FRAME_DROP su 0 nel formato di configurazione.

<Trasformazioni h4>durante il rendering su Superficie</h4>

Se il codec è configurato in modalità Surface, qualsiasi rettangolo di ritaglio, MediaFormat#KEY_ROTATION rotazione e #setVideoScalingMode modalità di ridimensionamento video verranno applicati automaticamente con un'eccezione: <p class=nota> Prima del android.os.Build.VERSION_CODES#M rilascio, i decodificatori software potrebbero non aver applicato la rotazione quando viene eseguito il rendering in un dispositivo Surface. Sfortunatamente, non esiste un modo standard e semplice per identificare i decodificatori software o se applicano la rotazione diversa da provandola.

Ci sono anche alcune avvertenze. <p class=Nota> che le proporzioni dei pixel non vengono considerate durante la visualizzazione dell'output in Surface. Ciò significa che, se usi #VIDEO_SCALING_MODE_SCALE_TO_FIT la modalità, devi posizionare surface di output in modo che abbia le proporzioni finali dello schermo appropriate. Al contrario, è possibile usare #VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING la modalità solo per il contenuto con pixel quadrati (proporzioni pixel o 1:1). <p class=nota> Nota anche che a partire dalla android.os.Build.VERSION_CODES#N versione, #VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING la modalità potrebbe non funzionare correttamente per i video ruotati di 90 o 270 gradi. <p class=nota Quando si imposta la modalità di ridimensionamento video, si noti> che deve essere reimpostata dopo ogni modifica dei buffer di output. Poiché l'evento #INFO_OUTPUT_BUFFERS_CHANGED è deprecato, è possibile eseguire questa operazione dopo ogni modifica del formato di output.

<h4>Uso di una superficie< di input/h4>

Quando si usa una superficie di input, non ci sono buffer di input accessibili, poiché i buffer vengono passati automaticamente dalla superficie di input al codec. La chiamata #dequeueInputBuffer dequeueInputBuffer genera un oggetto e #getInputBuffers restituisce IllegalStateExceptionuna matrice fittizia ByteBuffer[] in cui <deve essere scritto l'elemento MUST NOT</strong> sicuro>.

Chiamata #signalEndOfInputStream al segnale di fine flusso. L'area di input interromperà l'invio dei dati al codec subito dopo questa chiamata.

<h3>Ricerca & Supporto< per la riproduzione adattiva/h3>

I decodificatori video (e in generale codec che utilizzano dati video compressi) si comportano in modo diverso per quanto riguarda la ricerca e il formato cambiano se supportano o meno e sono configurati per la riproduzione adattiva. È possibile verificare se un decodificatore supporta CodecCapabilities#FEATURE_AdaptivePlayback la riproduzione adattiva tramite CodecCapabilities#isFeatureSupported CodecCapabilities.isFeatureSupported(String). Il supporto per la riproduzione adattiva per i decodificatori video viene attivato solo se si configura il codec per decodificare in un oggetto Surface.

<h4 id=KeyFrames"KeyFrames>">Stream Boundary and Key Frames</h4>

È importante che i dati di input dopo #start o #flush inizino in corrispondenza di un limite di flusso appropriato: il primo fotogramma deve essere un fotogramma chiave. >Un <fotogramma< chiave em/em> può essere decodificato completamente autonomamente (per la maggior parte dei codec significa un I-frame) e nessun fotogramma da visualizzare dopo un fotogramma chiave fa riferimento ai fotogrammi prima del fotogramma chiave.

La tabella seguente riepiloga i fotogrammi chiave adatti per vari formati video. <tabella>thead><tr><th>Format</th th><>Adatta fotogramma< chiave/th<>/tr<>/thead><tbody class=mid<>tr<>td>VP9/VP8</td td><>un intraframe adatto in cui nessun frame successivo fa riferimento a fotogrammi precedenti a questo frame.<<br>(Non esiste un nome specifico per tale fotogramma chiave.</td></tr><tr><td>H.265 HEVC</td td<>>IDR o CRA</td></tr tr>><<td>H.264 AVC</td><td Td>IDR</td></tr tr>><<td>MPEG-4<br H.263<br>>MPEG-2</td td td<>>un I-frame adatto in cui nessun frame successivo fa riferimento a fotogrammi precedenti a questo frame.<br>(Non esiste un nome specifico per tale fotogramma chiave.</td></tr></tbody></table>

<h4>Per decodificatori che non supportano la riproduzione adattiva (inclusa la decodifica in un dispositivo Surface)</h4>

Per iniziare a decodificare i dati che non sono adiacenti ai dati inviati in precedenza (ad esempio dopo una ricerca) è necessario<</>forte> scaricare il decodificatore. Poiché tutti i buffer di output vengono immediatamente revocati al punto dello scaricamento, potrebbe essere necessario prima segnalare e attendere la fine del flusso prima di chiamare flush. È importante che i dati di input dopo l'avvio di uno scaricamento inizino in corrispondenza di un limite di flusso/fotogramma chiave appropriato. <p class=nota nota forte>><Nota:</strong> il formato dei dati inviati dopo una scaricamento non deve cambiare; #flush non supporta le discontinuità di formato. Per questo, è necessario un ciclo completo.#stop - #configure configure(&hellip;) - #start

<p class=nota forte><>Nota anche:</strong> se si scarica il codec troppo presto dopo #start – in genere, prima che venga ricevuta la modifica del primo buffer di output o del formato di output – sarà necessario inviare di nuovo i dati specifici del codec al codec. Per altre informazioni, vedi la sezione codec-specific-data.see the codec-specific-data section for more info.

<h4>Per decodificatori che supportano e sono configurati per la riproduzione< adattiva/h4>

Per iniziare a decodificare i dati non adiacenti ai dati inviati in precedenza (ad esempio dopo una ricerca), non è <>necessario</em> per scaricare il decodificatore. Tuttavia, i dati di input dopo la discontinuità devono iniziare in corrispondenza di un limite di flusso/fotogramma chiave appropriato.

Per alcuni formati video, ovvero H.264, H.265, VP8 e VP9, è anche possibile modificare le dimensioni dell'immagine o il flusso di configurazione a metà flusso. A tale scopo, è necessario creare un pacchetto di tutti i nuovi dati di configurazione specifici del codec insieme al fotogramma chiave in un singolo buffer (inclusi i codici iniziali) e inviarli come buffer <>di input normale</>sicuro sicuro.

Si riceverà un #INFO_OUTPUT_FORMAT_CHANGED valore restituito da #dequeueOutputBuffer dequeueOutputBuffer o un Callback#onOutputBufferAvailable onOutputFormatChanged callback subito dopo la modifica delle dimensioni dell'immagine e prima che vengano restituiti fotogrammi con le nuove dimensioni. <p class=nota nota forte><>Nota:</strong> proprio come il caso per i dati specifici del codec, prestare attenzione quando si chiama #flush poco dopo aver modificato le dimensioni dell'immagine. Se non hai ricevuto conferma della modifica delle dimensioni dell'immagine, dovrai ripetere la richiesta per le nuove dimensioni dell'immagine.

<h3>Gestione degli errori</h3>

I metodi #createByCodecName createByCodecName factory e #createDecoderByType createDecoder/#createEncoderByType EncoderByType generano IOException un errore che è necessario rilevare o dichiarare di passare. I metodi MediaCodec generano un'eccezione IllegalStateException quando il metodo viene chiamato da uno stato codec che non lo consente, in genere a causa di un utilizzo errato dell'API dell'applicazione. I metodi che coinvolgono buffer sicuri possono generare CryptoException, che contiene ulteriori informazioni sugli errori recuperabili da CryptoException#getErrorCode.

Gli errori codec interni generano un CodecExceptionoggetto , che può essere causato da danneggiamento del contenuto multimediale, errore hardware, esaurimento delle risorse e così via, anche quando l'applicazione usa correttamente l'API. L'azione consigliata quando si riceve un CodecException oggetto può essere determinata chiamando CodecException#isRecoverable e CodecException#isTransient: <ul><li><strong>recoverable errors:</strong> If isRecoverable() restituisce true, quindi chiamare #stop, #configure configure(&hellip;)e #start per il ripristino.</li><li><strong>transient errors:</strong> If isTransient() restituisce true, le risorse sono temporaneamente non disponibili e il metodo può essere ritentato in un secondo momento.</li><strong><>fatal errors:</strong> Se entrambi isRecoverable() e isTransient() restituiscono false, il CodecException valore è irreversibile e il codec deve essere #reset reset o #release rilasciato.</li></ul>

Entrambi isRecoverable() e isTransient() non restituiscono true contemporaneamente.

<h2 id=Cronologia"Cronologia>">Chiamate API valide e cronologia< API/h2>

Questa sezione riepiloga le chiamate API valide in ogni stato e la cronologia API della classe MediaCodec. Per i numeri di versione dell'API, vedere 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; width: 30px; altezza: 83 px; } .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 div > { transform: skew(45deg, 0deg) translate(-55px, 55px) rotate(-45deg); }</Stile>

<table align="right" style="width: 0%">thead<>tr><th>Symbol</th th><>Meaning</th></tr<>/thead><tbody class=sml<>tr><td>●</td td><td>Supported</td></tr><tr><td>⁕</td><td>Semantics changed</td></tr tr>><<td>○</td><td td>Experimental support</td></tr><td><<>[ ]</td td><td>Deprecato</td></tr tr<><>td>⎋</td><td td>Limitato alla modalità< di input della superficie/td></tr><tr><td>⎆</td><td>Restricted to surface output mode</td></tr><><td▧</td><> td>Restricted to ByteBuffer input mode</td></tr><<>td>↩</td><td tdRestricted>to synchronous mode/< td></tr tr><<>td>⇄</td td>limitato alla modalità< asincrona/td></tr tr><><td>( )</td><td>Può essere chiamato, ma non< deve/td><></tr/tbody><></table>

<table style="width: 100%;"><thead class=api><tr><th class=deg45><div div><style="background:#4285f4"><div>Uninitialized</div/div></div></div></th><class=deg45><div div><style="background:#f4b400"><div>Configured</div/div><></div></th th<>class=deg45><div><style="background:#e67c73"><div>Flushed</div/div></div/div><></th th><class=deg45><div><div style="background:#0f9d58"><div>Running</div></div></div></th th<>class=deg45><div div><style="background:#f7cb4d"><div>End of Stream</div></div/div/div/div><></th th<>class=deg45><div div><style="background:#db4437"><div>Error</div/div></div><></th th<>class=deg45><div><style="background:#666"><div>Rilasciatod</div></div></div></th th><></th><colspan="8">SDK Version</th<>/tr><tr<>th colspan="7">State</th th Method</>><<>th th>16</><>th 17/th 17</><th>18</th<>th>19</th>20</<>th 21<<>/th><>>22</th<>>23</th></tr<>/thead><tbody class=api><tr><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 td>●</td></tr tr><<>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<>class=fn<#createEncoderByType createEncoderByType>/td 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><>< class=fn#createPersistentInputSurface createPersistentInputSurface></td<>td td></<><>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<>/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>><<td>-</td<>td>-</td td<>>16+</td><td>16+</td><td td>(16+)</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>td<>>-</td<>td>-</td td><>16+/td td>><16+<</td td<>>16+</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>↩</td></tr tr><<>td>-</><>td<><> 16+/td><td>16+</td td>><16+<</td 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></tr><tr<>td>18+</td><td>18+</td>><td 18+</td><td></Td><td>18+</td td>><18+</td td td>><<<> class=fn><#getCodecInfo getCodecInfo/td<>td></td td></><td><td>●</td td<>>●</td><td>●</td td>><●</td><td>●</td><td>●</td<>/tr><><td>-</td><td>-</td td><>(21+)</td td>><21+</td<>td>(21+)</td><td>-</td><<> td-/td td><class=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 class=fn#getInputBuffers getInputBuffers<>/td 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><>(21+)</td td>><(21+)</td td><>(21+)</td<>td>-</td><td td<<>> class=fn><#getInputFormat getInputFormat/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><class=fn><#getInputImage getInputImage/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<>td>18+</td<<>> td><class=fn>#getName getName</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<>class=fn<#getOutputBuffer getOutputBuffer>/td><td></td<>td></td<>td></td><>< td/td><<><> td>●</td><td><●/td td><>●</td/tr<>td>>><<-</td<>td> td><>< 16+</td td<>>16+/td td 16+</td td><>16+</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><>16+</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><>●</td></tr tr<>><td>-</td td><>-</td><td>(21+)</td td>><21+/td td>><21+<</td><td>-/td td><>-<</td><td class=fn>#getOutputFormat(int)</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 class=fn#getOutputImage getOutputImage<>/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><>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></tr><tr<>td-</td><> td>-</td td>><-</td td><>16+</Td><td>(16+)</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<>/tr tr><<>td>16+/td td<>>16+<</td td><>16+</td td<>>16+</td><td>16+/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 td>16+</td td>><16+</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><td>><><-</td<>td>-</td><td>><>< 21+</td td 21+/td<>td>21+</td><td>-</td td><<>>< class=fn>#releaseOutputBuffer(int, long)</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<>>21+</td td>><21+</td<>td td<><> class=fn#reset reset<>/td><<> td td/<>><td td/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>-</td td<>class=fn><#setCallback(Callback) setCallback/td<>td></td><td></td><td></Td><td></td><td></td td><>●</td td><>●</td<>td<>#setCallback(Callback, Handler) &#8277;/td<>/tr tr>><<td>-</td td>><23+</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></tr<>tr><td>23+</td<>td>23+</td><td>23+</td td>><23+/td td>><23+<</td><td>(23+)</td><td>(23+)</td<>td class=fn><#setOnFrameRenderedListener setOnFrameRenderedListener/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>23+</td><td>-</td<>td><<> class=fn><#setOutputSurface setOutputSurface/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<>td 19+/td><td>19+</td><td>(19+)</td td><>-</td td<>class=fn>#setParameters setParameters</td td<><>/td<>td></td td><>< td<>>●</td<>td>●</td td<>>●</td<>td>●</td<>td td>●</td<>/tr><><td td>-</td td><>(16+)/td td<>>(16+)</td td><>16+</td><td>(16+)<</td><td>(16+)</td<>td> td<>< class=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<>class=fn#setAudioPresentation setAudioPresentation></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<>/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><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></tr></tbody></table <>>

Documentazione java per android.media.MediaCodec.

Le parti di questa pagina sono modifiche basate sul lavoro creato e condiviso dal Android e usato in base ai termini descritti in 2.5 Attribution License Creative Commons 2.5 Attribution License.

Campi

BufferFlagCodecConfig
Obsoleti.

Questo ha indicato che il buffer contrassegnato come tale contiene dati specifici codec/inizializzazione codec anziché dati multimediali.

BufferFlagDecodeOnly
Obsoleti.

Ciò indica che il buffer viene decodificato e aggiorna lo stato interno del decodificatore, ma non produce alcun buffer di output.

BufferFlagEndOfStream
Obsoleti.

Questo segnala la fine del flusso, i.

BufferFlagKeyFrame
Obsoleti.

Ciò indica che il buffer (codificato) contrassegnato come tale contiene i dati per un fotogramma chiave.

BufferFlagPartialFrame
Obsoleti.

Ciò indica che il buffer contiene solo parte di un frame e il decodificatore deve eseguire il batch dei dati fino a quando non viene visualizzato un buffer senza questo flag prima di decodificare il frame.

BufferFlagSyncFrame
Obsoleti.

Ciò indica che il buffer (codificato) contrassegnato come tale contiene i dati per un fotogramma chiave.

ConfigureFlagEncode
Obsoleti.

Se questo codec deve essere usato come codificatore, passare questo flag.

ConfigureFlagUseBlockModel
Obsoleti.

Se questo codec deve essere usato con LinearBlock e/o HardwareBuffer, passare questo flag.

ConfigureFlagUseCryptoAsync
Obsoleti.

Questo flag deve essere usato solo in un decodificatore sicuro.

CryptoModeAesCbc
Obsoleti.

La classe MediaCodec può essere usata per accedere ai codec multimediali di basso livello, i.

CryptoModeAesCtr
CryptoModeUnencrypted
InfoOutputBuffersChanged
Obsoleti.

I buffer di output sono stati modificati, il client deve fare riferimento al nuovo set di buffer di output restituiti da #getOutputBuffers questo punto in poi.

InfoOutputFormatChanged
Obsoleti.

Il formato di output è stato modificato, i dati successivi seguiranno il nuovo formato.

InfoTryAgainLater
Obsoleti.

Se è stato specificato un timeout non negativo nella chiamata a #dequeueOutputBuffer, indica il timeout della chiamata.

ParameterKeyHdr10PlusInfo

Impostare i metadati HDR10+ nel frame di input in coda successivo.

ParameterKeyLowLatency

Abilitare/disabilitare la modalità di decodifica a bassa latenza.

ParameterKeyOffsetTime

Specificare un offset (in micro-secondo) da aggiungere sopra i timestamp in avanti.

ParameterKeyRequestSyncFrame

Richiedere che il codificatore produca un frame di sincronizzazione "soon".

ParameterKeySuspend

Sospendere/riprendere temporaneamente la codifica dei dati di input.

ParameterKeySuspendTime

Quando #PARAMETER_KEY_SUSPEND è presente, il client può anche usare questa chiave facoltativamente per specificare il timestamp (in micro-secondo) in corrispondenza del quale l'operazione di sospensione/ripresa ha effetto.

ParameterKeyTunnelPeek

Controllare la visualizzazione video del primo fotogramma quando un codec è configurato per la modalità tunnel con mentre MediaFormat#KEY_AUDIO_SESSION_ID è AudioTrack in pausa.

ParameterKeyVideoBitrate

Modificare la velocità in bit di destinazione di un codificatore video in tempo reale.

VideoScalingModeScaleToFit
Obsoleti.

Il contenuto viene ridimensionato in base alle dimensioni della superficie

VideoScalingModeScaleToFitWithCropping
Obsoleti.

Il contenuto viene ridimensionato, mantenendo le proporzioni, viene usata l'intera superficie di attacco, il contenuto può essere ritagliato.

Proprietà

CanonicalName

Recuperare il nome del codec sottostante.

Class

Restituisce la classe di runtime di questo Objectoggetto .

(Ereditato da Object)
CodecInfo

Ottenere le informazioni sul codec.

Handle

Handle per l'istanza di Android sottostante.

(Ereditato da Object)
InputFormat

Chiama questa operazione dopo #configure che viene restituito correttamente per ottenere il formato di input accettato dal codec.

JniIdentityHashCode

La classe MediaCodec può essere usata per accedere ai codec multimediali di basso livello, i.

(Ereditato da Object)
JniPeerMembers

La classe MediaCodec può essere usata per accedere ai codec multimediali di basso livello, i.

Metrics

Restituisce i dati delle metriche sull'istanza codec corrente.

Name

Recuperare il nome del codec.

OutputFormat

Chiamare questa operazione dopo che dequeueOutputBuffer segnala una modifica del formato restituendo #INFO_OUTPUT_FORMAT_CHANGED.

PeerReference

La classe MediaCodec può essere usata per accedere ai codec multimediali di basso livello, i.

(Ereditato da Object)
SupportedVendorParameters

Restituisce un elenco di nomi di parametri fornitore.

ThresholdClass

Questa API supporta l'infrastruttura Mono per Android e non deve essere usata direttamente dal codice.

(Ereditato da Object)
ThresholdType

Questa API supporta l'infrastruttura Mono per Android e non deve essere usata direttamente dal codice.

(Ereditato da Object)

Metodi

Clone()

Crea e restituisce una copia di questo oggetto.

(Ereditato da Object)
Configure(MediaFormat, Surface, MediaCodecConfigFlags, MediaDescrambler)

Configurare un componente da usare con un descrambler.

Configure(MediaFormat, Surface, MediaCrypto, MediaCodecConfigFlags)

Configura un componente.

CreateByCodecName(String)

Se si conosce il nome esatto del componente di cui si vuole creare un'istanza, usare questo metodo per crearne un'istanza.

CreateDecoderByType(String)

Creare un'istanza del decodificatore preferito che supporta i dati di input del tipo MIME specificato.

CreateEncoderByType(String)

Creare un'istanza del codificatore preferito che supporta i dati di output del tipo MIME specificato.

CreateInputSurface()

Richiede a Surface di usare come input a un codificatore, al posto dei buffer di input.

CreatePersistentInputSurface()

Creare una superficie di input persistente che può essere usata con codec che in genere hanno una superficie di input, ad esempio codificatori video.

DequeueInputBuffer(Int64)

Restituisce l'indice di un buffer di input da riempire con dati validi o -1 se tale buffer non è attualmente disponibile.

DequeueOutputBuffer(MediaCodec+BufferInfo, Int64)

Annullare la coda di un buffer di output, bloccando al massimo i microsecondi "timeoutUs".

Dispose()

La classe MediaCodec può essere usata per accedere ai codec multimediali di basso livello, i.

(Ereditato da Object)
Dispose(Boolean)

La classe MediaCodec può essere usata per accedere ai codec multimediali di basso livello, i.

(Ereditato da Object)
Equals(Object)

Indica se un altro oggetto è "uguale a" questo.

(Ereditato da Object)
Flush()

Scaricare sia le porte di input che di output del componente.

GetHashCode()

Restituisce un valore del codice hash per l'oggetto.

(Ereditato da Object)
GetInputBuffer(Int32)

Restituisce un java.nio.Buffer#clear clearedoggetto ByteBuffer scrivibile per un indice del buffer di input dequeued che contiene i dati di input.

GetInputBuffers()
Obsoleti.

Recuperare il set di buffer di input.

GetInputImage(Int32)

Restituisce un oggetto Image scrivibile per un indice del buffer di input dequeued che contiene il frame video di input non elaborato.

GetOutputBuffer(Int32)

Restituisce un ByteBuffer di sola lettura per un indice del buffer di output dequeued.

GetOutputBuffers()
Obsoleti.

Recuperare il set di buffer di output.

GetOutputFormat(Int32)

Restituisce il formato di output per un buffer di output specifico.

GetOutputFrame(Int32)

Restituisce un oggetto OutputFrame.

GetOutputImage(Int32)

Restituisce un oggetto Image di sola lettura per un indice del buffer di output dequeued che contiene il frame video non elaborato.

GetParameterDescriptor(String)

Descrivere un parametro con il nome.

GetQueueRequest(Int32)

Restituisce un oggetto per un QueueRequest indice dello slot di input.

JavaFinalize()

Chiamato dal Garbage Collector su un oggetto quando Garbage Collection determina che non sono presenti altri riferimenti all'oggetto .

(Ereditato da Object)
MapHardwareBuffer(HardwareBuffer)

Eseguire il mapping di un HardwareBuffer oggetto in Imagein modo che il contenuto del buffer sia accessibile.

Notify()

Riattiva un singolo thread in attesa del monitor dell'oggetto.

(Ereditato da Object)
NotifyAll()

Riattiva tutti i thread in attesa del monitoraggio di questo oggetto.

(Ereditato da Object)
QueueInputBuffer(Int32, Int32, Int32, Int64, MediaCodecBufferFlags)

Dopo aver compilato un intervallo del buffer di input in corrispondenza dell'indice specificato, inviarlo al componente.

QueueSecureInputBuffer(Int32, Int32, MediaCodec+CryptoInfo, Int64, MediaCodecBufferFlags)

Simile a #queueInputBuffer queueInputBuffer ma invia un buffer potenzialmente crittografato.

Release()

Liberare le risorse usate dall'istanza del codec.

ReleaseOutputBuffer(Int32, Boolean)

Se hai finito con un buffer, usa questa chiamata per restituire il buffer al codec o per eseguirne il rendering nell'area di output.

ReleaseOutputBuffer(Int32, Int64)

Se hai finito con un buffer, usa questa chiamata per aggiornare il timestamp di superficie e restituirlo al codec per eseguirne il rendering nell'area di output.

Reset()

Restituisce il codec allo stato iniziale (non inizializzato).

SetAudioPresentation(AudioPresentation)

Imposta la presentazione audio.

SetCallback(MediaCodec+Callback)

Imposta un callback asincrono per gli eventi MediaCodec interattivi nel looper predefinito.

SetCallback(MediaCodec+Callback, Handler)

Imposta un callback asincrono per gli eventi MediaCodec interattivi nel looper predefinito.

SetHandle(IntPtr, JniHandleOwnership)

Imposta la proprietà Handle.

(Ereditato da Object)
SetInputSurface(Surface)

Configura il codec (e.

SetOnFirstTunnelFrameReadyListener(Handler, MediaCodec+IOnFirstTunnelFrameReadyListener)

Registra un callback da richiamare quando il primo frame di output è stato decodificato ed è pronto per il rendering su un codec configurato per la modalità tunnel con KEY_AUDIO_SESSION_ID.

SetOnFrameRenderedListener(MediaCodec+IOnFrameRenderedListener, Handler)

Registra un callback da richiamare quando viene eseguito il rendering di un frame di output nell'area di output.

SetOutputSurface(Surface)

Imposta dinamicamente la superficie di output di un codec.

SetParameters(Bundle)

Comunicare modifiche aggiuntive ai parametri all'istanza del componente.

SetVideoScalingMode(VideoScalingMode)

Se è stata specificata una superficie in una chiamata precedente per #configure specificare la modalità di ridimensionamento da usare.

SignalEndOfInputStream()

Segnala la fine del flusso sull'input.

Start()

Dopo aver configurato correttamente il componente, chiamare start.

Stop()

Completare la sessione di decodifica/codifica. Si noti che l'istanza del codec rimane attiva e pronta per essere #startnuovamente terminata.

SubscribeToVendorParameters(IList<String>)

Sottoscrivere i parametri del fornitore, in modo che questi parametri siano presenti in #getOutputFormat e le modifiche apportate a questi parametri generino l'evento di modifica del formato di output.

ToArray<T>()

La classe MediaCodec può essere usata per accedere ai codec multimediali di basso livello, i.

(Ereditato da Object)
ToString()

Restituisce una rappresentazione in formato stringa dell'oggetto.

(Ereditato da Object)
UnregisterFromRuntime()

La classe MediaCodec può essere usata per accedere ai codec multimediali di basso livello, i.

(Ereditato da Object)
UnsubscribeFromVendorParameters(IList<String>)

Annullare la sottoscrizione ai parametri del fornitore, in modo che questi parametri non siano presenti in #getOutputFormat e le modifiche apportate a questi parametri non generino più l'evento di modifica del formato di output.

Wait()

Fa sì che il thread corrente attenda finché non viene risvegliato, in genere eseguendo <una>notifica</em> o <em>interrotto</em>.

(Ereditato da Object)
Wait(Int64)

Fa sì che il thread corrente attenda finché non viene risvegliato, in genere eseguendo <una notifica</>em> o <em>interrotto</em> o fino a quando non è trascorsa una certa quantità di tempo reale.

(Ereditato da Object)
Wait(Int64, Int32)

Fa sì che il thread corrente attenda finché non viene risvegliato, in genere eseguendo <una notifica</>em> o <em>interrotto</em> o fino a quando non è trascorsa una certa quantità di tempo reale.

(Ereditato da Object)

Implementazioni dell'interfaccia esplicita

IJavaPeerable.Disposed()

La classe MediaCodec può essere usata per accedere ai codec multimediali di basso livello, i.

(Ereditato da Object)
IJavaPeerable.DisposeUnlessReferenced()

La classe MediaCodec può essere usata per accedere ai codec multimediali di basso livello, i.

(Ereditato da Object)
IJavaPeerable.Finalized()

La classe MediaCodec può essere usata per accedere ai codec multimediali di basso livello, i.

(Ereditato da Object)
IJavaPeerable.JniManagedPeerState

La classe MediaCodec può essere usata per accedere ai codec multimediali di basso livello, i.

(Ereditato da Object)
IJavaPeerable.SetJniIdentityHashCode(Int32)

La classe MediaCodec può essere usata per accedere ai codec multimediali di basso livello, i.

(Ereditato da Object)
IJavaPeerable.SetJniManagedPeerState(JniManagedPeerStates)

La classe MediaCodec può essere usata per accedere ai codec multimediali di basso livello, i.

(Ereditato da Object)
IJavaPeerable.SetPeerReference(JniObjectReference)

La classe MediaCodec può essere usata per accedere ai codec multimediali di basso livello, i.

(Ereditato da Object)

Metodi di estensione

JavaCast<TResult>(IJavaObject)

Esegue una conversione del tipo verificato dal runtime Android.

JavaCast<TResult>(IJavaObject)

La classe MediaCodec può essere usata per accedere ai codec multimediali di basso livello, i.

GetJniTypeName(IJavaPeerable)

La classe MediaCodec può essere usata per accedere ai codec multimediali di basso livello, i.

Si applica a