我正在尝试使用MediaCodec
API 在 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
的初始差异。audio
video
第一个 if 块检查是否确实存在audio
轨道并且它已被初始化并nowUs
通过计算它的值来设置值audiotrack
If there is no audio
(first else) nowUs
is set to SystemTime
and the initial gap is set to zero. startTimeUs
在 main 函数中初始化为零。
同步块中的 if 块用于以防万一,要渲染的第一帧是audio
,然后audio
帧连接。first_audio_sample
flag 最初设置为 true。
如果有任何不清楚的地方,请告诉我。
此外,如果您知道任何开源链接,其中 av 文件的媒体播放器已使用视频编解码器实现,那就太好了。