私は、マイクからのオーディオ(didGetAudioDataの上書き)とカメラからのビデオ(onpreviewframeを上書き)を多重化してmp4ファイルを作成したいと思います。同期の問題では、ビデオはオーディオよりも速く表示されます。私は互換性のない設定やpresentationTimeUsに関連する問題が誰かに私の問題の解決方法を教えてくれるのかどうか疑問に思いました。私のソフトウェアは以下の通りです。mp4ファイルにmediacodecとmediamuxerを使用すると、オーディオとビデオのトラック同期の問題が発生する
ビデオ設定
formatVideo = MediaFormat.createVideoFormat(MIME_TYPE_VIDEO, 640, 360);
formatVideo.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar);
formatVideo.setInteger(MediaFormat.KEY_BIT_RATE, 2000000);
formatVideo.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
formatVideo.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5);
は、以下のようにビデオpresentationPTS、以下のようにオーディオpresentationPTSを得た
format = MediaFormat.createAudioFormat(MIME_TYPE, 48000/*sample rate*/, AudioFormat.CHANNEL_IN_MONO /*Channel config*/);
format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
format.setInteger(MediaFormat.KEY_SAMPLE_RATE,48000);
format.setInteger(MediaFormat.KEY_CHANNEL_COUNT,1);
format.setInteger(MediaFormat.KEY_BIT_RATE,64000);
if(generateIndex == 0) {
videoAbsolutePtsUs = 132;
StartVideoAbsolutePtsUs = System.nanoTime()/1000L;
}else {
CurrentVideoAbsolutePtsUs = System.nanoTime()/1000L;
videoAbsolutePtsUs =132+ CurrentVideoAbsolutePtsUs-StartVideoAbsolutePtsUs;
}
generateIndex++;
オーディオ構成を、持っ
if(generateIndex == 0) {
audioAbsolutePtsUs = 132;
StartAudioAbsolutePtsUs = System.nanoTime()/1000L;
}else {
CurrentAudioAbsolutePtsUs = System.nanoTime()/1000L;
audioAbsolutePtsUs =CurrentAudioAbsolutePtsUs - StartAudioAbsolutePtsUs;
}
generateIndex++;
audioAbsolutePtsUs = getJitterFreePTS(audioAbsolutePtsUs, audioInputLength/2);
long startPTS = 0;
long totalSamplesNum = 0;
private long getJitterFreePTS(long bufferPts, long bufferSamplesNum) {
long correctedPts = 0;
long bufferDuration = (1000000 * bufferSamplesNum)/48000;
bufferPts -= bufferDuration; // accounts for the delay of acquiring the audio buffer
if (totalSamplesNum == 0) {
// reset
startPTS = bufferPts;
totalSamplesNum = 0;
}
correctedPts = startPTS + (1000000 * totalSamplesNum)/48000;
if(bufferPts - correctedPts >= 2*bufferDuration) {
// reset
startPTS = bufferPts;
totalSamplesNum = 0;
correctedPts = startPTS;
}
totalSamplesNum += bufferSamplesNum;
return correctedPts;
}
私の問題は、オーディオ専用のジッタ機能を適用したことが原因でしたか?はいの場合、ビデオにジッタ機能を適用するにはどうすればよいですか?私も正しいオーディオとビデオのプレゼンテーションを見つけようとしました.PTSはhttps://android.googlesource.com/platform/cts/+/jb-mr2-release/tests/tests/media/src/android/media/cts/EncodeDecodeTest.javaです。しかし、encodedecodeTestはビデオPTSのみを提供しました。それが、私の実装がオーディオとビデオの両方にシステムナノタイムを使用した理由です。もし、私がビデオのプレゼンテーションを使用したいのであれば、どのようにオーディオプレゼンテーションを作成するのですか?手伝ってくれてありがとう!
以下は、私が参照するためにビデオmediacodecにyuvフレームをキューする方法です。オーディオ部分については、それは異なるプレゼンテーションPTSを除いて同一である。私は自分のアプリケーションでこれを解決する方法
int videoInputBufferIndex;
int videoInputLength;
long videoAbsolutePtsUs;
long StartVideoAbsolutePtsUs, CurrentVideoAbsolutePtsUs;
int put_v =0;
int get_v =0;
int generateIndex = 0;
public void setByteBufferVideo(byte[] buffer, boolean isUsingFrontCamera, boolean Input_endOfStream){
if(Build.VERSION.SDK_INT >=18){
try{
endOfStream = Input_endOfStream;
if(!Input_endOfStream){
ByteBuffer[] inputBuffers = mVideoCodec.getInputBuffers();
videoInputBufferIndex = mVideoCodec.dequeueInputBuffer(-1);
if (VERBOSE) {
Log.w(TAG,"[put_v]:"+(put_v)+"; videoInputBufferIndex = "+videoInputBufferIndex+"; endOfStream = "+endOfStream);
}
if(videoInputBufferIndex>=0) {
ByteBuffer inputBuffer = inputBuffers[videoInputBufferIndex];
inputBuffer.clear();
inputBuffer.put(mNV21Convertor.convert(buffer));
videoInputLength = buffer.length;
if(generateIndex == 0) {
videoAbsolutePtsUs = 132;
StartVideoAbsolutePtsUs = System.nanoTime()/1000L;
}else {
CurrentVideoAbsolutePtsUs = System.nanoTime()/1000L;
videoAbsolutePtsUs =132+ CurrentVideoAbsolutePtsUs - StartVideoAbsolutePtsUs;
}
generateIndex++;
if (VERBOSE) {
Log.w(TAG, "[put_v]:"+(put_v)+"; videoAbsolutePtsUs = " + videoAbsolutePtsUs + "; CurrentVideoAbsolutePtsUs = "+CurrentVideoAbsolutePtsUs);
}
if (videoInputLength == AudioRecord.ERROR_INVALID_OPERATION) {
Log.w(TAG, "[put_v]ERROR_INVALID_OPERATION");
} else if (videoInputLength == AudioRecord.ERROR_BAD_VALUE) {
Log.w(TAG, "[put_v]ERROR_ERROR_BAD_VALUE");
}
if (endOfStream) {
Log.w(TAG, "[put_v]:"+(put_v++)+"; [get] receive endOfStream");
mVideoCodec.queueInputBuffer(videoInputBufferIndex, 0, videoInputLength, videoAbsolutePtsUs, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
} else {
Log.w(TAG, "[put_v]:"+(put_v++)+"; receive videoInputLength :" + videoInputLength);
mVideoCodec.queueInputBuffer(videoInputBufferIndex, 0, videoInputLength, videoAbsolutePtsUs, 0);
}
}
}
}catch (Exception x) {
x.printStackTrace();
}
}
}
ありがとう、アドリアン、私に質問がありますか?オーディオジッタフリー関数(getJitterFreePTS)を削除した場合、オーディオdequeueOutputBufferがいくつかのオーディオデータをmediacodecに明白なエラーなしで送信した後に停止しました。考えられる原因について考えていますか? –
PTSを確認すると、単調に増加するはずですが、コードから133で始まっているように見えます。おそらく、2番目のサンプルではそれよりも低いものが得られます。同期クロックを使用するとこれを解決し、ジッタ機能が必要かどうかわからないので、ブロック単位でオーディオを受信します。また、48 kHzはすべてのデバイスで動作することは保証されていませんが、Androidで保証されているサンプルレートは44100です。 –
@AdrianCreţu私はビデオとオーディオの両方を記録し、両方のスレッドがシステムからPTSタイムスタンプを取得する記録エンジンを持っています。nano()は残念ながらオーディオでジッタを発生させ、オーディオを同期させず、最終ビデオで少し遅れてしまいます。私はあなたのソリューションを読んでいますが、PTSシステムの実装方法のコード例を提供できませんでしたか? – Steve