Mikrofondan multipleksleme ses (didGetAudioData üzerine yaz) ve kameradan video (onpreviewframe üzerine yazarak) üretmek istiyorum mp4 dosyası üretmek istiyorum.Ancak, ses ve video ile karşılaştım Senkronizasyon problemi, video sesden daha hızlı görünecektir. Uyumsuz yapılandırmalar veya presentationTimeUs ile ilgili problemin, birisinin sorunu nasıl düzeltebilirim diye bana rehberlik edip edemeyeceğini merak ettim. Aşağıda benim yazılımı vardı.mediacodec ve mp4 dosyaları için mediamuxer kullanırken ses ve video parça senkronizasyonu sorunu
video yapılandırma
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);
olarak aşağıdaki video presentationPTS, aşağıda ses presentationPTS var
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++;
ses konfigürasyonu, var
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;
}
Sorunum yalnızca ses için jitter işlevinin uygulanmasından mı kaynaklandı? Varsa, video için jitter işlevini nasıl uygulayabilirim? Ayrıca https://android.googlesource.com/platform/cts/+/jb-mr2-release/tests/tests/media/src/android/media/cts/EncodeDecodeTest.java tarafından doğru ses ve video sunumlarını bulmaya çalıştım. Ancak encodedecodeTest sadece video PTS sağladı. Uygulamamın hem ses hem de video için sistem nanotim kullanmasının sebebi buydu. Eğer encodedecodetest içinde video sunumuPTS kullanmak istersem, uyumlu ses sunumunu nasıl yapabilirim? Yardım için teşekkürler! Aşağıda, referans için yuva çerçevesini video mediacodec'e nasıl sıraya koyacağım . Ses parçası için farklı sunumlar hariç aynıdır. Bunu çözüldü nasıl
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();
}
}
}
Teşekkürler Adrian, bir sorum olabilir mi? Ben ses jitter serbest fonksiyonu (getJitterFreePTS), ses dequeueOutputBuffer açık bir hata olmadan mediacodec birkaç ses verileri gönderdikten sonra durdu buldum. Sorunun olası bir nedeni hakkında fikriniz var mı? –
PTS'yi kontrol edin, monotonik olarak artmalı, ancak kodunuz 133'den başlıyor gibi görünüyor ve muhtemelen ikinci örneğinizden daha düşük bir şey elde edersiniz. Bir senkronizasyon saati kullanarak bunu çözer ve btw bir jitter işlevine ihtiyacınız olduğundan emin değilim, bloklar halinde ses alırsınız. Ayrıca, 48 kHz'nin tüm cihazlarda çalışacağı garanti edilmez, Android'de garanti edilen tek örnekleme oranı 44100'dür. –
@ AdrianCrețu Hem görüntü hem ses kaydeden ve her iki iş parçacığının Sistem'den bir PTS zaman damgası almasını sağlayan bir kayıt motorum var.nano() maalesef bu, Audio'da jitter'e neden oluyor ve Audio'nun senkronizasyondan çıkmasını sağlıyor ve son videoda biraz geciktiriyorum, çözümünüzü okuyordum ama işe yaramayabilirdim, lütfen PTS sisteminizi nasıl uygulayacağınıza dair bir kod örneği verebilir misiniz? – Steve