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;