Commit e101efe5 authored by Philipp Schafft's avatar Philipp Schafft 🦁
Browse files

Merge branch 'devel-phschafft-feature-format'

Fixes: #1946
parents de5569da 163dda9c
......@@ -28,6 +28,7 @@
<itemizedlist><title>Audio Formats</title>
<listitem>Ogg (audio any video with different codecs)</listitem>
<listitem>WebM (audio and video)</listitem>
<listitem>Matroska (audio and video)</listitem>
<listitem>MP3</listitem>
</itemizedlist>
......@@ -548,6 +549,9 @@
are listed in <link linkend="format_constants">Format Constants</link>.
The default is <constant>SHOUT_FORMAT_OGG</constant>.
</para>
<warning>This function has been obsoleted and may not be included in future versions of the library.
Please use <link linkend="shout_set_content_format"><function>shout_set_content_format</function></link>
</warning>
<funcsynopsis id="shout_get_format">
<funcprototype>
......@@ -558,6 +562,55 @@
<para>
Returns the audio format used by this stream.
</para>
<warning>This function has been obsoleted and may not be included in future versions of the library.
Please use <link linkend="shout_get_content_format"><function>shout_get_content_format</function></link>
</warning>
<funcsynopsis id="shout_set_content_format">
<funcprototype>
<funcdef>int <function>shout_set_content_format</function></funcdef>
<paramdef><type>shout_t</type> *<parameter>self</parameter></paramdef>
<paramdef><type>unsigned int</type> <parameter>format</parameter></paramdef>
<paramdef><type>unsigned int</type> <parameter>usage</parameter></paramdef>
<paramdef><type>const char</type> *<parameter>codecs</parameter></paramdef>
</funcprototype>
</funcsynopsis>
<para>
Sets the format of the stream, the usage, and the used codecs.
</para>
<para>
The format must be one of the supported format constants
are listed in <link linkend="format_constants">Format Constants</link>.
The default is <constant>SHOUT_FORMAT_OGG</constant>.
</para>
<para>
The usage parameter is a bit-wise or-ed set of usages from the usage constants
are listed in <link linkend="usage_constants">Usage Constants</link>.
The default is <constant>SHOUT_USAGE_UNKNOWN</constant>.
</para>
<para>
The codecs parameter is used for codec pinning. In codec pinning mode only the listed codecs
are allowed to be contained in the stream. This helps listening software with playback.
This is not yet supported and must be set to NULL meaning no pinning.
The value of NULL will also be supported by future versions.
</para>
<note>
<constant>SHOUT_FORMAT_WEBMAUDIO</constant> is not accepted by this function as it is deprecated.
Use <constant>SHOUT_FORMAT_WEB</constant> and <constant>SHOUT_USAGE_AUDIO</constant>.
</note>
<funcsynopsis id="shout_get_content_format">
<funcprototype>
<funcdef>int <function>shout_set_content_format</function></funcdef>
<paramdef><type>shout_t</type> *<parameter>self</parameter></paramdef>
<paramdef><type>unsigned int</type> *<parameter>format</parameter></paramdef>
<paramdef><type>unsigned int</type> *<parameter>usage</parameter></paramdef>
<paramdef><type>const char</type> **<parameter>codecs</parameter></paramdef>
</funcprototype>
</funcsynopsis>
<para>Returns the content format parameters as set by link <link linkend="shout_set_content_format"><function>shout_set_content_format</function></link>.
</para>
<funcsynopsis id="shout_set_mount">
<funcprototype>
......@@ -1160,7 +1213,12 @@
<varlistentry>
<term><constant>SHOUT_FORMAT_WEBMAUDIO</constant></term>
<listitem>The WebM format, audio only streams.</listitem>
<listitem>his is deprecated. Use <constant>SHOUT_FORMAT_WEBM</constant> with <constant>SHOUT_USAGE_AUDIO</constant></listitem>
</varlistentry>
<varlistentry>
<term><constant>SHOUT_FORMAT_MATROSKA</constant></term>
<listitem>The Matroska format.</listitem>
</varlistentry>
<varlistentry>
......@@ -1175,6 +1233,79 @@
</varlistentry>
</variablelist>
<variablelist id="usage_constants"><title>Usages</title>
<varlistentry>
<term><constant>SHOUT_USAGE_AUDIO</constant></term>
<listitem>Contains audio substreams.</listitem>
</varlistentry>
<varlistentry>
<term><constant>SHOUT_USAGE_VISUAL</constant></term>
<listitem>Contains Picture/Video substreams. This is often combined with <constant>SHOUT_USAGE_AUDIO</constant>.</listitem>
</varlistentry>
<varlistentry>
<term><constant>SHOUT_USAGE_TEXT</constant></term>
<listitem>Contains text substreams that are not subtitles.</listitem>
</varlistentry>
<varlistentry>
<term><constant>SHOUT_USAGE_SUBTITLE</constant></term>
<listitem>Contains subtitles as substreams.</listitem>
</varlistentry>
<varlistentry>
<term><constant>SHOUT_USAGE_LIGHT</constant></term>
<listitem>Contains light control substreams.</listitem>
</varlistentry>
<varlistentry>
<term><constant>SHOUT_USAGE_UI</constant></term>
<listitem>Contains User Interface data as substreams. Example of such are DVD menus or Matroska buttons.</listitem>
</varlistentry>
<varlistentry>
<term><constant>SHOUT_USAGE_METADATA</constant></term>
<listitem>Contains additional metadata as substreams. Examples are substreams with references to additional data sources, or program guide data.</listitem>
</varlistentry>
<varlistentry>
<term><constant>SHOUT_USAGE_APPLICATION</constant></term>
<listitem>Contains substreams with data specific to the application.</listitem>
</varlistentry>
<varlistentry>
<term><constant>SHOUT_USAGE_CONTROL</constant></term>
<listitem>Contains substreams that include control data for the streaming environment. Examples include commands to the signal routers, remuxers, or transmitters.</listitem>
</varlistentry>
<varlistentry>
<term><constant>SHOUT_USAGE_COMPLEX</constant></term>
<listitem>Contains substreams that themself contain data of more than one type. Examples include encapsulation of one container into another.</listitem>
</varlistentry>
<varlistentry>
<term><constant>SHOUT_USAGE_OTHER</constant></term>
<listitem>Contains substreams of a type not yet known to libshout.</listitem>
</varlistentry>
<varlistentry>
<term><constant>SHOUT_USAGE_UNKNOWN</constant></term>
<listitem>May contain (future) substreams of yet unknown nature to the caller.</listitem>
</varlistentry>
<varlistentry>
<term><constant>SHOUT_USAGE_3D</constant></term>
<listitem>Contains information for 3D playback.</listitem>
</varlistentry>
<varlistentry>
<term><constant>SHOUT_USAGE_4D</constant></term>
<listitem>Contains information for 4D/XD playback. 4D/XD playback is used to improve the immersion by adding effects like body shakers or wind.</listitem>
</varlistentry>
</variablelist>
<variablelist id="protocol_constants"><title>Protocols</title>
<varlistentry>
<term><constant>SHOUT_PROTOCOL_HTTP</constant></term>
......
......@@ -48,14 +48,31 @@ extern "C" {
#define SHOUTERR_TLSBADCERT (-12) /* TLS connection can not be established because of bad certificate */
#define SHOUTERR_RETRY (-13) /* Retry last operation. */
#define SHOUT_FORMAT_OGG ( 0) /* application/ogg */
#define SHOUT_FORMAT_MP3 ( 1) /* audio/mpeg */
#define SHOUT_FORMAT_WEBM ( 2) /* video/webm */
#define SHOUT_FORMAT_WEBMAUDIO ( 3) /* audio/webm audio only */
#define SHOUT_FORMAT_OGG ( 0) /* Ogg */
#define SHOUT_FORMAT_MP3 ( 1) /* MP3 */
#define SHOUT_FORMAT_WEBM ( 2) /* WebM */
#define SHOUT_FORMAT_WEBMAUDIO ( 3) /* WebM, audio only, obsolete. Only used by shout_set_format() */
#define SHOUT_FORMAT_MATROSKA ( 4) /* Matroska */
/* backward-compatibility alias */
#define SHOUT_FORMAT_VORBIS SHOUT_FORMAT_OGG
/* Usages */
#define SHOUT_USAGE_AUDIO (0x0001U) /* Audio substreams*/
#define SHOUT_USAGE_VISUAL (0x0002U) /* Picture/Video substreams (most often combined with SHOUT_USAGE_AUDIO) */
#define SHOUT_USAGE_TEXT (0x0004U) /* Text substreams that are not subtitles */
#define SHOUT_USAGE_SUBTITLE (0x0008U) /* Subtitle substreams */
#define SHOUT_USAGE_LIGHT (0x0010U) /* Light control substreams */
#define SHOUT_USAGE_UI (0x0020U) /* User interface data, such as DVD menus or buttons */
#define SHOUT_USAGE_METADATA (0x0040U) /* Substreams that include metadata for the stream */
#define SHOUT_USAGE_APPLICATION (0x0080U) /* Application specific data substreams */
#define SHOUT_USAGE_CONTROL (0x0100U) /* Substreams that control the infrastructure */
#define SHOUT_USAGE_COMPLEX (0x0200U) /* Substreams that are themself a mixture of other types */
#define SHOUT_USAGE_OTHER (0x0400U) /* Substream of types not listed here */
#define SHOUT_USAGE_UNKNOWN (0x0800U) /* The stream MAY contain additional substreams of unknown nature */
#define SHOUT_USAGE_3D (0x1000U) /* The Stream contains information for 3D playback */
#define SHOUT_USAGE_4D (0x2000U) /* The Stream contains information for 4D/XD playback */
#define SHOUT_PROTOCOL_HTTP ( 0)
#define SHOUT_PROTOCOL_XAUDIOCAST ( 1) /* Deprecated. May be removed in future versions. Do not use. */
#define SHOUT_PROTOCOL_ICY ( 2)
......@@ -211,8 +228,16 @@ int shout_set_public(shout_t *self, unsigned int make_public);
unsigned int shout_get_public(shout_t *self);
/* takes a SHOUT_FORMAT_xxxx argument */
int shout_set_format(shout_t *self, unsigned int format);
unsigned int shout_get_format(shout_t *self);
int shout_set_format(shout_t *self, unsigned int format); // obsolete
unsigned int shout_get_format(shout_t *self); // obsolete
/* Set the format of the content to send.
* * format is one of SHOUT_FORMAT_xxxx.
* * usage is a bit vector composed of SHOUT_USAGE_xxxx.
* * codecs is NULL as of this version. Future versions will also support NULL.
*/
int shout_set_content_format(shout_t *self, unsigned int format, unsigned int usage, const char *codecs);
int shout_get_content_format(shout_t *self, unsigned int *format, unsigned int *usage, const char **codecs);
/* takes a SHOUT_PROTOCOL_xxxxx argument */
int shout_set_protocol(shout_t *self, unsigned int protocol);
......
......@@ -91,27 +91,10 @@ static shout_connection_return_state_t shout_create_http_request_source(shout_t
const char *mimetype;
char *mount = NULL;
switch (self->format) {
case SHOUT_FORMAT_OGG:
mimetype = "application/ogg";
break;
case SHOUT_FORMAT_MP3:
mimetype = "audio/mpeg";
break;
case SHOUT_FORMAT_WEBM:
mimetype = "video/webm";
break;
case SHOUT_FORMAT_WEBMAUDIO:
mimetype = "audio/webm";
break;
default:
shout_connection_set_error(connection, SHOUTERR_INSANE);
return SHOUT_RS_ERROR;
break;
mimetype = shout_get_mimetype_from_self(self);
if (!mimetype) {
shout_connection_set_error(connection, SHOUTERR_INSANE);
return SHOUT_RS_ERROR;
}
/* this is lazy code that relies on the only error from queue_* being
......
......@@ -131,6 +131,7 @@ shout_t *shout_new(void)
self->port = LIBSHOUT_DEFAULT_PORT;
self->format = LIBSHOUT_DEFAULT_FORMAT;
self->usage = LIBSHOUT_DEFAULT_USAGE;
self->protocol = LIBSHOUT_DEFAULT_PROTOCOL;
return self;
......@@ -811,22 +812,151 @@ int shout_set_format(shout_t *self, unsigned int format)
if (self->connection)
return self->error = SHOUTERR_CONNECTED;
if (format != SHOUT_FORMAT_OGG && format != SHOUT_FORMAT_MP3 &&
format != SHOUT_FORMAT_WEBM && format != SHOUT_FORMAT_WEBMAUDIO) {
switch (format) {
case SHOUT_FORMAT_OGG:
return shout_set_content_format(self, SHOUT_FORMAT_OGG, SHOUT_USAGE_UNKNOWN, NULL);
break;
case SHOUT_FORMAT_MP3:
return shout_set_content_format(self, SHOUT_FORMAT_MP3, SHOUT_USAGE_AUDIO, NULL);
break;
case SHOUT_FORMAT_WEBM:
return shout_set_content_format(self, SHOUT_FORMAT_WEBM, SHOUT_USAGE_AUDIO|SHOUT_USAGE_VISUAL, NULL);
break;
case SHOUT_FORMAT_WEBMAUDIO:
return shout_set_content_format(self, SHOUT_FORMAT_WEBM, SHOUT_USAGE_AUDIO, NULL);
break;
}
return self->error = SHOUTERR_UNSUPPORTED;
}
unsigned int shout_get_format(shout_t* self)
{
if (!self)
return 0;
if (self->format == SHOUT_FORMAT_WEBM && self->usage == SHOUT_USAGE_AUDIO) {
return SHOUT_FORMAT_WEBMAUDIO;
}
return self->format;
}
static inline unsigned int remove_bits(unsigned int value, unsigned int to_remove)
{
value |= to_remove;
value -= to_remove;
return value;
}
static inline int is_audio(unsigned int usage)
{
if (!(usage & SHOUT_USAGE_AUDIO))
return 0;
if (remove_bits(usage, SHOUT_USAGE_AUDIO|SHOUT_USAGE_SUBTITLE))
return 0;
return 1;
}
static inline int is_video(unsigned int usage)
{
if (!(usage & SHOUT_USAGE_VISUAL))
return 0;
if (remove_bits(usage, SHOUT_USAGE_VISUAL|SHOUT_USAGE_AUDIO|SHOUT_USAGE_SUBTITLE|SHOUT_USAGE_3D|SHOUT_USAGE_4D))
return 0;
return 1;
}
static const char *shout_get_mimetype(unsigned int format, unsigned int usage, const char *codecs)
{
if (codecs)
return NULL;
switch (format) {
case SHOUT_FORMAT_OGG:
if (is_audio(usage)) {
return "audio/ogg";
} else if (is_video(usage)) {
return "video/ogg";
} else {
return "application/ogg";
}
break;
case SHOUT_FORMAT_MP3:
/* MP3 *ONLY* support Audio. So all other values are outright invalid */
if (usage == SHOUT_USAGE_AUDIO) {
return "audio/mpeg";
}
break;
case SHOUT_FORMAT_WEBM:
if (is_audio(usage)) {
return "audio/webm";
} else if (is_video(usage)) {
return "video/webm";
}
break;
case SHOUT_FORMAT_MATROSKA:
if (is_audio(usage)) {
return "audio/x-matroska";
} else if (is_video(usage) && (usage & SHOUT_USAGE_3D)) {
return "video/x-matroska-3d";
} else if (is_video(usage)) {
return "video/x-matroska";
}
break;
}
return NULL;
}
const char *shout_get_mimetype_from_self(shout_t *self)
{
return shout_get_mimetype(self->format, self->usage, NULL);
}
int shout_set_content_format(shout_t *self, unsigned int format, unsigned int usage, const char *codecs)
{
if (!self)
return SHOUTERR_INSANE;
if (self->connection)
return self->error = SHOUTERR_CONNECTED;
if (codecs) {
return self->error = SHOUTERR_UNSUPPORTED;
}
if (!shout_get_mimetype(format, usage, codecs)) {
return self->error = SHOUTERR_UNSUPPORTED;
}
self->format = format;
self->usage = usage;
return self->error = SHOUTERR_SUCCESS;
}
unsigned int shout_get_format(shout_t* self)
int shout_get_content_format(shout_t *self, unsigned int *format, unsigned int *usage, const char **codecs)
{
if (!self)
return 0;
return SHOUTERR_INSANE;
return self->format;
if (format)
*format = self->format;
if (usage)
*usage = self->usage;
if (codecs)
*codecs = NULL;
return self->error = SHOUTERR_SUCCESS;
}
int shout_set_protocol(shout_t *self, unsigned int protocol)
......@@ -1209,7 +1339,7 @@ static int try_connect(shout_t *self)
rc = self->error = shout_open_mp3(self);
break;
case SHOUT_FORMAT_WEBM:
case SHOUT_FORMAT_WEBMAUDIO:
case SHOUT_FORMAT_MATROSKA:
rc = self->error = shout_open_webm(self);
break;
......
......@@ -48,6 +48,7 @@
#define LIBSHOUT_DEFAULT_HOST "localhost"
#define LIBSHOUT_DEFAULT_PORT 8000
#define LIBSHOUT_DEFAULT_FORMAT SHOUT_FORMAT_OGG
#define LIBSHOUT_DEFAULT_USAGE SHOUT_USAGE_UNKNOWN
#define LIBSHOUT_DEFAULT_PROTOCOL SHOUT_PROTOCOL_HTTP
#define LIBSHOUT_DEFAULT_USER "source"
#define LIBSHOUT_DEFAULT_USERAGENT "libshout/" VERSION
......@@ -214,6 +215,7 @@ struct shout {
unsigned int protocol;
/* type of data being sent */
unsigned int format;
unsigned int usage;
/* audio encoding parameters */
util_dict *audio_info;
......@@ -263,6 +265,8 @@ struct shout {
};
/* helper functions */
const char *shout_get_mimetype_from_self(shout_t *self);
int shout_queue_data(shout_queue_t *queue, const unsigned char *data, size_t len);
int shout_queue_str(shout_connection_t *self, const char *str);
int shout_queue_printf(shout_connection_t *self, const char *fmt, ...);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment