Compare commits

...

8 Commits
v0.53 ... v0.54

Author SHA1 Message Date
Devaev Maxim
4c8351c1bc Bump version: 0.53 → 0.54 2019-03-04 15:47:02 +03:00
Devaev Maxim
4492cc1efe refactoring 2019-03-04 15:42:47 +03:00
Devaev Maxim
b2ca0ea998 encoders subdir 2019-03-04 15:29:11 +03:00
Devaev Maxim
924665c1a3 refactoring 2019-03-04 15:16:36 +03:00
Devaev Maxim
5d49018bb2 refactoring 2019-03-04 15:07:16 +03:00
Devaev Maxim
3ae8818b3d consistent using fourcc 2019-03-04 15:06:29 +03:00
Devaev Maxim
2bb1f71c9c minor omx fixes 2019-03-04 14:25:57 +03:00
Devaev Maxim
537e55afc6 RGB24 2019-03-04 11:34:25 +03:00
19 changed files with 143 additions and 98 deletions

View File

@@ -1,7 +1,7 @@
[bumpversion]
commit = True
tag = True
current_version = 0.53
current_version = 0.54
parse = (?P<major>\d+)\.(?P<minor>\d+)(\.(?P<patch>\d+)(\-(?P<release>[a-z]+))?)?
serialize =
{major}.{minor}

View File

@@ -8,13 +8,13 @@ LDFLAGS ?=
CC = gcc
LIBS = -lm -ljpeg -pthread -levent -levent_pthreads -luuid
override CFLAGS += -c -std=c99 -Wall -Wextra -D_GNU_SOURCE
SOURCES = $(shell ls src/*.c src/jpeg/*.c src/hw/*.c)
SOURCES = $(shell ls src/*.c src/encoders/cpu/*.c src/encoders/hw/*.c)
OBJECTS = $(SOURCES:.c=.o)
PROG = ustreamer
ifeq ($(shell ls -d /opt/vc/include 2>/dev/null), /opt/vc/include)
SOURCES += $(shell ls src/omx/*.c)
SOURCES += $(shell ls src/encoders/omx/*.c)
LIBS += -lbcm_host -lvcos -lopenmaxil -L/opt/vc/lib
override CFLAGS += -DOMX_ENCODER -DOMX_SKIP64BIT -I/opt/vc/include
endif
@@ -59,5 +59,5 @@ push:
clean-all: clean
clean:
rm -f src/*.o src/{jpeg,omx}/*.o vgcore.* *.sock $(PROG)
rm -f src/*.o src/encoders/*/*.o vgcore.* *.sock $(PROG)
rm -rf pkg src/$(PROG)-* src/v*.tar.gz v*.tar.gz $(PROG)-*.pkg.tar.xz

View File

@@ -3,14 +3,14 @@
pkgname=ustreamer
pkgver=0.53
pkgver=0.54
pkgrel=1
pkgdesc="Lightweight and fast MJPG-HTTP streamer"
url="https://github.com/pi-kvm/ustreamer"
license=(GPL)
arch=(i686 x86_64 armv6h armv7h)
depends=(libjpeg libevent libutil-linux)
# optional: raspberrypi-firmware for OMX JPEG compressor
# optional: raspberrypi-firmware for OMX JPEG encoder
makedepends=(gcc make)
source=("$url/archive/v$pkgver.tar.gz")
md5sums=(SKIP)

View File

@@ -22,4 +22,4 @@
#pragma once
#define VERSION "0.53"
#define VERSION "0.54"

View File

@@ -55,6 +55,7 @@ static const struct {
{"YUYV", V4L2_PIX_FMT_YUYV},
{"UYVY", V4L2_PIX_FMT_UYVY},
{"RGB565", V4L2_PIX_FMT_RGB565},
{"RGB24", V4L2_PIX_FMT_RGB24},
{"JPEG", V4L2_PIX_FMT_MJPEG},
{"JPEG", V4L2_PIX_FMT_JPEG},
};
@@ -69,8 +70,9 @@ static int _device_open_mmap(struct device_t *dev);
static int _device_open_queue_buffers(struct device_t *dev);
static int _device_apply_resolution(struct device_t *dev, unsigned width, unsigned height);
static const char *_format_to_string_auto(char *buf, size_t size, unsigned format);
static const char *_format_to_string_null(unsigned format);
static const char *_format_to_string_fourcc(char *buf, size_t size, unsigned format);
static const char *_format_to_string_nullable(unsigned format);
static const char *_format_to_string_supported(unsigned format);
static const char *_standard_to_string(v4l2_std_id standard);
@@ -288,7 +290,6 @@ static int _device_apply_dv_timings(struct device_t *dev) {
static int _device_open_format(struct device_t *dev) {
struct v4l2_format fmt;
char format_str[8];
MEMSET_ZERO(fmt);
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@@ -301,8 +302,8 @@ static int _device_open_format(struct device_t *dev) {
LOG_DEBUG("Calling ioctl(VIDIOC_S_FMT) ...");
if (xioctl(dev->run->fd, VIDIOC_S_FMT, &fmt) < 0) {
LOG_PERROR(
"Unable to set format=%s; resolution=%ux%u",
_format_to_string_auto(format_str, 8, dev->format),
"Unable to set pixelformat=%s; resolution=%ux%u",
_format_to_string_supported(dev->format),
dev->run->width,
dev->run->height
);
@@ -325,24 +326,27 @@ static int _device_open_format(struct device_t *dev) {
LOG_ERROR(
"Could not obtain the requested pixelformat=%s; driver gave us %s",
_format_to_string_auto(format_str, 8, dev->format),
_format_to_string_auto(format_obtained_str, 8, fmt.fmt.pix.pixelformat)
_format_to_string_supported(dev->format),
_format_to_string_supported(fmt.fmt.pix.pixelformat)
);
if ((format_str_nullable = (char *)_format_to_string_null(fmt.fmt.pix.pixelformat)) != NULL) {
if ((format_str_nullable = (char *)_format_to_string_nullable(fmt.fmt.pix.pixelformat)) != NULL) {
LOG_INFO(
"Falling back to %s mode (consider using '--format=%s' option)",
format_str_nullable,
format_str_nullable
);
} else {
LOG_ERROR("Unsupported pixel format");
LOG_ERROR(
"Unsupported pixelformat=%s (fourcc)",
_format_to_string_fourcc(format_obtained_str, 8, fmt.fmt.pix.pixelformat)
);
return -1;
}
}
dev->run->format = fmt.fmt.pix.pixelformat;
LOG_INFO("Using pixelformat: %s", _format_to_string_auto(format_str, 8, dev->run->format));
LOG_INFO("Using pixelformat: %s", _format_to_string_supported(dev->run->format));
return 0;
}
@@ -441,7 +445,7 @@ static int _device_apply_resolution(struct device_t *dev, unsigned width, unsign
return 0;
}
static const char *_format_to_string_auto(char *buf, size_t size, unsigned format) {
static const char *_format_to_string_fourcc(char *buf, size_t size, unsigned format) {
assert(size >= 8);
buf[0] = format & 0x7F;
buf[1] = (format >> 8) & 0x7F;
@@ -458,7 +462,7 @@ static const char *_format_to_string_auto(char *buf, size_t size, unsigned forma
return buf;
}
static const char *_format_to_string_null(unsigned format) {
static const char *_format_to_string_nullable(unsigned format) {
for (unsigned index = 0; index < ARRAY_LEN(_FORMATS); ++index) {
if (format == _FORMATS[index].format) {
return _FORMATS[index].name;
@@ -467,6 +471,11 @@ static const char *_format_to_string_null(unsigned format) {
return NULL;
}
static const char *_format_to_string_supported(unsigned format) {
const char *format_str = _format_to_string_nullable(format);
return (format_str == NULL ? "unsupported" : format_str);
}
static const char *_standard_to_string(v4l2_std_id standard) {
for (unsigned index = 0; index < ARRAY_LEN(_STANDARDS); ++index) {
if (standard == _STANDARDS[index].standard) {

View File

@@ -39,7 +39,7 @@
#define STANDARDS_STR "UNKNOWN, PAL, NTSC, SECAM"
#define FORMAT_UNKNOWN -1
#define FORMATS_STR "YUYV, UYVY, RGB565, JPEG"
#define FORMATS_STR "YUYV, UYVY, RGB565, RGB24, JPEG"
struct hw_buffer_t {

View File

@@ -30,11 +30,11 @@
#include "device.h"
#include "encoder.h"
#include "jpeg/encoder.h"
#include "hw/encoder.h"
#include "encoders/cpu/encoder.h"
#include "encoders/hw/encoder.h"
#ifdef OMX_ENCODER
# include "omx/encoder.h"
# include "encoders/omx/encoder.h"
#endif
@@ -80,7 +80,7 @@ void encoder_prepare(struct encoder_t *encoder, struct device_t *dev) {
# ifdef OMX_ENCODER
if (encoder->run->type == ENCODER_TYPE_OMX) {
LOG_DEBUG("Preparing OMX encoder ...");
LOG_DEBUG("Preparing OMX JPEG encoder ...");
if (dev->n_workers > OMX_MAX_ENCODERS) {
LOG_INFO(
@@ -152,7 +152,7 @@ void encoder_prepare_live(struct encoder_t *encoder, struct device_t *dev) {
(dev->run->format == V4L2_PIX_FMT_MJPEG || dev->run->format == V4L2_PIX_FMT_JPEG)
&& encoder->run->type != ENCODER_TYPE_HW
) {
LOG_INFO("Switching to HW encoder because the input format is (M)JPEG");
LOG_INFO("Switching to HW JPEG encoder because the input format is (M)JPEG");
A_PTHREAD_M_LOCK(&encoder->run->mutex);
encoder->run->type = ENCODER_TYPE_HW;
A_PTHREAD_M_UNLOCK(&encoder->run->mutex);
@@ -160,21 +160,21 @@ void encoder_prepare_live(struct encoder_t *encoder, struct device_t *dev) {
if (encoder->run->type == ENCODER_TYPE_HW) {
if (dev->run->format != V4L2_PIX_FMT_MJPEG && dev->run->format != V4L2_PIX_FMT_JPEG) {
LOG_INFO("Switching to CPU encoder because the input format is not (M)JPEG");
LOG_INFO("Switching to CPU JPEG encoder because the input format is not (M)JPEG");
goto use_fallback;
}
if (hw_encoder_prepare_live(dev, encoder->quality) < 0) {
A_PTHREAD_M_LOCK(&encoder->run->mutex);
encoder->run->quality = 0;
A_PTHREAD_M_UNLOCK(&encoder->run->mutex);
LOG_INFO("Using JPEG quality: HW default");
LOG_INFO("Using JPEG quality: HW-default");
}
}
# ifdef OMX_ENCODER
else if (encoder->run->type == ENCODER_TYPE_OMX) {
for (unsigned index = 0; index < encoder->run->n_omxs; ++index) {
if (omx_encoder_prepare_live(encoder->run->omxs[index], dev, encoder->quality) < 0) {
LOG_ERROR("Can't prepare OMX encoder, falling back to CPU");
LOG_ERROR("Can't prepare OMX JPEG encoder, falling back to CPU");
goto use_fallback;
}
}
@@ -198,7 +198,7 @@ int encoder_compress_buffer(struct encoder_t *encoder, struct device_t *dev, uns
assert(encoder->run->type != ENCODER_TYPE_UNKNOWN);
if (encoder->run->type == ENCODER_TYPE_CPU) {
jpeg_encoder_compress_buffer(dev, buf_index, encoder->quality);
cpu_encoder_compress_buffer(dev, buf_index, encoder->quality);
} else if (encoder->run->type == ENCODER_TYPE_HW) {
hw_encoder_compress_buffer(dev, buf_index);
}

View File

@@ -28,7 +28,7 @@
#include "device.h"
#ifdef OMX_ENCODER
# include "omx/encoder.h"
# include "encoders/omx/encoder.h"
# define ENCODER_TYPES_OMX_HINT ", OMX"
#else
# define ENCODER_TYPES_OMX_HINT ""

View File

@@ -33,13 +33,13 @@
#include <jpeglib.h>
#include <linux/videodev2.h>
#include "../tools.h"
#include "../device.h"
#include "../../tools.h"
#include "../../device.h"
#include "encoder.h"
struct _mjpg_destination_mgr {
struct _jpeg_dest_manager_t {
struct jpeg_destination_mgr mgr; // Default manager
JOCTET *buffer; // Start of buffer
unsigned char *outbuffer_cursor;
@@ -50,18 +50,19 @@ struct _mjpg_destination_mgr {
static void _jpeg_set_dest_picture(j_compress_ptr jpeg, unsigned char *picture, unsigned long *written);
static void _jpeg_write_scanlines_yuyv(
struct jpeg_compress_struct *jpeg,
unsigned char *line_buffer, const unsigned char *data,
struct jpeg_compress_struct *jpeg, const unsigned char *data,
unsigned width, unsigned height);
static void _jpeg_write_scanlines_uyvy(
struct jpeg_compress_struct *jpeg,
unsigned char *line_buffer, const unsigned char *data,
struct jpeg_compress_struct *jpeg, const unsigned char *data,
unsigned width, unsigned height);
static void _jpeg_write_scanlines_rgb565(
struct jpeg_compress_struct *jpeg,
unsigned char *line_buffer, const unsigned char *data,
struct jpeg_compress_struct *jpeg, const unsigned char *data,
unsigned width, unsigned height);
static void _jpeg_write_scanlines_rgb24(
struct jpeg_compress_struct *jpeg, const unsigned char *data,
unsigned width, unsigned height);
static void _jpeg_init_destination(j_compress_ptr jpeg);
@@ -69,14 +70,11 @@ static boolean _jpeg_empty_output_buffer(j_compress_ptr jpeg);
static void _jpeg_term_destination(j_compress_ptr jpeg);
void jpeg_encoder_compress_buffer(struct device_t *dev, unsigned index, unsigned quality) {
void cpu_encoder_compress_buffer(struct device_t *dev, unsigned index, unsigned quality) {
// This function based on compress_image_to_jpeg() from mjpg-streamer
struct jpeg_compress_struct jpeg;
struct jpeg_error_mgr jpeg_error;
unsigned char *line_buffer;
A_CALLOC(line_buffer, dev->run->width * 3);
jpeg.err = jpeg_std_error(&jpeg_error);
jpeg_create_compress(&jpeg);
@@ -94,15 +92,16 @@ void jpeg_encoder_compress_buffer(struct device_t *dev, unsigned index, unsigned
jpeg_start_compress(&jpeg, TRUE);
# define WRITE_SCANLINES(_func) \
_func(&jpeg, line_buffer, dev->run->hw_buffers[index].start, dev->run->width, dev->run->height)
# define WRITE_SCANLINES(_format, _func) \
case _format: { _func(&jpeg, dev->run->hw_buffers[index].start, dev->run->width, dev->run->height); break; }
switch (dev->run->format) {
// https://www.fourcc.org/yuv.php
case V4L2_PIX_FMT_YUYV: WRITE_SCANLINES(_jpeg_write_scanlines_yuyv); break;
case V4L2_PIX_FMT_UYVY: WRITE_SCANLINES(_jpeg_write_scanlines_uyvy); break;
case V4L2_PIX_FMT_RGB565: WRITE_SCANLINES(_jpeg_write_scanlines_rgb565); break;
default: assert(0 && "Unsupported input format for JPEG compressor");
WRITE_SCANLINES(V4L2_PIX_FMT_YUYV, _jpeg_write_scanlines_yuyv);
WRITE_SCANLINES(V4L2_PIX_FMT_UYVY, _jpeg_write_scanlines_uyvy);
WRITE_SCANLINES(V4L2_PIX_FMT_RGB565, _jpeg_write_scanlines_rgb565);
WRITE_SCANLINES(V4L2_PIX_FMT_RGB24, _jpeg_write_scanlines_rgb24);
default: assert(0 && "Unsupported input format for CPU JPEG encoder");
}
# undef WRITE_SCANLINES
@@ -111,21 +110,20 @@ void jpeg_encoder_compress_buffer(struct device_t *dev, unsigned index, unsigned
// https://stackoverflow.com/questions/19857766/error-handling-in-libjpeg
jpeg_finish_compress(&jpeg);
jpeg_destroy_compress(&jpeg);
free(line_buffer);
assert(dev->run->pictures[index].size > 0);
assert(dev->run->pictures[index].size <= dev->run->max_picture_size);
}
static void _jpeg_set_dest_picture(j_compress_ptr jpeg, unsigned char *picture, unsigned long *written) {
struct _mjpg_destination_mgr *dest;
struct _jpeg_dest_manager_t *dest;
if (jpeg->dest == NULL) {
assert((jpeg->dest = (struct jpeg_destination_mgr *)(*jpeg->mem->alloc_small)(
(j_common_ptr) jpeg, JPOOL_PERMANENT, sizeof(struct _mjpg_destination_mgr)
(j_common_ptr) jpeg, JPOOL_PERMANENT, sizeof(struct _jpeg_dest_manager_t)
)));
}
dest = (struct _mjpg_destination_mgr *) jpeg->dest;
dest = (struct _jpeg_dest_manager_t *)jpeg->dest;
dest->mgr.init_destination = _jpeg_init_destination;
dest->mgr.empty_output_buffer = _jpeg_empty_output_buffer;
dest->mgr.term_destination = _jpeg_term_destination;
@@ -136,13 +134,15 @@ static void _jpeg_set_dest_picture(j_compress_ptr jpeg, unsigned char *picture,
#define NORM_COMPONENT(_x) (((_x) > 255) ? 255 : (((_x) < 0) ? 0 : (_x)))
static void _jpeg_write_scanlines_yuyv(
struct jpeg_compress_struct *jpeg,
unsigned char *line_buffer, const unsigned char *data,
struct jpeg_compress_struct *jpeg, const unsigned char *data,
unsigned width, unsigned height) {
unsigned char *line_buffer;
JSAMPROW scanlines[1];
unsigned z = 0;
A_CALLOC(line_buffer, width * 3);
while (jpeg->next_scanline < height) {
unsigned char *ptr = line_buffer;
@@ -168,17 +168,21 @@ static void _jpeg_write_scanlines_yuyv(
scanlines[0] = line_buffer;
jpeg_write_scanlines(jpeg, scanlines, 1);
}
free(line_buffer);
}
static void _jpeg_write_scanlines_uyvy(
struct jpeg_compress_struct *jpeg,
unsigned char *line_buffer, const unsigned char *data,
struct jpeg_compress_struct *jpeg, const unsigned char *data,
unsigned width, unsigned height) {
unsigned char *line_buffer;
JSAMPROW scanlines[1];
unsigned z = 0;
while(jpeg->next_scanline < height) {
A_CALLOC(line_buffer, width * 3);
while (jpeg->next_scanline < height) {
unsigned char *ptr = line_buffer;
for(unsigned x = 0; x < width; ++x) {
@@ -203,18 +207,22 @@ static void _jpeg_write_scanlines_uyvy(
scanlines[0] = line_buffer;
jpeg_write_scanlines(jpeg, scanlines, 1);
}
free(line_buffer);
}
#undef NORM_COMPONENT
static void _jpeg_write_scanlines_rgb565(
struct jpeg_compress_struct *jpeg,
unsigned char *line_buffer, const unsigned char *data,
struct jpeg_compress_struct *jpeg, const unsigned char *data,
unsigned width, unsigned height) {
unsigned char *line_buffer;
JSAMPROW scanlines[1];
while(jpeg->next_scanline < height) {
A_CALLOC(line_buffer, width * 3);
while (jpeg->next_scanline < height) {
unsigned char *ptr = line_buffer;
for(unsigned x = 0; x < width; ++x) {
@@ -230,12 +238,26 @@ static void _jpeg_write_scanlines_rgb565(
scanlines[0] = line_buffer;
jpeg_write_scanlines(jpeg, scanlines, 1);
}
free(line_buffer);
}
static void _jpeg_write_scanlines_rgb24(
struct jpeg_compress_struct *jpeg, const unsigned char *data,
unsigned width, unsigned height) {
JSAMPROW scanlines[1];
while (jpeg->next_scanline < height) {
scanlines[0] = (unsigned char *)(data + jpeg->next_scanline * width * 3);
jpeg_write_scanlines(jpeg, scanlines, 1);
}
}
#define JPEG_OUTPUT_BUFFER_SIZE 4096
static void _jpeg_init_destination(j_compress_ptr jpeg) {
struct _mjpg_destination_mgr *dest = (struct _mjpg_destination_mgr *) jpeg->dest;
struct _jpeg_dest_manager_t *dest = (struct _jpeg_dest_manager_t *)jpeg->dest;
// Allocate the output buffer - it will be released when done with image
assert((dest->buffer = (JOCTET *)(*jpeg->mem->alloc_small)(
@@ -249,7 +271,7 @@ static void _jpeg_init_destination(j_compress_ptr jpeg) {
static boolean _jpeg_empty_output_buffer(j_compress_ptr jpeg) {
// Called whenever local jpeg buffer fills up
struct _mjpg_destination_mgr *dest = (struct _mjpg_destination_mgr *) jpeg->dest;
struct _jpeg_dest_manager_t *dest = (struct _jpeg_dest_manager_t *)jpeg->dest;
memcpy(dest->outbuffer_cursor, dest->buffer, JPEG_OUTPUT_BUFFER_SIZE);
dest->outbuffer_cursor += JPEG_OUTPUT_BUFFER_SIZE;
@@ -265,7 +287,7 @@ static void _jpeg_term_destination(j_compress_ptr jpeg) {
// Called by jpeg_finish_compress after all data has been written.
// Usually needs to flush buffer
struct _mjpg_destination_mgr *dest = (struct _mjpg_destination_mgr *) jpeg->dest;
struct _jpeg_dest_manager_t *dest = (struct _jpeg_dest_manager_t *)jpeg->dest;
size_t data_count = JPEG_OUTPUT_BUFFER_SIZE - dest->mgr.free_in_buffer;
// Write any data remaining in the buffer

View File

@@ -22,7 +22,7 @@
#pragma once
#include "../device.h"
#include "../../device.h"
void jpeg_encoder_compress_buffer(struct device_t *dev, unsigned index, unsigned quality);
void cpu_encoder_compress_buffer(struct device_t *dev, unsigned index, unsigned quality);

View File

@@ -25,10 +25,10 @@
#include <linux/videodev2.h>
#include "../tools.h"
#include "../logging.h"
#include "../xioctl.h"
#include "../device.h"
#include "../../tools.h"
#include "../../logging.h"
#include "../../xioctl.h"
#include "../../device.h"
int hw_encoder_prepare_live(struct device_t *dev, unsigned quality) {
@@ -37,12 +37,12 @@ int hw_encoder_prepare_live(struct device_t *dev, unsigned quality) {
MEMSET_ZERO(comp);
if (xioctl(dev->run->fd, VIDIOC_G_JPEGCOMP, &comp) < 0) {
LOG_ERROR("Can't query HW JPEG compressor params and set quality (unsupported)");
LOG_ERROR("Can't query HW JPEG encoder params and set quality (unsupported)");
return -1;
}
comp.quality = quality;
if (xioctl(dev->run->fd, VIDIOC_S_JPEGCOMP, &comp) < 0) {
LOG_ERROR("Can't set HW JPEG compressor quality (unsopported)");
LOG_ERROR("Can't set HW JPEG encoder quality (unsopported)");
return -1;
}
return 0;
@@ -50,7 +50,7 @@ int hw_encoder_prepare_live(struct device_t *dev, unsigned quality) {
void hw_encoder_compress_buffer(struct device_t *dev, unsigned index) {
if (dev->run->format != V4L2_PIX_FMT_MJPEG && dev->run->format != V4L2_PIX_FMT_JPEG) {
assert(0 && "Unsupported input format for HW JPEG compressor");
assert(0 && "Unsupported input format for HW JPEG encoder");
}
assert(dev->run->pictures[index].allocated >= dev->run->hw_buffers[index].length);
memcpy(dev->run->pictures[index].data, dev->run->hw_buffers[index].start, dev->run->hw_buffers[index].length);

View File

@@ -22,7 +22,7 @@
#pragma once
#include "../device.h"
#include "../../device.h"
int hw_encoder_prepare_live(struct device_t *dev, unsigned quality);

View File

@@ -25,7 +25,7 @@
#include <IL/OMX_Core.h>
#include <IL/OMX_Component.h>
#include "../logging.h"
#include "../../logging.h"
#include "formatters.h"
#include "component.h"

View File

@@ -33,9 +33,9 @@
#include <IL/OMX_Broadcom.h>
#include <interface/vcos/vcos_semaphore.h>
#include "../logging.h"
#include "../tools.h"
#include "../device.h"
#include "../../logging.h"
#include "../../tools.h"
#include "../../device.h"
#include "formatters.h"
#include "component.h"
@@ -173,7 +173,8 @@ int omx_encoder_prepare_live(struct omx_encoder_t *omx, struct device_t *dev, un
int omx_encoder_compress_buffer(struct omx_encoder_t *omx, struct device_t *dev, unsigned index) {
OMX_ERRORTYPE error;
bool loaded = false;
unsigned slice_size = omx->input_buffer->nAllocLen;
unsigned pos = 0;
if ((error = OMX_FillThisBuffer(omx->encoder, omx->output_buffer)) != OMX_ErrorNone) {
LOG_OMX_ERROR(error, "Failed to request filling of the output buffer on encoder");
@@ -194,7 +195,7 @@ int omx_encoder_compress_buffer(struct omx_encoder_t *omx, struct device_t *dev,
memcpy(
dev->run->pictures[index].data + dev->run->pictures[index].size,
omx->output_buffer->pBuffer,
omx->output_buffer->pBuffer + omx->output_buffer->nOffset,
omx->output_buffer->nFilledLen
);
assert(dev->run->pictures[index].size + omx->output_buffer->nFilledLen <= dev->run->max_picture_size);
@@ -213,14 +214,20 @@ int omx_encoder_compress_buffer(struct omx_encoder_t *omx, struct device_t *dev,
if (omx->input_required) {
omx->input_required = false;
if (loaded) {
if (pos == dev->run->hw_buffers[index].length) {
continue;
}
loaded = true;
memcpy(omx->input_buffer->pBuffer, dev->run->hw_buffers[index].start, dev->run->hw_buffers[index].length);
memcpy(omx->input_buffer->pBuffer, dev->run->hw_buffers[index].start + pos, slice_size);
omx->input_buffer->nOffset = 0;
omx->input_buffer->nFilledLen = dev->run->hw_buffers[index].length;
omx->input_buffer->nFilledLen = slice_size;
pos += slice_size;
if (pos + slice_size > dev->run->hw_buffers[index].length) {
slice_size = dev->run->hw_buffers[index].length - pos;
}
if ((error = OMX_EmptyThisBuffer(omx->encoder, omx->input_buffer)) != OMX_ErrorNone) {
LOG_OMX_ERROR(error, "Failed to request emptying of the input buffer on encoder");
@@ -295,23 +302,32 @@ static int _omx_setup_input(struct omx_encoder_t *omx, struct device_t *dev) {
portdef.format.image.nFrameWidth = dev->run->width;
portdef.format.image.nFrameHeight = dev->run->height;
portdef.format.image.nStride = 0;
# define ALIGN(_x, _y) (((_x) + ((_y) - 1)) & ~((_y) - 1))
portdef.format.image.nSliceHeight = ALIGN(dev->run->height, 16);
# undef ALIGN
# define ALIGN_HEIGHT(_x, _y) (((_x) + ((_y) - 1)) & ~((_y) - 1))
portdef.format.image.nSliceHeight = ALIGN_HEIGHT(dev->run->height, 16);
# undef ALIGN_HEIGHT
portdef.format.image.bFlagErrorConcealment = OMX_FALSE;
portdef.format.image.eCompressionFormat = OMX_IMAGE_CodingUnused;
portdef.nBufferSize = dev->run->max_picture_size;
# 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
case V4L2_PIX_FMT_YUYV: portdef.format.image.eColorFormat = OMX_COLOR_FormatYCbYCr; break;
case V4L2_PIX_FMT_UYVY: portdef.format.image.eColorFormat = OMX_COLOR_FormatCbYCrY; break;
case V4L2_PIX_FMT_RGB565: portdef.format.image.eColorFormat = OMX_COLOR_Format16bitRGB565; break;
// TODO: Check RGB565 + OMX. I don't have any USB devices which supports it.
default: assert(0 && "Unsupported input format for OMX JPEG compressor");
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);
// TODO: найти устройство с RGB565 и протестить его.
// FIXME: RGB24 не работает нормально, нижняя половина экрана зеленая.
// FIXME: Китайский EasyCap тоже не работает, мусор на экране.
// Вероятно обе проблемы вызваны некорректной реализацией OMX на пае.
default: assert(0 && "Unsupported input format for OMX JPEG encoder");
}
# undef MAP_FORMAT
if (component_set_portdef(&omx->encoder, &portdef) < 0) {
return -1;
}

View File

@@ -27,7 +27,7 @@
#include <IL/OMX_Component.h>
#include <interface/vcos/vcos_semaphore.h>
#include "../device.h"
#include "../../device.h"
#define OMX_MAX_ENCODERS 3

View File

@@ -26,7 +26,7 @@
#include <IL/OMX_IVCommon.h>
#include <IL/OMX_Core.h>
#include "../tools.h"
#include "../../tools.h"
#include "formatters.h"

View File

@@ -30,8 +30,8 @@
#include <IL/OMX_Core.h>
#include <IL/OMX_Image.h>
#include "../logging.h"
#include "../tools.h"
#include "../../logging.h"
#include "../../tools.h"
#define LOG_OMX_ERROR(_error, _msg, ...) { \

View File

@@ -36,8 +36,6 @@
#include "encoder.h"
#include "stream.h"
#include "jpeg/encoder.h"
static long double _stream_get_fluency_delay(struct device_t *dev, struct workers_pool_t *pool);
static void _stream_expose_picture(struct stream_t *stream, unsigned buf_index);