有没有更快的跳帧抓帧方式?

Is there a faster way to grab frames by skipping frames?

我正在循环 av_read_frameavcodec_decode_video2 以从 mp4 视频中读取像素数据。

int i = 0;
while (av_read_frame(pFormatCtx, &pkt)>=0) {
    AVPacket orig_pkt = pkt;
    do {
        int ret = 0;
        int decoded = pkt.size;
        got
        if (i%7==0) { // Only process 1/7th of frames
            ret = avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &pkt);
            if (got_frame) {
                // get pixel data
            } else {
                printf("Error: could not get frame %d", i );
            }
        }
        ret = decoded;
        pkt.data += ret;
        pkt.size -= ret;
    } while (pkt.size > 0);
    av_free_packet(&orig_pkt);
}

这是一个35FPS的视频,但我只需要读取大约5FPS的像素数据。

i%7==0 条件导致超过 1/7 的帧被丢弃。删除该行会导致所有帧的处理速度变慢,而不会丢失任何帧。

有没有一种只读取 1/7 帧的快速方法?

这取决于视频。大多数视频被压缩成 "Group of pictures" 其中第一张图片是关键帧,其余是预测帧。关键帧可以自己解码,但是预测帧只有在所有之前的预测帧直到并包括之前的关键帧都被解码的情况下才能被解码(它实际上比这更复杂一点,但现在已经足够好了)。如果你正在解码的视频都是关键帧(例如 MJPEG),是的,你可以跳过你想要的任何帧。如果不是,并且您跳过了一个帧,则必须跳过所有帧直到下一个关键帧。关键帧通常约为 2 到 10 秒(假设 30fps 视频为 60-300 帧)。但它可能或多或少。

您可以通过检查 AV_PKT_FLAG_KEY & pkt.flags

来检查帧是否为关键帧

你可以这样做:

if (AV_PKT_FLAG_KEY &pkt.flags) {
    ret = avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &pkt);
...
}

但是您无法决定解码哪些帧,视频文件本身可以。