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));
        //decode
        if (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);
}

  代码是从标准的视频采集/转码程序改过来的,是测试程序,没有啥封装,看起来比较乱。

  

时间: 2024-10-10 04:16:12

ffmpeg实现mjpeg摄像头的采集-预览-拍照的相关文章

自定义相机(三) -- 视频流数据 AND 预览 拍照 变焦

实现功能: 1. 视频流数据 2. 预览和拍照变焦, 所见即所得. 运行环境: 1.  XCODE 5.1.1 2.  真机(IPHONE5  ,  IOS6.1.4) #import <UIKit/UIKit.h> #import <AVFoundation/AVFoundation.h> //导入 - "视频流" @interface MCViewController : UIViewController<AVCaptureVideoDataOutpu

Android自定义照相机 预览拍照 切换前后置摄像头

Android提供了Camera来控制拍照,步骤如下:(1)调用Camera的open()方法打开相机.(2)调用Camera的getParameters()获取拍照参数,该方法返回一个Cmera.Parameters对象.(3)调用Camera.Parameters对象对照相的参数进行设置.(4)调用Camera的setParameters(),并将Camera.Parameters对象作为参数传入,这样就可以对拍照进行参数控制,Android2.3.3以后不用设置.(5)调用Camerade

android通过camera和surfaceview选择摄像头并即时预览

在使用android设备的摄像头的时候我们有两种选择: 1.调用intent方法使用摄像头 2.通过camera类使用摄像头 第一种方法非常方便,不过需要跳到新的activity中,这样的用户体验并不是特别好 使用camera能有更大的自定义空间! 使用camera就需要用surfaceview显示摄像头的即时画面 我们这样设置layout: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android&qu

相机 视频流数据--预览 拍照 变焦

转载自 http://www.cnblogs.com/iCodePhone/p/3785283.html 实现功能: 1. 视频流数据 2. 预览和拍照变焦, 所见即所得. 运行环境: 1.  XCODE 5.1.1 2.  真机(IPHONE5  ,  IOS6.1.4) #import <UIKit/UIKit.h> #import <AVFoundation/AVFoundation.h> //导入 - "视频流" @interface MCViewCon

Android实战技巧之四十七:不用预览拍照与图片缩放剪裁

副标题:Take Picture without preview Android Google出于对隐私的保护,制定了一条门槛,即在Android应用开发中编写拍照程序是必需要有图像预览的.这会对那些恶意程序比如Android中泛滥的Service在后台偷偷记录手机用户的行为与周边信息.这样的门槛还包括手机厂商自带的相机软件在拍照时必须是有声音,这样要避免一些偷拍的情况. 处于技术调研与一些特殊无害场景的使用,我们要用到不用预览的拍照.此文就是以此为背景,做的一些调研.只是用不多与五款手机测试,

Android开发:实时处理摄像头预览帧视频------浅析PreviewCallback,onPreviewFrame,AsyncTask的综合应用(转)

原文地址:http://blog.csdn.net/yanzi1225627/article/details/8605061# 很多时候,android摄像头模块不仅预览,拍照这么简单,而是需要在预览视频的时候,能够做出一些检测,比如最常见的人脸检测.在未按下拍照按钮前,就检测出人脸然后矩形框标示出来,再按拍照.那么如何获得预览帧视频么? 只需要在Activity里继承PreviewCallback这个接口就行了.示例如下: public class RectPhoto extends Acti

利用Android Camera2 的照相机api 实现 实时的图像采集与预览

最近想要做一个客户端往服务器推送实时画面的功能,首先可以考虑到两种思路,一种是在客户端进行视频流的推送,主要利用RTSP等流媒体协议进行传输,而另外一种是通过摄像头获取当前画面,将每一帧作为对象单独传输. 项目想要实现的功能最终目的是对实时画面的每一帧进行处理,可以考虑客户端推流到服务器,再在服务器进行帧解析的操作,但由于目前很多的流媒体推送框架在推流端或者服务端都或多或少存在限制,很少有完全开源的项目,再加上传送画面的同时需要附带部分的数据,仍然需要另外建立连接进行传输,所以暂时搁置这一方案.

WebRTC中Android Demo中的摄像头从采集到预览流程

APPRTC-Demo调用流程 1.CallActivity#onCreate 执行startCall开始连接或创建房间 2.WebSocketClient#connectToRoom 请求一次服务器 3.回调到CallActivity#onConnectToRoom 开始创建对等连接,同时将视频采集对象,本地和远程的VideoSink,相关参数传入 localProxyVideoSink代理本地视频渲染器 remoteSinks是代理远程视频的渲染器,这里是一个集合 videoCapture是

Directshow_驱动摄像头预览视频

出于兴趣一直以来都断断续续看过dshow的东西,可没怎么系统地总结过(学习还是要多实践,多总结啊). dshow预览摄像头捕捉的视频比较简单基础,网上相关的资料很多,简单的思路由下面代码所示: ICaptureGraphBuilder2 *pBuild; // Capture Graph Builder // Initialize pBuild (not shown). IBaseFilter *pCap; // Video capture filter. /* Initialize pCap