Я работаю с ffmpeg 4.1 и показываю прямые трансляции с нескольких камер, h264 и h265.
Моя программа собирает пакеты одного кадра и затем вызывает функцию decodeVideo.На самом деле он отправляет все пакеты кадра сразу.
Программа работает хорошо, если нет пропущенных пакетов.Когда я удаляю пакет в случайных I-кадрах, потоки h264 и h265 работают должным образом (несколько секунд прыгает, но продолжает потоковую передачу).
Когда я удаляю пакет в случайном P-кадре из потоков h265, функция avcodec_send_packet выдает AVERROR_INVALIDDATAи потоки продолжаются.
Однако, когда я удаляю пакет в случайном P-кадре из потоков h264, функция avcodec_send_packet дает 0. Затем функция avcodec_receive_frame непрерывно дает AVERROR (EAGAIN) и блокирует потоки.
void decodeVideo(array<uint8_t>^ data, int length, AvFrame^ finishedFrame)
{
AVPacket* videoPacket = new AVPacket();
av_init_packet(videoPacket);
pin_ptr<unsigned char> dataPtr = &data[0];
videoPacket->data = dataPtr;
videoPacket->size = length;
int retVal = avcodec_send_packet((AVCodecContext*)context, videoPacket);
if(retVal < 0)
{
if (retVal == AVERROR_EOF)
Utility::Log->ErrorFormat("avcodec_send_packet() return value is AVERROR_EOF.");
else if( retVal == AVERROR_INVALIDDATA)
Utility::Log->ErrorFormat("avcodec_send_packet() INVALID DATA!");
else
Utility::Log->ErrorFormat("avcodec_send_packet() return value is negative:{0}",retVal);
}
else
{
int receive_frame = avcodec_receive_frame((AVCodecContext*)context, (AVFrame*)finishedFrame);
if (receive_frame == AVERROR(EAGAIN))
Utility::Log->ErrorFormat("avcodec_receive_frame() returns AVERROR(EAGAIN)");
else if(receive_frame == AVERROR_EOF)
Utility::Log->ErrorFormat("avcodec_receive_frame() returns AVERROR(AVERROR_EOF)");
else
Utility::Log->ErrorFormat("avcodec_receive_frame() return value is negative:{0}",receive_frame);
}
av_packet_unref(videoPacket);
delete videoPacket;
}
EDIT
Когда я добавляю avcodec_flush_buffers
, как показано, моя проблема временно решается.Однако через некоторое время он снова зависает.
if(receive_frame == AVERROR(EAGAIN))
{
Utility::Log->ErrorFormat("avcodec_receive_frame() returns AVERROR(EAGAIN)");
avcodec_flush_buffers((AVCodecContext*)context);
}
Протестировано с ffmpeg версии 4.1.1 с такими же результатами.
Найдите версию ffmpeg, такую как функция декодирования 2.5отличается, но нет проблем, когда я удаляю пакеты.Однако я тоже работаю с потоками h265.
EDIT2
AVCodecID id = AVCodecID::AV_CODEC_ID_H264;
AVCodec* dec = avcodec_find_decoder(id);
AVCodecContext* decContext = avcodec_alloc_context3(dec);
После этих строк мой код включал следующие строки. Когда я их удаляю, проблем теперь нет.
if(dec->capabilities & AV_CODEC_CAP_TRUNCATED)
decContext->flags |= AV_CODEC_FLAG_TRUNCATED;
decContext->flags2 |= AV_CODEC_FLAG2_CHUNKS;