예제 #1
0
        private async void StartPlay(IChannelHandlerContext ctx, MediaStream stream)
        {
            try
            {
                await ctx.WriteAndFlushAsync(UserControlMessageEvent.StreamBegin(Constants.DEFAULT_STREAM_ID));

                RtmpCommandMessage onStatus = OnStatus("status", "NetStream.Play.Start", "Start live");
                await ctx.WriteAndFlushAsync(onStatus);

                var args = new List <Object>();
                args.Add("|RtmpSampleAccess");
                args.Add(true);
                args.Add(true);
                RtmpCommandMessage rtmpSampleAccess = new RtmpCommandMessage(args);
                await ctx.WriteAndFlushAsync(rtmpSampleAccess);

                var metadata = new List <Object>();
                metadata.Add("onMetaData");
                metadata.Add(stream.Metadata);
                RtmpDataMessage msgMetadata = new RtmpDataMessage(metadata);
                await ctx.WriteAndFlushAsync(msgMetadata);

                await stream.AddSubscriber(ctx.Channel);
            }
            catch (Exception ex)
            {
                var i = 0;
            }
        }
예제 #2
0
        private void HandleCommand(IChannelHandlerContext ctx, RtmpCommandMessage msg)
        {
            var command     = msg.Command;
            var commandName = (String)command[0].ToString();

            switch (commandName)
            {
            case "connect":
                HandleConnect(ctx, msg);
                break;

            case "createStream":
                HandleCreateStream(ctx, msg);
                break;

            case "publish":
                HandlePublish(ctx, msg);
                _readAction?.Invoke(ctx, _streamName, msg);
                break;

            case "play":
                HandlePlay(ctx, msg);
                break;

            case "deleteStream":
            case "closeStream":
                HandleCloseStream(ctx, msg);
                _readAction?.Invoke(ctx, _streamName, msg);
                break;

            default:
                break;
            }
        }
예제 #3
0
        private async void HandleCreateStream(IChannelHandlerContext ctx, RtmpCommandMessage msg)
        {
            logger.Info($"create stream received : {msg}");
            var result = new List <Object>();

            result.Add("_result");
            result.Add(msg.Command[1]);
            result.Add(null);
            result.Add(Constants.DEFAULT_STREAM_ID);
            RtmpCommandMessage response = new RtmpCommandMessage(result);
            await ctx.WriteAndFlushAsync(response);
        }
예제 #4
0
        public RtmpCommandMessage OnStatus(String level, String code, String description)
        {
            var result = new List <Object>();

            result.Add("onStatus");
            result.Add(0);
            result.Add(null);
            result.Add(new AMF0Object().AddProperty("level", level).AddProperty("code", code).AddProperty("description",
                                                                                                          description));

            RtmpCommandMessage response = new RtmpCommandMessage(result);

            return(response);
        }
예제 #5
0
        private async void HandleConnect(IChannelHandlerContext ctx, RtmpCommandMessage msg)
        {
            logger.Info($"client connect {msg} ");
            var command             = ((Dictionary <string, object>)msg.Command[2]);
            var app                 = command.GetValueOrDefault("app").ToString();
            var clientRequestEncode = command.GetValueOrDefault("objectEncoding");

            if (!string.Equals(app, RtmpConfig.Instance.App, StringComparison.OrdinalIgnoreCase))
            {
                await ctx.CloseAsync();

                return;
            }
            if (clientRequestEncode != null && clientRequestEncode.ToString() == "3")
            {
                logger.Error($"client :{ctx} request AMF3 encoding  server  doesn't support");
                await ctx.CloseAsync();

                return;
            }

            _streamName = new StreamName(app, null, false);

            int ackSize = 5000000;
            WindowAcknowledgementSize was = new WindowAcknowledgementSize(ackSize);

            var spb = new  SetPeerBandWidth(ackSize, Constants.SET_PEER_BANDWIDTH_TYPE_SOFT);

            SetChunkSize setChunkSize = new SetChunkSize(5000);

            await ctx.WriteAndFlushAsync(was);

            await ctx.WriteAndFlushAsync(spb);

            await ctx.WriteAndFlushAsync(setChunkSize);

            var result = new List <Object>();

            result.Add("_result");
            result.Add(msg.Command[1]);            // transaction id
            result.Add(new AMF0Object().AddProperty("fmsVer", "FMS/3,0,1,123").AddProperty("capabilities", 31));
            result.Add(new AMF0Object().AddProperty("level", "status").AddProperty("code", "NetConnection.Connect.Success")
                       .AddProperty("description", "Connection succeeded").AddProperty("objectEncoding", 0));

            RtmpCommandMessage response = new RtmpCommandMessage(result);

            await ctx.WriteAndFlushAsync(response);
        }
예제 #6
0
        private async void HandlePublish(IChannelHandlerContext ctx, RtmpCommandMessage msg)
        {
            logger.Info($"publish :{msg}");
            _tag = RtmpTag.Publisher;
            var streamType = msg.Command[4].ToString();

            if (streamType != "live")
            {
                await ctx.Channel.DisconnectAsync();
            }
            var name = msg.Command[3].ToString();

            _streamName.Name = name;
            CreateStream(ctx);
            RtmpCommandMessage onStatus = OnStatus("status", "NetStream.Publish.Start", "Start publishing");
            await ctx.WriteAndFlushAsync(onStatus);
        }
예제 #7
0
        private async void HandleCloseStream(IChannelHandlerContext ctx, RtmpCommandMessage msg)
        {
            MediaStream stream = _mediaStreamDic.GetValueOrDefault(_streamName);

            try
            {
                if (_tag == RtmpTag.Subscriber)
                {
                    logger.Info($"subscriber:{ctx.Channel.RemoteAddress} close");
                    return;
                }
                var onStatus = OnStatus("status", "NetStream.Unpublish.Success", "Stop publishing");
                await ctx.WriteAsync(onStatus);

                if (stream == null)
                {
                    logger.Error($"can't find stream:{nameof(_streamName)} in buffer queue");
                }
                else
                {
                    if (stream != null)
                    {
                        await stream.SendEofToAllSubscriberAndClose();

                        _mediaStreamDic.Remove(_streamName, out MediaStream mediaStream);
                    }
                    _normalShutdown = true;
                    await ctx.CloseAsync();
                }
            }
            catch
            {
                if (stream != null)
                {
                    await stream.SendEofToAllSubscriberAndClose();

                    _mediaStreamDic.Remove(_streamName, out MediaStream mediaStream);
                }
                await ctx.CloseAsync();
            }
        }
예제 #8
0
        private async void HandlePlay(IChannelHandlerContext ctx, RtmpCommandMessage msg)
        {
            _tag = RtmpTag.Subscriber;
            var name = (String)msg.Command[3];

            _streamName.Name = name;
            var stream = _mediaStreamDic.GetValueOrDefault(_streamName);

            if (stream == null)
            {
                logger.Info($"client play request for stream:{nameof(_streamName)} not exist.");
                RtmpCommandMessage onStatus = OnStatus("error", "NetStream.Play.StreamNotFound", "No Such Stream");
                await ctx.WriteAndFlushAsync(onStatus);

                _normalShutdown = true;
                await ctx.Channel.CloseAsync();
            }
            else
            {
                StartPlay(ctx, stream);
            }
        }
        public static AbstractRtmpMessage Decode(RtmpHeader header, IByteBuffer payload)
        {
            AbstractRtmpMessage result = null;
            short messageTypeId        = header.MessageTypeId;

            switch (messageTypeId)
            {
            case Constants.MSG_SET_CHUNK_SIZE:
            {
                int          readInt      = payload.ReadInt();
                SetChunkSize setChunkSize = new SetChunkSize();
                setChunkSize.ChunkSize = readInt;
                result = setChunkSize;
            }
            break;

            case Constants.MSG_ABORT_MESSAGE:
            {
                int   csid  = payload.ReadInt();
                Abort abort = new Abort(csid);
                result = abort;
            }

            break;

            case Constants.MSG_ACKNOWLEDGEMENT:
            {
                int ack = payload.ReadInt();
                result = new Acknowledgement(ack);
            }
            break;

            case Constants.MSG_WINDOW_ACKNOWLEDGEMENT_SIZE:
            {
                int size = payload.ReadInt();
                result = new WindowAcknowledgementSize(size);
            }
            break;

            case Constants.MSG_SET_PEER_BANDWIDTH:
            {
                int ackSize = payload.ReadInt();
                int type    = payload.ReadByte();
                result = new SetPeerBandWidth(ackSize, type);
            }
            break;

            case Constants.MSG_TYPE_COMMAND_AMF0:
            {
                List <Object> decode = AMF0.DecodeAll(payload);
                result = new RtmpCommandMessage(decode);
            }
            break;

            case Constants.MSG_USER_CONTROL_MESSAGE_EVENTS:
            {
                short readShort = payload.ReadShort();
                int   data      = payload.ReadInt();
                result = new UserControlMessageEvent(readShort, data);
            }
            break;

            case Constants.MSG_TYPE_AUDIO_MESSAGE:
            {
                AudioMessage am = new AudioMessage();

                byte[] data = ReadAll(payload);
                am.AudioData = data;

                if (header.Fmt == Constants.CHUNK_FMT_0)
                {
                    am.Timestamp = header.Timestamp;
                }
                else if (header.Fmt == Constants.CHUNK_FMT_1 || header.Fmt == Constants.CHUNK_FMT_2)
                {
                    am.TimestampDelta = header.TimestampDelta;
                }
                result = am;
            }
            break;

            case Constants.MSG_TYPE_VIDEO_MESSAGE:
            {
                VideoMessage vm   = new VideoMessage();
                byte[]       data = ReadAll(payload);

                vm.VideoData = data;

                if (header.Fmt == Constants.CHUNK_FMT_0)
                {
                    vm.Timestamp = header.Timestamp;
                }
                else if (header.Fmt == Constants.CHUNK_FMT_1 || header.Fmt == Constants.CHUNK_FMT_2)
                {
                    vm.TimestampDelta = header.TimestampDelta;
                }
                result = vm;
            }
            break;

            case Constants.MSG_TYPE_DATA_MESSAGE_AMF0:
            {
                result = new RtmpDataMessage(AMF0.DecodeAll(payload));
            }
            break;

            default:
                break;
            }
            if (result != null)
            {
                result.InboundBodyLength   = header.MessageLength;
                result.InboundHeaderLength = header.HeaderLength;

                return(result);
            }
            else
            {
                return(null);
            }
        }
예제 #10
0
        public void  Publish(ConcurrentDictionary <StreamName, MediaStream> streams, RtmpCommandMessage msg)
        {
            var streamName = new StreamName(msg.Command[4].ToString(), msg.Command[3].ToString(), false);

            streams.GetOrAdd(streamName, new MediaStream(streamName));
        }