Есть ли более быстрый способ захвата кадров путем пропуска кадров? - PullRequest
0 голосов
/ 17 января 2020

Я зацикливаюсь на av_read_frame и avcodec_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 кадров?

1 Ответ

1 голос
/ 17 января 2020

Это зависит от видео. Большая часть видео сжимается в «группу изображений», где первое изображение является ключевым кадром, а остальные являются прогнозируемыми кадрами. Ключевой кадр может быть декодирован сам по себе, но предсказанный кадр может быть декодирован только в том случае, если были декодированы все предыдущие предсказанные кадры вплоть до предыдущего ключевого кадра включительно (на самом деле это немного сложнее, но пока достаточно хорошо). Если видео, которое вы декодируете, это все ключевые кадры (например, MJPEG), да, вы можете пропустить любые кадры, которые захотите. Если это не так, и вы пропускаете кадр, вы должны пропустить все кадры до следующего ключевого кадра. Ключевые кадры обычно занимают от 2 до 10 секунд (60–300 кадров при условии 30 кадров в секунду). Но это может быть более или менее.

Вы можете проверить, является ли кадр ключевым, проверив для AV_PKT_FLAG_KEY & pkt.flags

Вы можете сделать:

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

Но тогда вы не можете решить, что кадры, которые вы декодируете, сам видеофайл делает.

...