title: Segmentation fault with avcodec_encode_video2() while encoding H.264
body: <p>I'm trying to convert a <code>cv::Mat</code> to an <code>AVFrame</code> to encode it then in H.264 and wanted to start from a simple example, as I'm a newbie in both. So I first read in a JPEG file, and then do the pixel format conversion with <code>sws_scale()</code> from <code>AV_PIX_FMT_BGR24</code> to <code>AV_PIX_FMT_YUV420P</code> keeping the dimensions the same, and it all goes fine until I call <code>avcodec_encode_video2()</code>.</p>
  
  <p>I read quite a few discussions regarding an <code>AVFrame</code> allocation and the question <a href="https://stackoverflow.com/questions/16987749/segmetation-fault-while-avcodec-encode-video2">Segmentation fault while avcodec_encode_video2</a> seemed like a match but I just can't see what I'm missing or getting wrong.</p>
  
  <p>Here is the minimal code that you can reproduce the crash, it should be compiled with,</p>
  
  <pre><code>g++ -o OpenCV2FFmpeg OpenCV2FFmpeg.cpp -lopencv_imgproc -lopencv_highgui -lopencv_core -lswscale -lavutil -lavcodec -lavformat
  </code></pre>
  
  <p>It's output on my system,</p>
  
  <pre><code>cv::Mat [width=420, height=315, depth=0, channels=3, step=1260]
  I'll soon crash..
  Segmentation fault
  </code></pre>
  
  <p>And that <code>sample.jpg</code> file's details by <code>identify</code> tool,</p>
  
  <pre><code>~temporary/sample.jpg JPEG 420x315 420x315+0+0 8-bit sRGB 38.3KB 0.000u 0:00.000
  </code></pre>
  
  <p>Please note that I'm trying to create a video out of a single image, just to keep things simple.</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;cassert&gt;
  using namespace std;
  
  extern "C" {
      #include &lt;libavcodec/avcodec.h&gt;
      #include &lt;libswscale/swscale.h&gt;
      #include &lt;libavformat/avformat.h&gt;
  }
  
  #include &lt;opencv2/core/core.hpp&gt;
  #include &lt;opencv2/highgui/highgui.hpp&gt;
  
  const string TEST_IMAGE = "/home/baris/temporary/sample.jpg";
  
  int main(int /*argc*/, char** argv)
  {
      av_register_all();
      avcodec_register_all();
  
      /**
       * Initialise the encoder
       */
      AVCodec *h264encoder = avcodec_find_encoder(AV_CODEC_ID_H264);
      AVFormatContext *cv2avFormatContext = avformat_alloc_context();
  
      /**
       * Create a stream and allocate frames
       */
      AVStream *h264outputstream = avformat_new_stream(cv2avFormatContext, h264encoder);
      avcodec_get_context_defaults3(h264outputstream-&gt;codec, h264encoder);
      AVFrame *sourceAvFrame = av_frame_alloc(), *destAvFrame = av_frame_alloc();
      int got_frame;
  
      /**
       * Pixel formats for the input and the output
       */
      AVPixelFormat sourcePixelFormat = AV_PIX_FMT_BGR24;
      AVPixelFormat destPixelFormat = AV_PIX_FMT_YUV420P;
  
      /**
       * Create cv::Mat
       */
      cv::Mat cvFrame = cv::imread(TEST_IMAGE, CV_LOAD_IMAGE_COLOR);
      int width = cvFrame.size().width, height = cvFrame.size().height;
      cerr &lt;&lt; "cv::Mat [width=" &lt;&lt; width &lt;&lt; ", height=" &lt;&lt; height &lt;&lt; ", depth=" &lt;&lt; cvFrame.depth() &lt;&lt; ", channels=" &lt;&lt; cvFrame.channels() &lt;&lt; ", step=" &lt;&lt; cvFrame.step &lt;&lt; "]" &lt;&lt; endl;
  
      h264outputstream-&gt;codec-&gt;pix_fmt = destPixelFormat;
      h264outputstream-&gt;codec-&gt;width = cvFrame.cols;
      h264outputstream-&gt;codec-&gt;height = cvFrame.rows;
  
      /**
       * Prepare the conversion context
       */
      SwsContext *bgr2yuvcontext = sws_getContext(width, height,
                                                  sourcePixelFormat,
                                                  h264outputstream-&gt;codec-&gt;width, h264outputstream-&gt;codec-&gt;height,
                                                  h264outputstream-&gt;codec-&gt;pix_fmt,
                                                  SWS_BICUBIC, NULL, NULL, NULL);
  
      /**
       * Convert and encode frames
       */
      for (uint i=0; i &lt; 250; i++)
      {
          /**
           * Allocate source frame, i.e. input to sws_scale()
           */
          avpicture_alloc((AVPicture*)sourceAvFrame, sourcePixelFormat, width, height);
  
          for (int h = 0; h &lt; height; h++)
              memcpy(&amp;(sourceAvFrame-&gt;data[0][h*sourceAvFrame-&gt;linesize[0]]), &amp;(cvFrame.data[h*cvFrame.step]), width*3);
  
          /**
           * Allocate destination frame, i.e. output from sws_scale()
           */
          avpicture_alloc((AVPicture *)destAvFrame, destPixelFormat, width, height);
  
          sws_scale(bgr2yuvcontext, sourceAvFrame-&gt;data, sourceAvFrame-&gt;linesize,
                    0, height, destAvFrame-&gt;data, destAvFrame-&gt;linesize);
  
          /**
           * Prepare an AVPacket for encoded output
           */
          AVPacket avEncodedPacket;
          av_init_packet(&amp;avEncodedPacket);
          avEncodedPacket.data = NULL;
          avEncodedPacket.size = 0;
          // av_free_packet(&amp;avEncodedPacket); w/ or w/o result doesn't change
  
          cerr &lt;&lt; "I'll soon crash.." &lt;&lt; endl;
          if (avcodec_encode_video2(h264outputstream-&gt;codec, &amp;avEncodedPacket, destAvFrame, &amp;got_frame) &lt; 0)
              exit(1);
  
          cerr &lt;&lt; "Checking if we have a frame" &lt;&lt; endl;
          if (got_frame)
              av_write_frame(cv2avFormatContext, &amp;avEncodedPacket);
  
          av_free_packet(&amp;avEncodedPacket);
          av_frame_free(&amp;sourceAvFrame);
          av_frame_free(&amp;destAvFrame);
      }
  }
  </code></pre>
  
  <p>Thanks in advance!</p>
  
  <p><strong>EDIT:</strong> And the stack trace after the crash,</p>
  
  <pre><code>Thread 2 (Thread 0x7fffe5506700 (LWP 10005)):
  #0  0x00007ffff4bf6c5d in poll () at /lib64/libc.so.6
  #1  0x00007fffe9073268 in  () at /usr/lib64/libusb-1.0.so.0
  #2  0x00007ffff47010a4 in start_thread () at /lib64/libpthread.so.0
  #3  0x00007ffff4bff08d in clone () at /lib64/libc.so.6
  
  Thread 1 (Thread 0x7ffff7f869c0 (LWP 10001)):
  #0  0x00007ffff5ecc7dc in avcodec_encode_video2 () at /usr/lib64/libavcodec.so.56
  #1  0x00000000004019b6 in main(int, char**) (argv=0x7fffffffd3d8) at ../src/OpenCV2FFmpeg.cpp:99
  </code></pre>
  
  <p><strong>EDIT2:</strong> Problem was that I hadn't <code>avcodec_open2()</code> the codec as spotted by Ronald. Final version of the code is at <a href="https://github.com/barisdemiray/opencv2ffmpeg/" rel="nofollow noreferrer">https://github.com/barisdemiray/opencv2ffmpeg/</a>, with leaks and probably other problems hoping that I'll improve it while learning both libraries.</p>