mirror of
https://github.com/owntone/owntone-server.git
synced 2024-12-26 23:25:56 -05:00
[file/http/input] Implement metadata handling through input interface
This commit is contained in:
parent
0b9b008a1a
commit
8b5cac0538
@ -40,7 +40,7 @@ setup(struct player_source *ps)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
http_setup(struct player_source *ps)
|
setup_http(struct player_source *ps)
|
||||||
{
|
{
|
||||||
char *url;
|
char *url;
|
||||||
|
|
||||||
@ -103,6 +103,38 @@ seek(struct player_source *ps, int seek_ms)
|
|||||||
return transcode_seek(ps->xcode, seek_ms);
|
return transcode_seek(ps->xcode, seek_ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
metadata_get_http(struct input_metadata *metadata, struct player_source *ps)
|
||||||
|
{
|
||||||
|
struct http_icy_metadata *m;
|
||||||
|
int changed;
|
||||||
|
|
||||||
|
m = transcode_metadata(ps->xcode, &changed);
|
||||||
|
if (!m)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!changed)
|
||||||
|
{
|
||||||
|
http_icy_metadata_free(m, 0);
|
||||||
|
return -1; // TODO Perhaps a problem since this prohibits the player updating metadata
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m->artist)
|
||||||
|
metadata->artist = m->artist;
|
||||||
|
// Note we map title to album, because clients should show stream name as titel
|
||||||
|
if (m->title)
|
||||||
|
metadata->album = m->title;
|
||||||
|
if (m->artwork_url)
|
||||||
|
metadata->artwork_url = m->artwork_url;
|
||||||
|
|
||||||
|
m->artist = NULL;
|
||||||
|
m->title = NULL;
|
||||||
|
m->artwork_url = NULL;
|
||||||
|
|
||||||
|
http_icy_metadata_free(m, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
struct input_definition input_file =
|
struct input_definition input_file =
|
||||||
{
|
{
|
||||||
.name = "file",
|
.name = "file",
|
||||||
@ -119,7 +151,8 @@ struct input_definition input_http =
|
|||||||
.name = "http",
|
.name = "http",
|
||||||
.type = INPUT_TYPE_HTTP,
|
.type = INPUT_TYPE_HTTP,
|
||||||
.disabled = 0,
|
.disabled = 0,
|
||||||
.setup = http_setup,
|
.setup = setup_http,
|
||||||
.start = start,
|
.start = start,
|
||||||
.stop = stop,
|
.stop = stop,
|
||||||
|
.metadata_get = metadata_get_http,
|
||||||
};
|
};
|
||||||
|
@ -82,6 +82,9 @@ struct decode_ctx {
|
|||||||
// Duration (used to make wav header)
|
// Duration (used to make wav header)
|
||||||
uint32_t duration;
|
uint32_t duration;
|
||||||
|
|
||||||
|
// Data kind (used to determine if ICY metadata is relevant to look for)
|
||||||
|
enum data_kind data_kind;
|
||||||
|
|
||||||
// Contains the most recent packet from av_read_frame
|
// Contains the most recent packet from av_read_frame
|
||||||
// Used for resuming after seek and for freeing correctly
|
// Used for resuming after seek and for freeing correctly
|
||||||
// in transcode_decode()
|
// in transcode_decode()
|
||||||
@ -583,7 +586,7 @@ flush_encoder(struct encode_ctx *ctx, unsigned int stream_index)
|
|||||||
/* --------------------------- INPUT/OUTPUT INIT --------------------------- */
|
/* --------------------------- INPUT/OUTPUT INIT --------------------------- */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
open_input(struct decode_ctx *ctx, enum data_kind data_kind, const char *path, int decode_video)
|
open_input(struct decode_ctx *ctx, const char *path, int decode_video)
|
||||||
{
|
{
|
||||||
AVDictionary *options;
|
AVDictionary *options;
|
||||||
AVCodec *decoder;
|
AVCodec *decoder;
|
||||||
@ -600,10 +603,10 @@ open_input(struct decode_ctx *ctx, enum data_kind data_kind, const char *path, i
|
|||||||
|
|
||||||
# ifndef HAVE_FFMPEG
|
# ifndef HAVE_FFMPEG
|
||||||
// Without this, libav is slow to probe some internet streams, which leads to RAOP timeouts
|
// Without this, libav is slow to probe some internet streams, which leads to RAOP timeouts
|
||||||
if (data_kind == DATA_KIND_HTTP)
|
if (ctx->data_kind == DATA_KIND_HTTP)
|
||||||
ctx->ifmt_ctx->probesize = 64000;
|
ctx->ifmt_ctx->probesize = 64000;
|
||||||
# endif
|
# endif
|
||||||
if (data_kind == DATA_KIND_HTTP)
|
if (ctx->data_kind == DATA_KIND_HTTP)
|
||||||
av_dict_set(&options, "icy", "1", 0);
|
av_dict_set(&options, "icy", "1", 0);
|
||||||
|
|
||||||
// TODO Newest versions of ffmpeg have timeout and reconnect options we should use
|
// TODO Newest versions of ffmpeg have timeout and reconnect options we should use
|
||||||
@ -1245,14 +1248,15 @@ transcode_decode_setup(enum data_kind data_kind, const char *path, uint32_t song
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (open_input(ctx, data_kind, path, decode_video) < 0)
|
ctx->duration = song_length;
|
||||||
|
ctx->data_kind = data_kind;
|
||||||
|
|
||||||
|
if (open_input(ctx, path, decode_video) < 0)
|
||||||
{
|
{
|
||||||
free(ctx);
|
free(ctx);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->duration = song_length;
|
|
||||||
|
|
||||||
av_init_packet(&ctx->packet);
|
av_init_packet(&ctx->packet);
|
||||||
|
|
||||||
return ctx;
|
return ctx;
|
||||||
@ -1283,6 +1287,7 @@ transcode_encode_setup(struct decode_ctx *src_ctx, enum transcode_profile profil
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (src_ctx->data_kind == DATA_KIND_HTTP)
|
||||||
ctx->icy_interval = METADATA_ICY_INTERVAL * ctx->channels * ctx->byte_depth * ctx->sample_rate;
|
ctx->icy_interval = METADATA_ICY_INTERVAL * ctx->channels * ctx->byte_depth * ctx->sample_rate;
|
||||||
|
|
||||||
if (profile == XCODE_PCM16_HEADER)
|
if (profile == XCODE_PCM16_HEADER)
|
||||||
@ -1637,6 +1642,8 @@ transcode(struct evbuffer *evbuf, int wanted, struct transcode_ctx *ctx, int *ic
|
|||||||
int processed;
|
int processed;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
*icy_timer = 0;
|
||||||
|
|
||||||
processed = 0;
|
processed = 0;
|
||||||
while (processed < wanted)
|
while (processed < wanted)
|
||||||
{
|
{
|
||||||
@ -1653,6 +1660,7 @@ transcode(struct evbuffer *evbuf, int wanted, struct transcode_ctx *ctx, int *ic
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx->encode_ctx->total_bytes += processed;
|
ctx->encode_ctx->total_bytes += processed;
|
||||||
|
if (ctx->encode_ctx->icy_interval)
|
||||||
*icy_timer = (ctx->encode_ctx->total_bytes % ctx->encode_ctx->icy_interval < processed);
|
*icy_timer = (ctx->encode_ctx->total_bytes % ctx->encode_ctx->icy_interval < processed);
|
||||||
|
|
||||||
return processed;
|
return processed;
|
||||||
@ -1822,24 +1830,3 @@ transcode_metadata(struct transcode_ctx *ctx, int *changed)
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
|
||||||
transcode_metadata_artwork_url(struct transcode_ctx *ctx)
|
|
||||||
{
|
|
||||||
struct http_icy_metadata *m;
|
|
||||||
char *artwork_url;
|
|
||||||
|
|
||||||
if (!ctx->decode_ctx->ifmt_ctx || !ctx->decode_ctx->ifmt_ctx->filename)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
artwork_url = NULL;
|
|
||||||
|
|
||||||
m = http_icy_metadata_get(ctx->decode_ctx->ifmt_ctx, 1);
|
|
||||||
if (m && m->artwork_url)
|
|
||||||
artwork_url = strdup(m->artwork_url);
|
|
||||||
|
|
||||||
if (m)
|
|
||||||
http_icy_metadata_free(m, 0);
|
|
||||||
|
|
||||||
return artwork_url;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -100,7 +100,4 @@ transcode_seek(struct transcode_ctx *ctx, int ms);
|
|||||||
struct http_icy_metadata *
|
struct http_icy_metadata *
|
||||||
transcode_metadata(struct transcode_ctx *ctx, int *changed);
|
transcode_metadata(struct transcode_ctx *ctx, int *changed);
|
||||||
|
|
||||||
char *
|
|
||||||
transcode_metadata_artwork_url(struct transcode_ctx *ctx);
|
|
||||||
|
|
||||||
#endif /* !__TRANSCODE_H__ */
|
#endif /* !__TRANSCODE_H__ */
|
||||||
|
Loading…
Reference in New Issue
Block a user