Can't open encoder when use libavcodec - c++

I'm using libavcodec, version 9.7, to write a simple demo, almost exactly like example in official example.
However, I can't open encoder. Also, av_opt_set(context->priv_data, "preset", "slow", 0) always leads to crush.
This is my code:
// other code...
int ret = 0;
avcodec_register_all();
AVCodec* codec = NULL;
AVCodecContext* context = NULL;
AVFrame* frame = NULL;
uint8_t endcode[] = { 0, 0, 1, 0xb7 };
codec = avcodec_find_encoder(AV_CODEC_ID_H264);
if(!codec){
qDebug()<<"cannot find encoder";
return;
}
qDebug()<<"encoder found";
context = avcodec_alloc_context3(codec);
if(!context){
qDebug()<<"cannot alloc context";
return;
}
qDebug()<<"context allocted";
context->bit_rate = 400000;
/* resolution must be a multiple of two */
context->width = 352;
context->height = 288;
/* frames per second */
context->time_base= (AVRational){1,25};
context->gop_size = 10; /* emit one intra frame every ten frames */
context->max_b_frames=1;
context->pix_fmt = AV_PIX_FMT_YUV420P;
qDebug()<<"context init";
// av_opt_set(context->priv_data, "preset", "slow", 0); // this will crush
AVDictionary *d = NULL;
av_dict_set(&d, "preset", "ultrafast",0); // this won't
ret = avcodec_open2(context, codec, &d);
if ( ret < 0) {
qDebug()<<"cannot open codec"<<ret;
return;
}
qDebug()<<"codec open";
// other code...
This outputs:
encoder found
context allocted
context init
cannot open codec -22
[libx264 # 0340B340] [IMGUTILS # 0028FC34] Picture size 0x10 is invalid
[libx264 # 0340B340] ignoring invalid width/height values
[libx264 # 0340B340] Specified pix_fmt is not supported
I don't think the width/height is invalid and format there either. I have no idea what's wrong here.
Any help. plz?

This is an issue of libav, I haven't checked its issue list though. The code runs great when I use another daily build, 20131101.

Related

FFMPEG using AV_PIX_FMT_D3D11 gives "Error registering the input resource" from NVENC

Input frames start on the GPU as ID3D11Texture2D pointers.
I encode them to H264 using FFMPEG + NVENC. NVENC works perfectly if I download the textures to CPU memory as format AV_PIX_FMT_BGR0, but I'd like to cut out the CPU texture download entirely, and pass the GPU memory pointer directly into the encoder in native format. I write frames like this:
int write_gpu_video_frame(ID3D11Texture2D* gpuTex, AVFormatContext* oc, OutputStream* ost) {
AVFrame *hw_frame = ost->hw_frame;
printf("gpuTex address = 0x%x\n", &gpuTex);
hw_frame->data[0] = (uint8_t *) gpuTex;
hw_frame->data[1] = (uint8_t *) (intptr_t) 0;
hw_frame->pts = ost->next_pts++;
return write_frame(oc, ost->enc, ost->st, hw_frame);
// write_frame is identical to sample code in ffmpeg repo
}
Running the code with this modification gives the following error:
gpuTex address = 0x4582f6d0
[h264_nvenc # 00000191233e1bc0] Error registering an input resource: invalid call (9):
[h264_nvenc # 00000191233e1bc0] Could not register an input HW frame
Error sending a frame to the encoder: Unknown error occurred
Here's some supplemental code used in setting up and configuring the hw context and encoder:
/* A few config flags */
#define ENABLE_NVENC TRUE
#define USE_D3D11 TRUE // Skip downloading textures to CPU memory and send it straight to NVENC
/* Init hardware frame context */
static int set_hwframe_ctx(AVCodecContext* ctx, AVBufferRef* hw_device_ctx) {
AVBufferRef* hw_frames_ref;
AVHWFramesContext* frames_ctx = NULL;
int err = 0;
if (!(hw_frames_ref = av_hwframe_ctx_alloc(hw_device_ctx))) {
fprintf(stderr, "Failed to create HW frame context.\n");
throw;
}
frames_ctx = (AVHWFramesContext*) (hw_frames_ref->data);
frames_ctx->format = AV_PIX_FMT_D3D11;
frames_ctx->sw_format = AV_PIX_FMT_NV12;
frames_ctx->width = STREAM_WIDTH;
frames_ctx->height = STREAM_HEIGHT;
//frames_ctx->initial_pool_size = 20;
if ((err = av_hwframe_ctx_init(hw_frames_ref)) < 0) {
fprintf(stderr, "Failed to initialize hw frame context. Error code: %s\n", av_err2str(err));
av_buffer_unref(&hw_frames_ref);
throw;
}
ctx->hw_frames_ctx = av_buffer_ref(hw_frames_ref);
if (!ctx->hw_frames_ctx)
err = AVERROR(ENOMEM);
av_buffer_unref(&hw_frames_ref);
return err;
}
/* Add an output stream. */
static void add_video_stream(
OutputStream* ost,
AVFormatContext* oc,
const AVCodec** codec,
enum AVCodecID codec_id,
int width,
int height
) {
AVCodecContext* c;
int i;
bool nvenc = false;
/* find the encoder */
if (ENABLE_NVENC) {
printf("Getting nvenc encoder\n");
*codec = avcodec_find_encoder_by_name("h264_nvenc");
nvenc = true;
}
if (!ENABLE_NVENC || *codec == NULL) {
printf("Getting standard encoder\n");
avcodec_find_encoder(codec_id);
nvenc = false;
}
if (!(*codec)) {
fprintf(stderr, "Could not find encoder for '%s'\n",
avcodec_get_name(codec_id));
exit(1);
}
ost->st = avformat_new_stream(oc, NULL);
if (!ost->st) {
fprintf(stderr, "Could not allocate stream\n");
exit(1);
}
ost->st->id = oc->nb_streams - 1;
c = avcodec_alloc_context3(*codec);
if (!c) {
fprintf(stderr, "Could not alloc an encoding context\n");
exit(1);
}
ost->enc = c;
printf("Using video codec %s\n", avcodec_get_name(codec_id));
c->codec_id = codec_id;
c->bit_rate = 4000000;
/* Resolution must be a multiple of two. */
c->width = STREAM_WIDTH;
c->height = STREAM_HEIGHT;
/* timebase: This is the fundamental unit of time (in seconds) in terms
* of which frame timestamps are represented. For fixed-fps content,
* timebase should be 1/framerate and timestamp increments should be
* identical to 1. */
ost->st->time_base = {1, STREAM_FRAME_RATE};
c->time_base = ost->st->time_base;
c->gop_size = 12; /* emit one intra frame every twelve frames at most */
if (nvenc && USE_D3D11) {
const std::string hw_device_name = "d3d11va";
AVHWDeviceType device_type = av_hwdevice_find_type_by_name(hw_device_name.c_str());
// set up hw device context
AVBufferRef *hw_device_ctx;
// const char* device = "0"; // Default GPU (may be integrated in the case of switchable graphics!)
const char* device = "1";
ret = av_hwdevice_ctx_create(&hw_device_ctx, device_type, device, nullptr, 0);
if (ret < 0) {
fprintf(stderr, "Could not create hwdevice context; %s", av_err2str(ret));
}
set_hwframe_ctx(c, hw_device_ctx);
c->pix_fmt = AV_PIX_FMT_D3D11;
} else if (nvenc && !USE_D3D11)
c->pix_fmt = AV_PIX_FMT_BGR0;
else
c->pix_fmt = STREAM_PIX_FMT;
if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
/* just for testing, we also add B-frames */
c->max_b_frames = 2;
}
if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO) {
/* Needed to avoid using macroblocks in which some coeffs overflow.
* This does not happen with normal video, it just happens here as
* the motion of the chroma plane does not match the luma plane. */
c->mb_decision = 2;
}
/* Some formats want stream headers to be separate. */
if (oc->oformat->flags & AVFMT_GLOBALHEADER)
c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
}

An Unhandled exception: YUV Packed to JPEG Conversion On Button Press VC++2010 Form Application

i have YUV packed images which i have first convert to planar and then jpeg format (on button press) for Displaying in a picture box in VC++ 2010, using command at the end of entire code (after jpeg conversion done)
pictureBox1->Image = Image::FromFile("d:\\encoded_pic_420.jpg");
i am able to store and format convert these received images from YUV packed to YUV planar First and then Second from "Planar to JPEG format" (below Code First & Second).
on first time it Convert and Display image in picture box sucessfully, but when i press button second time it generate an error (in this below code section) SECOND PART OF CODE (PLANAR TO JPEG CONVERSION
if (got_picture==1)
{
pkt.stream_index = video_st->index;
ret = av_write_frame(pFormatCtx, &pkt);
}
error mesage is at Code Line (above) ret = av_write_frame (pFormatCtx,&pkt);
message is :
"An unhandled exception of type accured System.AccessViolationException , Additional information: Attempted to read or write protected memory, this is often an indication that other memory is corrupted"
the Complete code which i am using for YUV packet to Planar first and then second Planar to Jpeg conversion is below one.
First: YUV PACKED to PLANAR CONVERSION
FILE *in_file = NULL; //fopen("myHexFile.yuv","rb"); input PACKED
FILE *out_file = NULL; //Output File Planar format
int in_width = 2448; //YUV's width
int in_height = 2050; //YUV's heigh
int out_width = 2448; //YUV's width
int out_height = 2050; //YUV's heigh
int in_linesize[4];
int out_linesize[4];
uint8_t *in_data[4], *out_data[4];
unsigned long int out_bufsize,in_bufsize;
in_file = fopen("myHexFile.yuv","rb"); //This is YUV422-UYVY Input packed image
if(in_file == NULL)
{
this->Print2TextBox1(L"Input File Opening error...!");
exit(1);
}
out_file = fopen("d:\\myHexFile_Planar.yuv", "wb"); //Source Input File
if(out_file == NULL)
{
this->Print2TextBox1(L"toutput File Opening error...!!");
exit(1);
}
else { this->Print2TextBox1(L"Output File Created...!!\n"); }
//-Loads the whole database of available codecs and formats-------
av_register_all();
this->Print2TextBox1(L"Codac database Loaded...\n");
//---Create scaling context------------------------sws_getContex
this->Print2TextBox1(L"Creating Scaling context..\n");
sws_ctx = sws_getContext( in_width, in_height, src_pix_fmt,
out_width,out_height,dst_pix_fmt,
SWS_BICUBIC, NULL, NULL, NULL);
if(!sws_ctx) { this->Print2TextBox1(L"Context Error..\n"); }
//--Allocate Source Image Buffer--------------------------
this->Print2TextBox1(L"Allocate Source Image Buffer...\n");
AVFrame *RawPic = av_frame_alloc();
if(!RawPic)
{
this->Print2TextBox1(L"Could not allocate Raw Image frame\n");
exit(1);
}
RawPic->format = src_pix_fmt;
RawPic->width = in_width;
RawPic->height = in_height;
int num_bytes1 = avpicture_get_size(src_pix_fmt,in_width,in_height);
uint8_t* RawPic_Buffer = (uint8_t*)av_malloc(num_bytes1*sizeof(int8_t));
ret =av_image_alloc(RawPic->data,in_linesize,in_width,in_height,src_pix_fmt, 1);
if(ret < 0)
{
this->Print2TextBox1(L"Could not allocate raw picture buffer\n");
exit(1);
}
in_bufsize = ret;
//------Reading Input Image and Store in RawPic->Data Pointer---
fread(RawPic->data[0],1,in_bufsize,in_file);
//----Allocate Desitnation Image Buffer-------------------
this->Print2TextBox1(L"Allocate Destination Image Buffer...\n");
AVFrame *ScalePic = av_frame_alloc();
if(!ScalePic)
{
this->Print2TextBox1(L"Could not allocate Scale Image frame\n");
exit(1);
}
ScalePic->format = dst_pix_fmt;//pCodecCtx->pix_fmt;
ScalePic->width = out_width;
ScalePic->height = out_height;
int num_bytes2 = avpicture_get_size(dst_pix_fmt,out_width,out_height);
uint8_t* ScalePic_Buffer = (uint8_t *)av_malloc(num_bytes2*sizeof(int8_t));
ret = av_image_alloc(ScalePic->data,out_linesize,out_width,out_height,dst_pix_fmt, 1); //16
if(ret < 0) { this->Print2TextBox1(L"Could not allocate Scale picture buffer\n"); exit(1);}
out_bufsize = ret;
//-Create scaling context-OR CONVERTED TO DESTINATION FORMAT-----sws_scale
this->Print2TextBox1(L"Creating Scaling context...sws_scale\n");
sws_scale(sws_ctx, RawPic->data, in_linesize, 0, ScalePic->height, ScalePic->data, out_linesize);
//-----Write Scale Image to outputfile-
this->Print2TextBox1(L"Write Scale Image to outputfile..\n");
fwrite(ScalePic->data[0],1,out_bufsize,out_file);
//---Release all memory and close file--
fclose(in_file);
fclose(out_file);
av_freep(&RawPic->data[0]);
av_freep(&ScalePic->data[0]);
av_frame_free(&ScalePic);
av_frame_free(&RawPic);
SECOND--CONVERT to PLANAR TO JPEG FORMAT------(in Continuation to Above Code)
const char* myJpeg_file = "d:\\encoded_pic_444.jpg"; //Output JPEG
in_file = fopen("d:\\myHexFile_Planar.yuv", "rb"); //Input Planar File
if(in_file == NULL)
{
this->Print2TextBox1(L"File Opening error...!!");
exit(1);
}
else this->Print2TextBox1(L"YUV File Open Sucessfully...!!\n\n");
av_register_all(); // Loads the whole database of available codecs and formats.
pFormatCtx = avformat_alloc_context();
fmt = NULL;
fmt = av_guess_format("mjpeg",NULL,NULL);
pFormatCtx->oformat = fmt;
if (avio_open(&pFormatCtx->pb,myJpeg_file, AVIO_FLAG_READ_WRITE) < 0)
{
this->Print2TextBox1(L"Couldn't open output file.");
}
video_st = avformat_new_stream(pFormatCtx, 0);
if (video_st==NULL)
{
this->Print2TextBox1(L"avformat_new_stream.");
}
pCodecCtx = video_st->codec;
pCodecCtx->codec_id = fmt->video_codec;
pCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
pCodecCtx->pix_fmt = AV_PIX_FMT_YUVJ420P;
pCodecCtx->width = in_width;
pCodecCtx->height = in_height;
pCodecCtx->time_base.num = 1;
pCodecCtx->time_base.den = 1;//25;
this->Print2TextBox1(L"Conversion start\n");
//Output some information
av_dump_format(pFormatCtx, 0, myJpeg_file, 1);
// Determine if desired video encoder is installed
pCodec = avcodec_find_encoder(pCodecCtx->codec_id);
if (!pCodec)
{
this->Print2TextBox1(L"Codec not found.");
//return -1;
}
this->Print2TextBox1(L"Codec Identified done\n");
if (avcodec_open2(pCodecCtx, pCodec,NULL) < 0){
this->Print2TextBox1(L"Could not open codec.\n");
//return -1;
}
this->Print2TextBox1(L"Codec Open done\n");
//-----------------------------------------------
picture = av_frame_alloc();
size = avpicture_get_size(pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);
picture_buf = (uint8_t *)av_malloc(size);
if (!picture_buf)
{ this->Print2TextBox1(L"Size Allocation error\n");
//return -1;
}
avpicture_fill((AVPicture *)picture, picture_buf, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);
this->Print2TextBox1(L"Write Header..");
avformat_write_header(pFormatCtx,NULL);
y_size = pCodecCtx->width * pCodecCtx->height;
av_new_packet(&pkt,y_size*3);
//-------------------------------------------------------420 Format
//Read YUV
if (fread(picture_buf, 1, y_size*3/2, in_file) <=0)
{
this->Print2TextBox1(L"Could not read input file.");
//return -1;
}
//--------------------------------------------input image format UYVY
picture->data[0] = picture_buf; // Y
picture->data[1] = picture_buf+ y_size; // U
picture->data[2] = picture_buf+ y_size*5/4; // V
this->Print2TextBox1(L" Encode the image..\n");
ret = avcodec_encode_video2(pCodecCtx, &pkt,picture, &got_picture);
if(ret < 0)
{
this->Print2TextBox1(L"Encode Error.\n");
//return -1;
}
if (got_picture==1)
{
pkt.stream_index = video_st->index;
//#### PROBLEM IN THIS LINE BELOW WHEN RE-EXECUTE THE CODE ###
ret = av_write_frame(pFormatCtx, &pkt);
}
av_free_packet(&pkt);
//Write Trailer
av_write_trailer(pFormatCtx);
this->Print2TextBox1(L"Encode Successful.\n");
if (video_st)
{
avcodec_close(video_st->codec);
av_free(picture);
av_free(picture_buf);
}
avio_close(pFormatCtx->pb);
avformat_free_context(pFormatCtx);
fclose(in_file);
it seems that some of memory is not yet free or when i am trying to re-use this above code in second time in a loop,
plz suggest/guide me where i am doing wrong and not freeing up the memory..?
i am trying to Display Image (Current/updated) on every button press in VC++2010
You are allocating AVFrame
picture = av_frame_alloc();
, but casting it to deprecated AVPicture later:
avpicture_fill((AVPicture *)picture, picture_buf, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);
solved by renaming the "encoded_pic_420.jpg" file with some other name and display it on PictureBox
https://msdn.microsoft.com/en-us/library/windows/desktop/aa363851(v=vs.85).aspx

Programmatically creating a video using FFmpeg, using SDL's sprite screenshot BMP

I have an animation/sprite developed in C++ on SDL2 libs (based on this answer). The bitmaps are saved to a certain path. They are of dimensions 640x480 and format is given by the SDL constant SDL_PIXELFORMAT_ARGB8888.
I have a second program written in C on top of FFmpeg libs, which reads one image from the above path (just one for the time being, will read the whole series when it works for just one).
This does the following (in gist - skipping validation & comments for conciseness)
AVCodec *codec;
AVCodecContext *c = NULL;
int i, ret, x, y, got_output;
FILE *f;
AVFrame *frame;
AVPacket pkt;
uint8_t endcode[] = { 0, 0, 1, 0xb7 };
codec = avcodec_find_encoder(codec_id);
c = avcodec_alloc_context3(codec);
c->bit_rate = 400000;
/* resolution must be a multiple of two */
c->width = 640;
c->height = 480;
c->time_base = (AVRational ) { 1, 25 };
c->gop_size = 5;
c->max_b_frames = 1;
c->pix_fmt = AV_PIX_FMT_YUV420P;
av_opt_set(c->priv_data, "preset", "slow", 0);
avcodec_open2(c, codec, NULL);
fopen(filename, "wb");
frame = av_frame_alloc();
av_image_alloc(frame->data, frame->linesize, c->width, c->height, c->pix_fmt, 32);
for (i = 0; i < 25; ++i) {
readSingleFile("/tmp/alok1/ss099.bmp", &frame->data);//Read the saved BMP into frame->data
frame->pts = i;
frame->width = 640;
frame->height = 480;
frame->format = -1;
av_init_packet(&pkt);
pkt.data = NULL; // packet data will be allocated by the encoder
pkt.size = 0;
ret = avcodec_encode_video2(c, &pkt, frame, &got_output);
if (got_output) {
printf("Write frame %3d (size=%5d)\n", i, pkt.size);
fwrite(pkt.data, 1, pkt.size, f);
}
av_packet_unref(&pkt);
}
for (got_output = 1; got_output; i++) {
fflush(stdout);
ret = avcodec_encode_video2(c, &pkt, NULL, &got_output);
if (ret < 0) {
fprintf(stderr, "Error encoding frame\n");
exit(1);
}
if (got_output) {
printf("[DELAYED]Write frame %3d (size=%5d)\n", i, pkt.size);
fwrite(pkt.data, 1, pkt.size, f);
av_packet_unref(&pkt);
}
}
fwrite(endcode, 1, sizeof(endcode), f);
//cleanup
As a result of the above code(which compiles without trouble), I can get a video which plays for 1 second - this part is working as expected. Problem is that the image seen is a green full screen like below.
The image that is being read using the readSingleImage(...) function is rendered by image viewer(linux, gwenview and okular) as follows:
Any pointers as to what could be going wrong?
To sum up the comments:
Encoder expects raw image data in format specified upon opening; it will not try to convert anything
Colorspace/format conversion has to be done manually; use swscale
if you are using Windows API to load image: it uses BGR, not RGB
BMP files usually but not always store image bottom-up as opposed to top-down used by FFmpeg; if it is bottom-up then it has to be flipped (there might be a way to do that without much or any performance hit if combined with colorspace conversion).
Also keep an eye on linesizes. Each line in an image can occupy more bytes than its width. This applies both to images allocated by ffmpeg and to images loaded from BMP - one has to be careful to always provide valid linesizes to each API call.
In addition to the above, below are "must-reads" for the final solution:
1. Taking a screenshot with SDL
2. RGB to YUV conversion
3. FFmpeg-related source code was written with this as base

ffmpeg hangs in avcodec_encode_video2

I encode the video stream using ffmeg. Shell QT Creator. OC Windows 7. The compiler MinGW. H264 codec.
There is a function, which I give to the input frame, and I must return an encoded byte array. Within this function it hangs when calling avcodec_encode_video2, but not on the first call, and at random.
That is, an arbitrary coding frame hangs (100 to 10000).
QByteArray VideoEncoder::createFrameVideoFromImage(QImage picture)
{
AVFrame* frame_source = av_frame_alloc();
avpicture_fill((AVPicture*)frame_source, picture.bits(), AV_PIX_FMT_RGB24, this->width_frame, this->height_frame);
AVFrame* frame_dst = av_frame_alloc();
avpicture_fill((AVPicture*)frame_dst, (uint8_t*)this->inbuffer, AV_PIX_FMT_YUV420P, this->width_frame, this->height_frame);
sws_scale(this->convert_rgb_yuv, frame_source->data, frame_source->linesize,
0, this->ctx_codec_in->height, frame_dst->data, frame_dst->linesize);
AVPacket packet;
av_init_packet(&packet);
packet.data = NULL;
packet.size = 0;
packet.pts = packet.dts = AV_NOPTS_VALUE;
int nOutputSize = 0;
if (avcodec_encode_video2(this->ctx_codec_in, &packet, frame_dst, &nOutputSize) < 0)
{
qDebug() << "VideoEncoder error";
}
this->traffic += packet.size;
QByteArray data_frame = QByteArray((char*)packet.data, packet.size);
av_frame_free(&frame_source);
av_frame_free(&frame_dst);
av_free_packet(&packet);
return data_frame;
}
Thank you in advance!

avcodec_open2 error -542398533 : "Generic error in an external library"

I am encountering an error when trying to open the codec with avcodec_open2(). I have tried the same code without any problems if I specify avi instead of h264 in the av_guess_format() function.
I don't know what to make of it. Has anyone else encountered a similar problem?
The library that I'm using is ffmpeg-20160219-git-98a0053-win32-dev. I would really really appreciate if you could help me out of this confusion.
This is my console output:
Video encoding
[libx264 # 01383460] broken ffmpeg default settings detected
[libx264 # 01383460] use an encoding preset (e.g. -vpre medium)
[libx264 # 01383460] preset usage: -vpre -vpre
[libx264 # 01383460] speed presets are listed in x264 --help
[libx264 # 01383460] profile is optional; x264 defaults to high
Cannot open video codec, -542398533
This is the code that I'm working with:
// Video encoding sample
AVCodec *codec = NULL;
AVCodecContext *codecCtx= NULL;
AVFormatContext *pFormatCtx = NULL;
AVOutputFormat *pOutFormat = NULL;
AVStream * pVideoStream = NULL;;
AVFrame *picture = NULL;;
int i, x, y, ret;
printf("Video encoding\n");
// Register all formats and codecs
av_register_all();
// guess format from file extension
pOutFormat = av_guess_format("h264", NULL, NULL);
if (NULL==pOutFormat){
cerr << "Could not guess output format" << endl;
return -1;
}
// allocate context
pFormatCtx = avformat_alloc_context();
pFormatCtx->oformat = pOutFormat;
memcpy(pFormatCtx->filename,filename,
min(strlen(filename), sizeof(pFormatCtx->filename)));
// Add stream to pFormatCtx
pVideoStream = avformat_new_stream(pFormatCtx, 0);
if (!pVideoStream)
{
printf("Cannot add new video stream\n");
return -1;
}
// Set stream's codec context
codecCtx = pVideoStream->codec;
codecCtx->codec_id = (AVCodecID)pOutFormat->video_codec;
codecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
codecCtx->frame_number = 0;
// Put sample parameters.
codecCtx->bit_rate = 2000000;
// Resolution must be a multiple of two.
codecCtx->width = 320;
codecCtx->height = 240;
codecCtx->time_base.den = 10;
codecCtx->time_base.num = 1;
pVideoStream->time_base.den = 10;
pVideoStream->time_base.num = 1;
codecCtx->gop_size = 12; // emit one intra frame every twelve frames at most
codecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
if (codecCtx->codec_id == AV_CODEC_ID_H264)
{
// Just for testing, we also add B frames
codecCtx->mb_decision = 2;
}
// Some formats want stream headers to be separate.
if(pFormatCtx->oformat->flags & AVFMT_GLOBALHEADER)
{
codecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
if(codecCtx->codec_id == AV_CODEC_ID_H264)
av_opt_set(codecCtx->priv_data, "preset", "slow", 0);
// Open the codec.
codec = avcodec_find_encoder(codecCtx->codec_id);
if (codec == NULL) {
fprintf(stderr, "Codec not found\n");
return -1;
}
ret = avcodec_open2(codecCtx, codec, NULL); // returns -542398533 here
if (ret < 0)
{
printf("Cannot open video codec, %d\n",ret);
return -1;
}
Your problem is this line:
codecCtx = pVideoStream->codec;
This AVCodecContext was allocated using global defaults, which x264 rejects because they are not optimal. Instead, use avcodec_alloc_context3 to allocate it, which will set x264-specific defaults. At the end of your encoding, don't forget to avcodec_free_context the returned pointer.
you should pass codec param to avformat_new_stream
codec = avcodec_find_encoder(codecCtx->codec_id);
pVideoStream = avformat_new_stream(pFormatCtx, codec);