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
Post a Comment