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
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