Problem get RTSP Stream from network cameras

Topics: Question
Nov 17, 2015 at 1:49 PM
Hello,

thanks for your great libary.

I have create my own litte application but i have a problem with our network cameras.
Always when i connect to the rtsp server with vlc or smplayer i receive the following error message from my application:


Server Started @ 17.11.2015 13:47:07
Starting Stream: live1 Id=73bac4fb-2de7-4966-be4b-6bd71254a252
RTSP Server started...
Adding Client: 6416ffb2-1cb8-4a37-8440-e05a00129f53
Accepted Client: 6416ffb2-1cb8-4a37-8440-e05a00129f53 @ 17.11.2015 13:47:10 Added =True
Request=> OPTIONS rtsp://127.0.0.1/ RTSP/1.0
CSeq: 1
User-Agent: RealMedia Player Version 6.0.9.1235 (linux-2.0-libc6-i386-gcc2.95)
ClientChallenge: 9e26d33f2984236010ef6253fb1887f7
PlayerStarttime: [28/03/2003:22:50:23 00:00]
CompanyID: KnKV4M4I/B2FjJ1TToLycw==
GUID: 00000000-0000-0000-0000-000000000000
RegionData: 0
ClientID: Linux_2.4_6.0.9.1235_play32_RN01_EN_586

Session=> 6416ffb2-1cb8-4a37-8440-e05a00129f53

Response=> RTSP/1.0 200 OK
CSeq: 1
Public: OPTIONS, DESCRIBE, SETUP, PLAY, PAUSE, TEARDOWN, GET_PARAMETER
Allow: ANNOUNCE, RECORD, SET_PARAMETER
Server: ASTI Media Server RTSP 1.0
Date: Tue, 17 Nov 2015 13:47:10 GMT

Session=> 6416ffb2-1cb8-4a37-8440-e05a00129f53

Request=> DESCRIBE rtsp://127.0.0.1/live/live1 RTSP/1.0
CSeq: 2
Accept: application/sdp

Session=> 6416ffb2-1cb8-4a37-8440-e05a00129f53

Response=> RTSP/1.0 412 PreconditionFailed
CSeq: 2
Server: ASTI Media Server RTSP 1.0
Date: Tue, 17 Nov 2015 13:47:10 GMT

Session=> 6416ffb2-1cb8-4a37-8440-e05a00129f53

Adding Client: 0df4b7b9-281c-43a9-b91e-39e1061fdb38
Request=> DESCRIBE rtsp://127.0.0.1/live/live1 RTSP/1.0
CSeq: 2
User-Agent: MPlayer (LIVE555 Streaming Media v2013.04.30)
Accept: application/sdp

Session=> 0df4b7b9-281c-43a9-b91e-39e1061fdb38

Accepted Client: 0df4b7b9-281c-43a9-b91e-39e1061fdb38 @ 17.11.2015 13:47:10 Added =True
Response=> RTSP/1.0 412 PreconditionFailed
CSeq: 2
Server: ASTI Media Server RTSP 1.0
Date: Tue, 17 Nov 2015 13:47:10 GMT

Session=> 0df4b7b9-281c-43a9-b91e-39e1061fdb38

Eine vorhandene Verbindung wurde vom Remotehost geschlossen
bei System.Net.Sockets.Socket.DoBeginReceiveFrom(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, EndPoint endPointSnapshot, SocketAddress socketAddress, OverlappedAsyncResult asyncResult)
bei System.Net.Sockets.Socket.BeginReceiveFrom(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, EndPoint& remoteEP, AsyncCallback callback, Object state)
bei Media.Rtsp.ClientSession.StartReceive() in c:\Users\abeckers\Downloads\net7mma-111212\RtspServer\ClientSession.cs:Zeile 281.
bei Media.Rtsp.RtspServer.ProcessSendComplete(IAsyncResult ar) in c:\Users\abeckers\Downloads\net7mma-111212\RtspServer\RtspServer.cs:Zeile 1572.


Marking Client:0df4b7b9-281c-43a9-b91e-39e1061fdb38 Disconnected



What does mena the error message: RTSP/1.0 412 PreconditionFailed ?
When i use a demo url from the internet the the application works fine.

Can you help me?

Here is the really short code:
            string context = "live1";
            string rtsp_url = "rtsp://192.168.88.141/axis-media/media.amp?streamprofile=Quality ";
            string rtsp_user = "root";
            string rtsp_password = "root";
            int rtsp_port = 554;

            String[] arguments = Environment.GetCommandLineArgs();

            /* Parameter filtern */
            for (int argc = 1; argc < arguments.Length; argc++)
            {
                string line = arguments[argc];

                /* Nun den Parameter auseinander nehmen und filtern */
                StringTokenizer st = new StringTokenizer(line, "=", false);
                if (st.CountTokens() == 2)
                {
                    string key = st.NextToken().Trim();
                    string par = st.NextToken().Trim();

                    //bStartParamater = true;

                    /* - entfernen */
                    if (key.StartsWith("-"))
                    {
                        key = key.Remove(0, 1);
                    }

                    if (key.ToUpper().Equals("context"))
                    {
                        context = par;
                    }
                    else if (key.ToUpper().Equals("RTSP_URL"))
                    {
                        rtsp_url = par;
                    }
                    else if (key.ToUpper().Equals("RTSP_PORT"))
                    {
                        rtsp_port = Convert.ToInt32(par);
                    }
                    else if (key.ToUpper().Equals("RTSP_USER"))
                    {
                        rtsp_user = par;
                    }
                    else if (key.ToUpper().Equals("RTSP_PASSWORD"))
                    {
                        rtsp_password = par;
                    }
                }
            }
            //Setup a Media.RtspServer on port 554
            using (Media.Rtsp.RtspServer server = new Media.Rtsp.RtspServer(System.Net.IPAddress.Any, rtsp_port)
            {
                //new Media.Rtsp.Server.RtspServerDebuggingLogger() 
                Logger = new Media.Rtsp.Server.RtspServerConsoleLogger()
            })
            {
                Media.Rtsp.Server.MediaTypes.RtspSource source = new Media.Rtsp.Server.MediaTypes.RtspSource(context, rtsp_url, Media.Rtsp.RtspClient.ClientProtocolType.Tcp, Media.Rtsp.RtspMessage.MaximumLength * 4);

                //If the stream had a username and password
                source.SourceCredential = new System.Net.NetworkCredential(rtsp_user, rtsp_password);
                source.SourceAuthenticationScheme = System.Net.AuthenticationSchemes.Basic;

                server.TryAddMedia(source);

                //Start the server and underlying streams
                server.Start();

                while (!server.IsRunning)
                {
                    Console.WriteLine("RTSP Server starting...");
                    Thread.Sleep(0);
                }
                Console.WriteLine("RTSP Server started..."); 
                Console.ReadKey();
                server.Stop();
                Console.WriteLine("RTSP Server stopped!");
            }
Coordinator
Nov 17, 2015 at 2:57 PM
I am planning to release some updates shortly for this library.

I am not seeing anything in your code example which would cause the Precondition failed, I also don't usually encounter such an issue myself.

I have encountered it before, essentially what occurred in my instance is that a stream was running but somehow stopped either due to it's own connection faulting or to another reason.

The server runs a timer to start streams which are faulted, if you try to play a faulted stream you will receive the Precondition failed error.

It may be that the stream is not successfully starting, check 'source.Ready' and see what it returns, my guess is that it will be false and this will lead you to why the stream is not able to be played back.

If you need anything else let me know and keep an eye out for updates.
Marked as answer by juliusfriedman on 11/17/2015 at 6:57 AM
Nov 17, 2015 at 3:11 PM
Hi, thanks for the fast answer.

I have add the following lines to my code:
                server.Start();

                Console.WriteLine("source.Ready = " + source.Ready);
                while (!source.Ready)
                {
                    Console.WriteLine("source.Ready = " + source.Ready);
                    Thread.Sleep(100);
                }
                Console.WriteLine("source.Ready = " + source.Ready);

                while (!server.IsRunning)
                {
                    Console.WriteLine("RTSP Server starting...");
                    Thread.Sleep(0);
                }
                Console.WriteLine("RTSP Server started..."); 
                Console.ReadKey();
                server.Stop();
                Console.WriteLine("RTSP Server stopped!");
So, i test it several times. Sometimes the output is:

Server Started @ 17.11.2015 15:09:58
Starting Stream: live1 Id=88466d02-122d-4183-a52d-e03b79df5e9b
source.Ready = False
source.Ready = False
source.Ready = False
source.Ready = False
source.Ready = False
source.Ready = False
source.Ready = False
source.Ready = False
source.Ready = False
source.Ready = False
source.Ready = False
source.Ready = False
source.Ready = True
RTSP Server started...

Then all is fine and the server is runing.
But in most times source ready always is false.
Nov 17, 2015 at 3:12 PM
I have another question.
Is there anywhere a good example or code print what i must do to show the video (RTSP/H264) in a picturebox control?
Coordinator
Nov 17, 2015 at 7:25 PM
It seems your sources takes a few moments to start, you will need to wait for the source to start before it can be consumed.

For the H.264 you may want to see this thread.

http://net7mma.codeplex.com/discussions/569279

If you need anything else let me know.
Marked as answer by juliusfriedman on 11/17/2015 at 11:25 AM
Nov 17, 2015 at 7:40 PM
No not really. When i start the server in most times the source is endless not ready. I run the programm over 4-5 minutes and the state doesn't change to true.
So i think it is not only a problem from the source.

Thanks for the link, i will check it.
Coordinator
Nov 17, 2015 at 7:54 PM
I am not sure why you think that, you can confirm this with a demo source
var source = new Media.Rtsp.Server.MediaTypes.RtspSource("Omega", "rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov");

if(false == server.TryAddMedia(source)) {

Console.WriteLine("Source Already Added");

return;

}

server.Start();

Console.WriteLine("Waiting for source...");

while(source.Ready == false) Thread.Sleep(10);

Console.WriteLine("Source Ready...");
You will see that should eventually show "Source Ready" on the console, if not then there is a problem.

There was a few bugs which may have effected streams with 'PerPacket' but I don't think your using that option, either way see the updates posted on the patch page and check back for a new release of the library soon which may address that issue.
Marked as answer by juliusfriedman on 11/17/2015 at 11:54 AM
Nov 17, 2015 at 8:13 PM
Hi, thanks for your answer. With this URL i don't have the problem. i have checked bevor.
But with netcameras from Axis and HIk i have the posted problem.
Sometimes after an few seconds the source is ready but mostly it never becomes the state true.

I use your version 111212. Is there a newer one?
Coordinator
Nov 17, 2015 at 8:19 PM
Not at this time, in the next week or so there should be an updated version.
Marked as answer by juliusfriedman on 11/17/2015 at 12:19 PM
Nov 17, 2015 at 8:24 PM
Ok, thanks. I will look at the patches site and tomorrow i will test more.
I read your link with the h264 frame but there are so many code samples and i don't really know which one is working well.
Do i need the CSCODECS or is there an easier solution?
Coordinator
Nov 17, 2015 at 8:28 PM
Edited Nov 17, 2015 at 8:29 PM
The latest sample should work fine.

The 'CSCODECS' solution you referenced is from where the H.264 decoder was tested, I think actually it was a PSP emulator, either way that thread contains whatever information is relevant to such.

I am going to eventually have something for H.264 decoding in purely managed code along with other features I just have been very busy with things outside this project and just now am starting to get some additional free time to work on it again.

I would expect updates around Thanksgiving but they won't include anything for Encoding or Decoding until a bit later.

Let me know if you run into anything else!
Marked as answer by juliusfriedman on 11/17/2015 at 12:28 PM
Nov 17, 2015 at 8:32 PM
The latest sample you post or from other user?
Coordinator
Nov 17, 2015 at 8:36 PM
The latest sample I posted on that thread, towards the end. It's very similar to the others either way, you will notice if the correct one because it will have code the earlier methods don't.
Marked as answer by juliusfriedman on 11/17/2015 at 12:36 PM
Nov 18, 2015 at 8:31 AM
Hi,

i want to test some of your newest patches, but with them i have compiler errors.

I read your post and copy and add the following code to my winform example.
I have a question. The variable thisIsTheFirstWriteToTheFile has never change the state. Where must i do this? And ist it not better to check if the frame is complete?
Writing the buffer to file works with this code fine, i can play the file with vlc.

When i understood it correct i must use some codecs to display the video into a picturebox element?
The cscodec lib use some GPL stuff if i see it correct, so it's not an possible solution for me.
Do you have alternatives?
        private void Client_RtpFrameChanged(object sender, Media.Rtp.RtpFrame frame)
        {
            try
            {
                var context = ((Media.Rtp.RtpClient)sender).GetContextByPayloadType(frame.PayloadTypeByte);
                if (context == null || context.MediaDescription.MediaType != Media.Sdp.MediaType.video) return;

                using (Media.Rtsp.Server.MediaTypes.RFC6184Media.RFC6184Frame hframe = new Media.Rtsp.Server.MediaTypes.RFC6184Media.RFC6184Frame(frame))
                {
                    if (thisIsTheFirstWriteToTheFile)
                    {
                        Media.Sdp.SessionDescriptionLine fmtp = context.MediaDescription.FmtpLine;

                        byte[] sps = null, pps = null;

                        foreach (string p in fmtp.Parts)
                        {
                            string trim = p.Trim();
                            if (trim.StartsWith("sprop-parameter-sets=", StringComparison.InvariantCultureIgnoreCase))
                            {
                                string[] data = trim.Replace("sprop-parameter-sets=", string.Empty).Split(',');
                                sps = System.Convert.FromBase64String(data[0]);
                                pps = System.Convert.FromBase64String(data[1]);
                                break;
                            }
                        }

                        bool hasSps, hasPps, sei, slice, idr;

                        hframe.Depacketize();
                        hasSps = hframe.ContainsSequenceParameterSet;
                        hasPps = hframe.ContainsPictureParameterSet;
                        sei = hframe.ContainsSupplementalEncoderInformation;
                        slice = hframe.ContainsCodedSlice;
                        idr = hframe.ContainsInstantaneousDecoderRefresh;

                        /* compiler error! 
                        bool hasSps, hasPps, sei, slice, idr;
                        hframe.Depacketize(out hasSps, out hasPps, out sei, out slice, out idr);
                        */

                        using (var stream = new System.IO.MemoryStream())
                        {
                            if (!hasSps && sps != null)
                            {
                                stream.Write(new byte[] { 0x00, 0x00, 0x00, 0x01 }, 0, 4);

                                stream.Write(sps, 0, sps.Length);
                            }

                            if (!hasPps && pps != null)
                            {
                                stream.Write(new byte[] { 0x00, 0x00, 0x00, 0x01 }, 0, 4);

                                stream.Write(pps, 0, pps.Length);
                            }

                            hframe.Buffer.CopyTo(stream);
                            stream.Position = 0;

                            //Write All Bytes stream
                            using (var fs = new FileStream(string.Format("d:\\video.h264"), FileMode.Append))
                            {
                                byte[] buffer = new byte[stream.Length];

                                //  stream.Seek(0, SeekOrigin.Begin);
                                stream.Read(buffer, 0, (int)stream.Length);
                                fs.Write(buffer, 0, buffer.Length);
                                fs.Flush();
                                fs.Close();
                            }
                        }
                    }
                    else
                    {
                        hframe.Depacketize();

                        //Append All Bytes hFrame.Buffer.ToArray()
                        AppendAllBytes("d:\\video.h264", hframe.Buffer.ToArray());
                    }
                }
            }
            catch (Exception)
            {

            }
        }

        public static void AppendAllBytes(string path, byte[] bytes)
        {
            //argument-checking here.

            using (var stream = new System.IO.FileStream(path, System.IO.FileMode.Append))
            {
                stream.Write(bytes, 0, bytes.Length);
            }
        }
Coordinator
Nov 18, 2015 at 7:12 PM
I think I already answered this for you, please let me know if thats not the case.
Marked as answer by juliusfriedman on 11/18/2015 at 11:12 AM
Nov 18, 2015 at 7:23 PM
Yes thats ok and i find your answer.

I have add the cscodec stuff and take your function but it is not really working.
The first frame create a valid picture, thats perfect. But the next frames thows exceptions.

Here the actual code:
        void Client_RtpFrameChanged(object sender, Media.Rtp.RtpFrame frame)
        {
            if (frame.IsComplete)
            {
                try
                {
                    var context = ((Media.Rtp.RtpClient)sender).GetContextByPayloadType(frame.PayloadTypeByte);
                    if (context == null || context.MediaDescription.MediaType != Media.Sdp.MediaType.video) return;

                    using (Media.Rtsp.Server.MediaTypes.RFC6184Media.RFC6184Frame hframe = new Media.Rtsp.Server.MediaTypes.RFC6184Media.RFC6184Frame(frame))
                    {
                        if (frameDecoder == null)
                        {
                            Media.Sdp.SessionDescriptionLine fmtp = context.MediaDescription.FmtpLine;

                            byte[] sps = null, pps = null;

                            foreach (string p in fmtp.Parts)
                            {
                                string trim = p.Trim();
                                if (trim.StartsWith("sprop-parameter-sets=", StringComparison.InvariantCultureIgnoreCase))
                                {
                                    string[] data = trim.Replace("sprop-parameter-sets=", string.Empty).Split(',');
                                    sps = System.Convert.FromBase64String(data[0]);
                                    pps = System.Convert.FromBase64String(data[1]);
                                    break;

                                }
                            }

                            //bool hasSps, hasPps, sei, slice, idr;
                            //hframe.Depacketize(out hasSps, out hasPps, out sei, out slice, out idr);

                            bool hasSps, hasPps, sei, slice, idr;

                            hframe.Depacketize();
                            hasSps = hframe.ContainsSequenceParameterSet;
                            hasPps = hframe.ContainsPictureParameterSet;
                            sei = hframe.ContainsSupplementalEncoderInformation;
                            slice = hframe.ContainsCodedSlice;
                            idr = hframe.ContainsInstantaneousDecoderRefresh;

                            using (var stream = new System.IO.MemoryStream())
                            {
                                if (!hasSps && sps != null)
                                {
                                    stream.Write(new byte[] { 0x00, 0x00, 0x00, 0x01 }, 0, 4);

                                    stream.Write(sps, 0, sps.Length);
                                }

                                if (!hasPps && pps != null)
                                {
                                    stream.Write(new byte[] { 0x00, 0x00, 0x00, 0x01 }, 0, 4);

                                    stream.Write(pps, 0, pps.Length);
                                }

                                hframe.Buffer.CopyTo(stream);
                                stream.Position = 0;
                                playStream(stream);
                            }
                        }
                        else
                        {
                            hframe.Depacketize();
                            playStream(hframe.Buffer);
                        }
                    }
                }
                catch
                {
                    return;
                }
            }
        }

        public bool playStream(Stream fin)
        {
            if (frameDecoder == null) frameDecoder = new FrameDecoder(fin);
            else frameDecoder.SetStream(fin);

            try
            {
                while (true)
                {
                    var picture = frameDecoder.DecodeFrame();

                    var Width = picture.imageWidthWOEdge;
                    var Height = picture.imageHeightWOEdge;

                    Console.WriteLine("image width=" + Width + " Height=" + Height);

                    pictureBoxVideo.Image = FrameUtils.imageFromFrame(picture);
                    pictureBoxVideo.Refresh();
                }
            }
            catch (EndOfStreamException)
            {
                //frameDecoder = null;
                return false;
            }
        }
Coordinator
Nov 19, 2015 at 3:17 PM
Sorry, I can't support CSCodec, if your getting an exception from that library try posting for help on that project's pages.
Marked as answer by juliusfriedman on 11/19/2015 at 7:17 AM
Coordinator
Nov 20, 2015 at 7:47 PM
I have just updated the source code, please let me know what you think!
Marked as answer by juliusfriedman on 11/20/2015 at 11:47 AM
Nov 22, 2015 at 3:25 PM
Hello,

thanks. Tomorrow i'am in my office and i will test the new version.
Nov 23, 2015 at 6:55 AM
Hi, i downloaded the source package but there are several compiler errors and missing files.
Nov 24, 2015 at 8:37 AM
hi julius,
i got the same compiler errors with 111767 as abeckers. Any new solutions?
Coordinator
Nov 24, 2015 at 1:50 PM
I linked to the thread previously I will do it again, https://net7mma.codeplex.com/discussions/569279.

It also really depends on what compiler errors you are getting, please remember the code is intended for 4.6.
Marked as answer by juliusfriedman on 11/24/2015 at 5:50 AM