文档库 最新最全的文档下载
当前位置:文档库 › linux下ffmpeg3.0采集摄像头画面用libjpeg-turbo转成jpeg

linux下ffmpeg3.0采集摄像头画面用libjpeg-turbo转成jpeg

#include
#include
#include
#include
extern "C"{
#include "libavcodec/avcodec.h"
#include "libavutil/mem.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavdevice/avdevice.h"
}
#include "sys/time.h"
#include "turbojpeg.h"

using namespace std;

int tyuv2jpeg(unsigned char* yuv_buffer, int yuv_size, int width, int height, int subsample, unsigned char** jpeg_buffer, unsigned long* jpeg_size, int quality)
{
tjhandle handle = NULL;
int flags = 0;
int padding = 4; // 1或4均可,但不能是0
int need_size = 0;
int ret = 0;

handle = tjInitCompress();

flags |= 0;

need_size = tjBufSizeYUV2(width, padding, height, subsample);
if (need_size != yuv_size)
{
printf("we detect yuv size: %d, but you give: %d, check again.\n", need_size, yuv_size);
return 0;
}

ret = tjCompressFromYUV(handle,yuv_buffer, width, padding, height, subsample, jpeg_buffer, jpeg_size, quality, flags);
if (ret < 0)
{
printf("compress to jpeg failed: %s\n", tjGetErrorStr());
}

tjDestroy(handle);

return ret;
}

int main(int argc, char **argv) {
int ret;
int videoindex = -1;
AVFormatContext *fmtCtx = NULL;
AVCodecContext *c =NULL;
AVPacket pcaket;
AVDictionary *options = NULL;

/*1、注册*/
avcodec_register_all();
av_register_all();
avdevice_register_all();
/*2、连接视频源*/
av_init_packet(&pcaket);

AVInputFormat *inputFmt = av_find_input_format("video4linux2");
if (NULL != inputFmt) {
std::cout << "input device name:" << inputFmt->name << std::endl;
} else {
std::cout << "Null point!" << std::endl;
return -1;
}
/*设置分辨率*/
av_dict_set(&options, "video_size", "640x480", 0);
//av_dict_set(&options, "pixel_format","yuv422p", 0);

ret = avformat_open_input(&fmtCtx, "/dev/video0", inputFmt,&options);
if (0 == ret) {
std::cout << "Open input device seccess!" << std::endl;
}
//发现码流
if(avformat_find_stream_info(fmtCtx, NULL) < 0)
{
fprintf(stderr,"avformat_find_stream_info fail\n");
avformat_close_input(&fmtCtx);
avformat_free_context(fmtCtx);
exit(1);
}
//发现视频流
videoindex=-1;
int i = 0;
for(i=0; inb_streams; i++)
{
if(fmtCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO){
videoindex=i;
break;
}
}
if(videoindex==-1)
{
printf("Didn't find a video stream.\n");
return -1;
}
//取视频流句柄
c = fmtCtx->streams[videoindex]->codec;
printf("%d---%d-----%d\n",c->width,c->height,c->pix_fmt);
av_dump_format(fmtCtx,0,"/dev/video0",0);
struct SwsContext *img_convert_ctx = sws_getContext(c->

width,c->height,c->pix_fmt,c->width,c->height,AV_PIX_FMT_YUV420P,SWS_BICUBIC, NULL,NULL, NULL);

/*4、读取一帧数据,编码依据摄像头类型而定,我使用的摄像头输出的是yuv422格式*/
av_read_frame(fmtCtx,&pcaket);
AVFrame *frame=av_frame_alloc();
AVFrame *pFrameYUV=av_frame_alloc();
uint8_t *out_buffer=new uint8_t[avpicture_get_size(AV_PIX_FMT_YUV420P, c->width, c->height)];
avpicture_fill((AVPicture *)pFrameYUV, out_buffer, AV_PIX_FMT_YUV420P, c->width, c->height);
avpicture_fill((AVPicture *)frame, pcaket.data, c->pix_fmt, c->width, c->height);

sws_scale(img_convert_ctx, (const uint8_t* const*)frame->data, frame->linesize, 0,c->height,pFrameYUV->data,pFrameYUV->linesize);

int y_size=c->width*c->height;
unsigned char *jpegbuf = (unsigned char *)malloc(1024*1024*2);
unsigned char *yuvbuf = (unsigned char *)malloc(1024*1024*2);

memcpy(yuvbuf,pFrameYUV->data[0],y_size);
memcpy(yuvbuf+y_size,pFrameYUV->data[1],y_size/4);
memcpy(yuvbuf+y_size+y_size/4,pFrameYUV->data[2],y_size/4);

unsigned long jpegsize;
ret = tyuv2jpeg(yuvbuf,y_size+(y_size/4+y_size/4), c->width, c->height,TJSAMP_420,&jpegbuf,&jpegsize,50);
FILE *jfp = NULL;
jfp = fopen("out.jpg", "wb");
if (NULL != jfp) {
fwrite(jpegbuf,jpegsize,1,jfp);
}
//
av_free_packet(&pcaket);
fclose(jfp);
avcodec_close(c);
avformat_close_input(&fmtCtx);
free(jpegbuf);
free(yuvbuf);
delete out_buffer;
av_frame_free(&frame);
av_frame_free(&pFrameYUV);
sws_freeContext(img_convert_ctx);
av_dict_free(&options);
return 0;
}

相关文档
相关文档 最新文档