C# 调用ffmepg 读取海康或大华视频的功能

1 篇文章 0 订阅

一、C# 调用ffmepg

            调用C#FFmpeg.AutoGen.下载方法

 

注意这个版本需要和下载的ffmpeg的版本一致。也就是FFmpeg.AutoGen4.3.1那么下载的ffmpeg的动态链接库也要是4.3.1

ffmpeg下载

http://www.ffmpeg.org/download.html,下载静态共享版的DLL库

二、大华和海康的rtsp取流

//大华和海康rtsp地址可以根据型号去网上查找

例如大华:rtsp://admin:123456abc@10.8.30.50:554/cam/realmonitor?channel=1&subtype=1

根据这个地址可以下载VLC地址,输入上面地址到VLC的王若URL确保能够播放。

能够播放的话,写代码去推流。推流的地址需要了解第三点介绍的SRS推流。

三、SRS推流

http://www.ossrs.net/srs.release/releases/download.html

需要准备一个centos的服务器,安装SRS

根据自己的centos服务选择下载对应的服务

firewall-cmd –zone=public –add-port=9090/tcp –permanent

firewall-cmd –zone=public –add-port=1935/tcp –permanent

firewall-cmd –zone=public –add-port=8080/tcp –permanent

firewall-cmd --reload

  • 进入SRS-CentOS6-x86_64-x.x.x目录安装并启动流媒体服务(使用超级用户)

#./INSTALL

#cd /etc/init.d

#./srs start

启动以后推流服务器地址可以为:rtmp://x.x.x.x:1935/xxx

x.x.x.x是推流服务器地址

xxx是推流地址的子目录

四、推流服务器编码

 public unsafe void RunPushStream()
        {
           
            //开线程推
            int time = int.Parse(GetTimeStamp());
            playhandle = time;
            ThreadMethod(playhandle);
            
        }

 

 

unsafe static void ThreadMethod(object number)
        {
            PushStream pusher = null;
            for (int i = 0; i < GlobalVariable.PushStreamList.Count; i++)
            {
                var pusherTemp = GlobalVariable.PushStreamList[i];
                if (pusherTemp.playhandle == (int)number)
                {
                    pusher = GlobalVariable.PushStreamList[i];
                    //pusher.start_time = ffmpeg.av_gettime();
                    // pusher.RunPushStream();
                }
            }
            if (pusher == null)
                return;

            AVOutputFormat* ofmt = null;
            AVFormatContext* ifmt_ctx = null, ofmt_ctx = null;
            #region ffmpeg 转码
            var fmt = ffmpeg.avformat_alloc_context();

            int error;
            string url = "rtsp://admin:123456abc@10.8.30.50:554/cam/realmonitor?channel=1&subtype=1";
            //打开流
            error = ffmpeg.avformat_open_input(&fmt, url, null, null);

            pusher.pFormatContext = fmt;
            //if (error != 0) throw new ApplicationException(GetErrorMessage(error));

            // 读取媒体流信息
            error = ffmpeg.avformat_find_stream_info(pusher.pFormatContext, null);
            // if (error != 0) throw new ApplicationException(GetErrorMessage(error));


            for (var i = 0; i < pusher.pFormatContext->nb_streams; i++)
            {
                if (pusher.pFormatContext->streams[i]->codec->codec_type == AVMediaType.AVMEDIA_TYPE_VIDEO)
                {
                    // pStream = pFormatContext->streams[i];
                    pusher.videoindex = i;
                    // ffmpeg.avformat_new_stream(octx, pFormatContext->streams[i]->codec->codec);
                    //  ffmpeg.avcodec_parameters_copy(octx->streams[i]->codecpar, pFormatContext->streams[i]->codecpar);
                }

            }

            ffmpeg.av_dump_format(pusher.pFormatContext, 0, url, 0);

            AVPacket packet = new AVPacket();
            var pPacket = &packet;
            ffmpeg.av_init_packet(pPacket);

            int time = int.Parse(pusher.GetTimeStamp());
            string outUrl = string.Format("rtmp://192.168.60.129:1935/live/{0}", time);
            outUrl = "rtmp://192.168.60.129:1935/live/66";
            var octxtm = pusher.octx;
            var ret = ffmpeg.avformat_alloc_output_context2(&octxtm, null, "flv", outUrl);
            if (ret < 0)
            {

                Console.WriteLine(error + "\n");
            }

            // 从格式化上下文获取流索引
            pusher.octx = octxtm;
            for (var i = 0; i < pusher.pFormatContext->nb_streams; i++)
            {
                AVStream* in_stream = pusher.pFormatContext->streams[i];
                AVStream* out_stream = ffmpeg.avformat_new_stream(pusher.octx, in_stream->codec->codec);
                if (out_stream == null)
                {
                    Console.WriteLine("Failed allocating output stream\n");
                    ret = ffmpeg.AVERROR_UNKNOWN;
                    goto end;
                }

                //Copy the settings of AVCodecContext
                ret = ffmpeg.avcodec_copy_context(out_stream->codec, in_stream->codec);
                if (ret < 0)
                {
                    Console.WriteLine("Failed to copy context from input to output stream codec context\n");
                    goto end;
                }


            }

            ffmpeg.av_dump_format(pusher.octx, 0, outUrl, 1);
            //if (pStream == null) throw new ApplicationException(@"Could not found video stream.");

            // 初始化媒体数据包
            var frameNumber = 0;
            if ((pusher.octx->flags & ffmpeg.AVFMT_NOFILE) == 0)
            {
                ret = ffmpeg.avio_open(&pusher.octx->pb, outUrl, ffmpeg.AVIO_FLAG_WRITE);
                if (ret < 0)
                {
                    // printf("Could not open output URL '%s'", out_filename);
                    goto end;
                }
            }
            //Write file header
            ret = ffmpeg.avformat_write_header(pusher.octx, null);
            if (ret < 0)
            {
                // printf("Error occurred when opening output URL\n");
                goto end;
            }

            ifmt_ctx = pusher.pFormatContext;
            ofmt_ctx = pusher.octx;
            ofmt = ofmt_ctx->oformat;
            //AVPacket pkt;
            //var start_time = ffmpeg.av_gettime();


            pusher.starttime1 = ffmpeg.av_gettime();
            while (pusher.CanRun)
            {


                AVStream* in_stream, out_stream;
                //Get an AVPacket
                var pkt = pusher.pkt;
                ret = ffmpeg.av_read_frame(ifmt_ctx, &pkt);
                if (ret < 0)
                    break;
                pusher.pkt = pkt;
                //FIX:No PTS (Example: Raw H.264)
                //Simple Write PTS
                //rtsp://admin:123456abc@10.8.30.50:554/cam/realmonitor?channel=1&subtype=1
                if (pusher.pkt.pts == ffmpeg.AV_NOPTS_VALUE)
                {
                    //Write PTS
                    AVRational time_base1 = ifmt_ctx->streams[pusher.videoindex]->time_base;
                    //Duration between 2 frames (us)
                    double calc_duration = (double)ffmpeg.AV_TIME_BASE / ffmpeg.av_q2d(ifmt_ctx->streams[pusher.videoindex]->r_frame_rate);
                    //Parameters
                    pusher.pkt.pts = (long)((double)(pusher.frame_index * calc_duration) / (double)(ffmpeg.av_q2d(time_base1) * ffmpeg.AV_TIME_BASE));
                    pusher.pkt.dts = pusher.pkt.pts;
                    pusher.pkt.duration = (long)((double)calc_duration / (double)(ffmpeg.av_q2d(time_base1) * ffmpeg.AV_TIME_BASE));
                }
                //Important:Delay
                if (pusher.pkt.stream_index == pusher.videoindex)
                {
                    AVRational time_base = ifmt_ctx->streams[pusher.videoindex]->time_base;
                    AVRational time_base_q = new AVRational();
                    time_base_q.num = 1;
                    time_base_q.den = ffmpeg.AV_TIME_BASE;
                    long pts_time = ffmpeg.av_rescale_q(pusher.pkt.dts, time_base, time_base_q);
                    long now_time = ffmpeg.av_gettime() - pusher.starttime1;
                    if (pts_time > now_time)
                    {
                        //Console.WriteLine(pts_time - now_time);
                         // if (now_time > 1471268403)
                           
                       ffmpeg.av_usleep((uint)(pts_time - now_time));
                        //ffmpeg.av_usleep((uint)(1471268403));
                    }

                }

                in_stream = ifmt_ctx->streams[pusher.pkt.stream_index];
                out_stream = ofmt_ctx->streams[pusher.pkt.stream_index];
                // copy packet 
                //Convert PTS/DTS
                pusher.pkt.pts = ffmpeg.av_rescale_q_rnd(pusher.pkt.pts, in_stream->time_base, out_stream->time_base, (AVRounding)(AVRounding.AV_ROUND_NEAR_INF | AVRounding.AV_ROUND_PASS_MINMAX));
                pusher.pkt.dts = ffmpeg.av_rescale_q_rnd(pusher.pkt.dts, in_stream->time_base, out_stream->time_base, (AVRounding)(AVRounding.AV_ROUND_NEAR_INF | AVRounding.AV_ROUND_PASS_MINMAX));
                pusher.pkt.duration = ffmpeg.av_rescale_q(pusher.pkt.duration, in_stream->time_base, out_stream->time_base);
                pusher.pkt.pos = -1;
                //Print to Screen
                if (pusher.pkt.stream_index == pusher.videoindex)
                {
                   // Console.WriteLine("Send {0} video frames to output URL\n", pusher.frame_index);
                    pusher.frame_index++;
                }
                //ret = av_write_frame(ofmt_ctx, &pkt);
                ret = ffmpeg.av_interleaved_write_frame(ofmt_ctx, &pkt);

                if (ret < 0)
                {
                    Console.WriteLine("Error muxing packet\n");
                    // break;
                }

                ffmpeg.av_free_packet(&pkt);

                // pusher.frameNumber++;
            }

            ffmpeg.av_write_trailer(ofmt_ctx);
        end:
            var pcont = pusher.pFormatContext;
            ffmpeg.avformat_close_input(&pcont);
            // ffmpeg.avformat_close_input(&ifmt_ctx);

            if (ofmt_ctx != null && (ofmt->flags & ffmpeg.AVFMT_NOFILE) == 0)
                ffmpeg.avio_close(ofmt_ctx->pb);
            ffmpeg.avformat_free_context(ofmt_ctx);
            if (ret < 0 && ret != ffmpeg.AVERROR_EOF)
            {
                Console.WriteLine("Error occurred.\n");
                return;
            }
            #endregion
        }

 

需要DEMO:可以下载源码,下载后需要修改推流和拉流地址才能正常播放

 

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值