示例#1
0
        public override Stream ProvideCustomActionFile(string action, string param)
        {
            if (action == "playlist")
            {
                WCFUtil.SetContentType("application/vnd.apple.mpegurl");
                string playlistPath = Path.Combine(TemporaryDirectory, "index.m3u8");
                if (!File.Exists(playlistPath))
                {
                    StreamLog.Warn(Identifier, "HTTPLiveStreamer: Client requested index.m3u8 that doesn't exist for identifier '{0}'", Identifier);
                    return(Stream.Null);
                }

                // FFMpeg outputs the local segment paths in the playlist, replace with url
                string playlist = ReplacePathsWithURLs(playlistPath);
                if (playlist == string.Empty)
                {
                    // The playlist file is empty until the first segment has finished being encoded,
                    // wait for next segment to begin and retry.
                    string segmentPath = Path.Combine(TemporaryDirectory, "000001.ts");
                    while (!File.Exists(segmentPath))
                    {
                        System.Threading.Thread.Sleep(100);
                    }
                    playlist = ReplacePathsWithURLs(playlistPath);
                }
                return(new MemoryStream(Encoding.UTF8.GetBytes(playlist)));
            }

            return(base.ProvideCustomActionFile(action, param));
        }
示例#2
0
        public WebBoolResult InitStream(WebMediaType type, int?provider, string itemId, int?offset, string clientDescription, string identifier, int?idleTimeout)
        {
            AuthorizeStreaming();
            if (type == WebMediaType.TV)
            {
                int channelId = Int32.Parse(itemId);
                lock (_timeshiftings)
                {
                    StreamLog.Info(identifier, "Starting timeshifting on channel {0} for client {1}", channelId, clientDescription);
                    var card = Connections.TAS.SwitchTVServerToChannelAndGetVirtualCard("mpextended-" + identifier, channelId);
                    if (card == null)
                    {
                        StreamLog.Error(identifier, "Failed to start timeshifting for stream");
                        return(false);
                    }
                    else
                    {
                        StreamLog.Debug(identifier, "Timeshifting started!");
                        _timeshiftings[identifier] = card;
                        itemId = card.TimeShiftFileName;
                    }
                }
            }

            StreamLog.Info(identifier, "Called InitStream with type={0}; provider={1}; itemId={2}; offset={3}; clientDescription={4}; idleTimeout={5}",
                           type, provider, itemId, offset, clientDescription, idleTimeout);
            return(_stream.InitStream(identifier, clientDescription, new MediaSource(type, provider, itemId, offset), idleTimeout.HasValue ? idleTimeout.Value : 5 * 60));
        }
示例#3
0
 public WebStringResult StartStreamWithStreamSelection(string identifier, string profileName, long startPosition, int audioId, int subtitleId)
 {
     StreamLog.Debug(identifier, "Called StartStreamWithStreamSelection with profile={0}; start={1}; audioId={2}; subtitleId={3}",
                     profileName, startPosition, audioId, subtitleId);
     _stream.EndStream(identifier); // first end previous stream, if any available
     return(_stream.StartStream(identifier, Configuration.StreamingProfiles.GetTranscoderProfileByName(profileName), startPosition * 1000, audioId, subtitleId));
 }
示例#4
0
        public WebStreamLogs GetStreamLogs(string identifier)
        {
            var slh = StreamLog.GetStreamLogDetails(identifier);

            return(new WebStreamLogs()
            {
                LastError = slh.LastError,
                FullLogs = slh.FullLog.ToString()
            });
        }
        public void StreamLogStoresAndRetrievesLogEntries()
        {
            var serializer = CreateSerializer();

            using (var memoryStream = new MemoryStream())
            {
                var log = new StreamLog <TestOperation>(memoryStream, serializer);
                TestEmptyLog(log);
                TestLog(log);
                TestLog(log); // test again, as it will overwrite the existing entries
            }
        }
        public void StreamLogStoresAndRetrievesLogEntries()
        {
            var serializer = CreateSerializer();

            using (var memoryStream = new MemoryStream())
            {
                var log = new StreamLog<TestOperation>(memoryStream, serializer);
                TestEmptyLog(log);
                TestLog(log);
                TestLog(log); // test again, as it will overwrite the existing entries
                
            }
        }
示例#7
0
 private void CloseStream(Stream stream, string logName)
 {
     try
     {
         if (stream != null)
         {
             stream.Close();
         }
     }
     catch (Exception e)
     {
         StreamLog.Info(context.Identifier, "Encoding: Failed to close {0} stream: {1}", logName, e.Message);
     }
 }
示例#8
0
 public bool Setup()
 {
     try
     {
         using (var context = NetworkContextFactory.CreateImpersonationContext())
         {
             DataOutputStream = new FileStream(context.RewritePath(source), FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
         }
     }
     catch (Exception e)
     {
         StreamLog.Error(identifier, "Failed to setup ImpersonationInputUnit", e);
         return(false);
     }
     return(true);
 }
示例#9
0
        public Stream DoStream(WebMediaType type, int?provider, string itemId, string clientDescription, string profileName, long startPosition, int?idleTimeout)
        {
            if (!IsClientAuthorized())
            {
                Log.Warn("Host {0} isn't authorized to call DoStream", WCFUtil.GetClientIPAddress());
                WCFUtil.SetResponseCode(HttpStatusCode.Unauthorized);
                return(Stream.Null);
            }

            // calculate timeout, which is by default 5 minutes for direct streaming and 5 seconds for transcoded streams
            var profile = Configuration.StreamingProfiles.Transcoders.FirstOrDefault(x => x.Name == profileName);

            if (profile == null)
            {
                Log.Warn("Called DoStream with non-existing profile {0}", profileName);
                return(Stream.Null);
            }
            int timeout = profile.Transcoder == typeof(Transcoders.Direct).FullName ? 5 * 60 : 5;

            if (idleTimeout.HasValue)
            {
                timeout = idleTimeout.Value;
            }

            // This only works with profiles that actually return something in the RetrieveStream method (i.e. no RTSP or CustomTranscoderData)
            string identifier = String.Format("dostream-{0}", new Random().Next(10000, 99999));

            StreamLog.Debug(identifier, "DoStream: using timeout={0}", timeout);

            if (!InitStream(type, provider, itemId, null, clientDescription, identifier, timeout))
            {
                StreamLog.Info(identifier, "DoStream: InitStream() failed");
                FinishStream(identifier);
                return(Stream.Null);
            }

            if (String.IsNullOrEmpty(StartStream(identifier, profileName, startPosition)))
            {
                StreamLog.Info(identifier, "DoStream: StartStream failed");
                FinishStream(identifier);
                return(Stream.Null);
            }

            StreamLog.Info(identifier, "DoStream: succeeded, returning stream");
            return(RetrieveStream(identifier));
        }
示例#10
0
        public WebBoolResult FinishStream(string identifier)
        {
            StreamLog.Debug(identifier, "Called FinishStream");
            _stream.KillStream(identifier);

            lock (_timeshiftings)
            {
                if (_timeshiftings.ContainsKey(identifier) && _timeshiftings[identifier] != null)
                {
                    StreamLog.Info(identifier, "Cancelling timeshifting");
                    Connections.TAS.CancelCurrentTimeShifting("mpextended-" + identifier);
                    _timeshiftings.Remove(identifier);
                }
            }

            return(true);
        }
        private void StreamLogCanOpenAnExistingStream()
        {
            var serializer = CreateSerializer();

            using (var memoryStream = new MemoryStream())
            {
                var log1 = new StreamLog <TestOperation>(memoryStream, serializer);
                TestLog(log1);

                var log2 = new StreamLog <TestOperation>(memoryStream, serializer);

                var entries = log2.GetCursor(1).ToArray();
                entries.Should().HaveCount(3);
                entries[0].Id.Should().Be(new LogEntryId(1, 1));
                entries[1].Id.Should().Be(new LogEntryId(1, 2));
                entries[2].Id.Should().Be(new LogEntryId(1, 3));
            }
        }
示例#12
0
 private void InfoTimerTick(object source, ElapsedEventArgs args)
 {
     while (true)
     {
         try
         {
             // let's ignore the time here, for reasons detailed in VLCWrapperParsingUnit.cs around line 115
             float position = transcoder.GetPosition();
             StreamLog.Trace(context.Identifier, "VLCManagedInfo: calling NewPercentage with position {0}", position);
             calculator.NewPercentage(position);
             calculator.SaveStats(infoReference);
         }
         catch (Exception ex)
         {
             StreamLog.Warn(context.Identifier, "Failed to get VLC data", ex);
         }
     }
 }
示例#13
0
        public bool Stop()
        {
            StreamLog.Debug(context.Identifier, "VLCManagedEncoder: Stopping transcoding");
            try
            {
                DataOutputStream.Close();
            }
            catch (Exception e)
            {
                StreamLog.Info(context.Identifier, "VLCManagedEncoder: Failed to close data output stream", e);
            }

            inputTimer.Enabled = false;
            StreamLog.Trace(context.Identifier, "VLCManagedEncoder: Trying to stop vlc");
            transcoder.StopTranscoding();
            transcoder = null;
            StreamLog.Debug(context.Identifier, "VLCManagedEncoder: Stopped transcoding");

            return(true);
        }
示例#14
0
        public bool Setup()
        {
            // setup output named pipe
            DataOutputStream = new NamedPipe();
            string output = ((NamedPipe)DataOutputStream).Url;

            StreamLog.Info(context.Identifier, "VLCManagedEncoder: starting output named pipe {0}", output);
            ((NamedPipe)DataOutputStream).Start(false);

            // prepare sout, needs some trickery for vlc
            string realSout = sout.Replace("#OUT#", @"\" + output);

            // debug
            StreamLog.Debug(context.Identifier, "VLCManagedEncoder: sout {0}", realSout);
            StreamLog.Debug(context.Identifier, "VLCManagedEncoder: arguments {0}", String.Join("|", arguments));

            // start vlc
            transcoder = new VLCTranscoder();
            transcoder.SetArguments(arguments);
            transcoder.SetMediaName(Guid.NewGuid().ToString());
            transcoder.SetSout(realSout);

            // setup input
            if (inputMethod == InputMethod.NamedPipe)
            {
                transcoderInputStream = new NamedPipe();
                StreamLog.Info(context.Identifier, "VLCManagedEncoder: starting input named pipe {0}", transcoderInputStream);
                ((NamedPipe)transcoderInputStream).Start(false);
                inputPath = "stream://" + transcoderInputStream.Url; // use special syntax for VLC to pick up named pipe
            }
            StreamLog.Debug(context.Identifier, "VLCManagedEncoder: input {0}", inputPath);
            transcoder.SetInput(inputPath);

            // start transcoding
            transcoder.StartTranscoding();
            // doesn't work
            //transcoder.Seek(startPos * 1.0 / context.MediaInfo.Duration * 1000);

            context.TranscodingInfo.Supported = true;
            return(true);
        }
示例#15
0
        public void     DeleteStream(int i)
        {
            StreamLog stream = this.streams[i];

            stream.Uninit();
            stream.FilterAltered -= this.console.SaveModules;
            stream.OptionAltered -= this.console.SaveModules;
            this.streams.RemoveAt(i);

            if (this.StreamDeleted != null)
            {
                this.StreamDeleted(stream);
            }

            foreach (Vars var in this.perWindowVars.Each())
            {
                var.workingStream = Mathf.Clamp(var.workingStream, 0, this.streams.Count - 1);
            }

            this.console.SaveModules();
        }
示例#16
0
        public bool Stop()
        {
            // close streams
            CloseStream(InputStream, "input");
            CloseStream(transcoderInputStream, "transcoder input");
            CloseStream(DataOutputStream, "transcoder output");

            try
            {
                if (transcoderApplication != null && !transcoderApplication.HasExited)
                {
                    StreamLog.Debug(context.Identifier, "Encoding: Killing transcoder");
                    transcoderApplication.Stop();
                }
            }
            catch (Exception e)
            {
                StreamLog.Error(context.Identifier, "Encoding: Failed to kill transcoder", e);
            }

            return(true);
        }
示例#17
0
        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);
        }
示例#18
0
 public bool Setup()
 {
     try
     {
         if (source.IndexOf(".ts.tsbuffer") != -1)
         {
             StreamLog.Info(identifier, "Using TsBuffer to read input");
             DataOutputStream = new TsBuffer(this.source);
         }
         else
         {
             StreamLog.Info(identifier, "Using FileStream to read input");
             DataOutputStream = new FileStream(source, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
         }
     }
     catch (Exception e)
     {
         StreamLog.Error(identifier, "Failed to setup InputProcessingUnit", e);
         return(false);
     }
     return(true);
 }
 public bool Setup()
 {
     data.Value.Failed = false;
     vlcIsStarted      = false;
     processThread     = new Thread(delegate()
     {
         try
         {
             ParseOutputStream(InputStream, data, position, false);
         }
         catch (ThreadAbortException)
         {
         }
         catch (Exception ex)
         {
             StreamLog.Error(identifier, "VLCLogParsing failed with exception", ex);
         }
     });
     processThread.Name = "VLCLogParsing";
     processThread.Start();
     return(true);
 }
示例#20
0
        public bool Start()
        {
            // wait for the input pipe to be ready
            if (transcoderInputStream is NamedPipe)
            {
                ((NamedPipe)transcoderInputStream).WaitTillReady();
            }

            // copy the inputStream to the transcoderInputStream
            if (doInputCopy)
            {
                StreamLog.Info(context.Identifier, "Encoding: Copy stream of type {0} into transcoder input stream of type {1}", InputStream.ToString(), transcoderInputStream.ToString());
                StreamCopy.AsyncStreamCopy(InputStream, transcoderInputStream, "transinput");
            }

            // delay start of next unit till our output stream is ready
            if (DataOutputStream is NamedPipe && (outputMethod == TransportMethod.NamedPipe || outputMethod == TransportMethod.StandardOut))
            {
                StreamLog.Trace(context.Identifier, "Transcoder running: {0}", !transcoderApplication.HasExited);
                StreamLog.Info(context.Identifier, "Encoding: Waiting till output named pipe is ready");

                var pipe        = (NamedPipe)DataOutputStream;
                var checkFailed = context != null && context.TranscodingInfo != null;
                while (!pipe.IsReady && !(checkFailed && context.TranscodingInfo.Failed))
                {
                    System.Threading.Thread.Sleep(100);
                }

                if (checkFailed && context.TranscodingInfo.Failed)
                {
                    StreamLog.Warn(context.Identifier, "Encoding: Aborting wait because transcoder application failed and will never setup output named pipe.");
                    return(false);
                }
            }

            return(true);
        }
 public bool Setup()
 {
     // this might be better placed in the Start() method, but EncoderUnit.Start() depends on this
     data.Value.Supported = true;
     data.Value.Failed    = false;
     processThread        = new Thread(delegate()
     {
         try
         {
             ParseOutputStream(InputStream, data, startPosition, LogMessages, LogProgress, identifier);
         }
         catch (ThreadAbortException)
         {
             // ThreadAbortException is already handled in ParseOutputStream, but rethrown when the method is left. Don't be noisy.
         }
         catch (Exception ex)
         {
             StreamLog.Error(identifier, "FFMpegLogParsing brutally came to an end", ex);
         }
     });
     processThread.Name = "FFMpegLog";
     processThread.Start();
     return(true);
 }
示例#22
0
        private bool SpawnTranscoder(bool needsStdin, bool needsStdout)
        {
            ProcessStartInfo start = new ProcessStartInfo(transcoderPath, arguments);

            start.UseShellExecute        = false;
            start.RedirectStandardInput  = needsStdin;
            start.RedirectStandardOutput = needsStdout || (!DebugOutput && logStream == LogStream.StandardOut && IsLogStreamConnected);
            start.RedirectStandardError  = !DebugOutput && logStream == LogStream.StandardError && IsLogStreamConnected;
            start.WindowStyle            = DebugOutput ? ProcessWindowStyle.Normal : ProcessWindowStyle.Hidden;
            start.CreateNoWindow         = !DebugOutput;

            StreamLog.Info(context.Identifier, "Encoder: Transcoder configuration dump");
            StreamLog.Info(context.Identifier, "Encoder:   hasStdin {0}, hasStdout {1}, hasStderr {2}", start.RedirectStandardInput, start.RedirectStandardOutput, start.RedirectStandardError);
            StreamLog.Info(context.Identifier, "Encoder:   path {0}", transcoderPath);
            StreamLog.Info(context.Identifier, "Encoder:   arguments {0}", arguments);

            try
            {
                transcoderApplication           = new TranscoderProcess();
                transcoderApplication.StartInfo = start;
                if (context.Source.NeedsImpersonation)
                {
                    transcoderApplication.StartAsUser(Configuration.Services.NetworkImpersonation.Domain, Configuration.Services.NetworkImpersonation.Username, Configuration.Services.NetworkImpersonation.GetPassword());
                }
                else
                {
                    transcoderApplication.Start();
                }
            }
            catch (Win32Exception e)
            {
                StreamLog.Error(context.Identifier, "Encoding: Failed to start transcoder", e);
                return(false);
            }
            return(true);
        }
示例#23
0
        public void CouldAddNextChunkBeforeCompleted()
        {
            var path          = TestUtils.GetPath();
            var processConfig = new ProcessConfig(path);

            StartupConfig.StreamLogBufferPoolFlags = LMDBEnvironmentFlags.NoSync;
            StartupConfig.StreamBlockIndexFlags    = LMDBEnvironmentFlags.NoSync;
            var slm = new StreamLogManager(processConfig, "CouldAddNextChunk", null, 512, true, true);

            var bufferPool = slm.BufferPool;

            var blockIndex = slm.BlockIndex;

            var streamId = (StreamLogId)42;

            short valueSize = 8;

            var state = slm.StateStorage.GetState(streamId);

            state.CheckInit(streamId, 8, SerializationFormat.Binary);

            var sl = new StreamLog(slm, state, textId: "test_stream");

            var count = 100;

            SharedMemory currentBuffer = null;

            using (Benchmark.Run("AddNext (KOPS)", count * 1000))
            {
                var version = 1UL;
                var block   = blockIndex.RentNextWritableBlock(sl, minimumLength: 1, version, default);
                // var slc = new StreamBlock(buffer.RetainChunkMemory(false), streamId, valueSize, 1);

                var firstBufferRef = block.SharedMemory.BufferRef;

                for (int i = 0; i < count; i++)
                {
                    version = (ulong)i + 1;

                    if (!block.Claim(version, 8).IsValid)
                    {
                        Assert.Fail("!slc.Claim(version, 8).IsValid");
                    }
                    block.Commit();

                    var bufferRef = block.SharedMemory.BufferRef;

                    blockIndex.PrepareNextWritableStreamBlock(sl, length: 1);
                    blockIndex.PrepareNextWritableStreamBlock(sl, length: 1);
                    block.Complete();

                    block = blockIndex.RentNextWritableBlock(sl, minimumLength: 1, version + 1, default);
                    var bufferRef1 = block.SharedMemory.BufferRef;
                    // As if someone has created the next buffer before the second call, forget the first call

                    block.DisposeFree();
                    block = blockIndex.RentNextWritableBlock(sl, minimumLength: 1, version + 1, default);
                    var bufferRef2 = block.SharedMemory.BufferRef;

                    if (block.SharedMemory.ReferenceCount != 2)
                    {
                        Assert.Fail($"buffer.RefCount {block.SharedMemory.ReferenceCount} != 1");
                    }

                    if (bufferRef1 != bufferRef2)
                    {
                        Assert.Fail($"bufferRef1 {bufferRef1} != bufferRef2 {bufferRef2}");
                    }

                    block.Complete();

                    var nextVersion = block.NextVersion;
                    block.DisposeFree();

                    blockIndex.PrepareNextWritableStreamBlock(sl, length: 1);
                    blockIndex.PrepareNextWritableStreamBlock(sl, length: 1);

                    // block = new StreamBlock(block.SharedMemory.RetainBlockMemory(false), streamId, valueSize, nextVersion);
                    block = blockIndex.RentNextWritableBlock(sl, minimumLength: 1, nextVersion, default);
                }

                if (!block.Claim(version + 1, 8).IsValid)
                {
                    Assert.Fail("!slc.Claim(version, 8).IsValid");
                }
                block.Commit();
                block.Complete();

                block = blockIndex.RentNextWritableBlock(sl, minimumLength: 1, block.NextVersion, default);

                Assert.AreEqual(2, block.SharedMemory.ReferenceCount);

                block.DisposeFree();
                block = blockIndex.RentNextWritableBlock(sl, minimumLength: 1, version + 2, default);

                Assert.IsFalse(block.IsCompleted);

                // TODO test replace

                //// replace existing
                //var toReplaceVersion = slc.FirstVersion;
                //var toReplaceRef = buffer.BufferRef;

                //slc.Complete();
                //// SharedMemory.Free(buffer);
                //// slc.DisposeFree();

                //buffer = chunkIndex.GetOrCreateNextWritableChunkBuffer(sl, toReplaceVersion, toReplaceRef, 1);
                //slc = new StreamLogChunk(buffer.RetainChunkMemory(false), streamId, valueSize, version + 2);
                //Assert.AreNotEqual(toReplaceRef, buffer.BufferRef);

                // SharedMemory.Free(buffer);
                block.DisposeFree();
            }

            //bufferPool.PrintBuffers();

            //bufferPool.PrintBuffersAfterPoolDispose = true;

            Benchmark.Dump();
            Console.WriteLine("Finished");
            sl.Dispose();
            slm.Dispose();
        }
示例#24
0
        public bool Setup()
        {
            // sets up streams
            string input       = "";
            string output      = "";
            bool   needsStdin  = false;
            bool   needsStdout = false;

            // input
            if (inputMethod == TransportMethod.NamedPipe)
            {
                transcoderInputStream = new NamedPipe();
                input = ((NamedPipe)transcoderInputStream).Url;
                StreamLog.Info(context.Identifier, "Encoding: starting input named pipe {0}", input);
                ((NamedPipe)transcoderInputStream).Start(false);
                doInputCopy = true;
            }
            else if (inputMethod == TransportMethod.StandardIn)
            {
                needsStdin  = true;
                doInputCopy = true;
            }

            // output stream
            if (outputMethod == TransportMethod.NamedPipe)
            {
                DataOutputStream = new NamedPipe();
                output           = ((NamedPipe)DataOutputStream).Url;
                StreamLog.Info(context.Identifier, "Encoding: starting output named pipe {0}", output);
                ((NamedPipe)DataOutputStream).Start(false);
            }
            else if (outputMethod == TransportMethod.StandardOut)
            {
                needsStdout = true;
            }

            // arguments substitution
            arguments = arguments.Replace("#IN#", input).Replace("#OUT#", output);

            // start transcoder
            if (!SpawnTranscoder(needsStdin, needsStdout))
            {
                return(false);
            }

            // finish stream setup
            if (inputMethod == TransportMethod.StandardIn)
            {
                transcoderInputStream = transcoderApplication.StandardInput.BaseStream;
            }
            if (outputMethod == TransportMethod.StandardOut)
            {
                DataOutputStream = transcoderApplication.StandardOutput.BaseStream;
            }

            // setup log stream
            if (!DebugOutput && logStream == LogStream.StandardOut && IsLogStreamConnected && outputMethod != TransportMethod.StandardOut)
            {
                LogOutputStream = transcoderApplication.StandardOutput.BaseStream;
            }
            else if (!DebugOutput && logStream == LogStream.StandardError && IsLogStreamConnected)
            {
                LogOutputStream = transcoderApplication.StandardError.BaseStream;
            }
            else
            {
                LogOutputStream = new MemoryStream(4096);
            }

            return(true);
        }
        void StreamLogCanOpenAnExistingStream()
        {
            var serializer = CreateSerializer();
            using (var memoryStream = new MemoryStream())
            {
                var log1 = new StreamLog<TestOperation>(memoryStream, serializer);
                TestLog(log1);

                var log2 = new StreamLog<TestOperation>(memoryStream, serializer);

                var entries = log2.GetCursor(1).ToArray();
                entries.Should().HaveCount(3);
                entries[0].Id.Should().Be(new LogEntryId(1, 1));
                entries[1].Id.Should().Be(new LogEntryId(1, 2));
                entries[2].Id.Should().Be(new LogEntryId(1, 3));
            }
        }
        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
                    {
                        StreamLog.Trace(identifier, "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;
                        }

                        StreamLog.Warn(identifier, "VLCWrapperParsing: encountered unknown line {0}", line);
                    }
                    catch (ThreadAbortException)
                    {
                        data.Value.Finished = true;
                        reader.Close();
                        return;
                    }
                    catch (Exception e)
                    {
                        StreamLog.Error(identifier, "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();
        }
示例#27
0
        protected virtual VLCParameters GenerateVLCParameters(string options, string tsOptions, bool disableSeeking, string encoderOptions, string tsEncoderOptions, string muxerOptions)
        {
            List <string> arguments = options.Split(' ').Where(x => x.Length > 0).ToList();

            // input
            string inURL = "";

            if (Context.NeedsInputReaderUnit)
            {
                inURL = @"stream://\#IN#";
            }
            else
            {
                inURL = Context.Source.GetPath();
            }

            // add tv options if specified
            if ((Context.IsTv || Context.MediaInfo.Container == "MPEG-TS") && tsOptions.Length > 0)
            {
                arguments.AddRange(tsOptions.Split(' ').Where(x => x.Length > 0));
            }

            // position (disabling this is probably a bad idea as some things (watch sharing, transcoding info) fail then, which results in faulty clients.)
            if (Context.StartPosition > 0 && !disableSeeking)
            {
                arguments.Add("--start-time=" + (Context.StartPosition / 1000));
            }

            // audio track
            if (Context.AudioTrackId != null)
            {
                arguments.Add("--audio-track=" + Context.MediaInfo.AudioStreams.Where(x => x.ID == Context.AudioTrackId).First().Index);
            }
            else
            {
                StreamLog.Warn(Identifier, "VLC streaming without audio track is not implemented yet");
            }

            // subtitle selection
            string subtitleTranscoder;

            if (Context.SubtitleTrackId == null)
            {
                subtitleTranscoder = "scodec=none";
            }
            else
            {
                WebSubtitleStream stream = Context.MediaInfo.SubtitleStreams.First(x => x.ID == Context.SubtitleTrackId);
                if (stream.Filename != null)
                {
                    arguments.Add("--sub-file=" + stream.Filename);
                }
                else
                {
                    arguments.Add("--sub-track=" + stream.Index);
                }
                subtitleTranscoder = "soverlay";
            }

            // create parameters
            string sout;

            if (!String.IsNullOrEmpty(encoderOptions))
            {
                sout = "#transcode{" + encoderOptions + "," + subtitleTranscoder;
                if ((Context.IsTv || Context.MediaInfo.Container == "MPEG-TS") && !String.IsNullOrEmpty(tsEncoderOptions))
                {
                    sout += "," + tsEncoderOptions;
                }
                if (!Context.Profile.TranscoderParameters.ContainsKey("noResize") || Context.Profile.TranscoderParameters["noResize"] != "yes")
                {
                    sout += ",width=" + Context.OutputSize.Width + ",height=" + Context.OutputSize.Height;
                }
                sout += "}" + muxerOptions;
            }
            else
            {
                sout = "#" + muxerOptions.Substring(1);
            }

            // return
            return(new VLCParameters()
            {
                Sout = sout,
                Arguments = arguments.ToArray(),
                Input = inURL
            });
        }
示例#28
0
        private Rect    DrawStreamTabs(Rect r)
        {
            ConsoleSettings settings = HQ.Settings.Get <ConsoleSettings>();
            float           maxWidth = r.width;

            r.height = Constants.SingleLineHeight;

            // Switch stream
            if (settings.inputsManager.Check("Navigation", ConsoleConstants.SwitchNextStreamCommand) == true)
            {
                this.currentVars.workingStream += 1;
                if (this.currentVars.workingStream >= this.streams.Count)
                {
                    this.currentVars.workingStream = 0;
                }

                Event.current.Use();
            }
            if (settings.inputsManager.Check("Navigation", ConsoleConstants.SwitchPreviousStreamCommand) == true)
            {
                this.currentVars.workingStream -= 1;
                if (this.currentVars.workingStream < 0)
                {
                    this.currentVars.workingStream = this.streams.Count - 1;
                }

                Event.current.Use();
            }

            for (int i = 0; i < this.streams.Count; i++)
            {
                r = this.streams[i].OnTabGUI(r, i);
            }

            r.width = 16F;

            if (GUI.Button(r, "+", HQ.Settings.Get <GeneralSettings>().MenuButtonStyle) == true)
            {
                RemoteModuleSettings remoteSettings = HQ.Settings.Get <RemoteModuleSettings>();
                StreamLog            stream         = new StreamLog();
                stream.Init(this.console, this);
                stream.rowsDrawer.SetRowGetter(this);
                stream.FilterAltered += this.console.SaveModules;
                stream.OptionAltered += this.console.SaveModules;

                foreach (ILogFilter filter in remoteSettings.GenerateFilters())
                {
                    stream.groupFilters.filters.Add(filter);
                }

                this.streams.Add(stream);

                if (this.StreamAdded != null)
                {
                    this.StreamAdded(stream);
                }

                this.console.CheckNewLogConsume -= stream.ConsumeLog;
                this.console.PropagateNewLog    -= stream.AddLog;
                this.console.SaveModules();

                if (this.streams.Count == 1)
                {
                    this.currentVars.workingStream = 0;
                }
            }
            r.x += r.width;

            if (this.streams.Count > 2)
            {
                r.y    += r.height + 2F;
                r.x     = 0F;
                r.width = maxWidth;
            }
            else
            {
                r.width = maxWidth - r.x;
            }

            return(r);
        }
示例#29
0
 public WebStringResult StartStream(string identifier, string profileName, long startPosition)
 {
     StreamLog.Debug(identifier, "Called StartStream with profile={0}; start={1}", profileName, startPosition);
     _stream.EndStream(identifier); // first end previous stream, if any available
     return(_stream.StartStream(identifier, Configuration.StreamingProfiles.GetTranscoderProfileByName(profileName), startPosition * 1000));
 }
示例#30
0
 public WebBoolResult StopStream(string identifier)
 {
     StreamLog.Debug(identifier, "Called StopStream");
     _stream.EndStream(identifier);
     return(true);
 }
        private static void ParseOutputStream(Stream outputStream, Reference <WebTranscodingInfo> saveData, long startPosition, bool logMessages, bool logProgress, string identifier)
        {
            StreamReader reader = new StreamReader(outputStream);

            string line;

            while ((line = reader.ReadLine()) != null)
            {
                try
                {
                    bool canBeErrorLine = true;

                    if (line.StartsWith("frame="))
                    {
                        // format of an output line (yes, we're doomed as soon as ffmpeg changes it output):
                        // frame=  923 fps=256 q=31.0 size=    2712kB time=00:05:22.56 bitrate= 601.8kbits/s
                        Match match = Regex.Match(line, @"frame=([ 0-9]*) fps=([ 0-9]*) q=[^ ]* L?size=([ 0-9]*)kB time=([0-9]{2}):([0-9]{2}):([0-9]{2})\.[0-9]{2} bitrate=([ .0-9]*)kbits/s", RegexOptions.IgnoreCase);
                        if (match.Success)
                        {
                            canBeErrorLine = false;
                            lock (saveData)
                            {
                                saveData.Value.TranscodedTime      = (Int32.Parse(match.Groups[4].Value) * 3600 + Int32.Parse(match.Groups[5].Value) * 60 + Int32.Parse(match.Groups[6].Value)) * 1000;
                                saveData.Value.TranscodedFrames    = Int32.Parse(match.Groups[1].Value);
                                saveData.Value.TranscodingPosition = startPosition + saveData.Value.TranscodedTime;
                                saveData.Value.TranscodingFPS      = Int32.Parse(match.Groups[2].Value);
                                saveData.Value.OutputBitrate       = (int)Math.Round(Decimal.Parse(match.Groups[7].Value, System.Globalization.CultureInfo.InvariantCulture));
                            }

                            if (!logProgress) // we don't log output
                            {
                                continue;
                            }
                        }
                    }

                    if (line.StartsWith("video:"))
                    {
                        // process the result line to see if it completed successfully (example):
                        // video:5608kB audio:781kB global headers:0kB muxing overhead 13.235302%
                        Match resultMatch = Regex.Match(line, @"video:([0-9]*)kB audio:([0-9]*)kB global headers:([0-9]*)kB muxing overhead[^%]*%", RegexOptions.IgnoreCase);
                        saveData.Value.Finished = true;
                        canBeErrorLine          = false;
                    }

                    // show error messages
                    if (logMessages && canBeErrorLine)
                    {
                        StreamLog.Trace(identifier, "ffmpeg: " + line);
                    }
                }
                catch (ThreadAbortException)
                {
                    saveData.Value.Failed   = true;
                    saveData.Value.Finished = true;
                    reader.Close();
                    return;
                }
                catch (Exception e)
                {
                    StreamLog.Error(identifier, "Failure during parsing of ffmpeg output", e);
                }
            }

            saveData.Value.Finished = true;
            reader.Close();
            return;
        }
示例#32
0
文件: Log.cs 项目: akrisiun/AiLib
 public static void Close()
 {
     StreamLog.Close();
 }