libstagefright 音视频同步方案

libstagefright 音视频同步方案 (2013-01-13 19:08:19)
1:音视频数据都有一个list,用于存放解码后的数据;

  List mFilledBuffers;
 
2:解码后的音视频数据不断的往list中存放,不做音视频同步方面的时间上控制

  mFilledBuffers.push_back(i);

3:音视频同步主要表现在从list中取数据进行视频的显示和音频的输出;

4:其中audio数据在线程函数threadLoop中调用AudioPlayer的回调函数循环读取,不做时间上的控制;

4:视频数据正常情况下按照每10ms的时间取一次,如果有音视频不同步的情况,就可能需要做以下三种情况的处理

  1:如果视频数据过快,超过音频时间10ms,则显示当前帧后,将读取数据的事件延时(慢的时间-10ms)后放入队列;
 
  2:如果视频数据过慢,慢于音频时间40ms,则丢弃当前帧,然后再去取数据;
 
  3:如果视频数据过慢,慢于音频时间500ms,则丢弃当前帧,并且需要丢弃一段视频帧,直接对video部分(SEEK_VIDEO_ONLY)seek到音频当前帧的时间戳;
 
  PS:上面的三个时间参数可能会微调;
 
6:视频当前时间是指视频当前帧携带的时间戳,是通过该帧的sampleIndex从stts表中读取出来的;

  int64_t timeUs;
  CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
 
7:音频的时间戳通过以下方式计算:

  result + diffUs - realtime_us + mediatime_us = -mLatencyUs + ALooper::GetNowUs() - mNumFramesPlayedSysTimeU s + mediatime_us

  mNumFramesPlayedSysTimeU s = ALooper::GetNowUs() 和前面那个函数有一定的时间差
 
8:循环读取数据的机制     
 
  android中循环读取数据都是通过Thread类的threadLoop函数实现,这个函数的介绍如下:
 
    Derived class must implement threadLoop(). The thread starts its life here. There are two ways of using the Thread object:
    1) loop: if threadLoop() returns true, it will be called again if
            requestExit() wasn't called.
    2) once: if threadLoop() returns false, the thread will exit upon return.
   
    virtual bool        threadLoop() = 0;
 
  如果函数返回true,且没有调用requestExit()函数,则一直循环执行  ----------正常播放情况
 
  如果函数返回true,但调用requestExit()函数,则停止执行          ----------停止播放情况
 
  如果函数返回false,执行一次后返回
 
9:正常情况下音视频对应的threadLoop函数都在循环执行,并没有时间上的控制,音频数据确实如此,但是视频数据通过下面的机制控制读取

  读取视频数据被封装为一个个事件,这些事件都会携带一个什么执行的时间戳,这些事件按照执行时间的先后顺序放入一个队列;
 
  threadLoop函数循环执行的时候,会判断当前时间和队头事件的时间戳
 
      前者大于等于后者,取出时间执行,return true;

      前者小于后者,做下面的操作:      
      int64_t whenUs = (*mEventQueue.begin()).mWhenUs;
      int64_t nowUs = GetNowUs();
      if (whenUs > nowUs) {
          int64_t delayUs = whenUs - nowUs;
          mQueueChangedCondition.waitRelative(mLock, delayUs * 1000ll);
          return true;
      }
      event = *mEventQueue.begin();
      mEventQueue.erase(mEventQueue.begin());
      gLooperRoster.deliverMessage(event.mMessage);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值