私は、MediaCodecを使ってスクリーンキャプチャとオーディオを記録するアプリケーションを書いています。私は、mp4ファイルを作成するためにビデオとオーディオをmuxにMediaMuxerを使用しています。私は成功裏にビデオとオーディオを別々に書き込むことに成功しましたが、それらを一緒にマルチプレクサで試してみると、予期せぬ結果になります。オーディオはビデオなしで再生されるか、またはビデオはオーディオ直後に再生されます。私の推測では、私はタイムスタンプで何か間違っているのですが、私は正確に何が分かりません。私は既にその例を見てみました:https://github.com/OnlyInAmerica/HWEncoderExperiments/tree/audiotest/HWEncoderExperiments/src/main/java/net/openwatch/hwencoderexperimentsとbigflake.comのもので、答えを見つけることができませんでした。へオーディオとビデオの両方をマルチプレックスできません
mInputSurface.setPresentationTime(mSurfaceTexture.getTimestamp());
drainVideoEncoder(false);
そして、この:私は、ビデオのタイムスタンプを設定するために、これを使用
mVideoEncoder = MediaCodec.createEncoderByType(Preferences.MIME_TYPE);
mVideoEncoder.configure(mVideoFormat, null, null,
MediaCodec.CONFIGURE_FLAG_ENCODE);
mInputSurface = new InputSurface(mVideoEncoder.createInputSurface(),
mSavedEglContext);
mVideoEncoder.start();
if (recordAudio){
audioBufferSize = AudioRecord.getMinBufferSize(44100, AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT);
mAudioRecorder = new AudioRecord(MediaRecorder.AudioSource.MIC, 44100,
AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, audioBufferSize);
mAudioRecorder.startRecording();
mAudioEncoder = MediaCodec.createEncoderByType("audio/mp4a-latm");
mAudioEncoder.configure(mAudioFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
mAudioEncoder.start();
}
try {
String fileId = String.valueOf(System.currentTimeMillis());
mMuxer = new MediaMuxer(dir.getPath() + "/Video"
+ fileId + ".mp4",
MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
} catch (IOException ioe) {
throw new RuntimeException("MediaMuxer creation failed", ioe);
}
mVideoTrackIndex = -1;
mAudioTrackIndex = -1;
mMuxerStarted = false;
:
mVideoFormat = createMediaFormat();
private static MediaFormat createVideoFormat() {
MediaFormat format = MediaFormat.createVideoFormat(
Preferences.MIME_TYPE, mScreenWidth, mScreenHeight);
format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
format.setInteger(MediaFormat.KEY_BIT_RATE, Preferences.BIT_RATE);
format.setInteger(MediaFormat.KEY_FRAME_RATE, Preferences.FRAME_RATE);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL,
Preferences.IFRAME_INTERVAL);
return format;
}
mAudioFormat = createAudioFormat();
private static MediaFormat createAudioFormat() {
MediaFormat format = new MediaFormat();
format.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm");
format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
format.setInteger(MediaFormat.KEY_SAMPLE_RATE, 44100);
format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
format.setInteger(MediaFormat.KEY_BIT_RATE, 64000);
return format;
}
オーディオとビデオエンコーダー、ミュクサー:
は、ここに私のメディアフォーマットの設定ですオーディオタイムスタンプを設定する:
誰かが、私は問題を把握してください助けることができますか?lastQueuedPresentationTimeStampUs = getNextQueuedPresentationTimeStampUs();
if(endOfStream)
mAudioEncoder.queueInputBuffer(inputBufferIndex, 0, audioBuffer.length, lastQueuedPresentationTimeStampUs, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
else
mAudioEncoder.queueInputBuffer(inputBufferIndex, 0, audioBuffer.length, lastQueuedPresentationTimeStampUs, 0);
mAudioBufferInfo.presentationTimeUs = getNextDeQueuedPresentationTimeStampUs();
mMuxer.writeSampleData(mAudioTrackIndex, encodedData,
mAudioBufferInfo);
lastDequeuedPresentationTimeStampUs = mAudioBufferInfo.presentationTimeUs;
private static long getNextQueuedPresentationTimeStampUs(){
long nextQueuedPresentationTimeStampUs = (lastQueuedPresentationTimeStampUs > lastDequeuedPresentationTimeStampUs)
? (lastQueuedPresentationTimeStampUs + 1) : (lastDequeuedPresentationTimeStampUs + 1);
Log.i(TAG, "nextQueuedPresentationTimeStampUs: " + nextQueuedPresentationTimeStampUs);
return nextQueuedPresentationTimeStampUs;
}
private static long getNextDeQueuedPresentationTimeStampUs(){
Log.i(TAG, "nextDequeuedPresentationTimeStampUs: " + (lastDequeuedPresentationTimeStampUs + 1));
lastDequeuedPresentationTimeStampUs ++;
return lastDequeuedPresentationTimeStampUs;
}
私は「timestampUs XXX < lastTimestampUs XXX」エラー
を避けるために、この例https://github.com/OnlyInAmerica/HWEncoderExperiments/blob/audiotest/HWEncoderExperiments/src/main/java/net/openwatch/hwencoderexperiments/AudioEncodingTest.javaからそれを取りましたか
おかげで、私は、オーディオとビデオを同期することができました!あなたは素晴らしいです:) – Alexey
私はもう少し小さな問題があります。私の録音は、オーディオを再生してから、オーディオを再生しないで再生する方が速くなります。そして、オーディオトラックが歪んでいるようです。これはオーディオが各ビデオフレームでチャンクによってチャンクされているために起こると思います。書き込まれるオーディオチャンクのサイズは、fpsとサンプルレートに応じてカウントされます。私のfpsは大きく変わるので、オーディオは不等なチャンク、ひいては歪みによって書き込まれます。多分あなたはそれに対処する方法について何か提案がありますか? – Alexey
残念ながら私はオーディオであまり仕事をしていません。オーディオタイムスタンプはどこから来ていますか?あなたは、ビデオタイムスタンプ(SurfaceTextureタイムスタンプ)の良いソースを持っています。あなたは、オーディオのために似たようなものを使用しているか、 'System.nanoTime()'でそれを偽っているはずです。 (メディアのものは、一般的に、System.nanoTime()と同じようにシステム単調時計を使用しますが、その一部ではナノ秒ではなくマイクロ秒が使用されます)。 – fadden