aligned input

This commit is contained in:
Devaev Maxim
2021-01-05 21:26:07 +03:00
parent 17bb7c77f3
commit 2630147a96
14 changed files with 167 additions and 102 deletions

View File

@@ -79,6 +79,7 @@ void frame_copy_meta(const frame_s *src, frame_s *dest) {
COPY(width);
COPY(height);
COPY(format);
COPY(stride);
COPY(online);
COPY(grab_ts);
COPY(encode_begin_ts);
@@ -88,14 +89,35 @@ void frame_copy_meta(const frame_s *src, frame_s *dest) {
#undef COPY
bool frame_compare(const frame_s *a, const frame_s *b) {
# define CMP(_field) (a->_field == b->_field)
return (
a->allocated && b->allocated
&& a->used == b->used
&& a->width == b->width
&& a->height == b->height
&& a->online == b->online
&& CMP(used)
&& CMP(width)
&& CMP(height)
&& CMP(format)
&& CMP(stride)
&& CMP(online)
&& !memcmp(a->data, b->data, b->used)
);
# undef CMP
}
unsigned frame_get_padding(const frame_s *frame) {
unsigned bytes_per_pixel = 0;
switch (frame->format) {
case V4L2_PIX_FMT_YUYV:
case V4L2_PIX_FMT_UYVY:
case V4L2_PIX_FMT_RGB565: bytes_per_pixel = 2; break;
case V4L2_PIX_FMT_RGB24: bytes_per_pixel = 3; break;
case V4L2_PIX_FMT_MJPEG:
case V4L2_PIX_FMT_JPEG: bytes_per_pixel = 0; break;
default: assert(0 && "Unknown pixelformat");
}
if (bytes_per_pixel > 0 && frame->stride > frame->width) {
return (frame->stride - frame->width * bytes_per_pixel);
}
return 0;
}
const char *fourcc_to_string(unsigned format, char *buf, size_t size) {

View File

@@ -29,20 +29,28 @@
#include <string.h>
#include <assert.h>
#include <linux/videodev2.h>
#include "tools.h"
#include "logging.h"
typedef struct {
const char *name;
const char *name;
uint8_t *data;
size_t used;
size_t allocated;
unsigned width;
unsigned height;
unsigned format;
bool online;
uint8_t *data;
size_t used;
size_t allocated;
unsigned width;
unsigned height;
unsigned format;
unsigned stride;
// Stride is a bytesperline in V4L2
// https://www.kernel.org/doc/html/v4.14/media/uapi/v4l/pixfmt-v4l2.html
// https://medium.com/@oleg.shipitko/what-does-stride-mean-in-image-processing-bba158a72bcd
bool online;
long double grab_ts;
long double encode_begin_ts;
@@ -63,4 +71,6 @@ void frame_copy(const frame_s *src, frame_s *dest);
void frame_copy_meta(const frame_s *src, frame_s *dest);
bool frame_compare(const frame_s *a, const frame_s *b);
unsigned frame_get_padding(const frame_s *frame);
const char *fourcc_to_string(unsigned format, char *buf, size_t size);

View File

@@ -39,12 +39,7 @@ int unjpeg(const frame_s *src, frame_s *dest, bool decode) {
struct jpeg_decompress_struct jpeg;
jpeg_create_decompress(&jpeg);
frame_copy_meta(src, dest);
dest->format = V4L2_PIX_FMT_RGB24;
dest->used = 0;
// https://stackoverflow.com/questions/19857766/error-handling-in-libjpeg
_jpeg_error_manager_s jpeg_error;
jpeg.err = jpeg_std_error((struct jpeg_error_mgr *)&jpeg_error);
jpeg_error.mgr.error_exit = _jpeg_error_handler;
@@ -60,24 +55,26 @@ int unjpeg(const frame_s *src, frame_s *dest, bool decode) {
jpeg_start_decompress(&jpeg);
frame_copy_meta(src, dest);
dest->format = V4L2_PIX_FMT_RGB24;
dest->width = jpeg.output_width;
dest->height = jpeg.output_height;
dest->stride = jpeg.output_width * jpeg.output_components; // Row stride
dest->used = 0;
if (decode) {
const unsigned row_stride = jpeg.output_width * jpeg.output_components;
JSAMPARRAY scanlines;
scanlines = (*jpeg.mem->alloc_sarray)((j_common_ptr) &jpeg, JPOOL_IMAGE, row_stride, 1);
scanlines = (*jpeg.mem->alloc_sarray)((j_common_ptr) &jpeg, JPOOL_IMAGE, dest->stride, 1);
frame_realloc_data(dest, ((src->width * src->height) << 1) * 2);
frame_realloc_data(dest, ((dest->width * dest->height) << 1) * 2);
while (jpeg.output_scanline < jpeg.output_height) {
jpeg_read_scanlines(&jpeg, scanlines, 1);
frame_append_data(dest, scanlines[0], row_stride);
frame_append_data(dest, scanlines[0], dest->stride);
}
jpeg_finish_decompress(&jpeg);
}
dest->width = jpeg.output_width;
dest->height = jpeg.output_height;
done:
jpeg_destroy_decompress(&jpeg);
return retval;

View File

@@ -153,6 +153,7 @@ int memsink_server_put(memsink_s *sink, const frame_s *frame) {
COPY(width);
COPY(height);
COPY(format);
COPY(stride);
COPY(online);
COPY(grab_ts);
COPY(encode_begin_ts);
@@ -203,6 +204,7 @@ int memsink_client_get(memsink_s *sink, frame_s *frame) { // cppcheck-suppress u
COPY(width);
COPY(height);
COPY(format);
COPY(stride);
COPY(online);
COPY(grab_ts);
COPY(encode_begin_ts);

View File

@@ -51,6 +51,7 @@ typedef struct {
unsigned width;
unsigned height;
unsigned format;
unsigned stride;
bool online;
long double grab_ts;
long double encode_begin_ts;

View File

@@ -57,7 +57,7 @@ static const struct {
static int _device_open_check_cap(device_s *dev);
static int _device_open_dv_timings(device_s *dev);
static int _device_apply_dv_timings(device_s *dev);
static int _device_open_format(device_s *dev);
static int _device_open_format(device_s *dev, bool first);
static void _device_open_hw_fps(device_s *dev);
static void _device_open_jpeg_quality(device_s *dev);
static int _device_open_io_method(device_s *dev);
@@ -149,7 +149,7 @@ int device_open(device_s *dev) {
if (_device_open_dv_timings(dev) < 0) {
goto error;
}
if (_device_open_format(dev) < 0) {
if (_device_open_format(dev, true) < 0) {
goto error;
}
_device_open_hw_fps(dev);
@@ -327,6 +327,7 @@ int device_grab_buffer(device_s *dev, hw_buffer_s **hw) {
HW(raw.width) = RUN(width);
HW(raw.height) = RUN(height);
HW(raw.format) = RUN(format);
HW(raw.stride) = RUN(stride);
HW(raw.online) = true;
memcpy(&HW(buf_info), &buf_info, sizeof(struct v4l2_buffer));
HW(raw.grab_ts) = get_now_monotonic();
@@ -464,7 +465,9 @@ static int _device_apply_dv_timings(device_s *dev) {
return 0;
}
static int _device_open_format(device_s *dev) {
static int _device_open_format(device_s *dev, bool first) {
const unsigned stride = align_size(RUN(width), 32) << 1;
struct v4l2_format fmt;
MEMSET_ZERO(fmt);
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@@ -472,22 +475,28 @@ static int _device_open_format(device_s *dev) {
fmt.fmt.pix.height = RUN(height);
fmt.fmt.pix.pixelformat = dev->format;
fmt.fmt.pix.field = V4L2_FIELD_ANY;
fmt.fmt.pix.bytesperline = stride;
// Set format
LOG_DEBUG("Calling ioctl(VIDIOC_S_FMT) ...");
if (xioctl(RUN(fd), VIDIOC_S_FMT, &fmt) < 0) {
LOG_PERROR("Unable to set pixelformat=%s, resolution=%ux%u",
_format_to_string_supported(dev->format), RUN(width), RUN(height));
LOG_PERROR("Unable to set pixelformat=%s, stride=%u, resolution=%ux%u",
_format_to_string_supported(dev->format), stride, RUN(width), RUN(height));
return -1;
}
// Check resolution
bool retry = false;
if (fmt.fmt.pix.width != RUN(width) || fmt.fmt.pix.height != RUN(height)) {
LOG_ERROR("Requested resolution=%ux%u is unavailable", RUN(width), RUN(height));
retry = true;
}
if (_device_apply_resolution(dev, fmt.fmt.pix.width, fmt.fmt.pix.height) < 0) {
return -1;
}
if (first && retry) {
return _device_open_format(dev, false);
}
LOG_INFO("Using resolution: %ux%u", RUN(width), RUN(height));
// Check format
@@ -511,6 +520,7 @@ static int _device_open_format(device_s *dev) {
RUN(format) = fmt.fmt.pix.pixelformat;
LOG_INFO("Using pixelformat: %s", _format_to_string_supported(RUN(format)));
RUN(stride) = fmt.fmt.pix.bytesperline;
RUN(raw_size) = fmt.fmt.pix.sizeimage; // Only for userptr
return 0;
}

View File

@@ -81,6 +81,7 @@ typedef struct {
unsigned width;
unsigned height;
unsigned format;
unsigned stride;
unsigned hw_fps;
unsigned jpeg_quality;
size_t raw_size;

View File

@@ -97,13 +97,13 @@ void encoder_prepare(encoder_s *enc, device_s *dev) {
ER(n_workers) = min_u(enc->n_workers, DR(n_buffers));
if ((DR(format) == V4L2_PIX_FMT_MJPEG || DR(format) == V4L2_PIX_FMT_JPEG) && type != ENCODER_TYPE_HW) {
LOG_INFO("Switching to HW encoder because the input format is (M)JPEG");
LOG_INFO("Switching to HW encoder: the input is (M)JPEG ...");
type = ENCODER_TYPE_HW;
}
if (type == ENCODER_TYPE_HW) {
if (DR(format) != V4L2_PIX_FMT_MJPEG && DR(format) != V4L2_PIX_FMT_JPEG) {
LOG_INFO("Switching to CPU encoder because the input format is not (M)JPEG");
LOG_INFO("Switching to CPU encoder: the input format is not (M)JPEG ...");
goto use_cpu;
}
quality = DR(jpeg_quality);
@@ -111,8 +111,8 @@ void encoder_prepare(encoder_s *enc, device_s *dev) {
}
# ifdef WITH_OMX
else if (type == ENCODER_TYPE_OMX) {
if (align_size(DR(width), 32) != DR(width) || align_size(DR(height), 16) != DR(height)) {
LOG_INFO("Switching to CPU encoder because OMX can't handle %ux%u", DR(width), DR(height));
if (align_size(DR(width), 32) != DR(width)) {
LOG_INFO("Switching to CPU encoder: OMX can't handle width=%u ...", DR(width));
goto use_cpu;
}
@@ -135,9 +135,18 @@ void encoder_prepare(encoder_s *enc, device_s *dev) {
}
}
frame_s frame;
MEMSET_ZERO(frame);
frame.width = DR(width);
frame.height = DR(height);
frame.format = DR(format);
frame.stride = DR(stride);
for (unsigned index = 0; index < ER(n_omxs); ++index) {
if (omx_encoder_prepare(ER(omxs[index]), DR(width), DR(height), DR(format), quality) < 0) {
LOG_ERROR("Can't prepare OMX encoder, falling back to CPU");
int omx_error = omx_encoder_prepare(ER(omxs[index]), &frame, quality);
if (omx_error == -2) {
goto use_cpu;
} else if (omx_error < 0) {
goto force_cpu;
}
}
@@ -154,6 +163,7 @@ void encoder_prepare(encoder_s *enc, device_s *dev) {
# pragma GCC diagnostic push
// cppcheck-suppress unusedLabel
force_cpu:
LOG_ERROR("Forced CPU encoder permanently");
cpu_forced = true;
# pragma GCC diagnostic pop
@@ -196,6 +206,7 @@ int encoder_compress(encoder_s *enc, unsigned worker_number, frame_s *src, frame
frame_copy_meta(src, dest);
dest->format = V4L2_PIX_FMT_JPEG;
dest->stride = 0;
dest->encode_begin_ts = get_now_monotonic();
dest->used = 0;

View File

@@ -113,6 +113,7 @@ static void _jpeg_write_scanlines_yuyv(struct jpeg_compress_struct *jpeg, const
uint8_t *line_buffer;
A_CALLOC(line_buffer, frame->width * 3);
const unsigned padding = frame_get_padding(frame);
const uint8_t *data = frame->data;
unsigned z = 0;
@@ -137,9 +138,9 @@ static void _jpeg_write_scanlines_yuyv(struct jpeg_compress_struct *jpeg, const
data += 4;
}
}
data += padding;
JSAMPROW scanlines[1];
scanlines[0] = line_buffer;
JSAMPROW scanlines[1] = {line_buffer};
jpeg_write_scanlines(jpeg, scanlines, 1);
}
@@ -150,13 +151,14 @@ static void _jpeg_write_scanlines_uyvy(struct jpeg_compress_struct *jpeg, const
uint8_t *line_buffer;
A_CALLOC(line_buffer, frame->width * 3);
const unsigned padding = frame_get_padding(frame);
const uint8_t *data = frame->data;
unsigned z = 0;
while (jpeg->next_scanline < frame->height) {
uint8_t *ptr = line_buffer;
for(unsigned x = 0; x < frame->width; ++x) {
for (unsigned x = 0; x < frame->width; ++x) {
int y = (!z ? data[1] << 8 : data[3] << 8);
int u = data[0] - 128;
int v = data[2] - 128;
@@ -174,9 +176,9 @@ static void _jpeg_write_scanlines_uyvy(struct jpeg_compress_struct *jpeg, const
data += 4;
}
}
data += padding;
JSAMPROW scanlines[1];
scanlines[0] = line_buffer;
JSAMPROW scanlines[1] = {line_buffer};
jpeg_write_scanlines(jpeg, scanlines, 1);
}
@@ -192,12 +194,13 @@ static void _jpeg_write_scanlines_rgb565(struct jpeg_compress_struct *jpeg, cons
uint8_t *line_buffer;
A_CALLOC(line_buffer, frame->width * 3);
const unsigned padding = frame_get_padding(frame);
const uint8_t *data = frame->data;
while (jpeg->next_scanline < frame->height) {
uint8_t *ptr = line_buffer;
for(unsigned x = 0; x < frame->width; ++x) {
for (unsigned x = 0; x < frame->width; ++x) {
unsigned int two_byte = (data[1] << 8) + data[0];
*(ptr++) = data[1] & 248; // Red
@@ -206,9 +209,9 @@ static void _jpeg_write_scanlines_rgb565(struct jpeg_compress_struct *jpeg, cons
data += 2;
}
data += padding;
JSAMPROW scanlines[1];
scanlines[0] = line_buffer;
JSAMPROW scanlines[1] = {line_buffer};
jpeg_write_scanlines(jpeg, scanlines, 1);
}
@@ -216,10 +219,14 @@ static void _jpeg_write_scanlines_rgb565(struct jpeg_compress_struct *jpeg, cons
}
static void _jpeg_write_scanlines_rgb24(struct jpeg_compress_struct *jpeg, const frame_s *frame) {
const unsigned padding = frame_get_padding(frame);
uint8_t *data = frame->data;
while (jpeg->next_scanline < frame->height) {
JSAMPROW scanlines[1];
scanlines[0] = (uint8_t *)(frame->data + jpeg->next_scanline * frame->width * 3);
JSAMPROW scanlines[1] = {data};
jpeg_write_scanlines(jpeg, scanlines, 1);
data += (jpeg->next_scanline * frame->width * 3) + padding;
}
}

View File

@@ -30,7 +30,7 @@ static const OMX_U32 _OUTPUT_PORT = 341;
static int _vcos_semwait(VCOS_SEMAPHORE_T *sem);
static int _omx_init_component(omx_encoder_s *omx);
static int _omx_init_disable_ports(omx_encoder_s *omx);
static int _omx_setup_input(omx_encoder_s *omx, unsigned width, unsigned height, unsigned format);
static int _omx_setup_input(omx_encoder_s *omx, const frame_s *frame);
static int _omx_setup_output(omx_encoder_s *omx, unsigned quality);
static int _omx_encoder_clear_ports(omx_encoder_s *omx);
@@ -106,14 +106,19 @@ void omx_encoder_destroy(omx_encoder_s *omx) {
free(omx);
}
int omx_encoder_prepare(omx_encoder_s *omx, unsigned width, unsigned height, unsigned format, unsigned quality) {
int omx_encoder_prepare(omx_encoder_s *omx, const frame_s *frame, unsigned quality) {
if (align_size(frame->width, 32) != frame->width && frame_get_padding(frame) == 0) {
LOG_ERROR("%u %u", frame->width, frame->stride);
LOG_ERROR("OMX encoder can't handle unaligned width");
return -2;
}
if (omx_component_set_state(&omx->comp, OMX_StateIdle) < 0) {
return -1;
}
if (_omx_encoder_clear_ports(omx) < 0) {
return -1;
}
if (_omx_setup_input(omx, width, height, format) < 0) {
if (_omx_setup_input(omx, frame) < 0) {
return -1;
}
if (_omx_setup_output(omx, quality) < 0) {
@@ -136,7 +141,9 @@ int omx_encoder_compress(omx_encoder_s *omx, const frame_s *src, frame_s *dest)
return -1;
}
dest->width = align_size(src->width, 32);
dest->used = 0;
omx->output_available = false;
omx->input_required = true;
@@ -277,7 +284,7 @@ static int _omx_init_disable_ports(omx_encoder_s *omx) {
return 0;
}
static int _omx_setup_input(omx_encoder_s *omx, unsigned width, unsigned height, unsigned format) {
static int _omx_setup_input(omx_encoder_s *omx, const frame_s *frame) {
LOG_DEBUG("Setting up OMX JPEG input port ...");
OMX_ERRORTYPE error;
@@ -289,14 +296,14 @@ static int _omx_setup_input(omx_encoder_s *omx, unsigned width, unsigned height,
}
# define IFMT(_next) portdef.format.image._next
IFMT(nFrameWidth) = width;
IFMT(nFrameHeight) = height;
IFMT(nStride) = 0;
IFMT(nSliceHeight) = align_size(height, 16);
IFMT(nFrameWidth) = align_size(frame->width, 32);
IFMT(nFrameHeight) = frame->height;
IFMT(nStride) = align_size(frame->width, 32) << 1;
IFMT(nSliceHeight) = align_size(frame->height, 16);
IFMT(bFlagErrorConcealment) = OMX_FALSE;
IFMT(eCompressionFormat) = OMX_IMAGE_CodingUnused;
portdef.nBufferSize = ((width * height) << 1) * 2;
switch (format) {
portdef.nBufferSize = ((frame->width * frame->height) << 1) * 2;
switch (frame->format) {
// https://www.fourcc.org/yuv.php
// Also see comments inside OMX_IVCommon.h
case V4L2_PIX_FMT_YUYV: IFMT(eColorFormat) = OMX_COLOR_FormatYCbYCr; break;
@@ -307,7 +314,7 @@ static int _omx_setup_input(omx_encoder_s *omx, unsigned width, unsigned height,
// FIXME: RGB24 не работает нормально, нижняя половина экрана зеленая.
// FIXME: Китайский EasyCap тоже не работает, мусор на экране.
// Вероятно обе проблемы вызваны некорректной реализацией OMX на пае.
default: assert(0 && "Unsupported input format for OMX JPEG encoder");
default: assert(0 && "Unsupported pixelformat");
}
# undef IFMT
@@ -358,43 +365,31 @@ static int _omx_setup_output(omx_encoder_s *omx, unsigned quality) {
return -1;
}
{
OMX_CONFIG_BOOLEANTYPE exif;
OMX_INIT_STRUCTURE(exif);
exif.bEnabled = OMX_FALSE;
if ((error = OMX_SetParameter(omx->comp, OMX_IndexParamBrcmDisableEXIF, &exif)) != OMX_ErrorNone) {
LOG_ERROR_OMX(error, "Can't disable EXIF on OMX JPEG");
return -1;
# define SET_PARAM(_key, _value) { \
if ((error = OMX_SetParameter(omx->comp, OMX_IndexParam##_key, _value)) != OMX_ErrorNone) { \
LOG_ERROR_OMX(error, "Can't set OMX param %s", #_key); \
return -1; \
} \
}
}
{
OMX_PARAM_IJGSCALINGTYPE ijg;
OMX_CONFIG_BOOLEANTYPE exif;
OMX_INIT_STRUCTURE(exif);
exif.bEnabled = OMX_FALSE;
SET_PARAM(BrcmDisableEXIF, &exif);
OMX_INIT_STRUCTURE(ijg);
ijg.nPortIndex = _OUTPUT_PORT;
ijg.bEnabled = OMX_TRUE;
OMX_PARAM_IJGSCALINGTYPE ijg;
OMX_INIT_STRUCTURE(ijg);
ijg.nPortIndex = _OUTPUT_PORT;
ijg.bEnabled = OMX_TRUE;
SET_PARAM(BrcmEnableIJGTableScaling, &ijg);
if ((error = OMX_SetParameter(omx->comp, OMX_IndexParamBrcmEnableIJGTableScaling, &ijg)) != OMX_ErrorNone) {
LOG_ERROR_OMX(error, "Can't set OMX JPEG IJG settings");
return -1;
}
}
OMX_IMAGE_PARAM_QFACTORTYPE qfactor;
OMX_INIT_STRUCTURE(qfactor);
qfactor.nPortIndex = _OUTPUT_PORT;
qfactor.nQFactor = quality;
SET_PARAM(QFactor, &qfactor);
{
OMX_IMAGE_PARAM_QFACTORTYPE qfactor;
OMX_INIT_STRUCTURE(qfactor);
qfactor.nPortIndex = _OUTPUT_PORT;
qfactor.nQFactor = quality;
if ((error = OMX_SetParameter(omx->comp, OMX_IndexParamQFactor, &qfactor)) != OMX_ErrorNone) {
LOG_ERROR_OMX(error, "Can't set OMX JPEG quality");
return -1;
}
}
# undef SET_PARAM
if (omx_component_enable_port(&omx->comp, _OUTPUT_PORT) < 0) {
return -1;

View File

@@ -68,5 +68,5 @@ typedef struct {
omx_encoder_s *omx_encoder_init(void);
void omx_encoder_destroy(omx_encoder_s *omx);
int omx_encoder_prepare(omx_encoder_s *omx, unsigned width, unsigned height, unsigned format, unsigned quality);
int omx_encoder_prepare(omx_encoder_s *omx, const frame_s *frame, unsigned quality);
int omx_encoder_compress(omx_encoder_s *omx, const frame_s *src, frame_s *dest);

View File

@@ -95,9 +95,14 @@ void h264_encoder_destroy(h264_encoder_s *enc) {
free(enc);
}
int h264_encoder_prepare(h264_encoder_s *enc, unsigned width, unsigned height, unsigned format) {
int h264_encoder_prepare(h264_encoder_s *enc, const frame_s *frame) {
LOG_INFO("H264: Configuring MMAL encoder ...");
if (align_size(frame->width, 32) != frame->width && frame_get_padding(frame) == 0) {
LOG_ERROR("H264: MMAL encoder can't handle unaligned width");
goto error;
}
MMAL_STATUS_T error;
# define PREPARE_PORT(_id) { \
@@ -139,21 +144,21 @@ int h264_encoder_prepare(h264_encoder_s *enc, unsigned width, unsigned height, u
# define IFMT(_next) RUN(input_port->format->_next)
IFMT(type) = MMAL_ES_TYPE_VIDEO;
switch (format) {
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_MJPEG:
case V4L2_PIX_FMT_JPEG: // See unjpeg.c
case V4L2_PIX_FMT_RGB24: IFMT(encoding) = MMAL_ENCODING_RGB24; break;
default: assert(0 && "Unsupported input format for MMAL H264 encoder");
default: assert(0 && "Unsupported pixelformat");
}
IFMT(es->video.width) = align_size(width, 32);
IFMT(es->video.height) = align_size(height, 16);
IFMT(es->video.width) = align_size(frame->width, 32);
IFMT(es->video.height) = align_size(frame->height, 16);
IFMT(es->video.crop.x) = 0;
IFMT(es->video.crop.y) = 0;
IFMT(es->video.crop.width) = width;
IFMT(es->video.crop.height) = height;
IFMT(es->video.crop.width) = frame->width;
IFMT(es->video.crop.height) = frame->height;
IFMT(flags) = MMAL_ES_FORMAT_FLAG_FRAMED;
RUN(input_port->buffer_size) = 1000 * 1000;
RUN(input_port->buffer_num) = RUN(input_port->buffer_num_recommended) * 4;
@@ -211,9 +216,10 @@ int h264_encoder_prepare(h264_encoder_s *enc, unsigned width, unsigned height, u
ENABLE_PORT(input);
ENABLE_PORT(output);
RUN(width) = width;
RUN(height) = height;
RUN(format) = format;
RUN(width) = frame->width;
RUN(height) = frame->height;
RUN(format) = frame->format;
RUN(stride) = frame->stride;
return 0;
@@ -247,6 +253,7 @@ static void _h264_encoder_cleanup(h264_encoder_s *enc) {
RUN(width) = 0;
RUN(height) = 0;
RUN(format) = 0;
RUN(stride) = 0;
RUN(last_online) = -1;
}
@@ -254,6 +261,7 @@ int h264_encoder_compress(h264_encoder_s *enc, const frame_s *src, frame_s *dest
frame_copy_meta(src, dest);
dest->encode_begin_ts = get_now_monotonic();
dest->format = V4L2_PIX_FMT_H264;
dest->stride = 0;
if (src->format == V4L2_PIX_FMT_MJPEG || src->format == V4L2_PIX_FMT_JPEG) {
LOG_DEBUG("H264: Input frame format is JPEG; decoding ...");

View File

@@ -53,6 +53,7 @@ typedef struct {
unsigned width;
unsigned height;
unsigned format;
unsigned stride;
} h264_encoder_runtime_s;
typedef struct {
@@ -67,5 +68,5 @@ typedef struct {
h264_encoder_s *h264_encoder_init(void);
void h264_encoder_destroy(h264_encoder_s *enc);
int h264_encoder_prepare(h264_encoder_s *enc, unsigned width, unsigned height, unsigned format);
int h264_encoder_prepare(h264_encoder_s *enc, const frame_s *frame);
int h264_encoder_compress(h264_encoder_s *enc, const frame_s *src, frame_s *dest);

View File

@@ -431,7 +431,7 @@ static void _h264_stream_process(h264_stream_s *h264, const frame_s *frame) {
# define NEQ(_field) (frame->_field != h264->enc->run->_field)
if (NEQ(width) || NEQ(height) || NEQ(format)) {
# undef NEQ
h264_encoder_prepare(h264->enc, frame->width, frame->height, frame->format);
h264_encoder_prepare(h264->enc, frame);
}
if (h264->enc->run->format) {
if (h264_encoder_compress(h264->enc, frame, h264->dest) == 0) {