Android Tunnel Mode配置简介

贝研
2023-12-01

目录

 

简介

处理方式

配置流程

VLC适配


简介

Tunnel Mode是Android专门在TV上提出的多媒体技术方案,用来缓解播放4K高帧率视频播放带来的性能问题。有关Tunnel Mode的官方详细介绍地址如下https://source.android.com/devices/tv/multimedia-tunneling,下面简单介绍下Tunnel Mode的配置方式。

关于Tunnel Mode的配置,在Android 11版本以后又发生了一些变化,我们看下Android的官方说明:

For Android 11 or higher, as an alternate for the audio session ID, the app can get the HW sync ID from Tuner and provide it to AudioTrack and MediaCodec instances for A/V sync.

  • For Android 11 or higher, PCR or STC from Tuner might be the master clock for A/V sync.
  • For Android 10 or lower, the audio clock is the master clock used for A/V playback.

简单来说,对于Android 10及以前的版本,使用audio session ID,往audio主时钟同步;对于Android 11及以后的版本,可以使用HW sync ID,使用Tuner的PCR或STC做主时钟进行同步。

处理方式

Android多媒体框架目前有如下几种方式处理音视频内容:

1、纯软件(本地解码):应用处理器 (AP) 会在本地将音频解码为PCM,而不进行特殊处理。对于 Ogg Vorbis,会始终使用此方式;对于 MP3 和 AAC,在系统不支持offload时,会使用此方式。

2、audio offload:将音频编码数据直接发送到数字信号处理器 (DSP),并尽可能使 AP 处于关闭状态。此方式用于在关屏时播放音乐文件。

3、audio passthrough:通过 HDMI 将经过音频编码数据(具体来说就是 AC3 和 E-AC3)直接发送到外部电视或音频接收器,而不在 Android TV 设备上对其进行解码。系统会单独处理视频部分。

4、Multimedia tunneling:同时发送音频和视频编码数据。编码流被视频和音频解码器接收到后,不会再返回到framework层。理想情况下,编码流不会中断 AP。

5、Multimedia passthrough:将音频和视频编码数据同时从Tuner发送到视频和音频解码器,过程中不涉及framework层。huo

可以看到,在Tunnel Mode下,音视频流解码后不会再返回到framework层,无法在上层进行音画同步,这也是要设置audio session ID或HW sync ID的原因。

配置流程

1、创建一个SurfaceView实例

SurfaceView sv = new SurfaceView(mContext);

2、获取audio session ID。创建AudioTrack时将会用到这个唯一的id。该id同样会传递到MediaCodec,多媒体框架以此将音频和视频通路关联起来。

AudioManager am = mContext.getSystemService(AUDIO_SERVICE);

int audioSessionId = am.generateAudioSessionId()

// or, for Android 11 or higher

int avSyncId = tuner.getAvSyncHwId();

3、创建具有HW A/V sync标志的AudioAttributes。audio policy manager会询问hal层哪个设备输出支持HW A/V sync,并创建直接连接到该输出设备的AudioTrack(不经过mixer)。

AudioAttributes.Builder aab = new AudioAttributes.Builder();

aab.setUsage(AudioAttributes.USAGE_MEDIA);

aab.setContentType(AudioAttributes.CONTENT_TYPE_MOVIE);

aab.setFlag(AudioAttributes.FLAG_HW_AV_SYNC);

 

// or, for Android 11 or higher

new tunerConfig = TunerConfiguration(0, avSyncId);

aab.setTunerConfiguration(tunerConfig);

 

AudioAttributes aa = aab.build();

AudioTrack at = new AudioTrack(aa);

4、创建视频的MediaCodec实例,为其配置Tunnel playback。

// retrieve codec with tunneled video playback feature

MediaFormat mf = MediaFormat.createVideoFormat(“video/hevc”, 38402160);

mf.setFeatureEnabled(CodecCapabilities.FEATURE_TunneledPlayback, true);

MediaCodecList mcl = new MediaCodecList(MediaCodecList.ALL_CODECS);

String codecName = mcl.findDecoderForFormat(mf);

if (codecName == null) {

  return FAILURE;

}

// create codec and configure it

mf.setInteger(MediaFormat.KEY_AUDIO_SESSION_ID, audioSessionId);

 

// or, for Android 11 or higher

mf.setInteger(MediaFormat.KEY_HARDWARE_AV_SYNC_ID, avSyncId);

 

MediaCodec mc = MediaCodec.createCodecByName(codecName);

mc.configure(mf, sv.getSurfaceHolder().getSurface(), null0);

5、解码视频帧

mc.start();

 for (;;) {

   int ibi = mc.dequeueInputBuffer(timeoutUs);

   if (ibi >= 0) {

     ByteBuffer ib = mc.getInputBuffer(ibi);

     // fill input buffer (ib) with valid data

     ...

     mc.queueInputBuffer(ibi, ...);

   }

   // no need to dequeue explicitly output buffers. The codec

   // does this directly to the sideband layer.

 }

 mc.stop();

 mc.release();

 mc = null;

6、AudioTrack写音频时带上pts。

public int write (ByteBuffer audioData,

                int sizeInBytes,

                int writeMode,

                long timestamp)

//在音频帧前添加了同步字节头

// create timestamp header if none exists

if (mAvSyncHeader == null) {

    mAvSyncHeader = ByteBuffer.allocate(mOffset);

    mAvSyncHeader.order(ByteOrder.BIG_ENDIAN);

    mAvSyncHeader.putInt(0x55550002);

}

 

if (mAvSyncBytesRemaining == 0) {

    mAvSyncHeader.putInt(4, sizeInBytes);

    mAvSyncHeader.putLong(8, timestamp);

    mAvSyncHeader.putInt(16, mOffset);

    mAvSyncHeader.position(0);

    mAvSyncBytesRemaining = sizeInBytes;

}

VLC适配

目前的VLC对Tunnel Mode的适配几乎没有,总结了如下几点问题需要解决:

1.获取audio session id设置给video mediacodec和audiotrack module;

2.目前audiotrack module的new方法不支持AudioAttributes的设置,需要使用重载函数;

3.video mediacodec module需要配置Tunnel playback;

4.video decoder不再出帧,无法收到第一帧开画消息及EOS消息;

5.Tunnel Mode使用音视频帧的原始pts进行同步,VLC目前没有将pts信息传给MediaCodec;

6.目前audiotrack module的write方法不支持写入pts,需要使用重载函数;

7.VLC音画同步逻辑需要完全放弃。

 类似资料: