Комментарии 20
А покажите, пожалуйста, пример кодирования H.265, и с какой скоростью оно это делает. Очень интересно.
И, кстати, надеюсь, что в конце сентября покажу уже сервис по распределенному кодированию видео, о концепции которого писал год назад. Сейчас, я считаю, самое время: людям нужно кодировать и в h.265, и в vp8, и в vp9, да еще и 4K-видео вот-вот пойдет потоком, а тот же ZenCoder — один из самых популярных сервисов по кодированию видео — возьмет с вас более $2 (!!!) за кодирование 3-минутного видеоролика в 4K в H.265. Мой же сервис будет не только позволять устанавливать все параметры кодирования для любого видеокодека, и использовать встроенные фильтры ffmpeg, но и будет заметно дешевле. Кодирование подобного видео обойдется примерно в 30 центов.
И, кстати, надеюсь, что в конце сентября покажу уже сервис по распределенному кодированию видео, о концепции которого писал год назад. Сейчас, я считаю, самое время: людям нужно кодировать и в h.265, и в vp8, и в vp9, да еще и 4K-видео вот-вот пойдет потоком, а тот же ZenCoder — один из самых популярных сервисов по кодированию видео — возьмет с вас более $2 (!!!) за кодирование 3-минутного видеоролика в 4K в H.265. Мой же сервис будет не только позволять устанавливать все параметры кодирования для любого видеокодека, и использовать встроенные фильтры ffmpeg, но и будет заметно дешевле. Кодирование подобного видео обойдется примерно в 30 центов.
-5
Хм, а может это не лучшая идея просто игнорировать возвращенное значение? Ведь функция все-таки зачем-то вызывается. Мне кажется, стоило проверить, что на самом деле не так…
Кроме того, я не вижу, как функция явным образом меняет eax, да и код функции приведен не весь (куда ведет je 0x7fffe288d568?)
Кроме того, я не вижу, как функция явным образом меняет eax, да и код функции приведен не весь (куда ведет je 0x7fffe288d568?)
0
Код не полностью приведён, это правда, меняется ниже. Совпадение размера окна ассемлерного кода в отладчике и инструкции ret вводит в заблуждение.
Правда в том, что eax меняется вообще в другом модуле.
www.dropbox.com/s/9by7mkr9lh4ajg7/%D0%A1%D0%BA%D1%80%D0%B8%D0%BD%D1%88%D0%BE%D1%82%202015-07-15%2001.39.13.png?dl=0
То есть, когда первая загадочная функция вызывается, она что-то делает, получает через dlsym указатель на другую библиотечную функцию и прыгает по нему. Не вызывает, а просто прыгает. Возврат на пропатченную мною инструкцию происходит уже из другого модуля. Мне кажется, в коде это выглядит как хвостовая оптимизация, когда функция всегда возвращает результат другой функции. Вызов опускается, заменяется на прыжок и управление возвращается уже вызвавшему первую функцию. Мне кажется, там ничего ценного, раз она безусловно возвращается и результат не проверяется.
Правда в том, что eax меняется вообще в другом модуле.
www.dropbox.com/s/9by7mkr9lh4ajg7/%D0%A1%D0%BA%D1%80%D0%B8%D0%BD%D1%88%D0%BE%D1%82%202015-07-15%2001.39.13.png?dl=0
То есть, когда первая загадочная функция вызывается, она что-то делает, получает через dlsym указатель на другую библиотечную функцию и прыгает по нему. Не вызывает, а просто прыгает. Возврат на пропатченную мною инструкцию происходит уже из другого модуля. Мне кажется, в коде это выглядит как хвостовая оптимизация, когда функция всегда возвращает результат другой функции. Вызов опускается, заменяется на прыжок и управление возвращается уже вызвавшему первую функцию. Мне кажется, там ничего ценного, раз она безусловно возвращается и результат не проверяется.
0
Из условий лицензии:
Licensee agrees not to disassemble, decompile or reverse engineer the Object Code
-9
UPD: Всё указанное выше справедливо и для новых драйверов 367.35. Смещение в файле получается
0x163bd
.+1
https://github.com/keylase/nvidia-patch
+1
а есть мысли насчет реализации дров и работы с 1070?
Там после 3-го потока падает:
pthread_mutex_unlock(0x3681dc0, 2, 0x10cbbc0, 1) = 0
pthread_mutex_lock(0x3681dc0, 1, 0, 1) = 0
posix_memalign(0x7ffebf75a6f0, 32, 488, 0) = 0
memset(0x3682700, '\0', 488) = 0x3682700
free(0) = dlopen(«libcuda.so.1», 1) = 0x3682910
dlsym(0x3682910, «cuInit») = 0x7fe3dd42b500
dlsym(0x3682910, «cuDeviceGetCount») = 0x7fe3dd42b9a0
dlsym(0x3682910, «cuDeviceGet») = 0x7fe3dd42b800
dlsym(0x3682910, «cuDeviceGetName») = 0x7fe3dd42bb20
dlsym(0x3682910, «cuDeviceComputeCapability») = 0x7fe3dd42c1c0
dlsym(0x3682910, «cuCtxCreate_v2») = 0x7fe3dd42cb80
dlsym(0x3682910, «cuCtxPopCurrent_v2») = 0x7fe3dd42d030
dlsym(0x3682910, «cuCtxDestroy_v2») = 0x7fe3dd42cd30
dlopen(«libnvidia-encode.so.1», 1) = 0x3683280
dlsym(0x3683280, «NvEncodeAPIGetMaxSupportedVersio»...) = 0x7fe3dcde2cb0
dlsym(0x3683280, «NvEncodeAPICreateInstance») = 0x7fe3dcde6410
posix_memalign(0x7ffebf75a5f8, 32, 32, 1) = 0
memcmp(0x3dc3440, 0x344779c, 16, 0) = 0
free(0x3dc3440) = posix_memalign(0x7ffebf759090, 32, 24, 0x3dc4f50) = 0
memset(0x3dc3440, '\0', 24) = 0x3dc3440
realloc(0, 16) = 0x3dc3b30
posix_memalign(0x7ffebf75a5e0, 32, 0xc800, 31) = 0
memset(0x3e9d1c0, '\0', 51200) = 0x3e9d1c0
posix_memalign(0x7ffebf75a5d8, 32, 256, 0x3ea99c0) = 0
posix_memalign(0x7ffebf75a5c0, 32, 40, 0x7fe3e791f760) = 0
memset(0x3dc35e0, '\0', 40) = 0x3dc35e0
posix_memalign(0x7ffebf75a5d8, 32, 256, 0x7fe3e791f760) = 0
posix_memalign(0x7ffebf75a5c0, 32, 40, 0x7fe3e791f760) = 0
memset(0x3dc37c0, '\0', 40) = 0x3dc37c0
posix_memalign(0x7ffebf75a5d8, 32, 256, 0x7fe3e791f760) = 0
posix_memalign(0x7ffebf75a5c0, 32, 40, 0x7fe3e791f760) = 0
memset(0x3dc39a0, '\0', 40) = 0x3dc39a0
pthread_mutex_lock(0x1c94ac0, 16, 0x130298a, 0x7ffebf759ed8) = 0
__vsnprintf_chk(0x7ffebf758e94, 1004, 1, -1) = 25
__vsnprintf_chk(0x7ffebf759694, 1004, 1, -1) = 49
__snprintf_chk(0x7ffebf759a80, 1024, 1, 1024) = 74
strcmp("[h264_nvenc @ 0x340bde0] CreateB"..., "\n") = 81
__strcpy_chk(0x1c946a0, 0x7ffebf759a80, 1024, 0) = 0x1c946a0
__fprintf_chk(0x7fe3e79201c0, 1, 0x132c96d, 1[h264_nvenc @ 0x340bde0] ) = 36
__fprintf_chk(0x7fe3e79201c0, 1, 0x132c96d, 1CreateBitstreamBuffer failed: out of memory (10)
) = 60
pthread_mutex_unlock(0x1c94ac0, 0, 0x7ffebf759694, 0x7fe3e764c72d) = 0
free(0x3dc3480) = free(0x3dc35e0) = free(0x3dc3840) = free(0x3dc39a0) = free(0x3dc3660) = free(0x3dc37c0) = — SIGSEGV (Segmentation fault) — +++ killed by SIGSEGV +++
Там после 3-го потока падает:
pthread_mutex_unlock(0x3681dc0, 2, 0x10cbbc0, 1) = 0
pthread_mutex_lock(0x3681dc0, 1, 0, 1) = 0
posix_memalign(0x7ffebf75a6f0, 32, 488, 0) = 0
memset(0x3682700, '\0', 488) = 0x3682700
free(0) = dlopen(«libcuda.so.1», 1) = 0x3682910
dlsym(0x3682910, «cuInit») = 0x7fe3dd42b500
dlsym(0x3682910, «cuDeviceGetCount») = 0x7fe3dd42b9a0
dlsym(0x3682910, «cuDeviceGet») = 0x7fe3dd42b800
dlsym(0x3682910, «cuDeviceGetName») = 0x7fe3dd42bb20
dlsym(0x3682910, «cuDeviceComputeCapability») = 0x7fe3dd42c1c0
dlsym(0x3682910, «cuCtxCreate_v2») = 0x7fe3dd42cb80
dlsym(0x3682910, «cuCtxPopCurrent_v2») = 0x7fe3dd42d030
dlsym(0x3682910, «cuCtxDestroy_v2») = 0x7fe3dd42cd30
dlopen(«libnvidia-encode.so.1», 1) = 0x3683280
dlsym(0x3683280, «NvEncodeAPIGetMaxSupportedVersio»...) = 0x7fe3dcde2cb0
dlsym(0x3683280, «NvEncodeAPICreateInstance») = 0x7fe3dcde6410
posix_memalign(0x7ffebf75a5f8, 32, 32, 1) = 0
memcmp(0x3dc3440, 0x344779c, 16, 0) = 0
free(0x3dc3440) = posix_memalign(0x7ffebf759090, 32, 24, 0x3dc4f50) = 0
memset(0x3dc3440, '\0', 24) = 0x3dc3440
realloc(0, 16) = 0x3dc3b30
posix_memalign(0x7ffebf75a5e0, 32, 0xc800, 31) = 0
memset(0x3e9d1c0, '\0', 51200) = 0x3e9d1c0
posix_memalign(0x7ffebf75a5d8, 32, 256, 0x3ea99c0) = 0
posix_memalign(0x7ffebf75a5c0, 32, 40, 0x7fe3e791f760) = 0
memset(0x3dc35e0, '\0', 40) = 0x3dc35e0
posix_memalign(0x7ffebf75a5d8, 32, 256, 0x7fe3e791f760) = 0
posix_memalign(0x7ffebf75a5c0, 32, 40, 0x7fe3e791f760) = 0
memset(0x3dc37c0, '\0', 40) = 0x3dc37c0
posix_memalign(0x7ffebf75a5d8, 32, 256, 0x7fe3e791f760) = 0
posix_memalign(0x7ffebf75a5c0, 32, 40, 0x7fe3e791f760) = 0
memset(0x3dc39a0, '\0', 40) = 0x3dc39a0
pthread_mutex_lock(0x1c94ac0, 16, 0x130298a, 0x7ffebf759ed8) = 0
__vsnprintf_chk(0x7ffebf758e94, 1004, 1, -1) = 25
__vsnprintf_chk(0x7ffebf759694, 1004, 1, -1) = 49
__snprintf_chk(0x7ffebf759a80, 1024, 1, 1024) = 74
strcmp("[h264_nvenc @ 0x340bde0] CreateB"..., "\n") = 81
__strcpy_chk(0x1c946a0, 0x7ffebf759a80, 1024, 0) = 0x1c946a0
__fprintf_chk(0x7fe3e79201c0, 1, 0x132c96d, 1[h264_nvenc @ 0x340bde0] ) = 36
__fprintf_chk(0x7fe3e79201c0, 1, 0x132c96d, 1CreateBitstreamBuffer failed: out of memory (10)
) = 60
pthread_mutex_unlock(0x1c94ac0, 0, 0x7ffebf759694, 0x7fe3e764c72d) = 0
free(0x3dc3480) = free(0x3dc35e0) = free(0x3dc3840) = free(0x3dc39a0) = free(0x3dc3660) = free(0x3dc37c0) = — SIGSEGV (Segmentation fault) — +++ killed by SIGSEGV +++
0
Здравствуйте! У меня нету оборудования — ответил в ЛС.
0
Причина оказалась в лимите числа буферов у видеокарты. Решили ограничить аппетиты ffmpeg по числу буферов вот таким патчем:
diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c
index a3a2ef5..1691d15 100644
--- a/libavcodec/nvenc.c
+++ b/libavcodec/nvenc.c
@@ -1157,7 +1157,7 @@ static av_cold int nvenc_setup_surfaces(AVCodecContext *avctx)
NvencContext *ctx = avctx->priv_data;
int i, res;
int num_mbs = ((avctx->width + 15) >> 4) * ((avctx->height + 15) >> 4);
- ctx->nb_surfaces = FFMAX((num_mbs >= 8160) ? 32 : 48,
+ ctx->nb_surfaces = FFMAX((num_mbs >= 8160) ? 8 : 12,
ctx->nb_surfaces);
ctx->async_depth = FFMIN(ctx->async_depth, ctx->nb_surfaces - 1);
diff --git a/libavcodec/nvenc_h264.c b/libavcodec/nvenc_h264.c
index 6914046b..7f050af 100644
--- a/libavcodec/nvenc_h264.c
+++ b/libavcodec/nvenc_h264.c
@@ -80,7 +80,7 @@ static const AVOption options[] = {
{ "vbr_2pass", "Multi-pass variable bitrate mode", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_2_PASS_VBR }, 0, 0, VE, "rc" },
{ "rc-lookahead", "Number of frames to look ahead for rate-control",
OFFSET(rc_lookahead), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, VE },
- { "surfaces", "Number of concurrent surfaces", OFFSET(nb_surfaces), AV_OPT_TYPE_INT, { .i64 = 32 }, 0, INT_MAX, VE },
+ { "surfaces", "Number of concurrent surfaces", OFFSET(nb_surfaces), AV_OPT_TYPE_INT, { .i64 = 8 }, 0, INT_MAX, VE },
{ "cbr", "Use cbr encoding mode", OFFSET(cbr), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
{ "2pass", "Use 2pass encoding mode", OFFSET(twopass), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, VE },
{ "gpu", "Selects which NVENC capable GPU to use. First GPU is 0, second is 1, and so on.",
+1
Патч уже не нужен, начиная с этого коммита в ffmpeg. Ожидаем релиза, содержащего этот коммит.
0
На GP107GL Quadro P400 запуск патча убрал ограничение на количество одновременно запущенных ffmpeg'ов (ловите pull request на github'e для поддержки текущей версии и CentOS).
Однако скорость работы линейно уменьшается с увеличением числа ffmpeg'ов, как будто обработку всё равно ведут только два процессора.
Так и должно быть?
Измерял так: gist.github.com/ilyaevseev/fc75df36fe27f1ab580e6afb285b9ab7#file-ffmpeg-nvenc-parbench-sh
Однако скорость работы линейно уменьшается с увеличением числа ffmpeg'ов, как будто обработку всё равно ведут только два процессора.
Так и должно быть?
Измерял так: gist.github.com/ilyaevseev/fc75df36fe27f1ab580e6afb285b9ab7#file-ffmpeg-nvenc-parbench-sh
0
Если декодирование ведётся средствами процессора, то скорее всего в него и упирается. В мэйлинг-листе ffmpeg один пользователь сообщает, что достиг параллелизма 60 SD-каналов. И то, упёрся только в объём памяти GPU. Судя по опциям, которые он указал, у него и декодирование аппаратное.
А пуллреквесты принимает keylase.
А пуллреквесты принимает keylase.
+1
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Эффективное кодирование видео в Linux c Nvidia NVENC: часть 2, дополнительная