Qt ffmpeg解码av_read_frame 实现暂停功能

解码的时候都是通过线程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;
        }
    }
}

你可能感兴趣的:(qt,音视频,开发语言)