title: Using Live555 to Stream Live Video from an IP camera connected to an H264 encoder
body: <p>I am using a custom Texas Instruments OMAP-L138 based board that basically consists of an ARM9 based SoC and a DSP processor. It is connected to a camera lens. What I'm trying to do is to capture live video stream which is sent to the dsp processor for H264 encoding which is sent over uPP in packets of 8192 bytes. I want to use the testH264VideoStreamer supplied by Live555 to live stream the H264 encoded video over RTSP. The code I have modified is shown below: </p>
  
  <pre><code>#include &lt;liveMedia.hh&gt;
  #include &lt;BasicUsageEnvironment.hh&gt;
  #include &lt;GroupsockHelper.hh&gt;
  #include &lt;stdio.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;fcntl.h&gt;
  #include &lt;string.h&gt;
  #include &lt;errno.h&gt;
  #include &lt;string.h&gt;
  #include &lt;unistd.h&gt; //to allow read() function
  
  
  
  
  UsageEnvironment* env;
  H264VideoStreamFramer* videoSource;
  RTPSink* videoSink;
  
  
  //-------------------------------------------------------------------------------
  /* Open File Descriptor*/
  int stream = open("/dev/upp", O_RDONLY);
  /* Declaring a static 8 bit unsigned integer of size 8192 bytes that keeps its value between invocations */
  static uint8_t buf[8192];
  //------------------------------------------------------------------------------
  
  
  //------------------------------------------------------------------------------
  // Execute play function as a forwarding mechanism
  //------------------------------------------------------------------------------
  void play(); // forward
  
  
  //------------------------------------------------------------------------------
  // MAIN FUNCTION / ENTRY POINT 
  //------------------------------------------------------------------------------
  int main(int argc, char** argv) 
  {
      // Begin by setting up our live555 usage environment:
      TaskScheduler* scheduler = BasicTaskScheduler::createNew();
      env = BasicUsageEnvironment::createNew(*scheduler);
  
      // Create 'groupsocks' for RTP and RTCP:
      struct in_addr destinationAddress;
      destinationAddress.s_addr = chooseRandomIPv4SSMAddress(*env);
      // Note: This is a multicast address.  If you wish instead to stream
      // using unicast, then you should use the "testOnDemandRTSPServer"
      // test program - not this test program - as a model.
  
      const unsigned short rtpPortNum = 18888;
      const unsigned short rtcpPortNum = rtpPortNum+1;
      const unsigned char ttl = 255;
  
      const Port rtpPort(rtpPortNum);
      const Port rtcpPort(rtcpPortNum);
  
      Groupsock rtpGroupsock(*env, destinationAddress, rtpPort, ttl);
      rtpGroupsock.multicastSendOnly(); // we're a SSM source
      Groupsock rtcpGroupsock(*env, destinationAddress, rtcpPort, ttl);
      rtcpGroupsock.multicastSendOnly(); // we're a SSM source
  
      // Create a 'H264 Video RTP' sink from the RTP 'groupsock':
      OutPacketBuffer::maxSize = 1000000;
      videoSink = H264VideoRTPSink::createNew(*env, &amp;rtpGroupsock, 96);
  
      // Create (and start) a 'RTCP instance' for this RTP sink:
      const unsigned estimatedSessionBandwidth = 500; // in kbps; for RTCP b/w share
      const unsigned maxCNAMElen = 100;
      unsigned char CNAME[maxCNAMElen+1];
      gethostname((char*)CNAME, maxCNAMElen);
      CNAME[maxCNAMElen] = '\0'; // just in case
      RTCPInstance* rtcp
      = RTCPInstance::createNew(*env, &amp;rtcpGroupsock,
                  estimatedSessionBandwidth, CNAME,
                  videoSink, NULL /* we're a server */,
                  True /* we're a SSM source */);
      // Note: This starts RTCP running automatically
  
      /*Create RTSP SERVER*/
      RTSPServer* rtspServer = RTSPServer::createNew(*env, 8554);
      if (rtspServer == NULL) 
      {
           *env &lt;&lt; "Failed to create RTSP server: " &lt;&lt; env-&gt;getResultMsg() &lt;&lt; "\n";
           exit(1);
      }
      ServerMediaSession* sms
          = ServerMediaSession::createNew(*env, "IPCAM @ TeReSol","UPP Buffer" ,
             "Session streamed by \"testH264VideoStreamer\"",
                         True /*SSM*/);
      sms-&gt;addSubsession(PassiveServerMediaSubsession::createNew(*videoSink, rtcp));
      rtspServer-&gt;addServerMediaSession(sms);
  
      char* url = rtspServer-&gt;rtspURL(sms);
      *env &lt;&lt; "Play this stream using the URL \"" &lt;&lt; url &lt;&lt; "\"\n";
      delete[] url;
  
      // Start the streaming:
      *env &lt;&lt; "Beginning streaming...\n";
      play();
  
      env-&gt;taskScheduler().doEventLoop(); // does not return
  
      return 0; // only to prevent compiler warning
  }
  
  
  
  //----------------------------------------------------------------------------------
  // afterPlaying() -&gt; Defines what to do once a buffer is streamed
  //----------------------------------------------------------------------------------
  void afterPlaying(void* /*clientData*/) 
  {
      *env &lt;&lt; "...done reading from upp buffer\n";
      //videoSink-&gt;stopPlaying();
      //Medium::close(videoSource);
      // Note that this also closes the input file that this source read from.
  
      // Start playing once again to get the next stream      
      play();
  
      /* We don't need to close the dev as long as we're reading from it. But if we do, use: close( "/dev/upp", O_RDWR);*/ 
  
  }
  
  
  
  //----------------------------------------------------------------------------------------------
  // play() Method -&gt; Defines how to read and what to make of the input stream 
  //----------------------------------------------------------------------------------------------
  void play()
  {
  
  
  
      /* Read nbytes of buffer (sizeof buf ) from the filedescriptor stream and assign them to address where buf is located */
      read(stream, &amp;buf, sizeof buf);
      printf("Reading from UPP in to Buffer");
  
      /*Open the input file as a 'byte-stream file source': */
      ByteStreamMemoryBufferSource* buffSource
          = ByteStreamMemoryBufferSource::createNew(*env, buf, sizeof buf,False/*Empty Buffer After Reading*/);
      /*By passing False in the above creatNew() method means that the buffer would be read at once */
  
      if (buffSource == NULL) 
      {
        *env &lt;&lt; "Unable to read from\"" &lt;&lt; "Buffer"
             &lt;&lt; "\" as a byte-stream source\n";
            exit(1);
      }
  
      FramedSource* videoES = buffSource;
      // Create a framer for the Video Elementary Stream:
      videoSource = H264VideoStreamFramer::createNew(*env, videoES,False);
      // Finally, start playing:
      *env &lt;&lt; "Beginning to read from UPP...\n";
      videoSink-&gt;startPlaying(*videoSource, afterPlaying, videoSink);
  }
  </code></pre>
  
  <p>The Problem is that the code though compiles successfully but I'm unable to get the desired output. the RTSP stream on VLC player is on play mode however I can't see any video. I'd be grateful for any assistance in this matter. I might come as a little vague in my description but I'm happy to further explain any part that is required.</p>