热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

ffmpeg采集摄像头后解码并用framebuffer播放保存为bmp

FFmpeg解码流程:1、注册所有容器格式和CODEC:avcodec_register_all();2、查找对应的解码器࿱

FFmpeg解码流程:

1、注册所有容器格式和CODEC:avcodec_register_all();

2、查找对应的解码器:avcodec_find_decoder(AV_CODEC_ID_MJPEG);

3、分配编解码器参数数据结构avcodec_alloc_context3(AVCodec *codec);

4、对于部分编解码需要对上一步分配的数据结构进行初始化,因为某些参数在视频流中无效;

5、打开编解码器:avcodec_open2(AVCodecContext *ctx, AVCodec
*codec, NULL);

6、为解码帧分配内存:AVFrame *frame = av_frame_alloc();

7、初始化编解码输入数据结构AVPacket:av_init_packet(AVPacket
*packet);

8、将待解码的压缩视频数据放入数据结构AVPacket中:

(AVPacket)packet.data = inbuf(待解码视频数据缓存);

(AVPacket)packet.size = inbufsize(待解码视频数据长度);

9、调用解码函数开始解码:avcodec_decode_video2(AVCodecContext *ctx,AVFrame *frame,int *got,AVPacket *packet);

10、拷贝解码后的一帧数据,解码后的数据格式根据解码前的数据格式决定,例如,USB摄像头的MJPEG数据解码后是YUV422P格式,H264格式数据解码后是YUV420P格式;解码后的数据存放在AVFrame数据结构指向的缓存中,存放方式为:(AVFrame )frame->data[0]指向Y分量,(AVFrame )frame->data[1]指向U分量,(AVFrame )frame->data[2]指向V分量;(AVFrame )frame->linesize[0]、(AVFrame )frame->linesize[1]、(AVFrame )frame->linesize[2]分别为Y、U、V分量每行的长度。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include struct options
{int frames;int nodec;int bplay;int thread_count;int64_t lstart;char finput[256];
};// check the video stream
static int find_video_stream(AVFormatContext* pCtx)
{int videoStream = -1;int i;// check the video streamfor (i = 0; i nb_streams; i++){if (pCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO){videoStream = i;break;}}return videoStream;
}//save the BMP ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#pragma pack(1)
// 2byte
typedef struct bmp_magic
{unsigned char magic[2];
}magic_t;// 4 * 3 = 12 Byte
typedef struct bmp_header
{unsigned int file_size; //file size in Byte ,w * h * 3 + 54unsigned short creater1; //0unsigned short creater2; //0unsigned int offset; //offset to image data: 54D, 36H
}header_t ;typedef struct bmp_info
{unsigned int header_size; //info size in bytes, equals 4o D, or 28Hunsigned int width; //file wideth in pideunsigned int height; //file height in pideunsigned short nplanes; //number of clor planes , 1unsigned short bitspp; //bits per pidel, 24d, 18hunsigned int compress_type; //compress type,default 0unsigned int image_size; //image size in Byte. w * h * 3unsigned int hres; //pideles per meter, 0unsigned int vres; //pideles per meter, 0unsigned int ncolors; //number of colors, 0unsigned int nimpcolors; //important colors, 0
}info_t;int gen_bmp_header(unsigned char *head,unsigned w, unsigned h,unsigned bytepp)
{if(head==NULL)return -1;magic_t magic;info_t info;header_t header;magic.magic[0] = 'B';magic.magic[1] = 'M';header.file_size = (w * h * bytepp + 54);header.creater1 = 0;header.creater2 = 0;header.offset = (54);info.header_size = (40);info.width = (w);info.height = (h);info.nplanes = (1);info.bitspp = (bytepp * 8);info.compress_type = 0;info.image_size = (w * h * bytepp);info.hres = 0;info.vres = 0;info.ncolors = 0;info.nimpcolors = 0;unsigned char *p=head;memcpy(p,&magic,sizeof(magic));p+=sizeof(magic);memcpy(p,&header,sizeof(header));p+=sizeof(header);memcpy(p,&info,sizeof(info));return 0;
} static void saveBitMap(AVFrame *pFrameRGB, int width, int height, int index, int bpp)
{unsigned char head[54];int i;FILE *fp = NULL;memset(head, 0, 54);gen_bmp_header(head,width, height,bpp/8);fp = fopen("./10.bmp", "w+");if (fp == NULL){av_log(NULL, AV_LOG_INFO, "fopen BMP error\n");return ;}fwrite(head, 54, 1, fp);fwrite(pFrameRGB->data[0], width*height*bpp/8, 1, fp);fclose(fp);fp = NULL;
}
//save the BMP ---------------------------------------------------int main(int argc, char **argv)
{AVCodecContext *pCodecCtxVideo &#61; 0;//videoAVCodec *pCodecVideo &#61; 0;//videoAVPacket packet;AVFrame *pFrameVideo &#61; 0;//videoAVFrame *pFrameRGB &#61; 0;//save the RGB AVDictionary *options &#61; NULL; FILE *fpo1 &#61; NULL;FILE *fpo2 &#61; NULL;int nframe;int err;struct options opt;int got_picture;int picwidth, picheight, linesize;unsigned char *pBuf;int i;int64_t timestamp;int usefo &#61; 0;int dusecs;float usecs1 &#61; 0;float usecs2 &#61; 0;struct timeval elapsed1, elapsed2;int decoded &#61; 0;int ret &#61; -1;int videoStream &#61; -1; av_register_all();avdevice_register_all();AVInputFormat *inputFormat &#61; av_find_input_format("v4l2");AVFormatContext *pCtx&#61;avformat_alloc_context();av_dict_set(&options,"video_size","640*480",0);err &#61; avformat_open_input(&pCtx, "/dev/video0", NULL, &options);if (err <0){printf("\n->(avformat_open_input)\tERROR:\t%d\n", err);return -1;}printf("&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;\n");err &#61; avformat_find_stream_info(pCtx, 0);if (err <0){printf("\n->(avformat_find_stream_info)\tERROR:\t%d\n", err);return -1;}av_dump_format(pCtx, 0, opt.finput, 0);#if 1
// ************************VIDEO**********************************//// check the video streamvideoStream &#61; find_video_stream(pCtx);if (videoStream <0){printf("there is not video stream !!!!!!! \n");return -1;}pCodecCtxVideo&#61; pCtx->streams[videoStream]->codec;pCodecVideo &#61; avcodec_find_decoder(pCodecCtxVideo->codec_id);if (!pCodecVideo){printf("\ncan&#39;t find the video decoder!\n");return -1;}//open videoDecoderret &#61; avcodec_open2(pCodecCtxVideo, pCodecVideo, 0);if (ret <0){printf("avcodec_open2 error(video) \n");return -1;}pFrameVideo &#61; av_frame_alloc();pFrameRGB &#61; av_frame_alloc();
//------------------------------------------------------------------------//
#endif int tmp &#61; 10;//fb0 initopenframebuffer();init_fbmmap();while(av_read_frame(pCtx, &packet) >&#61; 0){#if 1//found the video frame !!! if (packet.stream_index &#61;&#61; videoStream) { int got; int i;
#if 1avcodec_decode_video2(pCodecCtxVideo, pFrameVideo,&got_picture,&packet); printf("pFrameVideo->width &#61; %d\n", pFrameVideo->width);printf("pFrameVideo->height &#61; %d\n", pFrameVideo->height);printf("pFrameVideo->linesize[0] &#61; %d\n", pFrameVideo->linesize[0]);printf("pFrameVideo->linesize[1] &#61; %d\n", pFrameVideo->linesize[1]);printf("pFrameVideo->linesize[2] &#61; %d\n", pFrameVideo->linesize[2]);
#endif//yuv420p -> rgb24int PictureSize &#61; avpicture_get_size (AV_PIX_FMT_BGR24, pCodecCtxVideo->width, pCodecCtxVideo->height);void *buf &#61; (uint8_t*)av_malloc(PictureSize);avpicture_fill ( (AVPicture *)pFrameRGB, buf,AV_PIX_FMT_BGR24, pCodecCtxVideo->width, pCodecCtxVideo->height);struct SwsContext* pSwsCxt &#61; sws_getContext(pFrameVideo->width,pFrameVideo->height,pCodecCtxVideo->pix_fmt,pFrameVideo->width, pFrameVideo->height,AV_PIX_FMT_BGR24, SWS_BILINEAR,NULL,NULL,NULL);sws_scale(pSwsCxt,pFrameVideo->data,pFrameVideo->linesize,0,pFrameVideo->height,pFrameRGB->data, pFrameRGB->linesize);av_log(NULL, AV_LOG_INFO, "pFrameRGB->linesize[0] &#61; %d\n", pFrameRGB->linesize[0]);//save the ARGB into BMP filesaveBitMap (pFrameRGB, pCodecCtxVideo->width, pCodecCtxVideo->height, 10, 24);fb_drawbmp(height, width, pFrame->data[0]); }
#endif }closefb();return 0;


推荐阅读
  • 本文介绍了使用C++Builder实现获取USB优盘序列号的方法,包括相关的代码和说明。通过该方法,可以获取指定盘符的USB优盘序列号,并将其存放在缓冲中。该方法可以在Windows系统中有效地获取USB优盘序列号,并且适用于C++Builder开发环境。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 本文介绍了一个题目的解法,通过二分答案来解决问题,但困难在于如何进行检查。文章提供了一种逃逸方式,通过移动最慢的宿管来锁门时跑到更居中的位置,从而使所有合格的寝室都居中。文章还提到可以分开判断两边的情况,并使用前缀和的方式来求出在任意时刻能够到达宿管即将锁门的寝室的人数。最后,文章提到可以改成O(n)的直接枚举来解决问题。 ... [详细]
  • 本文详细介绍了如何使用MySQL来显示SQL语句的执行时间,并通过MySQL Query Profiler获取CPU和内存使用量以及系统锁和表锁的时间。同时介绍了效能分析的三种方法:瓶颈分析、工作负载分析和基于比率的分析。 ... [详细]
  • WhenIusepythontoapplythepymysqlmoduletoaddafieldtoatableinthemysqldatabase,itdo ... [详细]
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
  • Android工程师面试准备及设计模式使用场景
    本文介绍了Android工程师面试准备的经验,包括面试流程和重点准备内容。同时,还介绍了建造者模式的使用场景,以及在Android开发中的具体应用。 ... [详细]
  • 本文介绍了在MFC下利用C++和MFC的特性动态创建窗口的方法,包括继承现有的MFC类并加以改造、插入工具栏和状态栏对象的声明等。同时还提到了窗口销毁的处理方法。本文详细介绍了实现方法并给出了相关注意事项。 ... [详细]
  • 本文讨论了如何使用GStreamer来删除H264格式视频文件中的中间部分,而不需要进行重编码。作者提出了使用gst_element_seek(...)函数来实现这个目标的思路,并提到遇到了一个解决不了的BUG。文章还列举了8个解决方案,希望能够得到更好的思路。 ... [详细]
  • 流数据流和IO流的使用及应用
    本文介绍了流数据流和IO流的基本概念和用法,包括输入流、输出流、字节流、字符流、缓冲区等。同时还介绍了异常处理和常用的流类,如FileReader、FileWriter、FileInputStream、FileOutputStream、OutputStreamWriter、InputStreamReader、BufferedReader、BufferedWriter等。此外,还介绍了系统流和标准流的使用。 ... [详细]
  • Question该提问来源于开源项目:react-native-device-info/react-native-device-info ... [详细]
  • STM32 IO口模拟串口通讯
    转自:http:ziye334.blog.163.comblogstatic224306191201452833850647前阵子,调项目时需要用到低波 ... [详细]
author-avatar
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有