QT ffmpeg 解码av_read_frame 实现进度条快进快退

这个是之前写的添加暂停功能的文章
https://blog.csdn.net/Lj2_jOker/article/details/121970262?spm=1001.2014.3001.5502

既然实现了暂停,为什么不把进度条实现呢

解码部分代码

status = VideoProcess::__running;
emit f->statusChanged();

decode->old_dts_ms = 0;

qDebug() << QThread::currentThreadId() << "start play stream";
while (status > VideoProcess::__stop)
{
    // 暂停视频
    if( status == VideoProcess::__pause )
    {
        // 视频暂停状态更新
        emit f->statusChanged();
        qDebug() << "stream puase";
        std::unique_lock<std::mutex> lock(mutex);
        condition.wait(lock);
        lock.unlock();
        // 恢复播放状态更新
        emit f->statusChanged();
    }

    read_stream_mutex.lock();
    res = av_read_frame(decode->fmtCnt, &decode->packet);

    if( res < 0 )
    {
        read_stream_mutex.unlock();
        status = VideoProcess::__stop;
        decode->current_time = decode->total_time;
        emit f->frame(img);

        qDebug() << "read stream finished";
        emit f->statusChanged();
        break;
    }
    if( decode->packet.stream_index == decode->video_index )
    {
        res = avcodec_send_packet(decode->codecCnt, &decode->packet);
        if( res < 0 ) {
            read_stream_mutex.unlock();
            continue;
        }
        res = avcodec_receive_frame(decode->codecCnt, decode->frame);
        if( res < 0 ) {
            read_stream_mutex.unlock();
            continue;
        }

        int64_t cur_dts = decode->packet.dts;
        decode->cur_dts_ms = cur_dts * av_q2d(decode->stream->time_base) * 1000;
        // 当前的播放时间, 单位秒
        decode->current_time = cur_dts * av_q2d(decode->stream->time_base);

        sws_scale(decode->sws,
                  decode->frame->data, decode->frame->linesize, 0, decode->frame->height,
                  decode->rgbFrame->data, decode->rgbFrame->linesize);

        emit f->frame(img);


        int wait_ms = decode->cur_dts_ms - decode->old_dts_ms;
        // 帧间隔延时
        if( wait_ms > 0 ) {
            std::this_thread::sleep_for(std::chrono::milliseconds(wait_ms));
        }
        decode->old_dts_ms = decode->cur_dts_ms;
    }
    read_stream_mutex.unlock();
}

read_stream_mutex 是QMutex不是std::mutex
使用std::mutex的效果不知道为什么有问题

对比之前的代码,修改了帧间隔等待的代码

快进快退代码

void seek(const int &msec)
{
    if( !decode && status > VideoProcess::__stop ) {
        return;
    }

    read_stream_mutex.lock();
    int64_t usec = msec * 1000;
    int ret = av_seek_frame(decode->fmtCnt, -1, usec, AVSEEK_FLAG_BACKWARD);
    if( ret >= 0 ) {
        decode->old_dts_ms = usec / 1000;
        avcodec_flush_buffers(decode->codecCnt);
    }
    read_stream_mutex.unlock();
}

视频总时间获取

// fmtCnt 为 AVFormatContext
decode->total_time = decode->fmtCnt->duration / 1000000.0;

进度条算法

进度条的进度 = 当前播放时间 / 总时间 * 进度条宽度
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值