[artwork] Add ability to rescale Spotify (should improve caching so we don't save too large images)

This commit is contained in:
ejurgensen 2016-01-05 21:44:44 +01:00
parent 9a0a390a73
commit 7caf8cc66a
4 changed files with 127 additions and 11 deletions

View File

@ -472,8 +472,8 @@ artwork_rescale(struct evbuffer *evbuf, AVFormatContext *src_ctx, int s, int out
av_free_packet(&pkt);
/* Open output file */
dst_ctx->pb = avio_evbuffer_open(evbuf);
if (ret < 0)
dst_ctx->pb = avio_output_evbuffer_open(evbuf);
if (!dst_ctx->pb)
{
DPRINTF(E_LOG, L_ART, "Could not open artwork destination buffer\n");
@ -1105,13 +1105,98 @@ source_item_stream_get(struct artwork_ctx *ctx)
static int
source_item_spotify_get(struct artwork_ctx *ctx)
{
AVFormatContext *src_ctx;
AVIOContext *avio;
AVInputFormat *ifmt;
struct evbuffer *evbuf;
int target_w;
int target_h;
int ret;
ret = spotify_artwork_get(ctx->evbuf, ctx->dbmfi->path, ctx->max_w, ctx->max_h);
if (ret < 0)
return ART_E_NONE;
evbuf = evbuffer_new();
if (!evbuf)
{
DPRINTF(E_LOG, L_ART, "Out of memory for Spotify evbuf\n");
return ART_E_ERROR;
}
ret = spotify_artwork_get(evbuf, ctx->dbmfi->path, ctx->max_w, ctx->max_h);
if (ret < 0)
{
DPRINTF(E_WARN, L_ART, "No artwork from Spotify for %s\n", ctx->dbmfi->path);
evbuffer_free(evbuf);
return ART_E_NONE;
}
// Now we take it by ffmpeg, since it probably needs to be rescaled
src_ctx = avformat_alloc_context();
if (!src_ctx)
{
DPRINTF(E_LOG, L_ART, "Out of memory for source context\n");
goto out_free_evbuf;
}
avio = avio_input_evbuffer_open(evbuf);
if (!avio)
{
DPRINTF(E_LOG, L_ART, "Could not alloc input evbuffer\n");
goto out_free_ctx;
}
src_ctx->pb = avio;
ifmt = av_find_input_format("mjpeg");
if (!ifmt)
{
DPRINTF(E_LOG, L_ART, "Could not find mjpeg input format\n");
goto out_close_avio;
}
ret = avformat_open_input(&src_ctx, NULL, ifmt, NULL);
if (ret < 0)
{
DPRINTF(E_LOG, L_ART, "Could not open input\n");
goto out_close_avio;
}
ret = avformat_find_stream_info(src_ctx, NULL);
if (ret < 0)
{
DPRINTF(E_LOG, L_ART, "Could not find stream info\n");
goto out_close_input;
}
ret = rescale_needed(src_ctx->streams[0]->codec, ctx->max_w, ctx->max_h, &target_w, &target_h);
if (!ret)
{
evbuffer_free(ctx->evbuf);
ctx->evbuf = evbuf;
}
else
{
ret = artwork_rescale(ctx->evbuf, src_ctx, 0, target_w, target_h);
if (ret < 0)
goto out_close_input;
evbuffer_free(evbuf);
}
avformat_close_input(&src_ctx);
avio_evbuffer_close(avio);
return ART_FMT_JPEG;
out_close_input:
avformat_close_input(&src_ctx);
out_close_avio:
avio_evbuffer_close(avio);
out_free_ctx:
if (src_ctx)
avformat_free_context(src_ctx);
out_free_evbuf:
evbuffer_free(evbuf);
return ART_E_ERROR;
}
#else
static int

View File

@ -38,6 +38,18 @@ struct avio_evbuffer {
uint8_t *buffer;
};
static int
avio_evbuffer_read(void *opaque, uint8_t *buf, int size)
{
struct avio_evbuffer *ae;
int ret;
ae = (struct avio_evbuffer *)opaque;
ret = evbuffer_remove(ae->evbuf, buf, size);
return ret;
}
static int
avio_evbuffer_write(void *opaque, uint8_t *buf, int size)
@ -52,8 +64,8 @@ avio_evbuffer_write(void *opaque, uint8_t *buf, int size)
return (ret == 0) ? size : -1;
}
AVIOContext *
avio_evbuffer_open(struct evbuffer *evbuf)
static AVIOContext *
avio_evbuffer_open(struct evbuffer *evbuf, int is_output)
{
struct avio_evbuffer *ae;
AVIOContext *s;
@ -77,7 +89,11 @@ avio_evbuffer_open(struct evbuffer *evbuf)
ae->evbuf = evbuf;
s = avio_alloc_context(ae->buffer, BUFFER_SIZE, 1, ae, NULL, avio_evbuffer_write, NULL);
if (is_output)
s = avio_alloc_context(ae->buffer, BUFFER_SIZE, 1, ae, NULL, avio_evbuffer_write, NULL);
else
s = avio_alloc_context(ae->buffer, BUFFER_SIZE, 0, ae, avio_evbuffer_read, NULL, NULL);
if (!s)
{
DPRINTF(E_LOG, L_FFMPEG, "Could not allocate AVIOContext\n");
@ -92,6 +108,18 @@ avio_evbuffer_open(struct evbuffer *evbuf)
return s;
}
AVIOContext *
avio_input_evbuffer_open(struct evbuffer *evbuf)
{
return avio_evbuffer_open(evbuf, 0);
}
AVIOContext *
avio_output_evbuffer_open(struct evbuffer *evbuf)
{
return avio_evbuffer_open(evbuf, 1);
}
void
avio_evbuffer_close(AVIOContext *s)
{
@ -101,7 +129,7 @@ avio_evbuffer_close(AVIOContext *s)
avio_flush(s);
av_free(ae->buffer);
av_free(s->buffer);
free(ae);
av_free(s);

View File

@ -5,7 +5,10 @@
#include <event2/buffer.h>
AVIOContext *
avio_evbuffer_open(struct evbuffer *evbuf);
avio_input_evbuffer_open(struct evbuffer *evbuf);
AVIOContext *
avio_output_evbuffer_open(struct evbuffer *evbuf);
void
avio_evbuffer_close(AVIOContext *s);

View File

@ -725,7 +725,7 @@ open_output(struct encode_ctx *ctx, struct decode_ctx *src_ctx)
goto out_fail_evbuf;
}
ctx->ofmt_ctx->pb = avio_evbuffer_open(ctx->obuf);
ctx->ofmt_ctx->pb = avio_output_evbuffer_open(ctx->obuf);
if (!ctx->ofmt_ctx->pb)
{
DPRINTF(E_LOG, L_XCODE, "Could not create output avio pb\n");