protected void StartVideoThread(int fps) { int curGuid = currentGuid; Task.Factory.StartNew(() => { DateTime lasthandleTime = DateTime.Now; byte[] byteZero = new byte[0]; int dropFrameTime = 0; double perFrameTime = 1000 / fps; Stopwatch stopwatch = new Stopwatch(); while (curGuid == currentGuid) { stopwatch.Start(); VideoSt frameData = null; lasthandleTime = lasthandleTime.AddMilliseconds(perFrameTime); bool isReCalcTime = false; //时间没到时,等待 while (lasthandleTime > DateTime.Now || isWait) { if (curGuid != currentGuid) { break; } Thread.Sleep(1); if (isWait) { lasthandleTime = DateTime.Now.AddMilliseconds(perFrameTime); if (!isReCalcTime) { Console.WriteLine("重新计算播放时间"); isReCalcTime = true; } } } if (curGuid != currentGuid) { break; } if (frames.Count > 0) { //while (frames.Count > TempBufferSize) //{ // Console.WriteLine($"主动丢帧:{dropFrameTime}"); // frames.RemoveAt(0); //} frameData = frames[0]; frames.RemoveAt(0); } if (frames.Count <= 1) { isWait = true; } if (frameData != null) { //Console.WriteLine($"length:{frameData.data.Count()}"); callBack(frameData.width, frameData.height, frameData.data, frameData.stride, false); frameData = null; } stopwatch.Stop(); if (stopwatch.ElapsedMilliseconds == 0) { Console.WriteLine($"{lasthandleTime:mm:ss:ffff} -> {DateTime.Now:mm:ss:ffff}"); Console.WriteLine($"解析时间:{stopwatch.ElapsedMilliseconds}毫秒 wait:{isWait}"); } stopwatch.Reset(); } }); }
private unsafe void DecodeAllFramesToImages(AVHWDeviceType HWDevice) { isWait = true; frames.Clear(); audioFrames.Clear(); // decode all frames from url, please not it might local resorce, e.g. string url = "../../sample_mpeg4.mp4"; //var url = "http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"; // be advised this file holds 1440 frames //var url = "rtmp://58.200.131.2:1935/livetv/hunantv"; int curGuid = currentGuid; //FileStream fs = new FileStream("E://tt.mp3", FileMode.OpenOrCreate); using (var vsd = new AudioStreamDecoder(url, HWDevice)) { TempBufferSize = vsd.Fps / 2; StartVideoThread(vsd.Fps); StartAudioThread(); Console.WriteLine($"FPS:{vsd.Fps}"); Console.WriteLine($"codec name: {vsd.CodecName}"); var info = vsd.GetContextInfo(); info.ToList().ForEach(x => Console.WriteLine($"{x.Key} = {x.Value}")); var sourceSize = vsd.FrameSize; var sourcePixelFormat = HWDevice == AVHWDeviceType.AV_HWDEVICE_TYPE_NONE ? vsd.PixelFormat : GetHWPixelFormat(HWDevice); //var destinationSize = sourceSize; var destinationSize = new Size(1920, 1080); var destinationPixelFormat = AVPixelFormat.AV_PIX_FMT_BGR24; using (VideoFrameConverter vfc = new VideoFrameConverter(sourceSize, sourcePixelFormat, destinationSize, destinationPixelFormat)) { using (AudioFrameConverter afc = new AudioFrameConverter(vsd.in_sample_fmt, vsd.in_sample_rate, vsd.in_channels)) { naudioInit(vsd.in_sample_rate, vsd.in_channels); Stopwatch stopwatch = new Stopwatch(); while (vsd.TryDecodeNextFrame(out var frame, out bool isVideo)) { if (curGuid != currentGuid) { break; } if (isVideo) { if (!isLastMode) { while (frames.Count >= TempBufferSize) { if (curGuid != currentGuid) { break; } Thread.Sleep(1); } } //stopwatch.Start(); AVFrame convertedFrame = vfc.Convert(frame); int length = convertedFrame.height * convertedFrame.linesize[0]; byte[] managedArray = IntPrtToBytes((IntPtr)convertedFrame.data[0], length); VideoSt st = new VideoSt() { data = managedArray, width = convertedFrame.width, height = convertedFrame.height, stride = convertedFrame.linesize[0] }; frames.Add(st); if (frames.Count >= TempBufferSize) { isWait = false; } //stopwatch.Stop(); //Console.WriteLine($"解析时间:{stopwatch.ElapsedMilliseconds}毫秒"); //stopwatch.Reset(); } else { var convertedFrame = afc.Convert(frame); int length = convertedFrame.pkt_size; byte[] managedArray = new byte[0]; if (managedArray.Length != length) { managedArray = new byte[length]; } Marshal.Copy((IntPtr)convertedFrame.data[0], managedArray, 0, managedArray.Length); audioFrames.Add(new AudioSt() { data = managedArray }); } } } } } //fs.Close(); }