ffmpeg从AVFrame取出yuv数据到保存到char*中

 
很多人一直不知道怎么利用ffmpeg从AVFrame取出yuv数据到保存到char*中,下面代码将yuv420p和yuv422p的数据取出并保存到char*buf中。
其他格式可以自己去扩展,前提先看戏yuv的各种格式,yuv的各种格式链接:数据格式分析
 
先确保视频格式sws_getContext()转换后是YUV格式:
     out_buffer=(uint8_t *)av_malloc(avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height));//分配AVFrame所需内存
avpicture_fill((AVPicture *)pFrameYUV, out_buffer, PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);//填充AVFrame img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,
pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
那么在后续的视频数据处理时,可以把YUV视频格式数据进行存储:
 //如果是视频
else if (pstream_info[i].dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO)
{
int new_videosize = pkt.size;
int video_decode_size = avpicture_get_size(pstream_info->dec_ctx->pix_fmt, Zoom_Width,Zoom_Height);
uint8_t * video_decode_buf =( uint8_t *)calloc(,video_decode_size * * sizeof(char)); //最大分配的空间,能满足yuv的各种格式 // Decode video frame
avcodec_decode_video2(pstream_info->dec_ctx, pDecodeFrame, &frameFinished,&pkt);
if(frameFinished)
{
if (pstream_info->dec_ctx->pix_fmt == AV_PIX_FMT_YUV420P) //如果是yuv420p的
{
for(i = ; i < pstream_info->dec_ctx->height; i++)
{
memcpy(video_decode_buf+pstream_info->dec_ctx->width*i,
pDecodeFrame->data[]+pDecodeFrame->linesize[]*i,
pstream_info->dec_ctx->width);
}
for(j = ; j < pstream_info->dec_ctx->height/; j++)
{
memcpy(video_decode_buf+pstream_info->dec_ctx->width*i+pstream_info->dec_ctx->width/*j,
pDecodeFrame->data[]+pDecodeFrame->linesize[]*j,
pstream_info->dec_ctx->width/);
}
for(k =; k < pstream_info->dec_ctx->height/; k++)
{
memcpy(video_decode_buf+pstream_info->dec_ctx->width*i+pstream_info->dec_ctx->width/*j+pstream_info->dec_ctx->width/*k,
pDecodeFrame->data[]+pDecodeFrame->linesize[]*k,
pstream_info->dec_ctx->width/);
}
}
else if (pstream_info->dec_ctx->pix_fmt == AV_PIX_FMT_YUV422P)//如果是yuv422p的
{
for(i = ; i < pstream_info->dec_ctx->height; i++)
{
memcpy(video_decode_buf+pstream_info->dec_ctx->width*i,
pDecodeFrame->data[]+pDecodeFrame->linesize[]*i,
pstream_info->dec_ctx->width);
}
for(j = ; j < pstream_info->dec_ctx->height; j++)
{
memcpy(video_decode_buf+pstream_info->dec_ctx->width*i+pstream_info->dec_ctx->width/*j,
pDecodeFrame->data[]+pDecodeFrame->linesize[]*j,
pstream_info->dec_ctx->width/);
}
for(k =; k < pstream_info->dec_ctx->height; k++)
{
memcpy(video_decode_buf+pstream_info->dec_ctx->width*i+pstream_info->dec_ctx->width/*j+pstream_info->dec_ctx->width/*k,
pDecodeFrame->data[]+pDecodeFrame->linesize[]*k,
pstream_info->dec_ctx->width/);
}
}
else
{
//可扩展
}
video_decode_size = avpicture_get_size(pstream_info->dec_ctx->pix_fmt, pstream_info->dec_ctx->width,pstream_info->dec_ctx->height);
new_videosize = video_decode_size; //缩放或格式转换
if (pstream_info->dec_ctx->width != Zoom_Width ||
pstream_info->dec_ctx->height != Zoom_Height ||
pstream_info->dec_ctx->pix_fmt != Zoom_pix_fmt)
{
new_videosize = VideoScaleYuvZoom(Is_flip,pstream_info->dec_ctx->width ,pstream_info->dec_ctx->height,(int)pstream_info->dec_ctx->pix_fmt,
Zoom_Width,Zoom_Height,Zoom_pix_fmt,video_decode_buf);
}
//这里可以取出数据
frame_info->stream_idx = pstream_info->stream_idx;
//frame_info->pts = pDecodeFrame->pkt_pts * 1000 * av_q2d(pstream_info->stream->time_base); //转化成毫秒
frame_info->pts = pDecodeFrame->pkt_pts;
frame_info->timebase_den = pstream_info->stream->time_base.den;
frame_info->timebase_num = pstream_info->stream->time_base.num;
frame_info->bufsize = new_videosize;
memcpy(frame_info->buf,video_decode_buf,new_videosize);
}
else
{
//缓存
frame_info->stream_idx = pstream_info->stream_idx;
frame_info->pts = ;
frame_info->timebase_den = ;
frame_info->timebase_num = ;
frame_info->bufsize = ;
memset(frame_info->buf,,MAX_FRAME_SIZE);
}
if (video_decode_buf)
{
free(video_decode_buf);
video_decode_buf = NULL;
}
video_decode_size = ;
}

也可以把YUV数据进行存储为PPM格式(Linux系统下的图片格式):

 //如果是视频
else if (pstream_info[i].dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO)
{
// Decode video frame
avcodec_decode_video2(pstream_info->dec_ctx, pDecodeFrame, &frameFinished,&pkt);
if(frameFinished)
{
sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, , pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);
if((++k<=) && (k%==)) {
SaveFrame(pFrameYUV, pCodecCtx->width, pCodecCtx->height, k);
}
}
} void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame)
{
FILE *pFile;
char szFilename[];
int y; SDL_Log("%d * %d", width, height);
// Open file
sprintf(szFilename, "frame/frame%d.ppm", iFrame);
pFile=fopen(szFilename, "wb");
if(pFile==NULL)
return; // Write header
fprintf(pFile, "P6\n%d %d\n255\n", width, height); // Write pixel data
for(y=; y<height; y++) {
fwrite(pFrame->data[]+y*pFrame->linesize[], , width*, pFile);
} // Close file
fclose(pFile);
}

ffmpeg从AVFrame取出yuv数据到保存到char*中的更多相关文章

  1. python 数据如何保存到excel中--xlwt

    第一步:下载xlwt 首先要下载xlwt,(前提是你已经安装好了Python) 下载地址:  https://pypi.python.org/pypi/xlwt/   下载第二个   第二步:安装xl ...

  2. (转) 从ffmpeg中提取出YUV数据

    有时需要从ffmpeg中提取出YUV数据用作预览,另存什么的. ffmpeg是先解码成YUV, 再以这个YUV作为输入进行编码,所以YUV数据有两种:  解码后的YUV数据, 以及  编码重建的YUV ...

  3. 1.scrapy爬取的数据保存到es中

    先建立es的mapping,也就是建立在es中建立一个空的Index,代码如下:执行后就会在es建lagou 这个index.     from datetime import datetime fr ...

  4. c# 抓取和解析网页,并将table数据保存到datatable中(其他格式也可以,自己去修改)

    使用HtmlAgilityPack 基础请参考这篇博客:https://www.cnblogs.com/fishyues/p/10232822.html 下面是根据抓取的页面string 来解析并保存 ...

  5. Redis使用场景一,查询出的数据保存到Redis中,下次查询的时候直接从Redis中拿到数据。不用和数据库进行交互。

    maven使用: <!--redis jar包--> <dependency> <groupId>redis.clients</groupId> < ...

  6. Android把图片保存到SQLite中

    1.bitmap保存到SQLite 中 数据格式:Blob db.execSQL("Create table " + TABLE_NAME + "( _id INTEGE ...

  7. 【redis,1】java操作redis: 将string、list、map、自己定义的对象保存到redis中

    一.操作string .list .map 对象 1.引入jar: jedis-2.1.0.jar   2.代码 /**      * @param args      */     public s ...

  8. 将数字n转换为字符串并保存到s中

    将数字n转换为字符串并保存到s中 参考 C程序设计语言 #include <stdio.h> #include <string.h> //reverse函数: 倒置字符串s中各 ...

  9. Flask实战第43天:把图片验证码和短信验证码保存到memcached中

    前面我们已经获取到图片验证码和短信验证码,但是我们还没有把它们保存起来.同样的,我们和之前的邮箱验证码一样,保存到memcached中 编辑commom.vews.py .. from utils i ...

随机推荐

  1. deleteRow

    如果是删除某一行的话,直接delete就可以,行数要在删除之前剪掉,否则会崩溃. 但是,如果section要减一的话,是不能删掉section的 Terminating app due to unca ...

  2. favicon.ico的制作

    1.选取需要的图片(jpg的格式等) 2.在网上搜索favicon.ico的制作,将jpg转为ico 3.在html中输入<link rel="shortcut icon" ...

  3. ionic卸载和更新

    卸载 npm uninstall -g ionic 更新 npm update -g ionic

  4. Sql Server 性能优化之包含列

    导读:数据数优化查询一直是个比较热门的话题,小生在这方面也只能算是个入门生.今 天我们就讲下数据库包含列这个一项的作用及带来的优化效果 引用下MSDN里面的一段解释: 当查询中的所有列都作为键列或非键 ...

  5. kafka 命令行操作

    1.创建主题(topic) bin/kafka-topics.sh --create --zookeeper m6:2181 --replication-factor 1 --partitions 1 ...

  6. 欧几里得算法:从证明等式gcd(m, n) = gcd(n, m mod n)对每一对正整数m, n都成立说开去

    写诗或者写程序的时候,我们经常要跟欧几里得算法打交道.然而有没要考虑到为什么欧几里得算法是有效且高效的,一些偏激(好吧,请允许我用这个带有浓重个人情感色彩的词汇)的计算机科学家认为,除非程序的正确性在 ...

  7. 获取dll中根目录

    AppDomain.CurrentDomain.BaseDirectory获取当前应用程序域的基目录 好像是万能的:form:可执行文件路径控制台:输出路径web:根目录

  8. python实现动态更新远程机器列表的SSH登录脚本

    在公司里, 常常要远程到很多机器上执行命令.机器列表会逐渐增多, 记忆这么多机器的IP或域名显然不是人脑所擅长的.因此, 需要保持一份SSH机器列表,从这些机器列表生成一个用于SSH到机器列表中机器的 ...

  9. php之XML转数组函数的方法

    <?/** * xml2array() will convert the given XML text to an array in the XML structure. * Link: htt ...

  10. Python—I/O多路复用

    一.I/O多路复用概念: 监听多个描述符的状态,如果描述符状态改变,则会被内核修改标志位,从而被进程获取进而进行读写操作 二.select,poll,epoll select模块,提供了:select ...