【发布时间】:2018-03-14 14:38:59
【问题描述】:
我尝试使用 ffmpeg 对图像进行编码(压缩)和解码(不压缩)。但是如果我想用 avcodec_receive_packet 取回发送的图像,我只会得到错误 AVERROR(EAGAIN)。
我改变什么都没关系...结果总是 AVERROR(EAGAIN)。只向编码器发送一帧可能是个问题吗?如果是,如何解决?
代码(仅显示相关内容):
avcodec_register_all();
/* ------ init codec ------------------*/
AVCodec *codec;
codec = avcodec_find_decoder(AV_CODEC_ID_H264);
if (!codec)
{
print("compressH264, could not find decoder:\"AV_CODEC_ID_H264\"!!!");
return false;
}
AVCodec *nVidiaCodec = avcodec_find_encoder_by_name("h264_nvenc");
if (!nVidiaCodec)
{
print("err");
}
/* ------ ------------ ------------------*/
/* ------ init context ------------------*/
AVCodecContext* av_codec_context_ = NULL;
av_codec_context_ = avcodec_alloc_context3(nVidiaCodec);
if (!av_codec_context_)
{
print("compressH264, avcodec_alloc_context3 failed!!!");
return false;
}
int w = imgSrc.width();
int h = imgSrc.height();
if ((w % 2) != 0)
{
++w;
}
if ((h % 2) != 0)
{
++h;
}
av_codec_context_->width = w;
av_codec_context_->height = h;
av_codec_context_->pix_fmt = AV_PIX_FMT_YUV420P;
av_codec_context_->gop_size = 1;
av_codec_context_->max_b_frames = 1;
av_codec_context_->bit_rate = 400000;
av_codec_context_->time_base.den = 1;
av_codec_context_->time_base.num = 1;
av_opt_set(av_codec_context_->priv_data, "preset", "slow", 0);
int ret = avcodec_open2(av_codec_context_, nVidiaCodec, NULL);
if (0 > ret)
{
print("compressH264, could not open codec context for decoder:\"AV_CODEC_ID_H264\"!!!");
return false;
}
AVFrame *picture = av_frame_alloc();
picture->format = AV_PIX_FMT_RGB24;
picture->width = w;
picture->height = h;
ret = avpicture_fill((AVPicture *)picture, imgSrc.bits(), AV_PIX_FMT_RGB24, w, h);
if (0 > ret)
{
print("compressH264, avpicture_fill - failed!!!");
return false;
}
AVFrame *tmp_picture = av_frame_alloc();
tmp_picture->format = AV_PIX_FMT_YUV420P;
tmp_picture->width = w;
tmp_picture->height = h;
ret = av_frame_get_buffer(tmp_picture, 32);
SwsContext *img_convert_ctx = sws_getContext(av_codec_context_->width, av_codec_context_->height, AV_PIX_FMT_RGB24, av_codec_context_->width, av_codec_context_->height, av_codec_context_->pix_fmt, SWS_BICUBIC, NULL, NULL, NULL);
ret = sws_scale(img_convert_ctx, picture->data, picture->linesize, 0, av_codec_context_->height, tmp_picture->data, tmp_picture->linesize);
int h264Size = avpicture_get_size(AV_PIX_FMT_YUV420P, w, h);
ret = avcodec_send_frame(av_codec_context_, tmp_picture);
if (0 > ret)
{
char err[AV_ERROR_MAX_STRING_SIZE];
av_make_error_string(err, AV_ERROR_MAX_STRING_SIZE, ret);
print("compressH264, avcodec_send_frame: %s", err);
}
AVPacket *pkt = av_packet_alloc();
while (ret >= 0)
{
ret = avcodec_receive_packet(av_codec_context_, pkt);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
{
break;
}
else if (ret < 0)
{
fprintf(stderr, "Error during encoding\n");
exit(1);
}
av_packet_unref(pkt);
}
print("success");
一切正常,直到: - avcodec_receive_packet ...我一直得到错误 AVERROR(EAGAIN)。
只要我有压缩图像,我就可以开始解码。
感谢你们的帮助。
编辑: 如果我现在执行以下代码,我会得到一个数据包并且 ret == 0,但我必须发送 46 次相同的图像......对我来说这没有任何意义。
do
{
ret = avcodec_receive_packet(av_codec_context_, &pkt);
if (ret == 0)
{
break;
}
else if ((ret < 0) && (ret != AVERROR(EAGAIN)))
{
coutF("error");
}
else if (ret == AVERROR(EAGAIN))
{
ret = avcodec_send_frame(av_codec_context_, tmp_picture);
if (0 > ret)
{
char err[AV_ERROR_MAX_STRING_SIZE];
av_make_error_string(err, AV_ERROR_MAX_STRING_SIZE, ret);
coutFRed("compressH264, avcodec_send_frame: %s", err);
}
coutF("cnt:%d", ++cnt);
}
} while (ret == 0);
编辑:
早上好,
更多投资后,我遇到了问题。由于 h264 的关键帧内容,我必须发送相同的帧很多时间。现在的问题是,是否可以从编码器中删除 h264 标准内容,只让 FFMPEG 转换一帧。
【问题讨论】: