ffmpeg实现mjpeg摄像头的采集-预览-拍照
摄像头输出是mjpeg格式的,需要实现在线预览功能,然后实现拍照功能
1.可以设置采集图像的分辨率,预览分辨率为640*480,可以自定义
2.ctrl+\ 拍照,ctrl+c 退出
void test() {
if (signal(SIGQUIT, sigHandle) == SIG_ERR) {
perror("set signal err");
}
if (signal(SIGINT, sigHandle) == SIG_ERR) {
perror("set signal err");
}
AVOutputFormat *ofmt = NULL;
AVFormatContext *ifmt_ctx = NULL, *ofmt_ctx = NULL;
AVCodecContext *ifcodec_ctx, *ofcodec_ctx;
AVCodec *icodec, *ocodec;
AVStream *out_stream;
AVFrame *pFrame, *pFrameYUV420, *pFrameBGR;
struct SwsContext *in_conCtx, *out_conCtx;
unsigned char *in_buffer, *out_buffer;
AVPacket inpkg, outpkg;
const char *in_filename;
int ret, i;
int got_picture;
IplImage *image;
int videoindex = -;
int frame_index = ;
int64_t start_time = , end_time = ;
// in_filename = "test.mp4";
in_filename = "/dev/video1";
// in_filename = "rtmp://219.216.87.170/live/test3";
// out_filename = "rtmp://219.216.87.170/live/test2";
av_register_all();
avdevice_register_all();
avformat_network_init();
ifmt_ctx = avformat_alloc_context();
ifmt_ctx->probesize = ;
ifmt_ctx->max_analyze_duration = ;
AVDictionary* options = NULL;
av_dict_set(&options, "fflags", "nobuffer", );
av_dict_set(&options, "max_delay", "", );
av_dict_set(&options, "framerate", "", );
av_dict_set(&options, "input_format", "mjpeg", );
av_dict_set(&options, "video_size", "1920x1080", );
// av_dict_set(&options, "video_size", "1280x720", 0);
if ((ret = avformat_open_input(&ifmt_ctx, in_filename, , &options)) < ) {
printf("open input file err\n");
goto end;
}
av_dict_free(&options);
if ((ret = avformat_find_stream_info(ifmt_ctx, )) < ) {
printf("failed to retrieve input stream information\n");
goto end;
}
for (i = ; i < ifmt_ctx->nb_streams; i++) {
if (ifmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
videoindex = i;
break;
}
printf("codec %d:%d %d\n", i, ifmt_ctx->streams[i]->codec->codec_type,
ifmt_ctx->streams[i]->codec->codec_id);
}
// exit(1);
ifcodec_ctx = ifmt_ctx->streams[videoindex]->codec;
icodec = avcodec_find_decoder(ifcodec_ctx->codec_id);
if (icodec == NULL) {
printf("icodec not find\n");
goto end;
}
if (avcodec_open2(ifcodec_ctx, icodec, NULL) < ) {
printf("open icodec err\n");
goto end;
}
printf("**************** input file info ******************\n");
av_dump_format(ifmt_ctx, , in_filename, );
// avformat_alloc_output_context2(&ofmt_ctx, NULL, "flv", out_filename);
ofmt_ctx = avformat_alloc_context();
if (!ofmt_ctx) {
printf("could not create output context\n");
ret = AVERROR_UNKNOWN;
goto end;
}
ofmt = av_guess_format("mjpeg", NULL, NULL);
ofmt_ctx->oformat = ofmt;
out_stream = avformat_new_stream(ofmt_ctx, NULL);
if (!out_stream) {
printf("failed allocating output stream\n");
ret = AVERROR_UNKNOWN;
goto end;
}
ofcodec_ctx = out_stream->codec;
ofcodec_ctx->codec_id = ofmt->video_codec;
ofcodec_ctx->codec_type = AVMEDIA_TYPE_VIDEO;
ofcodec_ctx->pix_fmt = AV_PIX_FMT_YUVJ420P;
ofcodec_ctx->width = ifcodec_ctx->width;
ofcodec_ctx->height = ifcodec_ctx->height;
ofcodec_ctx->time_base.den = ;
ofcodec_ctx->time_base.num = ;
printf("timebase %d %d\n", ofcodec_ctx->time_base.den,
ofcodec_ctx->time_base.num);
// ofcodec_ctx->bit_rate = 1000000;
// ofcodec_ctx->gop_size = 5;
// ofcodec_ctx->me_range = 16;
// ofcodec_ctx->max_qdiff = 4;
// ofcodec_ctx->qmin = 10;
// ofcodec_ctx->qmax = 51;
// ofcodec_ctx->qcompress = 0.6;
// if (ofcodec_ctx->codec_id == AV_CODEC_ID_H264) {
// av_opt_set(ofcodec_ctx->priv_data, "preset", "slow", 0);
// ofcodec_ctx->max_b_frames = 1;
// }
out_stream->codec->codec_tag = ;
if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) {
out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
ocodec = avcodec_find_encoder(ofcodec_ctx->codec_id);
if (!ocodec) {
printf("find encoder err\n");
goto end;
}
if (avcodec_open2(ofcodec_ctx, ocodec, NULL) < ) {
printf("open encoder err\n");
goto end;
}
/*******************************************/
pFrame = av_frame_alloc();
pFrameYUV420 = av_frame_alloc();
pFrameBGR = av_frame_alloc();
in_buffer = (unsigned char *) av_malloc(
avpicture_get_size(AV_PIX_FMT_BGR24, , ));
avpicture_fill((AVPicture*) pFrameBGR, in_buffer, AV_PIX_FMT_BGR24, ,
);
// printf("fmt %d\twidth %d\theight %d\n", pFrameBGR->format, pFrameBGR->width,
// pFrameBGR->height);
out_buffer = (unsigned char *) av_malloc(
avpicture_get_size(AV_PIX_FMT_YUV420P, ofcodec_ctx->width,
ofcodec_ctx->height));
avpicture_fill((AVPicture*) pFrameYUV420, out_buffer, AV_PIX_FMT_YUV420P,
ofcodec_ctx->width, ofcodec_ctx->height);
// printf("fmt %d\twidth %d\theight %d\n", pFrameYUV420->format,
// pFrameYUV420->width, pFrameYUV420->height);
in_conCtx = sws_getContext(ifcodec_ctx->width, ifcodec_ctx->height,
ifcodec_ctx->pix_fmt, , ,
AV_PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL);
out_conCtx = sws_getContext(ifcodec_ctx->width, ifcodec_ctx->height,
ifcodec_ctx->pix_fmt, ofcodec_ctx->width, ofcodec_ctx->height,
ofcodec_ctx->pix_fmt, SWS_BICUBIC, NULL, NULL, NULL);
image = cvCreateImageHeader(cvSize(, ),
IPL_DEPTH_8U, );
cvSetData(image, in_buffer, * );
// inpkg = (AVPacket*) av_malloc(sizeof(AVPacket));
// outpkg = (AVPacket*) av_malloc(sizeof(AVPacket));
start_time = av_gettime();
pFrameYUV420->format = AV_PIX_FMT_YUV420P;
pFrameYUV420->width = ofcodec_ctx->width;
pFrameYUV420->height = ofcodec_ctx->height;
av_new_packet(&outpkg, ofcodec_ctx->width * ofcodec_ctx->height * );
while (av_read_frame(ifmt_ctx, &inpkg) >= && runFlag) {
inpkg.dts = av_rescale_q_rnd(inpkg.dts,
ifmt_ctx->streams[videoindex]->time_base,
ifmt_ctx->streams[videoindex]->codec->time_base,
(enum AVRounding) (AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
inpkg.pts = av_rescale_q_rnd(inpkg.pts,
ifmt_ctx->streams[videoindex]->time_base,
ifmt_ctx->streams[videoindex]->codec->time_base,
(enum AVRounding) (AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
//decode
if (inpkg.stream_index == videoindex) {
ret = avcodec_decode_video2(ifcodec_ctx, pFrame, &got_picture,
&inpkg);
if (ret < ) {
printf("decode err\n");
exit(-);
}
if (got_picture) {
pFrame->pts = av_frame_get_best_effort_timestamp(pFrame);
sws_scale(in_conCtx,
(const unsigned char * const *) pFrame->data,
pFrame->linesize, , ifcodec_ctx->height,
pFrameBGR->data, pFrameBGR->linesize);
// printf("bgr fmt %d\twidth %d\theight %d\n", pFrameBGR->format,
// pFrameBGR->width, pFrameBGR->height);
cvShowImage("camera", image);
cvWaitKey();
if (flag == ) {
char out_filename[];
memset(out_filename, , sizeof(out_filename));
sprintf(out_filename, "%d.jpg", frame_index);
printf("encode frame %d\n", frame_index++);
if (!(ofmt->flags & AVFMT_NOFILE)) {
ret = avio_open(&ofmt_ctx->pb, out_filename,
AVIO_FLAG_WRITE);
if (ret < ) {
printf("could not open output url '%s'\n",
out_filename);
goto end;
}
}
printf(
"**************** output file info ******************\n");
av_dump_format(ofmt_ctx, , out_filename, );
ret = avformat_write_header(ofmt_ctx, NULL);
if (ret < ) {
printf("error occurred when opening output URL\n");
goto end;
}
sws_scale(out_conCtx,
(const unsigned char * const *) pFrame->data,
pFrame->linesize, , ofcodec_ctx->height,
pFrameYUV420->data, pFrameYUV420->linesize);
// printf("yuv420 fmt %d\twidth %d\theight %d\n",
// pFrameYUV420->format, pFrameYUV420->width,
// pFrameYUV420->height);
got_picture = ;
pFrameYUV420->pts = pFrame->pts;
ret = avcodec_encode_video2(ofcodec_ctx, &outpkg,
pFrameYUV420, &got_picture);
if (ret < ) {
printf("encode err\n");
goto end;
}
if (got_picture == && flag == ) {
av_write_frame(ofmt_ctx, &outpkg);
av_free_packet(&outpkg);
av_write_trailer(ofmt_ctx);
}
flag = ;
}
}
}
//encode
av_free_packet(&inpkg);
end_time = av_gettime();
printf("fps:%2f\n", (float) / (end_time - start_time));
start_time = end_time;
}
end: sws_freeContext(in_conCtx);
sws_freeContext(out_conCtx);
free(in_buffer);
free(out_buffer);
av_free(pFrameYUV420);
av_free(pFrameBGR);
avcodec_close(ifcodec_ctx);
avcodec_close(ofcodec_ctx);
avformat_close_input(&ifmt_ctx);
if (ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE))
avio_close(ofmt_ctx->pb);
avformat_free_context(ofmt_ctx);
if (ret < && ret != AVERROR_EOF) {
printf("Error occurred.\n");
exit(-);
}
exit();
}
代码是从标准的视频采集/转码程序改过来的,是测试程序,没有啥封装,看起来比较乱。
ffmpeg实现mjpeg摄像头的采集-预览-拍照的更多相关文章
- MFC Camera 摄像头预览 拍照
windows 上开发摄像头程序,比较容易的方式是 OpenCV ,几行代码就能显示出来,但是简单的容易搞,有点难度定制化需求的就不这么容易了.所以说还是要从,最基础的 DirectShow 开始搞起 ...
- ffmpeg实现视频文件合并/截取预览视频/抽取音频/crop(裁剪)(ffmpeg4.2.2)
一,ffmpeg的安装 请参见: https://www.cnblogs.com/architectforest/p/12807683.html 说明:刘宏缔的架构森林是一个专注架构的博客,地址:ht ...
- Unity 摄像头竖屏预览显示的问题
Unity可以通过WebCamTexture打开摄像头,通过 cameraRawImage.texture = camTexture; 将贴图给RawImage,但是WebCamTexture只能设置 ...
- Android开发:实时处理摄像头预览帧视频------浅析PreviewCallback,onPreviewFrame,AsyncTask的综合应用(转)
原文地址:http://blog.csdn.net/yanzi1225627/article/details/8605061# 很多时候,android摄像头模块不仅预览,拍照这么简单,而是需要在预览 ...
- ffmpeg从USB摄像头采集一张原始图片(转)
本文讲解使用ffmpeg从USB摄像头中采集一帧数据并写入文件保存,测试平台使用全志A20平台,其他平台修改交叉工具链即可移植.开发环境使用eclipse+CDT.交叉工具链使用arm-Linux-g ...
- Android 摄像头预览悬浮窗
用CameraX打开摄像头预览,显示在界面上.结合悬浮窗的功能.实现一个可拖动悬浮窗,实时预览摄像头的例子. 这个例子放进了单独的模块里.使用时注意gradle里的细微差别. 操作摄像头,打开预览.这 ...
- Android 摄像头预览悬浮窗,可拖动,可显示在其他app上方
市面上常见的摄像头悬浮窗,如微信.手机QQ的视频通话功能,有如下特点: 整屏页面能切换到一个小的悬浮窗 悬浮窗能运行在其他app上方 悬浮窗能跳回整屏页面,并且悬浮窗消失 我们探讨过用CameraX打 ...
- DirectShow 进行视频预览和录制
这一篇讲怎么采集摄像头图像并预览,以及录制视频到本地. 程序实现流程 这里通过使用 CaptureGraphBuilder 来简化 Graph 的创建流程. 具体流程如下: 初始化 COM 库 创建各 ...
- Android Camera2 预览功能实现
1. 概述 最近在做一些关于人脸识别的项目,需要用到 Android 相机的预览功能.网上查阅相关资料后,发现 Android 5.0 及以后的版本中,原有的 Camera API 已经被 Camer ...
随机推荐
- ObjC之RunTime(下)
之前通过学习官方文档对runtime有了初步的认识,接下来就要研究学习runtime到底能用在哪些地方,能如何改进我们的程序. 本文也可以从icocoa浏览. Swizzling Swizzling可 ...
- 竞赛题解 - NOIP2018 赛道修建
\(\mathcal {NOIP2018}\) 赛道修建 - 竞赛题解 额--考试的时候大概猜到正解,但是时间不够了,不敢写,就写了骗分QwQ 现在把坑填好了~ 题目 (Copy from 洛谷) 题 ...
- input 输入的一些限制说明
input输入框 只能输入 数字可以有小数点 <input class="form_text" id="purchasePrice" name=" ...
- centos install rabbitmq
安装rabbitmq 需要环境上有erlang,没有安装的可以参照下面的内容进行安装: https://www.erlang-solutions.com/resources/download.html ...
- N对数的排列问题 HDU - 2554
N对数的排列问题 HDU - 2554 有N对双胞胎,他们的年龄分别是1,2,3,……,N岁,他们手拉手排成一队到野外去玩,要经过一根独木桥,为了安全起见,要求年龄大的和年龄小的排在一起,好让年龄大的 ...
- 串口UART学习笔记(一)
买了一个开发板学习FPGA,找到的各种东西就记录在这个博客里了,同时也方便把自己不会的问题找到的结果记录一下,都是自己手打,所以可能说的话不那么严谨,不那么精准,看到的人要带着自己的思考去看,记住尽信 ...
- js闭包的理解-目前网上分析的最透彻文章
js的闭包对于大家实际上并不陌生,但是真正敢说自己完全理解的人并不多.笔者在网上看到分析闭包的文章非常多,篇幅用的非常多,但是实际上分析的并不到位,或者根本就是不正确的.我有时候都在想,写这些文章的人 ...
- C++ STL中的 Set的用法
https://blog.csdn.net/yas12345678/article/details/52601454 -----源头此处 1.关于set的概念 set 是STL中的集合. 集合 ...
- VS2015编译MapWinGIS
在github上下载MapWinGIS,目前最新版本为4.9.5.0 GitHub上项目地址为:https://github.com/MapWindow/MapWinGIS 通过git客户端下载mas ...
- 【BZOJ1564】【NOI2009】二叉查找树(动态规划)
[BZOJ1564][NOI2009]二叉查找树(动态规划) 题面 BZOJ 洛谷 题目描述 已知一棵特殊的二叉查找树.根据定义,该二叉查找树中每个结点的数据值都比它左儿子结点的数据值大,而比它右儿子 ...