有自媒体谁还做网站河北提供网站制作公司报价
news/
2025/9/23 14:46:04/
文章来源:
有自媒体谁还做网站,河北提供网站制作公司报价,wordpress修改背景,织梦系统做的网站打开慢介绍
工作开发中需要处理的文件很多并无音频#xff0c;针对这一场景#xff0c;这里分享工作中自己封装使用的类库。精简的代码实现了播放、暂停、停止、快进、快退、进度更新跳转播放功能。直接放代码#xff0c;方便后期复制使用。
代码
头文件
#ifndef VIDEOPLAYER_…介绍
工作开发中需要处理的文件很多并无音频针对这一场景这里分享工作中自己封装使用的类库。精简的代码实现了播放、暂停、停止、快进、快退、进度更新跳转播放功能。直接放代码方便后期复制使用。
代码
头文件
#ifndef VIDEOPLAYER_H
#define VIDEOPLAYER_H#include QThread
#include QDebug
#include QImageextern C
{
#include libavformat/avformat.h
#include libavcodec/avcodec.h
#include libswscale/swscale.h
#include libavutil/imgutils.h
#include libavutil/time.h
}class VideoDecoder : public QThread
{Q_OBJECT
public:explicit VideoDecoder(QObject *parent nullptr);~VideoDecoder();void startPlay(const QString path);void stopPlay();void pausePlay(bool pause);void seekPlay(int sec);signals:void sigDuration(int sec);void sigPlayPosition(int sec);void sigPlayFinished(int ret);void sigSendImage(const QImage image);protected:void run();private://运行标志volatile bool m_isRun false;//暂停状态volatile bool m_pause false;//进度跳转状态volatile bool m_seek false;//优化跳转速度volatile bool m_seekFilter false;//开始时间 ms单位int64_t m_startTime;//暂停时间 ms单位int64_t m_pauseTime;//跳转时间 ms单位int64_t m_seekTime;//文件路径QString m_filePath;//时长信息 秒int m_videoDuration;
};#endif // VIDEOPLAYER_H
实现文件
#include videoplayer.hVideoDecoder::VideoDecoder(QObject *parent) : QThread(parent)
{}VideoDecoder::~VideoDecoder()
{quit();wait();
}void VideoDecoder::startPlay(const QString path)
{m_filePath path;m_isRun true;m_pause false;m_seek false;this-start();
}void VideoDecoder::stopPlay()
{m_pause false;m_seek false;m_isRun false;
}void VideoDecoder::pausePlay(bool pause)
{m_pause pause;if(pause){m_pauseTime av_gettime_relative() / 1000;}else{int offset av_gettime_relative() / 1000 - m_pauseTime;m_startTime offset;}
}void VideoDecoder::seekPlay(int sec)
{if(!m_isRun)return;if(m_videoDuration sec)sec - 2;m_seekTime sec * 1000;m_seekFilter true;m_seek true;
}void VideoDecoder::run()
{qDebug() VideoDecoder start m_filePath;std::string temp m_filePath.toStdString();AVFormatContext *inFmtCtx avformat_alloc_context();int ret avformat_open_input(inFmtCtx, temp.c_str(), NULL, NULL);if (ret 0){qDebug() open input error;return;}//获取流信息ret avformat_find_stream_info(inFmtCtx, NULL);if (ret 0){qDebug() find stream info error;return;}//获取视频流信息 目前只有视频流bool getVideo false;int videoIndex av_find_best_stream(inFmtCtx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);AVStream *videoStream NULL;AVCodec *videoDecoder NULL;AVCodecContext *videoDeCodecCtx NULL;if (videoIndex 0){videoStream inFmtCtx-streams[videoIndex];//初始化解码器videoDecoder avcodec_find_decoder(videoStream-codecpar-codec_id);videoDeCodecCtx avcodec_alloc_context3(videoDecoder);if(videoDeCodecCtx ! NULL){avcodec_parameters_to_context(videoDeCodecCtx, videoStream-codecpar);ret avcodec_open2(videoDeCodecCtx, videoDecoder, NULL);if(ret 0)avcodec_free_context(videoDeCodecCtx);elsegetVideo true;}}if(!getVideo){avformat_close_input(inFmtCtx);return;}AVFrame *swsFrame av_frame_alloc();SwsContext *swsCtx nullptr;uint8_t *videoData nullptr;//输出视频参数信息if(getVideo){int srcW videoStream-codecpar-width;int srcH videoStream-codecpar-height;AVPixelFormat format videoDeCodecCtx-pix_fmt;m_videoDuration inFmtCtx-duration / AV_TIME_BASE;emit sigDuration(m_videoDuration);int byte av_image_get_buffer_size(AV_PIX_FMT_RGB32, srcW, srcH, 1);videoData (uint8_t *)av_malloc(byte * sizeof(uint8_t));av_image_fill_arrays(swsFrame-data, swsFrame-linesize, videoData, (AVPixelFormat)AV_PIX_FMT_RGB32, srcW, srcH, 1);swsCtx sws_getContext(srcW, srcH, (AVPixelFormat)format, srcW, srcH, (AVPixelFormat)AV_PIX_FMT_RGB32, SWS_FAST_BILINEAR, NULL, NULL, NULL);}//开始时刻m_startTime av_gettime_relative() / 1000;int64_t ptsTime 0;int curPlayPos 0;AVPacket *packet av_packet_alloc();AVFrame *videoFrame av_frame_alloc();while(m_isRun){//暂停if(m_pause){QThread::msleep(200);continue;}//进度切换if(m_seek){//跳转的播放时刻 单位微秒int64_t timeStamp m_seekTime * 1000;if (inFmtCtx-start_time ! AV_NOPTS_VALUE)timeStamp inFmtCtx-start_time;//注seek若关键帧间隔大需避免延时timeStamp av_rescale_q(timeStamp, AVRational{1, AV_TIME_BASE}, videoStream-time_base);ret av_seek_frame(inFmtCtx, videoIndex, timeStamp, AVSEEK_FLAG_BACKWARD);if(ret 0){qDebug() av_seek_frame fail m_seekTime;}else{//清空内部帧队列if(videoDeCodecCtx)avcodec_flush_buffers(videoDeCodecCtx);//调整时钟int64_t offset m_seekTime - ptsTime;m_startTime - offset;}m_seek false;}//不断读取packetret av_read_frame(inFmtCtx, packet);if (ret AVERROR_EOF){m_isRun false;break;}if(packet-stream_index videoIndex){//编码数据进行解码ret avcodec_send_packet(videoDeCodecCtx, packet);if (ret 0){av_packet_unref(packet);continue;}ret avcodec_receive_frame(videoDeCodecCtx, videoFrame);if (ret 0){av_packet_unref(packet);continue;}//控制速度 ms单位ptsTime videoFrame-pts * av_q2d(videoStream-time_base) * 1000;if(m_seekFilter){//跳转播放时间不符合的帧直接丢弃 默认阈值200msint offset m_seekTime - ptsTime;if(0 offset || offset 200){m_seekFilter false;}else{av_frame_unref(videoFrame);av_packet_unref(packet);continue;}}qint64 elapsed av_gettime_relative() / 1000 - m_startTime;int64_t sleepMs ptsTime - elapsed;if(sleepMs 3){QThread::msleep(sleepMs);}//发送播放位置信息int sec ptsTime / 1000;if(sec ! curPlayPos){curPlayPos sec;emit sigPlayPosition(curPlayPos);}//将解码后的frame数据转换为Imagesws_scale(swsCtx, (const uint8_t *const *)videoFrame-data, videoFrame-linesize, 0, videoFrame-height, swsFrame-data, swsFrame-linesize);QImage image((uchar *)videoData, videoFrame-width, videoFrame-height, QImage::Format_RGB32);QImage copy image.copy();emit sigSendImage(copy);av_frame_unref(videoFrame);}av_packet_unref(packet);}//释放资源sws_freeContext(swsCtx);av_frame_free(swsFrame);av_free(videoData);av_packet_free(packet);av_frame_free(videoFrame);avcodec_free_context(videoDeCodecCtx);avformat_close_input(inFmtCtx);emit sigPlayFinished(0);qDebug() VideoDecoder end m_filePath;return;
}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/912884.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!