[file/http/input] Implement metadata handling through input interface

This commit is contained in:
ejurgensen 2017-01-22 23:23:18 +01:00
parent 0b9b008a1a
commit 8b5cac0538
3 changed files with 51 additions and 34 deletions

View File

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

View File

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

View File

@ -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__ */