c++ - Segmentation fault with avcodec_encode_video2() while encoding H.264 -


i'm trying convert cv::mat avframe encode in h.264 , wanted start simple example, i'm newbie in both. first read in jpeg file, , pixel format conversion sws_scale() av_pix_fmt_bgr24 av_pix_fmt_yuv420p keeping dimensions same, , goes fine until call avcodec_encode_video2().

i read quite few discussions regarding avframe allocation , question segmentation fault while avcodec_encode_video2 seemed match can't see i'm missing or getting wrong.

here minimal code can reproduce crash, should compiled with,

g++ -o opencv2ffmpeg opencv2ffmpeg.cpp -lopencv_imgproc -lopencv_highgui -lopencv_core -lswscale -lavutil -lavcodec -lavformat 

it's output on system,

cv::mat [width=420, height=315, depth=0, channels=3, step=1260] i'll crash.. segmentation fault 

and sample.jpg file's details identify tool,

~temporary/sample.jpg jpeg 420x315 420x315+0+0 8-bit srgb 38.3kb 0.000u 0:00.000 

please note i'm trying create video out of single image, keep things simple.

#include <iostream> #include <cassert> using namespace std;  extern "c" {     #include <libavcodec/avcodec.h>     #include <libswscale/swscale.h>     #include <libavformat/avformat.h> }  #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp>  const string test_image = "/home/baris/temporary/sample.jpg";  int main(int /*argc*/, char** argv) {     av_register_all();     avcodec_register_all();      /**      * initialise encoder      */     avcodec *h264encoder = avcodec_find_encoder(av_codec_id_h264);     avformatcontext *cv2avformatcontext = avformat_alloc_context();      /**      * create stream , allocate frames      */     avstream *h264outputstream = avformat_new_stream(cv2avformatcontext, h264encoder);     avcodec_get_context_defaults3(h264outputstream->codec, h264encoder);     avframe *sourceavframe = av_frame_alloc(), *destavframe = av_frame_alloc();     int got_frame;      /**      * pixel formats input , 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 << "cv::mat [width=" << width << ", height=" << height << ", depth=" << cvframe.depth() << ", channels=" << cvframe.channels() << ", step=" << cvframe.step << "]" << endl;      h264outputstream->codec->pix_fmt = destpixelformat;     h264outputstream->codec->width = cvframe.cols;     h264outputstream->codec->height = cvframe.rows;      /**      * prepare conversion context      */     swscontext *bgr2yuvcontext = sws_getcontext(width, height,                                                 sourcepixelformat,                                                 h264outputstream->codec->width, h264outputstream->codec->height,                                                 h264outputstream->codec->pix_fmt,                                                 sws_bicubic, null, null, null);      /**      * convert , encode frames      */     (uint i=0; < 250; i++)     {         /**          * allocate source frame, i.e. input sws_scale()          */         avpicture_alloc((avpicture*)sourceavframe, sourcepixelformat, width, height);          (int h = 0; h < height; h++)             memcpy(&(sourceavframe->data[0][h*sourceavframe->linesize[0]]), &(cvframe.data[h*cvframe.step]), width*3);          /**          * allocate destination frame, i.e. output sws_scale()          */         avpicture_alloc((avpicture *)destavframe, destpixelformat, width, height);          sws_scale(bgr2yuvcontext, sourceavframe->data, sourceavframe->linesize,                   0, height, destavframe->data, destavframe->linesize);          /**          * prepare avpacket encoded output          */         avpacket avencodedpacket;         av_init_packet(&avencodedpacket);         avencodedpacket.data = null;         avencodedpacket.size = 0;         // av_free_packet(&avencodedpacket); w/ or w/o result doesn't change          cerr << "i'll crash.." << endl;         if (avcodec_encode_video2(h264outputstream->codec, &avencodedpacket, destavframe, &got_frame) < 0)             exit(1);          cerr << "checking if have frame" << endl;         if (got_frame)             av_write_frame(cv2avformatcontext, &avencodedpacket);          av_free_packet(&avencodedpacket);         av_frame_free(&sourceavframe);         av_frame_free(&destavframe);     } } 

thanks in advance!

edit: , stack trace after crash,

thread 2 (thread 0x7fffe5506700 (lwp 10005)): #0  0x00007ffff4bf6c5d in poll () @ /lib64/libc.so.6 #1  0x00007fffe9073268 in  () @ /usr/lib64/libusb-1.0.so.0 #2  0x00007ffff47010a4 in start_thread () @ /lib64/libpthread.so.0 #3  0x00007ffff4bff08d in clone () @ /lib64/libc.so.6  thread 1 (thread 0x7ffff7f869c0 (lwp 10001)): #0  0x00007ffff5ecc7dc in avcodec_encode_video2 () @ /usr/lib64/libavcodec.so.56 #1  0x00000000004019b6 in main(int, char**) (argv=0x7fffffffd3d8) @ ../src/opencv2ffmpeg.cpp:99 

edit2: problem hadn't avcodec_open2() codec spotted ronald. final version of code @ https://github.com/barisdemiray/opencv2ffmpeg/, leaks , other problems hoping i'll improve while learning both libraries.

please provide gdb backtrace after crashes. i'm pretty sure it'll crash because picture pointers unaligned (avpicture_alloc() allocate unaligned images, , avcodec_encode_video2() expects aligned data pointers), there may additional reasons why crash also.

to align data pointers in avframe, use av_image_alloc() , related functions, align=32.

another problem didn't call avcodec_open2(h264outputstream->codec, h264encoder).


Comments