title: using libav instead of ffmpeg
body: <p>I want to streaming video over http, i am using ogg(theora + vorbis), now i have sender and receiver, and i can run them using command line:</p>
  
  <p>Sender:</p>
  
  <pre><code>ffmpeg -f video4linux2 -s 320x240 -i /dev/mycam -codec:v libtheora -qscale:v 5 -f ogg http://127.0.0.1:8080 
  </code></pre>
  
  <p>Receiver:</p>
  
  <pre><code>sudo gst-launch-0.10 tcpserversrc port = 8080 ! oggdemux ! theoradec ! autovideosink
  </code></pre>
  
  <p>Now, sender sends both audio and video, but receiver plays only video.</p>
  
  <p>It works perfect, but now i want not to use ffmpeg and use only libav* instead.</p>
  
  <p>Here's my class for streaming:</p>
  
  <pre><code>class VCORE_LIBRARY_EXPORT VVideoWriter : private boost::noncopyable
  {
  public:
      VVideoWriter( );
      ~VVideoWriter( );
  
      bool openFile( const std::string&amp; name,
                     int fps, int videoBitrate, int width, int height,
                     int audioSampleRate, bool stereo, int audioBitrate );
      void close( );
  
      bool writeVideoFrame( const uint8_t* image, int64_t timestamp );
      bool writeAudioFrame( const int16_t* data, int64_t timestamp  );
  
      int audioFrameSize( ) const;
  
  private:
      AVFrame *m_videoFrame;
      AVFrame *m_audioFrame;
  
      AVFormatContext *m_context;
      AVStream *m_videoStream;
      AVStream *m_audioStream;
  
      int64_t m_startTime;
  };
  </code></pre>
  
  <p>Initialization:</p>
  
  <pre><code>bool VVideoWriter::openFile( const std::string&amp; name,
                               int fps, int videoBitrate, int width, int height,
                               int audioSampleRate, bool stereo, int audioBitrate )
  {
           if( ! m_context )
           {
              // initalize the AV context
              m_context = avformat_alloc_context( );
              assert( m_context );
  
              // get the output format
              m_context-&gt;oformat = av_guess_format( "ogg", name.c_str( ), nullptr );
              if( m_context-&gt;oformat )
              {
                  strcpy( m_context-&gt;filename, name.c_str( ) );
  
                  auto codecID = AV_CODEC_ID_THEORA;
                  auto codec = avcodec_find_encoder( codecID );
  
                  if( codec )
                  {
                      m_videoStream = avformat_new_stream( m_context, codec );
                      assert( m_videoStream );
  
                      // initalize codec
                      auto codecContext = m_videoStream-&gt;codec;
                      bool globalHeader = m_context-&gt;oformat-&gt;flags &amp; AVFMT_GLOBALHEADER;
                      if( globalHeader )
                          codecContext-&gt;flags |= CODEC_FLAG_GLOBAL_HEADER;
                      codecContext-&gt;codec_id = codecID;
                      codecContext-&gt;codec_type = AVMEDIA_TYPE_VIDEO;
                      codecContext-&gt;width = width;
                      codecContext-&gt;height = height;
                      codecContext-&gt;time_base.den = fps;
                      codecContext-&gt;time_base.num = 1;
                      codecContext-&gt;bit_rate = videoBitrate;
                      codecContext-&gt;pix_fmt = PIX_FMT_YUV420P;
                      codecContext-&gt;flags |= CODEC_FLAG_QSCALE;
                      codecContext-&gt;global_quality = FF_QP2LAMBDA * 5;
  
                      int res = avcodec_open2( codecContext, codec, nullptr );
  
                      if( res &gt;= 0 )
                      {
                          auto codecID = AV_CODEC_ID_VORBIS;
                          auto codec = avcodec_find_encoder( codecID );
  
                          if( codec )
                          {
                              m_audioStream = avformat_new_stream( m_context, codec );
                              assert( m_audioStream );
                              // initalize codec
                              auto codecContext = m_audioStream-&gt;codec;
  
                              bool globalHeader = m_context-&gt;oformat-&gt;flags &amp; AVFMT_GLOBALHEADER;
                              if( globalHeader )
                                  codecContext-&gt;flags |= CODEC_FLAG_GLOBAL_HEADER;
                              codecContext-&gt;codec_id = codecID;
                              codecContext-&gt;codec_type = AVMEDIA_TYPE_AUDIO;
                              codecContext-&gt;sample_fmt = AV_SAMPLE_FMT_FLTP;
                              codecContext-&gt;bit_rate = audioBitrate;
                              codecContext-&gt;sample_rate = audioSampleRate;
                              codecContext-&gt;channels = stereo ? 2 : 1;
                              codecContext-&gt;channel_layout = stereo ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO;
  
                              res = avcodec_open2( codecContext, codec, nullptr );
  
                              if( res &gt;= 0 )
                              {
                                  // try to open the file
                                  if( avio_open( &amp;m_context-&gt;pb, m_context-&gt;filename, AVIO_FLAG_WRITE ) &gt;= 0 )
                                  {
                                      m_audioFrame-&gt;nb_samples = codecContext-&gt;frame_size;
                                      m_audioFrame-&gt;format = codecContext-&gt;sample_fmt;
                                      m_audioFrame-&gt;channel_layout = codecContext-&gt;channel_layout;
  
                                      boost::posix_time::ptime time_t_epoch( boost::gregorian::date( 1970, 1, 1 ) );
                                      m_context-&gt;start_time_realtime = ( boost::posix_time::microsec_clock::universal_time( ) - time_t_epoch ).total_microseconds( );
                                      m_startTime = -1;
  
                                      // write the header
                                      if( avformat_write_header( m_context, nullptr ) &gt;= 0 )
                                      {
                                          return true;
                                      }
                                      else std::cerr &lt;&lt; "VVideoWriter: failed to write video header" &lt;&lt; std::endl;
                                  }
                                  else std::cerr &lt;&lt; "VVideoWriter: failed to open video file " &lt;&lt; name &lt;&lt; std::endl;
                              }
                              else std::cerr &lt;&lt; "VVideoWriter: failed to initialize audio codec" &lt;&lt; std::endl;
                          }
                          else std::cerr &lt;&lt; "VVideoWriter: requested audio codec is not supported" &lt;&lt; std::endl;
                      }
                      else std::cerr &lt;&lt; "VVideoWriter: failed to initialize video codec" &lt;&lt; std::endl;
                  }
                  else std::cerr &lt;&lt; "VVideoWriter: requested video codec is not supported" &lt;&lt; std::endl;
              }
              else std::cerr &lt;&lt; "VVideoWriter: requested video format is not supported" &lt;&lt; std::endl;
  
              avformat_free_context( m_context );
              m_context = nullptr;
              m_videoStream = nullptr;
              m_audioStream = nullptr;
          }
          return false;
  }
  </code></pre>
  
  <p>Writing video:</p>
  
  <pre><code>bool VVideoWriter::writeVideoFrame( const uint8_t* image, int64_t timestamp )
  {
      if( m_context ) {
          auto codecContext = m_videoStream-&gt;codec;
          avpicture_fill( reinterpret_cast&lt;AVPicture*&gt;( m_videoFrame ),
                          const_cast&lt;uint8_t*&gt;( image ),
                          codecContext-&gt;pix_fmt, codecContext-&gt;width, codecContext-&gt;height );
  
          AVPacket pkt;
          av_init_packet( &amp; pkt );
          pkt.data = nullptr;
          pkt.size = 0;
          int gotPacket = 0;
          if( ! avcodec_encode_video2( codecContext, &amp;pkt, m_videoFrame, &amp; gotPacket ) ) {
              if( gotPacket == 1 ) {
                  pkt.stream_index = m_videoStream-&gt;index;
                  int res;
                  {
                      pkt.pts = AV_NOPTS_VALUE;
                      pkt.dts = AV_NOPTS_VALUE;
                      pkt.stream_index = m_videoStream-&gt;index;
                      res = av_write_frame( m_context, &amp;pkt );
                  }
                  av_free_packet( &amp; pkt );
                  return res &gt;= 0;
              }
              assert( ! pkt.size );
              return true;
          }
      }
      return false;
  }
  </code></pre>
  
  <p>Writing audio (now i write test dummy audio):</p>
  
  <pre><code>bool VVideoWriter::writeAudioFrame( const int16_t* data, int64_t timestamp )
  {
      if( m_context ) {
          auto codecContext = m_audioStream-&gt;codec;
  
          int buffer_size = av_samples_get_buffer_size(nullptr, codecContext-&gt;channels, codecContext-&gt;frame_size, codecContext-&gt;sample_fmt, 0);
  
          float *samples = (float*)av_malloc(buffer_size);
  
          for (int i = 0; i &lt; buffer_size / sizeof(float); i++)
              samples[i] = 1000. * sin((double)i/2.);
  
          int ret = avcodec_fill_audio_frame( m_audioFrame, codecContext-&gt;channels, codecContext-&gt;sample_fmt, (const uint8_t*)samples, buffer_size, 0);
  
          assert( ret &gt;= 0 );
          (void)(ret);
  
          AVPacket pkt;
          av_init_packet( &amp; pkt );
          pkt.data = nullptr;
          pkt.size = 0;
          int gotPacket = 0;
          if( ! avcodec_encode_audio2( codecContext, &amp;pkt, m_audioFrame, &amp; gotPacket ) ) {
              if( gotPacket == 1 ) {
                  pkt.stream_index = m_audioStream-&gt;index;
                  int res;
                  {
                      pkt.pts = AV_NOPTS_VALUE;
                      pkt.dts = AV_NOPTS_VALUE;
                      pkt.stream_index = m_audioStream-&gt;index;
                      res = av_write_frame( m_context, &amp;pkt );
                  }
                  av_free_packet( &amp; pkt );
                  return res &gt;= 0;
              }
              assert( ! pkt.size );
              return true;
          }
          return false;
      }
      return false;
  }
  </code></pre>
  
  <p>Here's test example (i send video from webcam and dummy audio):</p>
  
  <pre><code>class TestVVideoWriter : public sigslot::has_slots&lt;&gt;
  {
  public:
      TestVVideoWriter( ) :
          m_fileOpened( false )
      {
      }
  
      void onCapturedFrame( cricket::VideoCapturer*, const cricket::CapturedFrame* capturedFrame )
      {
          if( m_fileOpened ) {
              m_writer.writeVideoFrame( reinterpret_cast&lt;const uint8_t*&gt;( capturedFrame-&gt;data ),
                                        capturedFrame-&gt;time_stamp / 1000 );
              m_writer.writeAudioFrame( nullptr , 0 );
  
  
          } else {
                m_fileOpened = m_writer.openFile( "http://127.0.0.1:8080",
                                                  15, 40000, capturedFrame-&gt;width, capturedFrame-&gt;height,
                                                  16000, false, 64000 );
          }
      }
  
  public:
      vcore::VVideoWriter m_writer;
      bool m_fileOpened;
  };
  
  TestVVideoWriter testWriter;
  
  BOOST_AUTO_TEST_SUITE(TEST_VIDEO_WRITER)
  
  BOOST_AUTO_TEST_CASE(testWritingVideo)
  {
      cricket::LinuxDeviceManager deviceManager;
      std::vector&lt;cricket::Device&gt; devs;
      if( deviceManager.GetVideoCaptureDevices( &amp;devs ) ) {
          if( devs.size( ) ) {
              boost::shared_ptr&lt;cricket::VideoCapturer&gt; camera( deviceManager.CreateVideoCapturer( devs[ 0 ] ) );
              if( camera ) {
                  cricket::VideoFormat format( 320, 240, cricket::VideoFormat::FpsToInterval( 30 ),
                                               camera-&gt;GetSupportedFormats( )-&gt;front( ).fourcc );
                  cricket::VideoFormat best;
                  if( camera-&gt;GetBestCaptureFormat( format, &amp;best ) ) {
                      camera-&gt;SignalFrameCaptured.connect( &amp;testWriter, &amp;TestVVideoWriter::onCapturedFrame );
                      if( camera-&gt;Start( best ) != cricket::CS_FAILED ) {
                          boost::this_thread::sleep( boost::posix_time::seconds( 10 ) );
                          return;
                      }
                  }
              }
          }
      }
      std::cerr &lt;&lt; "Problem has occured with camera" &lt;&lt; std::endl;
  }
  
  BOOST_AUTO_TEST_SUITE_END() // TEST_VIDEO_WRITER 
  </code></pre>
  
  <p>But, in this case, gstreamer start playing video only when my test program stop executing (after 10 seconds in this case). It does not suit me, i want gstreamer start playing immediately after starting my test program. </p>
  
  <p>Could someone help me?</p>
  
  <p>P.S. Sorry for my English.</p>