一.视频格式转换初始化

  将视频中的图像帧按照一定比例缩放或指定宽高进行放大和缩小是视频编辑中最为常见的操作之一,这里我们将1920x1080的yuv图像序列转换成640x480的rgb图像序列,并输出到文件。视频图像转换的核心为一个SwsContext结构,其中保存了输入图像和输出图像的宽高以及像素格式等多种参数。我们通过调用sws_getContext()函数就可以十分方便地创建并获取SwsContext结构的实例。下面给出初始化的代码:

//video_swscale_core.cpp
static AVFrame *input_frame= nullptr;
static struct SwsContext *sws_ctx;
static int32_t src_width=0,src_height=0,dst_width=0,dst_height=0;
static enum AVPixelFormat src_pix_fmt=AV_PIX_FMT_NONE,dst_pix_fmt=AV_PIX_FMT_NONE;
int32_t init_video_swscale(const char *src_size,const char *src_fmt,const char *dst_size,const char *dst_fmt){
int32_t result=0;
result=av_parse_video_size(&src_width,&src_height,src_size);
if(result<0){
cerr<<"Error:av_parse_video_size failed."<<endl;
return -1;
}
result= av_parse_video_size(&dst_width,&dst_height,dst_size);
if(result<0){
cerr<<"Error:av_parse_video_size failed."<<endl;
return -1;
}
//选择输入视频和输出视频的图像格式
if(!strcasecmp(src_fmt,"YUV420P")){
src_pix_fmt=AV_PIX_FMT_YUV420P;
}
else if(!strcasecmp(src_fmt,"RGB24")){
src_pix_fmt=AV_PIX_FMT_RGB24;
}
else{
cerr<<"Error:Unsupported input pixel format."<<endl;
return -1;
}
if(!strcasecmp(dst_fmt,"YUV420P")){
dst_pix_fmt=AV_PIX_FMT_YUV420P;
}
else if(!strcasecmp(dst_fmt,"RGB24")){
dst_pix_fmt=AV_PIX_FMT_RGB24;
}
else{
cerr<<"Error:Unsupported output pixel format."<<endl;
return -1;
}
//获取SwsContext结构
sws_ctx=sws_getContext(src_width,src_height,src_pix_fmt,dst_width,dst_height,dst_pix_fmt,SWS_BILINEAR, nullptr,
nullptr, nullptr);
if(!sws_ctx){
cerr<<"Error:failed to get SwsContext."<<endl;
return -1;
}
//初始化AVFrame结构
result= init_frame(src_width,src_height,src_pix_fmt);
if(result<0){
cerr<<"Error:init_frame failed."<<endl;
return -1;
}
return 0;
}

  初始化保存输入视频的AVFrame结构,并分配内存空间:

//video_swscale_core.cpp
static int32_t init_frame(int32_t width,int32_t height,enum AVPixelFormat pix_fmt){
int result=0;
input_frame=av_frame_alloc();
if(!input_frame){
cerr<<"Error:av_frame_alloc failed."<<endl;
return -1;
}
input_frame->width=width;
input_frame->height=height;
input_frame->format=pix_fmt;
result= av_frame_get_buffer(input_frame,0);
if(result<0){
cerr<<"Error:av_frame_get_buffer failed."<<endl;
return -1;
}
result= av_frame_make_writable(input_frame);
if(result<0){
cerr<<"Error:av_frame_make_writable failed."<<endl;
return -1;
}
return 0;
}

二.视频图像帧的循环转换

  视频格式转换的核心函数是sws_scale(),我们需要给出输出图像的缓存地址和缓存宽度,然后循环处理即可。下面给出代码:

//video_swscale_core.cpp
int32_t transforming(int32_t frame_cnt){
int32_t result=0;
uint8_t *dst_data[4];
int32_t dst_linesize[4]={0},dst_bufsize=0;
result= av_image_alloc(dst_data,dst_linesize,dst_width,dst_height,dst_pix_fmt,1);
if(result<0){
cerr<<"Error:av_image_alloc failed."<<endl;
return -1;
}
dst_bufsize=result;
for(int i=0;i<frame_cnt;i++){
result= read_yuv_to_frame(input_frame);
if(result<0){
cerr<<"Error:read_yuv_to_frame failed."<<endl;
return -1;
}
sws_scale(sws_ctx,input_frame->data,input_frame->linesize,0,src_height,dst_data,dst_linesize);
//write_packed_data_to_file(dst_data[0],dst_bufsize);
write_packed_data_to_file2(dst_data[0],dst_linesize[0],dst_width,dst_height);
}
av_freep(&dst_data[0]);
return 0;
}

三.将转换后的图像帧写入输出文件

  这里需要注意的是,由于我们转换后的图像格式是rgb24,是按packed方式存储的,也就是红绿蓝三个通道交错地存储在一个平面内,在内存中是连续存储的。也就是说,转换后的图像数据全部保存在dst_data[0]指向的内存空间中。下面给出代码:

//io_data.cpp
int32_t write_packed_data_to_file2(uint8_t *data,int32_t linesize,int32_t width,int32_t height){
for(int i=0;i<height;i++){
fwrite(data+i*linesize,1,width*3,output_file);
}
}

四.释放资源

void destroy_video_swscale(){
av_frame_free(&input_frame);
sws_freeContext(sws_ctx);
}

  还有其他的文件打开和关闭以及将yuv图像读到AVFrame结构中的代码请看我之前的博客。

五.main函数实现

int main(){
int result=0;
const char *input_file_name="../input.yuv";
const char *input_pic_size="1920x1080";
const char *input_pix_fmt="YUV420P";
const char *output_file_name="../output.rgb";
const char *output_pic_size="640x480";
const char *output_pix_fmt="RGB24";
result= open_input_output_files(input_file_name,output_file_name);
if(result<0){
return -1;
}
result=init_video_swscale(input_pic_size,input_pix_fmt,output_pic_size,output_pix_fmt);
if(result<0){
return -1;
}
result=transforming(250);
if(result<0){
return -1;
}
destroy_video_swscale();
close_input_output_files();
return 0;
}

  最后,可以用以下指令测试输出的output.rgb文件:

  ffplay -f rawvideo -video_size 640x480 -pixel_format rgb24 -i output.rgb

  

  

如何使用libswscale库将YUV420P格式的图像序列转换为RGB24格式输出?的更多相关文章

  1. 优酷1080p的kux格式文件怎么转换为MP4格式?

    直接使用优酷自己的FFMPEG解码! 格式为:"优酷ffmpeg.exe的安装地址" -y -i ".kux文件储存地址" -c:v copy -c:a cop ...

  2. JS如何将CST格式的日期转换为制定格式String

    <html> <body> <script type="text/javascript"> var d = new Date() dateFor ...

  3. 将对象格式的style转换为字符串格式

    var style = { position:'absolute', background:'red', width:'2px', height:'2px', color:'#fff', top:x, ...

  4. java 调用OpenOffice将word格式文件转换为pdf格式

    一:环境搭建 OpenOffice 下载地址http://www.openoffice.org/ JodConverter 下载地址http://sourceforge.net/projects/jo ...

  5. Excel表格文本格式的数字和数字格式如何批量转换

    Excel表格文本格式的数字和数字格式如何批量转换 在使用Excel表格对数据求和时,只能对单元格内常规格式的数据进行计算,而不能对单元格中的文本格式的数据进行计算,特点就是在单元格的左上角有一个绿色 ...

  6. 利用kindlegen实现txt格式小说转换为mobi格式小说(C++实现)

    一直以来喜欢在kindle上看小说,kindle不伤眼,也可以帮助控制玩手机的时间.但在kindle上看txt格式的网络小说就很头疼了,这类小说在kindle上是没有目录的,而且篇幅巨长.所以一直以来 ...

  7. 如何将EDI报文转换为CSV格式文件?

    如果您对EDI项目实施有一定的了解,想必您一定知道,在正式开始EDI项目实施之前,都会有EDI顾问与您接洽,沟通EDI项目需求.其中,会包含EDI通信双方使用哪种传输协议,传输的报文是符合什么标准的, ...

  8. web字体格式及几种在线格式转换工具介绍

    原文地址:http://blog.csdn.net/xiaolongtotop/article/details/8316554 目前,文字信息仍是网站最主要的内容,随着CSS3技术的不断成熟,Web字 ...

  9. 使用Javascript/jQuery将javascript对象转换为json格式数据 - 海涛的CSDN博客 - 博客频道 - CSDN.NET

    body{ font-family: "Microsoft YaHei UI","Microsoft YaHei",SimSun,"Segoe UI& ...

  10. (转) at&T语法格式 与 at&T - intel格式对比

    原地址 示例: movl (%ebp), %eax, 等同于Intel格式中的 ] ,AT&T中,源操作数在左,目的操作数在右.“l”是Longword,相当于Intel格式中的dword p ...

随机推荐

  1. [大数据]ETL之增量数据抽取(CDC)

    关于:转载/知识产权 本文遵循 GPL开源协议,如若转载: 1 请发邮件至博主,以作申请声明. 2 请于引用文章的显著处注明来源([大数据]ETL之增量数据抽取(CDC) - https://www. ...

  2. STM32新建模板【HAL库】

    看到这篇笔记的小伙伴可能会觉得我在做无用功,明明可以通过 STM32CubeMx 软件直接生成的,还在这里慢慢的创建项目.我觉得在学习的时候最好少借助工具,当我们过度依赖工具的时候,决绝问题的能力可能 ...

  3. 你真的懂synchronized锁?

    1. 前言 synchronized在我们的程序中非常的常见,主要是为了解决多个线程抢占同一个资源.那么我们知道synchronized有多种用法,以下从实践出发,题目由简入深,看你能答对几道题目? ...

  4. ArcGIS切片服务获取切片方案xml文件(conf.xml)

    在使用ArcGIS进行影像.地形等切片时,往往需要保持一致的切片方案才能够更好的加载地图服务. 本文介绍如何获取已经发布好的ArcGIS服务的切片方案xml文件. 当然切片xml文件还可以通过工具Ge ...

  5. nginx概要

    新机(CentOS7)配置nginx: 一. 更新yum源为阿里云镜像 ping mirrors.aliyun.com mv /etc/yum.repos.d/CentOS-Base.repo /et ...

  6. Consistency Models终结扩散模型

    最近看到一篇论文,觉得特别有意思,并且在学术界引起了不小的动静,他就是一致性模型,据说图像生成效果快.质量高,并且还可以实现零样本图像编辑,即不进行一些视觉任务训练,可以实现图像超分.修复.上色等功能 ...

  7. vue2.x/vue3.0中使用ts

    vue2.x(vue-cli3)中使用ts      https://www.jianshu.com/p/3cbcdd766295 https://www.cnblogs.com/xiaohuizha ...

  8. [C++基础入门] 6、 函数

    文章目录 6 函数 6.1 概述 6.2 函数的定义 6.3 函数的调用 6.4 值传递 6.5 函数的常见样式 6.6 函数的声明 6.7 函数的分文件编写 6 函数 6.1 概述 **作用:**将 ...

  9. 基于pip的python包管理工具

    以下是软件下载链接:https://mysecreat.lanzoub.com/i5yvf0swgtne 软件功能:可以对python包进行安装.卸载.升级.换源等操作,不用输入复杂命令 源码: im ...

  10. [UR #14]人类补完计划

    计数好题. 题意:给定简单无向图 \(G=(V,E),|V|=n,|E|=m\),有 \(n\leq 16,m\leq {n\choose 2}\),求所有为基环树的子图的权值之和.一个基环树的权值定 ...