C# 调用ffmepg 读取海康或大华视频的功能
一、C# 調(diào)用ffmepg
? ? ? ? ? ? 調(diào)用C#FFmpeg.AutoGen.下載方法
?
注意這個(gè)版本需要和下載的ffmpeg的版本一致。也就是FFmpeg.AutoGen4.3.1那么下載的ffmpeg的動(dòng)態(tài)鏈接庫也要是4.3.1
ffmpeg下載
http://www.ffmpeg.org/download.html,下載靜態(tài)共享版的DLL庫
二、大華和海康的rtsp取流
//大華和海康rtsp地址可以根據(jù)型號(hào)去網(wǎng)上查找
例如大華:rtsp://admin:123456abc@10.8.30.50:554/cam/realmonitor?channel=1&subtype=1
根據(jù)這個(gè)地址可以下載VLC地址,輸入上面地址到VLC的王若URL確保能夠播放。
能夠播放的話,寫代碼去推流。推流的地址需要了解第三點(diǎn)介紹的SRS推流。
三、SRS推流
http://www.ossrs.net/srs.release/releases/download.html
需要準(zhǔn)備一個(gè)centos的服務(wù)器,安裝SRS
根據(jù)自己的centos服務(wù)選擇下載對應(yīng)的服務(wù)
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
- 進(jìn)入SRS-CentOS6-x86_64-x.x.x目錄安裝并啟動(dòng)流媒體服務(wù)(使用超級(jí)用戶)
#./INSTALL
#cd /etc/init.d
#./srs start
啟動(dòng)以后推流服務(wù)器地址可以為:rtmp://x.x.x.x:1935/xxx
x.x.x.x是推流服務(wù)器地址
xxx是推流地址的子目錄
四、推流服務(wù)器編碼
?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 轉(zhuǎn)碼
? ? ? ? ? ? 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.");
? ? ? ? ? ? // 初始化媒體數(shù)據(jù)包
? ? ? ? ? ? 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:可以下載源碼,下載后需要修改推流和拉流地址才能正常播放
?
總結(jié)
以上是生活随笔為你收集整理的C# 调用ffmepg 读取海康或大华视频的功能的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C语言time函数
- 下一篇: DAV转换AVI指南