首页 > 代码库 > 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));        //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);}

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

  

ffmpeg实现mjpeg摄像头的采集-预览-拍照