title: ffmpeg Bmp to yuv : Crash at sws_scale
body: <p><strong>The context</strong> : 
  I have a succession of continuous bitmap and I want to encode them into a light video format.
  I use <em>ffmpeg</em> version 2.8.3 (the build <a href="https://ffmpeg.zeranoe.com/blog/?p=450" rel="nofollow">here</a>), under <em>qt5</em>, <em>qt IDE</em>, and <em>msvc2013</em> for <em>win32</em>.</p>
  
  <p><strong>The problem</strong> : 
  My code crash at <em>sws_scale ()</em> (and sometimes at <em>avcodec_encode_video2()</em>). When I explore the stack, the crash event occurs at <em>sws_getCachedContext ()</em>.  (I can only see the stack with these ffmpeg builds). 
  I only use these ffmpeg libraries (from the Qt <em>.pro</em> file) : </p>
  
  <pre><code>LIBS += -lavcodec -lavformat -lswscale -lavutil
  </code></pre>
  
  <p>It's <em>swscale</em> which bug. And this is the code :</p>
  
  <pre><code>void newVideo ()
  {
      ULONG_PTR gdiplusToken;
      GdiplusStartupInput gdiplusStartupInput;
      GdiplusStartup(&amp;gdiplusToken, &amp;gdiplusStartupInput, NULL);
  
      initBitmap (); //init bmp
      int screenWidth =  bmp.bmiHeader.biWidth;
      int screenHeight = bmp.bmiHeader.biHeight;
  
      AVCodec * codec;
      AVCodecContext * c = NULL;
      uint8_t * outbuf;
      int i, out_size, outbuf_size;
  
  
      avcodec_register_all();
  
      qDebug () &lt;&lt; "Video encoding\n";
  
      // Find the mpeg1 video encoder
      codec = avcodec_find_encoder(AV_CODEC_ID_H264);
      if (!codec)
      {
          qDebug () &lt;&lt; "Codec not found\n";
          avcodec_close(c);
          av_free(c);
          return;
      }
      else
          qDebug () &lt;&lt; "H264 codec found\n";
  
      c = avcodec_alloc_context3(codec);
  
      c-&gt;bit_rate = 1000000;
      c-&gt;width = 800; // resolution must be a multiple of two (1280x720),(1900x1080),(720x480)
      c-&gt;height = 600;
      c-&gt;time_base.num = 1; // framerate numerator
      c-&gt;time_base.den = 25; // framerate denominator
      c-&gt;gop_size = 30; // emit one intra frame every ten frames
      c-&gt;max_b_frames = 1; // maximum number of b-frames between non b-frames
      c-&gt;pix_fmt = AV_PIX_FMT_YUV420P; //Converstion RGB to YUV ?
      c-&gt;codec_id = AV_CODEC_ID_H264;
  
      struct SwsContext* fooContext = sws_getContext(screenWidth, screenHeight,
                                                     AV_PIX_FMT_RGB32,
                                                     c-&gt;width, c-&gt;height,
                                                     AV_PIX_FMT_YUV420P,
                                                     SWS_FAST_BILINEAR,
                                                     NULL, NULL, NULL);
  
      // Open the encoder
      if (avcodec_open2(c, codec, NULL) &lt; 0)
      {
          qDebug () &lt;&lt; "Could not open codec\n";
          avcodec_close(c);
          av_free(c);
          return;
      }
      else qDebug () &lt;&lt; "H264 codec opened\n";
  
      outbuf_size = 100000 + c-&gt;width*c-&gt;height*(32&gt;&gt;3);//*(32&gt;&gt;3); // alloc image and output buffer
      outbuf = static_cast&lt;uint8_t *&gt;(malloc(outbuf_size));
      qDebug() &lt;&lt; "Setting buffer size to: " &lt;&lt; outbuf_size &lt;&lt; "\n";
  
      FILE* f = fopen("TEST.mpg","wb");
      if(!f) qDebug() &lt;&lt; "x - Cannot open video file for writing\n";
      else qDebug() &lt;&lt; "Opened video file for writing\n";
  
      // encode 5 seconds of video
      for (i = 0; i &lt; STREAM_FRAME_RATE*STREAM_DURATION; i++) //the stop condition i &lt; 5.0*5
      {
          qDebug () &lt;&lt; "i = " &lt;&lt; i;
          fflush(stdout);
  
          HBITMAP hBmp;
          if (GetScreen(hBmp) == -1) return;
          BYTE * pPixels;// = new BYTE [bmp.bmiHeader.biSizeImage];
          pPixels = getPixels (hBmp);
          DeleteObject (hBmp);
  
          int nbytes = avpicture_get_size(AV_PIX_FMT_YUV420P, c-&gt;width, c-&gt;height);
          uint8_t* outbuffer = (uint8_t*)av_malloc(nbytes*sizeof(uint8_t));
          if(!outbuffer) // check if(outbuf) instead
          {
              qDebug () &lt;&lt; "Bytes cannot be allocated";
              return;
          }
  
          AVFrame* inpic = avcodec_alloc_frame(); //av_frame_alloc () ?
          AVFrame* outpic = avcodec_alloc_frame();
  
          outpic-&gt;pts = (int64_t)((float)i * (1000.0/((float)(c-&gt;time_base.den))) * 90);
          if (avpicture_fill((AVPicture*) inpic, (uint8_t*) pPixels, AV_PIX_FMT_RGB32,
                         screenWidth, screenHeight) &lt; 0)
              qDebug () &lt;&lt;  "avpicture_fill Fill picture with image failed"; //Fill picture with image
  
          if(avpicture_fill((AVPicture*) outpic, outbuffer, AV_PIX_FMT_YUV420P,
                         c-&gt;width, c-&gt;height) &lt; 0)
              qDebug () &lt;&lt;  "avpicture_fill failed";
  
          if (av_image_alloc(outpic-&gt;data, outpic-&gt;linesize, c-&gt;width, c-&gt;height,
                         c-&gt;pix_fmt, 1) &lt; 0)
              qDebug () &lt;&lt;  "av_image_alloc failed";
  
          inpic-&gt;data[0] += inpic-&gt;linesize[0]*(screenHeight - 1); // Flipping frame
          inpic-&gt;linesize[0] = -inpic-&gt;linesize[0]; // Flipping frame
  
  ////////////////////////////HERE THE BUG////////////////////////////////
          sws_scale(fooContext,
                    inpic-&gt;data, inpic-&gt;linesize,
                    0, c-&gt;height,
                    outpic-&gt;data, outpic-&gt;linesize); //HERE THE BUG
  
          av_free_packet((AVPacket *)outbuf);
          // encode the image
          out_size = avcodec_encode_video2 (c, (AVPacket *) outbuf,
                                            (AVFrame *) outbuf_size, (int *) outpic);
  ///////////////////////THE CODE DONT GO BEYOND/////////////////////////////////
  
          qDebug () &lt;&lt; "Encoding frame" &lt;&lt; i &lt;&lt;" (size=" &lt;&lt; out_size &lt;&lt;"\n";
          fwrite(outbuf, 1, out_size, f);
          delete [] pPixels;
          av_free(outbuffer);
          av_free(inpic);
          av_freep(outpic);
      }
  
      // get the delayed frames
      for(; out_size; i++)
      {
          fflush(stdout);
          out_size = avcodec_encode_video2 (c, (AVPacket *) outbuf,
                                            (AVFrame *) outbuf_size, NULL);
          qDebug () &lt;&lt; "Writing frame" &lt;&lt; i &lt;&lt;" (size=" &lt;&lt; out_size &lt;&lt;"\n";
          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);
  
      avcodec_close(c);
      free(outbuf);
      av_free(c);
      qDebug () &lt;&lt; "Closed codec and Freed\n";
  }
  </code></pre>
  
  <p>And the output :</p>
  
  <pre><code>Video encoding
  
  H264 codec found
  
  H264 codec opened
  
  Setting buffer size to:  2020000 
  
  Opened video file for writing
  
  i =  0
  **CRASH**
  </code></pre>
  
  <p>I have thougth that my bitmap wasn't good so I have crafted a bitmap just for testing,  the code was :</p>
  
  <pre><code>    uint8_t* pPixels = new uint8_t[Width * 3 * Height];
      int x = 50;
      for(unsigned int i = 0; i &lt; Width * 3 * Height; i = i + 3) // loop for generating color changing images
      {
          pPixels [i] = x % 255; //R
          pPixels [i + 1] = (x) % 255; //G
          pPixels [i + 2] = (255 - x) % 255; //B
      }
  </code></pre>
  
  <p>However the crash continue. Perhaps, it might prove that it's not the bitmap (pPixels) which has a problem.</p>
  
  <p>If anyone know, why I get this bug : Maybe don't I set one parameter well ? Or one ffmpeg deprecated function ? etc.</p>
  
  <hr>
  
  <h2><strong>EDIT 1 27/12/15</strong></h2>
  
  <p>Thanks to <em>Ronald S. Bultje</em> The function <em>sws_scale ()</em> does not crash with this code, <strong>however</strong> I get an error from it <em>bad dst image pointers</em>. My code:</p>
  
  <pre><code>//DESTINATION FRAME            
  if (avpicture_alloc ((AVPicture*) dst_frame, AV_PIX_FMT_YUV420P, c-&gt;width, c-&gt;height) &lt; 0)
              {
                  qDebug () &lt;&lt;  "# avpicture_alloc failed";
                  return;
              }
              if(avpicture_fill((AVPicture*) dst_frame, NULL, AV_PIX_FMT_YUV420P,
                             c-&gt;width, c-&gt;height) &lt; 0)
                  qDebug () &lt;&lt;  "avpicture_fill failed";
              avcodec_align_dimensions2 (c, &amp;c-&gt;width, &amp;c-&gt;height, dst_frame-&gt;linesize);
  
  //SOURCE FRAME
              if (avpicture_fill((AVPicture*) src_frame, (uint8_t *) pPixels, AV_PIX_FMT_RGB32,
                                 tmp_screenWidth, tmp_screenHeight) &lt; 0)
                  qDebug () &lt;&lt;  "# avpicture_fill Fill picture with image failed"; //Fill picture with image
              avcodec_align_dimensions2 (c, &amp;tmp_screenWidth, &amp;tmp_screenHeight, src_frame-&gt;linesize);
  
              struct SwsContext* conversionContext = sws_getContext(tmp_screenWidth,tmp_screenHeight,AV_PIX_FMT_RGB32,c-&gt;width, c-&gt;height, AV_PIX_FMT_YUV420P,SWS_FAST_BILINEAR, NULL, NULL, NULL);
  
              int output_Height = sws_scale(conversionContext,
                                            src_frame-&gt;data, src_frame-&gt;linesize,
                                            0, tmp_screenHeight,
                                            dst_frame-&gt;data, dst_frame-&gt;linesize); //return 0 -&gt; bad dst image pointers error
  </code></pre>
  
  <hr>
  
  <h2><strong>EDIT 2 28/12/15</strong></h2>
  
  <p>I have tried to follow the Ronald S. Bultje's suggestion and now I get a <em>bad src image pointers</em> error, I have investigated and worked many hours but I do not find a solution. Here, there is the new snippet :</p>
  
  <pre><code>AVFrame* src_frame = av_frame_alloc ();
  AVFrame* dst_frame = av_frame_alloc ();
  AVFrame* tmp_src_frame = av_frame_alloc ();
  
  /*........I do not use them until this snippet..........*/
  //DESTINATION
  //avpicture_free ((AVPicture*)dst_frame);
  avcodec_align_dimensions2 (c, &amp;c-&gt;width, &amp;c-&gt;height, dst_frame-&gt;linesize);
  if (avpicture_alloc ((AVPicture*) dst_frame, AV_PIX_FMT_YUV420P, c-&gt;width, c-&gt;height) &lt; 0)
  {
      qDebug () &lt;&lt;  "# avpicture_alloc failed";
      return;
  }
  
  //SOURCE
  //stride = src_frame-&gt;linesize [0] = ((((screenWidth * bitPerPixel) + 31) &amp; ~31) &gt;&gt; 3); do I need to do that ?
  //== stride - I have gotten this formula from : https://msdn.microsoft.com/en-us/library/windows/desktop/dd318229(v=vs.85).aspx
  if (avpicture_fill((AVPicture*) src_frame, (uint8_t *) pPixels, AV_PIX_FMT_RGB32,
                     screenWidth, screenHeight) &lt; 0)
      qDebug () &lt;&lt;  "# avpicture_fill Fill picture with image failed"; //Fill picture with image
  //linesize [0] == 21760 like commented stride
  
  //Source TO TMP Source
  avcodec_align_dimensions2 (c, &amp;tmp_screenWidth, &amp;tmp_screenHeight, tmp_src_frame-&gt;linesize);
  if (avpicture_fill((AVPicture*) tmp_src_frame, NULL, AV_PIX_FMT_RGB32,
                     tmp_screenWidth, tmp_screenHeight) &lt; 0)
      qDebug () &lt;&lt;  "# avpicture_fill Fill picture with image failed"; //Fill picture with image
  
  av_picture_copy ((AVPicture*) tmp_src_frame, (const AVPicture*) src_frame, AV_PIX_FMT_RGB32,
                   screenWidth, screenHeight);
  
  struct SwsContext* conversionContext = sws_getContext(tmp_screenWidth, tmp_screenHeight,
                                                        AV_PIX_FMT_RGB32,
                                                        c-&gt;width, c-&gt;height,
                                                        AV_PIX_FMT_YUV420P,
                                                        SWS_FAST_BILINEAR,
                                                        NULL, NULL, NULL);
  
  int output_Height = sws_scale(conversionContext,
                                tmp_src_frame-&gt;data, tmp_src_frame-&gt;linesize,
                                0, tmp_screenHeight,
                                dst_frame-&gt;data, dst_frame-&gt;linesize);
  //ffmpeg error = bad src image pointers
  // output_Height == 0
  </code></pre>
  
  <h2>EDIT 3</h2>
  
  <p>For temp Picture I have done an <code>avcode_align_dimension2()</code> then a <code>avpicture_alloc()</code> for allocating memory and <code>avpicture_fill()</code> in order to fill the picture pointer. Below the updated code:</p>
  
  <pre><code>//DESTINATION
  //avpicture_free ((AVPicture*)dst_frame);
  avcodec_align_dimensions2 (c, &amp;c-&gt;width, &amp;c-&gt;height, dst_frame-&gt;linesize);
  if (avpicture_alloc ((AVPicture*) dst_frame, AV_PIX_FMT_YUV420P, c-&gt;width, c-&gt;height) &lt; 0)
  {
      qDebug () &lt;&lt;  "# avpicture_alloc failed";
      return;
  }
  
  //SOURCE
  //src_frame-&gt;linesize [0] = ((((screenWidth * bpp) + 31) &amp; ~31) &gt;&gt; 3);
  //src_frame-&gt;linesize [0] = stride;
  if (avpicture_fill((AVPicture*) src_frame, (uint8_t *) pPixels, AV_PIX_FMT_RGB32,
                     screenWidth, screenHeight) &lt; 0)
      qDebug () &lt;&lt;  "# avpicture_fill Fill picture with image failed"; //Fill picture with image
  
  //Source TO TMP Source
  avcodec_align_dimensions2 (c, &amp;tmp_screenWidth, &amp;tmp_screenHeight, tmp_src_frame-&gt;linesize);
  if (avpicture_alloc ((AVPicture*) tmp_src_frame, AV_PIX_FMT_RGB32, tmp_screenWidth, tmp_screenHeight) &lt; 0)
  {
      qDebug () &lt;&lt;  "# avpicture_alloc failed";
      return;
  }
  int outbuf_size = tmp_screenWidth*tmp_screenHeight*4;// alloc image and output buffer
  outbuf = static_cast&lt;uint8_t *&gt;(malloc(outbuf_size));
  if (avpicture_fill((AVPicture*) tmp_src_frame, outbuf, AV_PIX_FMT_RGB32,
                     tmp_screenWidth, tmp_screenHeight) &lt; 0)
      qDebug () &lt;&lt;  "# avpicture_fill Fill picture with image failed"; //Fill picture with image
  av_picture_copy ((AVPicture*) tmp_src_frame, (const AVPicture*) src_frame, AV_PIX_FMT_RGB32,
                   tmp_screenWidth, tmp_screenHeight);
  
  struct SwsContext* conversionContext = sws_getContext(tmp_screenWidth, tmp_screenHeight,
                                                        AV_PIX_FMT_RGB32,
                                                        c-&gt;width, c-&gt;height,
                                                        AV_PIX_FMT_YUV420P,
                                                        SWS_FAST_BILINEAR,
                                                        NULL, NULL, NULL);
  
  int output_Height = sws_scale(conversionContext,
                                tmp_src_frame-&gt;data, tmp_src_frame-&gt;linesize,
                                0, tmp_screenHeight,
                                dst_frame-&gt;data, dst_frame-&gt;linesize);
  </code></pre>
  
  <p>The call stack is as follow : <code>av_picture_copy()</code> is called then <code>av_image_copy()</code> then <code>_VEC_memcpy()</code> then <code>fastcopy_I()</code> and crash ... The problem is not the dimensions (tmp_screenWidth/Height) ? (With <code>av_picture_copy ()</code> could we copy a picture P1 with dim W1xH1 to a picture P2 with dimension W2xH2 ?)</p>
  
  <h2><strong>EDIT 4</strong></h2>
  
  <p>Crash at <code>av_picture_copy()</code> which <code>call _aligned_malloc()</code> then <code>av_image_copy _VEC_memcpy()</code> and <code>fastcopy_I()</code></p>
  
  <pre><code>//SOURCE
  if (avpicture_fill((AVPicture*) src_frame, (uint8_t *) pPixels, AV_PIX_FMT_RGB32,
                     screenWidth, screenHeight) &lt; 0)
      qDebug () &lt;&lt;  "# avpicture_fill Fill picture with image failed"; //Fill picture with image
  
  //Source TO TMP Source
  avcodec_align_dimensions2 (c, &amp;tmp_screenWidth, &amp;tmp_screenHeight, tmp_src_frame-&gt;linesize);
  if (avpicture_alloc ((AVPicture*) tmp_src_frame, AV_PIX_FMT_RGB32, tmp_screenWidth, tmp_screenHeight) &lt; 0)
  {
      qDebug () &lt;&lt;  "# avpicture_alloc failed";
      return;
  }
  av_picture_copy ((AVPicture*) tmp_src_frame, (const AVPicture*) src_frame, AV_PIX_FMT_RGB32,
                   tmp_screenWidth, tmp_screenHeight);
  </code></pre>