Немонотонно увеличивающийся dts для мультиплексора в потоке

Я просто пытаюсь сохранить те же кадры на видео из буфера, где я правильно сохранил растровый кадр и отметку времени кадра.

writer1 = new VideoFileWriter();
this.writer1.Width = this.videoSourceEndo.VideoResolution.FrameSize.Width;
this.writer1.Height = this.videoSourceEndo.VideoResolution.FrameSize.Height;
this.writer1.VideoCodec = VideoCodec.H264;
this.writer1.BitRate = (this.videoSourceEndo.VideoResolution.FrameSize.Height * this.videoSourceEndo.VideoResolution.FrameSize.Width * 30);

this.writer1.VideoOptions["preset"] = "superfast";
this.writer1.VideoOptions["tune"] = "zerolatency";

writer1.Open("test_HDMI.mp4");

(...)

writer1.WriteVideoFrame(endoFrameBuffer[endoFrameBuffer.Tail],endoFrameBuffer.getframetime(endoFrameBuffer.Tail));

Но в Visual Studio (не на первом кадре) я получаю эту ошибку: Accord.Video.VideoException: 'Ошибка при записи видеокадра. Ошибка -22: Неверный аргумент. Дополнительные сведения см. в выводе консоли.'

И на консоли: Приложение предоставило неверный, немонотонно увеличивающийся dts для мультиплексора в потоке 0: 512 >= 512

Я не знаю причину этого, потому что при отладке все значения кажутся правильными. (Пожалуйста, дайте мне знать, если вам нужно больше кода)


person Eduardo Preto    schedule 06.03.2018    source источник
comment
Я предполагаю, что вы правильно установили кодек/поток time_base (чего я здесь не вижу). Итак, ваша проблема заключается здесь endoFrameBuffer.getframetime(endoFrameBuffer.Tail) давайте посмотрим код   -  person the kamilz    schedule 08.03.2018
comment
endoFrameBuffer — это просто RingBuffer с растровыми изображениями и правильным временным интервалом: public TimeSpan getframetime(int index) { return _timeBuffer[index]; }   -  person Eduardo Preto    schedule 08.03.2018
comment
чтобы установить значения, я просто добавляю новый элемент, например: endoFrameBuffer.Enqueue(eventArgs.Frame,DateTime.Now - _firstFrameTime.Value); при запуске события newframe. Тогда на другом потоке я просто записываю каждый кадр из RingBuffer.   -  person Eduardo Preto    schedule 08.03.2018
comment
Позвольте мне спросить вас прямо, что fps представляет собой этот видеопоток (потому что pts=512 для меня непривычен). Метод getFrameTime возвращает значение pts?   -  person the kamilz    schedule 08.03.2018
comment
видеопоток составляет около ок. 30 кадров в секунду. getFrameTime возвращает TimeSpan (разница во времени между кадром и первым полученным кадром)   -  person Eduardo Preto    schedule 08.03.2018
comment
Вот печать cmd: imgur.com/IcuSJX4   -  person Eduardo Preto    schedule 08.03.2018


Ответы (1)


Хорошо, я поставлю здесь. Во-первых, откуда VideoStream->time_base: 1/15360, это должно быть 1000/30000 для 30 кадров в секунду или 1001/30000 для 29,97 кадров в секунду.

Во-вторых, что-то не так с расчетом pts/dts и длительности кадра. Как видите, последние два значения pts/dts одинаковы.

Для продолжительности пакета (я предполагаю, что частота кадров постоянна, как обычно) используйте эти предварительно рассчитанные значения (или сверьтесь с вашими в качестве справки):

fps     duration (same unit as AVPacket::duration)
23.98   2086
24.00   2000
25.00   2000
29.97   2068
30.00   2000
50.00   1000
59.94   1016
60.00   1000

Что касается ручного вычисления pts/dts: это моя функция C++, которую я использую:

static void write_video_pts(EncoderContext *ectx, AVPacket *pkt)
{
    pkt->pts          = ectx->video_pts; /* this is to keep next pts value, same unit as AVPacket::pts */
    ectx->video_pts  += ectx->frame_duration; /* check above table for ectx->frame_duration value */
    pkt->dts          = pkt->pts;
    pkt->duration     = ectx->frame_duration; /* check above table for ectx->frame_duration value */
    pkt->stream_index = ectx->VideoStream->index; /* AVStream */
}

Это определенно работает при ручном кодировании из источника RAW, как у вас. Не для транскодирования, конечно.

Надеюсь, это поможет.

person the kamilz    schedule 08.03.2018
comment
Я не могу понять, почему это происходит. Используя платформу Accord, ссылка. Мне просто нужно передать эти значения, и они кажутся Правильно... - person Eduardo Preto; 08.03.2018