ffmpeg实现mjpeg摄像头的采集-预览-拍照
生活随笔
收集整理的這篇文章主要介紹了
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 = -1;int frame_index = 0;int64_t start_time = 0, end_time = 0; // 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 = 20000000;ifmt_ctx->max_analyze_duration = 2000;AVDictionary* options = NULL;av_dict_set(&options, "fflags", "nobuffer", 0);av_dict_set(&options, "max_delay", "100000", 0);av_dict_set(&options, "framerate", "30", 0);av_dict_set(&options, "input_format", "mjpeg", 0);av_dict_set(&options, "video_size", "1920x1080", 0); // av_dict_set(&options, "video_size", "1280x720", 0);if ((ret = avformat_open_input(&ifmt_ctx, in_filename, 0, &options)) < 0) {printf("open input file err\n");goto end;}av_dict_free(&options);if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0) {printf("failed to retrieve input stream information\n");goto end;}for (i = 0; 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) < 0) {printf("open icodec err\n");goto end;}printf("**************** input file info ******************\n");av_dump_format(ifmt_ctx, 0, in_filename, 0);// 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 = 30;ofcodec_ctx->time_base.num = 1;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 = 0;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) < 0) {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, 640, 480));avpicture_fill((AVPicture*) pFrameBGR, in_buffer, AV_PIX_FMT_BGR24, 640,480); // 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, 640, 480,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(640, 480),IPL_DEPTH_8U, 3);cvSetData(image, in_buffer, 640 * 3); // 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 * 3);while (av_read_frame(ifmt_ctx, &inpkg) >= 0 && 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));//decodeif (inpkg.stream_index == videoindex) {ret = avcodec_decode_video2(ifcodec_ctx, pFrame, &got_picture,&inpkg);if (ret < 0) {printf("decode err\n");exit(-1);}if (got_picture) {pFrame->pts = av_frame_get_best_effort_timestamp(pFrame);sws_scale(in_conCtx,(const unsigned char * const *) pFrame->data,pFrame->linesize, 0, 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(1);if (flag == 1) {char out_filename[30];memset(out_filename, 0, 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 < 0) {printf("could not open output url '%s'\n",out_filename);goto end;}}printf("**************** output file info ******************\n");av_dump_format(ofmt_ctx, 0, out_filename, 1);ret = avformat_write_header(ofmt_ctx, NULL);if (ret < 0) {printf("error occurred when opening output URL\n");goto end;}sws_scale(out_conCtx,(const unsigned char * const *) pFrame->data,pFrame->linesize, 0, ofcodec_ctx->height,pFrameYUV420->data, pFrameYUV420->linesize);// printf("yuv420 fmt %d\twidth %d\theight %d\n",// pFrameYUV420->format, pFrameYUV420->width,// pFrameYUV420->height); got_picture = 0;pFrameYUV420->pts = pFrame->pts;ret = avcodec_encode_video2(ofcodec_ctx, &outpkg,pFrameYUV420, &got_picture);if (ret < 0) {printf("encode err\n");goto end;}if (got_picture == 1 && flag == 1) {av_write_frame(ofmt_ctx, &outpkg);av_free_packet(&outpkg);av_write_trailer(ofmt_ctx);}flag = 0;}}}//encode av_free_packet(&inpkg);end_time = av_gettime();printf("fps:%2f\n", (float) 1000000 / (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 < 0 && ret != AVERROR_EOF) {printf("Error occurred.\n");exit(-1);}exit(0); }代碼是從標準的視頻采集/轉碼程序改過來的,是測試程序,沒有啥封裝,看起來比較亂。
轉載于:https://www.cnblogs.com/tla001/p/7061758.html
總結
以上是生活随笔為你收集整理的ffmpeg实现mjpeg摄像头的采集-预览-拍照的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 流程 dspace
- 下一篇: 华恩JAVA班第52天