使用ffmpeg打开rtsp流等视频流

void open_rtsp(const char *rtsp)
{
    unsigned int    i;
    int             ret;
    int             video_st_index = -1;
    int             audio_st_index = -1;
    AVFormatContext *ifmt_ctx = NULL;
    AVPacket        pkt;
    AVStream        *st = NULL;
    char            errbuf[64];
    AVDictionary *optionsDict = NULL;
    av_register_all();                                                          // Register all codecs and formats so that they can be used.
    avformat_network_init();                                                    // Initialization of network components
    av_init_packet(&pkt);                                                       // initialize packet.
    pkt.data = NULL;
    pkt.size = 0;
    bool nRestart = false;
    AVStream *pVst;
    uint8_t* buffer_rgb = NULL;
    AVCodecContext *pVideoCodecCtx = NULL;
    AVFrame         *pFrame = av_frame_alloc();
    AVFrame         *pFrameRGB = av_frame_alloc();
    int got_picture;
    SwsContext      *img_convert_ctx = NULL;
    AVCodec *pVideoCodec = NULL;
    av_dict_set(&optionsDict, "rtsp_transport", "tcp", 0);                //采用tcp传输
    av_dict_set(&optionsDict, "stimeout", "2000000", 0);                  //如果没有设置stimeout,那么把ipc网线拔掉,av_read_frame会阻塞(时间单位是微妙)
    if ((ret = avformat_open_input(&ifmt_ctx, rtsp, 0, &optionsDict)) < 0) {            // Open the input file for reading.
        printf("Could not open input file '%s' (error '%s')\n", rtsp, av_make_error_string(errbuf, sizeof(errbuf), ret));
        goto EXIT;
    }

    if ((ret = avformat_find_stream_info(ifmt_ctx, NULL)) < 0) {                // Get information on the input file (number of streams etc.).
        printf("Could not open find stream info (error '%s')\n", av_make_error_string(errbuf, sizeof(errbuf), ret));
        goto EXIT;
    }

    for (i = 0; i < ifmt_ctx->nb_streams; i++) {                                // dump information
        av_dump_format(ifmt_ctx, i, rtsp, 0);
    }

    for (i = 0; i < ifmt_ctx->nb_streams; i++) 
    {                                // find video stream index
        st = ifmt_ctx->streams[i];
        switch (st->codec->codec_type) 
        {
        case AVMEDIA_TYPE_AUDIO: audio_st_index = i; break;
        case AVMEDIA_TYPE_VIDEO: video_st_index = i; break;
        default: break;
        }
    }
    if (-1 == video_st_index) {
        printf("No H.264 video stream in the input file\n");
        goto EXIT;
    }

    if (!nRestart)
    {
        pVst = ifmt_ctx->streams[video_st_index];
        pVideoCodecCtx = pVst->codec;
        pVideoCodec = avcodec_find_decoder(pVideoCodecCtx->codec_id);
        if (pVideoCodec == NULL)
            return;
        if (avcodec_open2(pVideoCodecCtx, pVideoCodec, NULL) < 0)
            return;
    }

    while (1)
    {
        do {
            ret = av_read_frame(ifmt_ctx, &pkt);                                // read frames
            if (pkt.stream_index == video_st_index)
            {
                //fprintf(stdout, "pkt.size=%d,pkt.pts=%lld, pkt.data=0x%x.", pkt.size, pkt.pts, (unsigned int)pkt.data);
                int av_result = avcodec_decode_video2(pVideoCodecCtx, pFrame, &got_picture, &pkt);

                if (av_result < 0)
                {
                    fprintf(stderr, "decode failed: inputbuf = 0x%x , input_framesize = %d\n", pkt.data, pkt.size);
                    return;
                }
#if 1
                if (got_picture)
                {
                    int bytes = avpicture_get_size(AV_PIX_FMT_RGB24, pVideoCodecCtx->width, pVideoCodecCtx->height);
                    buffer_rgb = (uint8_t *)av_malloc(bytes);
                    avpicture_fill((AVPicture *)pFrameRGB, buffer_rgb, AV_PIX_FMT_RGB24, pVideoCodecCtx->width, pVideoCodecCtx->height);

                    img_convert_ctx = sws_getContext(pVideoCodecCtx->width, pVideoCodecCtx->height, pVideoCodecCtx->pix_fmt,
                        pVideoCodecCtx->width, pVideoCodecCtx->height, AV_PIX_FMT_BGR24, SWS_FAST_BILINEAR, NULL, NULL, NULL);
                    if (img_convert_ctx == NULL)
                    {

                        printf("can't init convert context!\n");
                        return;
                    }
                    sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0, pVideoCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
                    IplImage *pRgbImg = cvCreateImage(cvSize(pVideoCodecCtx->width, pVideoCodecCtx->height), 8, 3);
                    memcpy(pRgbImg->imageData, buffer_rgb, pVideoCodecCtx->width * 3 * pVideoCodecCtx->height);
                    Mat Img = cvarrToMat(pRgbImg, true);
                    DetectFace(Img);
                    cvReleaseImage(&pRgbImg);
                    sws_freeContext(img_convert_ctx);
                    av_free(buffer_rgb);
                }
#endif
            }
        } while (ret == AVERROR(EAGAIN));

        if (ret < 0) {
            printf("Could not read frame ---(error '%s')\n", av_make_error_string(errbuf, sizeof(errbuf), ret));
            goto EXIT;
        }
        av_packet_unref(&pkt);
    }

EXIT:

    if (NULL != ifmt_ctx) {
        avcodec_close(pVideoCodecCtx);
        avformat_close_input(&ifmt_ctx);
        av_free(pFrame);
        av_free(pFrameRGB);
        ifmt_ctx = NULL;
    }

    return;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

telllong

你的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值