实战小项目之基于嵌入式的图像采集压缩保存
2017-01-20 15:10
411 查看
项目简介
这是之前图像采集显示程序的升级版,首先基础部分的图像v4l2采集、framebuffer显示、IPU转码都进行了c++封装,之后加入了以下新功能:
SDL1.2显示
FFmpeg编码保存版本一(顺序执行)
FFmpeg编码保存版本二(线程方式)
c++ pthread库简单封装
这个小工程是一个附属产品,boss的项目中用到了图像编码保存,然后学了一段时间的多媒体技术(主要就是FFmpeg),后来就衍生出了这个版本的程序
不多说,上代码
首先是SDL显示部分
View Code
完整工程
https://github.com/tla001/CapTransV2
相关链接
ffmpeg移植
http://www.cnblogs.com/tla001/p/5906220.html
音视频处理(FFmpeg)基础
http://blog.csdn.net/leixiaohua1020/article/details/15811977
学习的资料,基本都是从雷神的博客中来的
相关命令
这是之前图像采集显示程序的升级版,首先基础部分的图像v4l2采集、framebuffer显示、IPU转码都进行了c++封装,之后加入了以下新功能:
SDL1.2显示
FFmpeg编码保存版本一(顺序执行)
FFmpeg编码保存版本二(线程方式)
c++ pthread库简单封装
这个小工程是一个附属产品,boss的项目中用到了图像编码保存,然后学了一段时间的多媒体技术(主要就是FFmpeg),后来就衍生出了这个版本的程序
不多说,上代码
首先是SDL显示部分
/* * EncodeSaver2.cpp * * Created on: Oct 12, 2016 * Author: tla001 */ #include "EncodeSaver2.h" EncodeSaver2::EncodeSaver2(int in_w,int in_h,int out_w,int out_h,char* out_file) { // TODO Auto-generated constructor stub this->in_w=in_w; this->in_h=in_h; this->out_w=out_w; this->out_h=out_h; this->framesize=0; this->out_file=out_file; this->basicsize=in_w*in_h; this->frameNum=0; this->ready=0; } EncodeSaver2::~EncodeSaver2() { // TODO Auto-generated destructor stub closeDevice(); } int EncodeSaver2::initDevice() { av_register_all(); //方法1.组合使用几个函数 pFormatCtx = avformat_alloc_context(); //猜格式 fmt = av_guess_format(NULL, out_file, NULL); pFormatCtx->oformat = fmt; if (avio_open(&pFormatCtx->pb,out_file, AVIO_FLAG_READ_WRITE) < 0) { printf("输出文件打开失败"); return -1; } video_st = av_new_stream(pFormatCtx, 0); if (video_st==NULL) { return -1; } pCodecCtx = video_st->codec; pCodecCtx->codec_id = fmt->video_codec; pCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO; pCodecCtx->pix_fmt = PIX_FMT_YUV420P; pCodecCtx->width = in_w; pCodecCtx->height = in_h; pCodecCtx->time_base.num = 1; pCodecCtx->time_base.den = 25; pCodecCtx->bit_rate = 400000; pCodecCtx->gop_size=250; //设置 video_st->time_base.num=1; video_st->time_base.den=25; //H264 pCodecCtx->me_range = 16; pCodecCtx->max_qdiff = 4; pCodecCtx->qmin = 10; pCodecCtx->qmax = 51; pCodecCtx->qcompress = 0.6; if (pCodecCtx->codec_id == CODEC_ID_MPEG2VIDEO) { pCodecCtx->max_b_frames = 2; } if (pCodecCtx->codec_id == CODEC_ID_MPEG1VIDEO) { pCodecCtx->mb_decision = 2; } if (!strcmp(pFormatCtx->oformat->name, "mp4") || !strcmp(pFormatCtx->oformat->name, "mov") || !strcmp(pFormatCtx->oformat->name, "3gp")) { pCodecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER; } //输出格式信息 av_dump_format(pFormatCtx, 0, out_file, 1); pCodec = avcodec_find_encoder(pCodecCtx->codec_id); if (!pCodec) { printf("没有找到合适的编码器!\n"); return -1; } if (avcodec_open2(pCodecCtx, pCodec,NULL) < 0) { printf("编码器打开失败!\n"); return -1; } //输出420 picture = avcodec_alloc_frame(); framesize = avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height); picture_buf = (uint8_t *)av_malloc(framesize); avpicture_fill((AVPicture *)picture, picture_buf, PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height); //输入422 picture422 = avcodec_alloc_frame(); framesize422 = avpicture_get_size(PIX_FMT_YUYV422, pCodecCtx->width, pCodecCtx->height); picture422_buf = (uint8_t *)av_malloc(framesize422); avpicture_fill((AVPicture *)picture422, picture422_buf, PIX_FMT_YUYV422, pCodecCtx->width, pCodecCtx->height); img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUYV422, pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL); //写文件头 avformat_write_header(pFormatCtx,NULL); av_new_packet(&pkt,basicsize*3); this->start(); cout<<"thread start"<<endl; } int EncodeSaver2::closeDevice() { this->stop(); int ret = flush_encoder(pFormatCtx,0); if (ret < 0) { printf("Flushing encoder failed\n"); return -1; } //写文件尾 av_write_trailer(pFormatCtx); //清理 if (video_st) { avcodec_close(video_st->codec); av_free(picture); av_free(picture_buf); av_free(picture422); av_free(picture422_buf); } avio_close(pFormatCtx->pb); avformat_free_context(pFormatCtx); return 0; } int EncodeSaver2::doEncode(unsigned char *buf) { int ret=0; //422 memcpy(picture422_buft.a,buf,basicsize*2); //picture422_bufs.push(picture422_buft); this->ready=1; return ret; } int EncodeSaver2::isReady(){ return ready; } void EncodeSaver2::run(){ int ret; struct timeval temp; temp.tv_sec = 0; temp.tv_usec = 40000000;//40ms printf("thread is up!\n"); while(1){ if(isStop()) pthread_exit(0); if(isStart()&&isReady()){ // printf("here 1\n"); // sleep(1); //select(0, NULL, NULL, NULL, &temp); //usleep(40000000); printf("**********time up********ttkf*** \n"); // if(picture422_bufs.empty()){ // cout<<" queue empty"<<endl; // continue; // } //picture422_buf=picture422_bufs.front().a; //picture422_bufs.pop(); memcpy(picture422_buf,picture422_buft.a,basicsize*2); picture422->data[0] = picture422_buf; sws_scale(img_convert_ctx, picture422->data, picture422->linesize, 0, pCodecCtx->height, picture->data, picture->linesize); //PTS if (pFormatCtx->oformat->flags & AVFMT_RAWPICTURE) { AVPacket pkt; av_init_packet(&pkt); pkt.flags |= AV_PKT_FLAG_KEY; pkt.stream_index = video_st->index; pkt.data = (uint8_t*)picture; pkt.size = sizeof(AVPicture); ret = av_write_frame(pFormatCtx, &pkt); } else{ int out_size = avcodec_encode_video(pCodecCtx, picture_buf, framesize, picture); if (out_size > 0) { AVPacket pkt; av_init_packet(&pkt); pkt.pts = av_rescale_q(pCodecCtx->coded_frame->pts, pCodecCtx->time_base, video_st->time_base); if (pCodecCtx->coded_frame->key_frame) { pkt.flags |= AV_PKT_FLAG_KEY; } pkt.stream_index = video_st->index; pkt.data = picture_buf; pkt.size = out_size; ret = av_write_frame(pFormatCtx, &pkt); } } }else{ printf("ready for data\n"); usleep(50000);//线程起来之后,由于参数没准备好,可能会空转 } } } int EncodeSaver2::flush_encoder(AVFormatContext *fmt_ctx,unsigned int stream_index) { int ret; int got_frame; AVPacket enc_pkt; if (!(fmt_ctx->streams[stream_index]->codec->codec->capabilities & CODEC_CAP_DELAY)) return 0; while (1) { printf("Flushing stream #%u encoder\n", stream_index); //ret = encode_write_frame(NULL, stream_index, &got_frame); enc_pkt.data = NULL; enc_pkt.size = 0; av_init_packet(&enc_pkt); ret = avcodec_encode_video2 (fmt_ctx->streams[stream_index]->codec, &enc_pkt, NULL, &got_frame); av_frame_free(NULL); if (ret < 0) break; if (!got_frame) {ret=0;break;} printf("successed frame!\n"); /* mux encoded frame */ ret = av_write_frame(fmt_ctx, &enc_pkt); if (ret < 0) break; } return ret; }
View Code
完整工程
https://github.com/tla001/CapTransV2
相关链接
ffmpeg移植
http://www.cnblogs.com/tla001/p/5906220.html
音视频处理(FFmpeg)基础
http://blog.csdn.net/leixiaohua1020/article/details/15811977
学习的资料,基本都是从雷神的博客中来的
相关命令
ffmpeg -f video4linux2 -i /dev/video0 -vcodec libx264 -s 320*240 -r 10 video0.mkv ffmpeg -f video4linux2 -s 640*480 -r 25 -i /dev/video0 test.avi
相关文章推荐
- 实战小项目之嵌入式linux图像采集与传输
- 基于嵌入式Linux的视频采集系统7---视频图像格式转化
- 实战小项目之基于嵌入式的视频直播客户端
- 基于嵌入式Linux的视频图像采集与传输
- 嵌入式实战项目:基于嵌入式linux花卉大棚温湿度监测与调节系统的设计与实现
- 基于USB的嵌入式CCD图像数据采集系统的实现
- 基于嵌入式Linux的视频图像采集与传输
- 基于PCI总线的嵌入式实时DSP图像采集系统(转)
- 基于嵌入式Linux的视频图像采集与传输
- 基于嵌入式Linux的视频图像采集与传输
- 基于PCI总线的嵌入式实时DSP图像采集系统-MIPS分析
- 嵌入式Linux的图像采集与显示
- 基于NiosⅡ的图像采集和显示的实现
- 基于OV6630图像传感器和DSP的图像采集系统设计
- 基于TMS320F2812的视频图像采集系统的设计
- 基于嵌入式Linux与S3C2410平台视频采集(转)
- 基于嵌入式linux和s3c2410平台的视频采集
- 基于ARM Linux的图像采集与蓝牙传输
- 基于Video4Linux 的USB摄像头图像采集实现
- 嵌入式Linux的图像采集与显示