ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

ffmpeg拉取rtsp视频流

2021-02-20 10:02:45  阅读:158  来源: 互联网

标签:视频流 ffmpeg stream format rtsp ret video av pAVCodePar


公司项目需要提供实时显示网络摄像头实时视频.

void RTSPFFmpeg::rtsp_open(const char *url) {
    AVFormatContext* format_ctx = avformat_alloc_context();
    AVCodecContext *pAVCodecContext_video = nullptr;
    AVCodec *pAVCodec_video = nullptr;
    AVCodecParameters *pAVCodePar_video = avcodec_parameters_alloc();
    AVPacket *pAVPacket = av_packet_alloc(); ;                                  // ffmpeg单帧数据包
    AVFrame *pAVFrame_video = av_frame_alloc();                                 // ffmpeg单帧缓存
    AVFrame *pAVFrameRGB32_video = av_frame_alloc();                            // ffmpeg单帧缓存转换颜色空间后的缓存
    AVCodecParserContext *pAVCodeParseContext_video = nullptr;
    struct SwsContext *pSwsContext_video = nullptr;                             // ffmpeg编码数据格式转换
    AVDictionary * opts = nullptr;

    int ret = -1;
    int numBytes = 0;                                                           // 解码后的数据长度
    u_char *outBuffer = nullptr;                                                // 解码后的数据存放缓存区
 // open rtsp: Open an input stream and read the header. The codecs are not opened
    //const char* url = "rtsp://admin:genepoint2020@192.168.100.14:554/cam/realmonitor?channel=1&subtype=0";
    av_dict_set(&opts, "rtsp_transport", "tcp", 0);
    av_dict_set(&opts, "stimeout", "2000000", 0);
    // audio/video stream index
    int video_stream_index = -1;
   ret = avformat_open_input(&format_ctx, url, nullptr, &opts);
        if (ret != 0) {
            fprintf(stderr, "fail to open url: %s, return value: %d\n", url, ret);
continue;
        }
        // Read packets of a media file to get stream information
        ret = avformat_find_stream_info(format_ctx, nullptr);
        if (ret < 0) {
            fprintf(stderr, "fail to get stream information: %d\n", ret);
continue;
        }

        fprintf(stdout, "Number of elements in AVFormatContext.streams: %d\n", format_ctx->nb_streams);
        for (int i = 0; i < format_ctx->nb_streams; ++i) {
            const AVStream *stream = format_ctx->streams[i];
            fprintf(stdout, "type of the encoded data: %d\n", stream->codecpar->codec_id);
            if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
                video_stream_index = i;
                // 对找到的视频流寻解码器
                pAVCodePar_video = stream->codecpar;
                pAVCodec_video = avcodec_find_decoder(stream->codecpar->codec_id);
                if (!pAVCodec_video) {
                    video_stream_index = -1;
                    break;
                }
                pAVCodeParseContext_video = av_parser_init(pAVCodec_video->id);
                if (!pAVCodeParseContext_video) {
                    video_stream_index = -1;
                    break;
                }
                pAVCodecContext_video = avcodec_alloc_context3(pAVCodec_video);
                if (!pAVCodecContext_video) {
                }
                if (avcodec_open2(pAVCodecContext_video, pAVCodec_video, NULL) < 0) {
                    video_stream_index = -1;
                    break;
                }
                fprintf(stdout, "dimensions of the video frame in pixels: width: %d, height: %d, pixel format: %d\n",
                        stream->codecpar->width, stream->codecpar->height, stream->codecpar->format);
            }
        }
        if (video_stream_index == -1) {
            fprintf(stderr, "no video stream\n");
continue;
        }
        // 对拿到的原始数据格式进行缩放转换为指定的格式高宽大小
        pSwsContext_video = sws_getContext(
                pAVCodePar_video->width,
                pAVCodePar_video->height,
                static_cast<AVPixelFormat>(pAVCodePar_video->format),
                pAVCodePar_video->width,
                pAVCodePar_video->height,
                AV_PIX_FMT_RGBA,
                SWS_FAST_BILINEAR,
                nullptr,
                nullptr,
                nullptr
        );
        numBytes = av_image_get_buffer_size(
                AV_PIX_FMT_RGBA,
                pAVCodePar_video->width,
                pAVCodePar_video->height,
                1
        );
        outBuffer = (u_char *) av_malloc(numBytes);
        // pAVFrame32的data指针指向了outBuffer
        av_image_fill_arrays(
                pAVFrameRGB32_video->data,
                pAVFrameRGB32_video->linesize,
                outBuffer,
                AV_PIX_FMT_RGBA,
                pAVCodePar_video->width,
                pAVCodePar_video->height,
                1
        );
 while (1) {
        ret = av_read_frame(format_ctx, pAVPacket);
        if (ret < 0) {
            fprintf(stderr, "error or end of file: %d\n", ret);
continue;
        }
        if (pAVPacket->stream_index == video_stream_index) {
//            fprintf(stdout, "video stream, packet size: %d\n", pAVPacket->size);
            ret = avcodec_send_packet(pAVCodecContext_video,pAVPacket);
            if( 0 != ret){
continue;
            }
while (avcodec_receive_frame(pAVCodecContext_video,pAVFrame_video) == 0){
                sws_scale(pSwsContext_video,
                          (const uint8_t * const *)pAVFrame_video->data,
                          pAVFrame_video->linesize,
                          0,
                          pAVCodePar_video->height,
                          pAVFrameRGB32_video->data,
                          pAVFrameRGB32_video->linesize);
                QImage image((u_char*)outBuffer,pAVCodePar_video->width,pAVCodePar_video->height,QImage::Format_RGBA8888);
                emit rtsp_image_sig(image);
            }
        }
        av_packet_unref(pAVPacket);
    }
    av_parser_close(pAVCodeParseContext_video);
    av_frame_free(&pAVFrame_video);
    av_frame_free(&pAVFrameRGB32_video);
    av_free(outBuffer);
    av_free(pSwsContext_video);
    avcodec_free_context(&pAVCodecContext_video);
    avformat_close_input(&format_ctx);
}

 

标签:视频流,ffmpeg,stream,format,rtsp,ret,video,av,pAVCodePar
来源: https://www.cnblogs.com/ohsolong/p/14419291.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有