You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用FFmpeg的C++编码视频丢帧且无法在QuickTime播放求助

Troubleshooting Your FFmpeg C++ Video Encoding Issues

Hey there! Let’s tackle these two common FFmpeg encoding headaches you’re dealing with—lost frames and QuickTime compatibility. I’ve run into both of these myself, so let’s break down what’s going on and how to fix them.


1. Missing the Final Frame (10 Frames Encoded → 9 Output)

What’s Causing It

Most video encoders (especially those that use B-frames for compression) cache frames internally to optimize prediction. When you stop sending input frames, the encoder still has that last set of cached frames stuck in its pipeline—you never trigger it to flush them out. That’s why you’re short one frame.

How to Fix It

After sending all your actual video frames to the encoder, you need to send a null frame to signal "no more input," then keep receiving packets until the encoder runs dry. Here’s how to add that to your code:

// After you’ve sent all your source frames to avcodec_send_frame()
// Step 1: Signal the encoder to flush cached frames
if (avcodec_send_frame(codec_ctx, nullptr) < 0) {
    // Handle error (log it, clean up, etc.)
    return -1;
}

// Step 2: Receive and write all remaining packets
AVPacket pkt = {0};
av_init_packet(&pkt);
int ret;
while ((ret = avcodec_receive_packet(codec_ctx, &pkt)) == 0) {
    // Write the flushed packet to your output file
    if (av_interleaved_write_frame(fmt_ctx, &pkt) < 0) {
        // Handle write error
        av_packet_unref(&pkt);
        break;
    }
    av_packet_unref(&pkt);
}

// Ignore EAGAIN (encoder needs more input, which we don’t have) and EOF
if (ret != AVERROR_EOF && ret != AVERROR(EAGAIN)) {
    // Handle unexpected error
}

This ensures every frame you sent gets processed and written to the output.


2. Black Screen in QuickTime (Plays Fine in MPV/VLC)

QuickTime is notoriously picky about video format compliance—MPV and VLC are way more forgiving. The issue almost always boils down to one of these four common mistakes:

Fix 1: Enable Global Headers for MP4

QuickTime requires the codec’s global header to be stored at the start of the MP4 file. Without it, it can’t properly initialize the decoder.

Add this line before opening the encoder:

codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;

Then, when setting up your output stream, make sure to copy the codec parameters correctly (including the extradata from the encoder):

AVStream* out_stream = avformat_new_stream(fmt_ctx, nullptr);
if (!out_stream) { /* Handle error */ }

// Copy codec parameters from encoder context to output stream
if (avcodec_parameters_from_context(out_stream->codecpar, codec_ctx) < 0) {
    /* Handle error */
}

Fix 2: Use YUV420P Pixel Format

QuickTime only supports the YUV420P planar pixel format for H.264 video. If you’re feeding the encoder RGB, YUV444P, or any other format, it’ll render as black.

Use sws_scale to convert your input frames to YUV420P before sending them to the encoder. Here’s a quick snippet to set up the scaler:

struct SwsContext* sws_ctx = sws_getContext(
    input_width, input_height, input_pix_fmt,
    output_width, output_height, AV_PIX_FMT_YUV420P,
    SWS_BILINEAR, nullptr, nullptr, nullptr
);

// Convert your input frame to YUV420P
sws_scale(
    sws_ctx,
    input_frame->data, input_frame->linesize,
    0, input_height,
    output_frame->data, output_frame->linesize
);

Fix 3: Correct Timebase and PTS/DTS Values

QuickTime relies on accurate timestamps to sync and render frames. Incorrect PTS/DTS values will cause it to fail to display content.

  • Set the encoder’s timebase to match your frame rate (e.g., 30fps = 1/30):
    codec_ctx->time_base = av_make_q(1, 30); // Replace 30 with your frame rate
    
  • Calculate the PTS for each frame correctly (use av_rescale_q to convert to the encoder’s timebase):
    // frame_index starts at 0 for your first frame
    output_frame->pts = av_rescale_q(frame_index, av_make_q(1, 30), codec_ctx->time_base);
    

Fix 4: Ensure the First Frame Is a Keyframe

QuickTime needs the first frame to be an I-frame (keyframe) to start decoding. If your first frame is a P/B frame, it’ll show a black screen.

Force the first frame to be a keyframe:

if (frame_index == 0) {
    output_frame->key_frame = 1;
    output_frame->pict_type = AV_PICTURE_TYPE_I;
}

You can also set a GOP size to ensure regular keyframes (e.g., one keyframe every 30 frames):

codec_ctx->gop_size = 30;

Final Checks

After making these changes, recompile and test:

  • Verify the frame count again with ffprobe -show_frames -pretty $VIDEO | grep -F '[FRAME]' | wc -l
  • Test the output in QuickTime—if it still shows black, double-check your pixel format conversion and timestamp calculations (those are the most common culprits).

内容的提问来源于stack exchange,提问作者Oliver Dain

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:49:48