• 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
    ");
            goto end;
        }
        av_dict_free(&options);
        if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0) {
            printf("failed to retrieve input stream information
    ");
            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
    ", 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
    ");
            goto end;
        }
        if (avcodec_open2(ifcodec_ctx, icodec, NULL) < 0) {
            printf("open icodec err
    ");
            goto end;
        }
        printf("**************** input file info ******************
    ");
        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
    ");
            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
    ");
            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
    ", 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
    ");
            goto end;
        }
        if (avcodec_open2(ofcodec_ctx, ocodec, NULL) < 0) {
            printf("open encoder err
    ");
            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	width %d	height %d
    ", 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	width %d	height %d
    ", 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
    ");
                    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	width %d	height %d
    ", 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
    ", 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'
    ",
                                        out_filename);
                                goto end;
                            }
                        }
                        printf(
                                "**************** output file info ******************
    ");
                        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
    ");
                            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	width %d	height %d
    ",
                        //                        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
    ");
                            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
    ", (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.
    ");
            exit(-1);
        }
        exit(0);
    }

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

      

  • 相关阅读:
    easy ui 表单ajax和from两种提交数据方法
    easy ui 下拉级联效果 ,下拉框绑定数据select控件
    easy ui 下拉框绑定数据select控件
    easy ui 异步上传文件,跨域
    easy ui 菜单和按钮(Menu and Button)
    HTTP 错误 404.3
    EXTJS4.2 后台管理菜单栏
    HTML 背景图片自适应
    easy ui 表单元素input控件后面加说明(红色)
    EXTJS 4.2 添加滚动条
  • 原文地址:https://www.cnblogs.com/tla001/p/7061758.html
Copyright © 2020-2023  润新知