title: Encoding raw YUV420P to h264 with AVCodec on iOS
body: <p>I am trying to encode a single YUV420P image gathered from a <code>CMSampleBuffer</code> to an <code>AVPacket</code> so that I can send h264 video over the network with RTMP.</p>
  
  <p>The posted code example seems to work as <code>avcodec_encode_video2</code> returns <code>0</code> (Success) however <code>got_output</code> is also <code>0</code> (<code>AVPacket</code> is empty).</p>
  
  <p>Does anyone have any experience with encoding video on iOS devices that might know what I am doing wrong?</p>
  
  <pre><code>- (void) captureOutput:(AVCaptureOutput *)captureOutput
   didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
          fromConnection:(AVCaptureConnection *)connection {
  
    // sampleBuffer now contains an individual frame of raw video frames
    CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
  
    CVPixelBufferLockBaseAddress(pixelBuffer, 0);
  
    // access the data
    int width = CVPixelBufferGetWidth(pixelBuffer);
    int height = CVPixelBufferGetHeight(pixelBuffer);
    int bytesPerRow = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 0);
    unsigned char *rawPixelBase = (unsigned char *)CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0);
  
  
    // Convert the raw pixel base to h.264 format
    AVCodec *codec = 0;
    AVCodecContext *context = 0;
    AVFrame *frame = 0;
    AVPacket packet;
  
    //avcodec_init();
    avcodec_register_all();
    codec = avcodec_find_encoder(AV_CODEC_ID_H264);
  
    if (codec == 0) {
      NSLog(@"Codec not found!!");
      return;
    }
  
    context = avcodec_alloc_context3(codec);
  
    if (!context) {
      NSLog(@"Context no bueno.");
      return;
    }
  
    // Bit rate
    context-&gt;bit_rate = 400000; // HARD CODE
    context-&gt;bit_rate_tolerance = 10;
    // Resolution
    context-&gt;width = width;
    context-&gt;height = height;
    // Frames Per Second
    context-&gt;time_base = (AVRational) {1,25};
    context-&gt;gop_size = 1;
    //context-&gt;max_b_frames = 1;
    context-&gt;pix_fmt = PIX_FMT_YUV420P;
  
    // Open the codec
    if (avcodec_open2(context, codec, 0) &lt; 0) {
      NSLog(@"Unable to open codec");
      return;
    }
  
  
    // Create the frame
    frame = avcodec_alloc_frame();
    if (!frame) {
      NSLog(@"Unable to alloc frame");
      return;
    }
    frame-&gt;format = context-&gt;pix_fmt;
    frame-&gt;width = context-&gt;width;
    frame-&gt;height = context-&gt;height;
  
  
    avpicture_fill((AVPicture *) frame, rawPixelBase, context-&gt;pix_fmt, frame-&gt;width, frame-&gt;height);
  
    int got_output = 0;
    av_init_packet(&amp;packet);
    avcodec_encode_video2(context, &amp;packet, frame, &amp;got_output)
  
    // Unlock the pixel data
    CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
    // Send the data over the network
    [self uploadData:[NSData dataWithBytes:packet.data length:packet.size] toRTMP:self.rtmp_OutVideoStream];
  }
  </code></pre>
  
  <p>Note: It is known that this code has memory leaks because I am not freeing the memory that is dynamically allocated.</p>
  
  <p><strong>UPDATE</strong></p>
  
  <p>I updated my code to use @pogorskiy method.  I only try to upload the frame if got output returns 1 and clear the buffer once I am done encoding video frames.</p>