Javacv: Failure to use avcodec_send_frame

Created on 26 Jun 2019  路  9Comments  路  Source: bytedeco/javacv

Hello,

My goal is to encode a sequence of raw frames into a h.264 stream.

I am using the avcodec_send_frame but it fails with the "Invalid argument" error message:

if ((avrc = avcodec.avcodec_send_frame(codecContext, frame)) < 0) {
  avutil.av_strerror(avrc, avErrorDescription, avErrorDescription.length);
  String error = new String(avErrorDescription); //TODO: remove, debug item
  LOGGER.error("Could not add frame to encoding pipeline, error code {}, exiting", avrc);
  return;
}

Before the avcodec_send_frame call I do (left out return codes verifications):

AVCodecContext codecContext = new avcodec.AVCodecContext(null);
avutil.AVFrame frame = new avutil.AVFrame(null);
avcodec.AVPacket avPacket = new avcodec.AVPacket(null);

avcodec.avcodec_register_all();
AVCodec h264Codec = avcodec.avcodec_find_decoder_by_name("h264");
codecContext = avcodec.avcodec_alloc_context3(h264Codec);
avPacket = avcodec.av_packet_alloc();
codecContext.bit_rate(1000000);
codecContext.width(704);
codecContext.height(480);
avutil.AVRational timeBase = new avutil.AVRational();
timeBase.num(1);
timeBase.den(25);
codecContext.time_base(timeBase);
avutil.AVRational frameRate = new avutil.AVRational();
frameRate.num(25);
frameRate.den(1);
codecContext.framerate(frameRate);
codecContext.gop_size(25);
codecContext.max_b_frames(10);
codecContext.pix_fmt(AV_PIX_FMT_YUV420P);
if (codecContext.codec_id() == AV_CODEC_ID_H264) {
  avutil.av_opt_set(codecContext, "preset", "slow", 0);
}
avutil.AVDictionary dictionary = null;
avcodec_open2(codecContext, h264Codec, dictionary);
frame = av_frame_alloc();
frame.format(codecContext.pix_fmt());
frame.width(codecContext.width());
frame.height(codecContext.height());
av_frame_get_buffer(frame, 0);
av_frame_make_writable(frame);
org.bytedeco.javacpp.BytePointer rawData = new org.bytedeco.javacpp.BytePointer(data.getData().getByteBuffer(0, data.getData().getSize())); //data is the raw frame to be encoded
frame.data(0, rawData);
frame.linesize(0, width);
av_image_fill_pointers(frame.data(), codecContext.pix_fmt(), codecContext.height(), rawData, frame.linesize());
avcodec.avcodec_send_frame(codecContext, frame); // Fails with rc = -22 (Invalid argument)

Is the sequence incorrect? What am I missing?

Thanks!

Raul

enhancement help wanted question

All 9 comments

BTW, some docs are available here: https://ffmpeg.org/documentation.html

Hello Saudet,

Thanks for the link, I have been reading ffmpeg and JavaCV documentation for the past days but was unable to understand what is wrong.

Also, I haven鈥檛 found a way to validate all the structures needed :/

The sequence I posted seems correct to you? Something must be amiss.

Thanks for the help,

Raul

BTW, is there anything missing from FFmpegFrameRecorder?

Hi again,

As far as I understand no, but I didn鈥檛 find FFmpegFrameRecorder using avcodec_send_frame. I鈥檒l have to recheck, I suppose.

Thanks!

Raul

Hello Saudet,

As far as I understand FFmpegFrameRecorder always uses a file as the output, what I am trying to implement is to get packets (encoded data) from YUV420P frames to send them through our infrastructure (our own video container).

Is there a way to do this using FFmpegFrameRecorder?

Thanks!

Raul

It also supports OutputStream for that.

Hi Saudet,

I need to add a header to the packets before sending the packets down the stream (using our own container), that is why I am trying to get an encoded packet from the raw image.

Thanks,

Raul

BTW, we eventually need to upgrade FFmpegFrameRecorder to use avcodec_send_frame(). Maybe if you try to do that, you'll figure out more easily what needs to be done for your case as well?

Hello Audet (sorry for misspelling your name before),

I will evaluate that as I get it to work on my side.

Thanks,

Raul

Was this page helpful?
0 / 5 - 0 ratings