obs-ffmepg
+ -

pts时间

2025-01-02 5 0

24fps
ns = 41 666 667
ms us ns

数据结构

//解析帧后更新下列参数
struct mp_decode 
{
    int64_t last_duration;//上一个包的持续时间
    int64_t frame_pts; //当前帧的时间戳
    int64_t next_pts; //= frame_pts+last_duration
}

//初始化时play_sys_ts=os_gettime_ns()
struct mp_media 
{
    struct mp_decode v;//video decode
    struct mp_decode a;//aduio decode

    int64_t play_sys_ts=os_gettime_ns()

    //这2货初始化时一样
    int64_t next_pts_ns;
    int64_t start_ts = next_pts_ns = min(av.frame_pts)

    //初始化为os_gettime_ns(),每循环一次调用mp_media_calc_next_ns
    uint64_t next_ns = min(av.frame_pts)+ os_gettime_ns()
             next_pts_ns = min(av.frame_pts)

    int64_t base_ts;//一直为0
}

主流程

mp_media_t *m;

bool mp_media_thread(mp_media_t *m)
{
    init_avformat(m);//1.初始化解码器,decode相关frame创建

    mp_media_reset(m);//2.first frame
    for(;;)
    {
        if (!is_active || pause) 
        {
            if (os_sem_wait(m->sem) < 0)
                return false;
            if (pause)
                reset_ts(m);//3.暂停时时间更新
        }
        else {
            //sleep m->next_ns - os_gettime_ns
            timeout = mp_media_sleep(m);
        }
        if (m->has_video)
        mp_media_next_video(m, false);

        if (m->has_audio)
            mp_media_next_audio(m);

        //avpacket
        if (!mp_media_prepare_frames(m))
            return false;
    }
}

1.init_avformat

init_avformat下的mp_decode_init。

    m->has_video = mp_decode_init(m, AVMEDIA_TYPE_VIDEO, m->hw);
    m->has_audio = mp_decode_init(m, AVMEDIA_TYPE_AUDIO, m->hw);

对于mp_decode的video和audio分别

    d->sw_frame = av_frame_alloc();
    if (d->hw)
        d->in_frame = d->hw_frame;
    else
        d->in_frame = d->sw_frame;

    d->frame = d->sw_frame;

完成后:

struct mp_decode 
{
    int64_t last_duration =0;
    int64_t frame_pts=0;
    int64_t next_pts=0;
}

struct mp_media 
{
    struct mp_decode v;//video decode
    struct mp_decode a;//aduio decode

    int64_t play_sys_ts=0;
    int64_t next_pts_ns=0;
    uint64_t next_ns=0;
    int64_t start_ts=0;
    int64_t base_ts=0;
}

2.mp_media_reset

开始或者播放结束或者复位时调用一次

  • 调用mp_media_prepare_frames准备frame
  • 更新时间戳

      //max(m->v.next_pts  m->a.next_pts)
      int64_t next_ts = mp_media_get_base_pts(m);
    
      //delta = d.next_pts - m->next_pts_ns;
      int64_t offset = next_ts - m->next_pts_ns;
    
      if (active) {
          if (!m->play_sys_ts)
              m->play_sys_ts = (int64_t)os_gettime_ns();
    
          //-1 or min(m->v.frame_pts,m->a.frame_pts)
          m->start_ts = m->next_pts_ns = mp_media_get_next_min_pts(m);
          if (m->next_ns)
              m->next_ns += offset;
      } else {
          m->start_ts = m->next_pts_ns = mp_media_get_next_min_pts(m);
          m->play_sys_ts = (int64_t)os_gettime_ns();
          m->next_ns = 0;
      }
    
  • m->play_sys_ts:是开始播放的时间(int64_t)os_gettime_ns()
  • m->start_ts = m->next_pts_ns = 0
  • m->next_ns= 0 //+delta

3.sleep

bool mp_media_sleep(mp_media_t *m)
{
    bool timeout = false;

    if (!m->next_ns) {
    //为0时不需要Sleep
        m->next_ns = os_gettime_ns();
    } else {
        const uint64_t t = os_gettime_ns();
        if (m->next_ns > t) {
            const uint32_t delta_ms =(uint32_t)((m->next_ns - t + 500000) / 1000000);
            if (delta_ms > 0) {
                static const uint32_t timeout_ms = 200;
                timeout = delta_ms > timeout_ms;
                os_sleep_ms(timeout ? timeout_ms : delta_ms);
            }
        }
    }

    return timeout;
}

4.packet 时间戳

d->frame_pts = av_rescale_q(d->frame_pts, (AVRational){1, d->m->speed},    (AVRational){1, 100});

//时长
int64_t duration = d->in_frame->pkt_duration;

//videopts = m_ListVideo.front()->pts * av_q2d(m_fmt_ctx->streams[m_VideoStreamIndex]->time_base);
duration = av_rescale_q(duration, d->stream->time_base,    (AVRational){1, 1000000000});
d->last_duration = duration;//ns

//下一帧时间戳
d->next_pts = d->frame_pts + duration;

4.frame时戳

frame->timestamp = 
    m->base_ts 
    + d->frame_pts 
    - m->start_ts 
    + m->play_sys_ts 
    - base_sys_ts;

0 篇笔记 写笔记

作者信息
我爱内核
Windows驱动开发,网站开发
好好学习,天天向上。
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!