/// <summary> /// Some IP cameras, like AirLink, claim that boundary is "myboundary", /// when it is really "--myboundary". This corrects the issue. /// </summary> /// <param name="streamParser"></param> public void FixMalformedBoundary(MJPEGStreamParser streamParser) { byte[] content = streamParser.Content; int boundaryIndex = streamParser.FindImageBoundary(); if (boundaryIndex != -1) { for (int i = boundaryIndex - 1; i >= 0; i--) { char ch = (char)content[i]; if (ch == '\n' || ch == '\r') { break; } Prepend(ch); } IsChecked = true; } }
private void WorkerThread() { while (!IsStopRequested) { MJPEGStreamParser parser; Boundary boundary; WebResponse response = null; // reset reload event _reloadEvent.Reset(); try { response = GetResponse(); boundary = Boundary.FromResponse(response); parser = new MJPEGStreamParser(boundary, JPEG_HEADER_BYTES); using (Stream stream = GetResponseStream(response)) { while (!IsStopRequested && !IsReloadRequested) { _bytesReceived += parser.Read(stream); if (boundary.HasValue && !boundary.IsChecked) { boundary.FixMalformedBoundary(parser); } if (boundary.IsValid) { parser.DetectFrame(); if (parser.HasFrame) { _framesReceived++; if (NewFrame != null && !IsStopRequested) { using (Bitmap frame = parser.GetFrame()) { NewFrame(this, new NewFrameEventArgs(frame)); } parser.RemoveFrame(); } } } } } } 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 if (VideoSourceError != null) { VideoSourceError(this, new VideoSourceErrorEventArgs(exception.Message, exception)); } // wait for a while before the next try Thread.Sleep(250); } finally { // close response if (response != null) { response.Close(); } } if (IsStopRequested) { break; } } if (PlayingFinished != null) { PlayingFinished(this, ReasonToFinishPlaying.StoppedByUser); } }