MediaSuite.NET Sample code

RTP Reception, H.263 decoding and Display

This sample uses RTP.NET to receive incoming packets and stores them in a frame. After the frame is complete the data is decoded and displayed on the screen.

using System;
using System.Drawing;
using System.Windows.Forms;
using StreamCoders.Network;
using System.Net;
using StreamCoders.Decoder;
using System.Drawing.Imaging;
using StreamCoders;
 
/*
 * Receives RFC 2429/4629 Frames, runs them through the decoder and displays them.
 * 
 * */
 
namespace VideoReceiver
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
 
            isRunning = false;
        }
 
 
        private void CreateVideoDecoder()
        {
 
            videoDecoder = new H263Decoder();
            videoDecoder.SetInputFrameRate(10);
            videoDecoder.SetInputResolution(176, 144);
            videoDecoder.VideoSource = StreamSources.NETWORK_RTP;
            bool res = videoDecoder.Init();
            if (res == false)
            {
                MessageBox.Show("Unable to initialize decoder.");
                return;
            }
        }
 
        private void DeleteVideoDecoder()
        {
 
            H263Decoder h263 = (H263Decoder)videoDecoder;
            h263.Dispose();
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            CreateVideoDecoder();
            videoJitter = new System.Collections.Generic.SortedDictionary<UInt32, RTPFrame>();
 
            session = new RTPSession();
            receiver = new RTPReceiver();
            IPEndPoint rtpEp = new IPEndPoint(IPAddress.Parse(StreamCoders.Network.Helper.GetLocalIP()), 23150);
            participant = new RTPParticipant(rtpEp, null, null, null);
            session.NewRTPPacket = NewRTPPacket;
            session.NewRTCPPacket = null;
            receiver.AddParticipant(participant);
            session.AddReceiver(receiver);
 
            dImage = new Bitmap(videoDecoder.InputWidth, videoDecoder.InputHeight, PixelFormat.Format24bppRgb);
            dImageRect = new Rectangle(0, 0, videoDecoder.InputWidth, videoDecoder.InputHeight);
            pictureGraphics = pictureBox1.CreateGraphics();
 
            isRunning = true;
            videoThread = new System.Threading.Thread(new System.Threading.ThreadStart(VideoDecoderThread));
            videoThread.Start();
        }
 
        private bool NewRTPPacket(RTPPacket packet, byte[] rawBuffer)
        {
            //RTP2190 p = new RTP2190(packet);
            RTP4629 p = new RTP4629(packet);
 
            AddPacketToJitter(p);
            return true;
        }
 
        private void NewRTCPPacket(RTCPCompoundPacket packet)
        {
        }
 
        private void AddPacketToJitter(RTPPacket packet)
        {
            if (packet == null)
                return;
            lock (videoJitter)
            {
                if (videoJitter.ContainsKey(packet.Timestamp))
                {
                    RTPFrame f = videoJitter[packet.Timestamp];
                    f.AddPacket(packet);
                    return;
                }
 
                RTPFrame newFrame = null;
 
                newFrame = new RTPFrame();
                newFrame.AddPacket(packet);
                videoJitter[packet.Timestamp] = newFrame;
            }
        }
 
        private RTPFrame CheckJitterForCompleteFrame()
        {
            lock (videoJitter)
            {
                foreach (RTPFrame f in videoJitter.Values)
                {
                    if ((f.Age > jitterAgeThreshold && f.FrameComplete == true))
                    {
                        if (f.HasSequenceGaps)
                            sequenceErrors++;
                        videoJitter.Remove(f.Timestamp);
                        return f;
                    }
 
                    if (f.FrameComplete == true)
                        break;
                }
            }
            return null;
        }
 
        private void VideoDecoderThread()
        {
            int iterations = 1;
            while (isRunning)
            {
                iterations++;
                RTPFrame frame = CheckJitterForCompleteFrame();
 
                if (frame == null)
                {
                    System.Threading.Thread.Sleep(0);
                    continue;
                }
 
                byte[] asm = frame.GetAssembledFrame();
                if (asm == null)
                    continue;
 
 
                byte[] pic = videoDecoder.Decode(asm);
                if (pic == null)
                    continue;
                iterations++;
                MediaPackage mp = new MediaPackage();
                mp.Buffer = pic;
                DisplayPicture(mp);
            }
        }
 
        private void ShutdownThread()
        {
            session.Dispose();
            participant.Dispose();
            receiver.Dispose();
            isRunning = false;
            videoThread.Join();
            Application.Exit();
        }
 
        private void DisplayPicture(MediaPackage mp)
        {
            if (isRunning == false)
                return;
            picData = dImage.LockBits(dImageRect, ImageLockMode.ReadWrite, dImage.PixelFormat);
            System.Runtime.InteropServices.Marshal.Copy(mp.Buffer, 0, picData.Scan0, mp.Buffer.Length);
            dImage.UnlockBits(picData);
            picturesDisplayed++;
            this.Invoke((MethodInvoker)delegate
            {
                pictureGraphics.DrawImage(dImage, 0, 0, pictureBox1.Width, pictureBox1.Height);
            });
        }
 
 
        private RTPSession session;
        private RTPReceiver receiver;
        private RTPParticipant participant;
        private System.Collections.Generic.SortedDictionary<UInt32, RTPFrame> videoJitter;
        private StreamCoders.Decoder.VideoDecoderBase videoDecoder;
        bool isRunning;
        private BitmapData picData;
        private Bitmap dImage;
        private Rectangle dImageRect;
        private Graphics pictureGraphics;
        private System.Threading.Thread videoThread;
        private int picturesDisplayed;
        private int sequenceErrors;
        private int jitterAgeThreshold = 500;
 
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (isRunning)
            {
                System.Threading.Thread st = new System.Threading.Thread(new System.Threading.ThreadStart(ShutdownThread));
                st.Start();
                e.Cancel = true;
            }
 
        }
    }
}