Support for live ICY metadata for streams (incl. artwork)

This commit is contained in:
ejurgensen
2015-03-14 21:42:53 +01:00
parent 34d815a130
commit 6221e24f1b
12 changed files with 709 additions and 108 deletions

View File

@@ -38,6 +38,7 @@
#include "logger.h"
#include "conffile.h"
#include "cache.h"
#include "player.h"
#if LIBAVFORMAT_VERSION_MAJOR >= 53
# include "avio_evbuffer.h"
@@ -725,6 +726,127 @@ artwork_get(char *path, int max_w, int max_h, struct evbuffer *evbuf)
return ret;
}
static int
artwork_get_player_image(char *path, int max_w, int max_h, struct evbuffer *evbuf)
{
AVFormatContext *src_ctx;
AVPacket pkt;
char *url;
int len;
int s;
int target_w;
int target_h;
int format_ok;
int ret;
DPRINTF(E_DBG, L_ART, "Trying internet stream artwork in %s\n", path);
player_icy_artwork_url(&url, path);
if (!url)
return 0;
len = strlen(url);
if ((len < 14) || (len > PATH_MAX)) // Can't be shorter than http://a/1.jpg
return 0;
src_ctx = NULL;
ret = avformat_open_input(&src_ctx, url, NULL, NULL);
if (ret < 0)
{
DPRINTF(E_WARN, L_ART, "Cannot open artwork file '%s': %s\n", url, strerror(AVUNERROR(ret)));
return 0;
}
free(url);
format_ok = 0;
for (s = 0; s < src_ctx->nb_streams; s++)
{
if (src_ctx->streams[s]->codec->codec_id == AV_CODEC_ID_PNG)
{
format_ok = ART_FMT_PNG;
break;
}
else if (src_ctx->streams[s]->codec->codec_id == AV_CODEC_ID_MJPEG)
{
format_ok = ART_FMT_JPEG;
break;
}
}
if (s == src_ctx->nb_streams)
{
DPRINTF(E_LOG, L_ART, "Artwork file '%s' not a PNG or JPEG file\n", path);
avformat_close_input(&src_ctx);
return 0;
}
ret = 0;
while (av_read_frame(src_ctx, &pkt) == 0)
{
if (pkt.stream_index != s)
{
av_free_packet(&pkt);
continue;
}
ret = 1;
break;
}
if (!ret)
{
DPRINTF(E_LOG, L_ART, "Could not read artwork: '%s'\n", path);
avformat_close_input(&src_ctx);
return 0;
}
ret = rescale_needed(src_ctx->streams[s]->codec, max_w, max_h, &target_w, &target_h);
/* Fastpath */
if (!ret && format_ok)
{
DPRINTF(E_DBG, L_ART, "Artwork not too large, using original image\n");
ret = evbuffer_expand(evbuf, pkt.size);
if (ret < 0)
{
DPRINTF(E_LOG, L_ART, "Out of memory for artwork\n");
av_free_packet(&pkt);
avformat_close_input(&src_ctx);
return -1;
}
ret = evbuffer_add(evbuf, pkt.data, pkt.size);
if (ret < 0)
{
DPRINTF(E_LOG, L_ART, "Could not add image to event buffer\n");
}
else
ret = format_ok;
}
else
{
DPRINTF(E_DBG, L_ART, "Artwork too large, rescaling image\n");
ret = artwork_rescale(src_ctx, s, target_w, target_h, evbuf);
}
av_free_packet(&pkt);
avformat_close_input(&src_ctx);
if (ret < 0)
{
if (evbuffer_get_length(evbuf) > 0)
evbuffer_drain(evbuf, evbuffer_get_length(evbuf));
}
return ret;
}
#if LIBAVFORMAT_VERSION_MAJOR >= 55 || (LIBAVFORMAT_VERSION_MAJOR == 54 && LIBAVFORMAT_VERSION_MINOR >= 6)
static int
artwork_get_embedded_image(char *path, int max_w, int max_h, struct evbuffer *evbuf)
@@ -786,7 +908,7 @@ artwork_get_embedded_image(char *path, int max_w, int max_h, struct evbuffer *ev
if (s == src_ctx->nb_streams)
{
DPRINTF(E_SPAM, L_ART, "Did not find embedded artwork in '%s'\n", path);
DPRINTF(E_DBG, L_ART, "Did not find embedded artwork in '%s'\n", path);
avformat_close_input(&src_ctx);
return -1;
@@ -1062,6 +1184,9 @@ artwork_get_item_path(char *in_path, int artwork, int max_w, int max_h, char *ou
ret = artwork_get_embedded_image(in_path, max_w, max_h, evbuf);
break;
#endif
case ARTWORK_HTTP:
ret = artwork_get_player_image(in_path, max_w, max_h, evbuf);
break;
}
return ret;