2

我正在尝试使用MediaCodecAPI 在 android 中实现媒体播放器。

我创建了三个线程 Thread 1 :将输入缓冲区出列以获取空闲索引,然后在各自编解码器的输入缓冲区中对帧audio和帧进行排队video

线程 2:将编解码器的输出缓冲区出列并使用类的 write 方法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。是必须始终保持的帧之间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 文件的媒体播放器已使用视频编解码器实现,那就太好了。

4

1 回答 1

0

如果您正在使用 的最新版本之一Android,您可以考虑直接检索audioTimeStampfrom AudioTrack。有关详细信息,请参阅此文档。同样,您也可以考虑检索sampling ratevia getSampleRate

如果您希望继续使用您的算法,可以考虑在本机示例中使用相对相似的实现。SimplePlayer通过使用实现播放器引擎,MediaCodec并且也有一个av 同步部分。请参阅执行同步的这部分代码。我觉得这应该有助于作为一个很好的参考。

于 2014-03-11T00:47:41.263 回答