mirror of
https://github.com/pikvm/ustreamer.git
synced 2026-03-03 06:11:42 +00:00
refactoring
This commit is contained in:
@@ -125,7 +125,7 @@ static int _h264_encoder_configure(h264_encoder_s *encoder, const frame_s *frame
|
||||
}
|
||||
|
||||
# define SET_PORT_PARAM(_id, _type, _key, _value) { \
|
||||
if ((error = mmal_port_parameter_set_##_type(RUN(_id##_port), _key, _value)) != MMAL_SUCCESS) { \
|
||||
if ((error = mmal_port_parameter_set_##_type(RUN(_id##_port), MMAL_PARAMETER_##_key, _value)) != MMAL_SUCCESS) { \
|
||||
LOG_ERROR_MMAL(error, "Can't set %s for the %s port", #_key, #_id); \
|
||||
goto error; \
|
||||
} \
|
||||
@@ -151,15 +151,12 @@ static int _h264_encoder_configure(h264_encoder_s *encoder, const frame_s *frame
|
||||
|
||||
# define IFMT(_next) RUN(input_port->format->_next)
|
||||
IFMT(type) = MMAL_ES_TYPE_VIDEO;
|
||||
char fourcc_buf[8];
|
||||
switch (frame->format) {
|
||||
case V4L2_PIX_FMT_YUYV: IFMT(encoding) = MMAL_ENCODING_YUYV; break;
|
||||
case V4L2_PIX_FMT_UYVY: IFMT(encoding) = MMAL_ENCODING_UYVY; break;
|
||||
case V4L2_PIX_FMT_RGB565: IFMT(encoding) = MMAL_ENCODING_RGB16; break;
|
||||
case V4L2_PIX_FMT_RGB24: IFMT(encoding) = MMAL_ENCODING_RGB24; break;
|
||||
default:
|
||||
LOG_ERROR("Unsupported input format for MMAL (fourcc): %s", fourcc_to_string(frame->format, fourcc_buf, 8));
|
||||
goto error;
|
||||
case V4L2_PIX_FMT_YUYV: IFMT(encoding) = MMAL_ENCODING_YUYV; break;
|
||||
case V4L2_PIX_FMT_UYVY: IFMT(encoding) = MMAL_ENCODING_UYVY; break;
|
||||
case V4L2_PIX_FMT_RGB565: IFMT(encoding) = MMAL_ENCODING_RGB16; break;
|
||||
case V4L2_PIX_FMT_RGB24: IFMT(encoding) = MMAL_ENCODING_RGB24; break;
|
||||
default: assert(0 && "Unsupported input format for MMAL H264 encoder");
|
||||
}
|
||||
IFMT(es->video.width) = align_size(frame->width, 32);
|
||||
IFMT(es->video.height) = align_size(frame->height, 16);
|
||||
@@ -173,7 +170,7 @@ static int _h264_encoder_configure(h264_encoder_s *encoder, const frame_s *frame
|
||||
# undef IFMT
|
||||
|
||||
COMMIT_PORT(input);
|
||||
SET_PORT_PARAM(input, boolean, MMAL_PARAMETER_ZERO_COPY, MMAL_FALSE);
|
||||
SET_PORT_PARAM(input, boolean, ZERO_COPY, MMAL_FALSE);
|
||||
}
|
||||
|
||||
{
|
||||
@@ -205,19 +202,19 @@ static int _h264_encoder_configure(h264_encoder_s *encoder, const frame_s *frame
|
||||
}
|
||||
}
|
||||
|
||||
SET_PORT_PARAM(output, boolean, MMAL_PARAMETER_ZERO_COPY, MMAL_TRUE);
|
||||
SET_PORT_PARAM(output, uint32, MMAL_PARAMETER_INTRAPERIOD, encoder->gop);
|
||||
SET_PORT_PARAM(output, uint32, MMAL_PARAMETER_NALUNITFORMAT, MMAL_VIDEO_NALUNITFORMAT_STARTCODES);
|
||||
SET_PORT_PARAM(output, boolean, MMAL_PARAMETER_MINIMISE_FRAGMENTATION, MMAL_TRUE);
|
||||
SET_PORT_PARAM(output, uint32, MMAL_PARAMETER_MB_ROWS_PER_SLICE, 0);
|
||||
SET_PORT_PARAM(output, boolean, MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT, MMAL_FALSE);
|
||||
SET_PORT_PARAM(output, boolean, MMAL_PARAMETER_VIDEO_DROPPABLE_PFRAMES, MMAL_FALSE);
|
||||
SET_PORT_PARAM(output, uint32, MMAL_PARAMETER_VIDEO_BIT_RATE, encoder->bps);
|
||||
SET_PORT_PARAM(output, uint32, MMAL_PARAMETER_VIDEO_ENCODE_PEAK_RATE, encoder->bps);
|
||||
SET_PORT_PARAM(output, uint32, MMAL_PARAMETER_VIDEO_ENCODE_MIN_QUANT, 16);
|
||||
SET_PORT_PARAM(output, uint32, MMAL_PARAMETER_VIDEO_ENCODE_MAX_QUANT, 34);
|
||||
SET_PORT_PARAM(output, uint32, MMAL_PARAMETER_VIDEO_ENCODE_FRAME_LIMIT_BITS, 1000000);
|
||||
SET_PORT_PARAM(output, uint32, MMAL_PARAMETER_VIDEO_ENCODE_H264_AU_DELIMITERS, MMAL_FALSE);
|
||||
SET_PORT_PARAM(output, boolean, ZERO_COPY, MMAL_TRUE);
|
||||
SET_PORT_PARAM(output, uint32, INTRAPERIOD, encoder->gop);
|
||||
SET_PORT_PARAM(output, uint32, NALUNITFORMAT, MMAL_VIDEO_NALUNITFORMAT_STARTCODES);
|
||||
SET_PORT_PARAM(output, boolean, MINIMISE_FRAGMENTATION, MMAL_TRUE);
|
||||
SET_PORT_PARAM(output, uint32, MB_ROWS_PER_SLICE, 0);
|
||||
SET_PORT_PARAM(output, boolean, VIDEO_IMMUTABLE_INPUT, MMAL_FALSE);
|
||||
SET_PORT_PARAM(output, boolean, VIDEO_DROPPABLE_PFRAMES, MMAL_FALSE);
|
||||
SET_PORT_PARAM(output, uint32, VIDEO_BIT_RATE, encoder->bps);
|
||||
SET_PORT_PARAM(output, uint32, VIDEO_ENCODE_PEAK_RATE, encoder->bps);
|
||||
SET_PORT_PARAM(output, uint32, VIDEO_ENCODE_MIN_QUANT, 16);
|
||||
SET_PORT_PARAM(output, uint32, VIDEO_ENCODE_MAX_QUANT, 34);
|
||||
SET_PORT_PARAM(output, uint32, VIDEO_ENCODE_FRAME_LIMIT_BITS, 1000000);
|
||||
SET_PORT_PARAM(output, uint32, VIDEO_ENCODE_H264_AU_DELIMITERS, MMAL_FALSE);
|
||||
}
|
||||
|
||||
RUN(wrapper->user_data) = (void *)encoder;
|
||||
@@ -358,21 +355,21 @@ static const char *_mmal_error_to_string(MMAL_STATUS_T error) {
|
||||
# define CASE_ERROR(_name, _msg) case MMAL_##_name: return "MMAL_" #_name " [" _msg "]"
|
||||
switch (error) {
|
||||
case MMAL_SUCCESS: return "MMAL_SUCCESS";
|
||||
CASE_ERROR(ENOMEM, "Out of memory");
|
||||
CASE_ERROR(ENOSPC, "Out of resources");
|
||||
CASE_ERROR(EINVAL, "Invalid argument");
|
||||
CASE_ERROR(ENOSYS, "Function not implemented");
|
||||
CASE_ERROR(ENOENT, "No such file or directory");
|
||||
CASE_ERROR(ENXIO, "No such device or address");
|
||||
CASE_ERROR(EIO, "IO error");
|
||||
CASE_ERROR(ESPIPE, "Illegal seek");
|
||||
CASE_ERROR(ECORRUPT, "Data is corrupt");
|
||||
CASE_ERROR(ENOTREADY, "Component is not ready");
|
||||
CASE_ERROR(ECONFIG, "Component is not configured");
|
||||
CASE_ERROR(EISCONN, "Port is already connected");
|
||||
CASE_ERROR(ENOTCONN, "Port is disconnected");
|
||||
CASE_ERROR(EAGAIN, "Resource temporarily unavailable");
|
||||
CASE_ERROR(EFAULT, "Bad address");
|
||||
CASE_ERROR(ENOMEM, "Out of memory");
|
||||
CASE_ERROR(ENOSPC, "Out of resources");
|
||||
CASE_ERROR(EINVAL, "Invalid argument");
|
||||
CASE_ERROR(ENOSYS, "Function not implemented");
|
||||
CASE_ERROR(ENOENT, "No such file or directory");
|
||||
CASE_ERROR(ENXIO, "No such device or address");
|
||||
CASE_ERROR(EIO, "IO error");
|
||||
CASE_ERROR(ESPIPE, "Illegal seek");
|
||||
CASE_ERROR(ECORRUPT, "Data is corrupt");
|
||||
CASE_ERROR(ENOTREADY, "Component is not ready");
|
||||
CASE_ERROR(ECONFIG, "Component is not configured");
|
||||
CASE_ERROR(EISCONN, "Port is already connected");
|
||||
CASE_ERROR(ENOTCONN, "Port is disconnected");
|
||||
CASE_ERROR(EAGAIN, "Resource temporarily unavailable");
|
||||
CASE_ERROR(EFAULT, "Bad address");
|
||||
case MMAL_STATUS_MAX: break; // Makes cpplint happy
|
||||
}
|
||||
return "Unknown error";
|
||||
|
||||
@@ -288,32 +288,28 @@ static int _omx_setup_input(omx_encoder_s *omx, device_s *dev) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
portdef.format.image.nFrameWidth = dev->run->width;
|
||||
portdef.format.image.nFrameHeight = dev->run->height;
|
||||
portdef.format.image.nStride = 0;
|
||||
portdef.format.image.nSliceHeight = align_size(dev->run->height, 16);
|
||||
portdef.format.image.bFlagErrorConcealment = OMX_FALSE;
|
||||
portdef.format.image.eCompressionFormat = OMX_IMAGE_CodingUnused;
|
||||
# define IFMT(_next) portdef.format.image._next
|
||||
IFMT(nFrameWidth) = dev->run->width;
|
||||
IFMT(nFrameHeight) = dev->run->height;
|
||||
IFMT(nStride) = 0;
|
||||
IFMT(nSliceHeight) = align_size(dev->run->height, 16);
|
||||
IFMT(bFlagErrorConcealment) = OMX_FALSE;
|
||||
IFMT(eCompressionFormat) = OMX_IMAGE_CodingUnused;
|
||||
portdef.nBufferSize = ((dev->run->width * dev->run->height) << 1) * 2;
|
||||
|
||||
# define MAP_FORMAT(_v4l2_format, _omx_format) \
|
||||
case _v4l2_format: { portdef.format.image.eColorFormat = _omx_format; break; }
|
||||
|
||||
switch (dev->run->format) {
|
||||
// https://www.fourcc.org/yuv.php
|
||||
// Also see comments inside OMX_IVCommon.h
|
||||
MAP_FORMAT(V4L2_PIX_FMT_YUYV, OMX_COLOR_FormatYCbYCr);
|
||||
MAP_FORMAT(V4L2_PIX_FMT_UYVY, OMX_COLOR_FormatCbYCrY);
|
||||
MAP_FORMAT(V4L2_PIX_FMT_RGB565, OMX_COLOR_Format16bitRGB565);
|
||||
MAP_FORMAT(V4L2_PIX_FMT_RGB24, OMX_COLOR_Format24bitRGB888);
|
||||
case V4L2_PIX_FMT_YUYV: IFMT(eColorFormat) = OMX_COLOR_FormatYCbYCr; break;
|
||||
case V4L2_PIX_FMT_UYVY: IFMT(eColorFormat) = OMX_COLOR_FormatCbYCrY; break;
|
||||
case V4L2_PIX_FMT_RGB565: IFMT(eColorFormat) = OMX_COLOR_Format16bitRGB565; break;
|
||||
case V4L2_PIX_FMT_RGB24: IFMT(eColorFormat) = OMX_COLOR_Format24bitRGB888; break;
|
||||
// TODO: найти устройство с RGB565 и протестить его.
|
||||
// FIXME: RGB24 не работает нормально, нижняя половина экрана зеленая.
|
||||
// FIXME: Китайский EasyCap тоже не работает, мусор на экране.
|
||||
// Вероятно обе проблемы вызваны некорректной реализацией OMX на пае.
|
||||
default: assert(0 && "Unsupported input format for OMX encoder");
|
||||
default: assert(0 && "Unsupported input format for OMX JPEG encoder");
|
||||
}
|
||||
|
||||
# undef MAP_FORMAT
|
||||
# undef IFMT
|
||||
|
||||
if (omx_component_set_portdef(&omx->encoder, &portdef) < 0) {
|
||||
return -1;
|
||||
@@ -347,9 +343,11 @@ static int _omx_setup_output(omx_encoder_s *omx, unsigned quality) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
portdef.format.image.bFlagErrorConcealment = OMX_FALSE;
|
||||
portdef.format.image.eCompressionFormat = OMX_IMAGE_CodingJPEG;
|
||||
portdef.format.image.eColorFormat = OMX_COLOR_FormatYCbYCr;
|
||||
# define OFMT(_next) portdef.format.image._next
|
||||
OFMT(bFlagErrorConcealment) = OMX_FALSE;
|
||||
OFMT(eCompressionFormat) = OMX_IMAGE_CodingJPEG;
|
||||
OFMT(eColorFormat) = OMX_COLOR_FormatYCbYCr;
|
||||
# undef OFMT
|
||||
|
||||
if (omx_component_set_portdef(&omx->encoder, &portdef) < 0) {
|
||||
return -1;
|
||||
|
||||
Reference in New Issue
Block a user