title: FFmpeg encoding in c
body: <p>I have been working on a project about video summarization on android platfrom. and I am stuck in encoding. I think; 
  first I must convert my frame into RGB Frame, then convert that RGB FRame into YUV Frame. Then encode the frame. After this operations, The output video was so weird. I think I missed something. Here is my las optimized code. Maybe someone has an experiement in this subject. </p>
  
  <p>Its syntax is changed  according to android ndk syntax: </p>
  
  <pre><code>jint Java_com_test_Test_encodeVideo(JNIEnv* env, jobject javaThis) 
  { 
       char *flname, *err, *info; 
       AVCodec *codec; 
       AVCodecContext *c= NULL; 
       int i,out_size, size, x, y,z, outbuf_size; 
       int frameCount=99; 
       FILE *f; 
       AVFrame *picture, *yuvFrame; 
       uint8_t *outbuf, *picture_buf; 
       PPMImage *img; 
       const char *destfilename = "/sdcard/new.mp4"; 
       int             numBytes; 
       uint8_t         *buffer; 
  
       av_register_all(); 
       // must be called before using avcodec lib 
       avcodec_init(); 
  
       // register all the codecs 
       avcodec_register_all(); 
       log_message("Video encoding\n"); 
  
       // find the H263 video encoder 
       codec = avcodec_find_encoder(CODEC_ID_H263); 
       if (!codec) { 
           sprintf(err, "codec not found\n"); 
           log_message(err); 
       } 
  
       c= avcodec_alloc_context(); 
       picture= avcodec_alloc_frame(); 
       yuvFrame= avcodec_alloc_frame(); 
  
       // get first ppm context. it is because I need width and height values. 
       img = getPPM("/sdcard/frame1.ppm"); 
  
       c-&gt;bit_rate = 400000; 
       // resolution must be a multiple of two 
  
       c-&gt;width = img-&gt;x; 
       c-&gt;height = img-&gt;y; 
       free(img); 
       // frames per second 
       c-&gt;time_base= (AVRational){1,25}; 
       c-&gt;gop_size = 10; // emit one intra frame every ten frames 
       //c-&gt;max_b_frames=1; 
       c-&gt;pix_fmt = PIX_FMT_YUV420P; 
       // open it 
       if (avcodec_open(c, codec) &lt; 0){ 
      log_message("codec couldn't open"); 
      return -1; 
       } 
       //destfilename = (*env)-&gt;GetStringUTFChars(env, dst, 0); 
       f = fopen(destfilename, "wb"); 
       log_message(destfilename); 
       if (!f) { 
           sprintf(err, "could not open %s", destfilename); 
           log_message(err); 
       } 
  
       log_message("after destination file opening"); 
       // alloc image and output buffer 
       outbuf_size = 100000; 
       outbuf = malloc(outbuf_size); 
       size = c-&gt;width * c-&gt;height; 
       picture_buf = malloc(size * 3); // size for RGB 
       picture-&gt;data[0] = picture_buf; 
       picture-&gt;data[1] = picture-&gt;data[0] + size; 
       picture-&gt;data[2] = picture-&gt;data[1] + size / 4; 
       picture-&gt;linesize[0] = c-&gt;width; 
       picture-&gt;linesize[1] = c-&gt;width / 2; 
       picture-&gt;linesize[2] = c-&gt;width / 2; 
  
       numBytes=avpicture_get_size(PIX_FMT_YUV420P, c-&gt;width, 
                c-&gt;height); 
  
       buffer=malloc(numBytes); 
  
            // Assign appropriate parts of buffer to image planes in FrameYUV 
       avpicture_fill((AVPicture *)yuvFrame, buffer, PIX_FMT_YUV420P, 
                c-&gt;width, c-&gt;height); 
       // encode the video 
       log_message("before for loop"); 
       for(z=1;z&lt;frameCount;z++) { 
                           sprintf(flname,"/sdcard/frame%d.ppm",z); 
                           // read the ppm file 
                           img = getPPM(flname); 
                           picture-&gt;data[0] = img-&gt;data; 
                           // convert the rgb frame into yuv frame 
                           rgb2yuv(picture,yuvFrame,c); 
                           log_message("translation completed."); 
                           // encode the image 
                           out_size = avcodec_encode_video(c, outbuf, outbuf_size, yuvFrame); 
                           sprintf(info,"encoding frame %3d (size=%5d)\n", z, out_size); 
                           log_message(info); 
                           fwrite(outbuf, 1, out_size, f); 
                           free(img); 
       } 
  
       // get the delayed frames 
       for(; out_size; i++) { 
           //fflush(stdout); 
           out_size = avcodec_encode_video(c, outbuf, outbuf_size, NULL); 
           sprintf(info,"write frame %3d (size=%5d)\n", i, out_size); 
               log_message(info); 
           fwrite(outbuf, 1, out_size, f); 
       } 
  
       // add sequence end code to have a real mpeg file 
       outbuf[0] = 0x00; 
       outbuf[1] = 0x00; 
       outbuf[2] = 0x01; 
       outbuf[3] = 0xb7; 
       fwrite(outbuf, 1, 4, f); 
       fclose(f); 
       free(picture_buf); 
       free(outbuf); 
  
       avcodec_close(c); 
       av_free(c); 
       av_free(picture); 
       av_free(yuvFrame); 
  } 
  
  int rgb2yuv(AVFrame *frameRGB, AVFrame *frameYUV, AVCodecContext *c) 
  { 
          char *err; 
          static struct SwsContext *img_convert_ctx; 
  
  
          log_message("conversion starts"); 
          // Convert the image into YUV format from RGB format 
          if(img_convert_ctx == NULL) { 
                  int w = c-&gt;width; 
                  int h = c-&gt;height; 
  
                  img_convert_ctx = sws_getContext(w, h, PIX_FMT_RGB24,w, h, c-&gt;pix_fmt, SWS_BICUBIC,NULL, NULL, NULL); 
  
                  if(img_convert_ctx == NULL) { 
                          sprintf(err, "Cannot initialize the conversion context!\n"); 
                          log_message(err); 
                          return -1; 
                  } 
          } 
    int ret = sws_scale(img_convert_ctx,frameRGB-&gt;data, frameRGB-&gt;linesize , 0,c-&gt;height,frameYUV-&gt;data, frameYUV-&gt;linesize ); 
          return; 
  }
  </code></pre>