Ejemplo n.º 1
0
        public void BuildPipeline(StreamContext context, EncoderUnit.LogStream log)
        {
            // input
            bool doInputReader = context.Source.NeedsInputReaderUnit;
            if(doInputReader)
            {
                context.Pipeline.AddDataUnit(context.Source.GetInputReaderUnit(), 1);
            }

            // get parameters
            VLCParameters vlcparam = GenerateVLCParameters(context);
            string path = @"\#OUT#";
            string sout = vlcparam.Sout.Replace("#OUT#", path);

            // generate vlc argument string
            var quotedArgList = vlcparam.Arguments.Select(x => x.Replace("\"", "\\\""));
            string vlcArguments = "\"" + String.Join("\" \"", quotedArgList) + "\"";
            string arguments = GenerateArguments(vlcparam.Input, sout, vlcArguments);

            // add the unit
            EncoderUnit.TransportMethod input = doInputReader ? EncoderUnit.TransportMethod.NamedPipe : EncoderUnit.TransportMethod.Other;
            EncoderUnit.TransportMethod outputMethod = readOutputStream ? EncoderUnit.TransportMethod.NamedPipe : EncoderUnit.TransportMethod.Other;
            // waiting for output pipe is meaningless for VLC as it opens it way earlier then that it actually writes to it. Instead, log parsing
            // in VLCWrapped handles the delay (yes, this class is standalone probably useless but is provided for debugging).
            EncoderUnit unit = new EncoderUnit(context.Profile.CodecParameters["path"], arguments, input, outputMethod, log);
            unit.DebugOutput = false; // change this for debugging
            context.Pipeline.AddDataUnit(unit, 5);
        }
Ejemplo n.º 2
0
        public override void BuildPipeline(StreamContext context)
        {
            base.BuildPipeline(context);

            // add metadata injection unit
            context.Pipeline.AddDataUnit(new FLVMetadataInjector(context), 15);
        }
Ejemplo n.º 3
0
 public void BuildPipeline(StreamContext context)
 {
     // we ignore our arguments :)
     context.TranscodingInfo.Supported = false;
     context.Pipeline.AddDataUnit(context.Source.GetInputReaderUnit(), 1);
     return;
 }
Ejemplo n.º 4
0
 public VLCManagedEncoder(string sout, string[] arguments, StreamContext context, InputMethod inputMethod)
 {
     this.sout = sout;
     this.arguments = arguments;
     this.inputMethod = inputMethod;
     this.context = context;
 }
Ejemplo n.º 5
0
        public override void BuildPipeline(StreamContext context)
        {
            SetupAssemblyLoader();

            // input
            bool doInputReader = context.Source.NeedsInputReaderUnit;
            if (doInputReader)
            {
                context.Pipeline.AddDataUnit(context.Source.GetInputReaderUnit(), 1);
            }

            // get parameters
            VLCParameters vlcparam = GenerateVLCParameters(context);
            int duration = (int)Math.Round((decimal)context.MediaInfo.Duration / 1000);

            // add the unit
            VLCManagedEncoder unit;
            if (doInputReader)
            {
                unit = new VLCManagedEncoder(vlcparam.Sout, vlcparam.Arguments, context, VLCManagedEncoder.InputMethod.NamedPipe);
            }
            else
            {
                unit = new VLCManagedEncoder(vlcparam.Sout, vlcparam.Arguments, context, VLCManagedEncoder.InputMethod.File, context.Source.GetPath());
            }
            context.Pipeline.AddDataUnit(unit, 5);
        }
Ejemplo n.º 6
0
 protected override Tuple<string, string> GetEncoderMuxerParameters(StreamContext context)
 {
     return new Tuple<string, string>(
         context.Profile.CodecParameters["encoder"],
         context.Profile.CodecParameters["muxer"].Replace("#ADDRESS#", String.Format(address, ""))
     );
 }
Ejemplo n.º 7
0
        public void StartStream(StreamContext context, Reference <WebTranscodingInfo> infoRef)
        {
            // ignore when not needed
            if (!enabled || (context.Source.MediaType != WebStreamMediaType.Movie && context.Source.MediaType != WebStreamMediaType.TVEpisode))
            {
                return;
            }

            // do some cleanup
            foreach (string id in streams.Where(x => x.Value.Stale).Select(x => x.Value.Id).ToList())
            {
                streams.Remove(id);
            }

            // generate identifier
            string identifier = GetIdentifierFromMediaSource(context.Source);

            // start if non-existent
            if (!streams.ContainsKey(identifier))
            {
                StreamState state = new StreamState()
                {
                    Id              = identifier,
                    Context         = context,
                    TranscodingInfo = infoRef,
                    Canceled        = false,
                    Stale           = false
                };

                // get mediadescriptor and rough runtime
                Log.Debug("WatchSharing: synchronizing start watching event to service");
                if (context.Source.MediaType == WebStreamMediaType.TVEpisode)
                {
                    state.MediaDescriptor = MPEServices.MAS.GetTVEpisodeDetailedById(context.Source.Provider, context.Source.Id);
                    state.Runtime         = MPEServices.MAS.GetTVShowDetailedById(context.Source.Provider, ((WebTVEpisodeDetailed)state.MediaDescriptor).ShowId).Runtime * 60000;
                }
                else if (context.Source.MediaType == WebStreamMediaType.Movie)
                {
                    state.MediaDescriptor = MPEServices.MAS.GetMovieDetailedById(context.Source.Provider, context.Source.Id);
                    state.Runtime         = ((WebMovieDetailed)state.MediaDescriptor).Runtime * 60000;
                }

                // get exact runtime if available
                if (context.MediaInfo.Duration > 60)
                {
                    state.Runtime = (int)context.MediaInfo.Duration;
                }

                streams[identifier]    = state;
                state.BackgroundThread = ThreadManager.Start("WatchWorker", new ParameterizedThreadStart(this.BackgroundWorker), identifier);
            }
            else
            {
                // just update the progress which will be send next time
                Log.Info("WatchSharing: Picking up old stream");
                streams[identifier].Canceled = false;
                streams[identifier].Context  = context;
            }
        }
Ejemplo n.º 8
0
 public EncoderUnit(string transcoder, string arguments, TransportMethod inputMethod, TransportMethod outputMethod, LogStream logStream, StreamContext context)
 {
     this.transcoderPath = transcoder;
     this.arguments = arguments;
     this.inputMethod = inputMethod;
     this.outputMethod = outputMethod;
     this.logStream = logStream;
     this.context = context;
 }
Ejemplo n.º 9
0
        public override void BuildPipeline(StreamContext context)
        {
            base.BuildPipeline(context, EncoderUnit.LogStream.StandardOut);

            // setup output parsing
            var einfo = new Reference<WebTranscodingInfo>(() => context.TranscodingInfo, x => { context.TranscodingInfo = x; });
            VLCWrapperParsingUnit logunit = new VLCWrapperParsingUnit(einfo, context.MediaInfo, context.StartPosition);
            context.Pipeline.AddLogUnit(logunit, 6);
        }
Ejemplo n.º 10
0
        public void BuildPipeline(StreamContext context)
        {
            this.context = context;
            obj.BuildPipeline(context);

            segmenterUnit = new HTTPLiveStreamingUnit(Identifier);
            segmenterUnit.DebugOutput = false; // change for debugging

            context.Pipeline.AddDataUnit(segmenterUnit, 20);
        }
Ejemplo n.º 11
0
        public void RetrieveStreamCalled(StreamContext context)
        {
            WCFUtil.SetContentLength(context.Source.GetFileInfo().Size);

            // there has to be a better way to do this
            object mime = RegistryReader.ReadKey(Microsoft.Win32.RegistryHive.ClassesRoot, Path.GetExtension(context.Source.GetFileInfo().Name), "Content Type");
            if (mime != null)
            {
                WCFUtil.SetContentType(mime.ToString());
            }
        }
Ejemplo n.º 12
0
        public void BuildPipeline(StreamContext context)
        {
            // add input
            bool doInputReader = context.Source.NeedsInputReaderUnit;
            if (doInputReader)
            {
                context.Pipeline.AddDataUnit(context.Source.GetInputReaderUnit(), 1);
            }

            // calculate stream mappings (no way I'm going to add subtitle support; it's just broken)
            string mappings = "";
            if (context.AudioTrackId != null)
            {
                mappings = String.Format("-map v:0 -map a:{0}", context.MediaInfo.AudioStreams.First(x => x.ID == context.AudioTrackId).Index);
            }

            // calculate full argument string
            string arguments;
            bool doResize = !context.Profile.CodecParameters.ContainsKey("noResize") || context.Profile.CodecParameters["noResize"] != "true";
            if (context.Profile.HasVideoStream && doResize)
            {
                arguments = String.Format(
                    "-y {0} -i \"#IN#\" -s {1} -aspect {2}:{3} {4} {5} \"#OUT#\"",
                    context.StartPosition != 0 ? "-ss " + (context.StartPosition / 1000) : "",
                    context.OutputSize, context.OutputSize.Width, context.OutputSize.Height,
                    mappings, context.Profile.CodecParameters["codecParameters"]
                );
            }
            else
            {
                arguments = String.Format(
                    "-y {0} -i \"#IN#\" {1} {2} \"#OUT#\"",
                    context.StartPosition != 0 ? "-ss " + (context.StartPosition / 1000) : "",
                    mappings, context.Profile.CodecParameters["codecParameters"]
                );
            }

            // fix input thing
            if (!doInputReader)
                arguments = arguments.Replace("#IN#", context.Source.GetPath());

            // add unit
            EncoderUnit.TransportMethod input = doInputReader ? EncoderUnit.TransportMethod.NamedPipe : EncoderUnit.TransportMethod.Other;
            EncoderUnit unit = new EncoderUnit(Configuration.Streaming.FFMpegPath, arguments, input, EncoderUnit.TransportMethod.NamedPipe, EncoderUnit.LogStream.StandardError);
            unit.DebugOutput = false; // change this for debugging
            context.Pipeline.AddDataUnit(unit, 5);

            // setup output parsing
            var einfo = new Reference<WebTranscodingInfo>(() => context.TranscodingInfo, x => { context.TranscodingInfo = x; });
            FFMpegLogParsingUnit logunit = new FFMpegLogParsingUnit(einfo, context.StartPosition);
            logunit.LogMessages = true;
            logunit.LogProgress = true;
            context.Pipeline.AddLogUnit(logunit, 6);
        }
Ejemplo n.º 13
0
 protected VLCParameters GenerateVLCParameters(StreamContext context)
 {
     var encmuxparam = GetEncoderMuxerParameters(context);
     return GenerateVLCParameters(
         context,
         context.Profile.CodecParameters.ContainsKey("options") ? context.Profile.CodecParameters["options"] : "",
         context.Profile.CodecParameters.ContainsKey("tsOptions") ? context.Profile.CodecParameters["tsOptions"] : "",
         context.Profile.CodecParameters.ContainsKey("disableSeeking") && context.Profile.CodecParameters["disableSeeking"] == "yes",
         encmuxparam.Item1,
         encmuxparam.Item2
     );
 }
Ejemplo n.º 14
0
        public HTTPLiveStreamer(string identifier, StreamContext context)
        {
            Identifier = identifier;
            Context = context;

            // create temporary directory
            TemporaryDirectory = Path.Combine(Path.GetTempPath(), "MPExtended", "httplivestreaming-" + identifier + "-" + new Random().Next(100000, 999999));
            if (Directory.Exists(TemporaryDirectory))
            {
                Directory.Delete(TemporaryDirectory, true);
            }
            Directory.CreateDirectory(TemporaryDirectory);

            // parse the <httpLiveRemoveOld> config option now for a tiny performance boost
            if (Context.Profile.TranscoderParameters.ContainsKey("httpLiveRemoveOld"))
                Int32.TryParse(Context.Profile.TranscoderParameters["httpLiveRemoveOld"], out keepSegments);
        }
Ejemplo n.º 15
0
        public HTTPLiveStreamer(string identifier, StreamContext context)
        {
            Identifier = identifier;
            Context    = context;

            // create temporary directory
            TemporaryDirectory = Path.Combine(Path.GetTempPath(), "MPExtended", "httplivestreaming-" + identifier + "-" + new Random().Next(100000, 999999));
            if (Directory.Exists(TemporaryDirectory))
            {
                Directory.Delete(TemporaryDirectory, true);
            }
            Directory.CreateDirectory(TemporaryDirectory);

            // parse the <httpLiveRemoveOld> config option now for a tiny performance boost
            if (Context.Profile.TranscoderParameters.ContainsKey("httpLiveRemoveOld"))
            {
                Int32.TryParse(Context.Profile.TranscoderParameters["httpLiveRemoveOld"], out keepSegments);
            }
        }
Ejemplo n.º 16
0
 public override void BuildPipeline(StreamContext context)
 {
     // VLC doesn't support output parsing, but subclasses do
     BuildPipeline(context, EncoderUnit.LogStream.None);
 }
Ejemplo n.º 17
0
 public VLCHTTPLiveStreamer(string identifier, StreamContext context)
     : base(identifier, context)
 {
 }
Ejemplo n.º 18
0
 protected virtual Tuple<string, string> GetEncoderMuxerParameters(StreamContext context)
 {
     return new Tuple<string, string>(
         context.Profile.CodecParameters["encoder"],
         context.Profile.CodecParameters["muxer"]
     );
 }
Ejemplo n.º 19
0
 public abstract void BuildPipeline(StreamContext context);
Ejemplo n.º 20
0
 public Resolution CalculateSize(StreamContext context)
 {
     return CalculateSize(context.Profile, context.Source, context.MediaInfo);
 }
Ejemplo n.º 21
0
        protected VLCParameters GenerateVLCParameters(StreamContext context, string options, string tsOptions, bool disableSeeking, string encoderOptions, string muxerOptions)
        {
            List<string> arguments = options.Split(' ').Where(x => x.Length > 0).ToList();

            // input
            string inURL = "";
            if (context.Source.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
            {
                Log.Warn("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 = "#transcode{" + encoderOptions +
                ",width=" + context.OutputSize.Width + ",height=" + context.OutputSize.Height + "," + subtitleTranscoder + "}" +
                muxerOptions;

            // return
            return new VLCParameters()
            {
                Sout = sout,
                Arguments = arguments.ToArray(),
                Input = inURL
            };
        }
Ejemplo n.º 22
0
 public VLCManagedEncoder(string sout, string[] arguments, StreamContext context, InputMethod inputMethod, string input)
     : this(sout, arguments, context, inputMethod)
 {
     this.inputPath = input;
 }
Ejemplo n.º 23
0
        public void StartStream(StreamContext context, Reference <WebTranscodingInfo> infoRef)
        {
            // ignore when not needed
            if (!enabled || (context.Source.MediaType != WebMediaType.Movie && context.Source.MediaType != WebMediaType.TVEpisode))
            {
                return;
            }

            // do some cleanup
            foreach (string id in streams.Where(x => x.Value.Stale).Select(x => x.Value.Id).ToList())
            {
                streams.Remove(id);
            }

            // generate identifier
            string identifier = GetIdentifierFromMediaSource(context.Source);

            // start if non-existent
            if (!streams.ContainsKey(identifier))
            {
                StreamState state = new StreamState()
                {
                    Id              = identifier,
                    Context         = context,
                    TranscodingInfo = infoRef,
                    Canceled        = false,
                    Stale           = false
                };

                // get mediadescriptor and rough runtime
                Log.Debug("WatchSharing: synchronizing start watching event to service");
                if (context.Source.MediaType == WebMediaType.TVEpisode)
                {
                    state.MediaDescriptor = Connections.MAS.GetTVEpisodeDetailedById(context.Source.Provider, context.Source.Id);
                    state.Runtime         = Connections.MAS.GetTVShowDetailedById(context.Source.Provider, ((WebTVEpisodeDetailed)state.MediaDescriptor).ShowId).Runtime * 60000;
                }
                else if (context.Source.MediaType == WebMediaType.Movie)
                {
                    state.MediaDescriptor = Connections.MAS.GetMovieDetailedById(context.Source.Provider, context.Source.Id);
                    state.Runtime         = ((WebMovieDetailed)state.MediaDescriptor).Runtime * 60000;
                }

                // get exact runtime if available
                if (context.MediaInfo.Duration > 60)
                {
                    state.Runtime = (int)context.MediaInfo.Duration;
                }

                // send start watching event
                Task.Factory.StartNew(delegate()
                {
                    if (state.Context.Source.MediaType == WebMediaType.TVEpisode)
                    {
                        services.ExecuteForAll(s => CallForEpisode(identifier, s.StartWatchingEpisode));
                    }
                    else if (state.Context.Source.MediaType == WebMediaType.Movie)
                    {
                        services.ExecuteForAll(s => s.StartWatchingMovie((WebMovieDetailed)state.MediaDescriptor));
                    }
                }).LogOnException();

                // and start the background timer
                streams[identifier]    = state;
                state.BackgroundTimers = new List <WatchSharingTimer>();
                foreach (IWatchSharingService service in services)
                {
                    var thisTimer = new WatchSharingTimer(identifier, service);
                    thisTimer.Elapsed += TimerElapsed;
                    thisTimer.Start();
                    state.BackgroundTimers.Add(thisTimer);
                }
            }
            else
            {
                // just update the progress which will be send next time
                Log.Info("WatchSharing: Picking up old stream");
                streams[identifier].Canceled = false;
                streams[identifier].Context  = context;
            }
        }
Ejemplo n.º 24
0
 public Resolution CalculateSize(StreamContext context)
 {
     return(CalculateSize(context.Profile, context.Source, context.MediaInfo));
 }
Ejemplo n.º 25
0
        public void StartStream(StreamContext context, Reference<WebTranscodingInfo> infoRef)
        {
            // ignore when not needed
            if (!enabled || (context.Source.MediaType != WebStreamMediaType.Movie && context.Source.MediaType != WebStreamMediaType.TVEpisode))
            {
                return;
            }

            // do some cleanup
            foreach (string id in streams.Where(x => x.Value.Stale).Select(x => x.Value.Id).ToList())
            {
                streams.Remove(id);
            }

            // generate identifier
            string identifier = GetIdentifierFromMediaSource(context.Source);

            // start if non-existent
            if (!streams.ContainsKey(identifier))
            {
                StreamState state = new StreamState()
                {
                    Id = identifier,
                    Context = context,
                    TranscodingInfo = infoRef,
                    Canceled = false,
                    Stale = false
                };

                // get mediadescriptor and rough runtime
                Log.Debug("WatchSharing: synchronizing start watching event to service");
                if (context.Source.MediaType == WebStreamMediaType.TVEpisode)
                {
                    state.MediaDescriptor = MPEServices.MAS.GetTVEpisodeDetailedById(context.Source.Provider, context.Source.Id);
                    state.Runtime = MPEServices.MAS.GetTVShowDetailedById(context.Source.Provider, ((WebTVEpisodeDetailed)state.MediaDescriptor).ShowId).Runtime * 60000;
                }
                else if (context.Source.MediaType == WebStreamMediaType.Movie)
                {
                    state.MediaDescriptor = MPEServices.MAS.GetMovieDetailedById(context.Source.Provider, context.Source.Id);
                    state.Runtime = ((WebMovieDetailed)state.MediaDescriptor).Runtime * 60000;
                }

                // get exact runtime if available
                if (context.MediaInfo.Duration > 60)
                {
                    state.Runtime = (int)context.MediaInfo.Duration;
                }

                streams[identifier] = state;
                state.BackgroundThread = ThreadManager.Start("WatchWorker", new ParameterizedThreadStart(this.BackgroundWorker), identifier);
            }
            else
            {
                // just update the progress which will be send next time
                Log.Info("WatchSharing: Picking up old stream");
                streams[identifier].Canceled = false;
                streams[identifier].Context = context;
            }
        }
Ejemplo n.º 26
0
 public FLVMetadataInjector(StreamContext context)
 {
     this.context = context;
 }
Ejemplo n.º 27
0
 public abstract void BuildPipeline(StreamContext context, int position);
Ejemplo n.º 28
0
        protected VLCParameters GenerateVLCParameters(StreamContext context, int position)
        {
            List<string> arguments = context.Profile.CodecParameters["options"].Split(' ').Where(x => x.Length > 0).ToList();

            // input
            string inURL = "";
            if (context.Pipeline.GetDataUnit(1) != null && context.Pipeline.GetDataUnit(1) is InputUnit)
            {
                inURL = "stream://#IN#";
            }
            else
            {
                inURL = context.Source.GetPath();
            }

            // add tv options if specified
            if (context.IsTv && context.Profile.CodecParameters.ContainsKey("tvOptions") && context.Profile.CodecParameters["tvOptions"].Length > 0)
            {
                arguments.AddRange(context.Profile.CodecParameters["tvOptions"].Split(' ').Where(x => x.Length > 0));
            }

            // position
            if (position > 0)
            {
                // FIXME: temporary allow disabling it as it breaks some profiles
                if (!context.Profile.CodecParameters.ContainsKey("disableSeeking") || context.Profile.CodecParameters["disableSeeking"] == "no")
                {
                    arguments.Add("--start-time=" + position);
                }
            }

            // audio track
            if (context.AudioTrackId != null)
            {
                arguments.Add("--audio-track=" + context.MediaInfo.AudioStreams.Where(x => x.ID == context.AudioTrackId).First().Index);
            }
            else
            {
                Log.Warn("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 =
                "#transcode{" + context.Profile.CodecParameters["encoder"] +
                ",width=" + context.OutputSize.Width + ",height=" + context.OutputSize.Height + "," + subtitleTranscoder + "}" +
                context.Profile.CodecParameters["muxer"];

            // return
            return new VLCParameters()
            {
                Sout = sout,
                Arguments = arguments.ToArray(),
                Input = inURL
            };
        }
Ejemplo n.º 29
0
 public EncoderUnit(string transcoder, string arguments, TransportMethod inputMethod, TransportMethod outputMethod, LogStream logStream, StreamContext context)
     : this(transcoder, arguments, inputMethod, outputMethod, logStream)
 {
     this.context = context;
 }
Ejemplo n.º 30
0
 public FFMpegHTTPLiveStreamer(string identifier, StreamContext context)
     : base(identifier, context)
 {
     indexUrl = WCFUtil.GetCurrentRoot() + "StreamingService/stream/CustomTranscoderData?identifier=" + identifier + "&action=segment&parameters=";
 }