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;
}
}
}
}