1
0
mirror of https://gitlab.xiph.org/xiph/ezstream.git synced 2025-01-03 14:56:35 -05:00

Modernize stream format options

Adds support for WebM/Matroska
Replaces Vorbis and Theora with Ogg
This commit is contained in:
Moritz Grimm 2020-01-24 23:27:02 +01:00
parent 4fe8ea4526
commit b61b78e161
13 changed files with 138 additions and 62 deletions

View File

@ -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 \&<encoder\ /\&>
Use the encoder configuration with the provided symbolic name

View File

@ -21,7 +21,7 @@
<streams>
<stream>
<mountpoint>/stream.ogg</mountpoint>
<format>Vorbis</format>
<format>Ogg</format>
<encoder>OggEnc-Q1.5</encoder>
</stream>
</streams>
@ -56,7 +56,7 @@
<encoders>
<encoder>
<name>OggEnc-Q1.5</name>
<format>Vorbis</format>
<format>Ogg</format>
<program>oggenc -r -B 16 -C 2 -R 44100 --raw-endianness 0 -q 1.5 -t @M@ -</program>
</encoder>

View File

@ -100,8 +100,8 @@
-->
<public>No</public>
<!-- Stream format: Vorbis, MP3, Theora -->
<format>Vorbis</format>
<!-- Stream format: Ogg, MP3, WebM, Matroska -->
<format>Ogg</format>
<!-- Encoder name (defined below) to use for (re)encoding -->
<encoder>OggEnc-Q1.5</encoder>
@ -198,7 +198,7 @@
<!-- Encoder name -->
<name>OggEnc-Q1.5</name>
<!-- Output stream format -->
<format>Vorbis</format>
<format>Ogg</format>
<!-- Program and options -->
<program>oggenc -r -B 16 -C 2 -R 44100 --raw-endianness 1 -q 1.5 -t @M@ -</program>
</encoder>

View File

@ -16,7 +16,7 @@
<streams>
<stream>
<mountpoint>/stream.ogg</mountpoint>
<format>Vorbis</format>
<format>Ogg</format>
</stream>
</streams>

View File

@ -3,7 +3,7 @@
<!--
EXAMPLE: A valid configuration that contains the absolute minimum
This configuration streams Ogg Vorbis files as-is.
This configuration streams Ogg files as-is.
-->
<ezstream>
@ -18,7 +18,7 @@
<streams>
<stream>
<mountpoint>/stream.ogg</mountpoint>
<format>Vorbis</format>
<format>Ogg</format>
</stream>
</streams>

View File

@ -18,7 +18,7 @@
<streams>
<stream>
<mountpoint>/stream.ogg</mountpoint>
<format>Vorbis</format>
<format>Ogg</format>
</stream>
</streams>

View File

@ -16,7 +16,7 @@
<streams>
<stream>
<mountpoint>/video.ogg</mountpoint>
<format>Theora</format>
<format>Ogg</format>
<!-- No encoder configured (see below). -->
</stream>
</streams>

View File

@ -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);
}

View File

@ -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;

View File

@ -206,9 +206,15 @@ _parse_ezconfig0(EZCONFIG *ez)
if (ez->password)
ENTITY_SET(srv, srv_list, cfg_server_set_password,
"<sourcepassword>", ez->password);
if (ez->format)
ENTITY_SET(str, str_list, cfg_stream_set_format,
"<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,
"<format>", "Ogg");
else
ENTITY_SET(str, str_list, cfg_stream_set_format,
"<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)
"<svrinfoquality>", ez->serverQuality);
ENTITY_SET(str, str_list, cfg_stream_set_public,
"<svrinfopublic>", ez->serverPublic ? "yes" : "no");
if (ez->reencode)
ENTITY_SET(str, str_list, cfg_stream_set_encoder, "<reencode>",
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,
"<reencode>", "Ogg");
else
ENTITY_SET(str, str_list, cfg_stream_set_encoder,
"<reencode>", 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,
"<encode>", ed->encoder);
if (ed->format) {
ENTITY_SET(enc, enc_list, cfg_encoder_set_name,
"<format> (encoder)", ed->format);
ENTITY_SET(enc, enc_list, cfg_encoder_set_format_str,
"<format> (encoder)", ed->format);
if (0 == strcasecmp(ed->format, "vorbis") ||
0 == strcasecmp(ed->format, "theora")) {
ENTITY_SET(enc, enc_list,
cfg_encoder_set_name,
"<format> (encoder)",
"Ogg");
ENTITY_SET(enc, enc_list,
cfg_encoder_set_format_str,
"<format> (encoder)",
"Ogg");
} else {
ENTITY_SET(enc, enc_list,
cfg_encoder_set_name,
"<format> (encoder)",
ed->format);
ENTITY_SET(enc, enc_list,
cfg_encoder_set_format_str,
"<format> (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,
"<decode>", ed->decoder);
if (ed->format)
ENTITY_SET(dec, dec_list, cfg_decoder_set_name,
"<format> (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,
"<format> (decoder)",
"Ogg");
else
ENTITY_SET(dec, dec_list,
cfg_decoder_set_name,
"<format> (decoder)",
ed->format);
}
if (ed->match)
ENTITY_SET(dec, dec_list, cfg_decoder_add_match,
"<match>", ed->match);

View File

@ -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));

View File

@ -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");

View File

@ -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("<something else>", &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)
"<something else>", &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);