dump as json

This commit is contained in:
Devaev Maxim
2021-01-07 09:44:39 +03:00
parent 0fbb41752e
commit d5275cacf7
5 changed files with 76 additions and 42 deletions

View File

@@ -11,12 +11,14 @@
#include "../libs/logging.h"
#include "../libs/frame.h"
#include "../libs/memsink.h"
#include "../libs/base64.h"
enum _OPT_VALUES {
_O_SINK = 's',
_O_TIMEOUT = 't',
_O_SINK_TIMEOUT = 't',
_O_OUTPUT = 'o',
_O_OUTPUT_JSON = 'j',
_O_HELP = 'h',
_O_VERSION = 'v',
@@ -31,8 +33,9 @@ enum _OPT_VALUES {
static const struct option _LONG_OPTS[] = {
{"sink", required_argument, NULL, _O_SINK},
{"output", no_argument, NULL, _O_OUTPUT},
{"timeout", required_argument, NULL, _O_TIMEOUT},
{"sink-timeout", required_argument, NULL, _O_SINK_TIMEOUT},
{"output", required_argument, NULL, _O_OUTPUT},
{"output-json", no_argument, NULL, _O_OUTPUT_JSON},
{"log-level", required_argument, NULL, _O_LOG_LEVEL},
{"perf", no_argument, NULL, _O_PERF},
@@ -53,7 +56,9 @@ volatile bool stop = false;
static void _signal_handler(int signum);
static void _install_signal_handlers(void);
static int _dump_sink(const char *sink_name, const char *output_path, unsigned timeout);
static int _dump_sink(const char *sink_name, unsigned sink_timeout, const char *output_path, bool output_json);
static void _help(FILE *fp);
@@ -62,8 +67,9 @@ int main(int argc, char *argv[]) {
A_THREAD_RENAME("main");
char *sink_name = NULL;
unsigned sink_timeout = 1;
char *output_path = NULL;
unsigned timeout = 1;
bool output_json = false;
# define OPT_SET(_dest, _value) { \
_dest = _value; \
@@ -80,11 +86,12 @@ int main(int argc, char *argv[]) {
break; \
}
for (int ch; (ch = getopt_long(argc, argv, "s:o:t:hv", _LONG_OPTS, NULL)) >= 0;) {
for (int ch; (ch = getopt_long(argc, argv, "s:t:o:jhv", _LONG_OPTS, NULL)) >= 0;) {
switch (ch) {
case _O_SINK: OPT_SET(sink_name, optarg);
case _O_OUTPUT: OPT_SET(output_path, optarg);
case _O_TIMEOUT: OPT_NUMBER("--timeout", timeout, 1, 60, 0);
case _O_SINK: OPT_SET(sink_name, optarg);
case _O_SINK_TIMEOUT: OPT_NUMBER("--sink-timeout", sink_timeout, 1, 60, 0);
case _O_OUTPUT: OPT_SET(output_path, optarg);
case _O_OUTPUT_JSON: OPT_SET(output_json, true);
case _O_LOG_LEVEL: OPT_NUMBER("--log-level", log_level, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, 0);
case _O_PERF: OPT_SET(log_level, LOG_LEVEL_PERF);
@@ -110,7 +117,7 @@ int main(int argc, char *argv[]) {
}
_install_signal_handlers();
return abs(_dump_sink(sink_name, output_path, timeout));
return abs(_dump_sink(sink_name, sink_timeout, output_path, output_json));
}
@@ -144,10 +151,12 @@ static void _install_signal_handlers(void) {
assert(!sigaction(SIGPIPE, &sig_act, NULL));
}
static int _dump_sink(const char *sink_name, const char *output_path, unsigned timeout) {
static int _dump_sink(const char *sink_name, unsigned sink_timeout, const char *output_path, bool output_json) {
frame_s *frame = frame_init("input");
FILE *output_fp = NULL;
memsink_s *sink = NULL;
FILE *output_fp = NULL;
char *base64_data = NULL;
size_t base64_allocated = 0;
if (output_path && output_path[0] != '\0') {
if (!strcmp(output_path, "-")) {
@@ -162,7 +171,7 @@ static int _dump_sink(const char *sink_name, const char *output_path, unsigned t
}
}
if ((sink = memsink_init("input", sink_name, false, 0, false, timeout)) == NULL) {
if ((sink = memsink_init("input", sink_name, false, 0, false, sink_timeout)) == NULL) {
goto error;
}
@@ -191,7 +200,20 @@ static int _dump_sink(const char *sink_name, const char *output_path, unsigned t
fps_accum += 1;
if (output_fp) {
fwrite(frame->data, 1, frame->used, output_fp);
if (output_json) {
base64_encode(frame->data, frame->used, &base64_data, &base64_allocated);
fprintf(output_fp,
"{\"size\": %zu, \"width\": %u, \"height\": %u,"
" \"format\": %u, \"stride\": %u, \"online\": %u,"
" \"grab_ts\": %.3Lf, \"encode_begin_ts\": %.3Lf, \"encode_end_ts\": %.3Lf,"
" \"data\": \"%s\"}\n",
frame->used, frame->width, frame->height,
frame->format, frame->stride, frame->online,
frame->grab_ts, frame->encode_begin_ts, frame->encode_end_ts,
base64_data);
} else {
fwrite(frame->data, 1, frame->used, output_fp);
}
fflush(output_fp);
}
} else if (error != -2) {
@@ -206,14 +228,17 @@ static int _dump_sink(const char *sink_name, const char *output_path, unsigned t
retval = -1;
ok:
if (sink) {
memsink_destroy(sink);
if (base64_data) {
free(base64_data);
}
if (output_fp && output_fp != stdout) {
if (fclose(output_fp) < 0) {
LOG_PERROR("Can't close output file");
}
}
if (sink) {
memsink_destroy(sink);
}
frame_destroy(frame);
LOG_INFO("Bye-bye");
@@ -228,13 +253,14 @@ static void _help(FILE *fp) {
SAY("Copyright (C) 2018 Maxim Devaev <mdevaev@gmail.com>\n");
SAY("Example:");
SAY("════════");
SAY(" ustreamer-dump --sink test -o - \\");
SAY(" ustreamer-dump --sink test --output - \\");
SAY(" | ffmpeg -use_wallclock_as_timestamps 1 -i pipe: -c:v libx264 test.mp4\n");
SAY("Sink options:");
SAY("═════════════");
SAY(" -s|--sink <name> ─── Memory sink ID. No default.\n");
SAY(" -t|--timeout <sec> ─ Timeout for the upcoming frame. Default: 1.\n");
SAY(" -o|--output ──────── Filename to dump. Use '-' for stdout. Default: just consume the sink.\n");
SAY(" -s|--sink <name> ──────── Memory sink ID. No default.\n");
SAY(" -t|--sink-timeout <sec> ─ Timeout for the upcoming frame. Default: 1.\n");
SAY(" -o|--output ───────────── Filename to dump. Use '-' for stdout. Default: just consume the sink.\n");
SAY(" -j|--output-json ──────── Format output as JSON. Required option --output.\n");
SAY("Logging options:");
SAY("════════════════");
SAY(" --log-level <N> ──── Verbosity level of messages from 0 (info) to 3 (debug).");

View File

@@ -37,30 +37,36 @@ static const char _ENCODING_TABLE[] = {
static const unsigned _MOD_TABLE[] = {0, 2, 1};
char *base64_encode(const uint8_t *str) {
size_t str_len = strlen((const char *)str);
size_t encoded_size = 4 * ((str_len + 2) / 3) + 1; // +1 for '\0'
void base64_encode(const uint8_t *data, size_t size, char **encoded, size_t *allocated) {
const size_t encoded_size = 4 * ((size + 2) / 3) + 1; // +1 for '\0'
char *encoded;
A_CALLOC(encoded, encoded_size);
if (*encoded == NULL || (allocated && *allocated < encoded_size)) {
A_REALLOC(*encoded, encoded_size);
if (allocated) {
*allocated = encoded_size;
}
}
for (unsigned str_index = 0, encoded_index = 0; str_index < str_len;) {
unsigned octet_a = (str_index < str_len ? (uint8_t)str[str_index++] : 0);
unsigned octet_b = (str_index < str_len ? (uint8_t)str[str_index++] : 0);
unsigned octet_c = (str_index < str_len ? (uint8_t)str[str_index++] : 0);
for (unsigned data_index = 0, encoded_index = 0; data_index < size;) {
# define OCTET(_name) unsigned _name = (data_index < size ? (uint8_t)data[data_index++] : 0)
OCTET(octet_a);
OCTET(octet_b);
OCTET(octet_c);
# undef OCTET
unsigned triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
encoded[encoded_index++] = _ENCODING_TABLE[(triple >> 3 * 6) & 0x3F];
encoded[encoded_index++] = _ENCODING_TABLE[(triple >> 2 * 6) & 0x3F];
encoded[encoded_index++] = _ENCODING_TABLE[(triple >> 1 * 6) & 0x3F];
encoded[encoded_index++] = _ENCODING_TABLE[(triple >> 0 * 6) & 0x3F];
# define ENCODE(_offset) (*encoded)[encoded_index++] = _ENCODING_TABLE[(triple >> _offset * 6) & 0x3F]
ENCODE(3);
ENCODE(2);
ENCODE(1);
ENCODE(0);
# undef ENCODE
}
for (unsigned index = 0; index < _MOD_TABLE[str_len % 3]; index++) {
encoded[encoded_size - 2 - index] = '=';
for (unsigned index = 0; index < _MOD_TABLE[size % 3]; index++) {
(*encoded)[encoded_size - 2 - index] = '=';
}
encoded[encoded_size - 1] = '\0';
return encoded;
(*encoded)[encoded_size - 1] = '\0';
}

View File

@@ -26,7 +26,9 @@
#include <stdint.h>
#include <string.h>
#include "../../libs/tools.h"
#include <sys/types.h>
#include "tools.h"
char *base64_encode(const uint8_t *str);
void base64_encode(const uint8_t *data, size_t size, char **encoded, size_t *allocated);

View File

@@ -149,11 +149,11 @@ int server_listen(server_s *server) {
if (server->user[0] != '\0') {
char *raw_token;
char *encoded_token;
char *encoded_token = NULL;
A_CALLOC(raw_token, strlen(server->user) + strlen(server->passwd) + 2);
sprintf(raw_token, "%s:%s", server->user, server->passwd);
encoded_token = base64_encode((uint8_t *)raw_token);
base64_encode((uint8_t *)raw_token, strlen(raw_token), &encoded_token, NULL);
free(raw_token);
A_CALLOC(RUN(auth_token), strlen(encoded_token) + 16);

View File

@@ -58,6 +58,7 @@
#include "../../libs/logging.h"
#include "../../libs/process.h"
#include "../../libs/frame.h"
#include "../../libs/base64.h"
#include "../data/index_html.h"
#include "../encoder.h"
#include "../stream.h"
@@ -68,7 +69,6 @@
#include "bev.h"
#include "unix.h"
#include "uri.h"
#include "base64.h"
#include "mime.h"
#include "static.h"