/// <summary> /// Stop video source. /// </summary> /// public void Stop() { if (IsRunning) { _res = ReasonToFinishPlaying.StoppedByUser; _abort.Set(); } else { _res = ReasonToFinishPlaying.StoppedByUser; PlayingFinished?.Invoke(this, new PlayingFinishedEventArgs(_res)); } }
// Worker thread private void WorkerThread( ) { try { _camera.StartAcquisition( ); // while there is no request for stop while (!_abort.WaitOne(10) && !MainForm.ShuttingDown) { // start time DateTime start = DateTime.Now; // get next frame if (ShouldEmitFrame) { using (var bitmap = _camera.GetImage(15000, false)) { NewFrame?.Invoke(this, new NewFrameEventArgs(bitmap)); } } } } catch (Exception ex) { Logger.LogException(ex, "XIMEA"); _res = ReasonToFinishPlaying.VideoSourceError; } finally { try { _camera?.StopAcquisition( ); } catch { } } PlayingFinished?.Invoke(this, new PlayingFinishedEventArgs(_res)); }
/// <summary> /// Worker thread. /// </summary> /// private void WorkerThread() { ReasonToFinishPlaying reasonToStop = ReasonToFinishPlaying.StoppedByUser; try { // run mediaControl.Run(); while (!stopEvent.WaitOne(0, true)) { Thread.Sleep(100); if (mediaEvent != null) { if (mediaEvent.GetEvent(out DsEvCode code, out IntPtr p1, out IntPtr p2, 0) >= 0) { mediaEvent.FreeEventParams(code, p1, p2); if (code == DsEvCode.Complete) { reasonToStop = ReasonToFinishPlaying.EndOfStreamReached; break; } } } } mediaControl.StopWhenReady(); } catch (Exception exception) { // provide information to clients VideoSourceError?.Invoke(this, new VideoSourceErrorEventArgs(exception.Message)); } finally { DestroyFilters(); } PlayingFinished?.Invoke(this, reasonToStop); }
private void CleanUp() { try { Program.MutexHelper.Wait(); if (pConvertedFrameBuffer != IntPtr.Zero) { Marshal.FreeHGlobal(pConvertedFrameBuffer); pConvertedFrameBuffer = IntPtr.Zero; } if (_formatContext != null) { if (_formatContext->streams != null) { var j = (int)_formatContext->nb_streams; for (var i = j - 1; i >= 0; i--) { var stream = _formatContext->streams[i]; if (stream != null && stream->codec != null && stream->codec->codec != null) { stream->discard = AVDiscard.AVDISCARD_ALL; ffmpeg.avcodec_close(stream->codec); } } } fixed(AVFormatContext **f = &_formatContext) { ffmpeg.avformat_close_input(f); } _formatContext = null; } if (_hwDeviceCtx != null) { var f = _hwDeviceCtx; ffmpeg.av_buffer_unref(&f); _hwDeviceCtx = null; } _videoStream = null; _audioStream = null; _audioCodecContext = null; _videoCodecContext = null; if (_swrContext != null) { fixed(SwrContext **s = &_swrContext) { ffmpeg.swr_free(s); } _swrContext = null; } if (pConvertContext != null) { ffmpeg.sws_freeContext(pConvertContext); pConvertContext = null; } if (sampleChannel != null) { sampleChannel.PreVolumeMeter -= SampleChannelPreVolumeMeter; sampleChannel = null; } } catch (Exception ex) { Logger.LogException(ex, SourceName + ": Media Stream (close)"); } finally { try { Program.MutexHelper.Release(); } catch { } } PlayingFinished?.Invoke(this, new PlayingFinishedEventArgs(_res)); AudioFinished?.Invoke(this, new PlayingFinishedEventArgs(_res)); }
// Worker thread private void WorkerThread() { var res = ReasonToFinishPlaying.StoppedByUser; while (!_stopEvent.WaitOne(0, false) && !MainForm.ShuttingDown) { try { DateTime start = DateTime.UtcNow; // increment frames counter _framesReceived++; // provide new image to clients if (NewFrame != null) { Screen s = Screen.AllScreens[_screenindex]; if (_screenSize == Rectangle.Empty) { if (_area != Rectangle.Empty) { _screenSize = _area; } else { _screenSize = s.Bounds; //virtual clients can have odd dimensions if (_screenSize.Width % 2 != 0) { _screenSize.Width = _screenSize.Width - 1; } if (_screenSize.Height % 2 != 0) { _screenSize.Height = _screenSize.Height - 1; } } } using (var target = new Bitmap(_screenSize.Width, _screenSize.Height, PixelFormat.Format24bppRgb)) { using (Graphics g = Graphics.FromImage(target)) { try { g.CopyFromScreen(s.Bounds.X + _screenSize.X, s.Bounds.Y + _screenSize.Y, 0, 0, new Size(_screenSize.Width, _screenSize.Height)); } catch (Exception ex) { throw new Exception("Error grabbing screen (" + ex.Message + ") - disable screensaver."); //probably remote desktop or screensaver has kicked in } if (MousePointer) { var cursorBounds = new Rectangle( Cursor.Position.X - s.Bounds.X - _screenSize.X, Cursor.Position.Y - s.Bounds.Y - _screenSize.Y, Cursors.Default.Size.Width, Cursors.Default.Size.Height); Cursors.Default.Draw(g, cursorBounds); } } // notify client NewFrame?.Invoke(this, new NewFrameEventArgs(target)); _error = false; } } // wait for a while ? if (_frameInterval > 0) { // get download duration TimeSpan span = DateTime.UtcNow.Subtract(start); // milliseconds to sleep int msec = _frameInterval - (int)span.TotalMilliseconds; if ((msec > 0) && (_stopEvent.WaitOne(msec, false))) { break; } } } catch (Exception ex) { if (!_error) { MainForm.LogExceptionToFile(ex, "Desktop"); _error = true; } // provide information to clients res = ReasonToFinishPlaying.DeviceLost; // wait for a while before the next try Thread.Sleep(250); break; } } PlayingFinished?.Invoke(this, new PlayingFinishedEventArgs(res)); }
private void Init() { _mediaPlayer?.Dispose(); _videoFormat = VideoFormat; _lockCB = LockVideo; _unlockCB = UnlockVideo; _displayCB = DisplayVideo; //_cleanupVideoCB = CleanupVideo; _audioSetup = AudioSetup; _processAudio = ProcessAudio; _cleanupAudio = CleanupAudio; _pauseAudio = PauseAudio; _resumeAudio = ResumeAudio; _flushAudio = FlushAudio; _drainAudio = DrainAudio; string overrideURL = null; if (_camera != null) { switch (_camera.Camobject.settings.sourceindex) { case 9: var od = _camera.ONVIFDevice; if (od != null) { var ep = od.StreamEndpoint; if (ep != null) { var u = ep.Uri.Uri; overrideURL = u; } } break; } } FromType ftype = FromType.FromLocation; Seekable = false; var murl = overrideURL ?? Source; if (string.IsNullOrEmpty(murl)) { throw new Exception("Video source is empty"); } try { var p = Path.GetFullPath(overrideURL ?? Source); Seekable = !string.IsNullOrEmpty(p); if (Seekable) { ftype = FromType.FromPath; } } catch (Exception) { Seekable = false; } using (var media = new Media(LibVLC, murl, ftype)) { Duration = Time = 0; foreach (var opt in _options) { media.AddOption(opt); } _mediaPlayer = new MediaPlayer(media); _mediaPlayer.SetVideoFormatCallbacks(_videoFormat, null);// _cleanupVideoCB); _mediaPlayer.SetVideoCallbacks(_lockCB, _unlockCB, _displayCB); _mediaPlayer.TimeChanged += _mediaPlayer_TimeChanged; _mediaPlayer.EnableHardwareDecoding = false; _mediaPlayer.SetAudioFormatCallback(_audioSetup, _cleanupAudio); _mediaPlayer.SetAudioCallbacks(_processAudio, _pauseAudio, _resumeAudio, _flushAudio, _drainAudio); _mediaPlayer.EncounteredError += (sender, e) => { ErrorHandler?.Invoke("VLC Error"); _res = ReasonToFinishPlaying.VideoSourceError; }; _mediaPlayer.EndReached += (sender, e) => { _res = ReasonToFinishPlaying.VideoSourceError; }; _mediaPlayer.Stopped += (sender, e) => { Logger.LogMessage("VLC stopped"); Task.Run(() => { Debug.WriteLine("CLEANUP"); IsRunning = false; _stopping = false; _stopped?.Set(); PlayingFinished?.Invoke(this, new PlayingFinishedEventArgs(_res)); AudioFinished?.Invoke(this, new PlayingFinishedEventArgs(_res)); }); }; } _lastTimeUpdate = DateTime.UtcNow; _mediaPlayer.Play(); }
private void WorkerThread() { bool file = false; try { if (File.Exists(_source)) { file = true; } } catch { // ignored } if (_mFactory == null) { var args = new List <string> { "-I", "dumy", "--ignore-config", "--no-osd", "--disable-screensaver", "--plugin-path=./plugins" }; if (file) { args.Add("--file-caching=3000"); } try { var l2 = args.ToList(); l2.AddRange(_arguments); l2 = l2.Distinct().ToList(); _mFactory = new MediaPlayerFactory(l2.ToArray()); } catch (Exception ex) { MainForm.LogExceptionToFile(ex, "VLC Stream"); MainForm.LogMessageToFile("VLC arguments are: " + string.Join(",", args.ToArray()), "VLC Stream"); MainForm.LogMessageToFile("Using default VLC configuration.", "VLC Stream"); _mFactory = new MediaPlayerFactory(args.ToArray()); } GC.KeepAlive(_mFactory); } _mMedia = file ? _mFactory.CreateMedia <IMediaFromFile>(_source) : _mFactory.CreateMedia <IMedia>(_source); _mMedia.Events.DurationChanged += EventsDurationChanged; _mMedia.Events.StateChanged += EventsStateChanged; if (_mPlayer != null) { try { _mPlayer?.Dispose(); } catch { // ignored } _mPlayer = null; } _mPlayer = _mFactory.CreatePlayer <IVideoPlayer>(); _mPlayer.Events.TimeChanged += EventsTimeChanged; var fc = new Func <SoundFormat, SoundFormat>(SoundFormatCallback); _mPlayer.CustomAudioRenderer.SetFormatCallback(fc); var ac = new AudioCallbacks { SoundCallback = SoundCallback }; _mPlayer.CustomAudioRenderer.SetCallbacks(ac); _mPlayer.CustomAudioRenderer.SetExceptionHandler(Handler); _mPlayer.CustomRenderer.SetCallback(FrameCallback); _mPlayer.CustomRenderer.SetExceptionHandler(Handler); GC.KeepAlive(_mPlayer); _needsSetup = true; _stopping = false; _mPlayer.CustomRenderer.SetFormat(new BitmapFormat(FormatWidth, FormatHeight, ChromaType.RV24)); _mPlayer.Open(_mMedia); _mMedia.Parse(true); _mPlayer.Delay = 0; _framesReceived = 0; Duration = Time = 0; LastFrame = DateTime.MinValue; //check if file source (isseekable in _mPlayer is not reliable) Seekable = false; try { var p = Path.GetFullPath(_mMedia.Input); Seekable = !string.IsNullOrEmpty(p); } catch (Exception) { Seekable = false; } _mPlayer.WindowHandle = IntPtr.Zero; _videoQueue = new ConcurrentQueue <Bitmap>(); _audioQueue = new ConcurrentQueue <byte[]>(); _eventing = new Thread(EventManager) { Name = "vlc eventing", IsBackground = true }; _eventing.Start(); _mPlayer.Play(); _stopEvent.WaitOne(); if (_eventing != null && !_eventing.Join(0)) { _eventing.Join(); } if (!Seekable && !_stopRequested) { PlayingFinished?.Invoke(this, new PlayingFinishedEventArgs(ReasonToFinishPlaying.DeviceLost)); AudioFinished?.Invoke(this, new PlayingFinishedEventArgs(ReasonToFinishPlaying.DeviceLost)); } else { PlayingFinished?.Invoke(this, new PlayingFinishedEventArgs(ReasonToFinishPlaying.StoppedByUser)); AudioFinished?.Invoke(this, new PlayingFinishedEventArgs(ReasonToFinishPlaying.StoppedByUser)); } DisposePlayer(); _stopEvent?.Close(); _stopEvent = null; }
// Worker thread private void WorkerThread() { // buffer to read stream byte[] buffer = new byte[bufSize]; // JPEG magic number byte[] jpegMagic = new byte[] { 0xFF, 0xD8, 0xFF }; int jpegMagicLength = 3; ASCIIEncoding encoding = new ASCIIEncoding(); while (!stopEvent.WaitOne(0, false)) { // reset reload event reloadEvent.Reset(); // HTTP web request HttpWebRequest request = null; // web responce WebResponse response = null; // stream for MJPEG downloading Stream stream = null; // boundary betweeen images (string and binary versions) byte[] boundary = null; string boudaryStr = null; // length of boundary int boundaryLen; // flag signaling if boundary was checked or not bool boundaryIsChecked = false; // read amounts and positions int read, todo = 0, total = 0, pos = 0, align = 1; int start = 0, stop = 0; // align // 1 = searching for image start // 2 = searching for image end try { // create request request = (HttpWebRequest)WebRequest.Create(source); // set user agent if (HttpUserAgent != null) { request.UserAgent = HttpUserAgent; } // set proxy if (Proxy != null) { request.Proxy = Proxy; } // set timeout value for the request request.Timeout = RequestTimeout; // set login and password if ((Login != null) && (Password != null) && (Login != string.Empty)) { request.Credentials = new NetworkCredential(Login, Password); } // set connection group name if (SeparateConnectionGroup) { request.ConnectionGroupName = GetHashCode().ToString(); } // force basic authentication through extra headers if required if (ForceBasicAuthentication) { string authInfo = string.Format("{0}:{1}", Login, Password); authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo)); request.Headers["Authorization"] = "Basic " + authInfo; } // get response response = request.GetResponse(); // check content type string contentType = response.ContentType; string[] contentTypeArray = contentType.Split('/'); // "application/octet-stream" if ((contentTypeArray[0] == "application") && (contentTypeArray[1] == "octet-stream")) { boundaryLen = 0; boundary = new byte[0]; } else if ((contentTypeArray[0] == "multipart") && (contentType.Contains("mixed"))) { // get boundary int boundaryIndex = contentType.IndexOf("boundary", 0); if (boundaryIndex != -1) { boundaryIndex = contentType.IndexOf("=", boundaryIndex + 8); } if (boundaryIndex == -1) { // try same scenario as with octet-stream, i.e. without boundaries boundaryLen = 0; boundary = new byte[0]; } else { boudaryStr = contentType.Substring(boundaryIndex + 1); // remove spaces and double quotes, which may be added by some IP cameras boudaryStr = boudaryStr.Trim(' ', '"'); boundary = encoding.GetBytes(boudaryStr); boundaryLen = boundary.Length; boundaryIsChecked = false; } } else { throw new Exception("Invalid content type."); } // get response stream stream = response.GetResponseStream(); stream.ReadTimeout = RequestTimeout; // loop while ((!stopEvent.WaitOne(0, false)) && (!reloadEvent.WaitOne(0, false))) { // check total read if (total > bufSize - readSize) { total = pos = todo = 0; } // read next portion from stream if ((read = stream.Read(buffer, total, readSize)) == 0) { throw new ApplicationException(); } total += read; todo += read; // increment received bytes counter bytesReceived += read; // do we need to check boundary ? if ((boundaryLen != 0) && (!boundaryIsChecked)) { // some IP cameras, like AirLink, claim that boundary is "myboundary", // when it is really "--myboundary". this needs to be corrected. pos = ByteArrayUtils.Find(buffer, boundary, 0, todo); // continue reading if boudary was not found if (pos == -1) { continue; } for (int i = pos - 1; i >= 0; i--) { byte ch = buffer[i]; if ((ch == (byte)'\n') || (ch == (byte)'\r')) { break; } boudaryStr = (char)ch + boudaryStr; } boundary = encoding.GetBytes(boudaryStr); boundaryLen = boundary.Length; boundaryIsChecked = true; } // search for image start if ((align == 1) && (todo >= jpegMagicLength)) { start = ByteArrayUtils.Find(buffer, jpegMagic, pos, todo); if (start != -1) { // found JPEG start pos = start + jpegMagicLength; todo = total - pos; align = 2; } else { // delimiter not found todo = jpegMagicLength - 1; pos = total - todo; } } // search for image end ( boundaryLen can be 0, so need extra check ) while ((align == 2) && (todo != 0) && (todo >= boundaryLen)) { stop = ByteArrayUtils.Find(buffer, (boundaryLen != 0) ? boundary : jpegMagic, pos, todo); if (stop != -1) { pos = stop; todo = total - pos; // increment frames counter framesReceived++; // image at stop if ((NewFrame != null) && (!stopEvent.WaitOne(0, false))) { var frame = new byte[stop - start]; Array.Copy(buffer, start, frame, 0, stop - start); NewFrame(frame); } // shift array pos = stop + boundaryLen; todo = total - pos; Array.Copy(buffer, pos, buffer, 0, todo); total = todo; pos = 0; align = 1; } else { // boundary not found if (boundaryLen != 0) { todo = boundaryLen - 1; pos = total - todo; } else { todo = 0; pos = total; } } } } } catch (ApplicationException) { // do nothing for Application Exception, which we raised on our own // wait for a while before the next try Thread.Sleep(250); } catch (ThreadAbortException) { break; } catch (Exception exception) { // provide information to clients VideoSourceError?.Invoke(exception.Message); // wait for a while before the next try Thread.Sleep(250); } finally { // abort request if (request != null) { request.Abort(); request = null; } // close response stream if (stream != null) { stream.Close(); stream = null; } // close response if (response != null) { response.Close(); response = null; } } // need to stop ? if (stopEvent.WaitOne(0, false)) { break; } } PlayingFinished?.Invoke(ReasonToFinishPlaying.StoppedByUser); }
void VideoSourcePlayingFinished(object sender, PlayingFinishedEventArgs e) { PlayingFinished?.Invoke(sender, e); }
private void DoStart() { var vss = Source; if (!_modeAudio) { vss = Tokenise(vss); } AVDictionary *options = null; if (_inputFormat == null) { ffmpeg.av_dict_set(&options, "analyzeduration", _analyzeDuration.ToString(), 0); string prefix = vss.ToLower().Substring(0, vss.IndexOf(":", StringComparison.Ordinal)); switch (prefix) { case "http": case "mmsh": case "mms": ffmpeg.av_dict_set(&options, "timeout", _timeout.ToString(), 0); ffmpeg.av_dict_set(&options, "stimeout", (_timeout * 1000).ToString(), 0); if (_cookies != "") { ffmpeg.av_dict_set(&options, "cookies", _cookies, 0); } if (_headers != "") { ffmpeg.av_dict_set(&options, "headers", _headers, 0); } if (_userAgent != "") { ffmpeg.av_dict_set(&options, "user-agent", _userAgent, 0); } break; case "tcp": case "udp": case "rtp": case "sdp": case "mmst": case "ftp": ffmpeg.av_dict_set(&options, "timeout", _timeout.ToString(), 0); break; case "rtsp": case "rtmp": ffmpeg.av_dict_set(&options, "stimeout", (_timeout * 1000).ToString(), 0); if (_userAgent != "") { ffmpeg.av_dict_set(&options, "user-agent", _userAgent, 0); } break; } ffmpeg.av_dict_set(&options, "rtsp_transport", RTSPmode, 0); } ffmpeg.av_dict_set(&options, "rtbufsize", "10000000", 0); var lo = _options.Split(Environment.NewLine.ToCharArray()); foreach (var nv in lo) { if (!string.IsNullOrEmpty(nv)) { var i = nv.IndexOf('='); if (i > -1) { var n = nv.Substring(0, i).Trim(); var v = nv.Substring(i + 1).Trim(); if (!string.IsNullOrEmpty(n) && !string.IsNullOrEmpty(v)) { int j; if (int.TryParse(v, out j)) { ffmpeg.av_dict_set_int(&options, n, j, 0); } else { ffmpeg.av_dict_set(&options, n, v, 0); } } } } } _stopReadingFrames = false; try { Program.FfmpegMutex.WaitOne(); var pFormatContext = ffmpeg.avformat_alloc_context(); _lastPacket = DateTime.UtcNow; _interruptCallback = InterruptCb; _interruptCallbackAddress = Marshal.GetFunctionPointerForDelegate(_interruptCallback); pFormatContext->interrupt_callback.callback = _interruptCallbackAddress; pFormatContext->interrupt_callback.opaque = null; if (ffmpeg.avformat_open_input(&pFormatContext, vss, _inputFormat, &options) != 0) { throw new ApplicationException(@"Could not open source"); } _formatContext = pFormatContext; SetupFormat(); } catch (Exception ex) { ErrorHandler?.Invoke(ex.Message); _res = ReasonToFinishPlaying.VideoSourceError; PlayingFinished?.Invoke(this, new PlayingFinishedEventArgs(_res)); AudioFinished?.Invoke(this, new PlayingFinishedEventArgs(_res)); } finally { try { Program.FfmpegMutex.ReleaseMutex(); } catch { } } _starting = false; }
public void Start() { Debug.WriteLine("START"); if (IsRunning) { return; } IsRunning = true; try { if (_failedLoad || string.IsNullOrEmpty(VlcHelper.VLCLocation)) { throw new ApplicationException("VLC not found. Set location in settings."); } _quit = false; _commands.Clear(); Task.Run(async() => { while (!_quit) { string cmd; if (_commands.TryDequeue(out cmd)) { switch (cmd) { case "init": try { Init(); } catch (ApplicationException ex) { Logger.LogException(ex, "VLC"); _res = ReasonToFinishPlaying.VideoSourceError; _quit = true; } break; case "stop": if (_mediaPlayer != null && _mediaPlayer.IsPlaying) { _mediaPlayer.Stop(); } else { _quit = true; } break; } } await Task.Delay(500); } Cleanup(); }); _commands.Enqueue("init"); _lastFrame = DateTime.UtcNow; _connecting = true; } catch (Exception ex) { Logger.LogException(ex, "VLCStream"); ErrorHandler?.Invoke("Invalid Source (" + Source + ")"); _connecting = false; IsRunning = false; _quit = false; _res = ReasonToFinishPlaying.VideoSourceError; PlayingFinished?.Invoke(this, new PlayingFinishedEventArgs(_res)); AudioFinished?.Invoke(this, new PlayingFinishedEventArgs(_res)); } }
private void ReadFrames() { var pConvertedFrameBuffer = IntPtr.Zero; SwsContext *pConvertContext = null; var audioInited = false; var videoInited = false; byte[] buffer = null, tbuffer = null; var dstData = new byte_ptrArray4(); var dstLinesize = new int_array4(); BufferedWaveProvider waveProvider = null; SampleChannel sampleChannel = null; var packet = new AVPacket(); do { ffmpeg.av_init_packet(&packet); if (_audioCodecContext != null && buffer == null) { buffer = new byte[_audioCodecContext->sample_rate * 2]; tbuffer = new byte[_audioCodecContext->sample_rate * 2]; } if (Log("AV_READ_FRAME", ffmpeg.av_read_frame(_formatContext, &packet))) { break; } if ((packet.flags & ffmpeg.AV_PKT_FLAG_CORRUPT) == ffmpeg.AV_PKT_FLAG_CORRUPT) { break; } var nf = NewFrame; var da = DataAvailable; _lastPacket = DateTime.UtcNow; int ret; if (_audioStream != null && packet.stream_index == _audioStream->index && _audioCodecContext != null) { if (HasAudioStream != null) { HasAudioStream?.Invoke(this, EventArgs.Empty); HasAudioStream = null; } if (da != null) { var s = 0; fixed(byte **outPtrs = new byte *[32]) { fixed(byte *bPtr = &tbuffer[0]) { outPtrs[0] = bPtr; ffmpeg.avcodec_send_packet(_audioCodecContext, &packet); do { ret = ffmpeg.avcodec_receive_frame(_audioCodecContext, _audioFrame); if (ret == 0) { var dat = _audioFrame->data[0]; var numSamplesOut = ffmpeg.swr_convert(_swrContext, outPtrs, _audioCodecContext->sample_rate, &dat, _audioFrame->nb_samples); var l = numSamplesOut * 2 * _audioCodecContext->channels; Buffer.BlockCopy(tbuffer, 0, buffer, s, l); s += l; } if (_audioFrame->decode_error_flags > 0) { break; } } while (ret == 0); if (s > 0) { var ba = new byte[s]; Buffer.BlockCopy(buffer, 0, ba, 0, s); if (!audioInited) { audioInited = true; RecordingFormat = new WaveFormat(_audioCodecContext->sample_rate, 16, _audioCodecContext->channels); waveProvider = new BufferedWaveProvider(RecordingFormat) { DiscardOnBufferOverflow = true, BufferDuration = TimeSpan.FromMilliseconds(500) }; sampleChannel = new SampleChannel(waveProvider); sampleChannel.PreVolumeMeter += SampleChannelPreVolumeMeter; } waveProvider.AddSamples(ba, 0, s); var sampleBuffer = new float[s]; var read = sampleChannel.Read(sampleBuffer, 0, s); da(this, new DataAvailableEventArgs(ba, read)); if (Listening) { WaveOutProvider?.AddSamples(ba, 0, read); } } } } } } if (nf != null && _videoStream != null && packet.stream_index == _videoStream->index && _videoCodecContext != null) { ffmpeg.avcodec_send_packet(_videoCodecContext, &packet); do { ret = ffmpeg.avcodec_receive_frame(_videoCodecContext, _videoFrame); if (ret == 0 && EmitFrame) { if (!videoInited) { videoInited = true; var convertedFrameBufferSize = ffmpeg.av_image_get_buffer_size(AVPixelFormat.AV_PIX_FMT_BGR24, _videoCodecContext->width, _videoCodecContext->height, 1); pConvertedFrameBuffer = Marshal.AllocHGlobal(convertedFrameBufferSize); ffmpeg.av_image_fill_arrays(ref dstData, ref dstLinesize, (byte *)pConvertedFrameBuffer, AVPixelFormat.AV_PIX_FMT_BGR24, _videoCodecContext->width, _videoCodecContext->height, 1); pConvertContext = ffmpeg.sws_getContext(_videoCodecContext->width, _videoCodecContext->height, _videoCodecContext->pix_fmt, _videoCodecContext->width, _videoCodecContext->height, AVPixelFormat.AV_PIX_FMT_BGR24, ffmpeg.SWS_FAST_BILINEAR, null, null, null); } Log("SWS_SCALE", ffmpeg.sws_scale(pConvertContext, _videoFrame->data, _videoFrame->linesize, 0, _videoCodecContext->height, dstData, dstLinesize)); if (_videoFrame->decode_error_flags > 0) { break; } using ( var mat = new Bitmap(_videoCodecContext->width, _videoCodecContext->height, dstLinesize[0], PixelFormat.Format24bppRgb, pConvertedFrameBuffer)) { var nfe = new NewFrameEventArgs(mat); nf.Invoke(this, nfe); } _lastVideoFrame = DateTime.UtcNow; } } while (ret == 0); } if (nf != null && _videoStream != null) { if ((DateTime.UtcNow - _lastVideoFrame).TotalMilliseconds > _timeout) { _res = ReasonToFinishPlaying.DeviceLost; _abort = true; } } ffmpeg.av_packet_unref(&packet); } while (!_abort && !MainForm.ShuttingDown); NewFrame?.Invoke(this, new NewFrameEventArgs(null)); try { Program.MutexHelper.Wait(); if (pConvertedFrameBuffer != IntPtr.Zero) { Marshal.FreeHGlobal(pConvertedFrameBuffer); } if (_formatContext != null) { if (_formatContext->streams != null) { var j = (int)_formatContext->nb_streams; for (var i = j - 1; i >= 0; i--) { var stream = _formatContext->streams[i]; if (stream != null && stream->codec != null && stream->codec->codec != null) { stream->discard = AVDiscard.AVDISCARD_ALL; ffmpeg.avcodec_close(stream->codec); } } } fixed(AVFormatContext **f = &_formatContext) { ffmpeg.avformat_close_input(f); } _formatContext = null; } if (_videoFrame != null) { fixed(AVFrame **pinprt = &_videoFrame) { ffmpeg.av_frame_free(pinprt); _videoFrame = null; } } if (_audioFrame != null) { fixed(AVFrame **pinprt = &_audioFrame) { ffmpeg.av_frame_free(pinprt); _audioFrame = null; } } _videoStream = null; _audioStream = null; _audioCodecContext = null; _videoCodecContext = null; if (_swrContext != null) { fixed(SwrContext **s = &_swrContext) { ffmpeg.swr_free(s); } _swrContext = null; } if (pConvertContext != null) { ffmpeg.sws_freeContext(pConvertContext); } if (sampleChannel != null) { sampleChannel.PreVolumeMeter -= SampleChannelPreVolumeMeter; sampleChannel = null; } } catch (Exception ex) { Logger.LogException(ex, "Media Stream (close)"); } finally { try { Program.MutexHelper.Release(); } catch { } } PlayingFinished?.Invoke(this, new PlayingFinishedEventArgs(_res)); AudioFinished?.Invoke(this, new PlayingFinishedEventArgs(_res)); }
private void DoStart() { var vss = Source; if (!IsAudio) { vss = Tokenise(vss); } AVDictionary *options = null; if (_inputFormat == null) { var prefix = vss.ToLower().Substring(0, vss.IndexOf(":", StringComparison.Ordinal)); switch (prefix) { case "https": case "http": case "mmsh": case "mms": ffmpeg.av_dict_set_int(&options, "timeout", _timeout, 0); ffmpeg.av_dict_set_int(&options, "stimeout", _timeout * 1000, 0); if (_cookies != "") { ffmpeg.av_dict_set(&options, "cookies", _cookies, 0); } if (_headers != "") { ffmpeg.av_dict_set(&options, "headers", _headers, 0); } if (_userAgent != "") { ffmpeg.av_dict_set(&options, "user-agent", _userAgent, 0); } break; default: ffmpeg.av_dict_set_int(&options, "timeout", _timeout, 0); break; case "rtsp": case "rtmp": ffmpeg.av_dict_set_int(&options, "stimeout", _timeout * 1000, 0); if (_userAgent != "") { ffmpeg.av_dict_set(&options, "user-agent", _userAgent, 0); } break; } ffmpeg.av_dict_set(&options, "rtsp_transport", _modeRTSP, 0); } ffmpeg.av_dict_set_int(&options, "rtbufsize", 10000000, 0); var lo = _options.Split(Environment.NewLine.ToCharArray()); foreach (var nv in lo) { if (!string.IsNullOrEmpty(nv)) { var i = nv.IndexOf('='); if (i > -1) { var n = nv.Substring(0, i).Trim(); var v = nv.Substring(i + 1).Trim(); if (!string.IsNullOrEmpty(n) && !string.IsNullOrEmpty(v)) { int j; if (int.TryParse(v, out j)) { ffmpeg.av_dict_set_int(&options, n, j, 0); } else { ffmpeg.av_dict_set(&options, n, v, 0); } } } } } _abort = false; try { Program.MutexHelper.Wait(); var pFormatContext = ffmpeg.avformat_alloc_context(); _lastPacket = DateTime.UtcNow; _interruptCallback = InterruptCb; _interruptCallbackAddress = Marshal.GetFunctionPointerForDelegate(_interruptCallback); _aviocb = new AVIOInterruptCB_callback_func { Pointer = _interruptCallbackAddress }; pFormatContext->interrupt_callback.callback = _aviocb; pFormatContext->interrupt_callback.opaque = null; pFormatContext->max_analyze_duration = 0; Throw("OPEN_INPUT", ffmpeg.avformat_open_input(&pFormatContext, vss, _inputFormat, &options)); _formatContext = pFormatContext; SetupFormat(); } catch (Exception ex) { ErrorHandler?.Invoke(ex.Message); _res = ReasonToFinishPlaying.VideoSourceError; PlayingFinished?.Invoke(this, new PlayingFinishedEventArgs(_res)); AudioFinished?.Invoke(this, new PlayingFinishedEventArgs(_res)); } finally { try { Program.MutexHelper.Release(); } catch { } } _starting = false; }
// Worker thread private void WorkerThread() { int width = region.Width; int height = region.Height; int x = region.Location.X; int y = region.Location.Y; Size size = region.Size; // Create 10 frames (which we will keep overwriting and reusing) Context[] buffer = new Context[10]; for (int i = 0; i < buffer.Length; i++) { // Note: It's important to use 32-bpp ARGB to avoid problems with FFmpeg later //var bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb); var bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb); buffer[i] = new Context { original = bmp, hwndGraphics = Graphics.FromHwnd(windowHandle), imgGraphics = Graphics.FromImage(bmp), args = new NewFrameEventArgs(bmp) }; } // download start time and duration DateTime start; TimeSpan span; int counter = 0; int bufferPos = 0; Context captureContext = buffer[bufferPos]; Context displayContext = null; while (!stopEvent.WaitOne(0, false)) { // set download start time start = DateTime.Now; try { // Start capturing a new frame at the same // time we send the previous one to listeners #if !NET35 Task.WaitAll( #if NET40 Task.Factory.StartNew(() => #else Task.Run(() => #endif { #endif // wait for a while ? if (frameInterval > 0) { // get download duration span = DateTime.Now.Subtract(start); // miliseconds to sleep int msec = frameInterval - (int)span.TotalMilliseconds; // if we should sleep, then sleep as long as needed if ((msec > 0) && (stopEvent.WaitOne(msec, false))) return; } // capture the screen var wndHdc = captureContext.hwndGraphics.GetHdc(); var imgHdc = captureContext.imgGraphics.GetHdc(); captureContext.args.CaptureStarted = DateTime.Now; BitBlt(imgHdc, 0, 0, width, height, wndHdc, x, y, (int)CopyPixelOperation.SourceCopy); captureContext.args.FrameSize = size; captureContext.args.CaptureFinished = DateTime.Now; captureContext.hwndGraphics.ReleaseHdc(wndHdc); captureContext.imgGraphics.ReleaseHdc(imgHdc); // increment frames counter captureContext.args.FrameIndex = counter++; framesReceived++; #if !NET35 } ), #if NET40 Task.Factory.StartNew(() => #else Task.Run(() => #endif { #endif // provide new image to clients if (displayContext != null) { // reset whatever listeners had done with the frame displayContext.args.Frame = displayContext.original; NewFrame?.Invoke(this, displayContext.args); } #if !NET35 })); #endif // Update buffer position displayContext = buffer[bufferPos]; bufferPos = (bufferPos + 1) % buffer.Length; captureContext = buffer[bufferPos]; Debug.Assert(displayContext != captureContext); } catch (ThreadAbortException) { break; } catch (Exception exception) { #if !NET35 AggregateException ae = exception as AggregateException; if (ae != null && ae.InnerExceptions.Count == 1) exception = ae.InnerExceptions[0]; #endif // provide information to clients if (VideoSourceError == null) throw; VideoSourceError(this, new VideoSourceErrorEventArgs(exception)); // wait for a while before the next try Thread.Sleep(250); } // need to stop ? if (stopEvent.WaitOne(0, false)) break; } // release resources foreach (var c in buffer) { c.imgGraphics.Dispose(); c.args.Frame.Dispose(); } PlayingFinished?.Invoke(this, ReasonToFinishPlaying.StoppedByUser); }
// Worker thread private void WorkerThread() { _abort = new ManualResetEvent(false); // buffer to read stream var buffer = new byte[BufferSize]; // HTTP web request HttpWebRequest request = null; // web responce WebResponse response = null; // stream for JPEG downloading Stream stream = null; // random generator to add fake parameter for cache preventing var rand = new Random((int)DateTime.UtcNow.Ticks); // download start time and duration var err = 0; var connectionFactory = new ConnectionFactory(); while (!_abort.WaitOne(10) && !MainForm.ShuttingDown) { var total = 0; if (ShouldEmitFrame) { try { // set download start time var start = DateTime.UtcNow; var vss = Tokenise(_source.settings.videosourcestring); var url = vss + (vss.IndexOf('?') == -1 ? '?' : '&') + "fake=" + rand.Next(); response = connectionFactory.GetResponse(url, _cookies, _headers, _httpUserAgent, _login, _password, "GET", "", "", _useHttp10, out request); // get response stream if (response == null) { throw new Exception("Connection failed"); } stream = response.GetResponseStream(); stream.ReadTimeout = _requestTimeout; bool frameComplete = false; // loop while (!_abort.WaitOne(0)) { // check total read if (total > BufferSize - ReadSize) { total = 0; } // read next portion from stream int read; if ((read = stream.Read(buffer, total, ReadSize)) == 0) { frameComplete = true; break; } total += read; } // provide new image to clients if (frameComplete && NewFrame != null) { using (var ms = new MemoryStream(buffer, 0, total)) { using (var bitmap = (Bitmap)Image.FromStream(ms)) { NewFrame(this, new NewFrameEventArgs(bitmap)); } } } err = 0; } catch (ThreadAbortException) { break; } catch (Exception ex) { Logger.LogException(ex, "JPEG"); err++; if (err > 3) { _res = ReasonToFinishPlaying.DeviceLost; break; } _abort.WaitOne(250); } finally { request?.Abort(); stream?.Flush(); stream?.Close(); response?.Close(); } } } PlayingFinished?.Invoke(this, new PlayingFinishedEventArgs(_res)); _abort.Close(); }
// Worker thread private void WorkerThread() { // buffer to read stream var buffer = new byte[BufSize]; // JPEG magic number var jpegMagic = new byte[] { 0xFF, 0xD8, 0xFF }; var encoding = new ASCIIEncoding(); while (!_abort.WaitOne(20) && !MainForm.ShuttingDown) { // HTTP web request HttpWebRequest request = null; // web response WebResponse response = null; // stream for MJPEG downloading Stream stream = null; // boundary between images (string and binary versions) string boudaryStr = null; // length of boundary // flag signaling if boundary was checked or not var boundaryIsChecked = false; // read amounts and positions int todo = 0, total = 0, pos = 0, align = 1; var start = 0; ConnectionFactory connectionFactory = new ConnectionFactory(); // align // 1 = searching for image start // 2 = searching for image end try { // create request // get response var vss = Tokenise(); response = connectionFactory.GetResponse(vss, _cookies, _headers, _httpUserAgent, _login, _password, "GET", "", "", _useHttp10, out request); if (response == null) { throw new Exception("Stream could not connect"); } // check content type var contentType = response.ContentType; var contentTypeArray = contentType.Split('/'); // "application/octet-stream" int boundaryLen; byte[] boundary; if ((contentTypeArray[0] == "application") && (contentTypeArray[1] == "octet-stream")) { boundaryLen = 0; boundary = new byte[0]; } else if ((contentTypeArray[0] == "multipart") && contentType.Contains("mixed")) { // get boundary var boundaryIndex = contentType.IndexOf("boundary", 0, StringComparison.Ordinal); if (boundaryIndex != -1) { boundaryIndex = contentType.IndexOf("=", boundaryIndex + 8, StringComparison.Ordinal); } if (boundaryIndex == -1) { // try same scenario as with octet-stream, i.e. without boundaries boundaryLen = 0; boundary = new byte[0]; } else { boudaryStr = contentType.Substring(boundaryIndex + 1); // remove spaces and double quotes, which may be added by some IP cameras boudaryStr = boudaryStr.Trim(' ', '"'); boundary = encoding.GetBytes(boudaryStr); boundaryLen = boundary.Length; boundaryIsChecked = false; } } else { throw new Exception("Invalid content type."); } // get response stream try { stream = response.GetResponseStream(); } catch (NullReferenceException) { throw new Exception("Connection failed"); } stream.ReadTimeout = _requestTimeout; // loop while (!_abort.WaitOne(0) && !MainForm.ShuttingDown) { // check total read if (total > BufSize - ReadSize) { total = pos = todo = 0; } // read next portion from stream int read; if ((read = stream.Read(buffer, total, ReadSize)) == 0) { throw new ApplicationException(); } total += read; todo += read; // increment received bytes counter _bytesReceived += read; // do we need to check boundary ? if ((boundaryLen != 0) && !boundaryIsChecked) { // some IP cameras, like AirLink, claim that boundary is "myboundary", // when it is really "--myboundary". this needs to be corrected. pos = ByteArrayUtils.Find(buffer, boundary, 0, todo); // continue reading if boudary was not found if (pos == -1) { continue; } for (var i = pos - 1; i >= 0; i--) { var ch = buffer[i]; if ((ch == (byte)'\n') || (ch == (byte)'\r')) { break; } boudaryStr = (char)ch + boudaryStr; } boundary = encoding.GetBytes(boudaryStr); boundaryLen = boundary.Length; boundaryIsChecked = true; } // search for image start if ((align == 1) && (todo >= jpegMagic.Length)) { start = ByteArrayUtils.Find(buffer, jpegMagic, pos, todo); if (start != -1) { // found JPEG start pos = start + jpegMagic.Length; todo = total - pos; align = 2; } else { // delimiter not found todo = jpegMagic.Length - 1; pos = total - todo; } } var decode = !string.IsNullOrEmpty(_decodeKey); // search for image end ( boundaryLen can be 0, so need extra check ) while ((align == 2) && (todo != 0) && (todo >= boundaryLen)) { var stop = ByteArrayUtils.Find(buffer, boundaryLen != 0 ? boundary : jpegMagic, pos, todo); if (stop != -1) { // increment frames counter _framesReceived++; var nf = NewFrame; // image at stop if (nf != null) { if (decode) { var marker = Encoding.ASCII.GetBytes(_decodeKey); using ( var ms = new MemoryStream(buffer, start + jpegMagic.Length, jpegMagic.Length + marker.Length)) { var key = new byte[marker.Length]; ms.Read(key, 0, marker.Length); if (!ByteArrayUtils.UnsafeCompare(marker, key)) { throw new Exception( "Image Decode Failed - Check the decode key matches the encode key on ispy server"); } } using ( var ms = new MemoryStream(buffer, start + marker.Length, stop - start - marker.Length)) { ms.Seek(0, SeekOrigin.Begin); ms.WriteByte(jpegMagic[0]); ms.WriteByte(jpegMagic[1]); ms.WriteByte(jpegMagic[2]); ms.Seek(0, SeekOrigin.Begin); using (var bmp = (Bitmap)Image.FromStream(ms)) { var da = new NewFrameEventArgs(bmp); nf.Invoke(this, da); } } } else { using (var ms = new MemoryStream(buffer, start, stop - start)) { using (var bmp = (Bitmap)Image.FromStream(ms)) { var da = new NewFrameEventArgs(bmp); nf.Invoke(this, da); } } } } // shift array pos = stop + boundaryLen; todo = total - pos; Array.Copy(buffer, pos, buffer, 0, todo); total = todo; pos = 0; align = 1; } else { // boundary not found if (boundaryLen != 0) { todo = boundaryLen - 1; pos = total - todo; } else { todo = 0; pos = total; } } } } } catch (ApplicationException) { // do nothing for Application Exception, which we raised on our own // wait for a while before the next try Thread.Sleep(250); } catch (ThreadAbortException) { break; } catch (Exception ex) { // provide information to clients Logger.LogException(ex, "MJPEG"); _res = ReasonToFinishPlaying.DeviceLost; break; // wait for a while before the next try //Thread.Sleep(250); } finally { // abort request request?.Abort(); stream?.Flush(); stream?.Close(); response?.Close(); } } PlayingFinished?.Invoke(this, new PlayingFinishedEventArgs(_res)); }
private void WorkerThread() { bool file = false; if (string.IsNullOrEmpty(Source)) { Logger.LogError("Source not found", "VLC"); _res = ReasonToFinishPlaying.VideoSourceError; PlayingFinished?.Invoke(this, new PlayingFinishedEventArgs(_res)); AudioFinished?.Invoke(this, new PlayingFinishedEventArgs(_res)); return; } try { if (File.Exists(Source)) { file = true; } } catch { // ignored } if (_mFactory == null) { var args = new List <string> { "-I", "dumy", "--ignore-config", "--no-osd", "--disable-screensaver", "--plugin-path=./plugins" }; if (file) { args.Add("--file-caching=3000"); } try { var l2 = args.ToList(); l2.AddRange(_arguments); l2 = l2.Distinct().ToList(); _mFactory = new MediaPlayerFactory(l2.ToArray()); } catch (Exception ex) { Logger.LogException(ex, "VLC Stream"); Logger.LogMessage("VLC arguments are: " + string.Join(",", args.ToArray()), "VLC Stream"); Logger.LogMessage("Using default VLC configuration.", "VLC Stream"); return; } GC.KeepAlive(_mFactory); } var vss = Source; if (!_modeAudio) { vss = Tokenise(vss); } _mMedia = file ? _mFactory.CreateMedia <IMediaFromFile>(vss) : _mFactory.CreateMedia <IMedia>(vss); _mMedia.Events.DurationChanged += EventsDurationChanged; _mMedia.Events.StateChanged += EventsStateChanged; if (_mPlayer != null) { try { _mPlayer?.Dispose(); } catch { // ignored } _mPlayer = null; } _mPlayer = _mFactory.CreatePlayer <IVideoPlayer>(); _mPlayer.Events.TimeChanged += EventsTimeChanged; var fc = new Func <SoundFormat, SoundFormat>(SoundFormatCallback); _mPlayer.CustomAudioRenderer.SetFormatCallback(fc); var ac = new AudioCallbacks { SoundCallback = SoundCallback }; _mPlayer.CustomAudioRenderer.SetCallbacks(ac); _mPlayer.CustomAudioRenderer.SetExceptionHandler(Handler); if (!_modeAudio) { _mPlayer.CustomRenderer.SetCallback(FrameCallback); _mPlayer.CustomRenderer.SetExceptionHandler(Handler); } GC.KeepAlive(_mPlayer); _needsSetup = true; if (!_modeAudio) { _mPlayer.CustomRenderer.SetFormat(new BitmapFormat(_source.settings.vlcWidth, _source.settings.vlcHeight, ChromaType.RV32)); } _mPlayer.Open(_mMedia); _mMedia.Parse(true); _mPlayer.Delay = 0; Duration = Time = 0; LastFrame = DateTime.MinValue; //check if file source (isseekable in _mPlayer is not reliable) Seekable = false; try { var p = Path.GetFullPath(_mMedia.Input); Seekable = !string.IsNullOrEmpty(p); } catch (Exception) { Seekable = false; } _videoQueue = new ConcurrentQueue <Bitmap>(); _audioQueue = new ConcurrentQueue <byte[]>(); _mPlayer.Play(); _abort = new ManualResetEvent(false); EventManager(); if (Seekable) { PlayingFinished?.Invoke(this, new PlayingFinishedEventArgs(ReasonToFinishPlaying.StoppedByUser)); AudioFinished?.Invoke(this, new PlayingFinishedEventArgs(ReasonToFinishPlaying.StoppedByUser)); } else { PlayingFinished?.Invoke(this, new PlayingFinishedEventArgs(_res)); AudioFinished?.Invoke(this, new PlayingFinishedEventArgs(_res)); } DisposePlayer(); _abort.Close(); }
private void ReadFrames() { AVFrame * pConvertedFrame = null; sbyte * pConvertedFrameBuffer = null; SwsContext *pConvertContext = null; BufferedWaveProvider waveProvider = null; SampleChannel sampleChannel = null; bool audioInited = false; bool videoInited = false; var packet = new AVPacket(); do { ffmpeg.av_init_packet(&packet); AVFrame *frame = ffmpeg.av_frame_alloc(); ffmpeg.av_frame_unref(frame); if (ffmpeg.av_read_frame(_formatContext, &packet) < 0) { _stopReadingFrames = true; _res = ReasonToFinishPlaying.VideoSourceError; break; } if ((packet.flags & ffmpeg.AV_PKT_FLAG_CORRUPT) == ffmpeg.AV_PKT_FLAG_CORRUPT) { break; } AVPacket packetTemp = packet; var nf = NewFrame; var da = DataAvailable; _lastPacket = DateTime.UtcNow; if (_audioStream != null && packetTemp.stream_index == _audioStream->index) { if (HasAudioStream != null) { HasAudioStream?.Invoke(this, EventArgs.Empty); HasAudioStream = null; } if (da != null) { int s = 0; var buffer = new sbyte[_audioCodecContext->sample_rate * 2]; var tbuffer = new sbyte[_audioCodecContext->sample_rate * 2]; bool b = false; fixed(sbyte **outPtrs = new sbyte *[32]) { fixed(sbyte *bPtr = &tbuffer[0]) { outPtrs[0] = bPtr; do { int gotFrame = 0; int inUsed = ffmpeg.avcodec_decode_audio4(_audioCodecContext, frame, &gotFrame, &packetTemp); if (inUsed < 0 || gotFrame == 0) { b = true; break; } int numSamplesOut = ffmpeg.swr_convert(_swrContext, outPtrs, _audioCodecContext->sample_rate, &frame->data0, frame->nb_samples); var l = numSamplesOut * 2 * _audioCodecContext->channels; Buffer.BlockCopy(tbuffer, 0, buffer, s, l); s += l; packetTemp.data += inUsed; packetTemp.size -= inUsed; } while (packetTemp.size > 0); } } if (b) { break; } ffmpeg.av_free_packet(&packet); ffmpeg.av_frame_free(&frame); if (!audioInited) { audioInited = true; RecordingFormat = new WaveFormat(_audioCodecContext->sample_rate, 16, _audioCodecContext->channels); waveProvider = new BufferedWaveProvider(RecordingFormat) { DiscardOnBufferOverflow = true, BufferDuration = TimeSpan.FromMilliseconds(500) }; sampleChannel = new SampleChannel(waveProvider); sampleChannel.PreVolumeMeter += SampleChannelPreVolumeMeter; } byte[] ba = new byte[s]; Buffer.BlockCopy(buffer, 0, ba, 0, s); waveProvider.AddSamples(ba, 0, s); var sampleBuffer = new float[s]; int read = sampleChannel.Read(sampleBuffer, 0, s); da(this, new DataAvailableEventArgs(ba, read)); if (Listening) { WaveOutProvider?.AddSamples(ba, 0, read); } } } if (nf != null && _videoStream != null && packet.stream_index == _videoStream->index) { int frameFinished = 0; //decode video frame int ret = ffmpeg.avcodec_decode_video2(_codecContext, frame, &frameFinished, &packetTemp); if (ret < 0) { ffmpeg.av_free_packet(&packet); ffmpeg.av_frame_free(&frame); break; } if (frameFinished == 1) { if (!videoInited) { videoInited = true; pConvertedFrame = ffmpeg.av_frame_alloc(); var convertedFrameBufferSize = ffmpeg.avpicture_get_size(AVPixelFormat.AV_PIX_FMT_BGR24, _codecContext->width, _codecContext->height); pConvertedFrameBuffer = (sbyte *)ffmpeg.av_malloc((ulong)convertedFrameBufferSize); ffmpeg.avpicture_fill((AVPicture *)pConvertedFrame, pConvertedFrameBuffer, AVPixelFormat.AV_PIX_FMT_BGR24, _codecContext->width, _codecContext->height); pConvertContext = ffmpeg.sws_getContext(_codecContext->width, _codecContext->height, _codecContext->pix_fmt, _codecContext->width, _codecContext->height, AVPixelFormat.AV_PIX_FMT_BGR24, ffmpeg.SWS_FAST_BILINEAR, null, null, null); } var src = &frame->data0; var dst = &pConvertedFrame->data0; var srcStride = frame->linesize; var dstStride = pConvertedFrame->linesize; ffmpeg.sws_scale(pConvertContext, src, srcStride, 0, _codecContext->height, dst, dstStride); var convertedFrameAddress = pConvertedFrame->data0; if (convertedFrameAddress != null) { var imageBufferPtr = new IntPtr(convertedFrameAddress); var linesize = dstStride[0]; if (frame->decode_error_flags > 0) { ffmpeg.av_free_packet(&packet); ffmpeg.av_frame_free(&frame); break; } using ( var mat = new Bitmap(_codecContext->width, _codecContext->height, linesize, PixelFormat.Format24bppRgb, imageBufferPtr)) { var nfe = new NewFrameEventArgs((Bitmap)mat.Clone()); nf.Invoke(this, nfe); } _lastVideoFrame = DateTime.UtcNow; } } } if (_videoStream != null) { if ((DateTime.UtcNow - _lastVideoFrame).TotalMilliseconds > _timeout) { _res = ReasonToFinishPlaying.DeviceLost; _stopReadingFrames = true; } } ffmpeg.av_free_packet(&packet); ffmpeg.av_frame_free(&frame); } while (!_stopReadingFrames && !MainForm.ShuttingDown); try { Program.FfmpegMutex.WaitOne(); if (pConvertedFrame != null) { ffmpeg.av_free(pConvertedFrame); } if (pConvertedFrameBuffer != null) { ffmpeg.av_free(pConvertedFrameBuffer); } if (_formatContext != null) { if (_formatContext->streams != null) { int j = (int)_formatContext->nb_streams; for (var i = j - 1; i >= 0; i--) { AVStream *stream = _formatContext->streams[i]; if (stream != null && stream->codec != null && stream->codec->codec != null) { stream->discard = AVDiscard.AVDISCARD_ALL; ffmpeg.avcodec_close(stream->codec); } } } fixed(AVFormatContext **f = &_formatContext) { ffmpeg.avformat_close_input(f); } _formatContext = null; } _videoStream = null; _audioStream = null; _audioCodecContext = null; _codecContext = null; if (_swrContext != null) { fixed(SwrContext **s = &_swrContext) { ffmpeg.swr_free(s); } _swrContext = null; } if (pConvertContext != null) { ffmpeg.sws_freeContext(pConvertContext); } if (sampleChannel != null) { sampleChannel.PreVolumeMeter -= SampleChannelPreVolumeMeter; sampleChannel = null; } } catch (Exception ex) { Logger.LogException(ex, "Media Stream (close)"); } finally { try { Program.FfmpegMutex.ReleaseMutex(); } catch { } } PlayingFinished?.Invoke(this, new PlayingFinishedEventArgs(_res)); AudioFinished?.Invoke(this, new PlayingFinishedEventArgs(_res)); }
// Worker thread private void WorkerThread() { // buffer to read stream var buffer = new byte[BufSize]; var encoding = new ASCIIEncoding(); var res = ReasonToFinishPlaying.StoppedByUser; while (!_stopEvent.WaitOne(0, false) && !MainForm.ShuttingDown) { // reset reload event _reloadEvent.Reset(); // HTTP web request HttpWebRequest request = null; // web responce WebResponse response = null; // stream for MJPEG downloading Stream stream = null; // boundary betweeen images (string and binary versions) try { // create request request = (HttpWebRequest)WebRequest.Create(_source); // set user agent if (_userAgent != null) { request.UserAgent = _userAgent; } // set proxy if (_proxy != null) { request.Proxy = _proxy; } if (_usehttp10) { request.ProtocolVersion = HttpVersion.Version10; } // set timeout value for the request request.Timeout = request.ServicePoint.ConnectionLeaseTimeout = request.ServicePoint.MaxIdleTime = _requestTimeout; request.AllowAutoRedirect = true; // set login and password if ((_login != null) && (_password != null) && (_login != string.Empty)) { request.Credentials = new NetworkCredential(_login, _password); } // set connection group name if (_useSeparateConnectionGroup) { request.ConnectionGroupName = GetHashCode().ToString(); } // get response response = request.GetResponse(); // get response stream stream = response.GetResponseStream(); stream.ReadTimeout = _requestTimeout; byte[] boundary = encoding.GetBytes("--myboundary"); byte[] sep = encoding.GetBytes("\r\n\r\n"); // loop int startPacket = -1; int endPacket = -1; int ttl = 0; bool hasaudio = false; while ((!_stopEvent.WaitOne(0, false)) && (!_reloadEvent.WaitOne(0, false))) { int read; if ((read = stream.Read(buffer, ttl, ReadSize)) == 0) { throw new ApplicationException(); } ttl += read; if (startPacket == -1) { startPacket = ByteArrayUtils.Find(buffer, boundary, 0, ttl); } else { if (endPacket == -1) { endPacket = ByteArrayUtils.Find(buffer, boundary, startPacket + boundary.Length, ttl - (startPacket + boundary.Length)); } } var nf = NewFrame; if (startPacket > -1 && endPacket > startPacket) { int br = ByteArrayUtils.Find(buffer, sep, startPacket, 100); if (br != -1) { var arr = new byte[br]; System.Array.Copy(buffer, startPacket, arr, 0, br - startPacket); string s = Encoding.ASCII.GetString(arr); int k = s.IndexOf("Content-type: ", StringComparison.Ordinal); if (k != -1) { s = s.Substring(k + 14); s = s.Substring(0, s.IndexOf("\r\n", StringComparison.Ordinal)); s = s.Trim(); } switch (s) { case "image/jpeg": try { using (var ms = new MemoryStream(buffer, br + 4, endPacket - br - 8)) { using (var bmp = (Bitmap)Image.FromStream(ms)) { var dae = new NewFrameEventArgs(bmp); nf.Invoke(this, dae); } } } catch (Exception ex) { //sometimes corrupted packets come through... Logger.LogExceptionToFile(ex, "KinectNetwork"); } break; case "audio/raw": if (!hasaudio) { hasaudio = true; //fixed 16khz 1 channel format RecordingFormat = new WaveFormat(16000, 16, 1); _waveProvider = new BufferedWaveProvider(RecordingFormat) { DiscardOnBufferOverflow = true, BufferDuration = TimeSpan.FromMilliseconds(500) }; _sampleChannel = new SampleChannel(_waveProvider); _sampleChannel.PreVolumeMeter += SampleChannelPreVolumeMeter; if (HasAudioStream != null) { HasAudioStream(this, EventArgs.Empty); HasAudioStream = null; } } var da = DataAvailable; if (da != null) { int l = endPacket - br - 8; var data = new byte[l]; int d; using (var ms = new MemoryStream(buffer, br + 4, l)) { d = ms.Read(data, 0, l); } if (d > 0) { _waveProvider.AddSamples(data, 0, data.Length); if (Listening) { WaveOutProvider.AddSamples(data, 0, data.Length); } //forces processing of volume level without piping it out var sampleBuffer = new float[data.Length]; int r = _sampleChannel.Read(sampleBuffer, 0, data.Length); da(this, new DataAvailableEventArgs((byte[])data.Clone(), r)); } } break; case "alert/text": // code to handle alert notifications goes here if (AlertHandler != null) { int dl = endPacket - br - 8; var data2 = new byte[dl]; using (var ms = new MemoryStream(buffer, br + 4, dl)) { ms.Read(data2, 0, dl); } string alerttype = Encoding.ASCII.GetString(data2); AlertHandler(this, new AlertEventArgs(alerttype)); } break; } } ttl -= endPacket; System.Array.Copy(buffer, endPacket, buffer, 0, ttl); startPacket = -1; endPacket = -1; } } } catch (ApplicationException) { // do nothing for Application Exception, which we raised on our own // wait for a while before the next try Thread.Sleep(250); } catch (ThreadAbortException) { break; } catch (Exception ex) { // provide information to clients Logger.LogExceptionToFile(ex, "KinectNetwork"); res = ReasonToFinishPlaying.DeviceLost; break; // wait for a while before the next try //Thread.Sleep(250); } finally { request?.Abort(); stream?.Flush(); stream?.Close(); response?.Close(); } // need to stop ? if (_stopEvent.WaitOne(0, false)) { break; } } PlayingFinished?.Invoke(this, new PlayingFinishedEventArgs(res)); }
// Worker thread private void WorkerThread( ) { // buffer to read stream var buffer = new byte[BufferSize]; // HTTP web request HttpWebRequest request = null; // web responce WebResponse response = null; // stream for JPEG downloading Stream stream = null; // random generator to add fake parameter for cache preventing var rand = new Random((int)DateTime.UtcNow.Ticks); // download start time and duration var res = ReasonToFinishPlaying.StoppedByUser; int err = 0; while (!_stopEvent.WaitOne(0, false) && !MainForm.ShuttingDown) { int total = 0; try { // set download start time DateTime start = DateTime.UtcNow; var url = _source + ((_source.IndexOf('?') == -1) ? '?' : '&') + "fake=" + rand.Next(); response = ConnectionFactory.GetResponse(url, Cookies, Headers, HttpUserAgent, Login, Password, "GET", "", UseHttp10, out request); // get response stream try { stream = response.GetResponseStream(); } catch (NullReferenceException) { throw new Exception("Connection failed"); } stream.ReadTimeout = _requestTimeout; // loop while (!_stopEvent.WaitOne(0, false)) { // check total read if (total > BufferSize - ReadSize) { total = 0; } // read next portion from stream int read; if ((read = stream.Read(buffer, total, ReadSize)) == 0) { break; } total += read; // increment received bytes counter _bytesReceived += read; } if (!_stopEvent.WaitOne(0, false)) { // increment frames counter _framesReceived++; // provide new image to clients if (NewFrame != null) { using (var bitmap = (Bitmap)Image.FromStream(new MemoryStream(buffer, 0, total))) { // notify client NewFrame(this, new NewFrameEventArgs(bitmap)); // release the image } } } // wait for a while ? if (_frameInterval > 0) { // get download duration var span = DateTime.UtcNow.Subtract(start); // milliseconds to sleep int msec = _frameInterval - (int)span.TotalMilliseconds; if ((msec > 0) && (_stopEvent.WaitOne(msec, false))) { break; } } err = 0; } catch (ThreadAbortException) { break; } catch (Exception ex) { // provide information to clients Logger.LogExceptionToFile(ex, "JPEG"); err++; if (err > 3) { res = ReasonToFinishPlaying.DeviceLost; break; } //if ( VideoSourceError != null ) //{ // VideoSourceError( this, new VideoSourceErrorEventArgs( exception.Message ) ); //} // wait for a while before the next try Thread.Sleep(250); } finally { request?.Abort(); stream?.Flush(); stream?.Close(); response?.Close(); } // need to stop ? if (_stopEvent.WaitOne(0, false)) { break; } } PlayingFinished?.Invoke(this, new PlayingFinishedEventArgs(res)); }
// Worker thread private void WorkerThread() { _abort = new ManualResetEvent(false); double multiX = 0, multiY = 0; while (!_abort.WaitOne(0) && !MainForm.ShuttingDown) { try { DateTime start = DateTime.UtcNow; var nf = NewFrame; // provide new image to clients if (nf != null && EmitFrame) { Screen s = Screen.AllScreens[_screenindex]; if (_screenSize == Rectangle.Empty) { if (_area != Rectangle.Empty) { _screenSize = _area; } else { _screenSize = s.Bounds; //virtual clients can have odd dimensions if (_screenSize.Width % 2 != 0) { _screenSize.Width = _screenSize.Width - 1; } if (_screenSize.Height % 2 != 0) { _screenSize.Height = _screenSize.Height - 1; } } } using (var target = new Bitmap(_screenSize.Width, _screenSize.Height, PixelFormat.Format24bppRgb)) { using (Graphics g = Graphics.FromImage(target)) { try { g.CopyFromScreen(s.Bounds.X + _screenSize.X, s.Bounds.Y + _screenSize.Y, 0, 0, new Size(_screenSize.Width, _screenSize.Height)); } catch (Exception ex) { throw new Exception("Error grabbing screen (" + ex.Message + ") - disable screensaver."); //probably remote desktop or screensaver has kicked in } if (MousePointer) { //if (multiX < 0.01) //{ // uint dpiX = 0, dpiY = 0; // var p = new Point(s.Bounds.Left + 1, s.Bounds.Top + 1); // var mon = MonitorFromPoint(p, 2); // GetDpiForMonitor(mon, DpiType.Effective, out dpiX, out dpiY); // multiX = Convert.ToDouble(dpiX) /96d; // multiY = Convert.ToDouble(dpiY) /96d; //} multiX = 1; multiY = 1; var mx = Convert.ToInt32(Cursor.Position.X * multiX - s.Bounds.X - _screenSize.X); var my = Convert.ToInt32(Cursor.Position.Y * multiY - s.Bounds.Y - _screenSize.Y); var cursorBounds = new Rectangle( mx, my, Cursors.Default.Size.Width, Cursors.Default.Size.Height); Cursors.Default.Draw(g, cursorBounds); } } // notify client nf.Invoke(this, new NewFrameEventArgs(target)); _error = false; } } // wait for a while ? if (FrameInterval > 0) { // get download duration TimeSpan span = DateTime.UtcNow.Subtract(start); // milliseconds to sleep int msec = FrameInterval - (int)span.TotalMilliseconds; if (msec > 0) { _abort.WaitOne(msec); } } } catch (Exception ex) { if (!_error) { Logger.LogException(ex, "Desktop"); _error = true; } // provide information to clients _res = ReasonToFinishPlaying.DeviceLost; // wait for a while before the next try _abort.WaitOne(250); break; } } PlayingFinished?.Invoke(this, new PlayingFinishedEventArgs(_res)); _abort.Close(); }