title: Make AVI file from H264 compressed data
body: <p>I'm using ffmpeg libraries to create a AVI file and following the <code>muxing.c ffmpeg</code> example as below</p>
  
  <ol>
  <li>Allocate the output media context:  <code>avformat_alloc_output_context2</code></li>
  <li><p>Add video streams using the <code>AV_CODEC_ID_H264</code> codec with below set of parameters:</p>
  
  <pre><code>int AddVideoStream(AVStream *&amp;video_st, AVFormatContext *&amp;oc, AVCodec **codec, enum AVCodecID codec_id){
  
  AVCodecContext *c;
  
  /* find the encoder */
  *codec = avcodec_find_encoder(codec_id); //codec id = AV_CODEC_ID_H264
  if (!(*codec)) {
      sprintf(strError , "Could not find encoder for '%s' line %d\n", avcodec_get_name(codec_id), __LINE__);
      commonGlobal-&gt;WriteRuntimeBackupLogs(strError);
      return RS_NOT_OK;
  }
  
  video_st = avformat_new_stream(oc, *codec);
  if (!video_st) {
      sprintf(strError , "Could not allocate stream line %d\n", __LINE__);
      commonGlobal-&gt;WriteRuntimeBackupLogs(strError);
      return RS_NOT_OK;
  }
  video_st-&gt;id = oc-&gt;nb_streams-1;
  c = video_st-&gt;codec;
  
  avcodec_get_context_defaults3(c, *codec);
  c-&gt;codec_id = codec_id;
  
  c-&gt;bit_rate = 500*1000;
  /* Resolution must be a multiple of two. */
  c-&gt;width    = 1280;
  c-&gt;height   = 720;
  /* timebase: This is the fundamental unit of time (in seconds) in terms
  * of which frame timestamps are represented. For fixed-fps content,
  * timebase should be 1/framerate and timestamp increments should be
  * identical to 1. */
  c-&gt;time_base.den = 25*1000;
  c-&gt;time_base.num = 1000;
  c-&gt;gop_size      = 12;//(int)(av_q2d(c-&gt;time_base) / 2);    // GOP size is framerate/2 
  c-&gt;pix_fmt       = STREAM_PIX_FMT;
  /* Some formats want stream headers to be separate. */
  if (oc-&gt;oformat-&gt;flags &amp; AVFMT_GLOBALHEADER)
      c-&gt;flags |= CODEC_FLAG_GLOBAL_HEADER;
  
  return RS_OK;
  </code></pre>
  
  <p>}</p></li>
  <li><p>Open Video stream: <code>open_video</code></p>
  
  <p><code>int open_video( AVFormatContext *oc, AVCodec *codec, AVStream *st ){</code></p>
  
  <pre><code>int ret;
  AVCodecContext *c = st-&gt;codec;
  char strError[STR_LENGTH_256];
  /* open the codec */
  ret = avcodec_open2(c, codec, NULL);
  if (ret &lt; 0) {
      sprintf(strError , "Could not open video codec line %d", __LINE__);
      commonGlobal-&gt;WriteRuntimeBackupLogs(strError);
      return RS_NOT_OK;
  }
  
  /* allocate and init a re-usable frame */
  frame = avcodec_alloc_frame();
  if (!frame) {
      sprintf(strError , "Could not allocate video frame line %d", __LINE__);
      commonGlobal-&gt;WriteRuntimeBackupLogs(strError);
      return RS_NOT_OK;
  }
  
  /* Allocate the encoded raw picture. */
  ret = avpicture_alloc(&amp;dst_picture, c-&gt;pix_fmt, c-&gt;width, c-&gt;height);
  if (ret &lt; 0) {
      sprintf(strError , "Could not allocate picture line %d", __LINE__);
      commonGlobal-&gt;WriteRuntimeBackupLogs(strError);
      return RS_NOT_OK;
  }
  
  /* If the output format is not YUV420P, then a temporary YUV420P
  * picture is needed too. It is then converted to the required
  * output format. */
  if (c-&gt;pix_fmt != AV_PIX_FMT_YUV420P) {
      ret = avpicture_alloc(&amp;src_picture, AV_PIX_FMT_YUV420P, c-&gt;width, c-&gt;height);
      if (ret &lt; 0) {
          sprintf(strError , "Could not allocate temporary picture line %d", __LINE__);
          commonGlobal-&gt;WriteRuntimeBackupLogs(strError);
          return RS_NOT_OK;
      }
  }
  
  /* copy data and linesize picture pointers to frame */
  *((AVPicture *)frame) = dst_picture;
  return RS_OK;
  </code></pre>
  
  <p>}</p></li>
  <li><p>Write AVI stream header: <code>avformat_write_header</code></p></li>
  <li><p>Encode video frame:<code>avcodec_encode_video2</code></p>
  
  <p>Case a: The input here are <code>BRG frames</code> so I encode them to H264 and pass to the next step.</p>
  
  <p>Case b: The input here are <code>H264 compressed frames (these frames captured from H264 RTP stream)</code> so I leave this step then move to next step.</p></li>
  <li><p>Write Interleave Video frame: <code>av_interleaved_write_frame(oc, &amp;pkt)</code></p>
  
  <p>Case a:  Writing the packet data encoded from step 5 correctly without error.</p>
  
  <p>Case b:  I Always get error from <code>av_interleaved_write_frame</code> with value -22. It could be EINVAL invalid argument. So someone can tell me what is wrong? or Some parameters I was missing here.</p>
  
  <pre><code>int WriteVideoFrame(AVFormatContext *&amp;oc, AVStream *&amp;st, 
  uint8_t *imageData `/*BRG data input*/`, 
  int width, 
  int height, 
  bool isStart, 
  bool isData,
  bool isCompressed, 
  AVPacket* packet `/*H264 data input*/`)
  </code></pre>
  
  <p>{ </p>
  
  <p><code>if (isCompressed == false)// For BRG data</code>
  {</p>
  
  <pre><code>static struct SwsContext *sws_ctx;
  AVCodecContext *c = st-&gt;codec;
  
  if (isData)
  {
      if (!frame) {
          //fprintf(stderr, "Could not allocate video frame\n");
          return RS_NOT_OK;
      }
      if (isStart == true)
          frame-&gt;pts = 0;
      /* Allocate the encoded raw picture. */
      if (width != c-&gt;width || height != c-&gt;height)
      {
          if (!sws_ctx)
          {
              sws_ctx = sws_getContext(width, height,
                  AV_PIX_FMT_BGR24, c-&gt;width, c-&gt;height,
                  AV_PIX_FMT_YUV420P, SWS_FAST_BILINEAR, 0, 0, 0);
  
              if (!sws_ctx)
              {
                  sprintf(strError, "Could not initialize the conversion context line %d\n", __LINE__);
                  commonGlobal-&gt;WriteRuntimeBackupLogs(strError);
                  return RS_NOT_OK;
              }
          }
          uint8_t * inData[1] = { imageData }; // RGB24 have one plane
          int inLinesize[1] = { 3 * width }; // RGB stride
          sws_scale(sws_ctx, inData, inLinesize, 0, height, dst_picture.data, dst_picture.linesize);
      }
      else
          BRG24ToYUV420p(dst_picture.data, imageData, width, height); //Phong Le changed this
  }
  if (oc-&gt;oformat-&gt;flags &amp; AVFMT_RAWPICTURE)
  {
      /* Raw video case - directly store the picture in the packet */
      AVPacket pkt;
      av_init_packet(&amp;pkt);
  
      pkt.flags |= AV_PKT_FLAG_KEY;
      pkt.stream_index = st-&gt;index;
      pkt.data = dst_picture.data[0];
      pkt.size = sizeof(AVPicture);
  
      ret = av_interleaved_write_frame(oc, &amp;pkt);
      av_free_packet(&amp;pkt);
  }
  else
  {
      /* encode the image */
      AVPacket pkt;
      int got_output;
  
      av_init_packet(&amp;pkt);
      pkt.data = NULL;    // packet data will be allocated by the encoder
      pkt.size = 0;
      ret = avcodec_encode_video2(c, &amp;pkt, frame, &amp;got_output);
      if (ret &lt; 0) {
          sprintf(strError, "Error encoding video frame line %d\n", __LINE__);
          commonGlobal-&gt;WriteRuntimeBackupLogs(strError);
          av_free_packet(&amp;pkt);
          return RS_NOT_OK;
      }
  
      /* If size is zero, it means the image was buffered. */
      if (got_output) {
          if (c-&gt;coded_frame-&gt;key_frame)
              pkt.flags |= AV_PKT_FLAG_KEY;
  
          pkt.stream_index = st-&gt;index;
  
          /* Write the compressed frame to the media file. */
          ret = av_interleaved_write_frame(oc, &amp;pkt);
      }
      else
      {
          ret = 0;
      }
      av_free_packet(&amp;pkt);
  }
  if (ret != 0)
  {
      sprintf(strError, "Error while writing video frame line %d\n", __LINE__);
      commonGlobal-&gt;WriteRuntimeBackupLogs(strError);
      return RS_NOT_OK;
  }
  frame-&gt;pts += av_rescale_q(1, st-&gt;codec-&gt;time_base, st-&gt;time_base);
  return RS_OK;
  </code></pre>
  
  <p>}</p>
  
  <p>else /<em>H264 data</em>/</p>
  
  <p>{</p>
  
  <pre><code>if (isStart == true)
      packet-&gt;pts = 0;
  
  else
      packet-&gt;pts += av_rescale_q(1, st-&gt;codec-&gt;time_base, st-&gt;time_base);
  
  ret = av_interleaved_write_frame(oc, packet);
  if (ret &lt; 0)
  {
      sprintf(strError, "Error while writing video frame line %d\n", __LINE__);
      commonGlobal-&gt;WriteRuntimeBackupLogs(strError);
      return RS_NOT_OK;
  }
  
  return RS_OK;
  </code></pre>
  
  <p>}</p></li>
  </ol>
  
  <p>}</p>
  
  <ol start="7">
  <li>Close file.</li>
  </ol>
  
  <p>->   Case a: Creating AVI file successful.</p>
  
  <p>->   Case b: Fail.</p>
  
  <p>Thanks
  Tien Vo</p>