Проблема с декодированием Libav (ffmpeg) HW с кадрами в конце файла - отсутствует или повреждена - PullRequest
0 голосов
/ 25 марта 2020

Моя цель - использовать ускоренное декодирование HW (с использованием vdpau, h265 и Nvidia RTX) для получения количества кадров из видео. Все работает, если кадры не доходят до конца видео. Я получаю меньше кадров, чем пытаюсь декодировать, обычно последний, но один отсутствует (я знаю, странно, последний в порядке, но не получает все), и иногда соседние кадры повреждены. Я следовал документам относительно конца файла. Вот код:

//getting first packet
if (!packet.data)
  av_read_frame(formatContext, & packet);

AVFrame * frame = av_frame_alloc();
if (!frame)
  throw std::runtime_error("Cannot allocate packet/frame");

//now trying to get frames from the video
for (int i = 0; i < number; i++) {
  int err = 0;
  //feeding the codec
  while (err == 0) {
    if (packet.stream_index == videoStreamId)
      if ((err = avcodec_send_packet(codecContext, & packet)) != 0)
        break;

    av_packet_unref( & packet);
    err = av_read_frame(formatContext, & packet);
    //sending null packet to flush the buffers
    if (err == AVERROR_EOF) {
      packet.data = NULL;
      packet.size = 0;
    }
  }

  bool waitForFrame = true;
  while (waitForFrame) {
    int err = avcodec_receive_frame(codecContext, frame);
    if (err == AVERROR_EOF)
      waitForFrame = false;

    else if (err < 0)
      throw std::runtime_error("Cannot receive frame");

    if (frame -> format == pixFmt)
    //I get here only number-1 times

Обратите внимание, что проблема возникает только тогда, когда я запрашиваю такое же количество кадров, как и длина видео. Похоже, что ситуация с концом файла не обрабатывается должным образом. Кадры декодируются нормально, если я пытаюсь получить, например, кадры длины 1.

Я также попытался записать события, и все выглядит хорошо, только один кадр не существует. Это тот случай, когда декодируется видео длиной 64 кадра и запрашивается 64 кадра:

Send packet 0 == 0 
Read frame status: Success
Send packet 1 == 0 
Read frame status: Success
Send packet 2 == 0 
Read frame status: Success
Send packet 3 == 0 
Read frame status: Success
Send packet 4 !=0 
Send packet status: Resource temporarily unavailable
Processing frame:0
Send packet 4 !=0 
Send packet status: Resource temporarily unavailable
Processing frame:1
Send packet 4 == 0 
Read frame status: Success
Send packet 5 == 0 
Read frame status: Success
Send packet 6 !=0 
Send packet status: Resource temporarily unavailable
Processing frame:2
Send packet 6 !=0 
Send packet status: Resource temporarily unavailable
Processing frame:3

...
Processing frame:56
Send packet 60 !=0 
Send packet status: Resource temporarily unavailable
Processing frame:57
Send packet 60 == 0 
Read frame status: Success
Send packet 61 == 0 
Read frame status: Success
Send packet 62 !=0 
Send packet status: Resource temporarily unavailable
Processing frame:58
Send packet 62 !=0 
Send packet status: Resource temporarily unavailable
Processing frame:59
Send packet 62 == 0 
Read frame status: Success
Send packet 63 == 0 
Read frame status: End of file
Set null packet
Processing frame:60
Send packet 64 == 0 
Read frame status: End of file
Set null packet
Processing frame:61
Send packet 65 !=0 
Send packet status: End of file
Processing frame:62
Send packet 65 !=0 
Send packet status: End of file
End of file at receive frame
...