public override bool AddStream(Media media, MediaOptions options, MediaStream stream, out MediaStream cachedStream)
		{
			/* STOCK METHOD (Decompiled) */
			Assert.ArgumentNotNull(media, "media");
			Assert.ArgumentNotNull(options, "options");
			Assert.ArgumentNotNull(stream, "stream");

			cachedStream = null;

			if (!CanCache(media, options))
				return false;

			MediaCacheRecord cacheRecord = CreateCacheRecord(media, options, stream);

			if (cacheRecord == null) return false;

			cachedStream = cacheRecord.GetStream();

			if (cachedStream == null) return false;

			AddToActiveList(cacheRecord);
			/* END STOCK */

			// we store the site context because on the background thread: without the Sitecore context saved (on a worker thread), that disables the media cache
			var currentSite = Context.Site;

			cacheRecord.PersistAsync((() => OnAfterPersist(cacheRecord, currentSite)));

			return true;
		}
示例#2
0
        public override IOptimizerResult Optimize(MediaStream stream)
        {
            var quantizer = new WuQuantizer();

            var memoryStream = new MemoryStream();

            using (var bitmap = new Bitmap(stream.Stream))
            {
                var bitDepth = Image.GetPixelFormatSize(bitmap.PixelFormat);
                if (bitDepth != 32)
                {
                    return OptimizerFailureResult("the image you are attempting to quantize does not contain a 32 bit ARGB palette. This image has a bit depth of {0} with {1} colors".FormatWith(bitDepth, bitmap.Palette.Entries.Length));
                }

                using (var quantized = quantizer.QuantizeImage(bitmap))
                {
                    quantized.Save(memoryStream, ImageFormat.Png);
                }

                // rewind the stream
                memoryStream.Seek(0, SeekOrigin.Begin);

                var result = new PngQuantOptimizerResult();
                result.Success = true;
                result.SizeBefore = (int)stream.Length;
                result.SizeAfter = (int)memoryStream.Length;
                result.ResultStream = memoryStream;

                return OptimizationSuccessful(result);
            }
        }
示例#3
0
		/// <summary>
		/// Optimizes a media stream and returns the optimized result. The original stream is closed if processing is successful.
		/// </summary>
		public virtual MediaStream Process(MediaStream stream, MediaOptions options)
		{
			Assert.ArgumentNotNull(stream, "stream");

			if (!stream.AllowMemoryLoading)
			{
				Tracer.Error("Could not resize image as it was larger than the maximum size allowed for memory processing. Media item: {0}", stream.MediaItem.Path);
				return null;
			}

			var optimizer = CreateOptimizer(stream);

			if (optimizer == null) return null;

			var sw = new Stopwatch();
			sw.Start();

			var result = optimizer.Optimize(stream);

			sw.Stop();

			if (result.Success)
			{
				stream.Stream.Close();

				Log.Info("Dianoga: optimized {0}.{1} [{2}] (final size: {3} bytes) - saved {4} bytes / {5:p}. Optimized in {6}ms.".FormatWith(stream.MediaItem.MediaPath, stream.MediaItem.Extension, GetDimensions(options), result.SizeAfter, result.SizeBefore - result.SizeAfter, 1 - ((result.SizeAfter / (float)result.SizeBefore)), sw.ElapsedMilliseconds), this);

				return new MediaStream(result.CreateResultStream(), stream.Extension, stream.MediaItem);
			}

			Log.Warn("Dianoga: unable to optimize {0}.{1} because {2}".FormatWith(stream.MediaItem.MediaPath, stream.MediaItem.Extension, result.ErrorMessage), this);

			return null;
		}
示例#4
0
 internal override async Task OnAddStream(MediaStream stream)
 {
     Context.RemoteStream = stream;
     var tracks = stream.GetVideoTracks();
     if (tracks.Count > 0)
     {
         var source = Context.Media.CreateMediaStreamSource(tracks[0], 30, "PEER");
         Context.RemoteVideoRenderer.SetupRenderer(Context.ForegroundProcessId, source);
     }
 }
示例#5
0
        public override IOptimizerResult Optimize(MediaStream stream)
        {
            var tempFilePath = GetTempFilePath();

            using (var fileStream = File.OpenWrite(tempFilePath))
            {
                stream.Stream.CopyTo(fileStream);
            }

            var result = new JpegOptimizerResult();

            result.SizeBefore = (int)stream.Length;

            var jpegtran = Process.Start(ExePath, "-optimize -copy none -progressive -outfile \"{0}\" \"{0}\"".FormatWith(tempFilePath));
            if (jpegtran != null && jpegtran.WaitForExit(ToolTimeout))
            {
                if (jpegtran.ExitCode != 0)
                {
                    result.Success = false;
                    result.ErrorMessage = "jpegtran exited with unexpected exit code " + jpegtran.ExitCode;
                    return result;
                }

                result.Success = true;
                result.SizeAfter = (int)new FileInfo(tempFilePath).Length;

                // read the file to memory so we can nuke the temp file
                using (var fileStream = File.OpenRead(tempFilePath))
                {
                    result.ResultStream = new MemoryStream();
                    fileStream.CopyTo(result.ResultStream);
                    result.ResultStream.Seek(0, SeekOrigin.Begin);
                }

                File.Delete(tempFilePath);

                return OptimizationSuccessful(result);
            }

            result.Success = false;
            result.ErrorMessage = "jpegtran took longer than {0} to execute, which we consider a failure.".FormatWith(ToolTimeout);
            // kill the process and clean up the tempfile as we have discarded the optimizer
            jpegtran.Kill();
            try
            {
                File.Delete(tempFilePath);
            } catch(IOException)
            {
                // Silently discard any io errors in the file deletion...
            }

            return result;
        }
示例#6
0
        internal override async Task OnAddStream(MediaStream stream)
        {
            Context.RemoteStream = stream;
            var tracks = stream.GetVideoTracks();
            if (tracks.Count > 0)
            {
#if WIN10
                var source = Context.Media.CreateMediaSource(tracks[0], VoipContext.PeerMediaStreamId);
#else
                var source = Context.Media.CreateMediaStreamSource(tracks[0], 30, VoipContext.PeerMediaStreamId);
#endif
                Context.RemoteVideoRenderer.SetupRenderer(Context.ForegroundProcessId, source, Context.RemoteVideoControlSize);
            }
        }
示例#7
0
        public AudioStream(BusAttachment bus, string name, MP3Reader mp3Reader, UInt32 jitter, UInt32 prefill)
        {
            _mediaStream = new MediaStream(bus, name, mp3Reader.GetDescription());
            _mediaPacer = new MediaPacer(mp3Reader.GetDescription(), jitter, 0);
            _mp3Reader = mp3Reader;
            _prefill = prefill;

            _mediaStream.OnOpen += OnOpen;
            _mediaStream.OnClose += OnClose;
            _mediaStream.OnPlay += OnPlay;
            _mediaStream.OnPause += OnPause;
            _mediaStream.OnSeekRelative += OnSeekRelative;
            _mediaStream.OnSeekAbsolute += OnSeekAbsolute;

            _mediaPacer.JitterMiss += JitterMiss;
            _mediaPacer.RequestFrames += RequestFrames;
            _buffer = new byte[_frameReadLength * _mp3Reader.FrameLen];

        }
示例#8
0
		public override IOptimizerResult Optimize(MediaStream stream)
		{
			IntPtr pngOptimizer = GetOrLoadPngOptimizer();

			using (var memoryStream = new MemoryStream())
			{
				stream.Stream.CopyTo(memoryStream);
				byte[] imageBytes = memoryStream.ToArray();
				byte[] resultBytes = new byte[imageBytes.Length + 400000];
				int resultSize;

				IntPtr addressOfOptimize = NativeMethods.GetProcAddress(pngOptimizer, "PO_OptimizeFileMem");

				if (addressOfOptimize == IntPtr.Zero) throw new Exception("Can't find optimize funtion in PngOptimizerDll.dll!");

				OptimizeBytes optimizeMethod = (OptimizeBytes)Marshal.GetDelegateForFunctionPointer(addressOfOptimize, typeof(OptimizeBytes));

				bool success = optimizeMethod(imageBytes, imageBytes.Length, resultBytes, resultBytes.Length, out resultSize);

				var result = new PngOptimizerResult();
				result.Success = success;
				result.SizeBefore = imageBytes.Length;
				result.SizeAfter = resultSize;
				result.OptimizedBytes = resultBytes.Take(resultSize).ToArray();

				if (!result.Success)
				{
					IntPtr addressOfGetError = NativeMethods.GetProcAddress(pngOptimizer, "PO_GetLastErrorString");

					if (addressOfGetError == IntPtr.Zero) throw new Exception("Can't find get last error funtion in PngOptimizerDll.dll!");

					GetLastErrorString errorMethod = (GetLastErrorString)Marshal.GetDelegateForFunctionPointer(addressOfGetError, typeof(GetLastErrorString));

					result.ErrorMessage = errorMethod();
				}

				return OptimizationSuccessful(result);
			}
		}
        private static void ProcessMediaUpload(Stream content, Database db, string itemParam, string entryName, bool skipExisting = false)
        {
            var mediaItem = (MediaItem)db.GetItem(itemParam) ?? db.GetItem(itemParam.TrimStart('/', '\\')) ??
                            db.GetItem(ApplicationSettings.MediaLibraryPath + itemParam);

            if (mediaItem == null)
            {
                var filename = itemParam.TrimEnd('/', '\\').Replace('\\', '/');
                var dirName = (Path.GetDirectoryName(filename) ?? string.Empty).Replace('\\', '/');
                if (!dirName.StartsWith(Constants.MediaLibraryPath))
                {
                    dirName = Constants.MediaLibraryPath + (dirName.StartsWith("/") ? dirName : "/" + dirName);
                }

                if (!String.IsNullOrEmpty(entryName))
                {
                    dirName += "/" + Path.GetDirectoryName(entryName).Replace('\\', '/');
                    filename = Path.GetFileName(entryName);
                }

                var mco = new MediaCreatorOptions
                {
                    Database = db,
                    Versioned = Settings.Media.UploadAsVersionableByDefault,
                    Destination = $"{dirName}/{Path.GetFileNameWithoutExtension(filename)}",
                };

                var mc = new MediaCreator();
                using (var ms = new MemoryStream())
                {
                    content.CopyTo(ms);
                    mc.CreateFromStream(ms, Path.GetFileName(filename), mco);
                }
            }
            else
            {
                if (skipExisting) return;

                var mediaUri = MediaUri.Parse(mediaItem);
                var media = MediaManager.GetMedia(mediaUri);

                using (var ms = new MemoryStream())
                {
                    content.CopyTo(ms);
                    using (new EditContext(mediaItem, SecurityCheck.Disable))
                    {
                        using (var mediaStream = new MediaStream(ms, media.Extension, mediaItem))
                        {
                            media.SetStream(mediaStream);
                        }
                    }
                }
            }
        }
        public Action <RTCIceCandidate> sendLocalCandidate = null; // new Function,

        private void _createPeerConnection()
        {
            if (this.pc != null)
            {
                throw new Exception("the peer connection is already initialized");
            }

            Messenger.Broadcast(SympleLog.LogDebug, "symple:webrtc: create peer connection: " + this.rtcConfig);

            this.pc = new RTCPeerConnection(this.rtcConfig);
            Messenger.Broadcast(SympleLog.LogDebug, "symple:webrtc: created this.pc");
            pc.OnIceCandidate += (RTCPeerConnectionIceEvent iceEvent) =>
            {
                if (iceEvent.Candidate != null)
                {
                    Messenger.Broadcast(SympleLog.LogDebug, "symple:webrtc: candidate gathered: " + iceEvent.Candidate);
                    if (sendLocalCandidate != null)
                    {
                        this.sendLocalCandidate(iceEvent.Candidate);
                    }
                }
                else
                {
                    Messenger.Broadcast(SympleLog.LogDebug, "symple:webrtc: candidate gathering complete");
                }
            };

            pc.OnAddStream += (MediaStreamEvent mediaStreamEvent) =>
            {
                //string objectURL = createObjectURL(mediaStreamEvent.Stream);
                Messenger.Broadcast(SympleLog.LogInfo, "symple:webrtc: remote stream added");

                // Set the state to playing once candidates have completed gathering.
                // This is the best we can do until ICE onstatechange is implemented.
                this.setState("playing");

                // ====== here we would play the video element ======
                Messenger.Broadcast(SympleLog.LogDebug, "symple:webrtc: remote stream added, should play it now (TODO)");

                MediaVideoTrack peerVideoTrack = mediaStreamEvent.Stream.GetVideoTracks().FirstOrDefault();
                if (peerVideoTrack != null)
                {
                    Messenger.Broadcast(SympleLog.RemoteStreamAdded, GetMedia(), peerVideoTrack);


                    //IMediaSource mediaSource = GetMedia().CreateMediaSource(peerVideoTrack, RemotePeerVideoTrackId); // was valid in org.webrt 1.54, not valid anymore
                    //Messenger.Broadcast(SympleLog.LogInfo, "Creating video source for remote peer video");
                    //IMediaSource mediaSource = GetMedia().CreateMediaStreamSource(RemotePeerVideoTrackId);
                    //Messenger.Broadcast(SympleLog.LogInfo, "Created video source for remote peer video");
                    //Messenger.Broadcast(SympleLog.CreatedMediaSource, mediaSource);
                }
                else
                {
                    Messenger.Broadcast(SympleLog.LogError, "ERROR: Received remote media stream, but there was no video track");
                }

                // store the active stream
                this.activeStream = mediaStreamEvent.Stream;
            };

            pc.OnRemoveStream += (MediaStreamEvent mediaStreamEvent) =>
            {
                Messenger.Broadcast(SympleLog.LogInfo, "symple:webrtc: remote stream removed: " + mediaStreamEvent);

                MediaVideoTrack peerVideoTrack = mediaStreamEvent.Stream.GetVideoTracks().FirstOrDefault();

                Messenger.Broadcast(SympleLog.RemoteStreamRemoved, GetMedia(), peerVideoTrack);



                //this.video.stop();
                //this.video.src = "";
            };

            // NOTE: The following state events are still very unreliable.
            // Hopefully when the spec is complete this will change, but until then
            // we need to 'guess' the state.
            // this.pc.onconnecting = function(event) { Symple.log('symple:webrtc: onconnecting:', event); };
            // this.pc.onopen = function(event) { Symple.log('symple:webrtc: onopen:', event); };
            // this.pc.onicechange = function(event) { Symple.log('symple:webrtc: onicechange :', event); };
            // this.pc.onstatechange = function(event) { Symple.log('symple:webrtc: onstatechange :', event); };
        }
示例#11
0
 public MediaStreamAudioSourceNode CreateMediaStreamSource(MediaStream mediaStream)
 {
     return default(MediaStreamAudioSourceNode);
 }
示例#12
0
        private async Task Initialize()
        {
            //Initialization of WebRTC worker threads, etc
            Org.WebRtc.WebRTC.Initialize(Dispatcher);

            _media = Media.CreateMedia();

            //Selecting video device to use, setting preferred capabilities
            var videoDevices        = _media.GetVideoCaptureDevices();
            var selectedVideoDevice = videoDevices.First();
            var videoCapabilites    = await selectedVideoDevice.GetVideoCaptureCapabilities();

            var selectedVideoCapability = videoCapabilites.FirstOrDefault();

            //Needed for HoloLens camera, will not set compatible video capability automatically
            //Hololens Cam default capability: 1280x720x30
            Org.WebRtc.WebRTC.SetPreferredVideoCaptureFormat(
                (int)selectedVideoCapability.Width,
                (int)selectedVideoCapability.Height,
                (int)selectedVideoCapability.FrameRate);

            //Setting up local stream
            RTCMediaStreamConstraints mediaStreamConstraints = new RTCMediaStreamConstraints
            {
                audioEnabled = false,
                videoEnabled = true
            };

            _localStream = await _media.GetUserMedia(mediaStreamConstraints);

            _media.SelectVideoDevice(selectedVideoDevice);

            // Get Video Tracks
            var videotrac = _localStream.GetVideoTracks();

            foreach (var videoTrack in videotrac) //This foreach may not be necessary
            {
                videoTrack.Enabled = true;
            }
            var selectedVideoTrac = videotrac.FirstOrDefault();

            Debug.WriteLine("Creating RTCPeerConnection");
            var config = new RTCConfiguration()
            {
                BundlePolicy       = RTCBundlePolicy.Balanced,
                IceTransportPolicy = RTCIceTransportPolicy.All,
                IceServers         = GetDefaultList()
            };

            _peerConnection = new RTCPeerConnection(config);
            _peerConnection.OnIceCandidate        += _localRtcPeerConnection_OnIceCandidate;
            _peerConnection.OnIceConnectionChange += _localRtcPeerConnection_OnIceConnectionChange;
            _peerConnection.OnAddStream           += _peerConnection_OnAddStream;

            //_peerConnection.AddStream(_localStream);
            _media.AddVideoTrackMediaElementPair(selectedVideoTrac, _localVideo, _localStream.Id);

            // Send event started
            Element.SendStarted();

            //Debug.WriteLine("Creating 'remote' RTCPeerConnection");
            //_remoteRtcPeerConnection = new RTCPeerConnection(config);
            //_remoteRtcPeerConnection.OnIceCandidate += _remoteRtcPeerConnection_OnIceCandidate;
            //_remoteRtcPeerConnection.OnIceConnectionChange += _remoteRtcPeerConnection_OnIceConnectionChange;
            //// Wait for Stream
            //_remoteRtcPeerConnection.OnAddStream += _remoteRtcPeerConnection_OnAddStream;
        }
示例#13
0
    public async Task <Either <BaseError, string> > GenerateSongImage(
        string ffmpegPath,
        string ffprobePath,
        Option <string> subtitleFile,
        Channel channel,
        Option <ChannelWatermark> playoutItemWatermark,
        Option <ChannelWatermark> globalWatermark,
        MediaVersion videoVersion,
        string videoPath,
        bool boxBlur,
        Option <string> watermarkPath,
        WatermarkLocation watermarkLocation,
        int horizontalMarginPercent,
        int verticalMarginPercent,
        int watermarkWidthPercent,
        CancellationToken cancellationToken)
    {
        try
        {
            string outputFile = _tempFilePool.GetNextTempFile(TempFileCategory.SongBackground);

            MediaStream videoStream = await _ffmpegStreamSelector.SelectVideoStream(videoVersion);

            Option <ChannelWatermark> watermarkOverride =
                videoVersion is FallbackMediaVersion or CoverArtMediaVersion
                    ? new ChannelWatermark
            {
                Mode = ChannelWatermarkMode.Permanent,
                HorizontalMarginPercent = horizontalMarginPercent,
                VerticalMarginPercent   = verticalMarginPercent,
                Location     = watermarkLocation,
                Size         = WatermarkSize.Scaled,
                WidthPercent = watermarkWidthPercent,
                Opacity      = 100
            }
                    : None;

            Option <WatermarkOptions> watermarkOptions =
                await GetWatermarkOptions(
                    ffprobePath,
                    channel,
                    playoutItemWatermark,
                    globalWatermark,
                    videoVersion,
                    watermarkOverride,
                    watermarkPath);

            FFmpegPlaybackSettings playbackSettings =
                _playbackSettingsCalculator.CalculateErrorSettings(channel.FFmpegProfile);

            FFmpegPlaybackSettings scalePlaybackSettings = _playbackSettingsCalculator.CalculateSettings(
                StreamingMode.TransportStream,
                channel.FFmpegProfile,
                videoVersion,
                videoStream,
                None,
                DateTimeOffset.UnixEpoch,
                DateTimeOffset.UnixEpoch,
                TimeSpan.Zero,
                TimeSpan.Zero,
                false,
                Option <int> .None);

            FFmpegProcessBuilder builder = new FFmpegProcessBuilder(ffmpegPath, false, _logger)
                                           .WithThreads(1)
                                           .WithQuiet()
                                           .WithFormatFlags(playbackSettings.FormatFlags)
                                           .WithSongInput(videoPath, videoStream.Codec, videoStream.PixelFormat, boxBlur)
                                           .WithWatermark(watermarkOptions, None, channel.FFmpegProfile.Resolution)
                                           .WithSubtitleFile(subtitleFile);

            foreach (IDisplaySize scaledSize in scalePlaybackSettings.ScaledSize)
            {
                builder = builder.WithScaling(scaledSize);

                if (NeedToPad(channel.FFmpegProfile.Resolution, scaledSize))
                {
                    builder = builder.WithBlackBars(channel.FFmpegProfile.Resolution);
                }
            }

            using Process process = builder
                                    .WithFilterComplex(
                      videoStream,
                      None,
                      videoPath,
                      None,
                      playbackSettings.VideoFormat)
                                    .WithOutputFormat("apng", outputFile)
                                    .Build();

            _logger.LogInformation(
                "ffmpeg song arguments {FFmpegArguments}",
                string.Join(" ", process.StartInfo.ArgumentList));

            await Cli.Wrap(process.StartInfo.FileName)
            .WithArguments(process.StartInfo.ArgumentList)
            .WithValidation(CommandResultValidation.None)
            .ExecuteAsync(cancellationToken);

            return(outputFile);
        }
        catch (Exception ex)
        {
            _logger.LogWarning(ex, "Error generating song image");
            _client.Notify(ex);
            return(Left(BaseError.New(ex.Message)));
        }
    }
示例#14
0
        /// <summary>
        /// Creates a peer connection.
        /// </summary>
        /// <returns>True if connection to a peer is successfully created.</returns>
        private async Task <bool> CreatePeerConnection(CancellationToken cancelationToken)
        {
            Debug.Assert(_peerConnection == null);
            if (cancelationToken.IsCancellationRequested)
            {
                return(false);
            }

            var config = new RTCConfiguration()
            {
                BundlePolicy = RTCBundlePolicy.Balanced,
#if ORTCLIB
                SignalingMode = _signalingMode,
                GatherOptions = new RTCIceGatherOptions()
                {
                    IceServers = new List <RTCIceServer>(_iceServers),
                }
#else
                IceTransportPolicy = RTCIceTransportPolicy.All,
                IceServers         = _iceServers
#endif
            };

            Debug.WriteLine("Conductor: Creating peer connection.");
            _peerConnection = new RTCPeerConnection(config);

            if (_peerConnection == null)
            {
                throw new NullReferenceException("Peer connection is not created.");
            }

#if !ORTCLIB
            _peerConnection.EtwStatsEnabled = _etwStatsEnabled;
            _peerConnection.ConnectionHealthStatsEnabled = _peerConnectionStatsEnabled;
#endif
            if (cancelationToken.IsCancellationRequested)
            {
                return(false);
            }
#if ORTCLIB
            OrtcStatsManager.Instance.Initialize(_peerConnection);
#endif
            OnPeerConnectionCreated?.Invoke();

            _peerConnection.OnIceCandidate += PeerConnection_OnIceCandidate;
#if ORTCLIB
            _peerConnection.OnTrack     += PeerConnection_OnAddTrack;
            _peerConnection.OnTrackGone += PeerConnection_OnRemoveTrack;
            _peerConnection.OnIceConnectionStateChange += () => { Debug.WriteLine("Conductor: Ice connection state change, state=" + (null != _peerConnection ? _peerConnection.IceConnectionState.ToString() : "closed")); };
#else
            _peerConnection.OnAddStream             += PeerConnection_OnAddStream;
            _peerConnection.OnRemoveStream          += PeerConnection_OnRemoveStream;
            _peerConnection.OnConnectionHealthStats += PeerConnection_OnConnectionHealthStats;
#endif

            // Setup Data Channel
            _peerSendDataChannel = _peerConnection.CreateDataChannel(
                "SendDataChannel",
                new RTCDataChannelInit()
            {
                Ordered = true
            });
            _peerSendDataChannel.OnOpen   += PeerSendDataChannelOnOpen;
            _peerSendDataChannel.OnClose  += PeerSendDataChannelOnClose;
            _peerSendDataChannel.OnError  += _peerSendDataChannel_OnError;
            _peerConnection.OnDataChannel += _peerConnection_OnDataChannel;     // DataChannel Setup Completed

            Debug.WriteLine("Conductor: Getting user media.");
            RTCMediaStreamConstraints mediaStreamConstraints = new RTCMediaStreamConstraints
            {
                // Always include audio/video enabled in the media stream,
                // so it will be possible to enable/disable audio/video if
                // the call was initiated without microphone/camera
                audioEnabled = true,
                videoEnabled = true
            };

            if (cancelationToken.IsCancellationRequested)
            {
                return(false);
            }

#if ORTCLIB
            var tracks = await _media.GetUserMedia(mediaStreamConstraints);

            if (tracks != null)
            {
                RTCRtpCapabilities audioCapabilities = RTCRtpSender.GetCapabilities("audio");
                RTCRtpCapabilities videoCapabilities = RTCRtpSender.GetCapabilities("video");

                _mediaStream = new MediaStream(tracks);
                Debug.WriteLine("Conductor: Adding local media stream.");
                IList <MediaStream> mediaStreamList = new List <MediaStream>();
                mediaStreamList.Add(_mediaStream);
                foreach (var mediaStreamTrack in tracks)
                {
                    //Create stream track configuration based on capabilities
                    RTCMediaStreamTrackConfiguration configuration = null;
                    if (mediaStreamTrack.Kind == MediaStreamTrackKind.Audio && audioCapabilities != null)
                    {
                        configuration =
                            await Helper.GetTrackConfigurationForCapabilities(audioCapabilities, AudioCodec);
                    }
                    else if (mediaStreamTrack.Kind == MediaStreamTrackKind.Video && videoCapabilities != null)
                    {
                        configuration =
                            await Helper.GetTrackConfigurationForCapabilities(videoCapabilities, VideoCodec);
                    }
                    if (configuration != null)
                    {
                        _peerConnection.AddTrack(mediaStreamTrack, mediaStreamList, configuration);
                    }
                }
            }
#else
            _mediaStream = await _media.GetUserMedia(mediaStreamConstraints);
#endif

            if (cancelationToken.IsCancellationRequested)
            {
                return(false);
            }

#if !ORTCLIB
            Debug.WriteLine("Conductor: Adding local media stream.");
            _peerConnection.AddStream(_mediaStream);
#endif
            OnAddLocalStream?.Invoke(new MediaStreamEvent()
            {
                Stream = _mediaStream
            });

            if (cancelationToken.IsCancellationRequested)
            {
                return(false);
            }
            return(true);
        }
示例#15
0
        private StreamInfo BuildAudioItem(MediaSourceInfo item, AudioOptions options)
        {
            StreamInfo playlistItem = new StreamInfo
            {
                ItemId       = options.ItemId,
                MediaType    = DlnaProfileType.Audio,
                MediaSource  = item,
                RunTimeTicks = item.RunTimeTicks
            };

            int?maxBitrateSetting = options.GetMaxBitrate();

            MediaStream audioStream = item.DefaultAudioStream;

            // Honor the max bitrate setting
            if (IsAudioEligibleForDirectPlay(item, maxBitrateSetting))
            {
                DirectPlayProfile directPlay = null;
                foreach (DirectPlayProfile i in options.Profile.DirectPlayProfiles)
                {
                    if (i.Type == playlistItem.MediaType && IsAudioDirectPlaySupported(i, item, audioStream))
                    {
                        directPlay = i;
                        break;
                    }
                }

                if (directPlay != null)
                {
                    string audioCodec = audioStream == null ? null : audioStream.Codec;

                    // Make sure audio codec profiles are satisfied
                    if (!string.IsNullOrEmpty(audioCodec))
                    {
                        ConditionProcessor conditionProcessor = new ConditionProcessor();

                        List <ProfileCondition> conditions = new List <ProfileCondition>();
                        foreach (CodecProfile i in options.Profile.CodecProfiles)
                        {
                            if (i.Type == CodecType.Audio && i.ContainsCodec(audioCodec))
                            {
                                foreach (ProfileCondition c in i.Conditions)
                                {
                                    conditions.Add(c);
                                }
                            }
                        }

                        int?audioChannels = audioStream.Channels;
                        int?audioBitrate  = audioStream.BitRate;

                        bool all = true;
                        foreach (ProfileCondition c in conditions)
                        {
                            if (!conditionProcessor.IsAudioConditionSatisfied(c, audioChannels, audioBitrate))
                            {
                                all = false;
                                break;
                            }
                        }

                        if (all)
                        {
                            playlistItem.PlayMethod = PlayMethod.DirectStream;
                            playlistItem.Container  = item.Container;

                            return(playlistItem);
                        }
                    }
                }
            }

            TranscodingProfile transcodingProfile = null;

            foreach (TranscodingProfile i in options.Profile.TranscodingProfiles)
            {
                if (i.Type == playlistItem.MediaType && i.Context == options.Context)
                {
                    transcodingProfile = i;
                    break;
                }
            }

            if (transcodingProfile != null)
            {
                playlistItem.PlayMethod            = PlayMethod.Transcode;
                playlistItem.TranscodeSeekInfo     = transcodingProfile.TranscodeSeekInfo;
                playlistItem.EstimateContentLength = transcodingProfile.EstimateContentLength;
                playlistItem.Container             = transcodingProfile.Container;
                playlistItem.AudioCodec            = transcodingProfile.AudioCodec;
                playlistItem.Protocol = transcodingProfile.Protocol;

                List <CodecProfile> audioCodecProfiles = new List <CodecProfile>();
                foreach (CodecProfile i in options.Profile.CodecProfiles)
                {
                    if (i.Type == CodecType.Audio && i.ContainsCodec(transcodingProfile.AudioCodec))
                    {
                        audioCodecProfiles.Add(i);
                    }

                    if (audioCodecProfiles.Count >= 1)
                    {
                        break;
                    }
                }

                List <ProfileCondition> audioTranscodingConditions = new List <ProfileCondition>();
                foreach (CodecProfile i in audioCodecProfiles)
                {
                    foreach (ProfileCondition c in i.Conditions)
                    {
                        audioTranscodingConditions.Add(c);
                    }
                }

                ApplyTranscodingConditions(playlistItem, audioTranscodingConditions);

                // Honor requested max channels
                if (options.MaxAudioChannels.HasValue)
                {
                    int currentValue = playlistItem.MaxAudioChannels ?? options.MaxAudioChannels.Value;

                    playlistItem.MaxAudioChannels = Math.Min(options.MaxAudioChannels.Value, currentValue);
                }

                int configuredBitrate = options.AudioTranscodingBitrate ??
                                        (options.Context == EncodingContext.Static ? options.Profile.MusicSyncBitrate : options.Profile.MusicStreamingTranscodingBitrate) ??
                                        128000;

                playlistItem.AudioBitrate = Math.Min(configuredBitrate, playlistItem.AudioBitrate ?? configuredBitrate);
            }

            return(playlistItem);
        }
示例#16
0
        private StreamInfo BuildVideoItem(MediaSourceInfo item, VideoOptions options)
        {
            StreamInfo playlistItem = new StreamInfo
            {
                ItemId        = options.ItemId,
                MediaType     = DlnaProfileType.Video,
                MediaSource   = item,
                RunTimeTicks  = item.RunTimeTicks,
                Context       = options.Context,
                DeviceProfile = options.Profile
            };

            playlistItem.SubtitleStreamIndex = options.SubtitleStreamIndex ?? GetDefaultSubtitleStreamIndex(item, options.Profile.SubtitleProfiles);
            MediaStream subtitleStream = playlistItem.SubtitleStreamIndex.HasValue ? item.GetMediaStream(MediaStreamType.Subtitle, playlistItem.SubtitleStreamIndex.Value) : null;

            MediaStream audioStream      = item.GetDefaultAudioStream(options.AudioStreamIndex ?? item.DefaultAudioStreamIndex);
            int?        audioStreamIndex = null;

            if (audioStream != null)
            {
                audioStreamIndex = audioStream.Index;
            }

            MediaStream videoStream = item.VideoStream;

            // TODO: This doesn't accout for situation of device being able to handle media bitrate, but wifi connection not fast enough
            bool isEligibleForDirectPlay   = IsEligibleForDirectPlay(item, GetBitrateForDirectPlayCheck(item, options), subtitleStream, options);
            bool isEligibleForDirectStream = IsEligibleForDirectPlay(item, options.GetMaxBitrate(), subtitleStream, options);

            _logger.Debug("Profile: {0}, Path: {1}, isEligibleForDirectPlay: {2}, isEligibleForDirectStream: {3}",
                          options.Profile.Name ?? "Unknown Profile",
                          item.Path ?? "Unknown path",
                          isEligibleForDirectPlay,
                          isEligibleForDirectStream);

            if (isEligibleForDirectPlay || isEligibleForDirectStream)
            {
                // See if it can be direct played
                PlayMethod?directPlay = GetVideoDirectPlayProfile(options.Profile, item, videoStream, audioStream, isEligibleForDirectPlay, isEligibleForDirectStream);

                if (directPlay != null)
                {
                    playlistItem.PlayMethod = directPlay.Value;
                    playlistItem.Container  = item.Container;

                    if (subtitleStream != null)
                    {
                        SubtitleProfile subtitleProfile = GetSubtitleProfile(subtitleStream, options.Profile.SubtitleProfiles, options.Context);

                        playlistItem.SubtitleDeliveryMethod = subtitleProfile.Method;
                        playlistItem.SubtitleFormat         = subtitleProfile.Format;
                    }

                    return(playlistItem);
                }
            }

            // Can't direct play, find the transcoding profile
            TranscodingProfile transcodingProfile = null;

            foreach (TranscodingProfile i in options.Profile.TranscodingProfiles)
            {
                if (i.Type == playlistItem.MediaType && i.Context == options.Context)
                {
                    transcodingProfile = i;
                    break;
                }
            }

            if (transcodingProfile != null)
            {
                if (!item.SupportsTranscoding)
                {
                    return(null);
                }

                if (subtitleStream != null)
                {
                    SubtitleProfile subtitleProfile = GetSubtitleProfile(subtitleStream, options.Profile.SubtitleProfiles, options.Context);

                    playlistItem.SubtitleDeliveryMethod = subtitleProfile.Method;
                    playlistItem.SubtitleFormat         = subtitleProfile.Format;
                }

                playlistItem.PlayMethod            = PlayMethod.Transcode;
                playlistItem.Container             = transcodingProfile.Container;
                playlistItem.EstimateContentLength = transcodingProfile.EstimateContentLength;
                playlistItem.TranscodeSeekInfo     = transcodingProfile.TranscodeSeekInfo;
                playlistItem.AudioCodec            = transcodingProfile.AudioCodec.Split(',')[0];
                playlistItem.VideoCodec            = transcodingProfile.VideoCodec;
                playlistItem.SubProtocol           = transcodingProfile.Protocol;
                playlistItem.AudioStreamIndex      = audioStreamIndex;

                List <ProfileCondition> videoTranscodingConditions = new List <ProfileCondition>();
                foreach (CodecProfile i in options.Profile.CodecProfiles)
                {
                    if (i.Type == CodecType.Video && i.ContainsCodec(transcodingProfile.VideoCodec))
                    {
                        foreach (ProfileCondition c in i.Conditions)
                        {
                            videoTranscodingConditions.Add(c);
                        }
                        break;
                    }
                }
                ApplyTranscodingConditions(playlistItem, videoTranscodingConditions);

                List <ProfileCondition> audioTranscodingConditions = new List <ProfileCondition>();
                foreach (CodecProfile i in options.Profile.CodecProfiles)
                {
                    if (i.Type == CodecType.VideoAudio && i.ContainsCodec(transcodingProfile.AudioCodec))
                    {
                        foreach (ProfileCondition c in i.Conditions)
                        {
                            audioTranscodingConditions.Add(c);
                        }
                        break;
                    }
                }
                ApplyTranscodingConditions(playlistItem, audioTranscodingConditions);

                // Honor requested max channels
                if (options.MaxAudioChannels.HasValue)
                {
                    int currentValue = playlistItem.MaxAudioChannels ?? options.MaxAudioChannels.Value;

                    playlistItem.MaxAudioChannels = Math.Min(options.MaxAudioChannels.Value, currentValue);
                }

                if (!playlistItem.AudioBitrate.HasValue)
                {
                    playlistItem.AudioBitrate = GetAudioBitrate(playlistItem.TargetAudioChannels, playlistItem.TargetAudioCodec);
                }

                int?maxBitrateSetting = options.GetMaxBitrate();
                // Honor max rate
                if (maxBitrateSetting.HasValue)
                {
                    int videoBitrate = maxBitrateSetting.Value;

                    if (playlistItem.AudioBitrate.HasValue)
                    {
                        videoBitrate -= playlistItem.AudioBitrate.Value;
                    }

                    int currentValue = playlistItem.VideoBitrate ?? videoBitrate;

                    playlistItem.VideoBitrate = Math.Min(videoBitrate, currentValue);
                }
            }

            return(playlistItem);
        }
示例#17
0
        private StreamInfo BuildAudioItem(MediaSourceInfo item, AudioOptions options)
        {
            StreamInfo playlistItem = new StreamInfo
            {
                ItemId        = options.ItemId,
                MediaType     = DlnaProfileType.Audio,
                MediaSource   = item,
                RunTimeTicks  = item.RunTimeTicks,
                Context       = options.Context,
                DeviceProfile = options.Profile
            };

            MediaStream audioStream = item.GetDefaultAudioStream(null);

            List <PlayMethod> directPlayMethods = GetAudioDirectPlayMethods(item, audioStream, options);

            if (directPlayMethods.Count > 0)
            {
                string audioCodec = audioStream == null ? null : audioStream.Codec;

                // Make sure audio codec profiles are satisfied
                if (!string.IsNullOrEmpty(audioCodec))
                {
                    ConditionProcessor conditionProcessor = new ConditionProcessor();

                    List <ProfileCondition> conditions = new List <ProfileCondition>();
                    foreach (CodecProfile i in options.Profile.CodecProfiles)
                    {
                        if (i.Type == CodecType.Audio && i.ContainsCodec(audioCodec))
                        {
                            foreach (ProfileCondition c in i.Conditions)
                            {
                                conditions.Add(c);
                            }
                        }
                    }

                    int?audioChannels = audioStream.Channels;
                    int?audioBitrate  = audioStream.BitRate;

                    bool all = true;
                    foreach (ProfileCondition c in conditions)
                    {
                        if (!conditionProcessor.IsAudioConditionSatisfied(c, audioChannels, audioBitrate))
                        {
                            all = false;
                            break;
                        }
                    }

                    if (all)
                    {
                        if (item.Protocol == MediaProtocol.File &&
                            directPlayMethods.Contains(PlayMethod.DirectPlay) &&
                            _localPlayer.CanAccessFile(item.Path))
                        {
                            playlistItem.PlayMethod = PlayMethod.DirectPlay;
                        }
                        else if (item.Protocol == MediaProtocol.Http &&
                                 directPlayMethods.Contains(PlayMethod.DirectPlay) &&
                                 _localPlayer.CanAccessUrl(item.Path, item.RequiredHttpHeaders.Count > 0))
                        {
                            playlistItem.PlayMethod = PlayMethod.DirectPlay;
                        }
                        else if (directPlayMethods.Contains(PlayMethod.DirectStream))
                        {
                            playlistItem.PlayMethod = PlayMethod.DirectStream;
                        }

                        playlistItem.Container = item.Container;

                        return(playlistItem);
                    }
                }
            }

            TranscodingProfile transcodingProfile = null;

            foreach (TranscodingProfile i in options.Profile.TranscodingProfiles)
            {
                if (i.Type == playlistItem.MediaType && i.Context == options.Context)
                {
                    transcodingProfile = i;
                    break;
                }
            }

            if (transcodingProfile != null)
            {
                if (!item.SupportsTranscoding)
                {
                    return(null);
                }

                playlistItem.PlayMethod            = PlayMethod.Transcode;
                playlistItem.TranscodeSeekInfo     = transcodingProfile.TranscodeSeekInfo;
                playlistItem.EstimateContentLength = transcodingProfile.EstimateContentLength;
                playlistItem.Container             = transcodingProfile.Container;
                playlistItem.AudioCodec            = transcodingProfile.AudioCodec;
                playlistItem.SubProtocol           = transcodingProfile.Protocol;

                List <CodecProfile> audioCodecProfiles = new List <CodecProfile>();
                foreach (CodecProfile i in options.Profile.CodecProfiles)
                {
                    if (i.Type == CodecType.Audio && i.ContainsCodec(transcodingProfile.AudioCodec))
                    {
                        audioCodecProfiles.Add(i);
                    }

                    if (audioCodecProfiles.Count >= 1)
                    {
                        break;
                    }
                }

                List <ProfileCondition> audioTranscodingConditions = new List <ProfileCondition>();
                foreach (CodecProfile i in audioCodecProfiles)
                {
                    foreach (ProfileCondition c in i.Conditions)
                    {
                        audioTranscodingConditions.Add(c);
                    }
                }

                ApplyTranscodingConditions(playlistItem, audioTranscodingConditions);

                // Honor requested max channels
                if (options.MaxAudioChannels.HasValue)
                {
                    int currentValue = playlistItem.MaxAudioChannels ?? options.MaxAudioChannels.Value;

                    playlistItem.MaxAudioChannels = Math.Min(options.MaxAudioChannels.Value, currentValue);
                }

                int configuredBitrate = options.AudioTranscodingBitrate ??
                                        (options.Context == EncodingContext.Static ? options.Profile.MusicSyncBitrate : options.Profile.MusicStreamingTranscodingBitrate) ??
                                        128000;

                playlistItem.AudioBitrate = Math.Min(configuredBitrate, playlistItem.AudioBitrate ?? configuredBitrate);
            }

            return(playlistItem);
        }
示例#18
0
        private async Task <Tuple <string, MediaProtocol, string, bool> > GetReadableFile(string mediaPath,
                                                                                          string[] inputFiles,
                                                                                          MediaProtocol protocol,
                                                                                          MediaStream subtitleStream,
                                                                                          CancellationToken cancellationToken)
        {
            if (!subtitleStream.IsExternal)
            {
                string outputFormat;
                string outputCodec;

                if (string.Equals(subtitleStream.Codec, "ass", StringComparison.OrdinalIgnoreCase) ||
                    string.Equals(subtitleStream.Codec, "ssa", StringComparison.OrdinalIgnoreCase) ||
                    string.Equals(subtitleStream.Codec, "srt", StringComparison.OrdinalIgnoreCase))
                {
                    // Extract
                    outputCodec  = "copy";
                    outputFormat = subtitleStream.Codec;
                }
                else if (string.Equals(subtitleStream.Codec, "subrip", StringComparison.OrdinalIgnoreCase))
                {
                    // Extract
                    outputCodec  = "copy";
                    outputFormat = "srt";
                }
                else
                {
                    // Extract
                    outputCodec  = "srt";
                    outputFormat = "srt";
                }

                // Extract
                var outputPath = GetSubtitleCachePath(mediaPath, protocol, subtitleStream.Index, "." + outputFormat);

                await ExtractTextSubtitle(inputFiles, protocol, subtitleStream.Index, outputCodec, outputPath, cancellationToken)
                .ConfigureAwait(false);

                return(new Tuple <string, MediaProtocol, string, bool>(outputPath, MediaProtocol.File, outputFormat, false));
            }

            var currentFormat = (Path.GetExtension(subtitleStream.Path) ?? subtitleStream.Codec)
                                .TrimStart('.');

            if (GetReader(currentFormat, false) == null)
            {
                // Convert
                var outputPath = GetSubtitleCachePath(mediaPath, protocol, subtitleStream.Index, ".srt");

                await ConvertTextSubtitleToSrt(subtitleStream.Path, subtitleStream.Language, protocol, outputPath, cancellationToken).ConfigureAwait(false);

                return(new Tuple <string, MediaProtocol, string, bool>(outputPath, MediaProtocol.File, "srt", true));
            }

            return(new Tuple <string, MediaProtocol, string, bool>(subtitleStream.Path, protocol, currentFormat, true));
        }
示例#19
0
        public IActionResult index()
        {
            string accountMessage = string.Empty;

            MediaStream[] mediaStreams = new MediaStream[] { };

            string authToken   = GetAuthToken(this.Request, this.Response);
            string queryString = this.Request.QueryString.Value.ToLower();

            if (this.Request.HasFormContentType)
            {
                RedirectToActionResult redirectAction = Startup.OnSignIn(this, authToken);
                if (redirectAction != null)
                {
                    return(redirectAction);
                }
            }

            int    streamNumber = 1;
            string autoPlay     = "false";

            if (queryString.Contains("stream"))
            {
                streamNumber = int.Parse(this.Request.Query["stream"]);
                autoPlay     = "true";
            }

            int streamOffset = 0;
            int streamIndex  = streamNumber - 1;

            try
            {
                if (string.IsNullOrEmpty(authToken))
                {
                    mediaStreams = Media.GetMediaStreams();
                }
                else
                {
                    MediaClient mediaClient = new MediaClient(authToken);
                    if (!Account.IsStreamingEnabled(mediaClient, out bool endpointStarting))
                    {
                        accountMessage = endpointStarting ? Constant.Message.StreamingEndpointStarting : Constant.Message.StreamingEndpointNotRunning;
                    }
                    else
                    {
                        mediaStreams = Media.GetMediaStreams(authToken, mediaClient, streamNumber, out streamOffset, out streamIndex, out bool endOfStreams);
                        if (endOfStreams)
                        {
                            streamNumber = streamNumber - 1;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                accountMessage = ex.ToString();
            }
            ViewData["accountMessage"] = accountMessage;

            ViewData["mediaStreams"] = mediaStreams;
            ViewData["streamNumber"] = streamNumber;

            ViewData["streamOffset"] = streamOffset;
            ViewData["streamIndex"]  = streamIndex;

            ViewData["languageCode"] = this.Request.Query["language"];
            ViewData["autoPlay"]     = autoPlay;

            return(View());
        }
 /// <summary>
 /// Determines whether the specified stream is H264.
 /// </summary>
 /// <param name="stream">The stream.</param>
 /// <returns><c>true</c> if the specified stream is H264; otherwise, <c>false</c>.</returns>
 protected bool IsH264(MediaStream stream)
 {
     return(stream.Codec.IndexOf("264", StringComparison.OrdinalIgnoreCase) != -1 ||
            stream.Codec.IndexOf("avc", StringComparison.OrdinalIgnoreCase) != -1);
 }
示例#21
0
        private DirectPlayProfile GetVideoDirectPlayProfile(DeviceProfile profile,
                                                            MediaSourceInfo mediaSource,
                                                            MediaStream videoStream,
                                                            MediaStream audioStream)
        {
            // See if it can be direct played
            DirectPlayProfile directPlay = null;

            foreach (DirectPlayProfile i in profile.DirectPlayProfiles)
            {
                if (i.Type == DlnaProfileType.Video && IsVideoDirectPlaySupported(i, mediaSource, videoStream, audioStream))
                {
                    directPlay = i;
                    break;
                }
            }

            if (directPlay == null)
            {
                return(null);
            }

            string container = mediaSource.Container;

            List <ProfileCondition> conditions = new List <ProfileCondition>();

            foreach (ContainerProfile i in profile.ContainerProfiles)
            {
                if (i.Type == DlnaProfileType.Video &&
                    ListHelper.ContainsIgnoreCase(i.GetContainers(), container))
                {
                    foreach (ProfileCondition c in i.Conditions)
                    {
                        conditions.Add(c);
                    }
                }
            }

            ConditionProcessor conditionProcessor = new ConditionProcessor();

            int?   width          = videoStream == null ? null : videoStream.Width;
            int?   height         = videoStream == null ? null : videoStream.Height;
            int?   bitDepth       = videoStream == null ? null : videoStream.BitDepth;
            int?   videoBitrate   = videoStream == null ? null : videoStream.BitRate;
            double?videoLevel     = videoStream == null ? null : videoStream.Level;
            string videoProfile   = videoStream == null ? null : videoStream.Profile;
            float? videoFramerate = videoStream == null ? null : videoStream.AverageFrameRate ?? videoStream.AverageFrameRate;
            bool?  isAnamorphic   = videoStream == null ? null : videoStream.IsAnamorphic;

            int?   audioBitrate  = audioStream == null ? null : audioStream.BitRate;
            int?   audioChannels = audioStream == null ? null : audioStream.Channels;
            string audioProfile  = audioStream == null ? null : audioStream.Profile;

            TransportStreamTimestamp?timestamp = videoStream == null ? TransportStreamTimestamp.None : mediaSource.Timestamp;
            int?packetLength = videoStream == null ? null : videoStream.PacketLength;
            int?refFrames    = videoStream == null ? null : videoStream.RefFrames;

            // Check container conditions
            foreach (ProfileCondition i in conditions)
            {
                if (!conditionProcessor.IsVideoConditionSatisfied(i, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, refFrames))
                {
                    return(null);
                }
            }

            string videoCodec = videoStream == null ? null : videoStream.Codec;

            if (string.IsNullOrEmpty(videoCodec))
            {
                return(null);
            }

            conditions = new List <ProfileCondition>();
            foreach (CodecProfile i in profile.CodecProfiles)
            {
                if (i.Type == CodecType.Video && i.ContainsCodec(videoCodec))
                {
                    foreach (ProfileCondition c in i.Conditions)
                    {
                        conditions.Add(c);
                    }
                }
            }

            foreach (ProfileCondition i in conditions)
            {
                if (!conditionProcessor.IsVideoConditionSatisfied(i, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, refFrames))
                {
                    return(null);
                }
            }

            if (audioStream != null)
            {
                string audioCodec = audioStream.Codec;

                if (string.IsNullOrEmpty(audioCodec))
                {
                    return(null);
                }

                conditions = new List <ProfileCondition>();
                foreach (CodecProfile i in profile.CodecProfiles)
                {
                    if (i.Type == CodecType.VideoAudio && i.ContainsCodec(audioCodec))
                    {
                        foreach (ProfileCondition c in i.Conditions)
                        {
                            conditions.Add(c);
                        }
                    }
                }

                foreach (ProfileCondition i in conditions)
                {
                    if (!conditionProcessor.IsVideoAudioConditionSatisfied(i, audioChannels, audioBitrate, audioProfile))
                    {
                        return(null);
                    }
                }
            }

            return(directPlay);
        }
示例#22
0
        private StreamInfo BuildVideoItem(MediaSourceInfo item, VideoOptions options)
        {
            StreamInfo playlistItem = new StreamInfo
            {
                ItemId       = options.ItemId,
                MediaType    = DlnaProfileType.Video,
                MediaSource  = item,
                RunTimeTicks = item.RunTimeTicks
            };

            int?audioStreamIndex = options.AudioStreamIndex ?? item.DefaultAudioStreamIndex;

            playlistItem.SubtitleStreamIndex = options.SubtitleStreamIndex ?? item.DefaultSubtitleStreamIndex;

            MediaStream audioStream    = audioStreamIndex.HasValue ? item.GetMediaStream(MediaStreamType.Audio, audioStreamIndex.Value) : null;
            MediaStream subtitleStream = playlistItem.SubtitleStreamIndex.HasValue ? item.GetMediaStream(MediaStreamType.Subtitle, playlistItem.SubtitleStreamIndex.Value) : null;

            MediaStream videoStream = item.VideoStream;

            int?maxBitrateSetting = options.GetMaxBitrate();

            if (IsEligibleForDirectPlay(item, maxBitrateSetting, subtitleStream, options))
            {
                // See if it can be direct played
                DirectPlayProfile directPlay = GetVideoDirectPlayProfile(options.Profile, item, videoStream, audioStream);

                if (directPlay != null)
                {
                    playlistItem.PlayMethod = PlayMethod.DirectStream;
                    playlistItem.Container  = item.Container;

                    if (subtitleStream != null)
                    {
                        playlistItem.SubtitleDeliveryMethod = GetSubtitleDeliveryMethod(subtitleStream, options);
                    }

                    return(playlistItem);
                }
            }

            // Can't direct play, find the transcoding profile
            TranscodingProfile transcodingProfile = null;

            foreach (TranscodingProfile i in options.Profile.TranscodingProfiles)
            {
                if (i.Type == playlistItem.MediaType && i.Context == options.Context)
                {
                    transcodingProfile = i;
                    break;
                }
            }

            if (transcodingProfile != null)
            {
                if (subtitleStream != null)
                {
                    playlistItem.SubtitleDeliveryMethod = GetSubtitleDeliveryMethod(subtitleStream, options);
                }

                playlistItem.PlayMethod            = PlayMethod.Transcode;
                playlistItem.Container             = transcodingProfile.Container;
                playlistItem.EstimateContentLength = transcodingProfile.EstimateContentLength;
                playlistItem.TranscodeSeekInfo     = transcodingProfile.TranscodeSeekInfo;
                playlistItem.AudioCodec            = transcodingProfile.AudioCodec.Split(',')[0];
                playlistItem.VideoCodec            = transcodingProfile.VideoCodec;
                playlistItem.Protocol         = transcodingProfile.Protocol;
                playlistItem.AudioStreamIndex = audioStreamIndex;

                List <ProfileCondition> videoTranscodingConditions = new List <ProfileCondition>();
                foreach (CodecProfile i in options.Profile.CodecProfiles)
                {
                    if (i.Type == CodecType.Video && i.ContainsCodec(transcodingProfile.VideoCodec))
                    {
                        foreach (ProfileCondition c in i.Conditions)
                        {
                            videoTranscodingConditions.Add(c);
                        }
                        break;
                    }
                }
                ApplyTranscodingConditions(playlistItem, videoTranscodingConditions);

                List <ProfileCondition> audioTranscodingConditions = new List <ProfileCondition>();
                foreach (CodecProfile i in options.Profile.CodecProfiles)
                {
                    if (i.Type == CodecType.VideoAudio && i.ContainsCodec(transcodingProfile.AudioCodec))
                    {
                        foreach (ProfileCondition c in i.Conditions)
                        {
                            audioTranscodingConditions.Add(c);
                        }
                        break;
                    }
                }
                ApplyTranscodingConditions(playlistItem, audioTranscodingConditions);

                // Honor requested max channels
                if (options.MaxAudioChannels.HasValue)
                {
                    int currentValue = playlistItem.MaxAudioChannels ?? options.MaxAudioChannels.Value;

                    playlistItem.MaxAudioChannels = Math.Min(options.MaxAudioChannels.Value, currentValue);
                }

                if (!playlistItem.AudioBitrate.HasValue)
                {
                    playlistItem.AudioBitrate = GetAudioBitrate(playlistItem.TargetAudioChannels, playlistItem.TargetAudioCodec);
                }

                // Honor max rate
                if (maxBitrateSetting.HasValue)
                {
                    int videoBitrate = maxBitrateSetting.Value;

                    if (playlistItem.AudioBitrate.HasValue)
                    {
                        videoBitrate -= playlistItem.AudioBitrate.Value;
                    }

                    int currentValue = playlistItem.VideoBitrate ?? videoBitrate;

                    playlistItem.VideoBitrate = Math.Min(videoBitrate, currentValue);
                }
            }

            return(playlistItem);
        }
		public virtual bool CanOptimize(MediaStream stream)
		{
			return SupportedExtensions.Any(ext => ext.Equals(stream.Extension, StringComparison.OrdinalIgnoreCase));
		}
        public SymplePlayerEngineWebRTC(SymplePlayer player) : base(player)
        {
            Messenger.Broadcast(SympleLog.LogDebug, "symple:webrtc: init");

#if NETFX_CORE
            if (!webrtcInitialized)
            {
                // needed before calling any webrtc functions http://stackoverflow.com/questions/43331677/webrtc-for-uwp-new-rtcpeerconnection-doesnt-complete-execution
                if (player.options.CoreDispatcher != null)
                {
                    WebRTC.Initialize(player.options.CoreDispatcher);
                }
                else
                {
                    WebRTC.Initialize(null);
                }


                WebRTC.EnableLogging(LogLevel.LOGLVL_ERROR);
                WebRTC.EnableLogging(LogLevel.LOGLVL_INFO);
                WebRTC.EnableLogging(LogLevel.LOGLVL_SENSITIVE);
                WebRTC.EnableLogging(LogLevel.LOGLVL_VERBOSE);
                WebRTC.EnableLogging(LogLevel.LOGLVL_WARNING);
                Messenger.Broadcast(SympleLog.LogInfo, "WebRTC logging enabled, log folder = " + WebRTC.LogFolder.Path + ", filename = " + WebRTC.LogFileName);
                webrtcInitialized = true;
            }

            this.userMediaConstraints = player.options.userMediaConstraints;

            if (player.options.rtcConfig != null)
            {
                this.rtcConfig = player.options.rtcConfig;
            }
            else
            {
                this.rtcConfig = new RTCConfiguration();
                this.rtcConfig.IceServers.Add(new RTCIceServer()
                {
                    Url = "stun:stun.l.google.com:19302", Username = string.Empty, Credential = string.Empty
                });
            }
#endif

            /*
             * this.rtcOptions = player.options.rtcOptions || {
             *  optional: [
             *      { DtlsSrtpKeyAgreement: true } // required for FF <=> Chrome interop
             *  ]
             * };
             */

            // Specifies that this client will be the ICE initiator,
            // and will be sending the initial SDP Offer.
            this.initiator = player.options.initiator;
            Messenger.Broadcast(SympleLog.LogDebug, "symple:webrtc: constructor, set this.initiator to " + this.initiator);

#if NETFX_CORE
            // Reference to the active local or remote media stream
            this.activeStream = null;
#endif
        }
示例#25
0
        private PlayMethod?GetVideoDirectPlayProfile(DeviceProfile profile,
                                                     MediaSourceInfo mediaSource,
                                                     MediaStream videoStream,
                                                     MediaStream audioStream,
                                                     bool isEligibleForDirectPlay,
                                                     bool isEligibleForDirectStream)
        {
            // See if it can be direct played
            DirectPlayProfile directPlay = null;

            foreach (DirectPlayProfile i in profile.DirectPlayProfiles)
            {
                if (i.Type == DlnaProfileType.Video && IsVideoDirectPlaySupported(i, mediaSource, videoStream, audioStream))
                {
                    directPlay = i;
                    break;
                }
            }

            if (directPlay == null)
            {
                _logger.Debug("Profile: {0}, No direct play profiles found for Path: {1}",
                              profile.Name ?? "Unknown Profile",
                              mediaSource.Path ?? "Unknown path");

                return(null);
            }

            string container = mediaSource.Container;

            List <ProfileCondition> conditions = new List <ProfileCondition>();

            foreach (ContainerProfile i in profile.ContainerProfiles)
            {
                if (i.Type == DlnaProfileType.Video &&
                    ListHelper.ContainsIgnoreCase(i.GetContainers(), container))
                {
                    foreach (ProfileCondition c in i.Conditions)
                    {
                        conditions.Add(c);
                    }
                }
            }

            ConditionProcessor conditionProcessor = new ConditionProcessor();

            int?   width          = videoStream == null ? null : videoStream.Width;
            int?   height         = videoStream == null ? null : videoStream.Height;
            int?   bitDepth       = videoStream == null ? null : videoStream.BitDepth;
            int?   videoBitrate   = videoStream == null ? null : videoStream.BitRate;
            double?videoLevel     = videoStream == null ? null : videoStream.Level;
            string videoProfile   = videoStream == null ? null : videoStream.Profile;
            float? videoFramerate = videoStream == null ? null : videoStream.AverageFrameRate ?? videoStream.AverageFrameRate;
            bool?  isAnamorphic   = videoStream == null ? null : videoStream.IsAnamorphic;
            bool?  isCabac        = videoStream == null ? null : videoStream.IsCabac;

            int?   audioBitrate  = audioStream == null ? null : audioStream.BitRate;
            int?   audioChannels = audioStream == null ? null : audioStream.Channels;
            string audioProfile  = audioStream == null ? null : audioStream.Profile;

            TransportStreamTimestamp?timestamp = videoStream == null ? TransportStreamTimestamp.None : mediaSource.Timestamp;
            int?packetLength = videoStream == null ? null : videoStream.PacketLength;
            int?refFrames    = videoStream == null ? null : videoStream.RefFrames;

            int?numAudioStreams = mediaSource.GetStreamCount(MediaStreamType.Audio);
            int?numVideoStreams = mediaSource.GetStreamCount(MediaStreamType.Video);

            // Check container conditions
            foreach (ProfileCondition i in conditions)
            {
                if (!conditionProcessor.IsVideoConditionSatisfied(i, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isCabac, refFrames, numVideoStreams, numAudioStreams))
                {
                    LogConditionFailure(profile, "VideoContainerProfile", i, mediaSource);

                    return(null);
                }
            }

            string videoCodec = videoStream == null ? null : videoStream.Codec;

            if (string.IsNullOrEmpty(videoCodec))
            {
                _logger.Debug("Profile: {0}, DirectPlay=false. Reason=Unknown video codec. Path: {1}",
                              profile.Name ?? "Unknown Profile",
                              mediaSource.Path ?? "Unknown path");

                return(null);
            }

            conditions = new List <ProfileCondition>();
            foreach (CodecProfile i in profile.CodecProfiles)
            {
                if (i.Type == CodecType.Video && i.ContainsCodec(videoCodec))
                {
                    foreach (ProfileCondition c in i.Conditions)
                    {
                        conditions.Add(c);
                    }
                }
            }

            foreach (ProfileCondition i in conditions)
            {
                if (!conditionProcessor.IsVideoConditionSatisfied(i, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isCabac, refFrames, numVideoStreams, numAudioStreams))
                {
                    LogConditionFailure(profile, "VideoCodecProfile", i, mediaSource);

                    return(null);
                }
            }

            if (audioStream != null)
            {
                string audioCodec = audioStream.Codec;

                if (string.IsNullOrEmpty(audioCodec))
                {
                    _logger.Debug("Profile: {0}, DirectPlay=false. Reason=Unknown audio codec. Path: {1}",
                                  profile.Name ?? "Unknown Profile",
                                  mediaSource.Path ?? "Unknown path");

                    return(null);
                }

                conditions = new List <ProfileCondition>();
                foreach (CodecProfile i in profile.CodecProfiles)
                {
                    if (i.Type == CodecType.VideoAudio && i.ContainsCodec(audioCodec))
                    {
                        foreach (ProfileCondition c in i.Conditions)
                        {
                            conditions.Add(c);
                        }
                    }
                }

                foreach (ProfileCondition i in conditions)
                {
                    bool?isSecondaryAudio = audioStream == null ? null : mediaSource.IsSecondaryAudio(audioStream);
                    if (!conditionProcessor.IsVideoAudioConditionSatisfied(i, audioChannels, audioBitrate, audioProfile, isSecondaryAudio))
                    {
                        LogConditionFailure(profile, "VideoAudioCodecProfile", i, mediaSource);

                        return(null);
                    }
                }
            }

            if (isEligibleForDirectPlay)
            {
                if (mediaSource.Protocol == MediaProtocol.Http)
                {
                    if (_localPlayer.CanAccessUrl(mediaSource.Path, mediaSource.RequiredHttpHeaders.Count > 0))
                    {
                        return(PlayMethod.DirectPlay);
                    }
                }

                else if (mediaSource.Protocol == MediaProtocol.File)
                {
                    if (_localPlayer.CanAccessFile(mediaSource.Path))
                    {
                        return(PlayMethod.DirectPlay);
                    }
                }
            }

            if (isEligibleForDirectStream)
            {
                if (mediaSource.SupportsDirectStream)
                {
                    return(PlayMethod.DirectStream);
                }
            }

            return(null);
        }
示例#26
0
        private IEnumerable <IntroInfo> GetMediaInfoIntrosByAudioStream(List <IntroInfo> allIntros, MediaStream stream)
        {
            var codec = stream.Codec;

            if (string.IsNullOrWhiteSpace(codec))
            {
                return(new List <IntroInfo>());
            }

            return(allIntros
                   .Where(i => IsAudioMatch(i.Path, stream)));
        }
示例#27
0
        public static SubtitleProfile GetSubtitleProfile(MediaStream subtitleStream, SubtitleProfile[] subtitleProfiles, EncodingContext context)
        {
            // Look for an external profile that matches the stream type (text/graphical)
            foreach (SubtitleProfile profile in subtitleProfiles)
            {
                bool requiresConversion = !StringHelper.EqualsIgnoreCase(subtitleStream.Codec, profile.Format);

                if (!profile.SupportsLanguage(subtitleStream.Language))
                {
                    continue;
                }

                if (profile.Method == SubtitleDeliveryMethod.External && subtitleStream.IsTextSubtitleStream == MediaStream.IsTextFormat(profile.Format))
                {
                    if (!requiresConversion)
                    {
                        return(profile);
                    }

                    if (subtitleStream.SupportsExternalStream)
                    {
                        return(profile);
                    }

                    // For sync we can handle the longer extraction times
                    if (context == EncodingContext.Static && subtitleStream.IsTextSubtitleStream)
                    {
                        return(profile);
                    }
                }
            }

            foreach (SubtitleProfile profile in subtitleProfiles)
            {
                bool requiresConversion = !StringHelper.EqualsIgnoreCase(subtitleStream.Codec, profile.Format);

                if (!profile.SupportsLanguage(subtitleStream.Language))
                {
                    continue;
                }

                if (profile.Method == SubtitleDeliveryMethod.Embed && subtitleStream.IsTextSubtitleStream == MediaStream.IsTextFormat(profile.Format))
                {
                    if (!requiresConversion)
                    {
                        return(profile);
                    }

                    return(profile);
                }
            }

            return(new SubtitleProfile
            {
                Method = SubtitleDeliveryMethod.Encode,
                Format = subtitleStream.Codec
            });
        }
示例#28
0
        private static void ProcessMediaUpload(Stream content, Database db, string path, bool skipExisting = false)
        {
            var guidPattern = @"(?<id>{[a-z0-9]{8}[-][a-z0-9]{4}[-][a-z0-9]{4}[-][a-z0-9]{4}[-][a-z0-9]{12}})";

            path = path.Replace('\\', '/').TrimEnd('/');
            path = (path.StartsWith("/") ? path : "/" + path);
            var originalPath = path;
            var dotIndex     = path.IndexOf(".", StringComparison.OrdinalIgnoreCase);

            if (dotIndex > -1)
            {
                path = path.Substring(0, dotIndex);
            }

            if (!path.StartsWith(Constants.MediaLibraryPath))
            {
                path = Constants.MediaLibraryPath + (path.StartsWith("/") ? path : "/" + path);
            }

            var mediaItem = (MediaItem)db.GetItem(path);

            if (mediaItem == null && Regex.IsMatch(originalPath, guidPattern, RegexOptions.Compiled | RegexOptions.IgnoreCase))
            {
                var id = Regex.Match(originalPath, guidPattern, RegexOptions.Compiled | RegexOptions.IgnoreCase).Value;
                mediaItem = db.GetItem(id);
            }

            if (mediaItem == null)
            {
                var fileName = Path.GetFileName(originalPath);
                var itemName = Path.GetFileNameWithoutExtension(path);
                var dirName  = (Path.GetDirectoryName(path) ?? string.Empty).Replace('\\', '/');

                if (String.IsNullOrEmpty(fileName))
                {
                    PowerShellLog.Warn($"The filename cannot be determined for the entry {fileName}.");
                    return;
                }

                var mco = new MediaCreatorOptions
                {
                    Database    = db,
                    Versioned   = Settings.Media.UploadAsVersionableByDefault,
                    Destination = $"{dirName}/{itemName}",
                };

                var mc = new MediaCreator();
                using (var ms = new MemoryStream())
                {
                    content.CopyTo(ms);
                    mc.CreateFromStream(ms, fileName, mco);
                }
            }
            else
            {
                if (skipExisting)
                {
                    return;
                }

                var mediaUri = MediaUri.Parse(mediaItem);
                var media    = MediaManager.GetMedia(mediaUri);

                using (var ms = new MemoryStream())
                {
                    content.CopyTo(ms);
                    using (new EditContext(mediaItem, SecurityCheck.Disable))
                    {
                        using (var mediaStream = new MediaStream(ms, media.Extension, mediaItem))
                        {
                            media.SetStream(mediaStream);
                        }
                    }
                }
            }
        }
示例#29
0
        private bool IsAudioDirectPlaySupported(DirectPlayProfile profile, MediaSourceInfo item, MediaStream audioStream)
        {
            if (profile.Container.Length > 0)
            {
                // Check container type
                string mediaContainer = item.Container ?? string.Empty;
                bool   any            = false;
                foreach (string i in profile.GetContainers())
                {
                    if (StringHelper.EqualsIgnoreCase(i, mediaContainer))
                    {
                        any = true;
                        break;
                    }
                }
                if (!any)
                {
                    return(false);
                }
            }

            return(true);
        }
示例#30
0
    public async Task <Command> ForError(
        string ffmpegPath,
        Channel channel,
        Option <TimeSpan> duration,
        string errorMessage,
        bool hlsRealtime,
        long ptsOffset)
    {
        FFmpegPlaybackSettings playbackSettings =
            _playbackSettingsCalculator.CalculateErrorSettings(channel.FFmpegProfile);

        IDisplaySize desiredResolution = channel.FFmpegProfile.Resolution;

        var fontSize = (int)Math.Round(channel.FFmpegProfile.Resolution.Height / 20.0);
        var margin   = (int)Math.Round(channel.FFmpegProfile.Resolution.Height * 0.05);

        string subtitleFile = await new SubtitleBuilder(_tempFilePool)
                              .WithResolution(desiredResolution)
                              .WithFontName("Roboto")
                              .WithFontSize(fontSize)
                              .WithAlignment(2)
                              .WithMarginV(margin)
                              .WithPrimaryColor("&HFFFFFF")
                              .WithFormattedContent(errorMessage.Replace(Environment.NewLine, "\\N"))
                              .BuildFile();

        var videoStream = new MediaStream {
            Index = 0
        };
        var audioStream = new MediaStream {
            Index = 0
        };

        string videoCodec = playbackSettings.VideoFormat switch
        {
            FFmpegProfileVideoFormat.Hevc => "libx265",
            FFmpegProfileVideoFormat.Mpeg2Video => "mpeg2video",
            _ => "libx264"
        };

        string audioCodec = playbackSettings.AudioFormat switch
        {
            FFmpegProfileAudioFormat.Ac3 => "ac3",
            _ => "aac"
        };

        FFmpegProcessBuilder builder = new FFmpegProcessBuilder(ffmpegPath, false, _logger)
                                       .WithThreads(1)
                                       .WithQuiet()
                                       .WithFormatFlags(playbackSettings.FormatFlags)
                                       .WithRealtimeOutput(playbackSettings.RealtimeOutput)
                                       .WithLoopedImage(Path.Combine(FileSystemLayout.ResourcesCacheFolder, "background.png"))
                                       .WithLibavfilter()
                                       .WithInput("anullsrc")
                                       .WithSubtitleFile(subtitleFile)
                                       .WithFilterComplex(
            videoStream,
            audioStream,
            Path.Combine(FileSystemLayout.ResourcesCacheFolder, "background.png"),
            "fake-audio-path",
            playbackSettings.VideoFormat)
                                       .WithPixfmt("yuv420p")
                                       .WithPlaybackArgs(playbackSettings, videoCodec, audioCodec)
                                       .WithMetadata(channel, None);

        await duration.IfSomeAsync(d => builder = builder.WithDuration(d));

        Process process = channel.StreamingMode switch
        {
            // HLS needs to segment and generate playlist
            StreamingMode.HttpLiveStreamingSegmenter =>
            builder.WithHls(
                channel.Number,
                None,
                ptsOffset,
                playbackSettings.VideoTrackTimeScale,
                playbackSettings.FrameRate)
            .Build(),
            _ => builder.WithFormat("mpegts")
            .WithPipe()
            .Build()
        };

        return(Cli.Wrap(process.StartInfo.FileName)
               .WithArguments(process.StartInfo.ArgumentList)
               .WithValidation(CommandResultValidation.None)
               .WithEnvironmentVariables(process.StartInfo.Environment.ToDictionary(kvp => kvp.Key, kvp => kvp.Value))
               .WithStandardErrorPipe(PipeTarget.ToStream(Stream.Null)));
    }
示例#31
0
        private bool IsVideoDirectPlaySupported(DirectPlayProfile profile, MediaSourceInfo item, MediaStream videoStream, MediaStream audioStream)
        {
            if (profile.Container.Length > 0)
            {
                // Check container type
                string mediaContainer = item.Container ?? string.Empty;
                bool   any            = false;
                foreach (string i in profile.GetContainers())
                {
                    if (StringHelper.EqualsIgnoreCase(i, mediaContainer))
                    {
                        any = true;
                        break;
                    }
                }
                if (!any)
                {
                    return(false);
                }
            }

            // Check video codec
            List <string> videoCodecs = profile.GetVideoCodecs();

            if (videoCodecs.Count > 0)
            {
                string videoCodec = videoStream == null ? null : videoStream.Codec;
                if (string.IsNullOrEmpty(videoCodec) || !ListHelper.ContainsIgnoreCase(videoCodecs, videoCodec))
                {
                    return(false);
                }
            }

            List <string> audioCodecs = profile.GetAudioCodecs();

            if (audioCodecs.Count > 0)
            {
                // Check audio codecs
                string audioCodec = audioStream == null ? null : audioStream.Codec;
                if (string.IsNullOrEmpty(audioCodec) || !ListHelper.ContainsIgnoreCase(audioCodecs, audioCodec))
                {
                    return(false);
                }
            }

            return(true);
        }
示例#32
0
 public Task <string> ExtractVideoImage(string[] inputFiles, string container, MediaProtocol protocol, MediaStream videoStream, Video3DFormat?threedFormat, TimeSpan?offset, CancellationToken cancellationToken)
 {
     return(ExtractImage(inputFiles, container, videoStream, null, protocol, false, threedFormat, offset, cancellationToken));
 }
示例#33
0
 public Task <string> ExtractVideoImage(string[] inputFiles, string container, MediaProtocol protocol, MediaStream imageStream, int?imageStreamIndex, CancellationToken cancellationToken)
 {
     return(ExtractImage(inputFiles, container, imageStream, imageStreamIndex, protocol, false, null, null, cancellationToken));
 }
示例#34
0
        private async Task <string> ExtractImage(string[] inputFiles, string container, MediaStream videoStream, int?imageStreamIndex, MediaProtocol protocol, bool isAudio,
                                                 Video3DFormat?threedFormat, TimeSpan?offset, CancellationToken cancellationToken)
        {
            var inputArgument = GetInputArgument(inputFiles, protocol);

            if (isAudio)
            {
                if (imageStreamIndex.HasValue && imageStreamIndex.Value > 0)
                {
                    // It seems for audio files we need to subtract 1 (for the audio stream??)
                    imageStreamIndex = imageStreamIndex.Value - 1;
                }
            }
            else
            {
                try
                {
                    return(await ExtractImageInternal(inputArgument, container, videoStream, imageStreamIndex, threedFormat, offset, true, cancellationToken).ConfigureAwait(false));
                }
                catch (ArgumentException)
                {
                    throw;
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "I-frame image extraction failed, will attempt standard way. Input: {arguments}", inputArgument);
                }
            }

            return(await ExtractImageInternal(inputArgument, container, videoStream, imageStreamIndex, threedFormat, offset, false, cancellationToken).ConfigureAwait(false));
        }
        private MediaStream ProcessThumbnail(MediaRequest request, Sitecore.Resources.Media.Media media)
        {
            MediaStream mStream = null;

            if (request.Options.Height == 0 && request.Options.Width == 0)
            {
                request.Options.Thumbnail = true;
            }

            mStream = MediaManager.Cache.GetStream(media, request.Options);

            if (mStream == null)
            {
                string tempPath = Settings.TempFolderPath + "/PDF-Thumbnails/";

                tempPath = MainUtil.MapPath(tempPath);

                if (!Directory.Exists(tempPath))
                {
                    Directory.CreateDirectory(tempPath);
                }

                // Prepare filenames
                string pdfFile = tempPath + media.MediaData.MediaItem.ID.ToString() + ".pdf";
                string jpgFile = tempPath + media.MediaData.MediaItem.ID.ToString() + "_" + media.MediaData.MediaItem.InnerItem["revision"] + ".jpg";

                string resizedJpgFile = tempPath + media.MediaData.MediaItem.ID.ToString() + "_" + request.Options.Width.ToString() + "_" + request.Options.Height.ToString();

                if (!File.Exists(jpgFile))
                {
                    // Save BLOB media file to disk
                    MediaConverter.ConvertMediaItemToFile(media.MediaData.MediaItem, pdfFile);

                    // Convert PDF to Jpeg - First Pager
                    MediaConverter.ConvertPDFtoJPG(pdfFile, 1, jpgFile);

                }

                // Resize Image
                MediaConverter.ReSizeJPG(jpgFile, resizedJpgFile, request.Options.Width, request.Options.Height, true);

                // Convert resized image to stream
                mStream = new MediaStream(File.Open(resizedJpgFile, FileMode.Open, FileAccess.Read, FileShare.Read), "jpg", media.MediaData.MediaItem);

                // Add the requested thumbnail to Media Cache
                MediaStream outStream = null;
                MediaManager.Cache.AddStream(media, request.Options, mStream, out outStream);

                if (outStream != null)
                {
                    // If Media cache is enabled
                    return outStream;
                }

            }

            // If Media cache is disabled
            return mStream;
        }
示例#36
0
 internal virtual async Task OnAddStream(MediaStream stream)
 {
 }
示例#37
0
		private void ResponseCallback(IAsyncResult iAsynchronousResult)
		{
			try
			{
				_ahMediaSourceAttributes = null;
				_aMediaStreamDescriptions = null;
				_cMP3WaveFormat = null;
				_cStream = new MediaStream(((HttpWebResponse)_cHttpWebRequest.EndGetResponse(iAsynchronousResult)).GetResponseStream());

				_cStream.Position = 0;
				// Initialize data structures to pass to the Media pipeline via the MediaStreamSource
				_ahMediaSourceAttributes = new Dictionary<MediaSourceAttributesKeys, string>();
				_aMediaStreamDescriptions = new List<MediaStreamDescription>();

				Dictionary<MediaStreamAttributeKeys, string> ahMediaStreamAttributes = new Dictionary<MediaStreamAttributeKeys, string>();

				ahMediaStreamAttributes[MediaStreamAttributeKeys.VideoFourCC] = "H264";
				ahMediaStreamAttributes[MediaStreamAttributeKeys.Width] = _nVideoFrameWidth.ToString();
				ahMediaStreamAttributes[MediaStreamAttributeKeys.Height] = _nVideoFrameHeight.ToString();
				_nCurrentFrameVideo = 0;
				_nCurrentFrameAudio = 0;

				_cMediaStreamVideoDescription = new MediaStreamDescription(MediaStreamType.Video, ahMediaStreamAttributes);
				_aMediaStreamDescriptions.Add(_cMediaStreamVideoDescription);

				FileTypeCompatibility cFtyp = (FileTypeCompatibility)Atom.Read(_cStream);
				Wide cWide = (Wide)cFtyp.cNext;
				MovieData cMdat = (MovieData)cWide.cNext;

				nDataStart = cMdat.DataOffsetGet();
				nDataSize = cMdat.DataSizeGet();

				//1. When the next four bytes in the bitstream form the four-byte sequence 0x00000001, the next byte in the byte
				//stream (which is a zero_byte syntax element) is extracted and discarded and the current position in the byte
				//stream is set equal to the position of the byte following this discarded byte.
				while (true)
				{
					if (0 == _cStream.ReadByte() && 0 == _cStream.ReadByte() && 0 == _cStream.ReadByte() && 1 == _cStream.ReadByte())
					{
						break;
					}
				}

				//2. The next three-byte sequence in the byte stream (which is a start_code_prefix_one_3bytes) is extracted and
				//discarded and the current position in the byte stream is set equal to the position of the byte following this
				//three-byte sequence.


				_cMP3WaveFormat = new MpegLayer3WaveFormat();
				_cMP3WaveFormat.WaveFormatEx = new WaveFormatEx();

				_cMP3WaveFormat.WaveFormatEx.FormatTag = WaveFormatEx.FormatMP3;
				//_cMP3WaveFormat.WaveFormatEx.Channels = (short)((mpegLayer3Frame.Channels == MediaParsers.Channel.SingleChannel) ? 1 : 2);
				_cMP3WaveFormat.WaveFormatEx.Channels = (short)2;
				//_cMP3WaveFormat.WaveFormatEx.SamplesPerSec = mpegLayer3Frame.SamplingRate;
				_cMP3WaveFormat.WaveFormatEx.SamplesPerSec = _nAudioSampleRate;
				//_cMP3WaveFormat.WaveFormatEx.AvgBytesPerSec = mpegLayer3Frame.Bitrate / 8;
				_cMP3WaveFormat.WaveFormatEx.AvgBytesPerSec = _nAudioBitRate / 8;
				_cMP3WaveFormat.WaveFormatEx.BlockAlign = 1;
				_cMP3WaveFormat.WaveFormatEx.BitsPerSample = 0;
				_cMP3WaveFormat.WaveFormatEx.Size = 12;

				_cMP3WaveFormat.Id = 1;
				_cMP3WaveFormat.BitratePaddingMode = 0;
				_cMP3WaveFormat.FramesPerBlock = 1;
				//_cMP3WaveFormat.BlockSize = (short)mpegLayer3Frame.FrameSize; //(short)(144 * nBitRate / _nAudioSampleRate + _cMP3WaveFormat.BitratePaddingMode);
				_cMP3WaveFormat.BlockSize = (short)(144 * _nAudioBitRate / _nAudioSampleRate + _cMP3WaveFormat.BitratePaddingMode);
				_cMP3WaveFormat.CodecDelay = 0;

				ahMediaStreamAttributes = new Dictionary<MediaStreamAttributeKeys, string>();
				ahMediaStreamAttributes[MediaStreamAttributeKeys.CodecPrivateData] = _cMP3WaveFormat.ToHexString();
				_cMediaStreamAudioDescription = new MediaStreamDescription(MediaStreamType.Audio, ahMediaStreamAttributes);
				_aMediaStreamDescriptions.Add(_cMediaStreamAudioDescription);

				switch (_nAudioBitRate)
				{
					case 64000:
						_nAudioMP3ControlByte = 0x54;
						break;
					case 128000:
						_nAudioMP3ControlByte = 0x94;
						break;
					default:
						throw new Exception("unsupported audio bit rate:" + _nAudioBitRate);
				}
				_aFramesOffsets.Add(new FrameOffset(0, 0));
				_nFrameDuration = TimeSpan.FromSeconds((double)1 / 25).Ticks; //FPS
				_nSampleDuration = TimeSpan.FromSeconds(((double)1 / _nAudioSampleRate) * 1152).Ticks;

				try
				{
					long nBufferTicks = TimeSpan.FromSeconds(_nBufferSeconds).Ticks;
					while ((ulong)_nBufferSeconds > _nFramesQty || nBufferTicks > (_aAudioNALs.Count * _nSampleDuration)) //если длительность меньше буфера, то крутим до исключения, по которому и выйдем из цикла
						NALUnitParse();
					_cThread = new System.Threading.Thread(NALUnitsReceive);
					_cThread.Start();
				}
				catch
				{
					_bCached = true;
				}

				TimeSpan tsDuration;
				if (1 > _nFramesQty)
				{
					lock (_cSyncRoot)
					{
						long nDurationAudio = (long)(_aAudioNALs.Count * _nSampleDuration);
						long nDurationVideo = (long)(_aVideoNALs.Count(row => row.bFrameStart) * _nFrameDuration);
						tsDuration = TimeSpan.FromTicks(nDurationAudio > nDurationVideo ? nDurationAudio : nDurationVideo);
					}
				}
				else
					tsDuration = TimeSpan.FromMilliseconds(_nFramesQty * 40); //FPS

				_ahMediaSourceAttributes[MediaSourceAttributesKeys.Duration] = tsDuration.Ticks.ToString(System.Globalization.CultureInfo.InvariantCulture);
				_ahMediaSourceAttributes[MediaSourceAttributesKeys.CanSeek] = true.ToString();

				ReportOpenMediaCompleted(_ahMediaSourceAttributes, _aMediaStreamDescriptions);
			}
			catch (WebException e)
			{
				// Need to handle the exception
			}
		}
        /// <summary>
        /// Gets the chapter.
        /// </summary>
        /// <param name="reader">The reader.</param>
        /// <returns>ChapterInfo.</returns>
        private MediaStream GetMediaStream(IDataReader reader)
        {
            var item = new MediaStream
            {
                Index = reader.GetInt32(1)
            };

            item.Type = (MediaStreamType)Enum.Parse(typeof(MediaStreamType), reader.GetString(2), true);

            if (!reader.IsDBNull(3))
            {
                item.Codec = reader.GetString(3);
            }

            if (!reader.IsDBNull(4))
            {
                item.Language = reader.GetString(4);
            }

            if (!reader.IsDBNull(5))
            {
                item.ChannelLayout = reader.GetString(5);
            }

            if (!reader.IsDBNull(6))
            {
                item.Profile = reader.GetString(6);
            }

            if (!reader.IsDBNull(7))
            {
                item.AspectRatio = reader.GetString(7);
            }

            if (!reader.IsDBNull(8))
            {
                item.Path = reader.GetString(8);
            }

            item.IsInterlaced = reader.GetBoolean(9);

            if (!reader.IsDBNull(10))
            {
                item.BitRate = reader.GetInt32(10);
            }

            if (!reader.IsDBNull(11))
            {
                item.Channels = reader.GetInt32(11);
            }

            if (!reader.IsDBNull(12))
            {
                item.SampleRate = reader.GetInt32(12);
            }

            item.IsDefault  = reader.GetBoolean(13);
            item.IsForced   = reader.GetBoolean(14);
            item.IsExternal = reader.GetBoolean(15);

            if (!reader.IsDBNull(16))
            {
                item.Width = reader.GetInt32(16);
            }

            if (!reader.IsDBNull(17))
            {
                item.Height = reader.GetInt32(17);
            }

            if (!reader.IsDBNull(18))
            {
                item.AverageFrameRate = reader.GetFloat(18);
            }

            if (!reader.IsDBNull(19))
            {
                item.RealFrameRate = reader.GetFloat(19);
            }

            if (!reader.IsDBNull(20))
            {
                item.Level = reader.GetFloat(20);
            }

            if (!reader.IsDBNull(21))
            {
                item.PixelFormat = reader.GetString(21);
            }

            if (!reader.IsDBNull(22))
            {
                item.BitDepth = reader.GetInt32(22);
            }

            if (!reader.IsDBNull(23))
            {
                item.IsAnamorphic = reader.GetBoolean(23);
            }

            if (!reader.IsDBNull(24))
            {
                item.RefFrames = reader.GetInt32(24);
            }

            return(item);
        }
示例#39
0
        /// <summary>
        /// Converts ffprobe stream info to our MediaStream class
        /// </summary>
        /// <param name="streamInfo">The stream info.</param>
        /// <param name="formatInfo">The format info.</param>
        /// <returns>MediaStream.</returns>
        private static MediaStream GetMediaStream(MediaStreamInfo streamInfo, MediaFormatInfo formatInfo)
        {
            var stream = new MediaStream
            {
                Codec       = streamInfo.codec_name,
                Profile     = streamInfo.profile,
                Level       = streamInfo.level,
                Index       = streamInfo.index,
                PixelFormat = streamInfo.pix_fmt
            };

            if (streamInfo.tags != null)
            {
                stream.Language = GetDictionaryValue(streamInfo.tags, "language");
            }

            if (string.Equals(streamInfo.codec_type, "audio", StringComparison.OrdinalIgnoreCase))
            {
                stream.Type = MediaStreamType.Audio;

                stream.Channels = streamInfo.channels;

                if (!string.IsNullOrEmpty(streamInfo.sample_rate))
                {
                    stream.SampleRate = int.Parse(streamInfo.sample_rate, UsCulture);
                }

                stream.ChannelLayout = ParseChannelLayout(streamInfo.channel_layout);
            }
            else if (string.Equals(streamInfo.codec_type, "subtitle", StringComparison.OrdinalIgnoreCase))
            {
                stream.Type = MediaStreamType.Subtitle;
            }
            else if (string.Equals(streamInfo.codec_type, "video", StringComparison.OrdinalIgnoreCase))
            {
                stream.Type = MediaStreamType.Video;

                stream.Width       = streamInfo.width;
                stream.Height      = streamInfo.height;
                stream.AspectRatio = GetAspectRatio(streamInfo);

                stream.AverageFrameRate = GetFrameRate(streamInfo.avg_frame_rate);
                stream.RealFrameRate    = GetFrameRate(streamInfo.r_frame_rate);

                stream.BitDepth = GetBitDepth(stream.PixelFormat);
            }
            else
            {
                return(null);
            }

            // Get stream bitrate
            var bitrate = 0;

            if (!string.IsNullOrEmpty(streamInfo.bit_rate))
            {
                bitrate = int.Parse(streamInfo.bit_rate, UsCulture);
            }
            else if (formatInfo != null && !string.IsNullOrEmpty(formatInfo.bit_rate) && stream.Type == MediaStreamType.Video)
            {
                // If the stream info doesn't have a bitrate get the value from the media format info
                bitrate = int.Parse(formatInfo.bit_rate, UsCulture);
            }

            if (bitrate > 0)
            {
                stream.BitRate = bitrate;
            }

            if (streamInfo.disposition != null)
            {
                var isDefault = GetDictionaryValue(streamInfo.disposition, "default");
                var isForced  = GetDictionaryValue(streamInfo.disposition, "forced");

                stream.IsDefault = string.Equals(isDefault, "1", StringComparison.OrdinalIgnoreCase);

                stream.IsForced = string.Equals(isForced, "1", StringComparison.OrdinalIgnoreCase);
            }

            return(stream);
        }
		public abstract IOptimizerResult Optimize(MediaStream stream);
示例#41
0
        public static int?GetDefaultSubtitleStreamIndex(List <MediaStream> streams,
                                                        string[] preferredLanguages,
                                                        SubtitlePlaybackMode mode,
                                                        string audioTrackLanguage)
        {
            streams = GetSortedStreams(streams, MediaStreamType.Subtitle, preferredLanguages)
                      .ToList();

            MediaStream stream = null;

            if (mode == SubtitlePlaybackMode.None)
            {
                return(null);
            }

            if (mode == SubtitlePlaybackMode.Default)
            {
                // Prefer embedded metadata over smart logic

                stream = streams.FirstOrDefault(s => s.IsForced && string.Equals(s.Language, audioTrackLanguage, StringComparison.OrdinalIgnoreCase)) ??
                         streams.FirstOrDefault(s => s.IsForced) ??
                         streams.FirstOrDefault(s => s.IsDefault);

                // if the audio language is not understood by the user, load their preferred subs, if there are any
                if (stream == null && !preferredLanguages.Contains(audioTrackLanguage, StringComparer.OrdinalIgnoreCase))
                {
                    stream = streams.Where(s => !s.IsForced).FirstOrDefault(s => preferredLanguages.Contains(s.Language, StringComparer.OrdinalIgnoreCase));
                }
            }
            else if (mode == SubtitlePlaybackMode.Smart)
            {
                // Prefer smart logic over embedded metadata

                // if the audio language is not understood by the user, load their preferred subs, if there are any
                if (!preferredLanguages.Contains(audioTrackLanguage, StringComparer.OrdinalIgnoreCase))
                {
                    stream = streams.Where(s => !s.IsForced).FirstOrDefault(s => preferredLanguages.Contains(s.Language, StringComparer.OrdinalIgnoreCase)) ??
                             streams.FirstOrDefault(s => preferredLanguages.Contains(s.Language, StringComparer.OrdinalIgnoreCase));
                }
            }
            else if (mode == SubtitlePlaybackMode.Always)
            {
                // always load the most suitable full subtitles
                stream = streams.FirstOrDefault(s => !s.IsForced);
            }
            else if (mode == SubtitlePlaybackMode.OnlyForced)
            {
                // always load the most suitable full subtitles
                stream = streams.FirstOrDefault(s => s.IsForced && string.Equals(s.Language, audioTrackLanguage, StringComparison.OrdinalIgnoreCase)) ??
                         streams.FirstOrDefault(s => s.IsForced);
            }

            // load forced subs if we have found no suitable full subtitles
            stream = stream ?? streams.FirstOrDefault(s => s.IsForced && string.Equals(s.Language, audioTrackLanguage, StringComparison.OrdinalIgnoreCase));

            if (stream != null)
            {
                return(stream.Index);
            }

            return(null);
        }
示例#42
0
		public virtual bool CanOptimize(MediaStream stream)
		{
			return CreateOptimizer(stream) != null;
		}
示例#43
0
        private async Task <bool> DetectInterlaced(MediaSourceInfo video, MediaStream videoStream, string inputPath, string probeSizeArgument)
        {
            if (video.Protocol != MediaProtocol.File)
            {
                return(false);
            }

            var formats = (video.Container ?? string.Empty).Split(',').ToList();
            var enableInterlacedDection = formats.Contains("vob", StringComparer.OrdinalIgnoreCase) &&
                                          formats.Contains("m2ts", StringComparer.OrdinalIgnoreCase) &&
                                          formats.Contains("ts", StringComparer.OrdinalIgnoreCase) &&
                                          formats.Contains("mpegts", StringComparer.OrdinalIgnoreCase) &&
                                          formats.Contains("wtv", StringComparer.OrdinalIgnoreCase);

            // If it's mpeg based, assume true
            if ((videoStream.Codec ?? string.Empty).IndexOf("mpeg", StringComparison.OrdinalIgnoreCase) != -1)
            {
                if (enableInterlacedDection)
                {
                    return(true);
                }
            }
            else
            {
                // If the video codec is not some form of mpeg, then take a shortcut and limit this to containers that are likely to have interlaced content
                if (!enableInterlacedDection)
                {
                    return(false);
                }
            }

            var args = "{0} -i {1} -map 0:v:{2} -an -filter:v idet -frames:v 500 -an -f null /dev/null";

            var process = new Process
            {
                StartInfo = new ProcessStartInfo
                {
                    CreateNoWindow  = true,
                    UseShellExecute = false,

                    // Must consume both or ffmpeg may hang due to deadlocks. See comments below.
                    RedirectStandardOutput = true,
                    RedirectStandardError  = true,
                    RedirectStandardInput  = true,
                    FileName  = FFMpegPath,
                    Arguments = string.Format(args, probeSizeArgument, inputPath, videoStream.Index.ToString(CultureInfo.InvariantCulture)).Trim(),

                    WindowStyle = ProcessWindowStyle.Hidden,
                    ErrorDialog = false
                },

                EnableRaisingEvents = true
            };

            _logger.Debug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);
            var idetFoundInterlaced = false;

            using (var processWrapper = new ProcessWrapper(process, this, _logger))
            {
                try
                {
                    StartProcess(processWrapper);
                }
                catch (Exception ex)
                {
                    _logger.ErrorException("Error starting ffprobe", ex);

                    throw;
                }

                try
                {
                    process.BeginOutputReadLine();

                    using (var reader = new StreamReader(process.StandardError.BaseStream))
                    {
                        while (!reader.EndOfStream)
                        {
                            var line = await reader.ReadLineAsync().ConfigureAwait(false);

                            if (line.StartsWith("[Parsed_idet", StringComparison.OrdinalIgnoreCase))
                            {
                                var idetResult = AnalyzeIdetResult(line);

                                if (idetResult.HasValue)
                                {
                                    if (!idetResult.Value)
                                    {
                                        return(false);
                                    }

                                    idetFoundInterlaced = true;
                                }
                            }
                        }
                    }
                }
                catch
                {
                    StopProcess(processWrapper, 100, true);

                    throw;
                }
            }

            return(idetFoundInterlaced);
        }
示例#44
0
        private async Task <string> ExtractImageInternal(string inputPath, string container, MediaStream videoStream, int?imageStreamIndex, Video3DFormat?threedFormat, TimeSpan?offset, bool useIFrame, CancellationToken cancellationToken)
        {
            if (string.IsNullOrEmpty(inputPath))
            {
                throw new ArgumentNullException(nameof(inputPath));
            }

            var tempExtractPath = Path.Combine(ConfigurationManager.ApplicationPaths.TempDirectory, Guid.NewGuid() + ".jpg");

            Directory.CreateDirectory(Path.GetDirectoryName(tempExtractPath));

            // apply some filters to thumbnail extracted below (below) crop any black lines that we made and get the correct ar then scale to width 600.
            // This filter chain may have adverse effects on recorded tv thumbnails if ar changes during presentation ex. commercials @ diff ar
            var vf = "scale=600:trunc(600/dar/2)*2";

            if (threedFormat.HasValue)
            {
                switch (threedFormat.Value)
                {
                case Video3DFormat.HalfSideBySide:
                    vf = "crop=iw/2:ih:0:0,scale=(iw*2):ih,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1,scale=600:trunc(600/dar/2)*2";
                    // hsbs crop width in half,scale to correct size, set the display aspect,crop out any black bars we may have made the scale width to 600. Work out the correct height based on the display aspect it will maintain the aspect where -1 in this case (3d) may not.
                    break;

                case Video3DFormat.FullSideBySide:
                    vf = "crop=iw/2:ih:0:0,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1,scale=600:trunc(600/dar/2)*2";
                    //fsbs crop width in half,set the display aspect,crop out any black bars we may have made the scale width to 600.
                    break;

                case Video3DFormat.HalfTopAndBottom:
                    vf = "crop=iw:ih/2:0:0,scale=(iw*2):ih),setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1,scale=600:trunc(600/dar/2)*2";
                    //htab crop heigh in half,scale to correct size, set the display aspect,crop out any black bars we may have made the scale width to 600
                    break;

                case Video3DFormat.FullTopAndBottom:
                    vf = "crop=iw:ih/2:0:0,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1,scale=600:trunc(600/dar/2)*2";
                    // ftab crop heigt in half, set the display aspect,crop out any black bars we may have made the scale width to 600
                    break;

                default:
                    break;
                }
            }

            var mapArg = imageStreamIndex.HasValue ? (" -map 0:v:" + imageStreamIndex.Value.ToString(CultureInfo.InvariantCulture)) : string.Empty;

            var enableThumbnail = !new List <string> {
                "wtv"
            }.Contains(container ?? string.Empty, StringComparer.OrdinalIgnoreCase);
            // Use ffmpeg to sample 100 (we can drop this if required using thumbnail=50 for 50 frames) frames and pick the best thumbnail. Have a fall back just in case.
            var thumbnail = enableThumbnail ? ",thumbnail=24" : string.Empty;

            var args = useIFrame ? string.Format("-i {0}{3} -threads 0 -v quiet -vframes 1 -vf \"{2}{4}\" -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg, thumbnail) :
                       string.Format("-i {0}{3} -threads 0 -v quiet -vframes 1 -vf \"{2}\" -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg);

            var probeSizeArgument       = EncodingHelper.GetProbeSizeArgument(1);
            var analyzeDurationArgument = EncodingHelper.GetAnalyzeDurationArgument(1);

            if (!string.IsNullOrWhiteSpace(probeSizeArgument))
            {
                args = probeSizeArgument + " " + args;
            }

            if (!string.IsNullOrWhiteSpace(analyzeDurationArgument))
            {
                args = analyzeDurationArgument + " " + args;
            }

            if (offset.HasValue)
            {
                args = string.Format("-ss {0} ", GetTimeParameter(offset.Value)) + args;
            }

            var encodinghelper = new EncodingHelper(this, FileSystem, SubtitleEncoder());

            if (videoStream != null)
            {
                /* fix
                 * var decoder = encodinghelper.GetHardwareAcceleratedVideoDecoder(VideoType.VideoFile, videoStream, GetEncodingOptions());
                 * if (!string.IsNullOrWhiteSpace(decoder))
                 * {
                 *  args = decoder + " " + args;
                 * }
                 */
            }

            if (!string.IsNullOrWhiteSpace(container))
            {
                var inputFormat = encodinghelper.GetInputFormat(container);
                if (!string.IsNullOrWhiteSpace(inputFormat))
                {
                    args = "-f " + inputFormat + " " + args;
                }
            }

            var process = _processFactory.Create(new ProcessOptions
            {
                CreateNoWindow      = true,
                UseShellExecute     = false,
                FileName            = FFmpegPath,
                Arguments           = args,
                IsHidden            = true,
                ErrorDialog         = false,
                EnableRaisingEvents = true
            });

            _logger.LogDebug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);

            using (var processWrapper = new ProcessWrapper(process, this, _logger))
            {
                bool ranToCompletion;

                await _thumbnailResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);

                try
                {
                    StartProcess(processWrapper);

                    var timeoutMs = ConfigurationManager.Configuration.ImageExtractionTimeoutMs;
                    if (timeoutMs <= 0)
                    {
                        timeoutMs = DefaultImageExtractionTimeoutMs;
                    }

                    ranToCompletion = await process.WaitForExitAsync(timeoutMs).ConfigureAwait(false);

                    if (!ranToCompletion)
                    {
                        StopProcess(processWrapper, 1000);
                    }
                }
                finally
                {
                    _thumbnailResourcePool.Release();
                }

                var exitCode = ranToCompletion ? processWrapper.ExitCode ?? 0 : -1;
                var file     = FileSystem.GetFileInfo(tempExtractPath);

                if (exitCode == -1 || !file.Exists || file.Length == 0)
                {
                    var msg = string.Format("ffmpeg image extraction failed for {0}", inputPath);

                    _logger.LogError(msg);

                    throw new Exception(msg);
                }

                return(tempExtractPath);
            }
        }
示例#45
0
        TsPacketizedElementaryStream CreatePacketizedElementaryStream(TsStreamType streamType, uint pid, IMediaStreamMetadata mediaStreamMetadata)
        {
            var streamBuffer = _bufferingManager.CreateStreamBuffer(streamType);

            MediaStream mediaStream = null;

            var pesStreamHandler = _pesHandlers.GetPesHandler(streamType, pid, mediaStreamMetadata, packet =>
            {
                // ReSharper disable AccessToModifiedClosure
                if (null != mediaStream)
                    mediaStream.EnqueuePacket(packet);
                else if (null != packet)
                    _tsPesPacketPool.FreePesPacket(packet);
                // ReSharper restore AccessToModifiedClosure
            });

            var pes = new TsPacketizedElementaryStream(_bufferPool, _tsPesPacketPool, pesStreamHandler.PacketHandler, streamType, pid);

            var configurator = pesStreamHandler.Configurator;

            if (null != configurator)
            {
                EventHandler configuratorOnConfigurationComplete = null;

                configuratorOnConfigurationComplete = (o, e) =>
                {
                    configurator.ConfigurationComplete -= configuratorOnConfigurationComplete;

                    CheckConfigurationComplete();
                };

                configurator.ConfigurationComplete += configuratorOnConfigurationComplete;
            }

            mediaStream = new MediaStream(configurator, streamBuffer, _tsPesPacketPool.FreePesPacket);

            AddMediaStream(mediaStream);

            _tsTimemestamp.RegisterMediaStream(mediaStream, pesStreamHandler.GetDuration);

            if (null == configurator)
                CheckConfigurationComplete();

            return pes;
        }
示例#46
0
        public async Task ExtractVideoImagesOnInterval(
            string[] inputFiles,
            string container,
            MediaStream videoStream,
            MediaProtocol protocol,
            Video3DFormat?threedFormat,
            TimeSpan interval,
            string targetDirectory,
            string filenamePrefix,
            int?maxWidth,
            CancellationToken cancellationToken)
        {
            var inputArgument = GetInputArgument(inputFiles, protocol);

            var vf = "fps=fps=1/" + interval.TotalSeconds.ToString(UsCulture);

            if (maxWidth.HasValue)
            {
                var maxWidthParam = maxWidth.Value.ToString(UsCulture);

                vf += string.Format(",scale=min(iw\\,{0}):trunc(ow/dar/2)*2", maxWidthParam);
            }

            Directory.CreateDirectory(targetDirectory);
            var outputPath = Path.Combine(targetDirectory, filenamePrefix + "%05d.jpg");

            var args = string.Format("-i {0} -threads 0 -v quiet -vf \"{2}\" -f image2 \"{1}\"", inputArgument, outputPath, vf);

            var probeSizeArgument       = EncodingHelper.GetProbeSizeArgument(1);
            var analyzeDurationArgument = EncodingHelper.GetAnalyzeDurationArgument(1);

            if (!string.IsNullOrWhiteSpace(probeSizeArgument))
            {
                args = probeSizeArgument + " " + args;
            }

            if (!string.IsNullOrWhiteSpace(analyzeDurationArgument))
            {
                args = analyzeDurationArgument + " " + args;
            }

            var encodinghelper = new EncodingHelper(this, FileSystem, SubtitleEncoder());

            if (videoStream != null)
            {
                /* fix
                 * var decoder = encodinghelper.GetHardwareAcceleratedVideoDecoder(VideoType.VideoFile, videoStream, GetEncodingOptions());
                 * if (!string.IsNullOrWhiteSpace(decoder))
                 * {
                 *  args = decoder + " " + args;
                 * }
                 */
            }

            if (!string.IsNullOrWhiteSpace(container))
            {
                var inputFormat = encodinghelper.GetInputFormat(container);
                if (!string.IsNullOrWhiteSpace(inputFormat))
                {
                    args = "-f " + inputFormat + " " + args;
                }
            }

            var process = _processFactory.Create(new ProcessOptions
            {
                CreateNoWindow      = true,
                UseShellExecute     = false,
                FileName            = FFmpegPath,
                Arguments           = args,
                IsHidden            = true,
                ErrorDialog         = false,
                EnableRaisingEvents = true
            });

            _logger.LogInformation(process.StartInfo.FileName + " " + process.StartInfo.Arguments);

            await _thumbnailResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);

            bool ranToCompletion = false;

            using (var processWrapper = new ProcessWrapper(process, this, _logger))
            {
                try
                {
                    StartProcess(processWrapper);

                    // Need to give ffmpeg enough time to make all the thumbnails, which could be a while,
                    // but we still need to detect if the process hangs.
                    // Making the assumption that as long as new jpegs are showing up, everything is good.

                    bool isResponsive = true;
                    int  lastCount    = 0;

                    while (isResponsive)
                    {
                        if (await process.WaitForExitAsync(30000).ConfigureAwait(false))
                        {
                            ranToCompletion = true;
                            break;
                        }

                        cancellationToken.ThrowIfCancellationRequested();

                        var jpegCount = FileSystem.GetFilePaths(targetDirectory)
                                        .Count(i => string.Equals(Path.GetExtension(i), ".jpg", StringComparison.OrdinalIgnoreCase));

                        isResponsive = (jpegCount > lastCount);
                        lastCount    = jpegCount;
                    }

                    if (!ranToCompletion)
                    {
                        StopProcess(processWrapper, 1000);
                    }
                }
                finally
                {
                    _thumbnailResourcePool.Release();
                }

                var exitCode = ranToCompletion ? processWrapper.ExitCode ?? 0 : -1;

                if (exitCode == -1)
                {
                    var msg = string.Format("ffmpeg image extraction failed for {0}", inputArgument);

                    _logger.LogError(msg);

                    throw new Exception(msg);
                }
            }
        }
示例#47
0
        internal async Task <Stream> OpenStreamAsync(bool synchronous, bool skipCache = false, bool linger = true)
        {
            var url = new LazyUri(Url);
            await Utils.CheckLocalFileAccessAsync(url);

            var mgr = this.manager;
            Func <long, Task <HttpResponseMessage> > createStream = null;

#if !STANDALONE && DESKTOP
            if (Caching.AzureApi != null && (mgr == null || !mgr.IsAlive) && !skipCache)
            {
                var container          = Caching.GetAzureContainer(url);
                HashSet <string> files = null;
                if (synchronous)
                {
                    ObjectManager.SynchronizationContext.Send(async() =>
                    {
                        files = await Caching.GetAzureCachedFiles(container);
                    });
                }
                else
                {
                    await ObjectManager.SynchronizationContext.SendAsync(async() =>
                    {
                        files = await Caching.GetAzureCachedFiles(container);
                    });
                }
                var name = Caching.GetFileCachePath(url);
                if (files.Contains(name))
                {
                    createStream = offset => Caching.GetAzureResponseAsync(container, name, offset, this);
                }
            }
            else
#endif
            if (
#if !STANDALONE && DESKTOP
                Caching.AzureApi == null &&
#endif
                !skipCache)
            {
#if DESKTOP
                var cache = Caching.GetFileCachePath(url);

                if (File.Exists(cache))
                {
                    var str = new FileStream(cache, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete);
                    if (str.Length == 0)
                    {
                        var errfile = Path.ChangeExtension(cache, ".err");
                        if (File.Exists(errfile))
                        {
                            str.Dispose();
                            var errlines = File.ReadAllText(errfile);
                            return(new MediaStream(MediaStream.ExceptionFromCachedResponse(errlines), this));
                        }
                    }
                    Sanity.AssertFastReadByte(str);
                    return(str);
                }
#endif
            }

            lock (this)
            {
                if (manager == null)
                {
                    manager = new MediaStreamManager(createStream ?? GetResponseAsync, true);
                }

                var stream = manager.TryCreateStream(this, 0, linger);
                if (stream == null)
                {
                    manager = new MediaStreamManager(createStream ?? GetResponseAsync, true);
                    stream  = manager.TryCreateStream(this, 0, linger);
                    Sanity.Assert(stream != null);
                }
                Sanity.AssertFastReadByte(stream);
                return(stream);
            }
        }
示例#48
0
		protected virtual IImageOptimizer CreateOptimizer(MediaStream stream)
		{
			return Optimizers.FirstOrDefault(optimizer => optimizer.CanOptimize(stream));
		}
示例#49
0
        void AddMediaStream(MediaStream mediaStream)
        {
            var mediaStreams = _mediaStreams;
            var newMediaStreams = new MediaStream[_mediaStreams.Length + 1];

            for (; ; )
            {
                if (newMediaStreams.Length != mediaStreams.Length)
                    newMediaStreams = new MediaStream[_mediaStreams.Length + 1];

                Array.Copy(mediaStreams, newMediaStreams, mediaStreams.Length);
                newMediaStreams[newMediaStreams.Length - 1] = mediaStream;

                var oldMediaStream = Interlocked.CompareExchange(ref _mediaStreams, newMediaStreams, mediaStreams);

                if (ReferenceEquals(oldMediaStream, mediaStreams))
                    break;

                mediaStreams = oldMediaStream;
            }

            CheckConfigurationComplete();
        }