mirror of
https://github.com/pikvm/ustreamer.git
synced 2026-02-18 02:55:46 +00:00
various fixes
This commit is contained in:
parent
c2b82312ec
commit
0717d2ee6a
@ -28,8 +28,11 @@
|
||||
#include <linux/videodev2.h>
|
||||
|
||||
|
||||
#define FORMAT_UNKNOWN -1
|
||||
#define STANDARD_UNKNOWN V4L2_STD_UNKNOWN
|
||||
#define STANDARDS_STR "UNKNOWN, PAL, NTSC, SECAM"
|
||||
|
||||
#define FORMAT_UNKNOWN -1
|
||||
#define FORMATS_STR "YUYV, UYVY, RGB565"
|
||||
|
||||
|
||||
struct hw_buffer_t {
|
||||
|
||||
@ -19,6 +19,9 @@
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#include <strings.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "tools.h"
|
||||
#include "device.h"
|
||||
#include "encoder.h"
|
||||
@ -29,12 +32,29 @@
|
||||
# include "omx/encoder.h"
|
||||
#endif
|
||||
|
||||
|
||||
static const struct {
|
||||
const char *name;
|
||||
const enum encoder_type_t type;
|
||||
} ENCODER_TYPES[] = {
|
||||
{"CPU", ENCODER_TYPE_CPU},
|
||||
# ifdef OMX_ENCODER
|
||||
{"OMX", ENCODER_TYPE_OMX},
|
||||
# endif
|
||||
};
|
||||
|
||||
|
||||
struct encoder_t *encoder_init(enum encoder_type_t type) {
|
||||
struct encoder_t *encoder;
|
||||
|
||||
assert(type != ENCODER_TYPE_UNKNOWN);
|
||||
A_CALLOC(encoder, 1);
|
||||
encoder->type = type;
|
||||
|
||||
if (encoder->type != ENCODER_TYPE_CPU) {
|
||||
LOG_DEBUG("Initializing encoder ...");
|
||||
}
|
||||
|
||||
# ifdef OMX_ENCODER
|
||||
if (type == ENCODER_TYPE_OMX) {
|
||||
if ((encoder->omx = omx_encoder_init()) == NULL) {
|
||||
@ -63,6 +83,15 @@ void encoder_destroy(struct encoder_t *encoder) {
|
||||
free(encoder);
|
||||
}
|
||||
|
||||
enum encoder_type_t encoder_parse_type(const char *const str) {
|
||||
for (unsigned index = 0; index < sizeof(ENCODER_TYPES) / sizeof(ENCODER_TYPES[0]); ++index) {
|
||||
if (!strcasecmp(str, ENCODER_TYPES[index].name)) {
|
||||
return ENCODER_TYPES[index].type;
|
||||
}
|
||||
}
|
||||
return ENCODER_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
#pragma GCC diagnostic push
|
||||
void encoder_prepare(struct encoder_t *encoder, struct device_t *dev) {
|
||||
@ -72,10 +101,10 @@ void encoder_prepare(struct encoder_t *encoder, struct device_t *dev) {
|
||||
if (omx_encoder_prepare(encoder->omx, dev) < 0) {
|
||||
goto use_fallback;
|
||||
}
|
||||
}
|
||||
if (dev->run->n_workers > 1) {
|
||||
LOG_INFO("OMX encoder can only work with one worker thread; forcing n_workers to 1");
|
||||
dev->run->n_workers = 1;
|
||||
if (dev->run->n_workers > 1) {
|
||||
LOG_INFO("OMX encoder can only work with one worker thread; forcing n_workers to 1");
|
||||
dev->run->n_workers = 1;
|
||||
}
|
||||
}
|
||||
# endif
|
||||
|
||||
@ -86,20 +115,29 @@ void encoder_prepare(struct encoder_t *encoder, struct device_t *dev) {
|
||||
use_fallback:
|
||||
LOG_ERROR("Can't prepare selected encoder, falling back to CPU");
|
||||
encoder->type = ENCODER_TYPE_CPU;
|
||||
dev->run->n_workers = dev->n_workers;
|
||||
# pragma GCC diagnostic pop
|
||||
}
|
||||
|
||||
void encoder_compress_buffer(struct encoder_t *encoder, struct device_t *dev, int index) {
|
||||
# ifdef OMX_ENCODER
|
||||
if (encoder->type == ENCODER_TYPE_OMX) {
|
||||
if (omx_encoder_compress_buffer(encoder->omx, dev, index) < 0) {
|
||||
LOG_INFO("OMX compressor error, falling back to CPU method");
|
||||
encoder->type = ENCODER_TYPE_CPU;
|
||||
}
|
||||
}
|
||||
# endif
|
||||
|
||||
int encoder_compress_buffer(struct encoder_t *encoder, struct device_t *dev, int index) {
|
||||
if (encoder->type == ENCODER_TYPE_CPU) {
|
||||
jpeg_encoder_compress_buffer(dev, index);
|
||||
}
|
||||
# ifdef OMX_ENCODER
|
||||
else if (encoder->type == ENCODER_TYPE_OMX) {
|
||||
if (omx_encoder_compress_buffer(encoder->omx, dev, index) < 0) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
# endif
|
||||
return 0;
|
||||
|
||||
# pragma GCC diagnostic ignored "-Wunused-label"
|
||||
# pragma GCC diagnostic push
|
||||
error:
|
||||
LOG_INFO("HW compressing error, falling back to CPU");
|
||||
encoder->type = ENCODER_TYPE_CPU;
|
||||
dev->run->n_workers = dev->n_workers;
|
||||
return -1;
|
||||
# pragma GCC diagnostic pop
|
||||
}
|
||||
|
||||
@ -29,7 +29,20 @@
|
||||
#endif
|
||||
|
||||
|
||||
#define ENCODER_TYPES_STR "CPU"
|
||||
#define PUSH _Pragma("push_macro(\"ENCODER_TYPES_STR\")")
|
||||
#define POP _Pragma("pop_macro(\"ENCODER_TYPES_STR\")")
|
||||
#ifdef OMX_ENCODER
|
||||
PUSH
|
||||
# undef ENCODER_TYPES_STR
|
||||
# define ENCODER_TYPES_STR POP ENCODER_TYPES_STR ", OMX"
|
||||
#endif
|
||||
#undef PUSH
|
||||
#undef POP
|
||||
|
||||
|
||||
enum encoder_type_t {
|
||||
ENCODER_TYPE_UNKNOWN, // Only for encoder_parse_type() and main()
|
||||
ENCODER_TYPE_CPU,
|
||||
|
||||
#ifdef OMX_ENCODER
|
||||
@ -49,5 +62,7 @@ struct encoder_t {
|
||||
struct encoder_t *encoder_init(enum encoder_type_t type);
|
||||
void encoder_destroy(struct encoder_t *encoder);
|
||||
|
||||
enum encoder_type_t encoder_parse_type(const char *const str);
|
||||
|
||||
void encoder_prepare(struct encoder_t *encoder, struct device_t *dev);
|
||||
void encoder_compress_buffer(struct encoder_t *encoder, struct device_t *dev, int index);
|
||||
int encoder_compress_buffer(struct encoder_t *encoder, struct device_t *dev, int index);
|
||||
|
||||
@ -21,9 +21,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "../device.h"
|
||||
|
||||
|
||||
|
||||
54
src/main.c
54
src/main.c
@ -40,7 +40,7 @@
|
||||
#include "http.h"
|
||||
|
||||
|
||||
static const char _short_opts[] = "d:x:y:f:a:e:z:tn:w:q:s:p:h";
|
||||
static const char _short_opts[] = "d:x:y:f:a:e:z:tn:w:q:c:s:p:h";
|
||||
static const struct option _long_opts[] = {
|
||||
{"device", required_argument, NULL, 'd'},
|
||||
{"width", required_argument, NULL, 'x'},
|
||||
@ -50,9 +50,10 @@ static const struct option _long_opts[] = {
|
||||
{"every-frame", required_argument, NULL, 'e'},
|
||||
{"min-frame-size", required_argument, NULL, 'z'},
|
||||
{"dv-timings", no_argument, NULL, 't'},
|
||||
{"buffers", required_argument, NULL, 'n'},
|
||||
{"buffers", required_argument, NULL, 'b'},
|
||||
{"workers", required_argument, NULL, 'w'},
|
||||
{"jpeg-quality", required_argument, NULL, 'q'},
|
||||
{"encoder", required_argument, NULL, 'c'},
|
||||
{"device-timeout", required_argument, NULL, 1000},
|
||||
{"device-error-timeout", required_argument, NULL, 1001},
|
||||
|
||||
@ -73,24 +74,28 @@ static void _help(struct device_t *dev, struct http_server_t *server) {
|
||||
printf("Copyright (C) 2018 Maxim Devaev <mdevaev@gmail.com>\n\n");
|
||||
printf("Capturing options:\n");
|
||||
printf("------------------\n");
|
||||
printf(" -d|--device </dev/path> -- Path to V4L2 device. Default: %s\n\n", dev->path);
|
||||
printf(" -x|--width <N> -- Initial image width. Default: %d\n\n", dev->width);
|
||||
printf(" -y|--height <N> -- Initial image height. Default: %d\n\n", dev->height);
|
||||
printf(" -f|--format <YUYV|UYVY|RGB565> -- Image format. Default: YUYV.\n\n");
|
||||
printf(" -a|--tv-standard <PAL|NTSC|SECAM> -- Force TV standard. Default: disabled.\n\n");
|
||||
printf(" -e|--every-frame <N> -- Drop all input frames except specified. Default: disabled.\n\n");
|
||||
printf(" -z|--min-frame-size <N> -- Drop frames smaller then this limit.\n");
|
||||
printf(" Useful if the device produces small-sized garbage frames.\n\n");
|
||||
printf(" -t|--dv-timings -- Enable DV timings queriyng and events processing.\n");
|
||||
printf(" Supports automatic resolution changing. Default: disabled.\n\n");
|
||||
printf(" -n|--buffers <N> -- The number of buffers to receive data from the device.\n");
|
||||
printf(" Each buffer may processed using an intermediate thread.\n");
|
||||
printf(" Default: %d (number of CPU cores + 1)\n\n", dev->n_buffers);
|
||||
printf(" -w|--workers <N> -- The number of compressing threads. Default: %d (== --buffers).\n\n", dev->n_workers);
|
||||
printf(" -q|--jpeg-quality <N> -- Set quality of JPEG encoding from 1 to 100 (best). Default: %d\n\n", dev->jpeg_quality);
|
||||
printf(" --device-timeout <seconds> -- Timeout for device querying. Default: %d\n\n", dev->timeout);
|
||||
printf(" --device-error-timeout <seconds> -- Delay before trying to connect to the device again\n");
|
||||
printf(" after a timeout. Default: %d\n\n", dev->error_timeout);
|
||||
printf(" -d|--device </dev/path> -- Path to V4L2 device. Default: %s\n\n", dev->path);
|
||||
printf(" -x|--width <N> -- Initial image width. Default: %d\n\n", dev->width);
|
||||
printf(" -y|--height <N> -- Initial image height. Default: %d\n\n", dev->height);
|
||||
printf(" -f|--format <fmt> -- Image format.\n");
|
||||
printf(" Available: %s; default: YUYV.\n\n", FORMATS_STR);
|
||||
printf(" -a|--tv-standard <std> -- Force TV standard.\n");
|
||||
printf(" Available: %s; default: disabled.\n\n", STANDARDS_STR);
|
||||
printf(" -e|--every-frame <N> -- Drop all input frames except specified. Default: disabled.\n\n");
|
||||
printf(" -z|--min-frame-size <N> -- Drop frames smaller then this limit.\n");
|
||||
printf(" Useful if the device produces small-sized garbage frames.\n\n");
|
||||
printf(" -t|--dv-timings -- Enable DV timings queriyng and events processing.\n");
|
||||
printf(" Supports automatic resolution changing. Default: disabled.\n\n");
|
||||
printf(" -b|--buffers <N> -- The number of buffers to receive data from the device.\n");
|
||||
printf(" Each buffer may processed using an intermediate thread.\n");
|
||||
printf(" Default: %d (number of CPU cores + 1)\n\n", dev->n_buffers);
|
||||
printf(" -w|--workers <N> -- The number of compressing threads. Default: %d (== --buffers).\n\n", dev->n_workers);
|
||||
printf(" -q|--jpeg-quality <N> -- Set quality of JPEG encoding from 1 to 100 (best). Default: %d\n\n", dev->jpeg_quality);
|
||||
printf(" --encoder <type> -- Use specified encoder. It may affects to workers number.\n");
|
||||
printf(" -- Available: %s; default: CPU.\n\n", ENCODER_TYPES_STR);
|
||||
printf(" --device-timeout <seconds> -- Timeout for device querying. Default: %d\n\n", dev->timeout);
|
||||
printf(" --device-error-timeout <seconds> -- Delay before trying to connect to the device again\n");
|
||||
printf(" after a timeout. Default: %d\n\n", dev->error_timeout);
|
||||
printf("HTTP server options:\n");
|
||||
printf("--------------------\n");
|
||||
printf(" --host <address> -- Listen on Hostname or IP. Default: %s\n\n", server->host);
|
||||
@ -106,7 +111,7 @@ static void _help(struct device_t *dev, struct http_server_t *server) {
|
||||
printf(" -h|--help -- Print this messages and exit\n\n");
|
||||
}
|
||||
|
||||
static int _parse_options(int argc, char *argv[], struct device_t *dev, struct http_server_t *server) {
|
||||
static int _parse_options(int argc, char *argv[], struct device_t *dev, struct encoder_t *encoder, struct http_server_t *server) {
|
||||
# define OPT_ARG(_dest) \
|
||||
{ _dest = optarg; break; }
|
||||
|
||||
@ -114,7 +119,7 @@ static int _parse_options(int argc, char *argv[], struct device_t *dev, struct h
|
||||
{ _dest = true; break; }
|
||||
|
||||
# define OPT_UNSIGNED(_dest, _name, _min, _max) \
|
||||
{ int _tmp = strtol(optarg, NULL, 0); \
|
||||
{ errno = 0; int _tmp = strtol(optarg, NULL, 0); \
|
||||
if (errno || _tmp < _min || _tmp > _max) \
|
||||
{ printf("Invalid value for '%s=%u'; minimal=%u; maximum=%u\n", _name, _tmp, _min, _max); return -1; } \
|
||||
_dest = _tmp; break; }
|
||||
@ -141,9 +146,10 @@ static int _parse_options(int argc, char *argv[], struct device_t *dev, struct h
|
||||
case 'e': OPT_UNSIGNED(dev->every_frame, "--every-frame", 1, 30);
|
||||
case 'z': OPT_UNSIGNED(dev->min_frame_size, "--min-frame-size", 0, 8192);
|
||||
case 't': OPT_TRUE(dev->dv_timings);
|
||||
case 'n': OPT_UNSIGNED(dev->n_buffers, "--buffers", 1, 32);
|
||||
case 'b': OPT_UNSIGNED(dev->n_buffers, "--buffers", 1, 32);
|
||||
case 'w': OPT_UNSIGNED(dev->n_workers, "--workers", 1, 32);
|
||||
case 'q': OPT_UNSIGNED(dev->jpeg_quality, "--jpeg-quality", 1, 100);
|
||||
case 'c': OPT_PARSE(encoder->type, encoder_parse_type, ENCODER_TYPE_UNKNOWN, "encoder type")
|
||||
case 1000: OPT_UNSIGNED(dev->timeout, "--timeout", 1, 60);
|
||||
case 1001: OPT_UNSIGNED(dev->error_timeout, "--error-timeout", 1, 60);
|
||||
|
||||
@ -231,7 +237,7 @@ int main(int argc, char *argv[]) {
|
||||
stream = stream_init(dev, encoder);
|
||||
server = http_server_init(stream);
|
||||
|
||||
if ((exit_code = _parse_options(argc, argv, dev, server)) == 0) {
|
||||
if ((exit_code = _parse_options(argc, argv, dev, encoder, server)) == 0) {
|
||||
_install_signal_handlers();
|
||||
|
||||
pthread_t stream_loop_tid;
|
||||
|
||||
@ -1,3 +1,24 @@
|
||||
/*****************************************************************************
|
||||
# uStreamer - Lightweight and fast MJPG-HTTP streamer. #
|
||||
# #
|
||||
# Copyright (C) 2018 Maxim Devaev <mdevaev@gmail.com> #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <IL/OMX_Core.h>
|
||||
|
||||
@ -1,3 +1,24 @@
|
||||
/*****************************************************************************
|
||||
# uStreamer - Lightweight and fast MJPG-HTTP streamer. #
|
||||
# #
|
||||
# Copyright (C) 2018 Maxim Devaev <mdevaev@gmail.com> #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@ -1,3 +1,24 @@
|
||||
/*****************************************************************************
|
||||
# uStreamer - Lightweight and fast MJPG-HTTP streamer. #
|
||||
# #
|
||||
# Copyright (C) 2018 Maxim Devaev <mdevaev@gmail.com> #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
|
||||
@ -1,3 +1,24 @@
|
||||
/*****************************************************************************
|
||||
# uStreamer - Lightweight and fast MJPG-HTTP streamer. #
|
||||
# #
|
||||
# Copyright (C) 2018 Maxim Devaev <mdevaev@gmail.com> #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
@ -38,7 +38,6 @@
|
||||
assert(0 && _buf); \
|
||||
}
|
||||
|
||||
|
||||
const char *omx_error_to_string(const OMX_ERRORTYPE error) {
|
||||
switch (error) {
|
||||
CASE_TO_STRING(OMX_ErrorNone);
|
||||
@ -79,5 +78,5 @@ const char *omx_state_to_string(const OMX_STATETYPE state) {
|
||||
}
|
||||
}
|
||||
|
||||
#undef CASE_ASSERT
|
||||
#undef CASE_TO_STRING
|
||||
#undef CASE_ASSERT
|
||||
|
||||
@ -413,7 +413,9 @@ static void *_stream_worker_thread(void *v_ctx) {
|
||||
|
||||
LOG_DEBUG("Worker %u compressing JPEG from buffer %d ...", ctx->number, ctx->buf_index);
|
||||
|
||||
encoder_compress_buffer(ctx->encoder, ctx->dev, ctx->buf_index);
|
||||
if (encoder_compress_buffer(ctx->encoder, ctx->dev, ctx->buf_index) < 0) {
|
||||
*ctx->job_failed = true;
|
||||
}
|
||||
|
||||
if (_stream_release_buffer(ctx->dev, &ctx->buf_info) == 0) {
|
||||
*ctx->job_start_time = start_time;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user