diff --git a/src/ustreamer/h264/stream.c b/src/ustreamer/h264/stream.c index f6a962c..59c74d1 100644 --- a/src/ustreamer/h264/stream.c +++ b/src/ustreamer/h264/stream.c @@ -31,34 +31,32 @@ h264_stream_s *h264_stream_init(memsink_s *sink, const char *path, unsigned bitr h264->dest = frame_init(); atomic_init(&h264->online, false); +# define OPTION(_required, _key, _value) {#_key, _required, V4L2_CID_MPEG_VIDEO_##_key, _value} + + m2m_option_s options[] = { + OPTION(true, BITRATE, bitrate * 1000), + OPTION(true, H264_I_PERIOD, gop), + OPTION(true, H264_PROFILE, V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE), + OPTION(true, H264_LEVEL, V4L2_MPEG_VIDEO_H264_LEVEL_4_0), + OPTION(true, REPEAT_SEQ_HEADER, 1), + OPTION(false, H264_MIN_QP, 16), + OPTION(false, H264_MAX_QP, 32), + {NULL, false, 0, 0}, + }; + +# undef OPTION + // FIXME: 30 or 0? https://github.com/6by9/yavta/blob/master/yavta.c#L2100 // По логике вещей правильно 0, но почему-то на низких разрешениях типа 640x480 // енкодер через несколько секунд перестает производить корректные фреймы. // TODO: Это было актуально для MMAL, надо проверить для V4L2. -# define ADD_OPTION(_index, _required, _key, _value) { \ - h264->options[_index] = (m2m_option_s){#_key, _required, V4L2_CID_MPEG_VIDEO_##_key, _value}; \ - } - - A_CALLOC(h264->options, 8); - ADD_OPTION(0, true, BITRATE, bitrate * 1000); - ADD_OPTION(1, true, H264_I_PERIOD, gop); - ADD_OPTION(2, true, H264_PROFILE, V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE); - ADD_OPTION(3, true, H264_LEVEL, V4L2_MPEG_VIDEO_H264_LEVEL_4_0); - ADD_OPTION(4, true, REPEAT_SEQ_HEADER, 1); - ADD_OPTION(5, false, H264_MIN_QP, 16); - ADD_OPTION(6, false, H264_MAX_QP, 32); - h264->options[7] = (m2m_option_s){NULL, false, 0, 0}; - -# undef ADD_OPTION - - h264->enc = m2m_encoder_init("H264", path, V4L2_PIX_FMT_H264, 30, h264->options); + h264->enc = m2m_encoder_init("H264", path, V4L2_PIX_FMT_H264, 30, options); return h264; } void h264_stream_destroy(h264_stream_s *h264) { m2m_encoder_destroy(h264->enc); - free(h264->options); frame_destroy(h264->dest); frame_destroy(h264->tmp_src); free(h264); diff --git a/src/ustreamer/h264/stream.h b/src/ustreamer/h264/stream.h index d2592b3..ad2e055 100644 --- a/src/ustreamer/h264/stream.h +++ b/src/ustreamer/h264/stream.h @@ -38,7 +38,6 @@ typedef struct { memsink_s *sink; frame_s *tmp_src; frame_s *dest; - m2m_option_s *options; m2m_encoder_s *enc; atomic_bool online; } h264_stream_s; diff --git a/src/ustreamer/m2m.c b/src/ustreamer/m2m.c index 01256e8..2430773 100644 --- a/src/ustreamer/m2m.c +++ b/src/ustreamer/m2m.c @@ -43,20 +43,28 @@ static int _m2m_encoder_compress_raw( m2m_encoder_s *m2m_encoder_init(const char *name, const char *path, unsigned format, unsigned fps, m2m_option_s *options) { LOG_INFO("%s: Initializing encoder ...", name); + m2m_encoder_s *enc; A_CALLOC(enc, 1); assert(enc->name = strdup(name)); assert(enc->path = strdup(path)); enc->output_format = format; enc->fps = fps; - enc->options = options; enc->last_online = -1; + + unsigned count = 0; + for (; options[count].name != NULL; ++count); + ++count; + A_CALLOC(enc->options, count); + memcpy(enc->options, options, sizeof(m2m_option_s) * count); + return enc; } void m2m_encoder_destroy(m2m_encoder_s *enc) { E_LOG_INFO("Destroying encoder ..."); _m2m_encoder_cleanup(enc); + free(enc->options); free(enc->path); free(enc->name); free(enc);