,转载)ffmpe---实现将视频存储为图片jpg

技术,转载)ffmpe---实现将视频存储为图片jpg (转载)ffmpe---实现将视频存储为图片jpg原文出自:https://images1.tqwba.com/20211201/xuqcjtf4

(转载)ffmpe -实现将视频存储为图片使用联合图象专家组文件交换格式存储的编码图像文件扩展名

原文出自:https://images 1 . tqwba.com/20211201/xuqcjtf 4 ewe ',' e :/QT/test _ ffmpegSavePic/ffmpeg/output/',索引);

sprintf_s(out_file),sizeof(out_file),' %s%d.jpg ','./output/',index);

//分配AVFormatContext对象

AVFormatContext * pfformactx=avformat _ alloc _ context();

//设置输出文件格式

pfformactx-oformat=av _ guess _ format(' mjpeg ',NULL,NULL);

//创建并初始化一个和该全球资源定位器(统一资源定位符)相关的AVIOContext

if(AVIO _ open(pfformactx-Pb,out_file,AVIO_FLAG_READ_WRITE) 0)

{

printf('无法打开输出文件');

返回-1;

}

//构建一个新溪流

AVStream * PavStream=avformat _ new _ stream(pfformactx,0);

if (pAVStream==空)

{

返回-1;

}

//设置该溪流的信息

AVCodecContext * pcodectx=Pavlastream-codec;

pcodectx-codec _ id=pfformactx-oformat-video _ codec;

pcodectx-codec _ TYPE=AVMEDIA _ TYPE _ VIDEO;

pcodectx-PIX _ fmt=AV _ PIX _ FMT _ yuvj 420 p;

pcodectx-width=width;

pcodectx-高度=高度;

pcodectx-时基。num=1;

pcodectx-时基。den=25

//打印输出相关信息

av _ dump _ format(pfformactx,0,out_file,1);

//==================================查找编码器==================================//

AVCodec * pCodec=AVCodec _ find _ encoder(pcodectx-codec _ id);

if(!pCodec)

{

printf('找不到编解码器');

返回-1;

}

//设置pCodecCtx的解码器为pCodec

if(av codec _ open 2(pcodectx,pCodec,NULL) 0)

{

printf('无法打开编解码器');

返回-1;

}

//=====================================写入标头=====================================//

avformat _ write _ header(pfformactx,NULL);

int y _ size=pcodectx-宽度* pcodectx-高度;

//====================================编码==================================//

//给AVPacket分配足够大的空间

AVPacket pkt

av_new_packet(pkt,y _ size * 3);

int get _ picture=0;

int ret=avcodec _ encode _ video 2(pcodectx,pkt,pFrame,got _ picture);

if (ret 0)

{

printf('编码错误\\ n ');

返回-1;

}

if(get _ picture==1)

{

PKT。stream _ index=PavStream-index;

ret=av _ write _ frame(pfformactx,PKT);

}

av _ free _ packet(PKT);

//写预告片

av_write_trailer(pF

ormatCtx);
//if (pFrame){
// av_frame_unref(pFrame);
//}
if (pAVStream)
{
avcodec_close(pAVStream-codec);
}
avio_close(pFormatCtx-pb);
avformat_free_context(pFormatCtx);
return 0;
}
//没有完全源代码,自己修改过的
void FFmpegDemo::on_pictureBtn2_clicked()
{
//1.FFMPEG初始化操作
av_register_all(); //初始化FFMPEG 调用了这个才能正常适用编码器和解码器
//=========================== 创建AVFormatContext结构体 ===============================//
//分配一个AVFormatContext,FFMPEG所有的操作都要通过这个AVFormatContext来进行
AVFormatContext *pFormatCtx = avformat_alloc_context();
//==================================== 打开文件 ======================================//
char *file_path = "./2.mp4";//这里必须使用左斜杠
int ret = avformat_open_input(pFormatCtx, file_path, NULL, NULL);
if (ret != 0)
{
cout "open error!" endl;
return ;
}
//循环查找视频中包含的流信息,直到找到视频类型的流
//便将其记录下来 保存到videoStream变量中
int i;
int videoStream;
//=================================== 获取视频流信息 ===================================//
if (avformat_find_stream_info(pFormatCtx, NULL) 0)
{
cout "Could't find stream infomation." endl;
return ;
}
videoStream = -1;
for (i = 0; i pFormatCtx-nb_streams; i++)
{
if (pFormatCtx-streams[i]-codec-codec_type == AVMEDIA_TYPE_VIDEO)
{
videoStream = i;
}
}
//如果videoStream为-1 说明没有找到视频流
if (videoStream == -1)
{
cout "Didn't find a video stream." endl;
return ;
}
//================================= 查找解码器 ===================================//
AVCodecContext* pCodecCtx = pFormatCtx-streams[videoStream]-codec;
AVCodec* pCodec = avcodec_find_decoder(pCodecCtx-codec_id);
if (pCodec == NULL)
{
cout "Codec not found." endl;
return ;
}
//================================ 打开解码器 ===================================//
if (avcodec_open2(pCodecCtx, pCodec, NULL) 0)// 具体采用什么解码器ffmpeg经过封装 我们无须知道
{
cout "Could not open codec." endl;
return ;
}
//================================ 设置数据转换参数 ================================//
SwsContext * img_convert_ctx;
img_convert_ctx = sws_getContext(pCodecCtx-width, pCodecCtx-height, pCodecCtx-pix_fmt, //源地址长宽以及数据格式
pCodecCtx-width, pCodecCtx-height, AV_PIX_FMT_YUVJ420P, //目的地址长宽以及数据格式
SWS_BICUBIC, NULL, NULL, NULL);//算法类型 AV_PIX_FMT_YUVJ420P AV_PIX_FMT_BGR24
//==================================== 分配空间 ==================================//
//一帧图像数据大小
int numBytes = avpicture_get_size(AV_PIX_FMT_YUVJ420P, pCodecCtx-width, pCodecCtx-height);
unsigned char *out_buffer;
out_buffer = (unsigned char *)av_malloc(numBytes * sizeof(unsigned char));
AVFrame * pFrame;
pFrame = av_frame_alloc();
AVFrame * pFrameRGB;
pFrameRGB = av_frame_alloc();
avpicture_fill((AVPicture *)pFrameRGB, out_buffer, AV_PIX_FMT_YUVJ420P, pCodecCtx-width, pCodecCtx-height);
//会将pFrameRGB的数据按RGB格式自动"关联"到buffer 即pFrameRGB中的数据改变了 out_buffer中的数据也会相应的改变
//=========================== 分配AVPacket结构体 ===============================//
int y_size = pCodecCtx-width * pCodecCtx-height;
AVPacket *packet = (AVPacket *)malloc(sizeof(AVPacket)); //分配一个packet
av_new_packet(packet, y_size); //分配packet的数据
//2.循环采集视频流数据 将其转换为图片
//=========================== 读取视频信息 ===============================//
int index = 0;
//读取的是一帧视频 数据存入一个AVPacket的结构中
while (av_read_frame(pFormatCtx, packet) = 0)
{
//此时数据存储在packet中
if (packet packet-stream_index == videoStream)
{
//视频解码函数 解码之后的数据存储在 pFrame中
int got_picture = 0;
ret = avcodec_decode_video2(pCodecCtx, pFrame, got_picture, packet);
if (ret 0)
{
cout "decode error." endl;
return;
}
//转换一帧图像
sws_scale(img_convert_ctx, pFrame-data, pFrame-linesize, 0,
pCodecCtx-height, //源
pFrameRGB-data, pFrameRGB-linesize); //目的
SaveAsJPEG(pFrameRGB, pCodecCtx-width, pCodecCtx-height, index++); //保存图片
}
}
free(packet);
av_frame_free(pFrameRGB);
av_frame_free(pFrame);
avcodec_close(pCodecCtx);
avformat_free_context(pFormatCtx);
}

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/128328.html

(0)

相关推荐

  • 通勤是什么意思,中国移动通勤流量包什么意思

    技术通勤是什么意思,中国移动通勤流量包什么意思通勤流量就是在上下班通勤时间的指定流量,以郑州移动9.99元通勤流量包为例,10G通勤流量包包含10G国内流量,流量有效期为订购当月每天6:00-9:00,17:00-20:

    生活 2021年11月1日
  • 如何利用树莓派监控家里温度和湿度

    技术如何利用树莓派监控家里温度和湿度小编给大家分享一下如何利用树莓派监控家里温度和湿度,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!硬件需求W

    攻略 2021年11月20日
  • CF161D Distance in Tree 题解

    技术CF161D Distance in Tree 题解 CF161D Distance in Tree 题解Description
    洛谷传送门
    Solution
    似乎各种做法都可以过,这里提供一篇 \

    礼包 2021年10月28日
  • 身份证扫描件电子版,用电脑身份证怎么扫描成电子版

    技术身份证扫描件电子版,用电脑身份证怎么扫描成电子版1/7分步阅读虽然最终做成Word文档身份证扫描件电子版,但是需要使用PPT做协助。先建立一个A4页面大小的PPT。2/7用手机或相机把身份证的正反面拍下来,变成图片文

    生活 2021年11月1日
  • mysql5.7 全文索引不支持中文分词怎么办

    技术mysql5.7 全文索引不支持中文分词怎么办本篇文章为大家展示了mysql5.7 全文索引不支持中文分词怎么办,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。在MySQL 5

    攻略 2021年10月20日
  • 【Python接口自动化测试】,7)Postman 的使用教程

    技术【Python接口自动化测试】,7)Postman 的使用教程 【Python接口自动化测试】(7)Postman 的使用教程Postman v6的使用Postman: 简单方便的接口调试工具,便于

    礼包 2021年11月7日