使用MediaCodec API在基于Android的媒体播放器应用程序中实现音频视频同步的最佳方法是什么?

时间:2014-03-07 06:33:37

标签: android android-mediaplayer mediacodec stagefright

我正在尝试使用MediaCodec API在Android中实现媒体播放器。

我创建了三个主题 线程1:对输入缓冲区进行解除队列以获取空闲索引,然后在相应编解码器的输入缓冲区中对audiovideo帧进行排队

线程2:对audio编解码器的输出缓冲区进行解除队列并使用AudioTrack类'写入方法对其进行渲染

线程3:对video编解码器的输出缓冲区进行解除队列并使用releaseBuffer方法对其进行渲染

我在实现audiovideo帧之间的同步时面临很多问题。我从不丢弃audio帧,在渲染video帧之前,我检查解码后的帧是否延迟超过3个,如果它们是我丢帧,如果它们提前超过10毫秒我不渲染框架。

要查找audiovideo之间的差异,请使用以下逻辑

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已播放的持续时间(以微秒为单位)。 startTimeUsaudiovideo帧之间的初始差异,必须始终保持这种差异。

第一个if块检查,是否确实存在audio轨道并且已经初始化,并通过从nowUs计算audiotrack来设置audio的值 如果 nowUs(第一个)SystemTime设置为startTimeUs且初始间隔设置为零。 audio在main函数中初始化为零。

在使用同步块中的if块的情况下,要渲染的第一帧是audio并且first_audio_sample帧稍后加入。 {{1}}标志最初设置为true。

如果有任何不清楚的地方,请告诉我。

此外,如果您知道使用视频编解码器实现了a-v文件的媒体播放器的任何开源链接,那就太棒了。

1 个答案:

答案 0 :(得分:0)

如果您正在处理Android的最新版本之一,则可以考虑直接从audioTimeStamp检索AudioTrack。有关详细信息,请参阅此documentation。同样,您也可以考虑通过getSampleRate检索sampling rate

如果您希望继续使用算法,可以考虑在此本机示例中使用相对类似的实现。 SimplePlayer使用MediaCodec实现了播放器引擎,并且还具有 a-v sync 部分。请参阅执行同步的section of code。我认为这应该有助于作为一个很好的参考。