public bool Start() { // setup input if (inputMethod == InputMethod.NamedPipe) { ((NamedPipe)transcoderInputStream).WaitTillReady(); StreamLog.Info(context.Identifier, "VLCManagedEncoder: Copy stream of type {0} into transcoder input pipe", InputStream.ToString()); StreamCopy.AsyncStreamCopy(InputStream, transcoderInputStream, "transinput"); } // delay start of next unit till our output stream is ready StreamLog.Info(context.Identifier, "VLCManagedEncoder: Waiting till output named pipe is ready"); ((NamedPipe)DataOutputStream).WaitTillReady(); // TODO: wait for state machine // setup the data reading infoReference = new Reference <WebTranscodingInfo>(() => context.TranscodingInfo, x => { context.TranscodingInfo = x; }); if (context.MediaInfo.Duration > 0) { StreamLog.Trace(context.Identifier, "VLCManagedInfo: duration known; is {0}", context.MediaInfo.Duration); calculator = new TranscodingInfoCalculator(context.StartPosition, 25, POLL_DATA_TIME, context.MediaInfo.Duration); } else { StreamLog.Trace(context.Identifier, "VLCManagedInfo: duration unknown"); calculator = new TranscodingInfoCalculator(context.StartPosition, 25, POLL_DATA_TIME); } // and setup the timer inputTimer = new Timer() { AutoReset = true, Interval = POLL_DATA_TIME }; inputTimer.Elapsed += InfoTimerTick; inputTimer.Start(); return(true); }
private void InfoThread(object passedPosition) { var einfo = new Reference <WebTranscodingInfo>(() => context.TranscodingInfo, x => { context.TranscodingInfo = x; }); TranscodingInfoCalculator calculator; if (context.MediaInfo.Duration > 0) { Log.Trace("VLCManagedInfo: duration known; is {0}", context.MediaInfo.Duration); calculator = new TranscodingInfoCalculator((int)passedPosition, 25, POLL_DATA_TIME, context.MediaInfo.Duration); } else { Log.Trace("VLCManagedInfo: duration unknown"); calculator = new TranscodingInfoCalculator((int)passedPosition, 25, POLL_DATA_TIME); } while (true) { try { // let's ignore the time here, for reasons detailed in VLCWrapperParsingUnit.cs around line 115 float position = transcoder.GetPosition(); Log.Trace("VLCManagedInfo: calling NewPercentage with position {0}", position); calculator.NewPercentage(position); calculator.SetStats(einfo); } catch (ThreadAbortException) { break; } catch (Exception ex) { Log.Warn("Failed to get VLC data", ex); } Thread.Sleep(POLL_DATA_TIME); } }
private void ParseOutputStream(Stream stdoutStream, Reference <WebTranscodingInfo> data, int startPosition, bool logProgress) { StreamReader reader = new StreamReader(stdoutStream); TranscodingInfoCalculator calculator = new TranscodingInfoCalculator(position, 25, 500, info.Duration); //VLCWrapper prints twice a second bool aborted = false; string line; while ((line = reader.ReadLine()) != null) { try { Log.Trace("VLCWrapperParsing: read line {0}", line); // just for debugging of the wrapper tool if (line.StartsWith("A") || line == "S started" || line == "S null") { continue; } // propagate start event to Start() method if (line == "S playing") { vlcIsStarted = true; continue; } // events if (line == "S error") { vlcIsStarted = true; data.Value.Finished = true; data.Value.Failed = true; break; } if (line == "S finished") { data.Value.Failed = false; data.Value.Finished = true; continue; } // the actual progress parsing if (line.StartsWith("P")) { // the format is 'P [time in microseconds] [percentage of file]'. Sadly we can't use the way more detailed time in microseconds // because the VLC guys decided it would be a good idea to convert it to a 32-bit integer before returning it, as opposed to // returning libvlc_time_t or a int64_t. And since it's in microseconds it gets big very fast, so it's absolutely useless. double percentage = Double.Parse(line.Substring(line.IndexOf(",") + 2), CultureInfo.InvariantCulture); calculator.NewPercentage(percentage); calculator.SetStats(data); continue; } Log.Warn("VLCWrapperParsing: encountered unknown line {0}", line); } catch (ThreadAbortException) { aborted = true; break; } catch (Exception e) { Log.Error("Failure during parsing of VLC output", e); } } data.Value.Failed = aborted; data.Value.Finished = true; reader.Close(); return; }
private void ParseOutputStream(Stream stdoutStream, Reference <WebTranscodingInfo> data, long startPosition, bool logProgress) { StreamReader reader = new StreamReader(stdoutStream); TranscodingInfoCalculator calculator = new TranscodingInfoCalculator(position, 25, 500, info.Duration); //VLCWrapper prints twice a second string line; try { while ((line = reader.ReadLine()) != null) { try { Log.Trace("VLCWrapperParsing: read line {0}", line); // just for debugging of the wrapper tool if (line.StartsWith("A") || line.StartsWith("I") || line == "S started" || line == "S null") { continue; } // propagate start event to Start() method if (line == "S playing") { vlcIsStarted = true; continue; } // events if (line == "S error") { vlcIsStarted = true; data.Value.Finished = true; data.Value.Failed = true; break; } if (line == "S finished") { data.Value.Finished = true; continue; } // the actual progress parsing if (line.StartsWith("P")) { // Starting with VLCWrapper 0.2, the output format has changed. It is 'P [time in milliseconds]' now, which is quite easy for // us to handle. With VLC 2 it also returns the time as a 64-bit integer, so we don't have overflow anymore either, but that risk // is with milliseconds quite small anyhow: it requires 596 hours of video. long milliseconds = Int64.Parse(line.Substring(2)); calculator.NewTime((int)milliseconds); calculator.SaveStats(data); continue; } Log.Warn("VLCWrapperParsing: encountered unknown line {0}", line); } catch (ThreadAbortException) { data.Value.Finished = true; reader.Close(); return; } catch (Exception e) { Log.Error("Failure during parsing of VLC output", e); } } } catch (ThreadAbortException) { // The double try-catch is to make sure that the parsing doesn't stop when it can't process a single line, but that we don't // log too much noise when a ThreadAbortException occurs while in the ReadLine() method. Funnily enough, this exception is // rethrown when we leave the catch block, so duplicate some code from below... data.Value.Finished = true; reader.Close(); return; } data.Value.Finished = true; reader.Close(); }