Поделиться через


MediaCodec Класс

Определение

Класс MediaCodec можно использовать для доступа к кодекам мультимедиа низкого уровня, 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
Наследование
MediaCodec
Атрибуты

Комментарии

Класс MediaCodec можно использовать для доступа к низкоуровневым кодекам мультимедиа, т. е. компонентам кодировщика или декодировщика. Она входит в инфраструктуру поддержки мультимедиа android низкого уровня (обычно используется вместе с MediaExtractor, MediaSync, MediaDrmMediaCryptoImageMediaMuxerSurfaceи AudioTrack.)

<center><img src=".. /.. /.. /images/media/mediacodec_buffers.svg" style="width: 540px; height: 205px" alt="Схема потока буфера MediaCodec"></center>

В целом кодек обрабатывает входные данные для создания выходных данных. Он обрабатывает данные асинхронно и использует набор входных и выходных буферов. На упрощенном уровне вы запрашиваете (или получаете) пустой входной буфер, заполняете его данными и отправляете его в кодек для обработки. Кодек использует данные и преобразует его в один из его пустых выходных буферов. Наконец, вы запрашиваете (или получаете) заполненный выходной буфер, используете его содержимое и освобождаете его обратно в кодек.

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

Начиная с android.os.Build.VERSION_CODES#S, Видеокодеки Android применяют минимальный уровень качества. Цель состоит в том, чтобы исключить кодирование видео низкого качества. Этот пол качества применяется, если кодек находится в режиме переменной скорости (VBR); Он не применяется, если кодек находится в режиме константной скорости (CBR). Применение качества пола также ограничено определенным диапазоном размеров; Этот диапазон размеров в настоящее время предназначен для разрешения видео размером более 320x240 до 1920x1080.

Если этот уровень качества действует, кодек и вспомогательный код платформы будут работать, чтобы гарантировать, что созданное видео имеет по крайней мере "справедливое" или "хорошее" качество. Метрика, используемая для выбора этих целевых объектов, представляет собой функцию vmAF (функция оценки с несколькими способами видео) с целевой оценкой 70 для выбранных последовательностей тестов.

Типичный эффект заключается в том, что некоторые видео будут создавать более высокую скорость, чем первоначально настроено. Это будет наиболее заметным для видео, которые были настроены с очень низкими скоростями; Кодек будет использовать скорость, которая определяется, что более вероятно, чтобы создать "справедливое" или "хорошее" качество видео. Другая ситуация заключается в том, что видео содержит очень сложное содержимое (много движения и детали); в таких конфигурациях кодек будет использовать дополнительную скорость при необходимости, чтобы избежать потери всех подробных сведений содержимого.

Этот пол качества не влияет на содержимое, захваченное на высоких скоростях (высокая скорость уже должна обеспечить кодек достаточной емкостью для кодирования всех деталей). Уровень качества не работает с кодировками CBR. Уровень качества в настоящее время не работает на разрешениях 320x240 или ниже, а также на видео с разрешением выше 1920x1080.

<h3 Типы< данных/h3>>

Кодеки работают с тремя типами данных: сжатыми данными, необработанными звуковыми данными и необработанными данными видео. Все три типа данных можно обрабатывать с помощью ByteBuffer ByteBuffers, но для необработанных видеоданных следует использовать Surface для повышения производительности кодека. Surface использует собственные буферы видео без сопоставления или копирования их в ByteBuffers; таким образом, это гораздо эффективнее. Обычно вы не можете получить доступ к необработанным видеоданных при использовании Surface, но вы можете использовать ImageReader класс для доступа к незащищенным декодированных (необработанных) видеокадров. Это может быть более эффективным, чем использование ByteBuffers, так как некоторые собственные буферы могут быть сопоставлены с ByteBuffer#isDirect direct ByteBuffers. При использовании режима ByteBuffer можно получить доступ к необработанным видеокадрам с помощью Image класса и/#getInputImage getInput#getOutputImage OutputImage(int) .

<h4>Сжатые буферы</h4>

Входные буферы (для декодеров) и выходных буферов (для кодировщиков) содержат сжатые данные в соответствии с типом формата MediaFormat#KEY_MIME. Для типов видео обычно это один сжатый видеокадр. Для звуковых данных это обычно один блок доступа (кодированный звуковой сегмент, который обычно содержит несколько миллисекундах звука в зависимости от типа формата), но это требование немного расслаблено в том, что буфер может содержать несколько закодированных единиц доступа звука. В любом случае буферы не начинаются или заканчиваются произвольными границами байтов, а вместо границ единиц кадра или доступа, если они не помечены.#BUFFER_FLAG_PARTIAL_FRAME

<H4>Необработанные буферы< звука/h4>

Необработанные звуковые буферы содержат целые кадры звуковых данных PCM, которые являются одним примером для каждого канала в порядке канала. Каждый образец звука PCM представляет собой 16-разрядное целое число со знаком или плавающее значение в собственном порядке байтов. Необработанные звуковые буферы в кодировке с плавающей запятой PCM возможны только в том случае, если для mediaFormat#KEY_PCM_ENCODING задано значение AudioFormat#ENCODING_PCM_FLOAT во время MediaCodec #configure configure(&hellip;) и подтверждено #getOutputFormat декодировщиками или #getInputFormat кодировщиками. Пример метода проверки с плавающей запятой PCM в MediaFormat выглядит следующим образом:

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

Для извлечения в коротком массиве одного канала буфера, содержащего 16-разрядные целочисленные звуковые данные со знаком, можно использовать следующий код:

// 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>Необработанные буферы< видео/h4>

В буферах видеотрансляции режима ByteBuffer размещаются в соответствии с форматом цвета MediaFormat#KEY_COLOR_FORMAT. Поддерживаемые форматы цветов можно получить в #getCodecInfo..MediaCodecInfo#getCapabilitiesForType getCapabilitiesForType(&hellip;)CodecCapabilities#colorFormats colorFormatsвиде массива. Видеокодеки могут поддерживать три типа цветовых форматов: <ul><li><strong>native raw video format:</strong> Это отмечено CodecCapabilities#COLOR_FormatSurface и может использоваться с входными или выходными данными Surface.</li>><<strong>гибкие буферы< YUV/strong> (напримерCodecCapabilities#COLOR_FormatYUV420Flexible: ): они могут использоваться с входными и выходными данными Surface, а также в режиме ByteBuffer с помощью#getInputImage getInput.</#getOutputImage OutputImage(int)/li><li><strong>other, определенные форматы:</strong> Они обычно поддерживаются только в режиме ByteBuffer. Некоторые форматы цветов зависят от поставщика. Другие определяются в CodecCapabilities. Для цветовых форматов, эквивалентных гибкому формату, можно по-прежнему использовать #getInputImage getInput/#getOutputImage OutputImage(int).</li></ul>

Все видеокодеки поддерживают гибкие буферы YUV 4:2:0 с тех пор android.os.Build.VERSION_CODES#LOLLIPOP_MR1.

<h4>Доступ к необработанным видео byteBuffers на старых устройствах</h4>

android.os.Build.VERSION_CODES#LOLLIPOP Прежде чем и Image поддерживать, необходимо использовать MediaFormat#KEY_STRIDE значения формата и MediaFormat#KEY_SLICE_HEIGHT выходных данных, чтобы понять макет необработанных выходных буферов. <p class=note Обратите внимание> , что на некоторых устройствах высота среза объявляется как 0. Это может означать, что высота среза совпадает с высотой кадра или что высота среза — это высота кадра, выравниваемая на некоторое значение (обычно значение 2). К сожалению, нет стандартного и простого способа сказать фактическую высоту среза в этом случае. Кроме того, вертикальный шаг U плоскости в планарных форматах также не указан или не определен, хотя обычно это половина высоты среза.

Ключи MediaFormat#KEY_WIDTHMediaFormat#KEY_HEIGHT указывают размер видеокадров, однако для большинства элементов видео (рисунок) занимает только часть видеокадры. Это представлено прямоугольником обрезки.

Для получения прямоугольника обрезки необработанных выходных изображений из формата выходных данных #getOutputFormat необходимо использовать следующие ключи. Если эти ключи отсутствуют, видео занимает весь кадр видео. Прямоугольник обрезки понятен в контексте выходного кадра <em>перед< применением> любого поворота MediaFormat#KEY_ROTATION. <table style="width: 0%"><thead<>tr th Format Key</<>>th>Type</>><th Description/th Description</><th/tr></thead><tbody<>tr><><td><MediaFormat#KEY_CROP_LEFT/td td>integer/><><>td td The left-координата (x) прямоугольника<>< обрезки/td/tr tr<<>MediaFormat#KEY_CROP_TOP>>< td/><td/td integer/<>< td td td>Top-координата (y) прямоугольника< обрезки/td/tr tr><<>><MediaFormat#KEY_CROP_RIGHT td<>/td td integer</<>>>><td справа координата (x) сильный>МИНУС 1/сильный прямоугольник обрезки</td<>/tr<>MediaFormat#KEY_CROP_BOTTOM><>< td/<>td td>integer</<>>td снизу координаты (y) <<сильный>> МИНУС 1<</strong><> прямоугольника обрезки</td/tr tr><<>td>< colspan=3> Правые и нижние координаты можно понять как координаты правого допустимого столбца или нижней допустимой строки обрезанного выходного изображения. </td></tr></tbody></table>

Размер кадра видео (перед поворотом) можно вычислить следующим образом:

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=note Также обратите> внимание, что значение BufferInfo#offset BufferInfo.offset не согласовано на разных устройствах. На некоторых устройствах смещение указывает на верхний левый пиксель прямоугольника обрезки, в то время как на большинстве устройств он указал на верхний левый пиксель всего кадра.

<h3 States</h3>>

В течение всего существования кодека концептуально существует в одном из трех состояний: остановлено, выполнено или освобождено. Остановленное коллективное состояние — это на самом деле конгломерация трех состояний: неинициализированная, настроенная и ошибка, в то время как состояние выполнения концептуально выполняется через три вложенных состояния: Flushed, Выполнение и завершение потока.

<center><img src=".. /.. /.. /images/media/mediacodec_states.svg" style="width: 519px; height: 356px" alt="Схема состояния MediaCodec"></center>

При создании кодека с помощью одного из методов фабрики кодек находится в неинициализированном состоянии. Сначала необходимо настроить его с помощью #configure configure(&hellip;), который переносит его в настроенное состояние, а затем вызов #start , чтобы переместить его в состояние выполнения. В этом состоянии можно обрабатывать данные с помощью манипуляции с буферной очередью, описанной выше.

Состояние выполнения содержит три вложенных состояния: Flushed, Выполнение и завершение потока. Сразу после того, как #start кодек находится в подзаготовке Flushed, где он содержит все буферы. Как только первый входной буфер удаляется, кодек перемещается в под-состояние "Выполнение", где он проводит большую часть своей жизни. При очереди входного буфера с маркером #BUFFER_FLAG_END_OF_STREAM маркера конца потока кодек переходит в подчиненное состояние End-of-Stream. В этом состоянии кодек больше не принимает дополнительные входные буферы, но по-прежнему создает выходные буферы до тех пор, пока не будет достигнут конец потока в выходных данных. Для декодеров вы можете вернуться к подзаготовке в любое время во время выполнения в состоянии выполнения.#flush <p class=note><strong>Note:</strong> Back to Flushed state поддерживается только для декодеров и может не работать для кодировщиков (поведение не определено).

Вызов для #stop возврата кодека в неинициализированное состояние, где он может быть настроен снова. Когда вы закончите использовать кодек, его необходимо освободить путем вызова #release.

В редких случаях кодек может столкнуться с ошибкой и перейти к состоянию ошибки. Это сообщается с помощью недопустимого возвращаемого значения из операции очереди или иногда с помощью исключения. Вызов #reset для повторного использования кодека. Его можно вызвать из любого состояния, чтобы переместить кодек обратно в неинициализированное состояние. В противном случае вызов для #release перемещения в состояние выпуска терминала.

<h3 Создание</h3>>

Используется MediaCodecList для создания MediaCodec для определенного MediaFormatобъекта. При декодировании файла или потока можно получить нужный формат MediaExtractor#getTrackFormat MediaExtractor.getTrackFormat. Введите все определенные функции, которые необходимо добавить с помощью MediaFormat#setFeatureEnabled MediaFormat.setFeatureEnabled, а затем вызовите MediaCodecList#findDecoderForFormat MediaCodecList.findDecoderForFormat имя кодека, который может обрабатывать этот конкретный формат мультимедиа. Наконец, создайте кодек с помощью #createByCodecName. <p class=note><strong>Note:</strong> On android.os.Build.VERSION_CODES#LOLLIPOP, формат, который MediaCodecList.findDecoder/EncoderForFormat не должен содержать частоту кадров MediaFormat#KEY_FRAME_RATE. Используется format.setString(MediaFormat.KEY_FRAME_RATE, null) для очистки любого существующего параметра частоты кадров в формате.

Вы также можете создать предпочтительный кодек для определенного типа MIME с помощью #createDecoderByType createDecoder/#createEncoderByType EncoderByType(String). Однако это не может использоваться для внедрения функций и может создавать кодек, который не может обрабатывать конкретный нужный формат мультимедиа.

<h4>Создание безопасных декодеров</h4>

В версиях и более ранних версиях защищенные android.os.Build.VERSION_CODES#KITKAT_WATCH кодеки могут не отображаться в MediaCodecListсистеме, но по-прежнему могут быть доступны в системе. Защищенные кодеки, которые существуют, могут быть созданы только по имени, добавив ".secure" к имени регулярного кодека (имя всех защищенных кодеков должно заканчиваться в ".secure".) #createByCodecName вызовет IOException исключение, если кодек отсутствует в системе.

Далее android.os.Build.VERSION_CODES#LOLLIPOP следует использовать CodecCapabilities#FEATURE_SecurePlayback функцию в формате мультимедиа для создания безопасного декодатора.

<h3 Initialization</h3>>

После создания кодека можно задать обратный вызов, используя, #setCallback setCallback если требуется асинхронно обрабатывать данные. Затем #configure настроить кодек с помощью определенного формата мультимедиа. Это происходит, когда можно указать выходные данные Surface для производителей видео – кодеков, которые создают необработанные данные видео (например, декодеры видео). Это также происходит при настройке параметров расшифровки для защищенных кодеков (см. раздел MediaCrypto). Наконец, так как некоторые кодеки могут работать в нескольких режимах, необходимо указать, будет ли он работать в качестве декодера или кодировщика.

Так как android.os.Build.VERSION_CODES#LOLLIPOPвы можете запросить результирующий формат входных и выходных данных в настроенном состоянии. Это можно использовать для проверки результирующей конфигурации, например цветовых форматов, перед запуском кодека.

Если вы хотите обрабатывать необработанные входные буферы видео в собственном коде с помощью потребителя видео – кодек, обрабатывающий необработанные входные видео, например кодировщик видео – создайте целевую поверхность для входных данных, используя #createInputSurface после настройки. Кроме того, настройте кодек для использования ранее созданной #createPersistentInputSurface постоянной входной области путем вызова #setInputSurface.

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

Некоторые форматы, в частности аудио-форматы AAC и MPEG4, H.264 и H.265, требуют, чтобы фактические данные были префиксированы рядом буферов, содержащих данные установки или определенные данные кодека. При обработке таких сжатых форматов эти данные должны быть отправлены в кодек после #start и перед любыми данными кадра. Эти данные должны быть помечены с помощью флага #BUFFER_FLAG_CODEC_CONFIG в вызове #queueInputBuffer queueInputBuffer.

Данные, относящиеся к коде, также могут быть включены в формат, передаваемый #configure configure в записи ByteBuffer с ключами csd-0, csd-1 и т. д. Эти ключи всегда включаются в дорожку MediaFormat , полученную из MediaExtractor#getTrackFormat MediaExtractor. Данные, относящиеся к кодеку в формате, автоматически передаются в кодек#start; <><> необходимо явно отправить эти данные. Если формат не содержал определенных данных кодека, его можно отправить с помощью указанного количества буферов в правильном порядке в соответствии с требованиями к формату. В случае H.264 AVC можно также объединить все данные, относящиеся к кодеку, и отправить его в виде одного буфера конфигурации codec-config.

Android использует следующие буферы данных для кодека. Они также должны быть заданы в формате отслеживания для правильной MediaMuxer настройки отслеживания. Каждый набор параметров и разделы данных для кодека, помеченные как< (sup>*</sup>), должны начинаться с начального "\x00\x00\x00\x01"кода.

<стиль>td. NA { фон: #ccc; } .mid > tr > td { вертикальное выравнивание: середина; }</style table><, thead<>th>Format</th<>th>CSD buffer #0</>><th CSD buffer #1</><>th th CSD buffer #2</><th/thead><tbody class=mid<>trd><>AAC</<>>td decoder-specific information from ESDS<sup>*</sup></<>td class=NA>Not Used</<>td td class=NA Not Usedd class=NA>Not Used><</td></tr tr><><td>VORBIS</td td>Identity< header/><td td Setup header</>><<>td td class=NA>Not Used</><td/tr>><<>td OPUS</td td identity header</>>><<>td pre-skip in nanosecs<br> (unsigned 64-bit ByteOrder#nativeOrder native-order integer.)<br> Это переопределяет значение предварительного пропуска в заголовке идентификации.</td td>><seek Pre-roll in nanosecs<br> (unsigned 64-bit ByteOrder#nativeOrder native-order integer).)</td></tr<>><td FLAC</td<>td>>"fLaC", маркер потока FLAC в ASCII,br><, за которым следует блок STREAMINFO (обязательный блок метаданных),<br> необязательно, за которым следует любое количество других блоков< метаданных/td<>td class=NA Not Used/td td class=>NA>Not Used<</<<>>td/tr<>><td>mpeg-4</td><td>Сведения о декодировщике из ESDS<sup*</sup><>/td td><class=NA Not Used</<>td td class=>NA>Not Used</td/<>tr tr><<>>td H.264 AVC</td<>td>SPS (последовательные наборы<> параметров sup*</sup)/>><td PPS (наборы<параметров рисунка 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=NA>Not Used/<<< td></tr tr>><<td VP9/td td><>>VP9 <CodecPrivate Data (необязательно)</><td td class=NA>Not Used</<>td td class=NA>Not< Used/td<>/tr>><><td AV1/td td>av1CodecConfigurationRecord<<> Data (необязательно) </td<>class=NA>Not Used/< td td><class=NA>Not Used</td></tr<>/tbody></table>

<p class=note><strong>Note:</strong> care be care beered if the codec flushed немедленно или вскоре после начала, прежде чем будет возвращен любой выходной буфер или выходной формат изменения, так как конкретные данные кодека могут быть потеряны во время очистки. Необходимо повторно отправить данные с помощью буферов, #BUFFER_FLAG_CODEC_CONFIG помеченных после такого сброса, чтобы обеспечить правильную операцию кодека.

Кодировщики (или кодеки, создающие сжатые данные) будут создавать и возвращать определенные данные кодека до того, как любой допустимый выходной буфер в выходных буферах помечается флагом конфигурации #BUFFER_FLAG_CODEC_CONFIG codec-config. Буферы, содержащие данные, относящиеся к кодеку, не имеют значимых меток времени.

<h3>Data Processing</h3>

Каждый кодек поддерживает набор входных и выходных буферов, которые называются идентификатором буфера в вызовах API. После успешного вызова #start клиента "владеет" ни входными, ни выходными буферами. В синхронном режиме вызовите #dequeueInputBuffer dequeueInput/#dequeueOutputBuffer OutputBuffer(&hellip;) получение (получение владения) входного или выходного буфера из кодека. В асинхронном режиме вы автоматически получите доступные буферы через Callback#onInputBufferAvailable MediaCodec.Callback.onInput/Callback#onOutputBufferAvailable OutputBufferAvailable(&hellip;) обратные вызовы.

После получения входного буфера заполните его данными и отправьте его в кодек с помощью #queueInputBuffer queueInputBuffer – или #queueSecureInputBuffer queueSecureInputBuffer при использовании расшифровки. Не отправляйте несколько входных буферов с одной меткой времени (если только не помечены такие данные кодека).

Кодек, в свою очередь, вернет выходной буфер только для чтения через Callback#onOutputBufferAvailable onOutputBufferAvailable обратный вызов в асинхронном режиме или в ответ на #dequeueOutputBuffer dequeueOutputBuffer вызов в синхронном режиме. После обработки выходного буфера вызовите один из #releaseOutputBuffer releaseOutputBuffer методов, чтобы вернуть буфер в кодек.

Хотя буферы повторной отправки и выпуска не требуются немедленно в кодек, удержание входных и /или выходных буферов может задержать кодек, и это поведение зависит от устройства. <В>частности, возможно, кодек может отложить создание выходных буферов до тех пор, пока <>не будут выпущены или повторно выведены все<> буферы или выдающиеся буферы.</strong> Поэтому старайтесь держаться на доступных буферах как можно меньше.

В зависимости от версии API можно обрабатывать данные тремя способами: <таблица<<>>tr tr<>th>Processing Mode</><>th API version <= 20<br>Jelly Bean/KitKat</th><th>API >= 21<br>Lollipop и более поздней</<>th/tr<>/thead<><>tr><td>синхронный API с помощью массивов буферов</td<>td>supported</td/td><td>Deprecated</td></tr><<>синхронный API с помощью буферов</><td>td class=NA>Not Available</<>td td/td>/>><<tr tr<>td>асинхронный API с помощью буферов</><td td class=NA>Not Available><></tdd supported<<<>/td/tr<>/tbody></table>

<асинхронная обработка h4>с помощью буферов</h4>

Так как android.os.Build.VERSION_CODES#LOLLIPOPпредпочтительный метод — асинхронно обрабатывать данные, задав обратный вызов перед вызовом #configure configure. Асинхронный режим немного изменяет переход состояния, так как необходимо вызвать #start после #flush перехода кодека в подзаготовку и начать получение входных буферов. Аналогичным образом при первоначальном вызове start кодека переместится непосредственно в состояние "Выполнение" и начнет передавать доступные входные буферы через обратный вызов.

<center><img src=".. /.. /.. /images/media/mediacodec_async_states.svg" style="width: 516px; height: 353px" alt="Схема состояния MediaCodec для асинхронной операции"></center>

MediaCodec обычно используется в асинхронном режиме:

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>с помощью буферов</h4>

Так как android.os.Build.VERSION_CODES#LOLLIPOPвы должны получать входные и выходные буферы с помощью/#getOutputBuffer OutputBuffer(int)#getInputBuffer getInputи (или) #getInputImage getInput/#getOutputImage OutputImage(int) даже при использовании кодека в синхронном режиме. Это позволяет оптимизировать платформу, например при обработке динамического содержимого. Эта оптимизация отключена при вызове #getInputBuffers getInput/#getOutputBuffers OutputBuffers().

<p class=note><strong>Note:</strong> не смешивает методы использования буферов и массивов буферов одновременно. В частности, только вызов getInput/OutputBuffers непосредственно после #start или после отмены идентификатора выходного буфера со значением #INFO_OUTPUT_FORMAT_CHANGED.

MediaCodec обычно используется в синхронном режиме:

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();

<Синхронная обработка h4>с помощью буферных массивов (не рекомендуется)</h4>

В версиях и до этого набор входных и выходных android.os.Build.VERSION_CODES#KITKAT_WATCH буферов представлен ByteBuffer[] массивами. После успешного вызова #startизвлеките массивы буферов с помощью #getInputBuffers getInput/#getOutputBuffers OutputBuffers(). Используйте идентификатор буфера в качестве индексов в эти массивы (если они не отрицательные), как показано в примере ниже. Обратите внимание, что между размером массивов и количеством входных и выходных буферов, используемых системой, не существует, хотя размер массива обеспечивает верхнюю границу.

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>Сквозная обработка< потока/h4>

Когда вы достигнете конца входных данных, необходимо сообщить ему кодеку, указав #BUFFER_FLAG_END_OF_STREAM флаг в вызове #queueInputBuffer queueInputBuffer. Это можно сделать в последнем допустимом входном буфере или путем отправки дополнительного пустого входного буфера с набором флагов конца потока. При использовании пустого буфера метка времени будет игнорироваться.

Кодек будет продолжать возвращать выходные буферы, пока в конечном итоге не будет сигнализировать конец выходного потока, указав тот же флаг конца потока в BufferInfo наборе #dequeueOutputBuffer dequeueOutputBuffer или возвращен через Callback#onOutputBufferAvailable onOutputBufferAvailableнего. Это можно задать в последнем допустимом выходном буфере или пустом буфере после последнего допустимого выходного буфера. Метка времени такого пустого буфера должна игнорироваться.

Не отправляйте дополнительные входные буферы после сигнализации конца входного потока, если кодек не был удален или остановлен и перезапущен.

<h4>С помощью выходной поверхности< или h4>

Обработка данных почти идентична режиму ByteBuffer при использовании выходных данных Surface, однако выходные буферы не будут доступны и представлены в виде null значений. Например, #getOutputBuffer getOutputBuffer/#getOutputImage Image(int) вернет null и #getOutputBuffers вернет массив, содержащий только null-s.

При использовании выходного surface можно выбрать, следует ли отображать каждый выходной буфер на поверхности. У вас есть три варианта: <ul><li><strong>Do not render the buffer:</strong> Call#releaseOutputBuffer(int, boolean) releaseOutputBuffer(bufferId, false).</li><li><strong>Render буфер с меткой времени по умолчанию:</strong> Call#releaseOutputBuffer(int, boolean) releaseOutputBuffer(bufferId, true).</li li>><<strong>Render the buffer with a specific timestamp:</strong> Call#releaseOutputBuffer(int, long) releaseOutputBuffer(bufferId, timestamp).</li></ul>

Так как android.os.Build.VERSION_CODES#Mметка времени по умолчанию — это метка времени презентации BufferInfo#presentationTimeUs буфера (преобразованная в nanoseconds). Он не был определен до этого.

Кроме того, так как android.os.Build.VERSION_CODES#Mвы можете динамически #setOutputSurface setOutputSurfaceизменять выходные данные Surface.

При отрисовке выходных данных в Surface surface может быть настроена для удаления чрезмерных кадров (которые не используются Surface своевременно). Или его можно настроить, чтобы не удалять избыточные кадры. В последнем режиме, если Surface не потребляет выходные кадры достаточно быстро, он в конечном итоге блокирует декодатор. android.os.Build.VERSION_CODES#Q До точного поведения не определено, за исключением того, что поверхности представления (SurfaceView или TextureView) всегда сбрасывали избыточные кадры. Так как android.os.Build.VERSION_CODES#Q поведение по умолчанию заключается в удалении избыточных кадров. Приложения могут отказаться от этого поведения для поверхностей, отличных от представления (например, ImageReader или SurfaceTexture), нацелив пакет SDK android.os.Build.VERSION_CODES#Q и задав ключ MediaFormat#KEY_ALLOW_FRAME_DROP0 в их формате настройки.

<Преобразования h4>при отрисовке на Surface</h4>

Если кодек настроен в режим Surface, любой прямоугольник обрезки, смена MediaFormat#KEY_ROTATION и режим масштабирования видео #setVideoScalingMode будет автоматически применен с одним исключением: <p class=note> До android.os.Build.VERSION_CODES#M выпуска декодирования программного обеспечения, возможно, не применяли поворот при отрисовке на Surface. К сожалению, нет стандартного и простого способа идентификации декодирования программного обеспечения, или если они применяют поворот, отличный от попытки его.

Есть также некоторые предостережения. <p class=note Обратите внимание> , что пропорции пикселей не учитываются при отображении выходных данных на Surface. Это означает, что если вы используете #VIDEO_SCALING_MODE_SCALE_TO_FIT режим, необходимо разместить выходную поверхность, чтобы она была правильной пропорцией отображения. И наоборот, можно использовать #VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING только режим для содержимого с квадратными пикселями (пропорции пикселей или 1:1). <p class=Note> также, что по состоянию android.os.Build.VERSION_CODES#N на выпуске режим может не работать правильно для видео, #VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING поворачиваемых на 90 или 270 градусов. <p class=note> При настройке режима масштабирования видео следует отметить, что его необходимо сбросить после каждого изменения выходных буферов. #INFO_OUTPUT_BUFFERS_CHANGED Так как событие устарело, это можно сделать после каждого изменения формата выходных данных.

<h4>С помощью входной поверхности</h4>

При использовании входной поверхности нет доступных входных буферов, так как буферы автоматически передаются из входной поверхности в кодек. Вызов #dequeueInputBuffer dequeueInputBuffer вызывает вызов и #getInputBuffers возвращает фиктивный IllegalStateExceptionByteBuffer[] массив, в который <необходимо< записать не>/сильный> массив.

Вызов #signalEndOfInputStream для сигнала конца потока. Входная область перестанет отправлять данные в кодек сразу после этого вызова.

<h3>Поиск и & Поддержка< адаптивного воспроизведения/h3>

Декодеры видео (и в целом кодеки, использующие сжатые видеоданных) ведут себя по-разному в отношении изменения формата поиска и форматирования независимо от того, поддерживаются ли они и настроены для адаптивного воспроизведения. Можно проверить, поддерживает ли декодировщик CodecCapabilities#FEATURE_AdaptivePlayback адаптивное воспроизведение с помощью CodecCapabilities#isFeatureSupported CodecCapabilities.isFeatureSupported(String). Поддержка адаптивного воспроизведения для декодеров видео активируется только при настройке кодека для декодирования на объект Surface.

<h4 id=KeyFrames"KeyFrames>">Stream Граничная граница и ключевые кадры</h4>

Важно, чтобы входные данные после #start или #flush запускались с подходящей границы потока: первый кадр должен быть ключевым кадром. Ключевой <кадр< или em> можно декодировать полностью самостоятельно (для большинства кодеков это означает I-frame), и никаких кадров, которые должны отображаться после ключевого кадра, ссылаются на кадры перед>ключевым кадром.

В следующей таблице перечислены подходящие ключевые кадры для различных форматов видео. <table>thead><tr th Format</th th><>Suitable key frame</th<>/tr<>/thead><tbody class=mid><tr><<>>td>VP9/VP8</td td><>a подходящий внутрифрейм, где последующие кадры не ссылаются на кадры до этого кадра.<<br>(Нет определенного имени для такого ключевого кадра.)</td></tr tr><td H.265 HEVC</td td>><IDR или CRA</<>td/><>><tr tr><td>H.264 AVC</><>td td IDR</td<>/tr><tr><td>MPEG-4><br H.263<>br MPEG-2</td<>td>td подходящий I-кадр, где никакие последующие кадры не ссылаются на кадры до этого кадра.<br>(Нет определенного имени для такого ключевого кадра.)</td></tr></tbody></table>

<h4>Для декодеров, которые не поддерживают адаптивное воспроизведение (включая, если не декодирование на Surface)</h4>

Чтобы начать декодирование данных, которые не находятся рядом с ранее отправленными данными (т. е. после поиска), необходимо <><или сильно> очистить декодатор. Так как все выходные буферы немедленно отозваны в точке очистки, может потребоваться сначала сигнал, а затем ждать завершения потока перед вызовом flush. Важно, чтобы входные данные после очистки начинались с подходящей границы потока или ключевого кадра. <p class=note>strong Note:</strong> формат данных, отправленных после очистки, не должен изменяться; #flush не поддерживает разрывы формата; для этого требуется полный #stop - #start#configure configure(&hellip;) - цикл.><

<p class=note><strong>Также обратите внимание:< /strong> , если кодек слишком скоро #start после – обычно до получения первого выходного буфера или изменения формата выходных данных будет получен – вам потребуется повторно отправить кодек-данные в кодек. Дополнительные сведения см. в разделе данных для конкретного кодека.

<h4>Для декодеров, поддерживающих и настроенных для адаптивного воспроизведения</h4>

Чтобы начать декодирование данных, которые не находятся рядом с ранее отправленными данными (т. е. после поиска), не требуется<></em> для очистки декодировщика; однако входные данные после прекращения должны начинаться с подходящей границы потока или ключевого кадра.

Для некоторых форматов видео — а именно H.264, H.265, VP8 и VP9 — также можно изменить размер рисунка или конфигурацию среднего потока. Для этого необходимо упаковать все новые данные конфигурации для кодека вместе с ключевым кадром в один буфер (включая любые коды запуска) и отправить его в виде строгого регулярного< или сильного><>входного буфера.

Вы получите возвращаемое значение или #dequeueOutputBuffer dequeueOutputBufferCallback#onOutputBufferAvailable onOutputFormatChanged обратный #INFO_OUTPUT_FORMAT_CHANGED вызов сразу после изменения размера рисунка и перед возвратом любых кадров с новым размером. <p class=note><strong>Note:</strong> так же, как и для данных, относящихся к кодеку, будьте осторожны при вызове #flush вскоре после изменения размера рисунка. Если вы не получили подтверждение изменения размера рисунка, необходимо повторить запрос на новый размер рисунка.

<Обработка ошибок< h3>/h3>

Методы #createByCodecName createByCodecName фабрики и#createEncoderByType EncoderByType#createDecoderByType createDecoder/вызов сбояIOException, которые необходимо поймать или объявить для передачи. Методы MediaCodec вызываются IllegalStateException при вызове метода из состояния кодека, которое не разрешает его; обычно это связано с неправильным использованием API приложений. Методы, связанные с безопасными буферами, могут вызываться CryptoException, что содержит дополнительные сведения об ошибках, получаемые из CryptoException#getErrorCode.

Внутренние ошибки кодека приводят CodecExceptionк повреждению содержимого мультимедиа, сбою оборудования, исчерпанию ресурсов и т. д., даже если приложение правильно использует API. Рекомендуемое действие при получении CodecException можно определить путем вызова CodecException#isRecoverable и <CodecException#isTransient: ul><li><strong>recoverable errors:</strong> If isRecoverable() возвращает значение true, а затем вызвать #stop#configure configure(&hellip;)и #start восстановить.</li><li><сильные>временные ошибки:</strong>, если isTransient() возвращает значение true, ресурсы временно недоступны и метод может быть извлечен позже.</li>><<li сильные неустранимые>ошибки:</strong>, если isRecoverable() оба и isTransient() возвращают значение false, то CodecException неустранимый и кодек должен быть #reset сброс или #release выпущен.</li></ul>

Оба isRecoverable() и isTransient() не возвращают значение true одновременно.

<h2 id=History"History>">Valid API Calls and API History</h2>

В этом разделе перечислены допустимые вызовы API в каждом состоянии и журнал API класса MediaCodec. Сведения о номерах версий API см. в статье android.os.Build.VERSION_CODES.

<style> .api > tr > th, .api > tr td { text-align: center; padding: 4px 4px; } .api > tr > th > { вертикальное выравнивание: нижнее; } .api > tr td { вертикальное выравнивание: середина; } 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 { пробел: nowrap; фон: нет; граница: нет; вертикальное выравнивание: вниз; ширина: 30px; высота: 83px; } .deg45 div { transform: skew(-45deg>, 0deg) translate(1px, -67px); преобразование: слева внизу 0; ширина: 30px; высота: 20px; } .deg45 > div div > { border: 1px solid #ddd; фон: #999; высота: 90px; ширина: 42px; } .deg45 > div div > div > { преобразование: skew(45deg, 0deg) translate(-55px, 55px) поворот(-45deg); }</стиль>

<table align="right" style="width: 0%"><thead><tr><th Symbol</>><th>th Meaning</><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>экспериментальная поддержка</td></tr tr<><>td>[ ]</td><td>deprecated</><td/<>tr tr><td>⎋</td td><>, ограниченный режимом< ввода поверхности/td/tr tr><><td><>⎆</td td><>, ограниченный режимом< вывода поверхности/td/tr tr><><td><>▧</td td><td Restricted to ByteBuffer input mode</td>/tr tr><<>td>><↩</td td td><>restricted to synchronous mode</td/tr tr><<>td>><⇄</td><td td>, ограниченный асинхронным режимом</td></tr tr><<>td>( )</td>><td td, но не должен/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/><th<>class=deg45><div><style="background:#f4b400">><div Configured</><div/><div/div></th><class=deg45><div><style="background:#e67c73">><<><div/div/div/><div/><th<>class=deg45<div style="background:#0f9d58">><div Running</div></div/div><></th<>class=deg45><><div style="background:#f7cb4d">><div End of Stream</><div/><><><th class=deg45><><div style="background:#db4437">><div Error</><div/div/><div/><><th class=deg45><><div div style="background:#666"div>><><><Released<></div/div></div></<>th th><>< colspan="8">SDK Version</<>th/tr tr>><<th colspan="7">State</th th Method><></><>th th 16>><</th th 17</><>th th 18/th th 18</th th 19</<>>th th 20><<>/>><th th 21</><th th>22</><th>23</th<>/tr/thead><tbody class=api<>tr<<>> 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 class=fn><#createDecoderByType createDecoderByType/<>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/tr tr>><<>< td/td/>><<td/>><<<><>><><td td/><<><><><>td class=fn>#createPersistentInputSurface createPersistentInputSurface</><<>>><<<><<>>><><><><><<>><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-/<>td class=fn<#createInputSurface createInputSurface>/><><><><>><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>#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></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></tr tr><><td 18+/td><>td>18<+</>><td td 18<+/<>>td td 18+</><>td td 18+/td td 18+<</><><>>td td-<></td td class=fn#getCodecInfo getCodecInfo<>/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(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></tr tr>><<td>-</td<>td>-</><>td td 16+</<>>td td(16+)</>><td td(16+)</><>td td-/td td-<</><><>td td class=fn>#getInputBuffers getInputBuffers</<>td td>●</td td><>●</td td><>●</td td><>●</td td><>●</td td><>[&>8277; ↩]</td td><>[&&>8617;]</td td><>[&&>8617;]</td></tr tr><<>td-</td><td>> 21+</<>>td td(21+)/>><td td(21+)<</<>>td td(21+)<><>/td td-/<>>td td-<><</td td class=fn>#getInputFormat getInputFormat</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></tr tr><<>td 18+</td><td>>18<+/>><td td 18><<>+/td td 18+</<>>td td 18+/td td 18+<</<<>>>>td td-<></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(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></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><>[&>8277; ↩]</td td><>[&&>8617;]</td td><>[&&>8617;]</td></tr tr>><<td-</td><td>> 21+</><>td td 16<+/<>>td td 16+</<>>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(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></tr tr>><<td>-<</td><>-/>><td td(21+)</>><td td 21+</><>td td 21+</<>>td td-/td td-<</>>><<td td class=fn<#getOutputImage getOutputImage>/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 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></tr tr>><<td 16+</td<>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><>●</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></tr tr>><<td>-</td><td>-/td td-<</>><<>>td td 21+</><>td td 21+</<>>td td-</td td-</><><>td td class=fn#releaseOutputBuffer(int, long)></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-><</td td class=fn#reset reset></td 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>><<><#setCallback(Callback, Handler) &#8277;/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>⎋</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></tr tr><><td-</td<>td>> 23+</>><td td 23<+/>><td td 23+</><>td td 23+</><>td td-/td td-<</>>><<td td class=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 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 tr>><<td-</td<>td>>(16+)/><>td td(16+)<</<>td td>16+</<>>td td(16+)</td td(16+)>><</><>td td-</<>td td class=fn<>#setVideoScalingMode setVideoScalingMode/<>>td 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 класс=fn>#setAudioPresentation setAudioPresentation</td td/><><><><><><>><<td/td td/>><<><<><><>td td/<><>><tr>>><< td-<</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></tr></tbody></table>

Документация по Java для android.media.MediaCodec.

Части этой страницы — это изменения на основе работы, созданной и общей проектом с открытым исходным кодом Android и используемой в соответствии с условиями, описанными в лицензии Creative Commons 2.5 Attribution.

Поля

BufferFlagCodecConfig
Устаревшие..

Это означает, что буфер, помеченный как такой, содержит инициализацию кодека или определенные данные кодека вместо данных мультимедиа.

BufferFlagDecodeOnly
Устаревшие..

Это означает, что буфер декодируется и обновляет внутреннее состояние декодера, но не создает выходной буфер.

BufferFlagEndOfStream
Устаревшие..

Это сигнализирует о конце потока, i.

BufferFlagKeyFrame
Устаревшие..

Это означает, что буфер (закодированный) помечен как такой, содержит данные для ключевого кадра.

BufferFlagPartialFrame
Устаревшие..

Это означает, что буфер содержит только часть кадра, а декодировщик должен пакетировать данные, пока буфер не появится без этого флага перед декодированием кадра.

BufferFlagSyncFrame
Устаревшие..

Это означает, что буфер (закодированный) помечен как такой, содержит данные для ключевого кадра.

ConfigureFlagEncode
Устаревшие..

Если этот кодек должен использоваться в качестве кодировщика, передайте этот флаг.

ConfigureFlagUseBlockModel
Устаревшие..

Если этот кодек используется с LinearBlock и/или HardwareBuffer, передайте этот флаг.

ConfigureFlagUseCryptoAsync
Устаревшие..

Этот флаг должен использоваться только для безопасного декодера.

CryptoModeAesCbc
Устаревшие..

Класс MediaCodec можно использовать для доступа к кодекам мультимедиа низкого уровня, i.

CryptoModeAesCtr
CryptoModeUnencrypted
InfoOutputBuffersChanged
Устаревшие..

Буферы выходных данных изменились, клиент должен ссылаться на новый набор выходных буферов, возвращаемых #getOutputBuffers с этой точки.

InfoOutputFormatChanged
Устаревшие..

Формат выходных данных изменился, последующие данные будут соответствовать новому формату.

InfoTryAgainLater
Устаревшие..

Если в вызове было указано не отрицательное время ожидания, указывает, что время ожидания вызова #dequeueOutputBufferистекло.

ParameterKeyHdr10PlusInfo

Задайте метаданные HDR10+ в следующем входном кадре очереди.

ParameterKeyLowLatency

Включение и отключение режима декодирования с низкой задержкой.

ParameterKeyOffsetTime

Укажите смещение (в микро-секунде), добавляемое поверх меток времени.

ParameterKeyRequestSyncFrame

Запросите, чтобы кодировщик создает кадр синхронизации "скоро".

ParameterKeySuspend

Временно приостанавливать и возобновлять кодировку входных данных.

ParameterKeySuspendTime

При #PARAMETER_KEY_SUSPEND наличии клиент также может использовать этот ключ, чтобы указать метку времени (в микро-секунде), при которой операция приостановки и возобновления вступает в силу.

ParameterKeyTunnelPeek

Управляйте просмотром видео первого кадра при настройке кодека в режиме туннеля при MediaFormat#KEY_AUDIO_SESSION_IDAudioTrack приостановке.

ParameterKeyVideoBitrate

Измените целевую скорость кодировщика видео на лету.

VideoScalingModeScaleToFit
Устаревшие..

Содержимое масштабируется до измерений поверхности

VideoScalingModeScaleToFitWithCropping
Устаревшие..

Содержимое масштабируется, сохраняя его пропорции, используется вся область поверхности, содержимое может быть обрезано.

Свойства

CanonicalName

Получите базовое имя кодека.

Class

Возвращает класс среды выполнения этого Objectобъекта.

(Унаследовано от Object)
CodecInfo

Получение сведений о кодеке.

Handle

Дескриптор базового экземпляра Android.

(Унаследовано от Object)
InputFormat

Вызовите этот вызов после #configure успешного возврата, чтобы получить входной формат, принятый кодеком.

JniIdentityHashCode

Класс MediaCodec можно использовать для доступа к кодекам мультимедиа низкого уровня, i.

(Унаследовано от Object)
JniPeerMembers

Класс MediaCodec можно использовать для доступа к кодекам мультимедиа низкого уровня, i.

Metrics

Возвращает данные метрик текущего экземпляра кодека.

Name

Получите имя кодека.

OutputFormat

Вызовите этот вызов после dequeueOutputBuffer сигнализирует об изменении формата, возвращая #INFO_OUTPUT_FORMAT_CHANGED.

PeerReference

Класс MediaCodec можно использовать для доступа к кодекам мультимедиа низкого уровня, i.

(Унаследовано от Object)
SupportedVendorParameters

Возвращает список имен параметров поставщика.

ThresholdClass

Этот API поддерживает инфраструктуру Mono для Android и не предназначен для использования непосредственно из кода.

(Унаследовано от Object)
ThresholdType

Этот API поддерживает инфраструктуру Mono для Android и не предназначен для использования непосредственно из кода.

(Унаследовано от Object)

Методы

Clone()

Создает и возвращает копию этого объекта.

(Унаследовано от Object)
Configure(MediaFormat, Surface, MediaCodecConfigFlags, MediaDescrambler)

Настройте компонент для использования с декрамблером.

Configure(MediaFormat, Surface, MediaCrypto, MediaCodecConfigFlags)

Настраивает компонент.

CreateByCodecName(String)

Если вы знаете точное имя компонента, который необходимо создать, используйте этот метод для создания экземпляра.

CreateDecoderByType(String)

Создайте экземпляр предпочтительного декодера, поддерживающего входные данные заданного типа mime.

CreateEncoderByType(String)

Создайте экземпляр предпочтительного кодировщика, поддерживающего выходные данные заданного типа mime.

CreateInputSurface()

Запрашивает Surface использовать в качестве входных данных кодировщику вместо входных буферов.

CreatePersistentInputSurface()

Создайте постоянную входную поверхность, которую можно использовать с кодеками, которые обычно имеют входную поверхность, например видеокодировщики.

DequeueInputBuffer(Int64)

Возвращает индекс входного буфера, заполненный допустимыми данными или -1, если такой буфер в настоящее время недоступен.

DequeueOutputBuffer(MediaCodec+BufferInfo, Int64)

Отмена выходного буфера, блок по крайней мере "timeoutUs" microseconds.

Dispose()

Класс MediaCodec можно использовать для доступа к кодекам мультимедиа низкого уровня, i.

(Унаследовано от Object)
Dispose(Boolean)

Класс MediaCodec можно использовать для доступа к кодекам мультимедиа низкого уровня, i.

(Унаследовано от Object)
Equals(Object)

Указывает, равен ли другой объект этому объекту.

(Унаследовано от Object)
Flush()

Очистка входных и выходных портов компонента.

GetHashCode()

Возвращает значение хэш-кода для объекта.

(Унаследовано от Object)
GetInputBuffer(Int32)

java.nio.Buffer#clear clearedВозвращает объект byteBuffer с возможностью записи для отложенного индекса входного буфера, содержащего входные данные.

GetInputBuffers()
Устаревшие..

Получение набора входных буферов.

GetInputImage(Int32)

Возвращает объект записываемого изображения для отложенного индекса буфера ввода, чтобы содержать необработанный входной видеокадр.

GetOutputBuffer(Int32)

Возвращает значение byteBuffer только для чтения для индексов буфера вывода.

GetOutputBuffers()
Устаревшие..

Извлеките набор выходных буферов.

GetOutputFormat(Int32)

Возвращает выходной формат для определенного выходного буфера.

GetOutputFrame(Int32)

Возвращает объект OutputFrame.

GetOutputImage(Int32)

Возвращает объект image только для чтения для индекса буфера вывода, содержащего необработанный кадр видео.

GetParameterDescriptor(String)

Описание параметра с именем.

GetQueueRequest(Int32)

QueueRequest Возвращает объект для входного индекса слота.

JavaFinalize()

Вызывается сборщиком мусора в объекте, когда сборка мусора определяет, что больше ссылок на объект нет.

(Унаследовано от Object)
MapHardwareBuffer(HardwareBuffer)

HardwareBuffer Сопоставите объект с Imageтем, чтобы содержимое буфера было доступно.

Notify()

Пробуждение одного потока, ожидающего монитора этого объекта.

(Унаследовано от Object)
NotifyAll()

Просыпает все потоки, ожидающие монитора этого объекта.

(Унаследовано от Object)
QueueInputBuffer(Int32, Int32, Int32, Int64, MediaCodecBufferFlags)

После заполнения диапазона входного буфера по указанному индексу отправьте его компоненту.

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

#queueInputBuffer queueInputBuffer Аналогично отправке буфера, который потенциально зашифрован.

Release()

Освободить ресурсы, используемые экземпляром кодека.

ReleaseOutputBuffer(Int32, Boolean)

Если вы закончите работу с буфером, используйте этот вызов, чтобы вернуть буфер в кодек или отобразить его на выходной поверхности.

ReleaseOutputBuffer(Int32, Int64)

Если вы закончите работу с буфером, используйте этот вызов, чтобы обновить метку времени поверхности и вернуть ее в кодек, чтобы отобразить его на выходной поверхности.

Reset()

Возвращает кодек в исходное (неинициализированное) состояние.

SetAudioPresentation(AudioPresentation)

Задает презентацию звука.

SetCallback(MediaCodec+Callback)

Задает асинхронный обратный вызов для событий MediaCodec, доступных для действий, в цикле по умолчанию.

SetCallback(MediaCodec+Callback, Handler)

Задает асинхронный обратный вызов для событий MediaCodec, доступных для действий, в цикле по умолчанию.

SetHandle(IntPtr, JniHandleOwnership)

Задает свойство Handle.

(Унаследовано от Object)
SetInputSurface(Surface)

Настраивает кодек (e.

SetOnFirstTunnelFrameReadyListener(Handler, MediaCodec+IOnFirstTunnelFrameReadyListener)

Регистрирует обратный вызов при декодировании первого выходного кадра и готов к отрисовке в кодеке, настроенном для режима KEY_AUDIO_SESSION_IDтуннеля.

SetOnFrameRenderedListener(MediaCodec+IOnFrameRenderedListener, Handler)

Регистрирует обратный вызов при отрисовке выходного кадра на выходной поверхности.

SetOutputSurface(Surface)

Динамически задает выходную поверхность кодека.

SetParameters(Bundle)

Обмен данными о дополнительных изменениях параметров экземпляра компонента.

SetVideoScalingMode(VideoScalingMode)

Если поверхность была указана в предыдущем вызове, чтобы #configure указать режим масштабирования для использования.

SignalEndOfInputStream()

Сигнализирует о завершении потока во входных данных.

Start()

После успешной настройки компонента вызовите start.

Stop()

Завершите сеанс декодирования и кодирования, обратите внимание, что экземпляр кодека остается активным и готов к повторному выполнению #start.

SubscribeToVendorParameters(IList<String>)

Подпишитесь на параметры поставщика, чтобы эти параметры отображались и изменялись #getOutputFormat в этих параметрах, создавая событие изменения формата выходных данных.

ToArray<T>()

Класс MediaCodec можно использовать для доступа к кодекам мультимедиа низкого уровня, i.

(Унаследовано от Object)
ToString()

Возвращает строковое представление объекта.

(Унаследовано от Object)
UnregisterFromRuntime()

Класс MediaCodec можно использовать для доступа к кодекам мультимедиа низкого уровня, i.

(Унаследовано от Object)
UnsubscribeFromVendorParameters(IList<String>)

Отмена подписки на параметры поставщика, поэтому эти параметры не будут присутствовать #getOutputFormat и изменения этих параметров больше не создают событие изменения формата выходных данных.

Wait()

Приводит к тому, что текущий поток будет ждать, пока он не проснется, как правило, при <>помощи уведомления</em> или <эм>прерванного</em>.

(Унаследовано от Object)
Wait(Int64)

Приводит к тому, что текущий поток будет ждать, пока он не проснется, как правило, при <>получении уведомления</>em или <>эм прервано< или> до тех пор, пока не истекло определенное количество реального времени.

(Унаследовано от Object)
Wait(Int64, Int32)

Приводит к тому, что текущий поток будет ждать, пока он не проснется, как правило, при <>получении уведомления</>em или <>эм прервано< или> до тех пор, пока не истекло определенное количество реального времени.

(Унаследовано от Object)

Явные реализации интерфейса

IJavaPeerable.Disposed()

Класс MediaCodec можно использовать для доступа к кодекам мультимедиа низкого уровня, i.

(Унаследовано от Object)
IJavaPeerable.DisposeUnlessReferenced()

Класс MediaCodec можно использовать для доступа к кодекам мультимедиа низкого уровня, i.

(Унаследовано от Object)
IJavaPeerable.Finalized()

Класс MediaCodec можно использовать для доступа к кодекам мультимедиа низкого уровня, i.

(Унаследовано от Object)
IJavaPeerable.JniManagedPeerState

Класс MediaCodec можно использовать для доступа к кодекам мультимедиа низкого уровня, i.

(Унаследовано от Object)
IJavaPeerable.SetJniIdentityHashCode(Int32)

Класс MediaCodec можно использовать для доступа к кодекам мультимедиа низкого уровня, i.

(Унаследовано от Object)
IJavaPeerable.SetJniManagedPeerState(JniManagedPeerStates)

Класс MediaCodec можно использовать для доступа к кодекам мультимедиа низкого уровня, i.

(Унаследовано от Object)
IJavaPeerable.SetPeerReference(JniObjectReference)

Класс MediaCodec можно использовать для доступа к кодекам мультимедиа низкого уровня, i.

(Унаследовано от Object)

Методы расширения

JavaCast<TResult>(IJavaObject)

Выполняет преобразование типа, проверяемого средой выполнения Android.

JavaCast<TResult>(IJavaObject)

Класс MediaCodec можно использовать для доступа к кодекам мультимедиа низкого уровня, i.

GetJniTypeName(IJavaPeerable)

Класс MediaCodec можно использовать для доступа к кодекам мультимедиа низкого уровня, i.

Применяется к