もう一度Androids MediaCodecクラスに関する私の質問。私は生のh264コンテンツをデコードし、その結果を2つのTextureViewに表示することに成功しました。 h264ストリームは、OpenGLシーンを実行しているサーバーからのものです。シーンにはカメラがあり、ユーザの入力に反応します。サーバー上の入力とスマートフォンでの実際の結果との間のレイテンシをさらに減らすために、私はMediaCodecs非同期モードを使用することを考えていました。ここで は、同期および非同期、私は両方のバリアントを設定する方法である:Android MediaCodecは非同期モードでは同期モードよりも遅いですか?
非同期:
//decoderCodec is "video/avc"
MediaFormat fmt = MediaFormat.createVideoFormat(decoderCodec, 1280,720);
codec.setCallback(new MediaCodec.Callback() {
@Override
public void onInputBufferAvailable(MediaCodec codec, int index) {
byte[] frameData;
try {
frameData = frameQueue.take(); //this call is blocking
} catch (InterruptedException e) {
return;
}
ByteBuffer inputData = codec.getInputBuffer(index);
inputData.clear();
inputData.put(frameData);
codec.queueInputBuffer(index, 0, frameData.length, 0, 0);
}
@Override
public void onOutputBufferAvailable(MediaCodec codec, int index, MediaCodec.BufferInfo info) {
codec.releaseOutputBuffer(index, true);
}
//The two other methods are left blank at the moment.
});
codec.configure(fmt, surface, null, 0);
codec.start();
同期:(codec.setCallback(...)
一部を除いて、非同期のように設定され、両方の変異体が中に存在するクラスがあります。 Runnableを。
public void run() {
while(!Thread.interrupted())
{
if(!IS_ASYNC) {
byte[] frameData;
try {
frameData = frameQueue.take(); //this call is blocking
} catch (InterruptedException e) {
break;
}
int inIndex = codec.dequeueInputBuffer(BUFFER_TIMEOUT);
if (inIndex >= 0) {
ByteBuffer input = codec.getInputBuffer(inIndex);
input.clear();
input.put(frameData);
codec.queueInputBuffer(inIndex, 0, frameData.length, 0, 0);
}
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
int outIndex = codec.dequeueOutputBuffer(bufferInfo, BUFFER_TIMEOUT);
if(outIndex >= 0)
codec.releaseOutputBuffer(outIndex, true);
}
else sleep(3000); //Just for testing, if we are in Async, this thread has nothing to do actually...
}
}
の両方が仕事に近づくが、私は、同期モードでプレイ動画がはるかにsmootheであることを観察していますrとレイテンシも低くなります。
frameQueue
がLinkedBlockingDeque
であると私は思った、新しいフレームデータが到着するのを同期デコーダが長すぎる待機している場合、デコード出力はすでに利用可能かもしれないがために表示されていないので、私は非同期モードを使用してのアイデアを思い付きましたキューのブロック性質の一方、私は忙しい待って、キュー、inputBuffersとoutputBuffersすべての時間をポーリングするような何かをしたいと思っていません。
私はコールバックを使用してAsyncModeを試しましたが、結果は同期モードより悪くなっています。皆さんへの質問は、今、なぜですか?私は非同期モードを誤用するのですか、それとも別のものですか?
フィードバックありがとうございます。
クリストフ
あなたは正しいです。同じスレッドから呼び出されたようです。私は作業コードで質問を更新します。 – Christoph
元の質問を新しい固定コードで更新しないでください。後で誰かがこの問題を読んで(まあまあです!)、全く固定されたコードで質問を読んでも意味がありません。固定コードを共有する場合は、固定コードを追加します。質問の終わりに別のセクションとして明示的に編集としてマークし、これが固定バージョンであるとのコメントを表示します。 – mstorsjo