Я пытаюсь кодировать изображения с веб-камеры с помощью libx265 (libx264 пробовал ранее) …
Веб-камера не может снимать со стабильным FPS из-за разного количества света, поступающего в матрицу, и, как следствие, разных задержек. Поэтому я подсчитываю fps и dts входящего кадра и устанавливаю эти значения для соответствующих параметров x265_image
объект и инициализировать кодировщик fpsNum
с 1000 и fpsDenom
с 1 (для миллисекунды).
Проблема в том, что кодер игнорирует точки и точки входного изображения и кодирует со скоростью 1000 кадров в секунду! Тот же трюк с timebase дает плавную запись с libvpx. Почему он не работает с кодеками x264 / x265?
Вот параметры инициализации:
...
error = (x265_param_default_preset(param, "fast", "zerolatency") != 0);
if(!error){
param->sourceWidth = width;
param->sourceHeight = height;
param->frameNumThreads = 1;
param->fpsNum = 1000;
param->fpsDenom = 1;
// Intra refres:
param->keyframeMax = 15;
param->intraRefine = 1;
// Rate control:
param->rc.rateControlMode = X265_RC_CQP;
param->rc.rfConstant = 12;
param->rc.rfConstantMax = 48;
// For streaming:
param->bRepeatHeaders = 1;
param->bAnnexB = 1;
encoder = x265_encoder_open(param);
...
}
...
Вот функция добавления кадра:
bool hevc::Push(unsigned char *data){
if(!error){
std::lock_guard<std::mutex> lock(m_framestack);
if( timer > 0){
framestack.back()->dts = clock() - timer;
timer+= framestack.back()->dts;
}
else{timer = clock();}
x265_picture *picture = x265_picture_alloc();
if( picture){
x265_picture_init(param, picture);
picture->height = param->sourceHeight;
picture->stride[0] = param->sourceWidth;
picture->stride[1] = picture->stride[2] = picture->stride[0] / 2;
picture->planes[0] = new char[ luma_size];
picture->planes[1] = new char[chroma_size];
picture->planes[2] = new char[chroma_size];
colorspaces::BGRtoI420(param->sourceWidth, param->sourceHeight, data, (byte*)picture->planes[0], (byte*)picture->planes[1], (byte*)picture->planes[2]);
picture->pts = picture->dts = 0;
framestack.emplace_back(picture);
}
else{error = true;}
}
return !error;
}
Глобальное PTS растет сразу после x265_encoder_encode
вызов:
pts+= pic_in->dts;
и устанавливает как очко нового изображения из framestack
очередь, когда дело доходит до кодера.
Могут ли кодеки x265 / x264 кодировать с переменной fps? Как это настроить, если да?
Я не знаю о x265, но в x264 для кодирования видео с переменной частотой кадров (VFR) вы должны включить параметр x264_param_t.b_vfr_input, который был отключен настройкой нулевой скорости (для кодирования VFR требуется задержка в 1 кадр). Также, по крайней мере, в x264 timebase должен быть в i_timebase_num / i_timebase_den и i_fps_num / i_fps_den, чтобы быть средним fps (или оставить значение по умолчанию 25/1, если вы не знаете fps), иначе вы нарушите контроль скорости.
Других решений пока нет …