Ejemplo n.º 1
0
 public void Clear()
 {
     Event     = string.Empty;
     Code      = string.Empty;
     Level     = string.Empty;
     EventInfo = null;
 }
Ejemplo n.º 2
0
 public void Reset()
 {
     numVal    = 0.0;
     stringVal = "";
     objVal    = null;
     type      = AMFDataType.AMF_INVALID;
 }
Ejemplo n.º 3
0
        public object Clone()
        {
            AMFObject clone = new AMFObject();
            foreach (AMFObjectProperty prop in properties)
            {
                clone.properties.Add((AMFObjectProperty)prop.Clone());
            } //foreach

            return clone;
        }
Ejemplo n.º 4
0
        public object Clone()
        {
            AMFObject clone = new AMFObject();

            foreach (AMFObjectProperty prop in properties)
            {
                clone.properties.Add((AMFObjectProperty)prop.Clone());
            } //foreach

            return(clone);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Decode the amfobject when NetConnection has a successfull connnection.
        /// Don't know if it's of any use and if the same info is available for
        /// different RTMP servers. (Only tested with wowza 3.5.2)
        /// </summary>
        /// <param name="obj"></param>
        private void DecodeNetConnectionInfo_Connect_Result(AMFObject obj)
        {
            netConnectionConnectInfo.Clear();

            // WOWZA: In position 2 and 3 is the info we want as
            // Red5: has all it's info in [3] it seems
            if (obj.Count < 3)
            {
                return;
            }

            List<AMFObjectProperty> props = new List<AMFObjectProperty>();
            props.Clear();

            obj.FindMatchingProperty("fmsVer", props, 1);
            if (props.Count > 0)
            {
                netConnectionConnectInfo.FMSVer = props[0].StringValue;
            }
            props.Clear();
            obj.FindMatchingProperty("capabilities", props, 1);
            if (props.Count > 0)
            {
                try
                {
                    netConnectionConnectInfo.Capabilities = Convert.ToInt32(props[0].NumberValue);
                }
                catch { }
            }
            props.Clear();
            obj.FindMatchingProperty("mode", props, 1);
            if (props.Count > 0)
            {
                try
                {
                    netConnectionConnectInfo.Mode = Convert.ToInt32(props[0].NumberValue);
                }
                catch { }
            }

            props.Clear();
            obj.FindMatchingProperty("code", props, 1);
            if (props.Count > 0)
            {
                netConnectionConnectInfo.Code = props[0].StringValue;
            }
            props.Clear();
            obj.FindMatchingProperty("level", props, 1);
            if (props.Count > 0)
            {
                netConnectionConnectInfo.Level = props[0].StringValue;
            }
            props.Clear();
            obj.FindMatchingProperty("description", props, 1);
            if (props.Count > 0)
            {
                netConnectionConnectInfo.Description = props[0].StringValue;
            }

            props.Clear();
            obj.FindMatchingProperty("data", props, 1);
            if (props.Count > 0)
            {
                AMFObject obj2 = props[0].ObjectValue;
                props.Clear();
                obj2.FindMatchingProperty("version", props, 1);
                if (props.Count > 0)
                {
                    try
                    {
                        netConnectionConnectInfo.Version = new Version(props[0].StringValue.Replace(',', '.'));
                        realRTMPServerVersion = netConnectionConnectInfo.Version;
                    }
                    catch { }
                }
            }

            // Red5 doesn't seem to have this property
            props.Clear();
            obj.FindMatchingProperty("clientid", props, 1);
            if (props.Count > 0)
            {
                try
                {
                    netConnectionConnectInfo.ClientID = Convert.ToInt64(props[0].NumberValue);
                }
                catch { }
            }
            // Red5 doesn't seem to have this property
            props.Clear();
            obj.FindMatchingProperty("objectEncoding", props, 1);
            if (props.Count > 0)
            {
                try
                {
                    netConnectionConnectInfo.ObjectEncoding = Convert.ToInt32(props[0].NumberValue);
                }
                catch { }
            }
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Analyzes and responds if required to the given <see cref="RTMPPacket"/>.
        /// </summary>
        /// <param name="packet">The packet to inspect and react to.</param>
        /// <returns>0 (false) for OK/Failed/error, 1 for 'Stop or Complete' (true)</returns>
        private bool HandleInvoke(RTMPPacket packet)
        {
            bool ret = false;

            if (packet.Body[0] != 0x02) // make sure it is a string method name we start with
            {
                LibRTMPLogger.Log(LibRTMPLogLevel.Warning, "[CDR.LibRTMP.NetConnection.HandleInvoke] Sanity failed. no string method in invoke packet");
                return false;
            }

            AMFObject obj = new AMFObject();
            int nRes = obj.Decode(packet.Body, 0, (int)packet.BodySize, false);
            if (nRes < 0)
            {
                LibRTMPLogger.Log(LibRTMPLogLevel.Warning, "[CDR.LibRTMP.NetConnection.HandleInvoke] Error decoding invoke packet");
                return false;
            }

            obj.Dump();
            string method = obj.GetProperty(0).StringValue;
            double txn = obj.GetProperty(1).NumberValue;

            LibRTMPLogger.Log(LibRTMPLogLevel.Trace, string.Format("[CDR.LibRTMP.NetConnection.HandleInvoke] Server invoking <{0}>", method));

            if (method == "_result")
            {
                int transactionResultNum = (int)obj.GetProperty(1).NumberValue;
                string methodInvoked = "";
                if (methodCallDictionary.ContainsKey(transactionResultNum))
                {
                    methodInvoked = methodCallDictionary[transactionResultNum];
                    methodCallDictionary.Remove(transactionResultNum);
                }

                LibRTMPLogger.Log(LibRTMPLogLevel.Trace, string.Format("[CDR.LibRTMP.NetConnection.HandleInvoke] received result for method call <{0}>", methodInvoked));

                if (methodInvoked == "connect")
                {
                    // Get some info out of the result connection
                    DecodeNetConnectionInfo_Connect_Result(obj);

                    // Is SecureToken activate (when using wowza server)
                    string tmpSecureTokenPassword = string.Empty;
                    lock (lockVAR)
                    {
                        tmpSecureTokenPassword = secureTokenPassword;
                    }
                    if (!string.IsNullOrEmpty(tmpSecureTokenPassword))
                    {
                        List<AMFObjectProperty> props = new List<AMFObjectProperty>();
                        obj.FindMatchingProperty("secureToken", props, int.MaxValue);
                        if (props.Count > 0)
                        {
#if INCLUDE_TMPE
#endif
                        }
                    }
                    MQInternal_SendServerBW();

                    // Send OnConnect event
                }
                else if (methodInvoked == "createStream")
                {
                    int transactionNum = (int)obj.GetProperty(1).NumberValue;
                    int stream_id = (int)obj.GetProperty(3).NumberValue;

                    if (transactionIDReferenceTable.ContainsKey(transactionNum) && transactionIDReferenceTable[transactionNum] is NetStream)
                    {
                        NetStream netStream = (NetStream)transactionIDReferenceTable[transactionNum];
                        transactionIDReferenceTable.Remove(transactionNum);
                        LibRTMPLogger.Log(LibRTMPLogLevel.Info, string.Format("[CDR.LibRTMP.NetConnection.HandleInvoke] Received createStream(stream_id={0})", stream_id));

                        netStream.Stream_ID = stream_id;
                        // make sure we know which NetStreams use this NetCOnnection
                        RegisterNetStream(netStream);

                        int contentBufferTime = NetConnection.DefaultContentBufferTime;
                        netStream.HandleOnAssignStream_ID(packet, stream_id, out contentBufferTime);
                        if (contentBufferTime <= 0)
                        {
                            contentBufferTime = NetConnection.DefaultContentBufferTime;
                        }
                        // Tell buffer time we want to use for this channel
                        MQ_SendPing(3, (uint)netStream.Stream_ID, (uint)contentBufferTime);
                    }
                    else
                    {
                        // We haven't found a NetStream for which this is intended, so delete it again
                        MQ_SendDeleteStream(stream_id);
                    }
                }
                else if (methodInvoked == "play")
                {
                    // Server send the play command?
                }
            }
            else if (method == "onBWDone")
            {
                if (bwCheckCounter == 0)
                {
                    MQInternal_SendCheckBW();
                }
            }
            else if (method == "_onbwcheck")
            {
                MQInternal_SendCheckBWResult(txn);
            }
            else if (method == "_onbwdone")
            {
                int transactionResultNum = (int)obj.GetProperty(1).NumberValue;
                if (methodCallDictionary.ContainsValue("_checkbw"))
                {
                    var item = methodCallDictionary.First(x => x.Value == "_checkbw");
                    methodCallDictionary.Remove(item.Key);
                }
            }
            else if (method == "_error")
            {
                LibRTMPLogger.Log(LibRTMPLogLevel.Trace, "[CDR.LibRTMP.NetConnection.HandleInvoke] rtmp server sent error");
            }
            else if (method == "close")
            {
                LibRTMPLogger.Log(LibRTMPLogLevel.Trace, "[CDR.LibRTMP.NetConnection.HandleInvoke] rtmp server requested close");
                CloseConnection();
            }
            else if (method == "onStatus")
            {
                int stream_id = packet.InfoField2;
                string code = obj[3].ObjectValue.GetProperty("code").StringValue;
                string level = obj[3].ObjectValue.GetProperty("level").StringValue;

                LibRTMPLogger.Log(LibRTMPLogLevel.Info, string.Format("[CDR.LibRTMP.NetConnection.HandleInvoke] stream_id={0}, method={1}, code={2}, level={3}", stream_id, method, code, level));
                // Zoek NetStream op en geef OnStatus door
                if (netStreams[stream_id] != null)
                {
                    if (code == "NetStream.Pause.Notify")
                    {
                        // fix to help netstream
                        packet.TimeStamp = channelTimestamp[netStreams[stream_id].MediaChannel];
                    }
                    netStreams[stream_id].HandleOnStatus(packet);
                }
                else
                {
                    LibRTMPLogger.Log(LibRTMPLogLevel.Info, string.Format("[CDR.LibRTMP.NetConnection.HandleInvoke] UNHANDLED | stream_id={0}, method={1}, code={2}, level={3}", stream_id, method, code, level));
                }
            }
            else if (dMethodLookup.ContainsKey(method))
            {
                ret = true;

                SynchronizationContext sc;
                State_NC_MethodCall stateMethodCall = new State_NC_MethodCall();
                lock (lockVAR)
                {
                    sc = synchronizationContext;
                    stateMethodCall.Call = dMethodLookup[method];
                } //lock
                stateMethodCall.thisObject = this;
                stateMethodCall.MethodParam = obj;

                if (sc != null)
                {
                    switch (synchronizationContextMethod)
                    {
                        case SynchronizationContextMethod.Post:
                            sc.Post(HandleOnMethodCall, stateMethodCall);
                            break;
                        case SynchronizationContextMethod.Send:
                            sc.Send(HandleOnMethodCall, stateMethodCall);
                            break;
                    } //switch
                }
                else
                {
                    HandleOnMethodCall(stateMethodCall);
                }
            }
            else
            {
                LibRTMPLogger.Log(LibRTMPLogLevel.Trace, string.Format("[CDR.LibRTMP.NetConnection.HandleInvoke] [EVENT]={0}", method));
            }

            return ret;
        }
Ejemplo n.º 7
0
        private void HandleMetadata(RTMPPacket packet)
        {
            int stream_id = packet.InfoField2;

            // Find matching NetStream and forward this packet.
            if (netStreams[stream_id] == null)
            {
                LibRTMPLogger.Log(LibRTMPLogLevel.Warning, string.Format("[CDR.LibRTMP.NetConnection.HandleMetadata] No matching NetStream found for stream_id {0}", stream_id));
                return;
            }

            AMFObject obj = new AMFObject();
            int nRes = obj.Decode(packet.Body, 0, (int)packet.BodySize, false);
            if (nRes < 0)
            {
                LibRTMPLogger.Log(LibRTMPLogLevel.Warning, "[CDR.LibRTMP.NetConnection.HandleMetadata] Error decoding meta data packet");
                return;
            }

            string metastring = obj.GetProperty(0).StringValue;
            switch (metastring)
            {
                case "|RtmpSampleAccess":
                    // Ignore this, unknown
                    return;

                // Looks more as an invoke to me Let NetStream.OnStatus handle it
                case "onStatus": // -=> "NetStream.Data.Start"
                case "onPlayStatus": // -=> "NetStream.Play.Switch"
                case "onMetaData": // This seams to me te real metadata
                case "onID3":
                    // Let NetStream Handle it
                    netStreams[stream_id].HandleOnMetaData(packet);
                    break;

                default:
                    LibRTMPLogger.Log(LibRTMPLogLevel.Warning, string.Format("[CDR.LibRTMP.NetConnection.HandleMetadata] Unknown metadata {0}", metastring));
                    break;
            } //switch


            return;
        }
Ejemplo n.º 8
0
        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] // hide it for code completion
        virtual internal bool HandleOnMetaData(RTMPPacket packet)
        {
            AMFObject obj = new AMFObject();
            int nRes = obj.Decode(packet.Body, 0, (int)packet.BodySize, false);
            if (nRes < 0)
            {
                LibRTMPLogger.Log(LibRTMPLogLevel.Warning, "[CDR.LibRTMP.NetStream.HandleOnMetaData] Error decoding meta data packet");
                return false;
            }

            /* For video:
             *   canSeekToEnd = true
             *   videocodecid = 4
             *   framerate = 15
             *   videodatarate = 400
             *   height = 215
             *   width = 320
             *   duration = 7.347
             *   
             * For Audio (MP3): metastring =="onID3"
             * 
             */


            string metastring = obj.GetProperty(0).StringValue;
            switch (metastring)
            {
                case "onMetaData":
                    List<AMFObjectProperty> props = new List<AMFObjectProperty>();

                    props.Clear();
                    obj.FindMatchingProperty("audiodatarate", props, 1);
                    if (props.Count > 0)
                    {
                        int rate = (int)props[0].NumberValue;
                        audioDatarate += rate;
                        LibRTMPLogger.Log(LibRTMPLogLevel.Trace, string.Format("[CDR.LibRTMP.NetStream.HandleOnMetaData] audiodatarate: {0}", audioDatarate));
                    }
                    props.Clear();
                    obj.FindMatchingProperty("videodatarate", props, 1);
                    if (props.Count > 0)
                    {
                        int rate = (int)props[0].NumberValue;
                        videoDatarate += rate;
                        LibRTMPLogger.Log(LibRTMPLogLevel.Trace, string.Format("[CDR.LibRTMP.NetStream.HandleOnMetaData] videodatarate: {0}", videoDatarate));
                    }
                    if (audioDatarate == 0 && videoDatarate == 0)
                    {
                        props.Clear();
                        obj.FindMatchingProperty("filesize", props, int.MaxValue);
                        if (props.Count > 0)
                        {
                            combinedTracksLength = (int)props[0].NumberValue;
                            LibRTMPLogger.Log(LibRTMPLogLevel.Trace, string.Format("[CDR.LibRTMP.NetStream.HandleOnMetaData] Set CombinedTracksLength from filesize: {0}", combinedTracksLength));
                        }
                    }
                    if (combinedTracksLength == 0)
                    {
                        props.Clear();
                        obj.FindMatchingProperty("datasize", props, int.MaxValue);
                        if (props.Count > 0)
                        {
                            combinedTracksLength = (int)props[0].NumberValue;
                            LibRTMPLogger.Log(LibRTMPLogLevel.Trace, string.Format("[CDR.LibRTMP.NetStream.HandleOnMetaData] Set CombinedTracksLength from datasize: {0}", combinedTracksLength));
                        }
                    }
                    props.Clear();
                    obj.FindMatchingProperty("duration", props, 1);
                    if (props.Count > 0)
                    {
                        double duration = props[0].NumberValue;
                        LibRTMPLogger.Log(LibRTMPLogLevel.Trace, string.Format("[CDR.LibRTMP.NetStream.HandleOnMetaData] Set duration: {0}", duration));
                        lock (lockVAR)
                        {
                            metaDataDurationInMS = Convert.ToInt64(duration * 1000);
                        }

                        // Looks the same as the "onPlayStatus" (See NetConnection.HandleMetadata (we route it there through HandleOnStatusDecoded
                        // doing it here also)
                        Internal_HandleOnStatusDecoded(packet, "onStatus", "NetStream.Play.OnMetaData", "onPlayStatus", obj);
                    }
                    break;
                // Looks more as an invoke to me Let NetStream.OnStatus handle it
                case "onStatus": // -=> "NetStream.Data.Start"
                    Internal_HandleOnStatusDecoded(packet, "onStatus", obj.GetProperty(1).ObjectValue.GetProperty("code").StringValue, "", obj);
                    break;
                case "onPlayStatus":
                    // "code" = "NetStream.Play.Switch"
                    // "level"= "status" ,made it "onPlayStatus" 
                    // Has also "duration" and "bytes" as additional metadata (looks like a normal onMetaData to me with less options as the normal)
                    Internal_HandleOnStatusDecoded(packet, "onStatus", obj.GetProperty(1).ObjectValue.GetProperty("code").StringValue, "onPlayStatus", obj);
                    break;
                case "onID3":
                    return HandleOnID3(obj);
                default:
                    LibRTMPLogger.Log(LibRTMPLogLevel.Trace, string.Format("[CDR.LibRTMP.NetConnection.NetStream.HandleOnMetaData] metastring= {0}", metastring));
                    break;
            } //switch

            return true;
        }
Ejemplo n.º 9
0
        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] // hide it for code completion
        virtual protected bool Internal_HandleOnStatusDecoded(RTMPPacket packet, string eventStr, string codeStr, string levelStr, AMFObject obj)
        {
            //LibRTMPLogger.Log(LibRTMPLogLevel.Error, string.Format("[CDR.LibRTMP.NetStream.Internal_HandleOnStatusDecoded] event={0} code={1} level={2} Timestamp={3}", eventStr, codeStr, levelStr, packet.TimeStamp));
            //Console.WriteLine(string.Format("event={0} code={1} level={2} Timestamp={3} seekIsActive={4}", eventStr, codeStr, levelStr, packet.TimeStamp, seekIsActive.ToString()));

            if (OnStatus != null)
            {
                NetStreamStatusEvent netStreamStatusEvent = new NetStreamStatusEvent();
                netStreamStatusEvent.Clear();
                netStreamStatusEvent.Event = eventStr;
                netStreamStatusEvent.Code = codeStr;
                netStreamStatusEvent.Level = levelStr;
                netStreamStatusEvent.EventInfo = (AMFObject)obj.Clone(); // for thread safety

                MQ_RTMPMessage message = new MQ_RTMPMessage();
                message.MethodCall = MethodCall.OnEventCallUserCode;
                message.Params = new object[] { OnStatus, this, netStreamStatusEvent };
                netConnection.PostOnEventUserCallCodeMessage(message);
            }

            // Make sure we point to the right record which is buffered!
            if (codeStr == "NetStream.Play.Switch")
            {
                // end of stream (adjust duration to correct for inaccuracy!)
                lock (lockVAR)
                {
                    seekIsActive = false;
                } //lock
            }

            // Now do our thing
            switch (codeStr)
            {
                // We need to flush the existing buffers and wait until 
                // new data arrives
                case "NetStream.Seek.Notify":
                    lock (lockVAR)
                    {
                        seekIsActive = true; // is probably already set
                        blockMediaPackets++;
                        deltaTimeStampInMS = packet.TimeStamp;
                    }

                    Internal_OnSeekNotify(packet.TimeStamp);
                    break;

                case "NetStream.Play.Reset": // send when playlist starts at the beginning
                    lock (lockVAR)
                    {
                        atBeginOfAudio = true;
                        mediaBytesReceived = 0;
                        deltaTimeStampInMS = 0;
                    } //lock
                    break;

                case "NetStream.Play.Switch":
                    // Tell we have to stop playing (and drain the buffers!)
                    if (mediaBytesReceived > 0) // only when we are streaming already
                    {
                        blockMediaPackets++;
                    }
                    break;
                case "NetStream.Data.Start":
                    mediaBytesReceived = 0;
                    break;

                // stream begins to play (that is data is send)
                // deblock if needed
                case "NetStream.Play.Start":
                    lock (lockVAR)
                    {
                        if (blockMediaPackets > 0)
                        {
                            blockMediaPackets--;
                        }
                        seekIsActive = false; // is probably already set
                    } //lock
                    break;
                case "NetStream.Play.Stop":
                    ReplaySavedPackets(); // needed in case packets where saved (we're at the end so a byte sync will not occure anymore)
                    lock (lockVAR)
                    {
                        atBeginOfAudio = true;
                    }
                    break;

                // Pause logic
                case "NetStream.Pause.Notify":
                    ReplaySavedPackets(); // needed in case packets where saved (we're at the end so a byte sync will not occure anymore)
                    lock (lockVAR)
                    {
                        if (mediaBytesReceived > 0) // we're buffering
                        {
                            pauseIsActive = true;
                            Internal_OnPauseStream(true);
                            if (OnPauseStream != null)
                            {
                                MQ_RTMPMessage message = new MQ_RTMPMessage();
                                message.MethodCall = MethodCall.OnEventCallUserCode;
                                message.Params = new object[] { OnPauseStream, this, true };
                                netConnection.PostOnEventUserCallCodeMessage(message);
                            }
                        }
                    } //lock
                    break;
                case "NetStream.Unpause.Notify":
                    lock (lockVAR)
                    {
                        syncAfterPauseNeeded = true;
                        pauseIsActive = false;
                        Internal_OnPauseStream(false);
                        if (OnPauseStream != null)
                        {
                            MQ_RTMPMessage message = new MQ_RTMPMessage();
                            message.MethodCall = MethodCall.OnEventCallUserCode;
                            message.Params = new object[] { OnPauseStream, this, false };
                            netConnection.PostOnEventUserCallCodeMessage(message);
                        }
                    } //lock
                    break;

                case "NetStream.Play.Failed":
                case "NetStream.Play.StreamNotFound":
                case "NetStream.Failed":
                    break;
                case "NetStream.Play.Complete": // all data is send
                    lock (lockVAR)
                    {
                        seekIsActive = false; // safety
                    }
                    break;

            } //switch

            // Code can be eg:
            // "NetStream.Failed"
            // "NetStream.Play.Failed" 
            // "NetStream.Play.StreamNotFound" 
            // "NetConnection.Connect.InvalidApp"
            // "NetStream.Play.Start"
            // "NetStream.Publish.Start"
            // "NetStream.Play.Complete" //audio
            // "NetStream.Play.Stop"     // audio
            // "NetStream.Pause.Notify"
            // "NetStream.Seek.Notify"

            return true;
        }
Ejemplo n.º 10
0
        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] // hide it for code completion
        internal bool HandleOnStatus(RTMPPacket packet)
        {
            AMFObject obj = new AMFObject();
            int nRes = obj.Decode(packet.Body, 0, (int)packet.BodySize, false);
            if (nRes < 0)
            {
                return false;
            }

            // string method = obj.GetProperty(0).GetString(); // always onStatus
            int stream_id = packet.InfoField2;
            string code = obj.GetProperty(3).ObjectValue.GetProperty("code").StringValue;
            string level = obj.GetProperty(3).ObjectValue.GetProperty("level").StringValue;
            LibRTMPLogger.Log(LibRTMPLogLevel.Trace, string.Format("[CDR.LibRTMP.NetStream.HandleOnStatus] code :{0}, level: {1}", code, level));

            return Internal_HandleOnStatusDecoded(packet, "onStatus", code, level, obj);
        }
Ejemplo n.º 11
0
        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] // hide it for code completion
        virtual internal bool HandleOnID3(AMFObject obj)
        {
            LibRTMPLogger.Log(LibRTMPLogLevel.Trace, "[CDR.LibRTMP.NetConnection.NetStream.HandleOnID3]");
            obj.Dump();
            audioMetaData.Clear();
            audioMetaData.Valid = true;
            List<AMFObjectProperty> props = new List<AMFObjectProperty>();

            props.Clear();
            obj.FindMatchingProperty("v1SongTitle", props, 1);
            if (props.Count > 0)
            {
                audioMetaData.SongTitle = props[0].StringValue;
            }
            props.Clear();
            obj.FindMatchingProperty("v1LeadArtist", props, 1);
            if (props.Count > 0)
            {
                audioMetaData.LeadArtist = props[0].StringValue;
            }
            props.Clear();
            obj.FindMatchingProperty("v1AlbumTitle", props, 1);
            if (props.Count > 0)
            {
                audioMetaData.AlbumTitle = props[0].StringValue;
            }
            props.Clear();
            obj.FindMatchingProperty("v1YearReleased", props, 1);
            if (props.Count > 0)
            {
                audioMetaData.YearReleased = props[0].StringValue;
            }
            props.Clear();
            obj.FindMatchingProperty("v1SongComment", props, 1);
            if (props.Count > 0)
            {
                audioMetaData.SongComment = props[0].StringValue;
            }
            props.Clear();
            obj.FindMatchingProperty("v1SongGenre", props, 1);
            if (props.Count > 0)
            {
                audioMetaData.SongGenre = props[0].StringValue;
            }
            props.Clear();
            obj.FindMatchingProperty("v1TrackNumberOnAlbum", props, 1);
            if (props.Count > 0)
            {
                audioMetaData.TrackNumberOnAlbum = props[0].StringValue;
            }


            // handle event
            if (OnID3 != null)
            {
                MQ_RTMPMessage message = new MQ_RTMPMessage();
                message.MethodCall = MethodCall.OnEventCallUserCode;
                message.Params = new object[] { OnID3, this, (AudioMetaData)audioMetaData.Clone(), obj };
                netConnection.PostOnEventUserCallCodeMessage(message);
            }

            return true;
        }
Ejemplo n.º 12
0
        public int Decode(byte[] buffer, int bufferOffset, int size, bool bDecodeName)
        {
            int originalSize = size;

            if (size == 0 || buffer == null)
            {
                return(-1);
            }

            if (buffer[bufferOffset] == 0x05)
            {
                type = AMFDataType.AMF_NULL;
                return(1);
            }

            if (bDecodeName && size < 4) // at least name (length + at least 1 byte) and 1 byte of data
            {
                return(-1);
            }

            if (bDecodeName)
            {
                ushort nNameSize = RTMPHelper.ReadInt16(buffer, bufferOffset);
                if (nNameSize > size - (short)sizeof(short))
                {
                    return(-1);
                }

                stringName    = RTMPHelper.ReadString(buffer, bufferOffset);
                size         -= sizeof(short) + stringName.Length;
                bufferOffset += sizeof(short) + stringName.Length;
            }

            if (size == 0)
            {
                return(-1);
            }

            size--;

            int stringSize = 0;
            int result     = 0;

            switch (buffer[bufferOffset])
            {
            case (byte)AMFDataType.AMF_NUMBER:
                if (size < (int)sizeof(double))
                {
                    return(-1);
                }
                numVal = RTMPHelper.ReadNumber(buffer, bufferOffset + 1);
                size  -= sizeof(double);
                type   = AMFDataType.AMF_NUMBER;
                break;

            case (byte)AMFDataType.AMF_BOOLEAN:
                if (size < 1)
                {
                    return(-1);
                }
                numVal = Convert.ToDouble(RTMPHelper.ReadBool(buffer, bufferOffset + 1));
                size--;
                type = AMFDataType.AMF_BOOLEAN;
                break;

            case (byte)AMFDataType.AMF_STRING:
                stringSize = RTMPHelper.ReadInt16(buffer, bufferOffset + 1);
                if (size < stringSize + (int)sizeof(short))
                {
                    return(-1);
                }
                stringVal = RTMPHelper.ReadString(buffer, bufferOffset + 1);
                size     -= sizeof(short) + stringSize;
                type      = AMFDataType.AMF_STRING;
                break;

            case (byte)AMFDataType.AMF_OBJECT:
                objVal = new AMFObject();
                result = objVal.Decode(buffer, bufferOffset + 1, size, true);
                if (result == -1)
                {
                    return(-1);
                }
                size -= result;
                type  = AMFDataType.AMF_OBJECT;
                break;

            case (byte)AMFDataType.AMF_MOVIECLIP:
                LibRTMPLogger.Log(LibRTMPLogLevel.Trace, "AMF_MOVIECLIP reserved!");
                return(-1);

            case (byte)AMFDataType.AMF_NULL:
            case (byte)AMFDataType.AMF_UNDEFINED:
            case (byte)AMFDataType.AMF_UNSUPPORTED:
                type = AMFDataType.AMF_NULL;
                break;

            case (byte)AMFDataType.AMF_REFERENCE:
                LibRTMPLogger.Log(LibRTMPLogLevel.Trace, "AMF_REFERENCE not supported!");
                return(-1);

            case (byte)AMFDataType.AMF_ECMA_ARRAY:
                size -= 4;

                // next comes the rest, mixed array has a final 0x000009 mark and names, so its an object
                objVal = new AMFObject();
                result = objVal.Decode(buffer, bufferOffset + 5, size, true);
                if (result == -1)
                {
                    return(-1);
                }
                size -= result;
                type  = AMFDataType.AMF_OBJECT;
                break;

            case (byte)AMFDataType.AMF_OBJECT_END:
                return(-1);

            case (byte)AMFDataType.AMF_STRICT_ARRAY:
                int nArrayLen = RTMPHelper.ReadInt32(buffer, bufferOffset + 1);
                size -= 4;

                objVal = new AMFObject();
                result = objVal.DecodeArray(buffer, bufferOffset + 5, size, nArrayLen, false);
                if (result == -1)
                {
                    return(-1);
                }
                size -= result;
                type  = AMFDataType.AMF_OBJECT;
                break;

            case (byte)AMFDataType.AMF_DATE:
                if (size < 10)
                {
                    return(-1);
                }
                date          = RTMPHelper.ReadNumber(buffer, bufferOffset + 1);
                dateUTCOffset = RTMPHelper.ReadInt16(buffer, bufferOffset + 9);
                size         -= 10;
                break;

            case (byte)AMFDataType.AMF_LONG_STRING:
                stringSize = RTMPHelper.ReadInt32(buffer, bufferOffset + 1);
                if (size < stringSize + 4)
                {
                    return(-1);
                }
                stringVal = RTMPHelper.ReadLongString(buffer, bufferOffset + 1);
                size     -= (4 + stringSize);
                type      = AMFDataType.AMF_STRING;
                break;

            case (byte)AMFDataType.AMF_RECORDSET:
                LibRTMPLogger.Log(LibRTMPLogLevel.Trace, "AMFObjectProperty.Decode AMF_RECORDSET reserved!");
                return(-1);

            case (byte)AMFDataType.AMF_XML_DOC:
                LibRTMPLogger.Log(LibRTMPLogLevel.Trace, "AMFObjectProperty.Decode AMF_XML_DOC not supported!");
                return(-1);

            case (byte)AMFDataType.AMF_TYPED_OBJECT:
                LibRTMPLogger.Log(LibRTMPLogLevel.Trace, "AMFObjectProperty.Decode AMF_TYPED_OBJECT not supported!");
                return(-1);

            default:
                LibRTMPLogger.Log(LibRTMPLogLevel.Trace, string.Format("AMFObjectProperty.Decode Unknown datatype {0}", buffer[bufferOffset]));
                return(-1);
            } //switch

            return(originalSize - size);
        }
Ejemplo n.º 13
0
 public void Clear()
 {
     Event = string.Empty;
     Code = string.Empty;
     Level = string.Empty;
     EventInfo = null;
 }
Ejemplo n.º 14
0
 public void Reset()
 {
     numVal = 0.0;
     stringVal = "";
     objVal = null;
     type = AMFDataType.AMF_INVALID;
 }
Ejemplo n.º 15
0
        public int Decode(byte[] buffer, int bufferOffset, int size, bool bDecodeName)
        {
            int originalSize = size;

            if (size == 0 || buffer == null)
            {
                return -1;
            }

            if (buffer[bufferOffset] == 0x05)
            {
                type = AMFDataType.AMF_NULL;
                return 1;
            }

            if (bDecodeName && size < 4) // at least name (length + at least 1 byte) and 1 byte of data
            {
                return -1;
            }

            if (bDecodeName)
            {
                ushort nNameSize = RTMPHelper.ReadInt16(buffer, bufferOffset);
                if (nNameSize > size - (short)sizeof(short))
                {
                    return -1;
                }

                stringName = RTMPHelper.ReadString(buffer, bufferOffset);
                size -= sizeof(short) + stringName.Length;
                bufferOffset += sizeof(short) + stringName.Length;
            }

            if (size == 0)
            {
                return -1;
            }

            size--;

            int stringSize = 0;
            int result = 0;
            switch (buffer[bufferOffset])
            {
                case (byte)AMFDataType.AMF_NUMBER:
                    if (size < (int)sizeof(double))
                    {
                        return -1;
                    }
                    numVal = RTMPHelper.ReadNumber(buffer, bufferOffset + 1);
                    size -= sizeof(double);
                    type = AMFDataType.AMF_NUMBER;
                    break;
                case (byte)AMFDataType.AMF_BOOLEAN:
                    if (size < 1)
                    {
                        return -1;
                    }
                    numVal = Convert.ToDouble(RTMPHelper.ReadBool(buffer, bufferOffset + 1));
                    size--;
                    type = AMFDataType.AMF_BOOLEAN;
                    break;
                case (byte)AMFDataType.AMF_STRING:
                    stringSize = RTMPHelper.ReadInt16(buffer, bufferOffset + 1);
                    if (size < stringSize + (int)sizeof(short))
                    {
                        return -1;
                    }
                    stringVal = RTMPHelper.ReadString(buffer, bufferOffset + 1);
                    size -= sizeof(short) + stringSize;
                    type = AMFDataType.AMF_STRING;
                    break;
                case (byte)AMFDataType.AMF_OBJECT:
                    objVal = new AMFObject();
                    result = objVal.Decode(buffer, bufferOffset + 1, size, true);
                    if (result == -1)
                    {
                        return -1;
                    }
                    size -= result;
                    type = AMFDataType.AMF_OBJECT;
                    break;

                case (byte)AMFDataType.AMF_MOVIECLIP:
                    LibRTMPLogger.Log(LibRTMPLogLevel.Trace, "AMF_MOVIECLIP reserved!");
                    return -1;
                case (byte)AMFDataType.AMF_NULL:
                case (byte)AMFDataType.AMF_UNDEFINED:
                case (byte)AMFDataType.AMF_UNSUPPORTED:
                    type = AMFDataType.AMF_NULL;
                    break;
                case (byte)AMFDataType.AMF_REFERENCE:
                    LibRTMPLogger.Log(LibRTMPLogLevel.Trace, "AMF_REFERENCE not supported!");
                    return -1;
                case (byte)AMFDataType.AMF_ECMA_ARRAY:
                    size -= 4;

                    // next comes the rest, mixed array has a final 0x000009 mark and names, so its an object
                    objVal = new AMFObject();
                    result = objVal.Decode(buffer, bufferOffset + 5, size, true);
                    if (result == -1)
                    {
                        return -1;
                    }
                    size -= result;
                    type = AMFDataType.AMF_OBJECT;
                    break;
                case (byte)AMFDataType.AMF_OBJECT_END:
                    return -1;
                case (byte)AMFDataType.AMF_STRICT_ARRAY:
                    int nArrayLen = RTMPHelper.ReadInt32(buffer, bufferOffset + 1);
                    size -= 4;

                    objVal = new AMFObject();
                    result = objVal.DecodeArray(buffer, bufferOffset + 5, size, nArrayLen, false);
                    if (result == -1)
                    {
                        return -1;
                    }
                    size -= result;
                    type = AMFDataType.AMF_OBJECT;
                    break;
                case (byte)AMFDataType.AMF_DATE:
                    if (size < 10)
                    {
                        return -1;
                    }
                    date = RTMPHelper.ReadNumber(buffer, bufferOffset + 1);
                    dateUTCOffset = RTMPHelper.ReadInt16(buffer, bufferOffset + 9);
                    size -= 10;
                    break;
                case (byte)AMFDataType.AMF_LONG_STRING:
                    stringSize = RTMPHelper.ReadInt32(buffer, bufferOffset + 1);
                    if (size < stringSize + 4)
                    {
                        return -1;
                    }
                    stringVal = RTMPHelper.ReadLongString(buffer, bufferOffset + 1);
                    size -= (4 + stringSize);
                    type = AMFDataType.AMF_STRING;
                    break;
                case (byte)AMFDataType.AMF_RECORDSET:
                    LibRTMPLogger.Log(LibRTMPLogLevel.Trace, "AMFObjectProperty.Decode AMF_RECORDSET reserved!");
                    return -1;
                case (byte)AMFDataType.AMF_XML_DOC:
                    LibRTMPLogger.Log(LibRTMPLogLevel.Trace, "AMFObjectProperty.Decode AMF_XML_DOC not supported!");
                    return -1;
                case (byte)AMFDataType.AMF_TYPED_OBJECT:
                    LibRTMPLogger.Log(LibRTMPLogLevel.Trace, "AMFObjectProperty.Decode AMF_TYPED_OBJECT not supported!");
                    return -1;
                default:
                    LibRTMPLogger.Log(LibRTMPLogLevel.Trace, string.Format("AMFObjectProperty.Decode Unknown datatype {0}", buffer[bufferOffset]));
                    return -1;
            } //switch

            return originalSize - size;
        }