解码的时候都是通过线程while读出视频流
然后在转为QImage发送出去
暂停就是把线程给暂停
通过QWaitCondition 或是 std::condition_variable(例子用的是std::condition_variable)
因为是通过帧的时间戳来发送QImage
在计算时间戳的时候,需要把暂停这段时间给减上就行了
// 记录开始读视频流的时间戳
qint64 start_ms = QDateTime::currentDateTime().toMSecsSinceEpoch();
// 暂停时长时间戳
qint64 wait_ms = 0;
// 当前时间减去start_ms
// 判断是否大于dts时间戳
// 小于就等待
// 大于就开始读下一帧
qint64 msec = 0;
status = VideoProcess::__running;
// 枚举类型
// __stop = 0
// __running = 1
// __pause = 2
while (status > VideoProcess::__stop)
{
res = av_read_frame(decode->fmtCnt, &decode->packet);
if( res < 0 ) {
// 解码完成 退出循环
status = VideoProcess::__stop;
break;
}
if( decode->packet.stream_index == decode->video_index )
{
res = avcodec_send_packet(decode->codecCnt, &decode->packet);
if( res < 0 ) {
continue;
}
res = avcodec_receive_frame(decode->codecCnt, decode->frame);
if( res < 0 ) {
continue;
}
// 获取帧的时间戳
int64_t cur_dts = decode->packet.dts;
int64_t cur_dts_ms = cur_dts * av_q2d(decode->stream->time_base) * 1000;
sws_scale(decode->sws,
decode->frame->data, decode->frame->linesize, 0, decode->frame->height,
decode->rgbFrame->data, decode->rgbFrame->linesize);
// 暂停视频
if( status == VideoProcess::__pause )
{
// 发送暂停信号
// 只要在其他线程调用condition.notify_all()
// 就可以解除暂停
emit f->statusChanged();
qint64 wait_start_ms = QDateTime::currentDateTime().toMSecsSinceEpoch();
std::unique_lock<std::mutex> lock(mutex);
condition.wait(lock);
lock.unlock();
wait_ms = wait_ms + (QDateTime::currentDateTime().toMSecsSinceEpoch() - wait_start_ms);
// 发送播放信号
status = __VideoProcess::__play
emit f->statusChanged();
}
// 发送帧图片
emit f->frame(img);
// 延时
while (1)
{
msec = QDateTime::currentDateTime().toMSecsSinceEpoch() - start_ms - wait_ms;
if( msec > cur_dts_ms ) {
break;
}
decode->current_time = msec / 1000.0;
}
}
}