LINUX.ORG.RU

FFmpeg libav сыпется изображение на h264

 ,


0

1

Приветствую

Продолжаю мучать перекодировку из mjpeg в libx264 с отдачей в rtsp

Запускаю ffmpeg с параметрами и смотрю на другой локальной машине в ffplay (или через rtsp-simple-server в vlc)

# ./ffmpeg -f v4l2 -input_format mjpeg -video_size 640x480 -i /dev/video0 -c:v libx264 -pix_fmt yuv422p -preset ultrafast -r 30 -b:v 500k -minrate:v 300k -maxrate:v 500k -bufsize 1000k -f rtsp -rtsp_transport udp rtsp://192.168.36.212:554/cam
ffmpeg version N-107213-gfed07ef Copyright (c) 2000-2022 the FFmpeg developers
  built with gcc 5.4.0 (Ubuntu/Linaro 5.4.0-6ubuntu1~16.04.12) 20160609
  configuration: --prefix=/usr --enable-nonfree --enable-gpl --enable-version3 --enable-libx264 --enable-libv4l2 --disable-libxcb --disable-vaapi --disable-bzlib --disable-zlib --disable-postproc --disable-xlib
  libavutil      57. 27.100 / 57. 27.100
  libavcodec     59. 33.100 / 59. 33.100
  libavformat    59. 25.100 / 59. 25.100
  libavdevice    59.  6.100 / 59.  6.100
  libavfilter     8. 41.100 /  8. 41.100
  libswscale      6.  6.100 /  6.  6.100
  libswresample   4.  6.100 /  4.  6.100
Input #0, video4linux2,v4l2, from '/dev/video0':
  Duration: N/A, start: 260677.910302, bitrate: N/A
  Stream #0:0: Video: mjpeg (Baseline), yuvj422p(pc, bt470bg/unknown/unknown), 640x480, 30 fps, 30 tbr, 1000k tbn
Stream mapping:
  Stream #0:0 -> #0:0 (mjpeg (native) -> h264 (libx264))
Press [q] to stop, [?] for help
[swscaler @ 0x14b65c0] [swscaler @ 0x14bfb20] deprecated pixel format used, make sure you did set range correctly
................
[swscaler @ 0x14b65c0] [swscaler @ 0x1536f00] deprecated pixel format used, make sure you did set range correctly
[libx264 @ 0x14a0b40] using cpu capabilities: ARMv6 NEON
[libx264 @ 0x14a0b40] profile High 4:2:2, level 3.0, 4:2:2 8-bit
[libx264 @ 0x14a0b40] 264 - core 148 r2643 5c65704 - H.264/MPEG-4 AVC codec - Copyleft 2003-2015 - http://www.videolan.org/x264.html - options: cabac=0 ref=1 deblock=0:0:0 analyse=0:0 me=dia subme=0 psy=1 psy_rd=1.00:0.00 mixed_ref=0 me_range=16 chroma_me=1 trellis=0 8x8dct=0 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=0 threads=6 lookahead_threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=0 weightp=0 keyint=250 keyint_min=25 scenecut=0 intra_refresh=0 rc_lookahead=0 rc=cbr mbtree=0 bitrate=500 ratetol=1.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 vbv_maxrate=500 vbv_bufsize=1000 nal_hrd=none filler=0 ip_ratio=1.40 aq=0
Output #0, rtsp, to 'rtsp://192.168.36.212:554/cam':
  Metadata:
    encoder         : Lavf59.25.100
  Stream #0:0: Video: h264, yuv422p(tv, bt470bg/unknown/unknown, progressive), 640x480, q=2-31, 500 kb/s, 30 fps, 90k tbn
    Metadata:
      encoder         : Lavc59.33.100 libx264
    Side data:
      cpb: bitrate max/min/avg: 500000/0/500000 buffer size: 1000000 vbv_delay: N/A
frame=  964 fps= 29 q=26.0 size=N/A time=00:00:31.86 bitrate=N/A dup=227 drop=0 speed=0.957x

Выхлоп ffplay

Input #0, rtsp, from 'rtsp://192.168.36.212:554/cam':    0B f=0/0   
  Metadata:
    title           : No Name
  Duration: N/A, start: 0.130000, bitrate: N/A
    Stream #0:0: Video: h264 (High 4:2:2), yuv422p(tv, bt470bg/unknown/unknown), 640x480, 30 fps, 30 tbr, 90k tbn, 60 tbc
 117.44 M-V: -0.030 fd=   5 aq=    0KB vq=   11KB sq=    0B f=1/1

ВСЕ ИДЕАЛЬНО!!! сравнительно конечно

запускаю свой говнокод, дампы

Input #0, video4linux2,v4l2, from '/dev/video0':
  Duration: N/A, start: 260917.808496, bitrate: N/A
  Stream #0:0: Video: mjpeg (Baseline), yuvj422p(pc, bt470bg/unknown/unknown), 640x480, 30 fps, 30 tbr, 1000k tbn
[libx264 @ 0x14e82c0] using cpu capabilities: ARMv6 NEON
[libx264 @ 0x14e82c0] profile High 4:2:2, level 3.0, 4:2:2 8-bit
[libx264 @ 0x14e82c0] 264 - core 148 r2643 5c65704 - H.264/MPEG-4 AVC codec - Copyleft 2003-2015 - http://www.videolan.org/x264.html - options: cabac=0 ref=1 deblock=0:0:0 analyse=0:0 me=dia subme=0 psy=1 psy_rd=1.00:0.00 mixed_ref=0 me_range=16 chroma_me=1 trellis=0 8x8dct=0 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=0 threads=6 lookahead_threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=0 weightp=0 keyint=250 keyint_min=25 scenecut=0 intra_refresh=0 rc_lookahead=0 rc=cbr mbtree=0 bitrate=500 ratetol=1.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 vbv_maxrate=500 vbv_bufsize=1000 nal_hrd=none filler=0 ip_ratio=1.40 aq=0
Output #0, rtsp, to 'rtsp://192.168.36.212:554/cam':
  Stream #0:0: Video: h264, yuv422p, 640x480, q=2-31, 500 kb/s, 90k tbn

Выхлоп ffplay

Input #0, rtsp, from 'rtsp://192.168.36.212:554/cam':    0B f=0/0   
  Metadata:
    title           : No Name
  Duration: N/A, start: 0.406333, bitrate: N/A
    Stream #0:0: Video: h264 (High 4:2:2), yuv422p, 640x480, 30 fps, 30 tbr, 90k tbn, 60 tbc
   7.28 M-V:  7.655 fd= 147 aq=    0KB vq=    0KB sq=    0B f=727/727

И с середины изображения сыпется вниз и тормоза...

Подскажите, если есть телепаты куда смотреть, замучался уже гадать.

★★★

Ответ на: комментарий от wolverin

этот вопрос нашел как задать

pOutCdcCtx->colorspace = pInpCdcCtx->colorspace;//AVCOL_SPC_BT470BG

вроде чуть лучше стало, но все равно верх нормально, с середины периодически осыпается и тормозит

wolverin ★★★
() автор топика
Ответ на: комментарий от dumauz

да, сам ффмпег же тянет, а вообще это АРМв7, просто видимо нет аппаратной поддержки в ффмпеге, точнее в libx264

wolverin ★★★
() автор топика
Последнее исправление: wolverin (всего исправлений: 1)
Ответ на: комментарий от wolverin

сделал через ffprobe -show_frames rtsp://

Отдает ффмпег

[FRAME]
media_type=video
stream_index=0
key_frame=0
pkt_pts=1974000
pkt_pts_time=21.933333
pkt_dts=1974000
pkt_dts_time=21.933333
best_effort_timestamp=1974000
best_effort_timestamp_time=21.933333
pkt_duration=3000
pkt_duration_time=0.033333
pkt_pos=N/A
pkt_size=1145
width=640
height=480
pix_fmt=yuv422p
sample_aspect_ratio=N/A
pict_type=P
coded_picture_number=658
display_picture_number=0
interlaced_frame=0
top_field_first=0
repeat_pict=0
[/FRAME]

Из моего кода

[FRAME]
media_type=video
stream_index=0
key_frame=0
pkt_pts=0
pkt_pts_time=0.000000
pkt_dts=0
pkt_dts_time=0.000000
best_effort_timestamp=0
best_effort_timestamp_time=0.000000
pkt_duration=3000
pkt_duration_time=0.033333
pkt_pos=N/A
pkt_size=3130
width=640
height=480
pix_fmt=yuv422p
sample_aspect_ratio=N/A
pict_type=P
coded_picture_number=1020
display_picture_number=0
interlaced_frame=0
top_field_first=0
repeat_pict=0
[/FRAME]

wolverin ★★★
() автор топика
Ответ на: комментарий от wolverin

что конечно больше напрягает, что VLC показывает, что кадры теряются не мало так (

при этом на ффмпег потоке потерей почти нет

wolverin ★★★
() автор топика
Последнее исправление: wolverin (всего исправлений: 2)
Ответ на: комментарий от wolverin

пробую это решение

https://stackoverflow.com/questions/29075467/set-rtsp-udp-buffer-size-in-ffmpeg-libav

вроде чем больше buffer_size тем стабильней становится… а сколько достаточно интересно!?

однако для ффмпега /proc/sys/net/core/rmem_max

мне править почти не пришлось, в чем может быть причина!?

wolverin ★★★
() автор топика
Последнее исправление: wolverin (всего исправлений: 1)
Ответ на: комментарий от wolverin

вопщим увеличение buffer_size осыпание видео с середины решает, однако тормоза воспроизведения так и остались, куда деваются отправленные пакеты не понимаю!? по времени нормально получается должно аж 30 фпс давать, по крайне мере ффплей пишет 22-25 tbr и 30 fps при просмотре

единственно, что из моего кода статистику пишет такую

Input #0, rtsp, from 'rtsp://192.168.36.212:554/cam':    0B f=0/0   
  Metadata:
    title           : No Name
  Duration: N/A, start: 35882.392967, bitrate: N/A
    Stream #0:0: Video: h264 (High 4:2:2), yuv422p(tv, bt470bg/unknown/unknown), 640x480, 30 fps, 22.50 tbr, 90k tbn, 60 tbc
35895.63 M-V:  0.042 fd=   5 aq=    0KB vq=  815KB sq=    0B f=1/1   
где значение перед M-V постоянно растет не с нуля, vq хоть и растет с нуля, но при отправке ффмпегом оно колеблется около 10КБ

wolverin ★★★
() автор топика
Ответ на: комментарий от wolverin

похоже все таки проблема с pts, dts и pkt_pos… которые я при перекодировании просто не задаю, но откуда их брать то и чему задавать - фрейму, пакету, стриму!?

wolverin ★★★
() автор топика
Ответ на: комментарий от hizel

Да смотрю, толку нет пока что (

Потерянные пакеты vlc пишет и отраженные подвисают, думал может во временных метках причина, точно не проблема производительности это

wolverin ★★★
() автор топика
Ответ на: комментарий от hizel

вот тут выложил картинку какая хрень у меня происходит

https://stackoverflow.com/questions/73290218/v4l2-to-rtsp-stream-using-ffmpeg-library-ver-5-1

пока понял, что AVFrame после ПЕРЕКОДИРОВАНИЯ из мжпег в х264 имеет pts, он же почему то равен key_frame (хотя я его вообще то обнуляю перед кодированием), dts 0

посчитал fps каждые 30 av_interleaved_write_frame пакетов и получилось что у меня фпс вапще 31-32 кадра в секунду, однако откель тормоза то!?

щас погляжу что там с AVPacket

wolverin ★★★
() автор топика
Ответ на: комментарий от wolverin

какие-то метания и вскрики, попробуйте системнее, выведите себе pts\dts на входе, после декодера и после энкодера

pts, он же почему то равен key_frame

key_frame=0,1 ; как он может быть равен pts или как вы это определили?

забавно, что на so вы таки занесли более менее кусок кода, сюда не потрудились

hizel ★★★★★
()
Ответ на: комментарий от hizel

Да он старый, вы его в другой теме уже видели )

Сейчас все значения пересмотрю и по вашей подсказке ранее ффпробе сравню что там получается

Просто до этого добивался совпадения дампов с ффмпегом и не помогло, получается не в настройках дело, единственно не пойму статистику ффмпег когда пишет он дропы и главное дубликаты откуда то считает

wolverin ★★★
() автор топика
Ответ на: комментарий от hizel

определял так, добавил код после avcodec_receive_frame(pInpCdcCtx, pInpFrm)

printf("Frame %c (%d) pts %ld dts %ld key_frame %d [coded_picture_number %d, display_picture_number %d]\n",
    av_get_picture_type_char(pInpFrm->pict_type),
    pInpCdcCtx->frame_number,
    pInpFrm->pts,
    pInpFrm->pkt_dts,
    pInpFrm->key_frame,
    pInpFrm->coded_picture_number,
    pInpFrm->display_picture_number);

потом засунул свою поделку в ртсп-симпл-сервер и смотрю выхлоп

Frame I (690) pts -615576705 dts 10 key_frame -615576705 [coded_picture_number 10, display_picture_number 1]
Frame I (691) pts -615532798 dts 10 key_frame -615532798 [coded_picture_number 10, display_picture_number 1]
Frame I (692) pts -615492793 dts 10 key_frame -615492793 [coded_picture_number 10, display_picture_number 1]
Frame I (693) pts -615452793 dts 10 key_frame -615452793 [coded_picture_number 10, display_picture_number 1]
Frame I (694) pts -615412793 dts 10 key_frame -615412793 [coded_picture_number 10, display_picture_number 1]
Frame I (695) pts -615372790 dts 10 key_frame -615372790 [coded_picture_number 10, display_picture_number 1]
Frame I (696) pts -615332791 dts 10 key_frame -615332791 [coded_picture_number 10, display_picture_number 1]

возможно конечно, что это связано с тем, что АВФрейм декодированный pInpFrm я отдаю сразу в кодировщик без sws_scale в другой фрейм и он там чего то внутри вертит с этим указателем

ПС тут еще наверное косяк с типом int64_t, проверяю

wolverin ★★★
() автор топика
Последнее исправление: wolverin (всего исправлений: 1)
Ответ на: комментарий от max_lapshin

да, но это требует выполнения sws_scale, а это ООООЧЕНЬ длительная операция, считаете что поэтому сыпется изображения в влц и ффплей?

просто у меня нет многих мест, в продакшене пока вообще одно, для теста еще 2 упомянутых выше, да и через сам ффмпег передается без проблем же.

wolverin ★★★
() автор топика
Последнее исправление: wolverin (всего исправлений: 2)
Ответ на: комментарий от wolverin

pts ты задаёшь исходя из соображений о том, когда кадр нужно показывать. dts скорее всего высчитает кодек, но libx264 заявляет, он может генерировать отрицательные dts, и это проблема того, кто кладёт поток в контейнер. Поле pkt_pos это смещение в файле, и при кодировании не актуально.

i-rinat ★★★★★
()
Ответ на: комментарий от wolverin

да, но это требует выполнения sws_scale, а это ООООЧЕНЬ длительная операция

Просто замени -pix_fmt yuv422p в команде на -pix_fmt yuv420p. Вряд ли ты заметишь нагрузку. Там нужно по четыре числа усреднить для каждой четвёрки пикселей. На небольших разрешениях это не будет заметно.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

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

я и в своем коде конечно же могу цветовое пространство менять, НО я так же вижу что на больших разрешения это вызывает проблему, сейчас не помню уже как было с одинаковым входящих и исходящим разрешением, но при уменьшении 1920х1080 до 640х480 время sws_scale занимал как декодирование и кодирование вместе взятое (наврал, раза в 4 медленнее, порядка 250 мс), мне то нужно добиться максимального фпс в узком канале

Дублирую свой код, буду премного благодарен если подскажите чего не хватает в моей процедуре транскодирования, что приводит к осыпанию и тормозам, повторяюсь вся процедура выполняется в среднем за 30мс для разрешения 640х480 без sws_scale

int WriteStream()
{
    int rt = 0;
    int64_t time_start = av_gettime_relative();

    if ((rt = avcodec_send_packet(pInpCdcCtx, pInpPkt)) < 0)
        goto ERROR;

    do {
        rt = avcodec_receive_frame(pInpCdcCtx, pInpFrm);
        if (rt == AVERROR_EOF || rt == AVERROR(EAGAIN))
            break;
        else if (rt < 0)
            goto ERROR_FRM;

int64_t time_dec = av_gettime_relative();

        if (pSwsCtx) /* it is NOT USED now because it is very slow, WHY???  and pOutFrm = pInpFrm */
        {
            pOutFrm->pts = pInpFrm->pts;

            sws_scale(pSwsCtx,
                    (const uint8_t * const *) pInpFrm->data, pInpFrm->linesize, 0, pInpCdcCtx->height,
                    pOutFrm->data, pOutFrm->linesize);
        }
        else
        {
            pInpFrm->key_frame = 0;
            pInpFrm->pict_type = AV_PICTURE_TYPE_NONE;
        }

int64_t time_sws = av_gettime_relative();


        if ((rt = avcodec_send_frame(pOutCdcCtx, pOutFrm)) < 0)
            goto ERROR_FRM;

        do {
            rt = avcodec_receive_packet(pOutCdcCtx, pOutPkt);
            if (rt == AVERROR_EOF || rt == AVERROR(EAGAIN))
                break;
            else if (rt < 0)
                goto ERROR_PKT;

int64_t time_enc = av_gettime_relative();

            fprintf(stdout, "Packet size inp: %d out: %d bytes Time decode: %.2f scale: %.2f encode: %.2f transcode: %.2f ms ...\r",
                            pInpPkt->size, pOutPkt->size, (time_dec - time_start)/1000.0, (time_sws - time_dec)/1000.0, (time_enc - time_sws)/1000.0, (av_gettime_relative() - time_start)/1000.0);

            rt = av_interleaved_write_frame(pOutFmtCtx, pOutPkt);

            av_packet_unref(pOutPkt);
        } while (rt >= 0);

        av_frame_unref(pInpFrm);
    } while (rt >= 0);
    return 0;

ERROR_PKT:
    av_packet_unref(pOutPkt);
ERROR_FRM:
    av_frame_unref(pInpFrm);
ERROR:
    PrintError("Error transcoding", rt);
    return rt;
}

wolverin ★★★
() автор топика
Последнее исправление: wolverin (всего исправлений: 1)
Ответ на: комментарий от i-rinat

Не уверен, лишний раз добавил чтобы память не утекала, убрал - разницы нет, влц все равно пишет много потерянных пакетов, как он их теряет не пойму, почему ффмпеговские пакеты с той же скоростью не теряются!?

wolverin ★★★
() автор топика
Ответ на: комментарий от wolverin

Если я правильно прочитал описания функций, вызывая лишний раз unref ты лишний раз освобождаешь-выделяешь память. Не фатально, просто лишняя работа. Если ты и так на пределе железа работаешь, небольшие дополнительные задержки могут как раз и дать потерю кадров.

В коде я не вижу проблем, разве что ты не заморачиваешься с пересчётом времени в pOutFrm->pts = pInpFrm->pts. Если «базы времени» у входного и выходного потоков одинаковые, то всё нормально, но если нет, у тебя проблемы с метками времени. Я бы смотрел в сторону меток времени. Чтобы не было отрицательных, чтобы выраженные в секундах метки времени почти что совпадали, и так далее.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

спасибо за помощь, действительно на пределе железа задача выполняется, однако как написал ранее - убрал, разницы нет ни во времени выполнения, ни в тормозах видео если использовать мой код, а не ффмпег

pOutFrm->pts = pInpFrm->pts

это же просто мое тупое предположение, что время смашстабированного фрейма должно быть такое же (что естественно не верно), но я пока еще и не использую этот участок кода, т.к. свс_скале ЖУТКО медленная и просто декодированный фрейм отправляю кодеру.

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

Полагаю там не хватает такой штуки как av_packet_rescale_ts перед записью av_interleaved_write_frame, в transcoding.c 3 раза, а в muxing.c 1 раз она встречается и я добавил такую строку

av_packet_rescale_ts(pOutPkt, pOutCdcCtx->time_base, pOutFmtCtx->streams[0]->time_base);

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

https://htrd.su/blog/2012/11/23/ffmpeg_nemnogo_pro_time-base/

wolverin ★★★
() автор топика
Последнее исправление: wolverin (всего исправлений: 1)
Ответ на: комментарий от wolverin

Не надо просто вслепую вставлять вызовы функций. Слишком уж маловероятно, что так ты случайно наткнёшься на рабочую конфигурацию. Посмотри вместо этого пример из /doc/examples/transcoding.c, возмьми как можно больше из него, а потом, если заработает нормально, сможешь мелкими шагами менять в направлении, которое нужно тебе.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

перевернул я параметры в вызове методом «научного тыка»

av_packet_rescale_ts(pOutPkt, pOutFmtCtx->streams[0]->time_base, pOutCdcCtx->time_base);

теперь ffplay показывает ИДЕАЛЬНО, а в влц тормоза приобрели другой вид - сначала копится какой то буфер, потом вываливается вместе с потерянными пакетами… чего то еще не хватает

wolverin ★★★
() автор топика
Последнее исправление: wolverin (всего исправлений: 1)
Ответ на: комментарий от wolverin

продолжаем ломать голову себе и другим

итак вот так вижу пакет от ффмпега

ffprobe -show_packets rtsp://192.168.36.53:554/cam

Input #0, rtsp, from 'rtsp://192.168.36.53:554/cam':
  Metadata:
    title           : Stream
  Duration: N/A, start: 0.033333, bitrate: N/A
  Stream #0:0: Video: h264 (High 4:2:2), yuv422p(tv, bt470bg/unknown/unknown, progressive), 640x480, 30 fps, 30 tbr, 90k tbn
[PACKET]
codec_type=video
stream_index=0
pts=N/A
pts_time=N/A
dts=N/A
dts_time=N/A
duration=3000
duration_time=0.033333
size=10652
pos=N/A
flags=K_
[/PACKET]
[PACKET]
codec_type=video
stream_index=0
pts=3000
pts_time=0.033333
dts=3000
dts_time=0.033333
duration=3000
duration_time=0.033333
size=361
pos=N/A
flags=__
[/PACKET]
[PACKET]
codec_type=video
stream_index=0
pts=6000
pts_time=0.066667
dts=6000
dts_time=0.066667
duration=3000
duration_time=0.033333
size=3822
pos=N/A
flags=__
[/PACKET]
[PACKET]
codec_type=video
stream_index=0
pts=9000
pts_time=0.100000
dts=9000
dts_time=0.100000
duration=3000
duration_time=0.033333
size=2487
pos=N/A
flags=__
[/PACKET]
[PACKET]
codec_type=video
stream_index=0
pts=12000
pts_time=0.133333
dts=12000
dts_time=0.133333
duration=3000
duration_time=0.033333
size=2789
pos=N/A
flags=__
[/PACKET]

каждый pts/dts четко увеличивается на duration, неизвестные pts_time/dts_time растут на duration_time

теперь то что получаю я, при добавлении

av_packet_rescale_ts(pOutPkt, pOutFmtCtx->streams[0]->time_base, pOutCdcCtx->time_base);

Input #0, rtsp, from 'rtsp://192.168.36.53:554/cam':
  Metadata:
    title           : Stream
  Duration: N/A, start: 0.000122, bitrate: N/A
  Stream #0:0: Video: h264 (High 4:2:2), yuv422p(tv, bt470bg/unknown/unknown, progressive), 640x480, 30 fps, 30 tbr, 90k tbn
[PACKET]
codec_type=video
stream_index=0
pts=N/A
pts_time=N/A
dts=N/A
dts_time=N/A
duration=3000
duration_time=0.033333
size=12365
pos=N/A
flags=K_
[/PACKET]
[PACKET]
codec_type=video
stream_index=0
pts=11
pts_time=0.000122
dts=11
dts_time=0.000122
duration=3000
duration_time=0.033333
size=50
pos=N/A
flags=__
[/PACKET]
[PACKET]
codec_type=video
stream_index=0
pts=24
pts_time=0.000267
dts=24
dts_time=0.000267
duration=3000
duration_time=0.033333
size=95
pos=N/A
flags=__
[/PACKET]
[PACKET]
codec_type=video
stream_index=0
pts=35
pts_time=0.000389
dts=35
dts_time=0.000389
duration=3000
duration_time=0.033333
size=222
pos=N/A
flags=__
[/PACKET]
[PACKET]
codec_type=video
stream_index=0
pts=46
pts_time=0.000511
dts=46
dts_time=0.000511
duration=3000
duration_time=0.033333
size=1060
pos=N/A
flags=__
[/PACKET]
[PACKET]
codec_type=video
stream_index=0
pts=56
pts_time=0.000622
dts=56
dts_time=0.000622
duration=3000
duration_time=0.033333
size=2025
pos=N/A
flags=__
[/PACKET]
[PACKET]
codec_type=video
stream_index=0
pts=70
pts_time=0.000778
dts=70
dts_time=0.000778
duration=3000
duration_time=0.033333
size=1075
pos=N/A
flags=__
[/PACKET]

какая то ахинея очевидна... как же все таки правильно задать эти времена...

wolverin ★★★
() автор топика
Ответ на: комментарий от wolverin

что там 3 раза av_packet_rescale_ts в процессе перекодирования

Там или один раз, если просто меняется контейнер, без перекодирования собственно видео, или два раза, «входной поток → кодировщик» и «кодировщик → выходной контейнер».

и явно pts не задается

Эм. Видео состоит из кадров, которые нужно показать в определённой последовательности в определённые моменты времени. Поэтому каждому кадру приписывается время, когда его нужно показывать, pts. Во время перекодирования одного видео в другое кадры берутся из исходного видеопотока, в котором уже размечены pts, ведь это видео, то есть набор кадров с указанием моментов времени, когда их нужно показывать.

Если у тебя видео генерируется из картинок, считанных с веб-камеры, ты сам решаешь, когда какой кадр нужно показывать, поэтому если вдруг код в ffmpeg, который захватывает кадры, не проставляет pts, ты сам их должен проставить.

i-rinat ★★★★★
()
Ответ на: комментарий от wolverin

неизвестные pts_time/dts_time

pts_time — момент времени, когда нужно показать кадр, в секундах.
dts_time — момент времени, когда нужно декодировать кадр, в секундах.
pts_time и dts_time не хранятся в видеопотоке или контейнере. Эти числа ffprobe вычисляет и показывает исключительно для удобства восприятия человеком.

pts и dts — целые числа, они задают время в «тиках». Длительность тика задаётся в метаданных контейнера и метаданных видеопотока. Длительность тика задаётся рациональной дробью. Тут нужно заметить, что в выхлопе ffprobe (без -show_frames) показывается не длительность тика, а сколько тиков происходит в секунду. Но длительность в частоту легко преобразуется, так что это не проблема. Это ведь рациональные дроби.

Это всё нужно, чтобы указывать время точно. Например, для видео с 30 кадрами в секунду не получится точно указать в виде числа с плавающей точкой время второго кадра, одну треть секунды, потому что это число не представимо точно в ieee754. Но можно задать длительность тика в 1/30 секунды и указать, что второй кадр показывается в pts=1.

при добавлении av_packet_rescale_ts

В задаче перекодирования у входного контейнера, у видео в этом контейнере, у результата кодирования и у выходного контейнера могут быть четыре разных длительности тиков. Функция av_packet_rescale_ts используется, чтобы преобразовать целые pts/dts между этими разными длительностями тиков, чтобы как можно точнее сохранить метки времени, выраженные в секундах.

Если ты просто наобум вставляешь вызовы функций, шанс на то, что случайно получится нужное, очень мал. Попробуй всё-таки проследить за длительностями тиков.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

СПАСИБО! За ликбез, про тики я прочитал ранее, но не подскажите что тоже никак не осилю как и откуда брать pts и dts и чему присвоить - делаю вывод этих значений входного пакета, декорированного фрейма и выходного кодированного пакета, если метки не менять они все одинаковые и равномерно растут не с нуля (видимо от системных часов) - почему метки выходного пакета отличаются от того что показывает ффпробе??? Или как увидеть то что я присваиваю контейнеру на принимающей-просматриваюшей стороне?

wolverin ★★★
() автор топика
Ответ на: комментарий от i-rinat

Нет конечно не наобум сама последовательность, делаю как в примере и в других примерах, ав_пакет_рескале_тс после чтения кодированного пакета и перед записью интерлив, но видео все равно не воспроизводится без тормозов, наобум поэтому временные базы подставляю

wolverin ★★★
() автор топика
Последнее исправление: wolverin (всего исправлений: 1)
Ответ на: комментарий от wolverin

вот как в примерах всяких разных

av_read_frame(pInpFmtCtx, pInpPkt);

av_packet_rescale_ts(pInpPkt, pInpCdcCtx->time_base, pOutCdcCtx->time_base);

теперь перед интерливом

av_packet_rescale_ts(pOutPkt, pOutCdcCtx->time_base, pOutFmtCtx->streams[0]->time_base);

av_write_frame(pOutFmtCtx, pOutPkt);

выхлоп

Input #0, rtsp, from 'rtsp://192.168.36.53:554/cam':
  Metadata:
    title           : Stream
  Duration: N/A, start: 0.000000, bitrate: N/A
  Stream #0:0: Video: h264 (High 4:2:2), yuv422p(tv, bt470bg/unknown/unknown, progressive), 640x480, 30 fps, 30 tbr, 90k tbn
[PACKET]
codec_type=video
stream_index=0
pts=N/A
pts_time=N/A
dts=N/A
dts_time=N/A
duration=3000
duration_time=0.033333
size=10256
pos=N/A
flags=K_
[/PACKET]
[PACKET]
codec_type=video
stream_index=0
pts=0
pts_time=0.000000
dts=0
dts_time=0.000000
duration=3000
duration_time=0.033333
size=790
pos=N/A
flags=__
[/PACKET]
[PACKET]
codec_type=video
stream_index=0
pts=0
pts_time=0.000000
dts=0
dts_time=0.000000
duration=3000
duration_time=0.033333
size=1177
pos=N/A
flags=__
[/PACKET]
[PACKET]
codec_type=video
stream_index=0
pts=0
pts_time=0.000000
dts=0
dts_time=0.000000
duration=3000
duration_time=0.033333
size=2367
pos=N/A
flags=__
[/PACKET]

т.е. птс и дтс теперь везде нули

wolverin ★★★
() автор топика
Ответ на: комментарий от wolverin

к этому уже примеру склоняюсь с ручным вычислением меток

https://stackoverflow.com/questions/48440670/how-to-set-pts-and-dts-of-avpacket-from-rtp-timestamps-while-muxing-vp8-rtp-stre

потому что либо я чего то где то еще не задаю, либо все эти av_packet_rescale_ts и соответственно внутри нее av_rescale_q неверно считают птс/дтс, хотя дампы я вроде до последнего символа сверил по значениям tbc tbr tbn

wolverin ★★★
() автор топика
Последнее исправление: wolverin (всего исправлений: 2)
Ответ на: комментарий от wolverin

как и откуда брать pts и dts

Значения, взятые от системных часов вполне подойдут. Так как ты получаешь сырые кадры, которые друг от друга никак не зависят, то dts можно взять то же, что и pts. Мне кажется, что libx264 всё равно в итоге расставит dts так, как считает нужным.

i-rinat ★★★★★
()
Последнее исправление: i-rinat (всего исправлений: 1)
Ответ на: комментарий от i-rinat

посмотрел дневную картинку, тормоза из vlc ушли, ффпробе показывает такие же птс и дтс как от ффмпега, это наводит меня на мысль, что av_packet_rescale_ts и av_rescale_q и системные часы вообще не используются самим ффмпегом для проставления меток, просто из временных баз потока и контейнера считается продолжительность и либо добавляется к предыдущей временной метке, либо множится на номер кадра

единственно теперь беспокоит - получаю фпс порядка 35 кадров в секунду при записи интерлив, хотя должен отдавать 30, куда эти 5 вперед улетевших пакетов деваются, вроде бы ускорения видео нет, но это пока не точно, т.к. камера далеко от меня

и чтоб 2 раза не вставать подскажите - есть способы увеличить производительность sws_scale и декодирования mjpeg, с учетом отсутствия у меня аппаратного ускорения на платформе arm (nanopi)??? или только объединять все в указатель на структуры и декодить и рескалить в нескольких потоках (иба как понимаю декодер мжпег не умеет это делать в нескольких потоках)

wolverin ★★★
() автор топика
Последнее исправление: wolverin (всего исправлений: 1)
Ответ на: комментарий от wolverin

системные часы вообще не используются самим ффмпегом для проставления меток

Согласно моему опыту чтения исходников ffmpeg вольно обходится с длительностями кадров, но метки времени обсчитывает тщательно и по возможности аккуратно.

но это пока не точно, т.к. камера далеко от меня

Зачем усложнять себе отладку? Не проще иметь все компоненты системы под рукой, чтобы не гадать?

есть способы увеличить производительность sws_scale

У libswscale есть обобщённые коды преобразования между форматами и размерами и есть особые случаи, для которых есть оптимизированный код. Например, масштабирование BGRA в BGRA было быстрое, а RGBA в RGBA — медленное. Результаты одинаковые, потому что цвета всё равно должны обрабатываться раздельно. В libswscale могли бы добавить тривиальный патч, чтобы для RGBA тоже вызывать тот же оптимизированный код, но похоже, что им плевать, потому что все пользователи уже давно привыкли для масштабирования RGBA указывать формат BGRA. Не знаю, как там сейчас, я уже много лет туда не заглядывал.

У тебя нет масштабирования произвольных соотношений, только кратное, и только для U и V, где у U и V разрешение по вертикали уменьшается вдвое. Наверняка для этого есть оптимизированный код, который будет выполняться быстро. Но может так оказаться, что такой код есть для I422→YV12, а для I422→I420 нет, хотя разница там будет просто в порядке аргументов для выходного кадра. Тебе придётся либо проверить код libswscale, либо найти нужную комбинацию перебором.

декодирования mjpeg, с учетом отсутствия у меня аппаратного ускорения на платформе arm

Не думаю, что там что-то можно ускорить. Разве что сразу сырые кадры с веб-камеры получать?

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

ООО, спасибо за подсказку про комбинации, но я вот например пробую самим ффмпегом смасштабировать мжпег из 1920х1080 в х264 960х640 в надежде, что это операция минимально затратна для цпу и вижу 20(!!!) раз сообщение swscaler о том, что формат на камере yuvJ422p депрекатед, видимо ффмпег все же создаёт очередь потоков, выполняющих масштабирование!? В своем коде я вижу только один раз это сообщение, при этом армка у меня показывает в одном потоке 70мс на декодирование, 130 на масштабмрование и лишь до 30 на сжатие, т.е. до 200мс первых двух операций создают проблему.

ЗЫ. Да я просто в отпуске, а железки на работе лежат )

wolverin ★★★
() автор топика
Ответ на: комментарий от wolverin

Самое забавное хоть и создаётся как я предполагаю 20 потоков масштабирования и пишется в статистике аж 30 фпс начиная правда с 15, но судя по видео там от силы 10, при этом кучу дубликатов пишет и скорость около 800-900 не знаю что значит, обычно она меньше 1

wolverin ★★★
() автор топика