You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

avcodec_receive_packet无输出求助:图片转视频编码器报错-53

Troubleshooting avcodec_receive_packet() Returning -53 (EAGAIN) in Image-to-Video Conversion

Hey there, let's break down why you're hitting that -53 (EAGAIN) error when trying to receive encoded packets after sending frames to your FFmpeg encoder. I’ve dealt with this exact scenario multiple times building similar converters, so here are the key fixes to check:

1. You Haven’t Flushed the Encoder with a NULL Frame

Most video encoders (especially those using B-frames) buffer input frames to perform temporal prediction. This means even after sending all your image frames, the encoder might still have pending frames in its buffer that haven’t been encoded.

To trigger the encoder to output these remaining frames, you need to send a NULL frame after your last image frame, then continue calling avcodec_receive_packet() until it returns AVERROR_EOF or another non-EAGAIN error. Here’s how to implement this:

// After sending all your image frames...
int ret = avcodec_send_frame(enc_ctx, NULL); // Signal end of input
if (ret < 0) {
    fprintf(stderr, "Error flushing encoder: %s\n", av_err2str(ret));
    return ret;
}

// Now receive all remaining packets
AVPacket pkt = {0};
av_packet_init(&pkt);
while (true) {
    ret = avcodec_receive_packet(enc_ctx, &pkt);
    if (ret == AVERROR(EAGAIN)) {
        continue; // Shouldn't happen after flushing, but handle just in case
    } else if (ret == AVERROR_EOF) {
        break; // No more packets to receive
    } else if (ret < 0) {
        fprintf(stderr, "Error receiving flushed packet: %s\n", av_err2str(ret));
        av_packet_unref(&pkt);
        return ret;
    }

    // Process the packet (write to output, etc.)
    av_packet_rescale_ts(&pkt, enc_ctx->time_base, fmt_ctx->streams[0]->time_base);
    av_interleaved_write_frame(fmt_ctx, &pkt);
    av_packet_unref(&pkt);
}

2. Your AVFrame Parameters Don’t Match the Encoder’s AVCodecContext

Even if you converted the UIImage to YUV, mismatched parameters can prevent the encoder from producing output. Double-check these critical values:

  • Width/Height: Must exactly match codec_ctx->width and codec_ctx->height (no rounding errors or mismatched aspect ratios).
  • Pixel Format: Ensure you’re using a format the encoder supports (most H.264/H.265 encoders require AV_PIX_FMT_YUV420P—not YUV444 or other variants unless explicitly configured).
  • Presentation Timestamp (PTS): Encoders rely on valid PTS values to order frames correctly. Don’t leave PTS as 0; calculate it based on your target frame rate:
    // Example: For 30 FPS, increment PTS by 1 per frame, scaled to encoder time base
    static int frame_index = 0;
    frame->pts = frame_index++;
    av_rescale_q(frame->pts, av_make_q(1, 30), codec_ctx->time_base);
    

3. You’re Not Checking avcodec_send_frame() Return Values

It’s easy to assume avcodec_send_frame() succeeds every time, but silent failures here mean the encoder never receives your frames. Always validate the return code:

int ret = avcodec_send_frame(enc_ctx, frame);
if (ret < 0) {
    fprintf(stderr, "Failed to send frame to encoder: %s\n", av_err2str(ret));
    // Handle error (e.g., check frame format, encoder state)
    av_frame_unref(frame);
    return ret;
}

4. Your Encoder Initialization Is Incomplete

Double-check that you’ve set all required parameters in AVCodecContext before calling avcodec_open2():

  • bit_rate: Set a valid bitrate (e.g., 5000000 for 5 Mbps).
  • framerate: Explicitly set with av_make_q(fps_num, fps_den) (e.g., av_make_q(30, 1) for 30 FPS).
  • gop_size: Keyframe interval (e.g., 30 for a keyframe every second at 30 FPS).
  • For H.264/H.265: Set profile and level (e.g., FF_PROFILE_H264_BASELINE and FF_LEVEL_3_1 for broad compatibility).

Final Checklist

  1. Send a NULL frame after all input frames to flush the encoder.
  2. Verify AVFrame width, height, pixel format, and PTS match the encoder’s context.
  3. Always check return codes for avcodec_send_frame().
  4. Confirm all critical encoder parameters are set during initialization.

This should resolve the EAGAIN error in most cases—let me know if you hit any specific edge cases!

内容的提问来源于stack exchange,提问作者Eugene Alexeev

火山引擎 最新活动