ffmpeg系列:使用C++类封装ffmpeg,封装视频帧解码功能Decode()方法
来源:互联网 发布:阿里巴巴店铺数据分析 编辑:程序博客网 时间:2024/06/15 19:22
新增AVFrame *Decode(const AVPacket *pkt)方法
MyFFmpeg.h文件:
#pragma onceextern "C"{#include <libavformat/avformat.h>#include <libswscale/swscale.h>}#include <string>#include <QMutex>class MyFFmpeg{public:/*设置成为单件模式*/static MyFFmpeg *Get(){static MyFFmpeg ff;return &ff;}/** *打开指定路径的视频文件,如果已有打开的视频文件则先关闭 */bool Open(const char *path);//关闭之前打开的视频文件void Close();//读取视频帧AVPacket Read();//解码功能AVFrame *Decode(const AVPacket *pkt);/*获取相关错误信息*/std::string GetError();/*类析构函数*/virtual ~MyFFmpeg();/*视频文件总的毫秒数*/int totalMs = 0;protected:int videoStream = 0;/*相关错误信息*/char errorbuf[1024];//应对多线程访问时的同步锁QMutex mutex;AVFormatContext *ac = NULL;AVFrame *yuv = NULL;/*设置成为单件模式,所以要把构造函数设置为私有*/MyFFmpeg();};
MyFFmpeg.cpp文件:
#include "MyFFmpeg.h"#pragma comment(lib,"avformat.lib")#pragma comment(lib,"avutil.lib")#pragma comment(lib,"avcodec.lib")#pragma comment(lib,"swscale.lib")bool MyFFmpeg::Open(const char *path){Close();mutex.lock();int re = avformat_open_input(&ac, path, 0, 0);if (re != 0){//打开文件失败mutex.unlock();av_strerror(re, errorbuf, sizeof(errorbuf));return false;}//得到视频总时长的毫秒数totalMs = ((ac->duration / AV_TIME_BASE)*1000);for (int i = 0; i < ac->nb_streams; i++){AVCodecContext *enc = ac->streams[i]->codec;if (enc->codec_type == AVMEDIA_TYPE_VIDEO){videoStream = i;AVCodec *codec = avcodec_find_decoder(enc->codec_id);if (!codec){mutex.unlock();printf("无法解码此视频文件\n");return false;}int err = avcodec_open2(enc, codec, NULL);if (err != 0){mutex.unlock();char buf[1024] = { 0 };av_strerror(err, buf, sizeof(buf));printf(buf);return false;}printf("\n");printf("成功打开视频编码流\n");}}mutex.unlock();return true;}void MyFFmpeg::Close(){mutex.lock();if (ac) avformat_close_input(&ac);if (yuv) av_frame_free(&yuv);mutex.unlock();}std::string MyFFmpeg::GetError(){mutex.lock();std::string re = this->errorbuf;mutex.unlock();return re;}AVPacket MyFFmpeg::Read(){AVPacket pkt;memset(&pkt, 0, sizeof(AVPacket));mutex.lock();if (!ac){mutex.unlock();return pkt;}int err = av_read_frame(ac, &pkt);if (err != 0){//读取失败av_strerror(err, errorbuf, sizeof(errorbuf));}mutex.unlock();return pkt;}AVFrame * MyFFmpeg::Decode(const AVPacket *pkt){mutex.lock();if (!ac){mutex.unlock();return NULL;}if (yuv == NULL){yuv = av_frame_alloc();}int re = avcodec_send_packet(ac->streams[pkt->stream_index]->codec, pkt);if (re != 0){//失败mutex.unlock();return NULL;}re = avcodec_receive_frame(ac->streams[pkt->stream_index]->codec, yuv);if (re != 0){//失败mutex.unlock();return NULL;}mutex.unlock();return yuv;}MyFFmpeg::MyFFmpeg(){errorbuf[0] = '\0';av_register_all();}MyFFmpeg::~MyFFmpeg(){}
main.cpp调用:
#include "myplayer.h"#include <QtWidgets/QApplication>#include "MyFFmpeg.h"int main(int argc, char *argv[]){char path[1024] = "test.mp4";if (MyFFmpeg::Get()->Open(path)){printf("文件[%s]打开成功",path);}else{printf("\n文件[%s]打开失败;错误信息:%s", path,MyFFmpeg::Get()->GetError().c_str());getchar();return -1;}for (;;){AVPacket pkt = MyFFmpeg::Get()->Read();if (pkt.size == 0){break;}printf("pts = %lld\n",pkt.pts);AVFrame *yuv = MyFFmpeg::Get()->Decode(&pkt);if (yuv){printf("解码成功 --- ");}//释放空间av_packet_unref(&pkt);}QApplication a(argc, argv);MyPlayer w;w.show();return a.exec();}
运行结果:
阅读全文
0 0
- ffmpeg系列:使用C++类封装ffmpeg,封装视频帧解码功能Decode()方法
- ffmpeg系列:使用C++类封装ffmpeg,封装读取视频帧功能Read()方法
- ffmpeg系列:使用C++类封装ffmpeg,封装视频帧缩放转换rgb功能ToRGB()方法
- ffmpeg系列:使用C++类封装ffmpeg,实现打开视频文件功能
- ffmpeg学习4--ffmpeg类的简单封装,包含解码和定时录像功能
- FFmpeg解码封装为类以及Opencv显示播放
- ffmpeg的相关方法封装
- 通过C++/CLI使用FFMPEG库进行视频解码[初步]
- FFMPEG的C++封装类
- 使用FFmpeg库实现视频解码
- 使用FFmpeg+GDI解码和播放视频
- FFmpeg - 视频解码过程
- ffmpeg视频解码分析
- FFmpeg解码音视频
- ffmpeg解码视频
- Qt+ffmpeg解码视频
- Qt + ffmpeg 视频解码
- FFmpeg -- 解码视频
- 插入排序-1
- 【HTML5】响应式图片
- [教程]如何降低 Delphi 编码后的 Debug 版本的程序体积
- h5 场景动画效果相关插件 aos.js 和 swiper.animate.js
- 云ERP第一:为什么选择NetSuite?
- ffmpeg系列:使用C++类封装ffmpeg,封装视频帧解码功能Decode()方法
- 数学建模(一)线性规划问题
- 模拟字符串有关功能库函数实现
- MAC 安装mysql全过程记录
- SQL_Server_on_VMware-Best_Practices_Guide.pdf 英文原版 免费下载
- Python控制流
- 关于01背包dp的一些理解
- Bailian2743 字符串判等【字符串】
- Leetcode-26题