我正在尝试使用MediaCodecAPI 在 android 中实现媒体播放器。
我创建了三个线程 Thread 1 :将输入缓冲区出列以获取空闲索引,然后在各自编解码器的输入缓冲区中对帧audio和帧进行排队video
线程 2:将编解码器的输出缓冲区出列并使用类的 write 方法audio渲染它AudioTrack
线程 3:将编解码器的输出缓冲区出列并使用方法video渲染它releaseBuffer
我在实现audio和video帧之间的同步方面面临很多问题。我从不audio丢帧,在渲染video帧之前,我检查解码帧是否延迟超过 3 毫秒,如果是我丢帧,如果它们提前超过 10 毫秒我不渲染帧。
为了找到和之间的区别audio,video我使用以下逻辑
public long calculateLateByUs(long timeUs) {
long nowUs = 0;
if (hasAudio && audioTrack != null) {
synchronized (audioTrack) {
if(first_audio_sample && startTimeUs >=0){
System.out.println("First video after audio Time Us: " + timeUs );
startTimeUs = -1;
first_audio_sample = false;
}
nowUs = (audioTrack.getPlaybackHeadPosition() * 1000000L) /
audioCodec.format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
}
} else if(!hasAudio){
nowUs = System.currentTimeMillis() * 1000;
startTimeUs = 0;
}else{
nowUs = System.currentTimeMillis() * 1000;
}
if (startTimeUs == -1) {
startTimeUs = nowUs - timeUs;
}
if(syslog){
System.out.println("Timing Statistics:");
System.out.println("Key Sample Rate :"+ audioCodec.format.getInteger(MediaFormat.KEY_SAMPLE_RATE) + " nowUs: " + nowUs + " startTimeUs: "+startTimeUs + " timeUs: "+timeUs + " return value :"+(nowUs - (startTimeUs + timeUs)));
}
return (nowUs - (startTimeUs + timeUs));
}
timeUs是以微秒为单位的视频帧的呈现时间。nowUs应该包含播放的持续时间(以微秒为单位)audio。是必须始终保持的帧之间startTimeUs的初始差异。audiovideo
第一个 if 块检查是否确实存在audio轨道并且它已被初始化并nowUs通过计算它的值来设置值audiotrack
If there is no audio (first else) nowUsis set to SystemTimeand the initial gap is set to zero. startTimeUs在 main 函数中初始化为零。
同步块中的 if 块用于以防万一,要渲染的第一帧是audio,然后audio帧连接。first_audio_sampleflag 最初设置为 true。
如果有任何不清楚的地方,请告诉我。
此外,如果您知道任何开源链接,其中 av 文件的媒体播放器已使用视频编解码器实现,那就太好了。