From b61b78e161e39cbd6fa5755d0ff08dc984304f47 Mon Sep 17 00:00:00 2001 From: Moritz Grimm Date: Fri, 24 Jan 2020 23:27:02 +0100 Subject: [PATCH] Modernize stream format options Adds support for WebM/Matroska Replaces Vorbis and Theora with Ogg --- doc/ezstream.1.in.in | 12 +++-- examples/ezstream-file_template.xml | 4 +- examples/ezstream-full.xml | 6 +-- examples/ezstream-metadata.xml | 2 +- examples/ezstream-minimal.xml | 4 +- examples/ezstream-stdin.xml | 2 +- examples/ezstream-video.xml | 2 +- src/cfg_stream.c | 20 +++++--- src/cfg_stream.h | 14 +++--- src/ezstream-cfgmigrate.c | 75 +++++++++++++++++++++++------ src/stream.c | 21 +++++++- tests/check_cfg_encoder.c | 10 ++-- tests/check_cfg_stream.c | 28 ++++++----- 13 files changed, 138 insertions(+), 62 deletions(-) diff --git a/doc/ezstream.1.in.in b/doc/ezstream.1.in.in index c7b1e3b..97ac8a8 100644 --- a/doc/ezstream.1.in.in +++ b/doc/ezstream.1.in.in @@ -343,13 +343,15 @@ Default: .Pq Mandatory. The stream format. .Pp -.Bl -tag -width VORBIS -compact -.It Ar Vorbis -Ogg Vorbis audio format +.Bl -tag -width Matroska -compact +.It Ar Ogg +Ogg media format .It Ar MP3 MP3 audio format -.It Ar Theora -Ogg Theora video format +.It Ar WebM +WebM media format +.It Ar Matroska +Matroska media format .El .It Sy \& Use the encoder configuration with the provided symbolic name diff --git a/examples/ezstream-file_template.xml b/examples/ezstream-file_template.xml index d016648..832a5a6 100644 --- a/examples/ezstream-file_template.xml +++ b/examples/ezstream-file_template.xml @@ -21,7 +21,7 @@ /stream.ogg - Vorbis + Ogg OggEnc-Q1.5 @@ -56,7 +56,7 @@ OggEnc-Q1.5 - Vorbis + Ogg oggenc -r -B 16 -C 2 -R 44100 --raw-endianness 0 -q 1.5 -t @M@ - diff --git a/examples/ezstream-full.xml b/examples/ezstream-full.xml index 2cd4306..eaf94e2 100644 --- a/examples/ezstream-full.xml +++ b/examples/ezstream-full.xml @@ -100,8 +100,8 @@ --> No - - Vorbis + + Ogg OggEnc-Q1.5 @@ -198,7 +198,7 @@ OggEnc-Q1.5 - Vorbis + Ogg oggenc -r -B 16 -C 2 -R 44100 --raw-endianness 1 -q 1.5 -t @M@ - diff --git a/examples/ezstream-metadata.xml b/examples/ezstream-metadata.xml index 3a99f1f..54a95e5 100644 --- a/examples/ezstream-metadata.xml +++ b/examples/ezstream-metadata.xml @@ -16,7 +16,7 @@ /stream.ogg - Vorbis + Ogg diff --git a/examples/ezstream-minimal.xml b/examples/ezstream-minimal.xml index 747b9a2..2e8f7d4 100644 --- a/examples/ezstream-minimal.xml +++ b/examples/ezstream-minimal.xml @@ -3,7 +3,7 @@ @@ -18,7 +18,7 @@ /stream.ogg - Vorbis + Ogg diff --git a/examples/ezstream-stdin.xml b/examples/ezstream-stdin.xml index a11c1bc..d622d75 100644 --- a/examples/ezstream-stdin.xml +++ b/examples/ezstream-stdin.xml @@ -18,7 +18,7 @@ /stream.ogg - Vorbis + Ogg diff --git a/examples/ezstream-video.xml b/examples/ezstream-video.xml index 0ff1f4c..828bb40 100644 --- a/examples/ezstream-video.xml +++ b/examples/ezstream-video.xml @@ -16,7 +16,7 @@ /video.ogg - Theora + Ogg diff --git a/src/cfg_stream.c b/src/cfg_stream.c index 892e5e4..e48bd99 100644 --- a/src/cfg_stream.c +++ b/src/cfg_stream.c @@ -169,12 +169,14 @@ cfg_stream_destroy(struct cfg_stream **s_p) int cfg_stream_str2fmt(const char *str, enum cfg_stream_format *fmt_p) { - if (0 == strcasecmp(str, CFG_SFMT_VORBIS)) { - *fmt_p = CFG_STREAM_VORBIS; + if (0 == strcasecmp(str, CFG_SFMT_OGG)) { + *fmt_p = CFG_STREAM_OGG; } else if (0 == strcasecmp(str, CFG_SFMT_MP3)) { *fmt_p = CFG_STREAM_MP3; - } else if (0 == strcasecmp(str, CFG_SFMT_THEORA)) { - *fmt_p = CFG_STREAM_THEORA; + } else if (0 == strcasecmp(str, CFG_SFMT_WEBM)) { + *fmt_p = CFG_STREAM_WEBM; + } else if (0 == strcasecmp(str, CFG_SFMT_MATROSKA)) { + *fmt_p = CFG_STREAM_MATROSKA; } else return (-1); return (0); @@ -184,12 +186,14 @@ const char * cfg_stream_fmt2str(enum cfg_stream_format fmt) { switch (fmt) { - case CFG_STREAM_VORBIS: - return (CFG_SFMT_VORBIS); + case CFG_STREAM_OGG: + return (CFG_SFMT_OGG); case CFG_STREAM_MP3: return (CFG_SFMT_MP3); - case CFG_STREAM_THEORA: - return (CFG_SFMT_THEORA); + case CFG_STREAM_WEBM: + return (CFG_SFMT_WEBM); + case CFG_STREAM_MATROSKA: + return (CFG_SFMT_MATROSKA); default: return (NULL); } diff --git a/src/cfg_stream.h b/src/cfg_stream.h index bd9e6df..32da6d7 100644 --- a/src/cfg_stream.h +++ b/src/cfg_stream.h @@ -17,17 +17,19 @@ #ifndef __CFG_STREAM_H__ #define __CFG_STREAM_H__ -#define CFG_SFMT_VORBIS "VORBIS" +#define CFG_SFMT_OGG "Ogg" #define CFG_SFMT_MP3 "MP3" -#define CFG_SFMT_THEORA "THEORA" +#define CFG_SFMT_WEBM "WebM" +#define CFG_SFMT_MATROSKA "Matroska" enum cfg_stream_format { CFG_STREAM_INVALID = 0, - CFG_STREAM_VORBIS, + CFG_STREAM_OGG, CFG_STREAM_MP3, - CFG_STREAM_THEORA, - CFG_STREAM_MIN = CFG_STREAM_VORBIS, - CFG_STREAM_MAX = CFG_STREAM_THEORA, + CFG_STREAM_WEBM, + CFG_STREAM_MATROSKA, + CFG_STREAM_MIN = CFG_STREAM_OGG, + CFG_STREAM_MAX = CFG_STREAM_MATROSKA, }; typedef struct cfg_stream * cfg_stream_t; diff --git a/src/ezstream-cfgmigrate.c b/src/ezstream-cfgmigrate.c index b460f09..4561248 100644 --- a/src/ezstream-cfgmigrate.c +++ b/src/ezstream-cfgmigrate.c @@ -206,9 +206,15 @@ _parse_ezconfig0(EZCONFIG *ez) if (ez->password) ENTITY_SET(srv, srv_list, cfg_server_set_password, "", ez->password); - if (ez->format) - ENTITY_SET(str, str_list, cfg_stream_set_format, - "", ez->format); + if (ez->format) { + if (0 == strcasecmp(ez->format, "vorbis") || + 0 == strcasecmp(ez->format, "theora")) + ENTITY_SET(str, str_list, cfg_stream_set_format, + "", "Ogg"); + else + ENTITY_SET(str, str_list, cfg_stream_set_format, + "", ez->format); + } if (ez->fileName) { if (0 == strcasecmp(ez->fileName, "stdin")) ENTITY_SET(in, in_list, cfg_intake_set_type, @@ -281,9 +287,15 @@ _parse_ezconfig0(EZCONFIG *ez) "", ez->serverQuality); ENTITY_SET(str, str_list, cfg_stream_set_public, "", ez->serverPublic ? "yes" : "no"); - if (ez->reencode) - ENTITY_SET(str, str_list, cfg_stream_set_encoder, "", - ez->format); + if (ez->reencode) { + if (0 == strcasecmp(ez->format, "vorbis") || + 0 == strcasecmp(ez->format, "theora")) + ENTITY_SET(str, str_list, cfg_stream_set_encoder, + "", "Ogg"); + else + ENTITY_SET(str, str_list, cfg_stream_set_encoder, + "", ez->format); + } for (i = 0; i < MAX_FORMAT_ENCDEC; i++) { FORMAT_ENCDEC *ed = ez->encoderDecoders[i]; @@ -298,10 +310,26 @@ _parse_ezconfig0(EZCONFIG *ez) ENTITY_SET(enc, enc_list, cfg_encoder_set_program, "", ed->encoder); if (ed->format) { - ENTITY_SET(enc, enc_list, cfg_encoder_set_name, - " (encoder)", ed->format); - ENTITY_SET(enc, enc_list, cfg_encoder_set_format_str, - " (encoder)", ed->format); + if (0 == strcasecmp(ed->format, "vorbis") || + 0 == strcasecmp(ed->format, "theora")) { + ENTITY_SET(enc, enc_list, + cfg_encoder_set_name, + " (encoder)", + "Ogg"); + ENTITY_SET(enc, enc_list, + cfg_encoder_set_format_str, + " (encoder)", + "Ogg"); + } else { + ENTITY_SET(enc, enc_list, + cfg_encoder_set_name, + " (encoder)", + ed->format); + ENTITY_SET(enc, enc_list, + cfg_encoder_set_format_str, + " (encoder)", + ed->format); + } } if (0 > cfg_encoder_validate(enc, &err_str)) { log_warning("%s: %s: %s", v0_cfgfile, @@ -313,16 +341,33 @@ _parse_ezconfig0(EZCONFIG *ez) if (ed->decoder) { cfg_decoder_t dec = NULL; - if (ed->format) - dec = cfg_decoder_list_find(dec_list, ed->format); + if (ed->format) { + if (0 == strcasecmp(ed->format, "vorbis") || + 0 == strcasecmp(ed->format, "theora")) + dec = cfg_decoder_list_find(dec_list, + "Ogg"); + else + dec = cfg_decoder_list_find(dec_list, + ed->format); + } if (NULL == dec) dec = cfg_decoder_list_get(dec_list, CFG_DEFAULT); ENTITY_SET(dec, dec_list, cfg_decoder_set_program, "", ed->decoder); - if (ed->format) - ENTITY_SET(dec, dec_list, cfg_decoder_set_name, - " (decoder)", ed->format); + if (ed->format) { + if (0 == strcasecmp(ed->format, "vorbis") || + 0 == strcasecmp(ed->format, "theora")) + ENTITY_SET(dec, dec_list, + cfg_decoder_set_name, + " (decoder)", + "Ogg"); + else + ENTITY_SET(dec, dec_list, + cfg_decoder_set_name, + " (decoder)", + ed->format); + } if (ed->match) ENTITY_SET(dec, dec_list, cfg_decoder_add_match, "", ed->match); diff --git a/src/stream.c b/src/stream.c index a1d63e4..7b01698 100644 --- a/src/stream.c +++ b/src/stream.c @@ -216,8 +216,7 @@ _stream_cfg_stream(struct stream *s, cfg_stream_t cfg_stream) return (-1); } switch (cfg_stream_get_format(cfg_stream)) { - case CFG_STREAM_VORBIS: - case CFG_STREAM_THEORA: + case CFG_STREAM_OGG: if (SHOUTERR_SUCCESS != shout_set_format(s->shout, SHOUT_FORMAT_OGG)) { log_error("stream: %s: format_ogg: %s", @@ -233,6 +232,24 @@ _stream_cfg_stream(struct stream *s, cfg_stream_t cfg_stream) return (-1); } break; + case CFG_STREAM_WEBM: + if (SHOUTERR_SUCCESS != + shout_set_format(s->shout, SHOUT_FORMAT_WEBM)) { + log_error("stream: %s: format_mp3: %s", + s->name, shout_get_error(s->shout)); + return (-1); + } + break; +#ifdef SHOUT_FORMAT_MATROSKA + case CFG_STREAM_MATROSKA: + if (SHOUTERR_SUCCESS != + shout_set_format(s->shout, SHOUT_FORMAT_MATROSKA)) { + log_error("stream: %s: format_mp3: %s", + s->name, shout_get_error(s->shout)); + return (-1); + } + break; +#endif /* SHOUT_FORMAT_MATROSKA */ default: log_error("stream: %s: format: unsupported: %s", s->name, cfg_stream_get_format_str(cfg_stream)); diff --git a/tests/check_cfg_encoder.c b/tests/check_cfg_encoder.c index 692d9e6..dc4be25 100644 --- a/tests/check_cfg_encoder.c +++ b/tests/check_cfg_encoder.c @@ -77,12 +77,14 @@ START_TEST(test_encoder_set_format_str) ck_assert_str_eq(errstr, "unsupported stream format"); ck_assert_int_eq(cfg_encoder_set_format_str(enc, encoders, - CFG_SFMT_VORBIS, NULL), 0); + CFG_SFMT_OGG, NULL), 0); ck_assert_int_eq(cfg_encoder_set_format_str(enc, encoders, CFG_SFMT_MP3, NULL), 0); ck_assert_int_eq(cfg_encoder_set_format_str(enc, encoders, - CFG_SFMT_THEORA, NULL), 0); - ck_assert_uint_eq(cfg_encoder_get_format(enc), CFG_STREAM_THEORA); + CFG_SFMT_MP3, NULL), 0); + ck_assert_int_eq(cfg_encoder_set_format_str(enc, encoders, + CFG_SFMT_MATROSKA, NULL), 0); + ck_assert_uint_eq(cfg_encoder_get_format(enc), CFG_STREAM_MATROSKA); } END_TEST @@ -101,7 +103,7 @@ START_TEST(test_encoder_validate) ck_assert_int_ne(cfg_encoder_validate(enc, &errstr), 0); ck_assert_str_eq(errstr, "format not set"); - ck_assert_int_eq(cfg_encoder_set_format(enc, CFG_STREAM_VORBIS), 0); + ck_assert_int_eq(cfg_encoder_set_format(enc, CFG_STREAM_OGG), 0); ck_assert_int_ne(cfg_encoder_validate(enc, &errstr), 0); ck_assert_str_eq(errstr, "program not set"); diff --git a/tests/check_cfg_stream.c b/tests/check_cfg_stream.c index c41911a..ea2ddeb 100644 --- a/tests/check_cfg_stream.c +++ b/tests/check_cfg_stream.c @@ -47,24 +47,28 @@ START_TEST(test_stream_str2fmt) { enum cfg_stream_format fmt; - ck_assert_int_eq(cfg_stream_str2fmt(CFG_SFMT_VORBIS, &fmt), 0); - ck_assert_int_eq(fmt, CFG_STREAM_VORBIS); + ck_assert_int_eq(cfg_stream_str2fmt(CFG_SFMT_OGG, &fmt), 0); + ck_assert_int_eq(fmt, CFG_STREAM_OGG); ck_assert_int_eq(cfg_stream_str2fmt(CFG_SFMT_MP3, &fmt), 0); ck_assert_int_eq(fmt, CFG_STREAM_MP3); - ck_assert_int_eq(cfg_stream_str2fmt(CFG_SFMT_THEORA, &fmt), 0); - ck_assert_int_eq(fmt, CFG_STREAM_THEORA); + ck_assert_int_eq(cfg_stream_str2fmt(CFG_SFMT_WEBM, &fmt), 0); + ck_assert_int_eq(fmt, CFG_STREAM_WEBM); + ck_assert_int_eq(cfg_stream_str2fmt(CFG_SFMT_MATROSKA, &fmt), 0); + ck_assert_int_eq(fmt, CFG_STREAM_MATROSKA); ck_assert_int_eq(cfg_stream_str2fmt("", &fmt), -1); } END_TEST START_TEST(test_stream_fmt2str) { - ck_assert_str_eq(cfg_stream_fmt2str(CFG_STREAM_VORBIS), - CFG_SFMT_VORBIS); + ck_assert_str_eq(cfg_stream_fmt2str(CFG_STREAM_OGG), + CFG_SFMT_OGG); ck_assert_str_eq(cfg_stream_fmt2str(CFG_STREAM_MP3), CFG_SFMT_MP3); - ck_assert_str_eq(cfg_stream_fmt2str(CFG_STREAM_THEORA), - CFG_SFMT_THEORA); + ck_assert_str_eq(cfg_stream_fmt2str(CFG_STREAM_WEBM), + CFG_SFMT_WEBM); + ck_assert_str_eq(cfg_stream_fmt2str(CFG_STREAM_MATROSKA), + CFG_SFMT_MATROSKA); ck_assert_ptr_eq(cfg_stream_fmt2str(CFG_STREAM_INVALID), NULL); } END_TEST @@ -116,11 +120,11 @@ START_TEST(test_stream_format) "", &errstr2), -1); ck_assert_str_eq(errstr2, "unsupported stream format"); - ck_assert_int_eq(cfg_stream_set_format(str, streams, CFG_SFMT_VORBIS, + ck_assert_int_eq(cfg_stream_set_format(str, streams, CFG_SFMT_OGG, NULL), 0); - ck_assert_int_eq(cfg_stream_get_format(str), CFG_STREAM_VORBIS); + ck_assert_int_eq(cfg_stream_get_format(str), CFG_STREAM_OGG); ck_assert_str_eq(cfg_stream_get_format_str(str), - cfg_stream_fmt2str(CFG_STREAM_VORBIS)); + cfg_stream_fmt2str(CFG_STREAM_OGG)); } END_TEST @@ -197,7 +201,7 @@ START_TEST(test_stream_validate) ck_assert_int_ne(cfg_stream_validate(str, &errstr), 0); ck_assert_ptr_ne(errstr, NULL); ck_assert_str_eq(errstr, "format missing or unsupported"); - ck_assert_int_eq(cfg_stream_set_format(str, streams, CFG_SFMT_VORBIS, + ck_assert_int_eq(cfg_stream_set_format(str, streams, CFG_SFMT_OGG, NULL), 0); ck_assert_int_eq(cfg_stream_validate(str, NULL), 0);