MediaCodec クラス
定義
重要
一部の情報は、リリース前に大きく変更される可能性があるプレリリースされた製品に関するものです。 Microsoft は、ここに記載されている情報について、明示または黙示を問わず、一切保証しません。
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 クラスを使用して、低レベルのメディア コーデック (エンコーダー/デコーダー コンポーネントなど) にアクセスできます。 これは、Android の低レベルのマルチメディア サポート インフラストラクチャの一部です (通常、、、MediaCrypto
Surface
MediaSync
MediaMuxer
MediaDrm
Image
および AudioTrack
とMediaExtractor
共に使用されます)。
<center><img src="../../../images/media/mediacodec_buffers.svg" style="width: 540px;height: 205px" alt="MediaCodec buffer flow diagram"></center>
大まかに言えば、コーデックは入力データを処理して出力データを生成します。 データは非同期的に処理され、一連の入力バッファーと出力バッファーが使用されます。 単純なレベルでは、空の入力バッファーを要求 (または受信) し、データを入力してコーデックに送信して処理します。 コーデックはデータを使用し、空の出力バッファーのいずれかに変換します。 最後に、入力された出力バッファーを要求 (または受信) し、その内容を使用してコーデックに解放します。
<h3 id=quality Floor>"quality Floor">Minimum Quality Floor for Video Encoding</h3>
以降、 android.os.Build.VERSION_CODES#S
Android の Video MediaCodecs では、最小品質のフロアが適用されます。 その目的は、品質の低いビデオ エンコーディングを排除することです。 この品質フロアは、コーデックが Variable Bitrate (VBR) モードの場合に適用されます。コーデックが Constant Bitrate (CBR) モードの場合は適用されません。 品質の床の適用はまた、特定のサイズ範囲に制限されています。このサイズ範囲は現在、320 x 240 から 1920x1080 までのビデオ解像度に対応しています。
この品質のフロアが有効な場合、コーデックとサポート フレームワーク コードは、生成されたビデオが少なくとも "公平" または "良い" 品質であることを確認するために機能します。 これらのターゲットの選択に使用されるメトリックは、選択したテスト シーケンスのターゲット スコアが 70 の VMAF (ビデオマルチメソッド評価関数) です。
一般的な効果は、一部のビデオでは、最初に構成されたよりも高いビットレートが生成されるということです。 これは、非常に低いビットレートで構成されたビデオで最も注目に値します。コーデックでは、"公平" または "良い" 品質のビデオを生成する可能性が高いと判断されたビットレートが使用されます。 もう 1 つの状況は、ビデオに非常に複雑なコンテンツ (多くのモーションと詳細) が含まれている場合です。このような構成では、コーデックは必要に応じて追加のビットレートを使用して、コンテンツの詳細をすべて失わないようにします。
この品質の床は、高ビットレートでキャプチャされたコンテンツには影響しません (高ビットレートでは、すべての詳細をエンコードするのに十分な容量をコーデックに既に提供する必要があります)。 品質フロアは CBR エンコードでは動作しません。 現在、品質フロアは 320 x 240 以下の解像度、1920 x 1080 を超える解像度のビデオでは動作しません。
<h3>データ型</h3>
コーデックは、圧縮データ、生オーディオ データ、生ビデオ データの 3 種類のデータで動作します。 3 種類のデータはすべて を使用して ByteBuffer ByteBuffers
処理できますが、コーデックのパフォーマンスを向上させるには、生のビデオ データに を使用 Surface
する必要があります。 Surface では、マッピングや ByteBuffers へのコピーを行わずにネイティブ ビデオ バッファーを使用します。したがって、はるかに効率的です。 通常、Surface を使用する場合は生のビデオ データにアクセスできませんが、 クラスを ImageReader
使用して、セキュリティで保護されていないデコード (未加工) ビデオ フレームにアクセスできます。 一部のネイティブ バッファーは ByteBuffer#isDirect ダイレクト ByteBuffers にマップされる可能性があるため、これは ByteBuffers を使用するよりも効率的な場合があります。 ByteBuffer モードを使用する場合は、 クラス と #getInputImage getInput
/#getOutputImage OutputImage(int)
を使用して生のビデオ フレームにImage
アクセスできます。
<h4>圧縮バッファー</h4>
入力バッファー (デコーダーの場合) と出力バッファー (エンコーダーの場合) には、MediaFormat#KEY_MIME 形式の型に従って圧縮されたデータが含まれます。 ビデオの種類の場合、これは通常、1 つの圧縮されたビデオ フレームです。 オーディオ データの場合、これは通常、1 つのアクセス ユニット (通常、形式の種類によって指定された数ミリ秒のオーディオを含むエンコードされたオーディオ セグメント) ですが、この要件は、バッファーに複数のエンコードされたオーディオ アクセスユニットが含まれている可能性がある点で少し緩和されます。 どちらの場合も、バッファーは任意のバイト境界で開始または終了するのではなく、 でフラグが設定されていない限り、フレーム/アクセス ユニットの境界で #BUFFER_FLAG_PARTIAL_FRAME
開始または終了しません。
<h4>生オーディオ バッファー</h4>
生オーディオ バッファーには、チャネル順のチャネルごとに 1 つのサンプルである PCM オーディオ データのフレーム全体が含まれています。 各 PCM オーディオ サンプルは、ネイティブバイト順の 16 ビット符号付き整数または float です。 float PCM エンコードの生オーディオ バッファーは、MediaCodec #configure configure(…)
中に MediaFormat の MediaFormat#KEY_PCM_ENCODING が AudioFormat#ENCODING_PCM_FLOAT に設定され、デコーダーまたは#getInputFormat
エンコーダーの場合は によって#getOutputFormat
確認された場合にのみ可能です。 MediaFormat で float PCM をチェックするサンプル メソッドは次のとおりです。
static boolean isPcmFloat(MediaFormat format) {
return format.getInteger(MediaFormat.KEY_PCM_ENCODING, AudioFormat.ENCODING_PCM_16BIT)
== AudioFormat.ENCODING_PCM_FLOAT;
}
短い配列で、16 ビット符号付き整数オーディオ データを含むバッファーの 1 つのチャネルを抽出するために、次のコードを使用できます。
// Assumes the buffer PCM encoding is 16 bit.
short[] getSamplesForChannel(MediaCodec codec, int bufferId, int channelIx) {
ByteBuffer outputBuffer = codec.getOutputBuffer(bufferId);
MediaFormat format = codec.getOutputFormat(bufferId);
ShortBuffer samples = outputBuffer.order(ByteOrder.nativeOrder()).asShortBuffer();
int numChannels = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
if (channelIx < 0 || channelIx >= numChannels) {
return null;
}
short[] res = new short[samples.remaining() / numChannels];
for (int i = 0; i < res.length; ++i) {
res[i] = samples.get(i * numChannels + channelIx);
}
return res;
}
<h4>生ビデオ バッファー</h4>
ByteBuffer モードでは、ビデオ バッファーは MediaFormat#KEY_COLOR_FORMAT 色形式に従ってレイアウトされます。 サポートされている色形式は、 から#getCodecInfo
.
.
MediaCodecInfo#getCapabilitiesForType getCapabilitiesForType(…)
CodecCapabilities#colorFormats colorFormats
配列として取得できます。 ビデオ コーデックは、3 種類のカラー形式をサポートしている場合があります。<ul<>li><strong>ネイティブ生ビデオ形式:</strong> これは によってCodecCapabilities#COLOR_FormatSurface
マークされ、入力または出力 Surface で使用できます。</li li><<>strong>フレキシブル YUV バッファー</strong> (例: CodecCapabilities#COLOR_FormatYUV420Flexible
): これらは、 を使用して、入力/出力 Surface および ByteBuffer モードで使用#getOutputImage OutputImage(int)
#getInputImage getInput
/できます。</li li>><<strong>other, specific formats:</strong> これらは通常、ByteBuffer モードでのみサポートされています。 一部の色形式はベンダー固有です。 その他は で CodecCapabilities
定義されています。 フレキシブル形式と同等の色書式の場合でも、 を使用 #getInputImage getInput
/#getOutputImage OutputImage(int)
できます。</li></ul>
すべてのビデオ コーデックは、 以降 android.os.Build.VERSION_CODES#LOLLIPOP_MR1
の柔軟な YUV 4:2:0 バッファーをサポートしています。
<h4>古いデバイス<で生のビデオ ByteBuffers にアクセスする/h4>
と Image
をサポートする前にandroid.os.Build.VERSION_CODES#LOLLIPOP
、 と MediaFormat#KEY_SLICE_HEIGHT
出力形式の値をMediaFormat#KEY_STRIDE
使用して、生出力バッファーのレイアウトを理解する必要があります。 <p class=note> 一部のデバイスでは、スライスの高さが 0 としてアドバタイズされることに注意してください。 これは、スライスの高さがフレームの高さと同じか、スライスの高さが何らかの値 (通常は 2 の累乗) に揃えたフレームの高さであることを意味する可能性があります。 残念ながら、この場合、実際のスライスの高さを伝える標準的で簡単な方法はありません。 さらに、平面の垂直方向の U
ストライドも指定または定義されませんが、通常はスライスの高さの半分です。
キーと MediaFormat#KEY_HEIGHT
キーはMediaFormat#KEY_WIDTH
ビデオ フレームのサイズを指定しますが、ほとんどの場合、ビデオ (画像) はビデオ フレームの一部のみを占めます。 これは'トリミング四角形' で表されます。
#getOutputFormat 出力形式から生出力イメージのトリミング四角形を取得するには、次のキーを使用する必要があります。 これらのキーが存在しない場合、ビデオはビデオ フレーム全体を占有します。トリミング四角形は、MediaFormat#KEY_ROTATION 回転を適用する出力フレーム <em>before</em> のコンテキストで理解されます。 <table style="width: 0%"><thead><tr<>th>Format Key</th><th>Type</th<>description></th<>/tr></thead<>tbody<>tr<>tdMediaFormat#KEY_CROP_LEFT
<>/td td><td>Integer</td td<>td>トリミング四角形</td<>/tr><tr><td><MediaFormat#KEY_CROP_TOP
/td td<>>整数/<td td>><トリミング四角形</td/tr tr><td>><MediaFormat#KEY_CROP_RIGHT
<></td><td td>の上座標 (y) 整数</td><td>右座標 (x) トリミング四角形</td></tr tr><><td/td><td<MediaFormat#KEY_CROP_BOTTOM
>> 整数</td><td>の右座標 (x) <<の強>い>マイナス 1<></強さ>トリミング四角形</td></tr tr td<><>colspan=3> 右座標と下端座標は、トリミングされた出力画像の右端の有効な列/最下位の有効な行の座標として理解できます。 </td></tr></tbody></table>
ビデオ フレームのサイズ (回転前) は、次のように計算できます。
MediaFormat format = decoder.getOutputFormat(…);
int width = format.getInteger(MediaFormat.KEY_WIDTH);
if (format.containsKey(MediaFormat.KEY_CROP_LEFT)
&& format.containsKey(MediaFormat.KEY_CROP_RIGHT)) {
width = format.getInteger(MediaFormat.KEY_CROP_RIGHT) + 1
- format.getInteger(MediaFormat.KEY_CROP_LEFT);
}
int height = format.getInteger(MediaFormat.KEY_HEIGHT);
if (format.containsKey(MediaFormat.KEY_CROP_TOP)
&& format.containsKey(MediaFormat.KEY_CROP_BOTTOM)) {
height = format.getInteger(MediaFormat.KEY_CROP_BOTTOM) + 1
- format.getInteger(MediaFormat.KEY_CROP_TOP);
}
<p class=note> また、 の意味 BufferInfo#offset BufferInfo.offset
はデバイス間で一貫していません。 一部のデバイスでは、オフセットはトリミング四角形の左上のピクセルを指し、ほとんどのデバイスではフレーム全体の左上のピクセルを指しています。
<h3>States</h3>
その期間中、コーデックは概念的には、停止、実行、またはリリースの 3 つの状態のいずれかに存在します。 停止された集合状態は、実際には 3 つの状態 (初期化されていない、構成済み、およびエラー) の結合です。一方、実行中の状態は概念的に Flushed、Running、End-of-Stream の 3 つのサブ状態を通じて進行します。
<center><img src="../../../images/media/mediacodec_states.svg" style="width: 519px;height: 356px" alt="MediaCodec 状態図"></center>
いずれかのファクトリ メソッドを使用してコーデックを作成すると、コーデックは初期化されていない状態になります。 まず、 を使用して #configure configure(…)
構成する必要があります。これにより、構成済み状態になります。次に、 を呼び出 #start
して実行状態に移動します。 この状態では、上記のバッファー キュー操作を通じてデータを処理できます。
実行状態には、Flushed、Running、End-of-Stream の 3 つのサブ状態があります。 コーデックが Flushed サブ状態の直後 #start
に、すべてのバッファーを保持します。 最初の入力バッファーがデキューされるとすぐに、コーデックは実行中のサブ状態に移動し、そこでほとんどの時間を費やします。 #BUFFER_FLAG_END_OF_STREAMストリーム終了マーカーを使用して入力バッファーをキューに入れると、コーデックはストリームの終了サブ状態に遷移します。 この状態では、コーデックはそれ以上の入力バッファーを受け入れなくなりましたが、出力でストリームの終わりに達するまで出力バッファーを生成します。 デコーダーの場合は、 を使用して #flush
実行中の状態でいつでも Flushed サブ状態に戻すことができます。 <p class=note><strong Note strong>Note:</strong> Flushed 状態に戻る操作はデコーダーでのみサポートされており、エンコーダーでは機能しない可能性があります (動作は未定義です)。
を呼び出 #stop
してコーデックを初期化されていない状態に戻します。ここで、再度構成できます。 コーデックの使用が完了したら、 を呼び出 #release
して解放する必要があります。
まれにコーデックでエラーが発生し、エラー状態に移行することがあります。 これは、キュー操作からの無効な戻り値を使用して、または例外を介して伝達されます。 を呼び出 #reset
して、コーデックを再び使用できるようにします。 任意の状態から呼び出して、コーデックを初期化されていない状態に戻すことができます。 それ以外の場合は、 を呼び出 #release
して、ターミナルの Released 状態に移動します。
<h3>Creation</h3>
を使用して MediaCodecList
、特定 MediaFormat
の の MediaCodec を作成します。 ファイルまたはストリームをデコードするときに、 から MediaExtractor#getTrackFormat MediaExtractor.getTrackFormat
目的の形式を取得できます。 を使用して MediaFormat#setFeatureEnabled MediaFormat.setFeatureEnabled
追加する特定の機能を挿入し、 を呼び出 MediaCodecList#findDecoderForFormat MediaCodecList.findDecoderForFormat
して、その特定のメディア形式を処理できるコーデックの名前を取得します。 最後に、 を使用してコーデックを #createByCodecName
作成します。 <p class=note><厳密な>Note:</strong> On ではandroid.os.Build.VERSION_CODES#LOLLIPOP
、 の形式にEncoderForFormat
MediaCodecList.findDecoder
/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"
終わる必要があります) #createByCodecName
を追加".secure"
することによって、名前のみでインスタンス化できます。コーデックがシステムに存在しない場合は、 がスローIOException
されます。
以降 android.os.Build.VERSION_CODES#LOLLIPOP
は、メディア形式の機能を CodecCapabilities#FEATURE_SecurePlayback
使用して、セキュリティで保護されたデコーダーを作成する必要があります。
<h3>初期化</h3>
コーデックを作成した後、データを非同期的に処理する場合は、 を使用して #setCallback setCallback
コールバックを設定できます。 次に、特定のメディア形式を使用してコーデックを構成 #configure。 これは、ビデオ プロデューサー &ndash、生のビデオ データを生成するコーデック (ビデオ デコーダーなど) の出力 Surface
を指定できる場合です。 これは、セキュリティで保護されたコーデックの復号化パラメーターを設定できる場合もあります (「」を参照)。MediaCrypto
最後に、一部のコーデックは複数のモードで動作できるため、デコーダーまたはエンコーダーとして動作させるかどうかを指定する必要があります。
の場合 android.os.Build.VERSION_CODES#LOLLIPOP
、結果の入力形式と出力形式を構成済み状態で照会できます。 これを使用して、コーデックを開始する前に、結果の構成 (カラー形式など) を確認できます。
ビデオ コンシューマーを使用して生の入力ビデオ バッファーをネイティブに処理する場合は、ndash &します。ビデオ エンコーダー &ndash など、生のビデオ入力を処理するコーデック。構成後に を使用して #createInputSurface
、入力データの変換先 Surface を作成します。 または、 を呼び出 #setInputSurface
して、以前に作成 #createPersistentInputSurface 永続入力サーフェスを使用するようにコーデックを設定します。
<h4 id=CSD>"CSD">Codec 固有のデータ</h4>
一部の形式 (特に AAC オーディオおよび MPEG4、H.264、H.265 ビデオ形式) には、実際のデータの前に、セットアップ データを含むバッファーの数、またはコーデック固有のデータが含まれている必要があります。 このような圧縮形式を処理する場合、このデータはフレーム データの前後 #start
にコーデックに送信する必要があります。 このようなデータは、 の呼び出しで フラグ #BUFFER_FLAG_CODEC_CONFIG
を使用してマークする #queueInputBuffer queueInputBuffer
必要があります。
コーデック固有のデータは、"csd-0"、"csd-1" などのキーを使用して #configure configure
ByteBuffer エントリに渡される形式に含めることもできます。これらのキーは、常に から取得したトラック MediaFormat
に MediaExtractor#getTrackFormat MediaExtractor
含まれます。 形式のコーデック固有のデータは、 に#start
自動的にコーデックに送信されます。この>データを<明示的に送信する<>必要があります。 形式にコーデック固有のデータが含まれていない場合は、形式の要件に従って、指定した数のバッファーを使用して正しい順序で送信することを選択できます。 H.264 AVC の場合は、コーデック固有のすべてのデータを連結し、1 つのコーデック構成バッファーとして送信することもできます。
Android では、次のコーデック固有のデータ バッファーが使用されます。 これらは、適切な MediaMuxer
トラック構成のためにトラック形式で設定する必要もあります。 でマークされた各パラメーター セットとコーデック固有のデータ セクション (<sup>*</sup>) は、 の "\x00\x00\x00\x01"
開始コードで始まる必要があります。
<style>td。NA { background: #ccc; } .mid > tr > td { vertical-align: middle; }</style><table><thead><th>Format</th><th>CSD buffer #0</th<>>CSD buffer #1</th><>CSD buffer #2</th></thead<>tbody class=mid><tr<>td>AAC</td td td<>>Decoder-specific information from ESDS<sup>*</sup></td td><class=NA>Not Used</td td><class=NA>Not Used</Td></tr tr>td><>VORBIS</td td<>td>Identification header</td><td td>Setup header</td<>td class=NA>Not Used</td></tr tr<>td<>>OPUS</td<>td>Identification header</td td>><pre-skip in nanosecs<br> (unsigned 64 ビット ByteOrder#nativeOrder nativeOrder native-order integer.)<<br> これは、識別ヘッダーのスキップ前の値をオーバーライドします。</td td>><Seek Pre-roll in nanosecs<br> (unsigned 64 ビット ByteOrder#nativeOrder native-order integer.)</td></tr tr><<>td>FLAC</td td td<>>"fLaC",ASCII,br<> の中のFLAC ストリーム マーカーの後に STREAMINFO ブロック (必須メタデータ ブロック)< が続き、必要に応じて他>の任意の数のメタデータ ブロック</td td<>class=NA>Not Used</td td><td class=NA>Not Used</td<>/tr tr<>td<>>MPEG-4</td><Td>ESDS sup*/sup></td td td<>class=NA>Not Used</td td><class=NA>Not Used</td<>/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></tr tr><><td>VP9</td td>><VP9 CodecPrivate Data (省略可能)</td><td class=NA>Not Used</td td><class=NA>Not Used</td></tr tr><<>td>AV1</td td ><>AV1 AV1CodecConfigurationRecord Data (省略可能) </td<>td class=NA>Not Used</td><td class=NA>Not Used</td></tr></tbody></table>
<p class=note><strong Note:<>/strong> care は、コーデックが開始直後または直後にフラッシュされた場合、出力バッファーまたは出力形式の変更が返される前に、フラッシュ中にコーデック固有のデータが失われる可能性があるため、注意する必要があります。 適切なコーデック操作を確保するには、このようなフラッシュ後に で #BUFFER_FLAG_CODEC_CONFIG
マークされたバッファーを使用してデータを再送信する必要があります。
エンコーダー (または圧縮データを生成するコーデック) は、#BUFFER_FLAG_CODEC_CONFIG codec-config フラグでマークされた出力バッファー内の有効な出力バッファーの前にコーデック固有のデータを作成して返します。 コーデック固有のデータを含むバッファーには、意味のあるタイムスタンプがありません。
<h3>データ処理</h3>
各コーデックは、API 呼び出しでバッファー ID によって参照される入力バッファーと出力バッファーのセットを保持します。 クライアントへの #start
呼び出しが成功した後、入力バッファーも出力バッファーも "所有" しません。 同期モードでは、 を呼び出 #dequeueInputBuffer dequeueInput
/#dequeueOutputBuffer OutputBuffer(…)
して、コーデックから入力バッファーまたは出力バッファーを取得 (所有権の取得) します。 非同期モードでは、コールバックを介して使用可能なバッファーを自動的に Callback#onInputBufferAvailable MediaCodec.Callback.onInput
/Callback#onOutputBufferAvailable OutputBufferAvailable(…)
受け取ります。
入力バッファーを取得したら、データを入力し、&ndash を使用して #queueInputBuffer queueInputBuffer
コーデックに送信するか #queueSecureInputBuffer queueSecureInputBuffer
、復号化を使用する場合はコーデックに送信します。 同じタイムスタンプを持つ複数の入力バッファーを送信しないでください (コーデック固有のデータとしてマークされている場合を除く)。
次に、コーデックは、非同期モードのコールバックを介して、または同期モードでの呼び出しに応答して Callback#onOutputBufferAvailable onOutputBufferAvailable
、読み取り専用出力バッファーを #dequeueOutputBuffer dequeueOutputBuffer
返します。 出力バッファーが処理されたら、いずれかのメソッドを #releaseOutputBuffer releaseOutputBuffer
呼び出して、バッファーをコーデックに返します。
コーデックにすぐにバッファーを再送信または解放する必要はありませんが、入力バッファーまたは出力バッファーを保持するとコーデックが停止する可能性があり、この動作はデバイスによって異なります。 <厳密>には、すべての</em> 未処理のバッファーが解放/再送信されるまで<>、コーデックが出力バッファーの生成を保留する可能性があります。</strong> そのため、可能な限り少ない限り使用可能なバッファーを保持してみてください。
API バージョンに応じて、3 つの方法<でデータを処理できます。table><thead><tr<>th>Processing Mode</th><th>API バージョン <= 20<br>Jelly Bean/KitKat</th api>><version >= 21<br>Lollipop 以降</th<>/tr></thead<>tbody tr><td><>buffer arrays</td td td<>>Supported</td を使用した同期 APItd>Deprecated</td></tr tr><td><>buffers</td<>td class=NA>Not Available</td td td<>>Supported</td<>/tr tr><td><>Buffers</td><td class=NA>Not Available</td td<>td>Supported</td></tr></tbody></table を使用した同期 API ><>
<h4>バッファー/h4 を<使用した非同期処理>
の android.os.Build.VERSION_CODES#LOLLIPOP
推奨される方法は、 を呼び出す #configure configure
前にコールバックを設定してデータを非同期的に処理することです。 非同期モードでは、 を呼び出#start
#flush
してコーデックを Running サブ状態に移行し、入力バッファーの受信を開始する必要があるため、状態遷移が若干変わります。 同様に、コーデックへの start
最初の呼び出し時に、実行中のサブ状態に直接移動し、コールバックを介して使用可能な入力バッファーの渡しを開始します。
<center><img src="../../../images/media/mediacodec_async_states.svg" style="width: 516px;height: 353px" alt="MediaCodec state diagram for asynchronous operation"></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
…
codec.queueInputBuffer(inputBufferId, …);
}
{@literal @Override}
void onOutputBufferAvailable(MediaCodec mc, int outputBufferId, …) {
ByteBuffer outputBuffer = codec.getOutputBuffer(outputBufferId);
MediaFormat bufferFormat = codec.getOutputFormat(outputBufferId); // option A
// bufferFormat is equivalent to mOutputFormat
// outputBuffer is ready to be processed or rendered.
…
codec.releaseOutputBuffer(outputBufferId, …);
}
{@literal @Override}
void onOutputFormatChanged(MediaCodec mc, MediaFormat format) {
// Subsequent data will conform to new format.
// Can ignore if using getOutputFormat(outputBufferId)
mOutputFormat = format; // option B
}
{@literal @Override}
void onError(…) {
…
}
{@literal @Override}
void onCryptoError(…) {
…
}
});
codec.configure(format, …);
mOutputFormat = codec.getOutputFormat(); // option B
codec.start();
// wait for processing to complete
codec.stop();
codec.release();
<h4>バッファー</h4 を使用した同期処理>
以降android.os.Build.VERSION_CODES#LOLLIPOP
では、同期モードでコーデックを使用する場合でも、 や #getInputImage getInput
/#getOutputImage OutputImage(int)
を使用して#getInputBuffer getInput
/#getOutputBuffer OutputBuffer(int)
入力バッファーと出力バッファーを取得する必要があります。 これにより、動的コンテンツを処理する場合など、フレームワークによる特定の最適化が可能になります。 を呼び出 #getInputBuffers getInput
/#getOutputBuffers OutputBuffers()
すと、この最適化は無効になります。
<p class=note><strong>Note:</strong> では、バッファーとバッファー配列を同時に使用するメソッドは混在しません。 具体的には、 の値#INFO_OUTPUT_FORMAT_CHANGED
を使用して出力バッファー ID をデキューした直後#start
または後にのみ を呼び出getInput
/OutputBuffers
します。
MediaCodec は通常、同期モードで次のように使用されます。
MediaCodec codec = MediaCodec.createByCodecName(name);
codec.configure(format, …);
MediaFormat outputFormat = codec.getOutputFormat(); // option B
codec.start();
for (;;) {
int inputBufferId = codec.dequeueInputBuffer(timeoutUs);
if (inputBufferId >= 0) {
ByteBuffer inputBuffer = codec.getInputBuffer(…);
// fill inputBuffer with valid data
…
codec.queueInputBuffer(inputBufferId, …);
}
int outputBufferId = codec.dequeueOutputBuffer(…);
if (outputBufferId >= 0) {
ByteBuffer outputBuffer = codec.getOutputBuffer(outputBufferId);
MediaFormat bufferFormat = codec.getOutputFormat(outputBufferId); // option A
// bufferFormat is identical to outputFormat
// outputBuffer is ready to be processed or rendered.
…
codec.releaseOutputBuffer(outputBufferId, …);
} else if (outputBufferId == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
// Subsequent data will conform to new format.
// Can ignore if using getOutputFormat(outputBufferId)
outputFormat = codec.getOutputFormat(); // option B
}
}
codec.stop();
codec.release();
<h4>バッファー配列を使用した同期処理 (非推奨)</h4>
バージョン android.os.Build.VERSION_CODES#KITKAT_WATCH
以前では、入力バッファーと出力バッファーのセットは 配列によって ByteBuffer[]
表されます。 への #start
呼び出しが成功した後、 を使用して #getInputBuffers getInput
/#getOutputBuffers OutputBuffers()
バッファー配列を取得します。 次のサンプルに示すように、バッファー ID をこれらの配列のインデックスとして使用します (負でない場合)。 配列サイズには上限がありますが、配列のサイズとシステムで使用される入出力バッファーの数には固有の相関関係がないことに注意してください。
MediaCodec codec = MediaCodec.createByCodecName(name);
codec.configure(format, …);
codec.start();
ByteBuffer[] inputBuffers = codec.getInputBuffers();
ByteBuffer[] outputBuffers = codec.getOutputBuffers();
for (;;) {
int inputBufferId = codec.dequeueInputBuffer(…);
if (inputBufferId >= 0) {
// fill inputBuffers[inputBufferId] with valid data
…
codec.queueInputBuffer(inputBufferId, …);
}
int outputBufferId = codec.dequeueOutputBuffer(…);
if (outputBufferId >= 0) {
// outputBuffers[outputBufferId] is ready to be processed or rendered.
…
codec.releaseOutputBuffer(outputBufferId, …);
} else if (outputBufferId == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
outputBuffers = codec.getOutputBuffers();
} else if (outputBufferId == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
// Subsequent data will conform to new format.
MediaFormat format = codec.getOutputFormat();
}
}
codec.stop();
codec.release();
<h4>ストリームの終了処理</h4>
入力データの末尾に到達したら、 の呼び出しで フラグを #BUFFER_FLAG_END_OF_STREAM
指定してコーデックに通知する #queueInputBuffer queueInputBuffer
必要があります。 これは、最後に有効な入力バッファーに対して行うか、ストリームの終わりフラグが設定された空の追加の入力バッファーを送信することによって行うことができます。 空のバッファーを使用している場合、タイムスタンプは無視されます。
コーデックは、最終的に 出力ストリームの終わりを通知するまで、出力バッファーを引き続き返します。この場合、セット#dequeueOutputBuffer dequeueOutputBuffer
内で同じストリームの終了フラグをBufferInfo
指定するか、 を介してCallback#onOutputBufferAvailable onOutputBufferAvailable
返されます。 これは、最後の有効な出力バッファーで設定することも、最後の有効な出力バッファーの後の空のバッファーに設定することもできます。 このような空のバッファーのタイムスタンプは無視する必要があります。
コーデックがフラッシュされていない限り、またはコーデックが停止して再起動されない限り、入力ストリームの末尾にシグナルを送信した後は、追加の入力バッファーを送信しないでください。
<h4>出力サーフェス<の使用/h4>
データ処理は、出力を使用する場合の ByteBuffer モードとほぼ同じです。ただし、出力 Surface
バッファーにはアクセスできません。値として null
表されます。 たとえば #getOutputBuffer getOutputBuffer
/#getOutputImage Image(int)
、 は を返 null
し #getOutputBuffers
、-s のみを null
含む配列を返します。
出力 Surface を使用する場合は、各出力バッファーをサーフェスにレンダリングするかどうかを選択できます。 次の 3 つの選択肢があります。ul>li strong バッファーをレンダリングしません:</strong> 呼び出し#releaseOutputBuffer(int, boolean) releaseOutputBuffer(bufferId, false)
。<>><<</li li>><<strong>既定の timestamp:</strong> 呼び出し#releaseOutputBuffer(int, boolean) releaseOutputBuffer(bufferId, true)
を使用してバッファーをレンダリングします。</li li>><<strong>特定の timestamp:</strong> 呼び出しを使用してバッファーをレンダリング#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
前は未定義でしたが、View サーフェス (SurfaceView または TextureView) は常に過剰なフレームをドロップするという例外があります。 既定の動作では過剰なフレームが削除されるため android.os.Build.VERSION_CODES#Q
です。 アプリケーションは、SDK android.os.Build.VERSION_CODES#Q
をターゲットにし、キー MediaFormat#KEY_ALLOW_FRAME_DROP
を構成形式で に 0
設定することで、ビュー以外のサーフェス (ImageReader や SurfaceTexture など) に対してこの動作をオプトアウトできます。
<Surface</h4>にレンダリングするときの h4 変換>
コーデックが Surface モードに構成されている場合、トリミング四角形、MediaFormat#KEY_ROTATION 回転、#setVideoScalingMode ビデオ スケーリング モードは 1 つの例外で自動的に適用されます。 <p class=note> リリース前 android.os.Build.VERSION_CODES#M
は、ソフトウェア デコーダーが Surface にレンダリングされるときに回転が適用されていない可能性があります。 残念ながら、ソフトウェア デコーダーを識別する標準的で簡単な方法はありません。または、試してみる以外に回転を適用する場合は。
いくつかの注意事項もあります。 <p class=note> Surface に出力を表示する場合、ピクセル縦横比は考慮されません。 つまり、モードを使用 #VIDEO_SCALING_MODE_SCALE_TO_FIT
している場合は、出力 Surface を配置して、最終的な表示縦横比が適切になるようにする必要があります。 逆に、モードは正方形ピクセル (ピクセル縦横比または 1:1) のコンテンツにのみ使用 #VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING
できます。 <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>
入力 Surface を使用する場合、バッファーは入力サーフェスからコーデックに自動的に渡されるため、アクセス可能な入力バッファーはありません。 を呼び出#dequeueInputBuffer dequeueInputBuffer
すと、 がIllegalStateException
スローされ、#getInputBuffers
strong>MUST NOT</strong> が<書き込まれる偽ByteBuffer[]
の配列が返されます。
を呼び出 #signalEndOfInputStream
して、ストリームの終了を通知します。 入力サーフェスは、この呼び出しの直後にコーデックへのデータの送信を停止します。
<h3>シーク &&アダプティブ再生のサポート</h3>
ビデオ デコーダー (および圧縮されたビデオ データを使用する一般的なコーデック) は、アダプティブ再生をサポートし、構成されているかどうかに関係なく、シークとフォーマットの変更に関して動作が異なります。 デコーダーが CodecCapabilities#FEATURE_AdaptivePlayback を介したCodecCapabilities#isFeatureSupported CodecCapabilities.isFeatureSupported(String)
アダプティブ再生をサポートしているかどうかをチェックできます。 ビデオ デコーダーのアダプティブ再生のサポートは、 に Surface
デコードするようにコーデックを構成した場合にのみアクティブになります。
<h4 id=KeyFrames>"KeyFrames">Stream Boundary and Key Frames</h4>
入力データは、適切なストリーム境界の後 #start
、または #flush
開始することが重要です。最初のフレームはキー フレームである必要があります。 <em>キー フレーム</em> は、単独で完全にデコードできます (ほとんどのコーデックでは、これは I フレームを意味します)、キー フレームの後に表示されるフレームはキー フレームの前のフレームを参照しません。
次の表は、さまざまなビデオ形式に適したキー フレームをまとめたものです。 <テーブル>thead><tr><th>Format</th><th>Suitable key frame</th></tr></thead><tbody class=mid><tr><td>VP9/VP8</td td>><a suitable intraframe where no subsequent frames refer to frames prior to this frame.<<br>(このようなキー フレームには特定の名前はありません。)</td></tr td><><>H.265 HEVC</td td><td>IDR または CRA</td<>/tr tr><td<>>H.264 AVC</td><td td>IDR</td/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
しないでください。形式の不連続性はサポートされていません。そのため、完全#start
- - #stop
#configure configure(…)
なサイクルが必要です。><
<p class=note><strong>また、&ndash の後#start
にコーデックをフラッシュする場合も注意<>してください。一般に、最初の出力バッファーまたは出力形式の変更を ndash &受信する前に、コーデック固有のデータをコーデックに再送信する必要があります。 詳細については、コーデック固有のデータに関するセクションを参照してください。
<h4>アダプティブ再生</h4 をサポートし、構成されているデコーダーの場合>
以前に送信されたデータ (シーク後) に隣接していないデータのデコードを開始するには、デコーダーをフラッシュする必要<はありません。>ただし、不連続の後の入力データは<>、適切なストリーム境界/キー フレームから開始する必要があります。
一部のビデオ形式 (つまり、H.264、H.265、VP8、VP9) では、画像のサイズや構成のミッドストリームを変更することもできます。 これを行うには、新しいコーデック固有の構成データ全体をキー フレームと共に 1 つのバッファー (開始コードを含む) にパッケージ化し、強力>な標準</強力>な<入力バッファーとして送信する必要があります。
画像サイズの#INFO_OUTPUT_FORMAT_CHANGED
変更が行われた直後、および新しいサイズのフレームが返される前に、 または Callback#onOutputBufferAvailable onOutputFormatChanged
コールバックから#dequeueOutputBuffer dequeueOutputBuffer
戻り値を受け取ります。 <p class=note><strong>注:</strong> コーデック固有のデータの場合と同様に、画像サイズを変更した直後に を呼び出 #flush
すときは注意してください。 画像サイズの変更の確認を受け取っていない場合は、新しい画像サイズの要求を繰り返す必要があります。
<h3>エラー処理</h3>
ファクトリ メソッド#createByCodecName createByCodecName
と#createEncoderByType EncoderByType
#createDecoderByType createDecoder
/は、成功するためにキャッチまたは宣言する必要があるエラー時に をスローIOException
します。 MediaCodec メソッドは、許可しないコーデック状態からメソッドが呼び出されたときに スロー IllegalStateException
します。これは通常、アプリケーション API の使用が正しくないためです。 セキュリティで保護されたバッファーを含むメソッドは をスロー CryptoException
する可能性があります。これにより、 から CryptoException#getErrorCode
さらにエラー情報を取得できます。
内部コーデック エラーにより、 が発生 CodecException
します。これは、アプリケーションが API を正しく使用している場合でも、メディア コンテンツの破損、ハードウェアの障害、リソースの枯渇などが原因である可能性があります。 をCodecException
受け取るときに推奨されるアクションは、 と <CodecException#isTransient
を呼び出CodecException#isRecoverable
すことによって決定できます。ul><li><強力>な回復可能なエラー:</strong> If が true を返した後isRecoverable()
、、#configure configure(…)
#start
、 を呼び出#stop
して回復します。</li li strong transient errors:/strong If returns true, then resources is temporarily unavailable and the method may be retried at later time. (/li li li><><strong>transient errors:</strong> If isTransient()
returns true, then resources is temporarily unavailable and the method may be retried at after time.</li li><<>強力な>致命的なエラー:</strong> 両方とも isTransient()
isRecoverable()
false を返す場合CodecException
、 は致命的であり、コーデックをリセット #reset するか、#release リリースする必要があります。</li></ul>
と isTransient()
の両方isRecoverable()
が同時に true を返しません。
<h2 id=History>"History">Valid API Calls and API History</h2>
このセクションでは、各状態の有効な API 呼び出しと、MediaCodec クラスの API 履歴を要約します。 API のバージョン番号については、「」を参照してください 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; height: 83px;} .deg45 > div { transform: skew(-45deg, 0deg) translate(1px, -67px); transform-origin: 左下 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); }</スタイル>
<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>セマンティクス changed</td></tr tr>><<td>○</td td>試験的サポート</td><></tr tr>><<td<>[ ]</td td>><Deprecated</td></tr tr><<>td>⎋</td td><td>Surface input mode</td></tr tr><<>td>⎆</td td>><Restricted to surface output mode</td></tr tr><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></tr tr><><td>( )</td td><td>呼び出すことができますが、t</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 th><class=deg45><div><div style="background:#f4b400"><div>Configured</div></div><></th><class=deg45><div><div style="background:#e67c73"><div>Flushed</div></div></th><>< class=deg45><div><div style="background:#0f9d58"><div>Running</div></div><></th<>th class=deg45><div><div style="background:#f7cb4d"><div>End of Stream</div></div><></th><class=deg45><div div><style="background:#db4437"><div>Error</div></div></div></th><th class=deg45><div><div style="background:#666"div>><Released</div></div></div></th/th>><<th>< colspan="8">SDK Version</th<>/tr tr>><<th colspan="7">State</th th<>>Method</th>><16</th<>>17/th>><18</th>><19</th 19</th<>>20</th><>21</th th th><>22</th>><23</th<>/tr></thead<>tbody class=api><tr><td></td><td></td<><> td/td><>< td td/><><td>><< td td/><td<>td>< td class=fn>#createByCodecName createByCodecName
</td<>td td>●</td><td>●</td><td>●</td><td>●</td<>td>●/td><td>●<</td><td>●/td<>td>●<</td<>/tr tr><<>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>><<td></td<>td></><<><>td td>< td/td><td td></Td><td></td><td><>< td class=fn>#createEncoderByType createEncoderByType
</td td><td>●</td><td>●/td<>td>●</td<>td>●<</td<>td>●</td><td>●</td<>td td>●/td td>●<</td><></tr<>td<>></td><td></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><>●</td></tr<>><td>-</td td>><18+</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>⎋</td<>/tr<>td><>-<</<>td<>td td> td>16+/td td td>16+<</td t><><>(16+)</td><td><>-</td<>><td td class=fn/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>16+/td><td td>16+</td><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<>/tr tr<><>td>-<</td<><>td td>> 16+</td<>td td>16+</td><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><<>td>18+</td td td>18+</td><><td>18+</td><td>18+</Td><td>18+</td><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>●<</td<>/tr tr><><td>-</td><td>-</td td>><(21+)</td><td>21+</td td><>(21+)</td><td>>-<</td<><>td td class=fn#getInputBuffer getInputBuffer
<>/td<>td></td><td></td><td></td<>td></td<>td>< td/td><td td><●/td td>><●/td td>><●<</td></tr<>td<>>-/td td><td>-<</td<>td td>16+</td<>td>(16+)</td><td>(16+)</td<>td>-</td td><td>-</td><td class=fn#getInputBuffers getInputBuffers
<>/td td●><></Td><td>●</td td>><●</td td<>>●</td td<>>●</td<>td> [⁕↩]</td td<>>[↩]<// td td><>[↩]</td></tr tr>><<td>-</td><td td>21+</td td><>(21+)</td td>><(21+)</td td td><>(21+)</td><td>-</td<>td td>-</td td<>td class=fn><#getInputFormat getInputFormat
/td<>td></td><td></><td td>< td/><><<><><>>td●</td><td●/td<>td>>●<</td/tr><><> td><-</td><td>-</td td>><(21+)</td<>td td>21+</td td>><(21+)</td><td>>-<</td<><>td td class=fn#getInputImage getInputImage
<>/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 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/tr<<>>td>><-</td><td>-</td><td>(21+)</td<>td>21+</td><td td>21+</td><td>-<</td<>><td td> class=fn><#getOutputBuffer getOutputBuffer
/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>td>16+<</td<>td>-/td td td>-<</td><<>td td class=fn#getOutputBuffers getOutputBuffers
<>/td td><></td td><>●/td td●</td><td>●</td><td>●</td<>td td>●</td><td td>[⁕↩]</td<>td>[↩]</td<>td>[↩]</td<>/tr tr><><td>-</td td>21+</td><td●><td>16+</td<>td>16+</td><td td>16+</td<>td> td-<</><td td><td> class=fn>#getOutputFormat()
</td><td <>●/td><td <>●/td><td>●</td td>●/td>><<td>●/<<td><td>●</td<>td>●</td td><td>●</td<>/tr><tr><td>-<</td><<>td td>>(21+)</td<>td>21+</td<>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 td>●</td<>td>●</td<>/tr tr<>><td>-</td><td td><><(21+)</td td>>< td>21+</td><td td>21+</td><td td>-</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></tr tr<<>>td>-</td<>td td>-</td><td td>-</td><td td>16+</td<>td>(16+)</td><td>-<</td<><>td td> class=fn><#queueInputBuffer queueInputBuffer
/td<>td td>●</td td><td></td td>><●/td td>●</td<>><td●</td><td>>⁕</td<>td>●<</td<>td>●</td/tr><><td<>>-</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><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>●</td/tr><><td><>-</td<>td td>-<</td><><td> td>16+</td><td td>16+</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>><⁕</td<>/tr td>>><<-</td td><td>-<</<>td<>td> td>21+</td><td td>21+</td><td>-</td><td td<>>< class=fn>#releaseOutputBuffer(int, long)
</td><td></td><td></td><td>< td></td<><>td></td td<>td>⎆</td<>td>⎆</td><td>⎆</td<>/tr td>><<>21+</td<>td td>21+</td><td>21+</td td td><td21+/td<>td>21+</td td><td>21+</td td><td>-</td td<>class=fn#reset reset
></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<> class=fn><#setCallback(Callback) setCallback
/td<>td></td td<><>/td td td><td></Td><td></td><td></td><td td>●</td td><>●</td<>td<>#setCallback(Callback, Handler) ⁕
/td<>/tr tr>><<td>-</td<>td td>23+</td><td>-</td<>td>-</td><td>-</td><td>-</td><td>-</td td<>class=fn><#setInputSurface setInputSurface
/td td<>td></td<>td></td><td></td><<> td/td><td><<><> td/td><<>td>><⎋</td></tr tr><><td>23+</td td 23+</td><td>><td>23+</td><td>23+</td<>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><td>○ ⎆</td<>/tr td><>><-</td td<>td>23+</td><td>23+</td<>td>23+</td><td td>23+</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><><td>19+</td<>td>19+</td<>td>19+</td><td>19+/td<>td>19+<</td td 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>●</td<>/tr tr><><td>-</td td>><(16+)</td<>td>(16+)</td><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<>td>⎆</td<>/tr tr>><<td>(29+)</td><td>29+</td><td td>29+</td><td>29+</td td<>>(29+)/<td td><>(29+)</td<>td>-</td td<>td class=fn#setAudioPresentation setAudioPresentation
></td><td></td><td></td><td></td<>>><< td></td><td></td><td></td><td></td/tr<><>td><-</td>><td>-</td><td>18+</td<>td td>18+</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 td<>>⎋</td<>/tr<>td><>-</td td><td>>16+<(><⇄)</td 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<>td><>-</td td<>>-/<td><td>16+</td><td>16+</td<>td td>16+</td><td> td-<</><td<>td td> class=fn#stop stop
<>/td<>td td>●</td><td <>●/td<>td <>●/td<>td>●</td><td●></Td><td●/td td>><●</td td<>>●</td></tr></tbody></table <>>
の Java ドキュメント android.media.MediaCodec
。
このページの一部は、によって作成および共有され、に記載されている条件に従って使用される作業に基づく変更です。
フィールド
BufferFlagCodecConfig |
古い.
これにより、そのようにマークされたバッファーに、メディア データの代わりにコーデックの初期化/コーデック固有のデータが含まれていることが示されました。 |
BufferFlagDecodeOnly |
古い.
これは、バッファーがデコードされ、デコーダーの内部状態が更新されますが、出力バッファーは生成されないことを示します。 |
BufferFlagEndOfStream |
古い.
これは、ストリームの終了を通知します, i. |
BufferFlagKeyFrame |
古い.
これは、そのようにマークされた (エンコードされた) バッファーにキー フレームのデータが含まれていることを示します。 |
BufferFlagPartialFrame |
古い.
これは、バッファーにフレームの一部のみが含まれていることを示します。デコーダーは、フレームをデコードする前に、このフラグのないバッファーが表示されるまでデータをバッチ処理する必要があります。 |
BufferFlagSyncFrame |
古い.
これは、そのようにマークされた (エンコードされた) バッファーにキー フレームのデータが含まれていることを示します。 |
ConfigureFlagEncode |
古い.
このコーデックをエンコーダーとして使用する場合は、このフラグを渡します。 |
ConfigureFlagUseBlockModel |
古い.
このコーデックを や |
ConfigureFlagUseCryptoAsync |
古い.
このフラグは、セキュリティで保護されたデコーダーでのみ使用する必要があります。 |
CryptoModeAesCbc |
古い.
MediaCodec クラスを使用して、低レベルのメディア コーデック (i) にアクセスできます。 |
CryptoModeAesCtr | |
CryptoModeUnencrypted | |
InfoOutputBuffersChanged |
古い.
出力バッファーが変更されました。クライアントは、この時点から によって |
InfoOutputFormatChanged |
古い.
出力形式が変更され、後続のデータは新しい形式に従います。 |
InfoTryAgainLater |
古い.
への呼び出しで負以外のタイムアウトが指定されている場合は |
ParameterKeyHdr10PlusInfo |
次のキューに入った入力フレームに HDR10 以降のメタデータを設定します。 |
ParameterKeyLowLatency |
待機時間の短いデコード モードを有効または無効にします。 |
ParameterKeyOffsetTime |
タイムスタンプの上に追加するオフセット (マイクロ秒単位) を指定します。 |
ParameterKeyRequestSyncFrame |
エンコーダーが "間もなく" 同期フレームを生成することを要求します。 |
ParameterKeySuspend |
入力データのエンコードを一時的に中断または再開します。 |
ParameterKeySuspendTime |
が存在する場合 |
ParameterKeyTunnelPeek |
が一時停止されている間に、コーデックがトンネル モード |
ParameterKeyVideoBitrate |
ビデオ エンコーダーのターゲット ビットレートをその場で変更します。 |
VideoScalingModeScaleToFit |
古い.
コンテンツはサーフェスの寸法に合わせてスケーリングされます |
VideoScalingModeScaleToFitWithCropping |
古い.
コンテンツは拡大縮小され、そのアスペクト比を維持し、表面積全体が使用され、コンテンツはトリミングされ得る。 |
プロパティ
CanonicalName |
基になるコーデック名を取得します。 |
Class |
この |
CodecInfo |
コーデック情報を取得します。 |
Handle |
基になる Android インスタンスへのハンドル。 (継承元 Object) |
InputFormat |
が正常に返された後 |
JniIdentityHashCode |
MediaCodec クラスを使用して、低レベルのメディア コーデック (i) にアクセスできます。 (継承元 Object) |
JniPeerMembers |
MediaCodec クラスを使用して、低レベルのメディア コーデック (i) にアクセスできます。 |
Metrics |
現在のコーデック インスタンスに関するメトリック データを返します。 |
Name |
コーデック名を取得します。 |
OutputFormat |
dequeueOutputBuffer が を返すことによって形式の変更を通知した後に、これを呼び出します |
PeerReference |
MediaCodec クラスを使用して、低レベルのメディア コーデック (i) にアクセスできます。 (継承元 Object) |
SupportedVendorParameters |
ベンダー パラメーター名の一覧を返します。 |
ThresholdClass |
この API は Android 用 Mono インフラストラクチャをサポートしており、コードから直接使用することを意図したものではありません。 (継承元 Object) |
ThresholdType |
この API は Android 用 Mono インフラストラクチャをサポートしており、コードから直接使用することを意図したものではありません。 (継承元 Object) |
メソッド
Clone() |
このオブジェクトのコピーを作成して返します。 (継承元 Object) |
Configure(MediaFormat, Surface, MediaCodecConfigFlags, MediaDescrambler) |
descrambler で使用するコンポーネントを構成します。 |
Configure(MediaFormat, Surface, MediaCrypto, MediaCodecConfigFlags) |
コンポーネントを構成します。 |
CreateByCodecName(String) |
インスタンス化するコンポーネントの正確な名前がわかっている場合は、このメソッドを使用してインスタンス化します。 |
CreateDecoderByType(String) |
指定された MIME の種類の入力データをサポートする優先デコーダーをインスタンス化します。 |
CreateEncoderByType(String) |
指定された MIME の種類の出力データをサポートする優先エンコーダーをインスタンス化します。 |
CreateInputSurface() |
入力バッファーの代わりに、エンコーダーへの入力として使用する Surface を要求します。 |
CreatePersistentInputSurface() |
ビデオ エンコーダーなど、通常は入力サーフェスを持つコーデックで使用できる永続的な入力サーフェスを作成します。 |
DequeueInputBuffer(Int64) |
有効なデータが格納される入力バッファーのインデックスを返します。現在使用できるバッファーがない場合は -1 を返します。 |
DequeueOutputBuffer(MediaCodec+BufferInfo, Int64) |
出力バッファーをデキューし、最大で "timeoutUs" マイクロ秒をブロックします。 |
Dispose() |
MediaCodec クラスを使用して、低レベルのメディア コーデック (i) にアクセスできます。 (継承元 Object) |
Dispose(Boolean) |
MediaCodec クラスを使用して、低レベルのメディア コーデック (i) にアクセスできます。 (継承元 Object) |
Equals(Object) |
他のオブジェクトがこのオブジェクトと "等しい" かどうかを示します。 (継承元 Object) |
Flush() |
コンポーネントの入力ポートと出力ポートの両方をフラッシュします。 |
GetHashCode() |
オブジェクトのハッシュ コード値を返します。 (継承元 Object) |
GetInputBuffer(Int32) |
入力データを |
GetInputBuffers() |
古い.
入力バッファーのセットを取得します。 |
GetInputImage(Int32) |
未加工の入力ビデオ フレームを含むデキューされた入力バッファー インデックスの書き込み可能な Image オブジェクトを返します。 |
GetOutputBuffer(Int32) |
デキューされた出力バッファー インデックスの読み取り専用 ByteBuffer を返します。 |
GetOutputBuffers() |
古い.
出力バッファーのセットを取得します。 |
GetOutputFormat(Int32) |
特定の出力バッファーの出力形式を返します。 |
GetOutputFrame(Int32) |
|
GetOutputImage(Int32) |
未加工のビデオ フレームを含むデキューされた出力バッファー インデックスの読み取り専用 Image オブジェクトを返します。 |
GetParameterDescriptor(String) |
名前を使用してパラメーターを記述します。 |
GetQueueRequest(Int32) |
入力スロット インデックスの |
JavaFinalize() |
ガベージ コレクションがオブジェクトへの参照がなくなったと判断したときに、オブジェクトのガベージ コレクターによって呼び出されます。 (継承元 Object) |
MapHardwareBuffer(HardwareBuffer) |
バッファーの |
Notify() |
このオブジェクトのモニターで待機している 1 つのスレッドをウェイクアップします。 (継承元 Object) |
NotifyAll() |
このオブジェクトのモニターで待機しているすべてのスレッドをウェイクアップします。 (継承元 Object) |
QueueInputBuffer(Int32, Int32, Int32, Int64, MediaCodecBufferFlags) |
指定したインデックス位置にある入力バッファーの範囲を入力した後、それをコンポーネントに送信します。 |
QueueSecureInputBuffer(Int32, Int32, MediaCodec+CryptoInfo, Int64, MediaCodecBufferFlags) |
に |
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) |
コーデックを構成します (例: |
SetOnFirstTunnelFrameReadyListener(Handler, MediaCodec+IOnFirstTunnelFrameReadyListener) |
最初の出力フレームがデコードされ、 を使用してトンネル モード用に構成されたコーデックでレンダリングする準備ができたときに呼び出されるコールバックを |
SetOnFrameRenderedListener(MediaCodec+IOnFrameRenderedListener, Handler) |
出力フレームが出力サーフェイスにレンダリングされるときに呼び出されるコールバックを登録します。 |
SetOutputSurface(Surface) |
コーデックの出力サーフェスを動的に設定します。 |
SetParameters(Bundle) |
コンポーネント インスタンスに追加のパラメーター変更を伝えます。 |
SetVideoScalingMode(VideoScalingMode) |
の以前の呼び出し |
SignalEndOfInputStream() |
入力時にストリームの終わりを通知します。 |
Start() |
コンポーネントが正常に構成されたら、 を呼び出します |
Stop() |
デコード/エンコード セッションを終了します。コーデック インスタンスはアクティブなままで、もう一度有効になる準備ができていることに |
SubscribeToVendorParameters(IList<String>) |
ベンダー パラメーターをサブスクライブして、これらのパラメーターが に |
ToArray<T>() |
MediaCodec クラスを使用して、低レベルのメディア コーデック (i) にアクセスできます。 (継承元 Object) |
ToString() |
オブジェクトの文字列形式を返します。 (継承元 Object) |
UnregisterFromRuntime() |
MediaCodec クラスを使用して、低レベルのメディア コーデック (i) にアクセスできます。 (継承元 Object) |
UnsubscribeFromVendorParameters(IList<String>) |
ベンダー パラメーターの登録を解除して、これらのパラメーターが存在 |
Wait() |
現在のスレッドが起動するまで待機します。通常<>は、通知</em> または <em>割り込み</em によって待機します>。 (継承元 Object) |
Wait(Int64) |
現在のスレッドが起動するまで待機します。通常<>は、通知</em> または>< em 割り込み</em>、または一定のリアルタイムが経過するまで待機します。 (継承元 Object) |
Wait(Int64, Int32) |
現在のスレッドが起動するまで待機します。通常<>は、通知</em> または>< em 割り込み</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) にアクセスできます。 |