Powered by Blogger.

Video Streaming with Gstreamer - 02

Monday, December 31, 2012

Today I completed the code to send 4 videos from one machine to another using RTP/RTCP with Python and Gstreamer.

Following figure shows the pipeline connectivity.



Here is the code:

#!/usr/bin/python

import pygst
pygst.require("0.10")
import gst
import pygtk
import gtk

class Main:
    def __init__(self):
       
       def onPad(obj, pad, target):
           sinkpad = target.get_compatible_pad(pad, pad.get_caps())
           if sinkpad:
               pad.link(sinkpad)
           print "pad added"
           print obj
           return True
  
       self.pipeline = gst.Pipeline("mypipeline")

       # video 1
       self.src1 = gst.element_factory_make("filesrc", "filesrc1")
       self.src1.set_property("location", "x101.avi")
       self.decodebin1 = gst.element_factory_make("decodebin")
       self.encoder1 = gst.element_factory_make("x264enc")
       self.rtp_payload1 = gst.element_factory_make("rtph264pay")
       self.rtpbin1 = gst.element_factory_make("gstrtpbin")
       self.udpsink11 = gst.element_factory_make("udpsink")
       self.udpsink11.set_property("host", "192.168.1.104")
       self.udpsink11.set_property("port", 5011)
       self.udpsink12 = gst.element_factory_make("udpsink")
       self.udpsink12.set_property("host", "192.168.1.104")
       self.udpsink12.set_property("port", 5012)
       self.udpsrc1 = gst.element_factory_make("udpsrc")
       self.udpsrc1.set_property("port", 5013)
       self.pipeline.add_many(self.src1, self.decodebin1, self.encoder1, \
                             self.rtp_payload1, self.rtpbin1, self.udpsink11, self.udpsink12, self.udpsrc1)
      
       # video 1 linking
       self.src1.link(self.decodebin1)
       self.decodebin1.connect("pad-added", onPad, self.encoder1)
       self.encoder1.link(self.rtp_payload1)
       self.rtp_payload1.link_pads('src', self.rtpbin1, 'send_rtp_sink_0')
       self.rtpbin1.link_pads('send_rtp_src_0', self.udpsink11, 'sink')
       self.rtpbin1.link_pads('send_rtcp_src_0', self.udpsink12, 'sink')
       self.udpsrc1.link_pads('src', self.rtpbin1, 'recv_rtcp_sink_0')
       
       # video 2
       self.src2 = gst.element_factory_make("filesrc", "filesrc2")
       self.src2.set_property("location", "x102.avi")
       self.decodebin2 = gst.element_factory_make("decodebin")
       self.encoder2 = gst.element_factory_make("x264enc")
       self.rtp_payload2 = gst.element_factory_make("rtph264pay")
       self.rtpbin2 = gst.element_factory_make("gstrtpbin")
       self.udpsink21 = gst.element_factory_make("udpsink")
       self.udpsink21.set_property("host", "192.168.1.104")
       self.udpsink21.set_property("port", 5021)
       self.udpsink22 = gst.element_factory_make("udpsink")
       self.udpsink22.set_property("host", "192.168.1.104")
       self.udpsink22.set_property("port", 5022)
       self.udpsrc2 = gst.element_factory_make("udpsrc")
       self.udpsrc2.set_property("port", 5023)
       self.pipeline.add_many(self.src2, self.decodebin2, self.encoder2, \
                             self.rtp_payload2, self.rtpbin2, self.udpsink21, self.udpsink22, self.udpsrc2)
      
       # video 2 linking
       self.src2.link(self.decodebin2)
       self.decodebin2.connect("pad-added", onPad, self.encoder2)
       self.encoder2.link(self.rtp_payload2)
       self.rtp_payload2.link_pads('src', self.rtpbin2, 'send_rtp_sink_0')
       self.rtpbin2.link_pads('send_rtp_src_0', self.udpsink21, 'sink')
       self.rtpbin2.link_pads('send_rtcp_src_0', self.udpsink22, 'sink')
       self.udpsrc2.link_pads('src', self.rtpbin2, 'recv_rtcp_sink_0')
       
       # video 3
       self.src3 = gst.element_factory_make("filesrc", "filesrc3")
       self.src3.set_property("location", "x103.avi")
       self.decodebin3 = gst.element_factory_make("decodebin")
       self.encoder3 = gst.element_factory_make("x264enc")
       self.rtp_payload3 = gst.element_factory_make("rtph264pay")
       self.rtpbin3 = gst.element_factory_make("gstrtpbin")
       self.udpsink31 = gst.element_factory_make("udpsink")
       self.udpsink31.set_property("host", "192.168.1.104")
       self.udpsink31.set_property("port", 5031)
       self.udpsink32 = gst.element_factory_make("udpsink")
       self.udpsink32.set_property("host", "192.168.1.104")
       self.udpsink32.set_property("port", 5032)
       self.udpsrc3 = gst.element_factory_make("udpsrc")
       self.udpsrc3.set_property("port", 5033)
       self.pipeline.add_many(self.src3, self.decodebin3, self.encoder3, \
                             self.rtp_payload3, self.rtpbin3, self.udpsink31, self.udpsink32, self.udpsrc3)
      
       # video 3 linking
       self.src3.link(self.decodebin3)
       self.decodebin3.connect("pad-added", onPad, self.encoder3)
       self.encoder3.link(self.rtp_payload3)
       self.rtp_payload3.link_pads('src', self.rtpbin3, 'send_rtp_sink_0')
       self.rtpbin3.link_pads('send_rtp_src_0', self.udpsink31, 'sink')
       self.rtpbin3.link_pads('send_rtcp_src_0', self.udpsink32, 'sink')
       self.udpsrc3.link_pads('src', self.rtpbin3, 'recv_rtcp_sink_0')
       
       # video 4
       self.src4 = gst.element_factory_make("filesrc", "filesrc4")
       self.src4.set_property("location", "x104.avi")
       self.decodebin4 = gst.element_factory_make("decodebin")
       self.encoder4 = gst.element_factory_make("x264enc")
       self.rtp_payload4 = gst.element_factory_make("rtph264pay")
       self.rtpbin4 = gst.element_factory_make("gstrtpbin")
       self.udpsink41 = gst.element_factory_make("udpsink")
       self.udpsink41.set_property("host", "192.168.1.104")
       self.udpsink41.set_property("port", 5041)
       self.udpsink42 = gst.element_factory_make("udpsink")
       self.udpsink42.set_property("host", "192.168.1.104")
       self.udpsink42.set_property("port", 5042)
       self.udpsrc4 = gst.element_factory_make("udpsrc")
       self.udpsrc4.set_property("port", 5043)
       self.pipeline.add_many(self.src4, self.decodebin4, self.encoder4, \
                             self.rtp_payload4, self.rtpbin4, self.udpsink41, self.udpsink42, self.udpsrc4)
      
       # video 4 linking
       self.src4.link(self.decodebin4)
       self.decodebin4.connect("pad-added", onPad, self.encoder4)
       self.encoder4.link(self.rtp_payload4)
       self.rtp_payload4.link_pads('src', self.rtpbin4, 'send_rtp_sink_0')
       self.rtpbin4.link_pads('send_rtp_src_0', self.udpsink41, 'sink')
       self.rtpbin4.link_pads('send_rtcp_src_0', self.udpsink42, 'sink')
       self.udpsrc4.link_pads('src', self.rtpbin4, 'recv_rtcp_sink_0')
      
       self.pipeline.set_state(gst.STATE_PLAYING)
  
start = Main()
gtk.main()



Video Streaming with Gstreamer - 01

Tuesday, December 4, 2012

I wanted to send a video through the network few days back, on Ubuntu using Python. It took a several days to figure out how to perform such a task. I found out that Gstreamer is a good tool to start with, it has many capabilities. Today I was able to complete what I wanted to do, sending a video and receiving in the other end. Still work is not finished, I need to synchronize several streams together at the receiver as well. I will keep updating the progress and any interesting findings. So this will be a start of several future posts.

Please note that I am still new to this particular field, the purpose of this post is just sharing my experience with others. Please correct me if you find any mistakes or wrong ways of doing things in this post.

1. Sending a video file from a PC to another PC through network or Internet

Receiver's IP is 192.168.1.104. I used following codes in the Ubuntu terminal.

This is the sender's code:

gst-launch -v \
filesrc location=/home/x101.avi ! \
decodebin ! \
x264enc ! \
rtph264pay ! \
udpsink host=192.168.1.104 port=5000

This is the receiver's code:

gst-launch \
udpsrc port=5000 caps = "application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, sprop-parameter-sets=(string)\"Z01AFeygbCPNLgIgAAADAC7msoAB4sWywA\\=\\=\\,aOvssg\\=\\=\", payload=(int)96, ssrc=(uint)861153369, clock-base=(uint)4026289255, seqnum-base=(uint)30449" ! \
gstrtpbin ! \
rtph264depay ! \
queue ! \
ffdec_h264 ! \
autovideosink

I used a 'avi' type video file. When you enter the code at the sender you will get a text output in the terminal. Copy the things under 'caps' field and use it in the receiver's 'caps' field.

2. Receiving and displaying two videos in the same window

Videomixer is a very useful tool to view more than one videos in the same window. Here we send two videos from the same PC and receives in second PC through different ports.

Sender's code:

gst-launch -v \
filesrc location=/home/x101.avi ! decodebin ! x264enc ! rtph264pay ! udpsink host=192.168.1.104 port=5000 \
filesrc location=/home/x102.avi ! decodebin ! x264enc ! rtph264pay ! udpsink host=192.168.1.104 port=5001


Receiver's code:

gst-launch -e \
videomixer name=mix ! ffmpegcolorspace ! xvimagesink \
\
udpsrc port=5000 caps = "application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, sprop-parameter-sets=(string)\"Z01AFeygbCPNLgIgAAADAC7msoAB4sWywA\\=\\=\\,aOvssg\\=\\=\", payload=(int)96, ssrc=(uint)861153369, clock-base=(uint)4026289255, seqnum-base=(uint)30449" ! gstrtpbin ! rtph264depay ! queue ! ffdec_h264 ! \
videobox border-alpha=0 top=0 left=0 ! mix.  \
\
udpsrc port=5001 caps = "application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, sprop-parameter-sets=(string)\"Z01AFeygbCPNLgIgAAADAC7msoAB4sWywA\\=\\=\\,aOvssg\\=\\=\", payload=(int)96, ssrc=(uint)861153369, clock-base=(uint)4026289255, seqnum-base=(uint)30449" ! gstrtpbin ! rtph264depay ! queue ! ffdec_h264 ! \
videobox border-alpha=0 top=-125 left=0 ! mix. multifilesrc location=/home/Image.jpg caps="image/jpeg,framerate=1/1" ! jpegdec ! ffmpegcolorspace ! video/x-raw-yuv,format=\(fourcc\)AYUV ! mix.


Presentation slides with LATEX on Ubuntu

Tuesday, October 2, 2012

A. Installation of LATEX and other required components

Open a terminal window and type the following commands.

$ sudo apt-get update 
$ sudo apt-get install texlive-full gedit-latex-plugin texlive-fonts-recommended 
latex-beamer texpower texlive-pictures texlive-latex-extra texpower-examples 
imagemagick

 Your LATEX installation with Beamer front end should be ready to work now.

B. How to start with LATEX

I am going to use GEDIT text editor here. Let's say our file name is "test.tex" ("tex" is the file extension used by LATEX). Type the following in your terminal.

$ gedit test.tex &

C. A simple LATEX code

Following code will create a simple presentation in LATEX. Just copy and paste the code in to your 'test.tex' file. Concept is more similar to HTML. Just go through the lines with comments, hopefully you will be able to understand how to modify the code based on your requirement.


\documentclass[compress]{beamer} %this is to use copressed header from the template
\usepackage{beamerthemeshadow} %our theme, later you can change it

% editing header
\setbeamertemplate{headline}
{
  \leavevmode%
  \hbox{%
  \begin{beamercolorbox}[wd=.5\paperwidth,ht=2.25ex,dp=1.8ex,leftskip=1em,left]{section in head/foot}%
    \usebeamerfont{subsection in head/foot}\hspace*{5ex}\insertsectionhead
  \end{beamercolorbox}%
  \begin{beamercolorbox}[wd=.5\paperwidth,ht=2.25ex,dp=1.8ex,left,leftskip=1em]{subsection in head/foot}%
    \usebeamerfont{section in head/foot}\insertshorttitle\hspace*{2ex}
  \end{beamercolorbox}}%
  \vskip0pt%
}

% editing footer
\setbeamertemplate{footline}
{
  \leavevmode%
  \hbox{%
  \begin{beamercolorbox}[wd=.5\paperwidth,ht=2.25ex,dp=1ex,right]{author in head/foot}%
    \usebeamerfont{author in head/foot}\insertshortauthor\hspace*{2ex}
  \end{beamercolorbox}%
  \begin{beamercolorbox}[wd=.5\paperwidth,ht=2.25ex,dp=1ex,right]{date in head/foot}%
    \usebeamerfont{date in head/foot}\insertshortdate{}\hspace*{2em}
    \insertframenumber{} / \inserttotalframenumber\hspace*{2ex} 
  \end{beamercolorbox}}%
  \vskip0pt%
}

%enable numbering captions for the images
\setbeamertemplate{caption}[numbered]

%begining of the doc
\begin{document}

 \title{Presentation Title}  
 \author{Author Name}
 \date{October 2, 2012} %specify the date, if you want the current date use this, \date{\today}

 %title page
 \begin{frame}
 \titlepage
 \end{frame}

 %ToC page
 \begin{frame}
 \scriptsize
 {
  \frametitle{Table of contents}
  \tableofcontents
 }
 \end{frame} 

 %use sections for main headings
 \section{Section 1}
  
 %use subsection for subheadings
 \subsection{Section 1.1}
 \begin{frame}%create frame for each sldie
  \frametitle{Section 1.1} 
  \begin{itemize}%to have bulleted item list
   \item Item 1
    \begin{itemize}%sub bulleted items
     \item Item 1.1
    \end{itemize}
   \item Item 2
    \begin{itemize}
     \item Item 2.1
     \item Item 2.2
     \item Item 2.3
    \end{itemize}
   \item Item 3
  \end{itemize}
 \end{frame}

 \subsection{Section 1.2}
 \begin{frame}
  \frametitle{Section 1.2} 
  \begin{figure}
   \includegraphics[scale=0.3]{ubuntu} 
   \caption{Caption 1}
  \end{figure}
 \end{frame}
  
 \subsection{Section 1.3}
 \begin{frame}
  \frametitle{Subsection 1.3}
  \begin{columns}%columnize the page content
   \column{.5\textwidth}%one column is half of the text width of the slide
   \begin{figure}
    \includegraphics[scale=0.2]{ubuntu}
    \caption{Caption 2}
   \end{figure}
   \column{.5\textwidth}
   \begin{figure}
    \includegraphics[scale=0.2]{ubuntu}
    \caption{Caption 3}
   \end{figure}
  \end{columns}
 \end{frame}

 \section{Section 2}
 
 \begin{frame}
  \frametitle{Section 2}
  Section texts can be typed here. If you want to \textbf{Bold} use this.%bolding text
  To \underline{Underline} use this.
  To \emph{Emphasis} use this. %text will change to eirther Italic or normal based on the present state
 \end{frame}

 \section{Section 3}

 \subsection{Section 3.1}
 \begin{frame}
  \frametitle{Section 3.1}
  \begin{enumerate}%numbered list
   \item Item 1
    \begin{itemize}%bulleted list
     \item Item 1.1
     \item Item 1.2
    \end{itemize}
   \item Item 2
   \item Item 3
   \item Item 4
   \end{enumerate}
 \end{frame}

 \subsection{Section 3.2}
 \begin{frame}
  \frametitle{Section 3.2}
  \begin{itemize}
   \item Item 1
   \item Item 2
  \end{itemize}
  
  \begin{columns}%place 3 figures in the same slide
   \column{.5\textwidth}
   \begin{figure}
    \includegraphics[scale=0.3]{ubuntu}
    \caption{Caption A}
   \end{figure}
   \column{.5\textwidth}
   \begin{figure}
    \includegraphics[scale=0.1]{ubuntu}
    \caption{Caption B}
   \end{figure}
   \begin{figure}
    \includegraphics[scale=0.1]{ubuntu}
    \caption{Caption C}
   \end{figure}    
  \end{columns}
 \end{frame}

 \subsection{Section 3.3}
 \begin{frame}
  \frametitle{Section 3.3}
  \begin{columns}
   \column{.5\textwidth}
   \begin{itemize}
    \item Item a
    \item Item b
    \item Item c
   \end{itemize}
   \column{.5\textwidth}
   \begin{figure}
    \includegraphics[scale=0.2]{ubuntu}
    \caption{Caption}
   \end{figure}
  \end{columns}
 \end{frame}

 \begin{frame}
   {\Huge
     \vspace {0.15\textwidth}
     \begin{columns}[ccc]
       \begin{column}{0.3\textwidth}
       \end{column}
       \begin{column}{0.3\textwidth}
        \text{Thank you!}
       \end{column}
       \begin{column}{0.3\textwidth}
       \end{column}
     \end{columns}
   }
   \vspace {0.025\textwidth}
   \begin{center}
   {\huge Q\&A}
   \end{center}
 \end{frame}

\end{document}
 

Note: Your images should be in the same location with the 'test.tex' file. Later you can modify that. Pictures are recommended to be in the '.ps' format. Picture I used is 'ubuntu.ps'. So to run the code without any errors you should have a picture called 'ubuntu.ps' in the same location of 'test.tex'. Here is my file.

D. Let's run your LATEX code and create a PDF.

Paste and save the code in to 'test.tex' file. Switch back to terminal and run the following code.

$ gedit test.tex &
$ latex test.tex && dvips test.dvi && ps2pdf test.ps

This is how you can install "dvips" and "ps2pdf" if it is not installed in your box.

$ sudo apt-get install dvips ps2pdf

Now your PDF file of the presentation should be ready.