FFmpeg4.0笔记:封装ffmpeg的视频帧转换功能类CSws
Github
https://github.com/gongluck/FFmpeg4.0-study/tree/master/Cff
CSws.h
/*******************************************************************
* Copyright(c) 2019
* All rights reserved.
*
* 文件名称: CSws.h
* 简要描述: 帧转换
*
* 作者: gongluck
* 说明:
*
*******************************************************************/
#ifndef __CSWS_H__
#define __CSWS_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h> // av_image_alloc
#ifdef __cplusplus
}
#endif
#include <string>
#include <mutex>
class CSws
{
public:
virtual ~CSws();
// 状态
enum STATUS { STOP, LOCKED };
// 设置源参数
bool set_src_opt(AVPixelFormat pixfmt, int w, int h, std::string& err);
// 设置目标参数
bool set_dst_opt(AVPixelFormat pixfmt, int w, int h, std::string& err);
// 锁定设置
bool lock_opt(std::string& err);
// 解除锁定
bool unlock_opt(std::string& err);
// 转换
int scale(const uint8_t* const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t* const dst[], const int dstStride[], std::string& err);
private:
STATUS status_ = STOP;
std::recursive_mutex mutex_;
SwsContext* swsctx_ = nullptr;
AVPixelFormat src_pix_fmt_ = AV_PIX_FMT_NONE;
AVPixelFormat dst_pix_fmt_ = AV_PIX_FMT_NONE;
int src_w_ = 0;
int src_h_ = 0;
int dst_w_ = 0;
int dst_h_ = 0;
};
#endif//__CSWS_H__
CSws.cpp
/*******************************************************************
* Copyright(c) 2019
* All rights reserved.
*
* 文件名称: CSws.cpp
* 简要描述: 帧转换
*
* 作者: gongluck
* 说明:
*
*******************************************************************/
#include "common.h"
#include "CSws.h"
CSws::~CSws()
{
std::string err;
unlock_opt(err);
}
bool CSws::set_src_opt(AVPixelFormat pixfmt, int w, int h, std::string& err)
{
LOCK();
CHECKSTOP(err);
err = "opt succeed.";
src_pix_fmt_ = pixfmt;
src_w_ = w;
src_h_ = h;
return true;
}
bool CSws::set_dst_opt(AVPixelFormat pixfmt, int w, int h, std::string& err)
{
LOCK();
CHECKSTOP(err);
err = "opt succeed.";
dst_pix_fmt_ = pixfmt;
dst_w_ = w;
dst_h_ = h;
return true;
}
bool CSws::lock_opt(std::string& err)
{
LOCK();
CHECKSTOP(err);
err = "opt succeed.";
swsctx_ = sws_getContext(src_w_, src_h_, src_pix_fmt_, dst_w_, dst_h_, dst_pix_fmt_, SWS_FAST_BILINEAR, nullptr, nullptr, nullptr);
if (swsctx_ == nullptr)
{
err = "sws_getContext return nullptr.";
return false;
}
status_ = LOCKED;
return true;
}
bool CSws::unlock_opt(std::string& err)
{
LOCK();
err = "opt succeed.";
sws_freeContext(swsctx_);
swsctx_ = nullptr;
status_ = STOP;
src_w_ = 0;
src_h_ = 0;
dst_w_ = 0;
dst_h_ = 0;
return true;
}
int CSws::scale(const uint8_t* const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t* const dst[], const int dstStride[], std::string& err)
{
LOCK();
CHECKNOTSTOP(err);
err = "opt succeed.";
int ret = sws_scale(swsctx_, srcSlice, srcStride, srcSliceY, srcSliceH, dst, dstStride);
CHECKFFRET(ret);
return ret;
}
测试
// 视频帧转换
void test_sws()
{
bool ret = false;
std::string err;
std::ifstream yuv("in.yuv", std::ios::binary);
CSws sws;
// 分配图像数据内存
uint8_t* src[4] = { 0 };
int srclinesize[4] = { 0 };
uint8_t* dst[4] = { 0 };
int dstlinesize[4] = { 0 };
int srcsize = av_image_alloc(src, srclinesize, 640, 432, AV_PIX_FMT_YUV420P, 1);
int dstsize = av_image_alloc(dst, dstlinesize, 320, 240, AV_PIX_FMT_BGR24, 1);
yuv.read(reinterpret_cast<char*>(src[0]), 640 * 432);
yuv.read(reinterpret_cast<char*>(src[1]), 640 * 432 / 4);
yuv.read(reinterpret_cast<char*>(src[2]), 640 * 432 / 4);
ret = sws.set_src_opt(AV_PIX_FMT_YUV420P, 640, 432, err);
TESTCHECKRET(ret);
ret = sws.set_dst_opt(AV_PIX_FMT_BGR24, 320, 240, err);
TESTCHECKRET(ret);
ret = sws.lock_opt(err);
TESTCHECKRET(ret);
int size = sws.scale(src, srclinesize, 0, 432, dst, dstlinesize, err);
std::cout << "sws " << size << " line" << std::endl;
std::ofstream bgr("out.bgr", std::ios::binary);
bgr.write(reinterpret_cast<char*>(dst[0]), dstsize);
ret = sws.unlock_opt(err);
TESTCHECKRET(ret);
// 清理
if (src != nullptr)
{
av_freep(&src[0]);
}
av_freep(&src);
if (dst != nullptr)
{
av_freep(&dst[0]);
}
av_freep(&dst);
}
FFmpeg4.0笔记:封装ffmpeg的视频帧转换功能类CSws的更多相关文章
- FFmpeg4.0笔记:本地媒体文件解码、帧格式转换、重采样、编码、封装、转封装、avio、硬解码等例子
Github https://github.com/gongluck/FFmpeg4.0-study/blob/master/official%20example/my_example.cpp #in ...
- FFmpeg解码视频帧为jpg图片保存到本地
FFmpeg解码视频帧为jpg图片保存到本地 - CSDN博客 https://blog.csdn.net/qq_28284547/article/details/78151635
- C#使用FFmpeg 将视频格式转换成Gif图片示例
根据EFmpeg封装的视频转换gif工具:https://my.oschina.net/tianma3798/blog/825317 一.本次使用参数说明 /* * 参数说明: * -i 源文件位置 ...
- NET 2.0(C#)调用ffmpeg处理视频的方法
另外:ffmpeg的net封装库 http://www.intuitive.sk/fflib/ NET 2.0 调用FFMPEG,并异步读取输出信息的代码...public void ConvertV ...
- 基于C#利用ffmpeg提取视频帧
利用ffmepg提取视频帧实际上是利用C#调用ffmepg命令行进行处理对应的视频,然后输出出视频帧 GetPicFromVideo("); static public string Get ...
- FFmpeg进行视频帧提取&音频重采样-Process.waitFor()引发的阻塞超时
由于产品需要对视频做一系列的解析操作,利用FFmpeg命令来完成视频的音频提取.第一帧提取作为封面图片.音频重采样.字幕压缩等功能: 前一篇文章已经记录了FFmpeg在JAVA中的使用-音频提取&am ...
- 利用ffmpeg获取视频帧
如果要对视频帧进行处理,可以先把视频帧读取出来. sh文件代码如下: #!/usr/bin/env sh VIDEO=/home/xxx/video/ FRAMES=/home/xxx/frame/ ...
- C#使用FFmpeg 将视频格式转换成MP4示例
一.常用视频格式分辨率 640x480p 720p格式,分辨率为1280×720p / 60Hz,行频为45kHz 1080p格式,分辨率为1920×1080逐行扫描,专业格式 二.FFmpeg部分参 ...
- FFmpeg4.0笔记:封装ffmpeg的解封装功能类CDemux
Github https://github.com/gongluck/FFmpeg4.0-study/tree/master/Cff CDemux.h /*********************** ...
随机推荐
- 2019南昌网络赛 J Distance on the tree 主席树+lca
题意 给一颗树,每条边有边权,每次询问\(u\)到\(v\)的路径中有多少边的边权小于等于\(k\) 分析 在树的每个点上建\(1\)到\(i\)的权值线段树,查询的时候同时跑\(u,v,lca ...
- #if/#else/#endif
在linux环境下写c代码时会尝试各种方法或调整路径,需要用到#if #include<stdio.h> int main(){ int i; #if 0 i = ; #else i = ...
- hearthbuddy中的Class276
构造函数 需要注意的是this.intptr_0 = this.method_18("mono.dll"); 所以,这个类里面的操作,最后是和mono.dll相关的 interna ...
- mysq乱码问题
不乱码的思想 liunx字符集→linux客户端字符集(例如:ssh)→mysql客户端字符集→mysql服务端字符集→库的字符集→表的字符集→程序字符集统一 mysql表跟库,库跟服务端字符集 li ...
- 解决 ElementTree 无法处理中文
解决 ElementTree 无法处理中文,UnicodeEncodeError: ‘ascii’ codec can’t encode characters in position 76-99: o ...
- Mysql强制修改密码
windows: 1,停止MYSQL服务,CMD打开DOS窗口,输入 net stop mysql 2,在CMD命令行窗口,进入MYSQL安装目录 比如E:\Program Files\MySQL\M ...
- 性能测试之JMeter远程模式
性能测试之JMeter远程模式 事实上,你的JMeter客户端机器是不能表现出完美的压力请求,来模拟足够多的用户或由于网络限制去向服务施加压力,一种解决方法是通过一个JMeter去控制多个/远程JMe ...
- SQL常见面试题(学生表_课程表_总表)
问题描述: 为管理岗位业务培训信息,建立3个表: S (S#,SN,SD,SA) S#,SN,SD,SA 分别代表学号.学员姓名.所属单位.学员年龄 C (C#,CN ) C#,CN 分别代表课程编号 ...
- Spring aop 切入点表达式
转自: https://blog.csdn.net/qq_36951116/article/details/79172485 切入点指示符用来指示切入点表达式目的,,在Spring AOP中目前只 ...
- mysql账户授权
mysql新加用户及授权 --登录数据库mysql -uroot -p --查询当前用户1.SELECT User, Host FROM mysql.user;2.select host,user,a ...