title: ffmpeg mono8/rgb24 images to yuv420p to x264 conversion
body: <p>this is probably a trivial question but I'm going crazy with this (ffmpeg) framework. 
  Based on this post (<a href="https://stackoverflow.com/questions/8494546/sws-scale-yuv-rgb-distorted-image">sws_scale YUV --&gt; RGB distorted image</a>) (and much more searches) I've written the following code to take a char* pointer to a buffer image (Mono8 or RGB24) and I convert to YUV420P to encode in x264. I have to create a streaming of this images between two PC. </p>
  
  <p>This is the code:</p>
  
  <pre><code>bool compressImageX264(Frame *f, int size, char* image){
   codec = avcodec_find_encoder(AV_CODEC_ID_H264);
   if (!codec) {
    std::cout &lt;&lt; "Codec not found" &lt;&lt; std::endl;
    return false;
   }
   c = avcodec_alloc_context3(codec);
   if (!c) {
    std::cout &lt;&lt; "Could not allocate video codec context" &lt;&lt; std::endl;
    return false;
   }
   av_opt_set(c-&gt;priv_data, "preset", "veryfast", 0);
   av_opt_set(c-&gt;priv_data, "tune", "zerolatency", 0);
   c-&gt;width = std::stoi(f-&gt;width);
   c-&gt;height = std::stoi(f-&gt;height);
   c-&gt;gop_size = 10;
   c-&gt;max_b_frames = 1;
   EDIT: c-&gt;pix_fmt = AV_PIX_FMT_YUV420P;
   /* open it */
   if (avcodec_open2(c, codec, NULL) &lt; 0) {
    std::cout &lt;&lt; "Could not open codec" &lt;&lt; std::endl;
    return false;
   }
  
   AVFrame *avFrameRGB = av_frame_alloc();
   if (!avFrameRGB) {
    std::cout &lt;&lt; "Could not allocate video frame" &lt;&lt; std::endl;
    return false;
   }
   avFrameRGB-&gt;format = std::stoi(f-&gt;channels) &gt; 1 ? AV_PIX_FMT_RGB24 : AV_PIX_FMT_GRAY8;
   avFrameRGB-&gt;width = c-&gt;width;
   avFrameRGB-&gt;height = c-&gt;height;
  
   int ret = av_image_alloc(
     avFrameRGB-&gt;data, avFrameRGB-&gt;linesize,
     avFrameRGB-&gt;width, avFrameRGB-&gt;height, AVPixelFormat(avFrameRGB-&gt;format),
     32);
   if (ret &lt; 0) {
    std::cout &lt;&lt; "Could not allocate raw picture buffer" &lt;&lt; std::endl;
    return false;
   }
  
   uint8_t *p = avFrameRGB-&gt;data[0];
   for (int i = 0; i &lt; size; i++){
     *p++ = image[i];
   }
   AVFrame* avFrameYUV = av_frame_alloc();
   avFrameYUV-&gt;format = AV_PIX_FMT_YUV420P;
   avFrameYUV-&gt;width = c-&gt;width;
   avFrameYUV-&gt;height = c-&gt;height;
   ret = av_image_alloc(
      avFrameYUV-&gt;data, avFrameYUV-&gt;linesize,
      avFrameYUV-&gt;width, avFrameYUV-&gt;height, AVPixelFormat(avFrameYUV-&gt;format),
      32);
  
   SwsContext *img_convert_ctx = sws_getContext(c-&gt;width, c-&gt;height, AVPixelFormat(avFrameRGB-&gt;format),
     c-&gt;width, c-&gt;height, AV_PIX_FMT_YUV420P,
     SWS_FAST_BILINEAR, NULL, NULL, NULL);
   ret = sws_scale(img_convert_ctx, 
     avFrameRGB-&gt;data, avFrameRGB-&gt;linesize,
     0, c-&gt;height, 
     avFrameYUV-&gt;data, avFrameYUV-&gt;linesize);
   sws_freeContext(img_convert_ctx);
  
   AVPacket pkt;
   av_init_packet(&amp;pkt);
   pkt.data = NULL; // packet data will be allocated by the encoder
   pkt.size = 0;
  
   avFrameYUV-&gt;pts = frameCount; frameCount++; //GLOBAL VARIABLE
   int got_output;
   ret = avcodec_encode_video2(c, &amp;pkt, avFrameYUV, &amp;got_output);
   if (ret &lt; 0) { //&lt;-- Where the code broke
     std::cout &lt;&lt; "Error encoding frame" &lt;&lt; std::endl;
     return false;
   }
   if (got_output) {
      std::cout &lt;&lt; "Write frame " &lt;&lt; frameCount - 1 &lt;&lt; "(size = " &lt;&lt; pkt.size &lt;&lt; ")" &lt;&lt; std::endl;
      char* buffer = new char[pkt.size];
      for (int i = 0; i &lt; pkt.size; i++){
        buffer[i] = pkt.data[i];
      }
      f-&gt;buffer = buffer;
      f-&gt;size = std::to_string(pkt.size);
      f-&gt;compression = std::string("x264");
      av_free_packet(&amp;pkt);
    }
    return true;
  }
  </code></pre>
  
  <p>I know that maybe this is a lot inefficient but for now I'm worried to make it work. I failed when I call avcodec_encode_video2. On console it's printed this message: "Input picture width (640) is greater than stride (320)".
  I think that conversion is the assassin. But I don't fully know the parameters meanings
  Thanks for all your help.</p>
  
  <p>EDIT:
  Ok, I have founded the "first" error. Now the conversion work properly and avcodec_encode_video2 return 0. The problem now is that got_output is always equal zero and on the console nothing is available. </p>